diff options
25 files changed, 151 insertions, 93 deletions
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h index d8541017126..eaff4790ed9 100644 --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -138,6 +138,11 @@ static inline void native_apic_msr_write(u32 reg, u32 v)  	wrmsr(APIC_BASE_MSR + (reg >> 4), v, 0);  } +static inline void native_apic_msr_eoi_write(u32 reg, u32 v) +{ +	wrmsr(APIC_BASE_MSR + (APIC_EOI >> 4), APIC_EOI_ACK, 0); +} +  static inline u32 native_apic_msr_read(u32 reg)  {  	u64 msr; @@ -351,6 +356,14 @@ struct apic {  	/* apic ops */  	u32 (*read)(u32 reg);  	void (*write)(u32 reg, u32 v); +	/* +	 * ->eoi_write() has the same signature as ->write(). +	 * +	 * Drivers can support both ->eoi_write() and ->write() by passing the same +	 * callback value. Kernel can override ->eoi_write() and fall back +	 * on write for EOI. +	 */ +	void (*eoi_write)(u32 reg, u32 v);  	u64 (*icr_read)(void);  	void (*icr_write)(u32 low, u32 high);  	void (*wait_icr_idle)(void); @@ -426,6 +439,11 @@ static inline void apic_write(u32 reg, u32 val)  	apic->write(reg, val);  } +static inline void apic_eoi(void) +{ +	apic->eoi_write(APIC_EOI, APIC_EOI_ACK); +} +  static inline u64 apic_icr_read(void)  {  	return apic->icr_read(); @@ -450,6 +468,7 @@ static inline u32 safe_apic_wait_icr_idle(void)  static inline u32 apic_read(u32 reg) { return 0; }  static inline void apic_write(u32 reg, u32 val) { } +static inline void apic_eoi(void) { }  static inline u64 apic_icr_read(void) { return 0; }  static inline void apic_icr_write(u32 low, u32 high) { }  static inline void apic_wait_icr_idle(void) { } @@ -463,9 +482,7 @@ static inline void ack_APIC_irq(void)  	 * ack_APIC_irq() actually gets compiled as a single instruction  	 * ... yummie.  	 */ - -	/* Docs say use 0 for future compatibility */ -	apic_write(APIC_EOI, 0); +	apic_eoi();  }  static inline unsigned default_get_apic_id(unsigned long x) diff --git a/arch/x86/include/asm/apicdef.h b/arch/x86/include/asm/apicdef.h index 134bba00df0..c46bb99d5fb 100644 --- a/arch/x86/include/asm/apicdef.h +++ b/arch/x86/include/asm/apicdef.h @@ -37,7 +37,7 @@  #define		APIC_ARBPRI_MASK	0xFFu  #define	APIC_PROCPRI	0xA0  #define	APIC_EOI	0xB0 -#define		APIC_EIO_ACK		0x0 +#define		APIC_EOI_ACK		0x0 /* Docs say 0 for future compat. */  #define	APIC_RRR	0xC0  #define	APIC_LDR	0xD0  #define		APIC_LDR_MASK		(0xFFu << 24) diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 2c4943de515..73d8c5398ea 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -5,7 +5,7 @@  #include <asm/mpspec.h>  #include <asm/apicdef.h>  #include <asm/irq_vectors.h> - +#include <asm/x86_init.h>  /*   * Intel IO-APIC support for SMP and UP systems.   * @@ -21,15 +21,6 @@  #define IO_APIC_REDIR_LEVEL_TRIGGER	(1 << 15)  #define IO_APIC_REDIR_MASKED		(1 << 16) -struct io_apic_ops { -	void		(*init)  (void); -	unsigned int	(*read)  (unsigned int apic, unsigned int reg); -	void		(*write) (unsigned int apic, unsigned int reg, unsigned int value); -	void		(*modify)(unsigned int apic, unsigned int reg, unsigned int value); -}; - -void __init set_io_apic_ops(const struct io_apic_ops *); -  /*   * The structure of the IO-APIC:   */ @@ -156,7 +147,6 @@ struct io_apic_irq_attr;  extern int io_apic_set_pci_routing(struct device *dev, int irq,  		 struct io_apic_irq_attr *irq_attr);  void setup_IO_APIC_irq_extra(u32 gsi); -extern void ioapic_and_gsi_init(void);  extern void ioapic_insert_resources(void);  int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr); @@ -185,12 +175,29 @@ extern void mp_save_irq(struct mpc_intsrc *m);  extern void disable_ioapic_support(void); +extern void __init native_io_apic_init_mappings(void); +extern unsigned int native_io_apic_read(unsigned int apic, unsigned int reg); +extern void native_io_apic_write(unsigned int apic, unsigned int reg, unsigned int val); +extern void native_io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val); + +static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) +{ +	return x86_io_apic_ops.read(apic, reg); +} + +static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) +{ +	x86_io_apic_ops.write(apic, reg, value); +} +static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) +{ +	x86_io_apic_ops.modify(apic, reg, value); +}  #else  /* !CONFIG_X86_IO_APIC */  #define io_apic_assign_pci_irqs 0  #define setup_ioapic_ids_from_mpc x86_init_noop  static const int timer_through_8259 = 0; -static inline void ioapic_and_gsi_init(void) { }  static inline void ioapic_insert_resources(void) { }  #define gsi_top (NR_IRQS_LEGACY)  static inline int mp_find_ioapic(u32 gsi) { return 0; } @@ -212,6 +219,10 @@ static inline int restore_ioapic_entries(void)  static inline void mp_save_irq(struct mpc_intsrc *m) { };  static inline void disable_ioapic_support(void) { } +#define native_io_apic_init_mappings	NULL +#define native_io_apic_read		NULL +#define native_io_apic_write		NULL +#define native_io_apic_modify		NULL  #endif  #endif /* _ASM_X86_IO_APIC_H */ diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h index 764b66a4cf8..c090af10ac7 100644 --- a/arch/x86/include/asm/x86_init.h +++ b/arch/x86/include/asm/x86_init.h @@ -188,11 +188,18 @@ struct x86_msi_ops {  	void (*restore_msi_irqs)(struct pci_dev *dev, int irq);  }; +struct x86_io_apic_ops { +	void		(*init)  (void); +	unsigned int	(*read)  (unsigned int apic, unsigned int reg); +	void		(*write) (unsigned int apic, unsigned int reg, unsigned int value); +	void		(*modify)(unsigned int apic, unsigned int reg, unsigned int value); +}; +  extern struct x86_init_ops x86_init;  extern struct x86_cpuinit_ops x86_cpuinit;  extern struct x86_platform_ops x86_platform;  extern struct x86_msi_ops x86_msi; - +extern struct x86_io_apic_ops x86_io_apic_ops;  extern void x86_init_noop(void);  extern void x86_init_uint_noop(unsigned int unused); diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 3722179a49d..39a222e094a 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1326,11 +1326,13 @@ void __cpuinit setup_local_APIC(void)  			       acked);  			break;  		} -		if (cpu_has_tsc) { -			rdtscll(ntsc); -			max_loops = (cpu_khz << 10) - (ntsc - tsc); -		} else -			max_loops--; +		if (queued) { +			if (cpu_has_tsc) { +				rdtscll(ntsc); +				max_loops = (cpu_khz << 10) - (ntsc - tsc); +			} else +				max_loops--; +		}  	} while (queued && max_loops > 0);  	WARN_ON(max_loops <= 0); diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c index 359b6899a36..0e881c46e8c 100644 --- a/arch/x86/kernel/apic/apic_flat_64.c +++ b/arch/x86/kernel/apic/apic_flat_64.c @@ -227,6 +227,7 @@ static struct apic apic_flat =  {  	.read				= native_apic_mem_read,  	.write				= native_apic_mem_write, +	.eoi_write			= native_apic_mem_write,  	.icr_read			= native_apic_icr_read,  	.icr_write			= native_apic_icr_write,  	.wait_icr_idle			= native_apic_wait_icr_idle, @@ -386,6 +387,7 @@ static struct apic apic_physflat =  {  	.read				= native_apic_mem_read,  	.write				= native_apic_mem_write, +	.eoi_write			= native_apic_mem_write,  	.icr_read			= native_apic_icr_read,  	.icr_write			= native_apic_icr_write,  	.wait_icr_idle			= native_apic_wait_icr_idle, diff --git a/arch/x86/kernel/apic/apic_noop.c b/arch/x86/kernel/apic/apic_noop.c index 634ae6cdd5c..a6e4c6e06c0 100644 --- a/arch/x86/kernel/apic/apic_noop.c +++ b/arch/x86/kernel/apic/apic_noop.c @@ -181,6 +181,7 @@ struct apic apic_noop = {  	.read				= noop_apic_read,  	.write				= noop_apic_write, +	.eoi_write			= noop_apic_write,  	.icr_read			= noop_apic_icr_read,  	.icr_write			= noop_apic_icr_write,  	.wait_icr_idle			= noop_apic_wait_icr_idle, diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index 23e75422e01..6ec6d5d297c 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -295,6 +295,7 @@ static struct apic apic_numachip __refconst = {  	.read				= native_apic_mem_read,  	.write				= native_apic_mem_write, +	.eoi_write			= native_apic_mem_write,  	.icr_read			= native_apic_icr_read,  	.icr_write			= native_apic_icr_write,  	.wait_icr_idle			= native_apic_wait_icr_idle, diff --git a/arch/x86/kernel/apic/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c index 0cdec7065af..31fbdbfbf96 100644 --- a/arch/x86/kernel/apic/bigsmp_32.c +++ b/arch/x86/kernel/apic/bigsmp_32.c @@ -248,6 +248,7 @@ static struct apic apic_bigsmp = {  	.read				= native_apic_mem_read,  	.write				= native_apic_mem_write, +	.eoi_write			= native_apic_mem_write,  	.icr_read			= native_apic_icr_read,  	.icr_write			= native_apic_icr_write,  	.wait_icr_idle			= native_apic_wait_icr_idle, diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index e42d1d3b913..db4ab1be3c7 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c @@ -678,6 +678,7 @@ static struct apic __refdata apic_es7000_cluster = {  	.read				= native_apic_mem_read,  	.write				= native_apic_mem_write, +	.eoi_write			= native_apic_mem_write,  	.icr_read			= native_apic_icr_read,  	.icr_write			= native_apic_icr_write,  	.wait_icr_idle			= native_apic_wait_icr_idle, @@ -742,6 +743,7 @@ static struct apic __refdata apic_es7000 = {  	.read				= native_apic_mem_read,  	.write				= native_apic_mem_write, +	.eoi_write			= native_apic_mem_write,  	.icr_read			= native_apic_icr_read,  	.icr_write			= native_apic_icr_write,  	.wait_icr_idle			= native_apic_wait_icr_idle, diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index ef0648cd708..ffdc152e507 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -68,24 +68,6 @@  #define for_each_irq_pin(entry, head) \  	for (entry = head; entry; entry = entry->next) -static void		__init __ioapic_init_mappings(void); - -static unsigned int	__io_apic_read  (unsigned int apic, unsigned int reg); -static void		__io_apic_write (unsigned int apic, unsigned int reg, unsigned int val); -static void		__io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val); - -static struct io_apic_ops io_apic_ops = { -	.init	= __ioapic_init_mappings, -	.read	= __io_apic_read, -	.write	= __io_apic_write, -	.modify = __io_apic_modify, -}; - -void __init set_io_apic_ops(const struct io_apic_ops *ops) -{ -	io_apic_ops = *ops; -} -  #ifdef CONFIG_IRQ_REMAP  static void irq_remap_modify_chip_defaults(struct irq_chip *chip);  static inline bool irq_remapped(struct irq_cfg *cfg) @@ -329,21 +311,6 @@ static void free_irq_at(unsigned int at, struct irq_cfg *cfg)  	irq_free_desc(at);  } -static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) -{ -	return io_apic_ops.read(apic, reg); -} - -static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) -{ -	io_apic_ops.write(apic, reg, value); -} - -static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) -{ -	io_apic_ops.modify(apic, reg, value); -} -  struct io_apic {  	unsigned int index; @@ -365,14 +332,14 @@ static inline void io_apic_eoi(unsigned int apic, unsigned int vector)  	writel(vector, &io_apic->eoi);  } -static unsigned int __io_apic_read(unsigned int apic, unsigned int reg) +unsigned int native_io_apic_read(unsigned int apic, unsigned int reg)  {  	struct io_apic __iomem *io_apic = io_apic_base(apic);  	writel(reg, &io_apic->index);  	return readl(&io_apic->data);  } -static void __io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) +void native_io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)  {  	struct io_apic __iomem *io_apic = io_apic_base(apic); @@ -386,7 +353,7 @@ static void __io_apic_write(unsigned int apic, unsigned int reg, unsigned int va   *   * Older SiS APIC requires we rewrite the index register   */ -static void __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) +void native_io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)  {  	struct io_apic __iomem *io_apic = io_apic_base(apic); @@ -395,29 +362,6 @@ static void __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int v  	writel(value, &io_apic->data);  } -static bool io_apic_level_ack_pending(struct irq_cfg *cfg) -{ -	struct irq_pin_list *entry; -	unsigned long flags; - -	raw_spin_lock_irqsave(&ioapic_lock, flags); -	for_each_irq_pin(entry, cfg->irq_2_pin) { -		unsigned int reg; -		int pin; - -		pin = entry->pin; -		reg = io_apic_read(entry->apic, 0x10 + pin*2); -		/* Is the remote IRR bit set? */ -		if (reg & IO_APIC_REDIR_REMOTE_IRR) { -			raw_spin_unlock_irqrestore(&ioapic_lock, flags); -			return true; -		} -	} -	raw_spin_unlock_irqrestore(&ioapic_lock, flags); - -	return false; -} -  union entry_union {  	struct { u32 w1, w2; };  	struct IO_APIC_route_entry entry; @@ -2439,6 +2383,29 @@ static void ack_apic_edge(struct irq_data *data)  atomic_t irq_mis_count;  #ifdef CONFIG_GENERIC_PENDING_IRQ +static bool io_apic_level_ack_pending(struct irq_cfg *cfg) +{ +	struct irq_pin_list *entry; +	unsigned long flags; + +	raw_spin_lock_irqsave(&ioapic_lock, flags); +	for_each_irq_pin(entry, cfg->irq_2_pin) { +		unsigned int reg; +		int pin; + +		pin = entry->pin; +		reg = io_apic_read(entry->apic, 0x10 + pin*2); +		/* Is the remote IRR bit set? */ +		if (reg & IO_APIC_REDIR_REMOTE_IRR) { +			raw_spin_unlock_irqrestore(&ioapic_lock, flags); +			return true; +		} +	} +	raw_spin_unlock_irqrestore(&ioapic_lock, flags); + +	return false; +} +  static inline bool ioapic_irqd_mask(struct irq_data *data, struct irq_cfg *cfg)  {  	/* If we are moving the irq we need to mask it */ @@ -3756,12 +3723,7 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics)  	return res;  } -void __init ioapic_and_gsi_init(void) -{ -	io_apic_ops.init(); -} - -static void __init __ioapic_init_mappings(void) +void __init native_io_apic_init_mappings(void)  {  	unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;  	struct resource *ioapic_res; diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c index 00d2422ca7c..f00a68cca37 100644 --- a/arch/x86/kernel/apic/numaq_32.c +++ b/arch/x86/kernel/apic/numaq_32.c @@ -530,6 +530,7 @@ static struct apic __refdata apic_numaq = {  	.read				= native_apic_mem_read,  	.write				= native_apic_mem_write, +	.eoi_write			= native_apic_mem_write,  	.icr_read			= native_apic_icr_read,  	.icr_write			= native_apic_icr_write,  	.wait_icr_idle			= native_apic_wait_icr_idle, diff --git a/arch/x86/kernel/apic/probe_32.c b/arch/x86/kernel/apic/probe_32.c index ff2c1b9aac4..1b291da09e6 100644 --- a/arch/x86/kernel/apic/probe_32.c +++ b/arch/x86/kernel/apic/probe_32.c @@ -142,6 +142,7 @@ static struct apic apic_default = {  	.read				= native_apic_mem_read,  	.write				= native_apic_mem_write, +	.eoi_write			= native_apic_mem_write,  	.icr_read			= native_apic_icr_read,  	.icr_write			= native_apic_icr_write,  	.wait_icr_idle			= native_apic_wait_icr_idle, diff --git a/arch/x86/kernel/apic/summit_32.c b/arch/x86/kernel/apic/summit_32.c index fea000b27f0..659897c0075 100644 --- a/arch/x86/kernel/apic/summit_32.c +++ b/arch/x86/kernel/apic/summit_32.c @@ -546,6 +546,7 @@ static struct apic apic_summit = {  	.read				= native_apic_mem_read,  	.write				= native_apic_mem_write, +	.eoi_write			= native_apic_mem_write,  	.icr_read			= native_apic_icr_read,  	.icr_write			= native_apic_icr_write,  	.wait_icr_idle			= native_apic_wait_icr_idle, diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index 48f3103b3c9..ff35cff0e1a 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -260,6 +260,7 @@ static struct apic apic_x2apic_cluster = {  	.read				= native_apic_msr_read,  	.write				= native_apic_msr_write, +	.eoi_write			= native_apic_msr_eoi_write,  	.icr_read			= native_x2apic_icr_read,  	.icr_write			= native_x2apic_icr_write,  	.wait_icr_idle			= native_x2apic_wait_icr_idle, diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index 991e315f422..c17e982db27 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c @@ -172,6 +172,7 @@ static struct apic apic_x2apic_phys = {  	.read				= native_apic_msr_read,  	.write				= native_apic_msr_write, +	.eoi_write			= native_apic_msr_eoi_write,  	.icr_read			= native_x2apic_icr_read,  	.icr_write			= native_x2apic_icr_write,  	.wait_icr_idle			= native_x2apic_wait_icr_idle, diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 87bfa69e216..c6d03f7a440 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -404,6 +404,7 @@ static struct apic __refdata apic_x2apic_uv_x = {  	.read				= native_apic_msr_read,  	.write				= native_apic_msr_write, +	.eoi_write			= native_apic_msr_eoi_write,  	.icr_read			= native_x2apic_icr_read,  	.icr_write			= native_x2apic_icr_write,  	.wait_icr_idle			= native_x2apic_wait_icr_idle, diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 1a290156205..7e67c5a7106 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1012,7 +1012,8 @@ void __init setup_arch(char **cmdline_p)  	init_cpu_to_node();  	init_apic_mappings(); -	ioapic_and_gsi_init(); +	if (x86_io_apic_ops.init) +		x86_io_apic_ops.init();  	kvm_guest_init(); diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 9cf71d0b2d3..35c5e543f55 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -18,6 +18,7 @@  #include <asm/e820.h>  #include <asm/time.h>  #include <asm/irq.h> +#include <asm/io_apic.h>  #include <asm/pat.h>  #include <asm/tsc.h>  #include <asm/iommu.h> @@ -119,3 +120,10 @@ struct x86_msi_ops x86_msi = {  	.teardown_msi_irqs = default_teardown_msi_irqs,  	.restore_msi_irqs = default_restore_msi_irqs,  }; + +struct x86_io_apic_ops x86_io_apic_ops = { +	.init	= native_io_apic_init_mappings, +	.read	= native_io_apic_read, +	.write	= native_io_apic_write, +	.modify	= native_io_apic_modify, +}; diff --git a/arch/x86/platform/visws/visws_quirks.c b/arch/x86/platform/visws/visws_quirks.c index c7abf13a213..94d8a39332e 100644 --- a/arch/x86/platform/visws/visws_quirks.c +++ b/arch/x86/platform/visws/visws_quirks.c @@ -445,7 +445,7 @@ static void ack_cobalt_irq(struct irq_data *data)  	spin_lock_irqsave(&cobalt_lock, flags);  	disable_cobalt_irq(data); -	apic_write(APIC_EOI, APIC_EIO_ACK); +	apic_write(APIC_EOI, APIC_EOI_ACK);  	spin_unlock_irqrestore(&cobalt_lock, flags);  } diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile index add2c2d729c..96ab2c09cb6 100644 --- a/arch/x86/xen/Makefile +++ b/arch/x86/xen/Makefile @@ -20,5 +20,5 @@ obj-$(CONFIG_EVENT_TRACING) += trace.o  obj-$(CONFIG_SMP)		+= smp.o  obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o  obj-$(CONFIG_XEN_DEBUG_FS)	+= debugfs.o -obj-$(CONFIG_XEN_DOM0)		+= vga.o +obj-$(CONFIG_XEN_DOM0)		+= apic.o vga.o  obj-$(CONFIG_SWIOTLB_XEN)	+= pci-swiotlb-xen.o diff --git a/arch/x86/xen/apic.c b/arch/x86/xen/apic.c new file mode 100644 index 00000000000..ec57bd3818a --- /dev/null +++ b/arch/x86/xen/apic.c @@ -0,0 +1,33 @@ +#include <linux/init.h> + +#include <asm/x86_init.h> +#include <asm/apic.h> +#include <asm/xen/hypercall.h> + +#include <xen/xen.h> +#include <xen/interface/physdev.h> + +unsigned int xen_io_apic_read(unsigned apic, unsigned reg) +{ +	struct physdev_apic apic_op; +	int ret; + +	apic_op.apic_physbase = mpc_ioapic_addr(apic); +	apic_op.reg = reg; +	ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op); +	if (!ret) +		return apic_op.value; + +	/* fallback to return an emulated IO_APIC values */ +	if (reg == 0x1) +		return 0x00170020; +	else if (reg == 0x0) +		return apic << 24; + +	return 0xfd; +} + +void __init xen_init_apic(void) +{ +	x86_io_apic_ops.read = xen_io_apic_read; +} diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 95dccce8e97..c0f5facdb10 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1396,6 +1396,8 @@ asmlinkage void __init xen_start_kernel(void)  		xen_start_info->console.domU.mfn = 0;  		xen_start_info->console.domU.evtchn = 0; +		xen_init_apic(); +  		/* Make sure ACS will be enabled */  		pci_request_acs();  	} diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 69f5857660a..3506cd4f9a4 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1864,7 +1864,6 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd,  #endif	/* CONFIG_X86_64 */  static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss; -static unsigned char fake_ioapic_mapping[PAGE_SIZE] __page_aligned_bss;  static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)  { @@ -1905,7 +1904,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)  		 * We just don't map the IO APIC - all access is via  		 * hypercalls.  Keep the address in the pte for reference.  		 */ -		pte = pfn_pte(PFN_DOWN(__pa(fake_ioapic_mapping)), PAGE_KERNEL); +		pte = pfn_pte(PFN_DOWN(__pa(dummy_mapping)), PAGE_KERNEL);  		break;  #endif @@ -2070,7 +2069,6 @@ void __init xen_init_mmu_ops(void)  	pv_mmu_ops = xen_mmu_ops;  	memset(dummy_mapping, 0xff, PAGE_SIZE); -	memset(fake_ioapic_mapping, 0xfd, PAGE_SIZE);  }  /* Protected by xen_reservation_lock. */ diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index b095739ccd4..45c0c0667bd 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -92,11 +92,15 @@ struct dom0_vga_console_info;  #ifdef CONFIG_XEN_DOM0  void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size); +void __init xen_init_apic(void);  #else  static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,  				       size_t size)  {  } +static inline void __init xen_init_apic(void) +{ +}  #endif  /* Declare an asm function, along with symbols needed to make it  |