aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-22 21:38:11 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-22 21:38:11 -0400
commitf08b9c2f8af0d61faa1170aeae4fbca1eff6a504 (patch)
tree367b04b7750b66c8412bd377e549aa0fb5b3df02
parentd79ee93de909dfb252279b9a95978bbda9a814a9 (diff)
parent0ab711ae6ab0db7696b43c74f9ba9de4d7fc1deb (diff)
Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86/apic changes from Ingo Molnar: "Most of the changes are about helping virtualized guest kernels achieve better performance." Fix up trivial conflicts with the iommu updates to arch/x86/kernel/apic/io_apic.c * 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/apic: Implement EIO micro-optimization x86/apic: Add apic->eoi_write() callback x86/apic: Use symbolic APIC_EOI_ACK x86/apic: Fix typo EIO_ACK -> EOI_ACK and document it x86/xen/apic: Add missing #include <xen/xen.h> x86/apic: Only compile local function if used with !CONFIG_GENERIC_PENDING_IRQ x86/apic: Fix UP boot crash x86: Conditionally update time when ack-ing pending irqs xen/apic: implement io apic read with hypercall Revert "xen/x86: Workaround 'x86/ioapic: Add register level checks to detect bogus io-apic entries'" xen/x86: Implement x86_apic_ops x86/apic: Replace io_apic_ops with x86_io_apic_ops.
-rw-r--r--arch/x86/include/asm/apic.h23
-rw-r--r--arch/x86/include/asm/apicdef.h2
-rw-r--r--arch/x86/include/asm/io_apic.h35
-rw-r--r--arch/x86/include/asm/x86_init.h9
-rw-r--r--arch/x86/kernel/apic/apic.c12
-rw-r--r--arch/x86/kernel/apic/apic_flat_64.c2
-rw-r--r--arch/x86/kernel/apic/apic_noop.c1
-rw-r--r--arch/x86/kernel/apic/apic_numachip.c1
-rw-r--r--arch/x86/kernel/apic/bigsmp_32.c1
-rw-r--r--arch/x86/kernel/apic/es7000_32.c2
-rw-r--r--arch/x86/kernel/apic/io_apic.c92
-rw-r--r--arch/x86/kernel/apic/numaq_32.c1
-rw-r--r--arch/x86/kernel/apic/probe_32.c1
-rw-r--r--arch/x86/kernel/apic/summit_32.c1
-rw-r--r--arch/x86/kernel/apic/x2apic_cluster.c1
-rw-r--r--arch/x86/kernel/apic/x2apic_phys.c1
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c1
-rw-r--r--arch/x86/kernel/setup.c3
-rw-r--r--arch/x86/kernel/x86_init.c8
-rw-r--r--arch/x86/platform/visws/visws_quirks.c2
-rw-r--r--arch/x86/xen/Makefile2
-rw-r--r--arch/x86/xen/apic.c33
-rw-r--r--arch/x86/xen/enlighten.c2
-rw-r--r--arch/x86/xen/mmu.c4
-rw-r--r--arch/x86/xen/xen-ops.h4
25 files changed, 151 insertions, 93 deletions
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index d85410171260..eaff4790ed96 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)
138 wrmsr(APIC_BASE_MSR + (reg >> 4), v, 0); 138 wrmsr(APIC_BASE_MSR + (reg >> 4), v, 0);
139} 139}
140 140
141static inline void native_apic_msr_eoi_write(u32 reg, u32 v)
142{
143 wrmsr(APIC_BASE_MSR + (APIC_EOI >> 4), APIC_EOI_ACK, 0);
144}
145
141static inline u32 native_apic_msr_read(u32 reg) 146static inline u32 native_apic_msr_read(u32 reg)
142{ 147{
143 u64 msr; 148 u64 msr;
@@ -351,6 +356,14 @@ struct apic {
351 /* apic ops */ 356 /* apic ops */
352 u32 (*read)(u32 reg); 357 u32 (*read)(u32 reg);
353 void (*write)(u32 reg, u32 v); 358 void (*write)(u32 reg, u32 v);
359 /*
360 * ->eoi_write() has the same signature as ->write().
361 *
362 * Drivers can support both ->eoi_write() and ->write() by passing the same
363 * callback value. Kernel can override ->eoi_write() and fall back
364 * on write for EOI.
365 */
366 void (*eoi_write)(u32 reg, u32 v);
354 u64 (*icr_read)(void); 367 u64 (*icr_read)(void);
355 void (*icr_write)(u32 low, u32 high); 368 void (*icr_write)(u32 low, u32 high);
356 void (*wait_icr_idle)(void); 369 void (*wait_icr_idle)(void);
@@ -426,6 +439,11 @@ static inline void apic_write(u32 reg, u32 val)
426 apic->write(reg, val); 439 apic->write(reg, val);
427} 440}
428 441
442static inline void apic_eoi(void)
443{
444 apic->eoi_write(APIC_EOI, APIC_EOI_ACK);
445}
446
429static inline u64 apic_icr_read(void) 447static inline u64 apic_icr_read(void)
430{ 448{
431 return apic->icr_read(); 449 return apic->icr_read();
@@ -450,6 +468,7 @@ static inline u32 safe_apic_wait_icr_idle(void)
450 468
451static inline u32 apic_read(u32 reg) { return 0; } 469static inline u32 apic_read(u32 reg) { return 0; }
452static inline void apic_write(u32 reg, u32 val) { } 470static inline void apic_write(u32 reg, u32 val) { }
471static inline void apic_eoi(void) { }
453static inline u64 apic_icr_read(void) { return 0; } 472static inline u64 apic_icr_read(void) { return 0; }
454static inline void apic_icr_write(u32 low, u32 high) { } 473static inline void apic_icr_write(u32 low, u32 high) { }
455static inline void apic_wait_icr_idle(void) { } 474static inline void apic_wait_icr_idle(void) { }
@@ -463,9 +482,7 @@ static inline void ack_APIC_irq(void)
463 * ack_APIC_irq() actually gets compiled as a single instruction 482 * ack_APIC_irq() actually gets compiled as a single instruction
464 * ... yummie. 483 * ... yummie.
465 */ 484 */
466 485 apic_eoi();
467 /* Docs say use 0 for future compatibility */
468 apic_write(APIC_EOI, 0);
469} 486}
470 487
471static inline unsigned default_get_apic_id(unsigned long x) 488static 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 134bba00df09..c46bb99d5fb2 100644
--- a/arch/x86/include/asm/apicdef.h
+++ b/arch/x86/include/asm/apicdef.h
@@ -37,7 +37,7 @@
37#define APIC_ARBPRI_MASK 0xFFu 37#define APIC_ARBPRI_MASK 0xFFu
38#define APIC_PROCPRI 0xA0 38#define APIC_PROCPRI 0xA0
39#define APIC_EOI 0xB0 39#define APIC_EOI 0xB0
40#define APIC_EIO_ACK 0x0 40#define APIC_EOI_ACK 0x0 /* Docs say 0 for future compat. */
41#define APIC_RRR 0xC0 41#define APIC_RRR 0xC0
42#define APIC_LDR 0xD0 42#define APIC_LDR 0xD0
43#define APIC_LDR_MASK (0xFFu << 24) 43#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 2c4943de5150..73d8c5398ea9 100644
--- a/arch/x86/include/asm/io_apic.h
+++ b/arch/x86/include/asm/io_apic.h
@@ -5,7 +5,7 @@
5#include <asm/mpspec.h> 5#include <asm/mpspec.h>
6#include <asm/apicdef.h> 6#include <asm/apicdef.h>
7#include <asm/irq_vectors.h> 7#include <asm/irq_vectors.h>
8 8#include <asm/x86_init.h>
9/* 9/*
10 * Intel IO-APIC support for SMP and UP systems. 10 * Intel IO-APIC support for SMP and UP systems.
11 * 11 *
@@ -21,15 +21,6 @@
21#define IO_APIC_REDIR_LEVEL_TRIGGER (1 << 15) 21#define IO_APIC_REDIR_LEVEL_TRIGGER (1 << 15)
22#define IO_APIC_REDIR_MASKED (1 << 16) 22#define IO_APIC_REDIR_MASKED (1 << 16)
23 23
24struct io_apic_ops {
25 void (*init) (void);
26 unsigned int (*read) (unsigned int apic, unsigned int reg);
27 void (*write) (unsigned int apic, unsigned int reg, unsigned int value);
28 void (*modify)(unsigned int apic, unsigned int reg, unsigned int value);
29};
30
31void __init set_io_apic_ops(const struct io_apic_ops *);
32
33/* 24/*
34 * The structure of the IO-APIC: 25 * The structure of the IO-APIC:
35 */ 26 */
@@ -156,7 +147,6 @@ struct io_apic_irq_attr;
156extern int io_apic_set_pci_routing(struct device *dev, int irq, 147extern int io_apic_set_pci_routing(struct device *dev, int irq,
157 struct io_apic_irq_attr *irq_attr); 148 struct io_apic_irq_attr *irq_attr);
158void setup_IO_APIC_irq_extra(u32 gsi); 149void setup_IO_APIC_irq_extra(u32 gsi);
159extern void ioapic_and_gsi_init(void);
160extern void ioapic_insert_resources(void); 150extern void ioapic_insert_resources(void);
161 151
162int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr); 152int 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);
185 175
186extern void disable_ioapic_support(void); 176extern void disable_ioapic_support(void);
187 177
178extern void __init native_io_apic_init_mappings(void);
179extern unsigned int native_io_apic_read(unsigned int apic, unsigned int reg);
180extern void native_io_apic_write(unsigned int apic, unsigned int reg, unsigned int val);
181extern void native_io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val);
182
183static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
184{
185 return x86_io_apic_ops.read(apic, reg);
186}
187
188static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
189{
190 x86_io_apic_ops.write(apic, reg, value);
191}
192static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
193{
194 x86_io_apic_ops.modify(apic, reg, value);
195}
188#else /* !CONFIG_X86_IO_APIC */ 196#else /* !CONFIG_X86_IO_APIC */
189 197
190#define io_apic_assign_pci_irqs 0 198#define io_apic_assign_pci_irqs 0
191#define setup_ioapic_ids_from_mpc x86_init_noop 199#define setup_ioapic_ids_from_mpc x86_init_noop
192static const int timer_through_8259 = 0; 200static const int timer_through_8259 = 0;
193static inline void ioapic_and_gsi_init(void) { }
194static inline void ioapic_insert_resources(void) { } 201static inline void ioapic_insert_resources(void) { }
195#define gsi_top (NR_IRQS_LEGACY) 202#define gsi_top (NR_IRQS_LEGACY)
196static inline int mp_find_ioapic(u32 gsi) { return 0; } 203static inline int mp_find_ioapic(u32 gsi) { return 0; }
@@ -212,6 +219,10 @@ static inline int restore_ioapic_entries(void)
212 219
213static inline void mp_save_irq(struct mpc_intsrc *m) { }; 220static inline void mp_save_irq(struct mpc_intsrc *m) { };
214static inline void disable_ioapic_support(void) { } 221static inline void disable_ioapic_support(void) { }
222#define native_io_apic_init_mappings NULL
223#define native_io_apic_read NULL
224#define native_io_apic_write NULL
225#define native_io_apic_modify NULL
215#endif 226#endif
216 227
217#endif /* _ASM_X86_IO_APIC_H */ 228#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 764b66a4cf89..c090af10ac7d 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 {
188 void (*restore_msi_irqs)(struct pci_dev *dev, int irq); 188 void (*restore_msi_irqs)(struct pci_dev *dev, int irq);
189}; 189};
190 190
191struct x86_io_apic_ops {
192 void (*init) (void);
193 unsigned int (*read) (unsigned int apic, unsigned int reg);
194 void (*write) (unsigned int apic, unsigned int reg, unsigned int value);
195 void (*modify)(unsigned int apic, unsigned int reg, unsigned int value);
196};
197
191extern struct x86_init_ops x86_init; 198extern struct x86_init_ops x86_init;
192extern struct x86_cpuinit_ops x86_cpuinit; 199extern struct x86_cpuinit_ops x86_cpuinit;
193extern struct x86_platform_ops x86_platform; 200extern struct x86_platform_ops x86_platform;
194extern struct x86_msi_ops x86_msi; 201extern struct x86_msi_ops x86_msi;
195 202extern struct x86_io_apic_ops x86_io_apic_ops;
196extern void x86_init_noop(void); 203extern void x86_init_noop(void);
197extern void x86_init_uint_noop(unsigned int unused); 204extern void x86_init_uint_noop(unsigned int unused);
198 205
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index 3722179a49db..39a222e094af 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)
1326 acked); 1326 acked);
1327 break; 1327 break;
1328 } 1328 }
1329 if (cpu_has_tsc) { 1329 if (queued) {
1330 rdtscll(ntsc); 1330 if (cpu_has_tsc) {
1331 max_loops = (cpu_khz << 10) - (ntsc - tsc); 1331 rdtscll(ntsc);
1332 } else 1332 max_loops = (cpu_khz << 10) - (ntsc - tsc);
1333 max_loops--; 1333 } else
1334 max_loops--;
1335 }
1334 } while (queued && max_loops > 0); 1336 } while (queued && max_loops > 0);
1335 WARN_ON(max_loops <= 0); 1337 WARN_ON(max_loops <= 0);
1336 1338
diff --git a/arch/x86/kernel/apic/apic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c
index 359b6899a36c..0e881c46e8c8 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 = {
227 227
228 .read = native_apic_mem_read, 228 .read = native_apic_mem_read,
229 .write = native_apic_mem_write, 229 .write = native_apic_mem_write,
230 .eoi_write = native_apic_mem_write,
230 .icr_read = native_apic_icr_read, 231 .icr_read = native_apic_icr_read,
231 .icr_write = native_apic_icr_write, 232 .icr_write = native_apic_icr_write,
232 .wait_icr_idle = native_apic_wait_icr_idle, 233 .wait_icr_idle = native_apic_wait_icr_idle,
@@ -386,6 +387,7 @@ static struct apic apic_physflat = {
386 387
387 .read = native_apic_mem_read, 388 .read = native_apic_mem_read,
388 .write = native_apic_mem_write, 389 .write = native_apic_mem_write,
390 .eoi_write = native_apic_mem_write,
389 .icr_read = native_apic_icr_read, 391 .icr_read = native_apic_icr_read,
390 .icr_write = native_apic_icr_write, 392 .icr_write = native_apic_icr_write,
391 .wait_icr_idle = native_apic_wait_icr_idle, 393 .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 634ae6cdd5c9..a6e4c6e06c08 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 = {
181 181
182 .read = noop_apic_read, 182 .read = noop_apic_read,
183 .write = noop_apic_write, 183 .write = noop_apic_write,
184 .eoi_write = noop_apic_write,
184 .icr_read = noop_apic_icr_read, 185 .icr_read = noop_apic_icr_read,
185 .icr_write = noop_apic_icr_write, 186 .icr_write = noop_apic_icr_write,
186 .wait_icr_idle = noop_apic_wait_icr_idle, 187 .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 23e75422e013..6ec6d5d297c3 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 = {
295 295
296 .read = native_apic_mem_read, 296 .read = native_apic_mem_read,
297 .write = native_apic_mem_write, 297 .write = native_apic_mem_write,
298 .eoi_write = native_apic_mem_write,
298 .icr_read = native_apic_icr_read, 299 .icr_read = native_apic_icr_read,
299 .icr_write = native_apic_icr_write, 300 .icr_write = native_apic_icr_write,
300 .wait_icr_idle = native_apic_wait_icr_idle, 301 .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 0cdec7065aff..31fbdbfbf960 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 = {
248 248
249 .read = native_apic_mem_read, 249 .read = native_apic_mem_read,
250 .write = native_apic_mem_write, 250 .write = native_apic_mem_write,
251 .eoi_write = native_apic_mem_write,
251 .icr_read = native_apic_icr_read, 252 .icr_read = native_apic_icr_read,
252 .icr_write = native_apic_icr_write, 253 .icr_write = native_apic_icr_write,
253 .wait_icr_idle = native_apic_wait_icr_idle, 254 .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 e42d1d3b9134..db4ab1be3c79 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 = {
678 678
679 .read = native_apic_mem_read, 679 .read = native_apic_mem_read,
680 .write = native_apic_mem_write, 680 .write = native_apic_mem_write,
681 .eoi_write = native_apic_mem_write,
681 .icr_read = native_apic_icr_read, 682 .icr_read = native_apic_icr_read,
682 .icr_write = native_apic_icr_write, 683 .icr_write = native_apic_icr_write,
683 .wait_icr_idle = native_apic_wait_icr_idle, 684 .wait_icr_idle = native_apic_wait_icr_idle,
@@ -742,6 +743,7 @@ static struct apic __refdata apic_es7000 = {
742 743
743 .read = native_apic_mem_read, 744 .read = native_apic_mem_read,
744 .write = native_apic_mem_write, 745 .write = native_apic_mem_write,
746 .eoi_write = native_apic_mem_write,
745 .icr_read = native_apic_icr_read, 747 .icr_read = native_apic_icr_read,
746 .icr_write = native_apic_icr_write, 748 .icr_write = native_apic_icr_write,
747 .wait_icr_idle = native_apic_wait_icr_idle, 749 .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 ef0648cd7084..ffdc152e507d 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -68,24 +68,6 @@
68#define for_each_irq_pin(entry, head) \ 68#define for_each_irq_pin(entry, head) \
69 for (entry = head; entry; entry = entry->next) 69 for (entry = head; entry; entry = entry->next)
70 70
71static void __init __ioapic_init_mappings(void);
72
73static unsigned int __io_apic_read (unsigned int apic, unsigned int reg);
74static void __io_apic_write (unsigned int apic, unsigned int reg, unsigned int val);
75static void __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val);
76
77static struct io_apic_ops io_apic_ops = {
78 .init = __ioapic_init_mappings,
79 .read = __io_apic_read,
80 .write = __io_apic_write,
81 .modify = __io_apic_modify,
82};
83
84void __init set_io_apic_ops(const struct io_apic_ops *ops)
85{
86 io_apic_ops = *ops;
87}
88
89#ifdef CONFIG_IRQ_REMAP 71#ifdef CONFIG_IRQ_REMAP
90static void irq_remap_modify_chip_defaults(struct irq_chip *chip); 72static void irq_remap_modify_chip_defaults(struct irq_chip *chip);
91static inline bool irq_remapped(struct irq_cfg *cfg) 73static inline bool irq_remapped(struct irq_cfg *cfg)
@@ -329,21 +311,6 @@ static void free_irq_at(unsigned int at, struct irq_cfg *cfg)
329 irq_free_desc(at); 311 irq_free_desc(at);
330} 312}
331 313
332static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
333{
334 return io_apic_ops.read(apic, reg);
335}
336
337static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
338{
339 io_apic_ops.write(apic, reg, value);
340}
341
342static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
343{
344 io_apic_ops.modify(apic, reg, value);
345}
346
347 314
348struct io_apic { 315struct io_apic {
349 unsigned int index; 316 unsigned int index;
@@ -365,14 +332,14 @@ static inline void io_apic_eoi(unsigned int apic, unsigned int vector)
365 writel(vector, &io_apic->eoi); 332 writel(vector, &io_apic->eoi);
366} 333}
367 334
368static unsigned int __io_apic_read(unsigned int apic, unsigned int reg) 335unsigned int native_io_apic_read(unsigned int apic, unsigned int reg)
369{ 336{
370 struct io_apic __iomem *io_apic = io_apic_base(apic); 337 struct io_apic __iomem *io_apic = io_apic_base(apic);
371 writel(reg, &io_apic->index); 338 writel(reg, &io_apic->index);
372 return readl(&io_apic->data); 339 return readl(&io_apic->data);
373} 340}
374 341
375static void __io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) 342void native_io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
376{ 343{
377 struct io_apic __iomem *io_apic = io_apic_base(apic); 344 struct io_apic __iomem *io_apic = io_apic_base(apic);
378 345
@@ -386,7 +353,7 @@ static void __io_apic_write(unsigned int apic, unsigned int reg, unsigned int va
386 * 353 *
387 * Older SiS APIC requires we rewrite the index register 354 * Older SiS APIC requires we rewrite the index register
388 */ 355 */
389static void __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) 356void native_io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
390{ 357{
391 struct io_apic __iomem *io_apic = io_apic_base(apic); 358 struct io_apic __iomem *io_apic = io_apic_base(apic);
392 359
@@ -395,29 +362,6 @@ static void __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int v
395 writel(value, &io_apic->data); 362 writel(value, &io_apic->data);
396} 363}
397 364
398static bool io_apic_level_ack_pending(struct irq_cfg *cfg)
399{
400 struct irq_pin_list *entry;
401 unsigned long flags;
402
403 raw_spin_lock_irqsave(&ioapic_lock, flags);
404 for_each_irq_pin(entry, cfg->irq_2_pin) {
405 unsigned int reg;
406 int pin;
407
408 pin = entry->pin;
409 reg = io_apic_read(entry->apic, 0x10 + pin*2);
410 /* Is the remote IRR bit set? */
411 if (reg & IO_APIC_REDIR_REMOTE_IRR) {
412 raw_spin_unlock_irqrestore(&ioapic_lock, flags);
413 return true;
414 }
415 }
416 raw_spin_unlock_irqrestore(&ioapic_lock, flags);
417
418 return false;
419}
420
421union entry_union { 365union entry_union {
422 struct { u32 w1, w2; }; 366 struct { u32 w1, w2; };
423 struct IO_APIC_route_entry entry; 367 struct IO_APIC_route_entry entry;
@@ -2439,6 +2383,29 @@ static void ack_apic_edge(struct irq_data *data)
2439atomic_t irq_mis_count; 2383atomic_t irq_mis_count;
2440 2384
2441#ifdef CONFIG_GENERIC_PENDING_IRQ 2385#ifdef CONFIG_GENERIC_PENDING_IRQ
2386static bool io_apic_level_ack_pending(struct irq_cfg *cfg)
2387{
2388 struct irq_pin_list *entry;
2389 unsigned long flags;
2390
2391 raw_spin_lock_irqsave(&ioapic_lock, flags);
2392 for_each_irq_pin(entry, cfg->irq_2_pin) {
2393 unsigned int reg;
2394 int pin;
2395
2396 pin = entry->pin;
2397 reg = io_apic_read(entry->apic, 0x10 + pin*2);
2398 /* Is the remote IRR bit set? */
2399 if (reg & IO_APIC_REDIR_REMOTE_IRR) {
2400 raw_spin_unlock_irqrestore(&ioapic_lock, flags);
2401 return true;
2402 }
2403 }
2404 raw_spin_unlock_irqrestore(&ioapic_lock, flags);
2405
2406 return false;
2407}
2408
2442static inline bool ioapic_irqd_mask(struct irq_data *data, struct irq_cfg *cfg) 2409static inline bool ioapic_irqd_mask(struct irq_data *data, struct irq_cfg *cfg)
2443{ 2410{
2444 /* If we are moving the irq we need to mask it */ 2411 /* 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)
3756 return res; 3723 return res;
3757} 3724}
3758 3725
3759void __init ioapic_and_gsi_init(void) 3726void __init native_io_apic_init_mappings(void)
3760{
3761 io_apic_ops.init();
3762}
3763
3764static void __init __ioapic_init_mappings(void)
3765{ 3727{
3766 unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; 3728 unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
3767 struct resource *ioapic_res; 3729 struct resource *ioapic_res;
diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c
index 00d2422ca7c9..f00a68cca37a 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 = {
530 530
531 .read = native_apic_mem_read, 531 .read = native_apic_mem_read,
532 .write = native_apic_mem_write, 532 .write = native_apic_mem_write,
533 .eoi_write = native_apic_mem_write,
533 .icr_read = native_apic_icr_read, 534 .icr_read = native_apic_icr_read,
534 .icr_write = native_apic_icr_write, 535 .icr_write = native_apic_icr_write,
535 .wait_icr_idle = native_apic_wait_icr_idle, 536 .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 ff2c1b9aac4d..1b291da09e60 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 = {
142 142
143 .read = native_apic_mem_read, 143 .read = native_apic_mem_read,
144 .write = native_apic_mem_write, 144 .write = native_apic_mem_write,
145 .eoi_write = native_apic_mem_write,
145 .icr_read = native_apic_icr_read, 146 .icr_read = native_apic_icr_read,
146 .icr_write = native_apic_icr_write, 147 .icr_write = native_apic_icr_write,
147 .wait_icr_idle = native_apic_wait_icr_idle, 148 .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 fea000b27f07..659897c00755 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 = {
546 546
547 .read = native_apic_mem_read, 547 .read = native_apic_mem_read,
548 .write = native_apic_mem_write, 548 .write = native_apic_mem_write,
549 .eoi_write = native_apic_mem_write,
549 .icr_read = native_apic_icr_read, 550 .icr_read = native_apic_icr_read,
550 .icr_write = native_apic_icr_write, 551 .icr_write = native_apic_icr_write,
551 .wait_icr_idle = native_apic_wait_icr_idle, 552 .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 48f3103b3c93..ff35cff0e1a7 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 = {
260 260
261 .read = native_apic_msr_read, 261 .read = native_apic_msr_read,
262 .write = native_apic_msr_write, 262 .write = native_apic_msr_write,
263 .eoi_write = native_apic_msr_eoi_write,
263 .icr_read = native_x2apic_icr_read, 264 .icr_read = native_x2apic_icr_read,
264 .icr_write = native_x2apic_icr_write, 265 .icr_write = native_x2apic_icr_write,
265 .wait_icr_idle = native_x2apic_wait_icr_idle, 266 .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 991e315f4227..c17e982db275 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 = {
172 172
173 .read = native_apic_msr_read, 173 .read = native_apic_msr_read,
174 .write = native_apic_msr_write, 174 .write = native_apic_msr_write,
175 .eoi_write = native_apic_msr_eoi_write,
175 .icr_read = native_x2apic_icr_read, 176 .icr_read = native_x2apic_icr_read,
176 .icr_write = native_x2apic_icr_write, 177 .icr_write = native_x2apic_icr_write,
177 .wait_icr_idle = native_x2apic_wait_icr_idle, 178 .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 87bfa69e216e..c6d03f7a4401 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 = {
404 404
405 .read = native_apic_msr_read, 405 .read = native_apic_msr_read,
406 .write = native_apic_msr_write, 406 .write = native_apic_msr_write,
407 .eoi_write = native_apic_msr_eoi_write,
407 .icr_read = native_x2apic_icr_read, 408 .icr_read = native_x2apic_icr_read,
408 .icr_write = native_x2apic_icr_write, 409 .icr_write = native_x2apic_icr_write,
409 .wait_icr_idle = native_x2apic_wait_icr_idle, 410 .wait_icr_idle = native_x2apic_wait_icr_idle,
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 1a2901562059..7e67c5a71061 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1012,7 +1012,8 @@ void __init setup_arch(char **cmdline_p)
1012 init_cpu_to_node(); 1012 init_cpu_to_node();
1013 1013
1014 init_apic_mappings(); 1014 init_apic_mappings();
1015 ioapic_and_gsi_init(); 1015 if (x86_io_apic_ops.init)
1016 x86_io_apic_ops.init();
1016 1017
1017 kvm_guest_init(); 1018 kvm_guest_init();
1018 1019
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index 9cf71d0b2d37..35c5e543f550 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -18,6 +18,7 @@
18#include <asm/e820.h> 18#include <asm/e820.h>
19#include <asm/time.h> 19#include <asm/time.h>
20#include <asm/irq.h> 20#include <asm/irq.h>
21#include <asm/io_apic.h>
21#include <asm/pat.h> 22#include <asm/pat.h>
22#include <asm/tsc.h> 23#include <asm/tsc.h>
23#include <asm/iommu.h> 24#include <asm/iommu.h>
@@ -119,3 +120,10 @@ struct x86_msi_ops x86_msi = {
119 .teardown_msi_irqs = default_teardown_msi_irqs, 120 .teardown_msi_irqs = default_teardown_msi_irqs,
120 .restore_msi_irqs = default_restore_msi_irqs, 121 .restore_msi_irqs = default_restore_msi_irqs,
121}; 122};
123
124struct x86_io_apic_ops x86_io_apic_ops = {
125 .init = native_io_apic_init_mappings,
126 .read = native_io_apic_read,
127 .write = native_io_apic_write,
128 .modify = native_io_apic_modify,
129};
diff --git a/arch/x86/platform/visws/visws_quirks.c b/arch/x86/platform/visws/visws_quirks.c
index c7abf13a213f..94d8a39332ec 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)
445 445
446 spin_lock_irqsave(&cobalt_lock, flags); 446 spin_lock_irqsave(&cobalt_lock, flags);
447 disable_cobalt_irq(data); 447 disable_cobalt_irq(data);
448 apic_write(APIC_EOI, APIC_EIO_ACK); 448 apic_write(APIC_EOI, APIC_EOI_ACK);
449 spin_unlock_irqrestore(&cobalt_lock, flags); 449 spin_unlock_irqrestore(&cobalt_lock, flags);
450} 450}
451 451
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
index add2c2d729ce..96ab2c09cb68 100644
--- a/arch/x86/xen/Makefile
+++ b/arch/x86/xen/Makefile
@@ -20,5 +20,5 @@ obj-$(CONFIG_EVENT_TRACING) += trace.o
20obj-$(CONFIG_SMP) += smp.o 20obj-$(CONFIG_SMP) += smp.o
21obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o 21obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
22obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o 22obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o
23obj-$(CONFIG_XEN_DOM0) += vga.o 23obj-$(CONFIG_XEN_DOM0) += apic.o vga.o
24obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o 24obj-$(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 000000000000..ec57bd3818a4
--- /dev/null
+++ b/arch/x86/xen/apic.c
@@ -0,0 +1,33 @@
1#include <linux/init.h>
2
3#include <asm/x86_init.h>
4#include <asm/apic.h>
5#include <asm/xen/hypercall.h>
6
7#include <xen/xen.h>
8#include <xen/interface/physdev.h>
9
10unsigned int xen_io_apic_read(unsigned apic, unsigned reg)
11{
12 struct physdev_apic apic_op;
13 int ret;
14
15 apic_op.apic_physbase = mpc_ioapic_addr(apic);
16 apic_op.reg = reg;
17 ret = HYPERVISOR_physdev_op(PHYSDEVOP_apic_read, &apic_op);
18 if (!ret)
19 return apic_op.value;
20
21 /* fallback to return an emulated IO_APIC values */
22 if (reg == 0x1)
23 return 0x00170020;
24 else if (reg == 0x0)
25 return apic << 24;
26
27 return 0xfd;
28}
29
30void __init xen_init_apic(void)
31{
32 x86_io_apic_ops.read = xen_io_apic_read;
33}
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 95dccce8e979..c0f5facdb10c 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1396,6 +1396,8 @@ asmlinkage void __init xen_start_kernel(void)
1396 xen_start_info->console.domU.mfn = 0; 1396 xen_start_info->console.domU.mfn = 0;
1397 xen_start_info->console.domU.evtchn = 0; 1397 xen_start_info->console.domU.evtchn = 0;
1398 1398
1399 xen_init_apic();
1400
1399 /* Make sure ACS will be enabled */ 1401 /* Make sure ACS will be enabled */
1400 pci_request_acs(); 1402 pci_request_acs();
1401 } 1403 }
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 69f5857660ac..3506cd4f9a43 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,
1864#endif /* CONFIG_X86_64 */ 1864#endif /* CONFIG_X86_64 */
1865 1865
1866static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss; 1866static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss;
1867static unsigned char fake_ioapic_mapping[PAGE_SIZE] __page_aligned_bss;
1868 1867
1869static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot) 1868static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
1870{ 1869{
@@ -1905,7 +1904,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
1905 * We just don't map the IO APIC - all access is via 1904 * We just don't map the IO APIC - all access is via
1906 * hypercalls. Keep the address in the pte for reference. 1905 * hypercalls. Keep the address in the pte for reference.
1907 */ 1906 */
1908 pte = pfn_pte(PFN_DOWN(__pa(fake_ioapic_mapping)), PAGE_KERNEL); 1907 pte = pfn_pte(PFN_DOWN(__pa(dummy_mapping)), PAGE_KERNEL);
1909 break; 1908 break;
1910#endif 1909#endif
1911 1910
@@ -2070,7 +2069,6 @@ void __init xen_init_mmu_ops(void)
2070 pv_mmu_ops = xen_mmu_ops; 2069 pv_mmu_ops = xen_mmu_ops;
2071 2070
2072 memset(dummy_mapping, 0xff, PAGE_SIZE); 2071 memset(dummy_mapping, 0xff, PAGE_SIZE);
2073 memset(fake_ioapic_mapping, 0xfd, PAGE_SIZE);
2074} 2072}
2075 2073
2076/* Protected by xen_reservation_lock. */ 2074/* Protected by xen_reservation_lock. */
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index b095739ccd4c..45c0c0667bd9 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -92,11 +92,15 @@ struct dom0_vga_console_info;
92 92
93#ifdef CONFIG_XEN_DOM0 93#ifdef CONFIG_XEN_DOM0
94void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size); 94void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size);
95void __init xen_init_apic(void);
95#else 96#else
96static inline void __init xen_init_vga(const struct dom0_vga_console_info *info, 97static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,
97 size_t size) 98 size_t size)
98{ 99{
99} 100}
101static inline void __init xen_init_apic(void)
102{
103}
100#endif 104#endif
101 105
102/* Declare an asm function, along with symbols needed to make it 106/* Declare an asm function, along with symbols needed to make it