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 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 | ||
| 141 | static 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 | |||
| 141 | static inline u32 native_apic_msr_read(u32 reg) | 146 | static 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 | ||
| 442 | static inline void apic_eoi(void) | ||
| 443 | { | ||
| 444 | apic->eoi_write(APIC_EOI, APIC_EOI_ACK); | ||
| 445 | } | ||
| 446 | |||
| 429 | static inline u64 apic_icr_read(void) | 447 | static 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 | ||
| 451 | static inline u32 apic_read(u32 reg) { return 0; } | 469 | static inline u32 apic_read(u32 reg) { return 0; } |
| 452 | static inline void apic_write(u32 reg, u32 val) { } | 470 | static inline void apic_write(u32 reg, u32 val) { } |
| 471 | static inline void apic_eoi(void) { } | ||
| 453 | static inline u64 apic_icr_read(void) { return 0; } | 472 | static inline u64 apic_icr_read(void) { return 0; } |
| 454 | static inline void apic_icr_write(u32 low, u32 high) { } | 473 | static inline void apic_icr_write(u32 low, u32 high) { } |
| 455 | static inline void apic_wait_icr_idle(void) { } | 474 | static 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 | ||
| 471 | static inline unsigned default_get_apic_id(unsigned long x) | 488 | 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 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 | ||
| 24 | struct 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 | |||
| 31 | void __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; | |||
| 156 | extern int io_apic_set_pci_routing(struct device *dev, int irq, | 147 | extern 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); |
| 158 | void setup_IO_APIC_irq_extra(u32 gsi); | 149 | void setup_IO_APIC_irq_extra(u32 gsi); |
| 159 | extern void ioapic_and_gsi_init(void); | ||
| 160 | extern void ioapic_insert_resources(void); | 150 | extern void ioapic_insert_resources(void); |
| 161 | 151 | ||
| 162 | int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr); | 152 | 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); | |||
| 185 | 175 | ||
| 186 | extern void disable_ioapic_support(void); | 176 | extern void disable_ioapic_support(void); |
| 187 | 177 | ||
| 178 | extern void __init native_io_apic_init_mappings(void); | ||
| 179 | extern unsigned int native_io_apic_read(unsigned int apic, unsigned int reg); | ||
| 180 | extern void native_io_apic_write(unsigned int apic, unsigned int reg, unsigned int val); | ||
| 181 | extern void native_io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val); | ||
| 182 | |||
| 183 | static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) | ||
| 184 | { | ||
| 185 | return x86_io_apic_ops.read(apic, reg); | ||
| 186 | } | ||
| 187 | |||
| 188 | static 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 | } | ||
| 192 | static 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 |
| 192 | static const int timer_through_8259 = 0; | 200 | static const int timer_through_8259 = 0; |
| 193 | static inline void ioapic_and_gsi_init(void) { } | ||
| 194 | static inline void ioapic_insert_resources(void) { } | 201 | static inline void ioapic_insert_resources(void) { } |
| 195 | #define gsi_top (NR_IRQS_LEGACY) | 202 | #define gsi_top (NR_IRQS_LEGACY) |
| 196 | static inline int mp_find_ioapic(u32 gsi) { return 0; } | 203 | static inline int mp_find_ioapic(u32 gsi) { return 0; } |
| @@ -212,6 +219,10 @@ static inline int restore_ioapic_entries(void) | |||
| 212 | 219 | ||
| 213 | static inline void mp_save_irq(struct mpc_intsrc *m) { }; | 220 | static inline void mp_save_irq(struct mpc_intsrc *m) { }; |
| 214 | static inline void disable_ioapic_support(void) { } | 221 | static 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 | ||
| 191 | struct 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 | |||
| 191 | extern struct x86_init_ops x86_init; | 198 | extern struct x86_init_ops x86_init; |
| 192 | extern struct x86_cpuinit_ops x86_cpuinit; | 199 | extern struct x86_cpuinit_ops x86_cpuinit; |
| 193 | extern struct x86_platform_ops x86_platform; | 200 | extern struct x86_platform_ops x86_platform; |
| 194 | extern struct x86_msi_ops x86_msi; | 201 | extern struct x86_msi_ops x86_msi; |
| 195 | 202 | extern struct x86_io_apic_ops x86_io_apic_ops; | |
| 196 | extern void x86_init_noop(void); | 203 | extern void x86_init_noop(void); |
| 197 | extern void x86_init_uint_noop(unsigned int unused); | 204 | extern 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 | ||
| 71 | static void __init __ioapic_init_mappings(void); | ||
| 72 | |||
| 73 | static unsigned int __io_apic_read (unsigned int apic, unsigned int reg); | ||
| 74 | static void __io_apic_write (unsigned int apic, unsigned int reg, unsigned int val); | ||
| 75 | static void __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int val); | ||
| 76 | |||
| 77 | static 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 | |||
| 84 | void __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 |
| 90 | static void irq_remap_modify_chip_defaults(struct irq_chip *chip); | 72 | static void irq_remap_modify_chip_defaults(struct irq_chip *chip); |
| 91 | static inline bool irq_remapped(struct irq_cfg *cfg) | 73 | 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) | |||
| 329 | irq_free_desc(at); | 311 | irq_free_desc(at); |
| 330 | } | 312 | } |
| 331 | 313 | ||
| 332 | static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) | ||
| 333 | { | ||
| 334 | return io_apic_ops.read(apic, reg); | ||
| 335 | } | ||
| 336 | |||
| 337 | static 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 | |||
| 342 | static 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 | ||
| 348 | struct io_apic { | 315 | struct 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 | ||
| 368 | static unsigned int __io_apic_read(unsigned int apic, unsigned int reg) | 335 | unsigned 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 | ||
| 375 | static void __io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) | 342 | void 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 | */ |
| 389 | static void __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) | 356 | void 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 | ||
| 398 | static 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 | |||
| 421 | union entry_union { | 365 | union 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) | |||
| 2439 | atomic_t irq_mis_count; | 2383 | atomic_t irq_mis_count; |
| 2440 | 2384 | ||
| 2441 | #ifdef CONFIG_GENERIC_PENDING_IRQ | 2385 | #ifdef CONFIG_GENERIC_PENDING_IRQ |
| 2386 | static 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 | |||
| 2442 | static inline bool ioapic_irqd_mask(struct irq_data *data, struct irq_cfg *cfg) | 2409 | static 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 | ||
| 3759 | void __init ioapic_and_gsi_init(void) | 3726 | void __init native_io_apic_init_mappings(void) |
| 3760 | { | ||
| 3761 | io_apic_ops.init(); | ||
| 3762 | } | ||
| 3763 | |||
| 3764 | static 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 | |||
| 124 | struct 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 | |||
| 20 | obj-$(CONFIG_SMP) += smp.o | 20 | obj-$(CONFIG_SMP) += smp.o |
| 21 | obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o | 21 | obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o |
| 22 | obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o | 22 | obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o |
| 23 | obj-$(CONFIG_XEN_DOM0) += vga.o | 23 | obj-$(CONFIG_XEN_DOM0) += apic.o vga.o |
| 24 | obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o | 24 | 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 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 | |||
| 10 | unsigned 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 | |||
| 30 | void __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 | ||
| 1866 | static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss; | 1866 | static unsigned char dummy_mapping[PAGE_SIZE] __page_aligned_bss; |
| 1867 | static unsigned char fake_ioapic_mapping[PAGE_SIZE] __page_aligned_bss; | ||
| 1868 | 1867 | ||
| 1869 | static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot) | 1868 | static 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 |
| 94 | void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size); | 94 | void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size); |
| 95 | void __init xen_init_apic(void); | ||
| 95 | #else | 96 | #else |
| 96 | static inline void __init xen_init_vga(const struct dom0_vga_console_info *info, | 97 | static 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 | } |
| 101 | static 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 |
