diff options
author | Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> | 2012-03-21 22:58:08 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-03-28 03:49:29 -0400 |
commit | 136d249ef7dbf0fefa292082cc40be1ea864cbd6 (patch) | |
tree | 584684e7d7c79aaa698bfb29a496dc44a02e2528 /arch | |
parent | a3c8121b8724c3d496dc00201ab40e8313edcf0d (diff) |
x86/ioapic: Add io_apic_ops driver layer to allow interception
Xen dom0 needs to paravirtualize IO operations to the IO APIC,
so add a io_apic_ops for it to intercept. Do this as ops
structure because there's at least some chance that another
paravirtualized environment may want to intercept these.
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Acked-by: Suresh Siddha <suresh.b.siddha@intel.com>
Cc: jwboyer@redhat.com
Cc: yinghai@kernel.org
Link: http://lkml.kernel.org/r/1332385090-18056-2-git-send-email-konrad.wilk@oracle.com
[ Made all the affected code easier on the eyes ]
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/include/asm/io_apic.h | 9 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 58 |
2 files changed, 60 insertions, 7 deletions
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index 690d1cc9a877..2c4943de5150 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h | |||
@@ -21,6 +21,15 @@ | |||
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 | |||
24 | /* | 33 | /* |
25 | * The structure of the IO-APIC: | 34 | * The structure of the IO-APIC: |
26 | */ | 35 | */ |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 2c428c5d7ca3..e88300d8e80a 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -64,9 +64,28 @@ | |||
64 | #include <asm/apic.h> | 64 | #include <asm/apic.h> |
65 | 65 | ||
66 | #define __apicdebuginit(type) static type __init | 66 | #define __apicdebuginit(type) static type __init |
67 | |||
67 | #define for_each_irq_pin(entry, head) \ | 68 | #define for_each_irq_pin(entry, head) \ |
68 | for (entry = head; entry; entry = entry->next) | 69 | for (entry = head; entry; entry = entry->next) |
69 | 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 | |||
70 | /* | 89 | /* |
71 | * Is the SiS APIC rmw bug present ? | 90 | * Is the SiS APIC rmw bug present ? |
72 | * -1 = don't know, 0 = no, 1 = yes | 91 | * -1 = don't know, 0 = no, 1 = yes |
@@ -294,6 +313,22 @@ static void free_irq_at(unsigned int at, struct irq_cfg *cfg) | |||
294 | irq_free_desc(at); | 313 | irq_free_desc(at); |
295 | } | 314 | } |
296 | 315 | ||
316 | static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) | ||
317 | { | ||
318 | return io_apic_ops.read(apic, reg); | ||
319 | } | ||
320 | |||
321 | static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) | ||
322 | { | ||
323 | io_apic_ops.write(apic, reg, value); | ||
324 | } | ||
325 | |||
326 | static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) | ||
327 | { | ||
328 | io_apic_ops.modify(apic, reg, value); | ||
329 | } | ||
330 | |||
331 | |||
297 | struct io_apic { | 332 | struct io_apic { |
298 | unsigned int index; | 333 | unsigned int index; |
299 | unsigned int unused[3]; | 334 | unsigned int unused[3]; |
@@ -314,16 +349,17 @@ static inline void io_apic_eoi(unsigned int apic, unsigned int vector) | |||
314 | writel(vector, &io_apic->eoi); | 349 | writel(vector, &io_apic->eoi); |
315 | } | 350 | } |
316 | 351 | ||
317 | static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) | 352 | static unsigned int __io_apic_read(unsigned int apic, unsigned int reg) |
318 | { | 353 | { |
319 | struct io_apic __iomem *io_apic = io_apic_base(apic); | 354 | struct io_apic __iomem *io_apic = io_apic_base(apic); |
320 | writel(reg, &io_apic->index); | 355 | writel(reg, &io_apic->index); |
321 | return readl(&io_apic->data); | 356 | return readl(&io_apic->data); |
322 | } | 357 | } |
323 | 358 | ||
324 | static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) | 359 | static void __io_apic_write(unsigned int apic, unsigned int reg, unsigned int value) |
325 | { | 360 | { |
326 | struct io_apic __iomem *io_apic = io_apic_base(apic); | 361 | struct io_apic __iomem *io_apic = io_apic_base(apic); |
362 | |||
327 | writel(reg, &io_apic->index); | 363 | writel(reg, &io_apic->index); |
328 | writel(value, &io_apic->data); | 364 | writel(value, &io_apic->data); |
329 | } | 365 | } |
@@ -334,7 +370,7 @@ static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned i | |||
334 | * | 370 | * |
335 | * Older SiS APIC requires we rewrite the index register | 371 | * Older SiS APIC requires we rewrite the index register |
336 | */ | 372 | */ |
337 | static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) | 373 | static void __io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) |
338 | { | 374 | { |
339 | struct io_apic __iomem *io_apic = io_apic_base(apic); | 375 | struct io_apic __iomem *io_apic = io_apic_base(apic); |
340 | 376 | ||
@@ -377,6 +413,7 @@ static struct IO_APIC_route_entry __ioapic_read_entry(int apic, int pin) | |||
377 | 413 | ||
378 | eu.w1 = io_apic_read(apic, 0x10 + 2 * pin); | 414 | eu.w1 = io_apic_read(apic, 0x10 + 2 * pin); |
379 | eu.w2 = io_apic_read(apic, 0x11 + 2 * pin); | 415 | eu.w2 = io_apic_read(apic, 0x11 + 2 * pin); |
416 | |||
380 | return eu.entry; | 417 | return eu.entry; |
381 | } | 418 | } |
382 | 419 | ||
@@ -384,9 +421,11 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin) | |||
384 | { | 421 | { |
385 | union entry_union eu; | 422 | union entry_union eu; |
386 | unsigned long flags; | 423 | unsigned long flags; |
424 | |||
387 | raw_spin_lock_irqsave(&ioapic_lock, flags); | 425 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
388 | eu.entry = __ioapic_read_entry(apic, pin); | 426 | eu.entry = __ioapic_read_entry(apic, pin); |
389 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); | 427 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
428 | |||
390 | return eu.entry; | 429 | return eu.entry; |
391 | } | 430 | } |
392 | 431 | ||
@@ -396,8 +435,7 @@ static struct IO_APIC_route_entry ioapic_read_entry(int apic, int pin) | |||
396 | * the interrupt, and we need to make sure the entry is fully populated | 435 | * the interrupt, and we need to make sure the entry is fully populated |
397 | * before that happens. | 436 | * before that happens. |
398 | */ | 437 | */ |
399 | static void | 438 | static void __ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) |
400 | __ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) | ||
401 | { | 439 | { |
402 | union entry_union eu = {{0, 0}}; | 440 | union entry_union eu = {{0, 0}}; |
403 | 441 | ||
@@ -409,6 +447,7 @@ __ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) | |||
409 | static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) | 447 | static void ioapic_write_entry(int apic, int pin, struct IO_APIC_route_entry e) |
410 | { | 448 | { |
411 | unsigned long flags; | 449 | unsigned long flags; |
450 | |||
412 | raw_spin_lock_irqsave(&ioapic_lock, flags); | 451 | raw_spin_lock_irqsave(&ioapic_lock, flags); |
413 | __ioapic_write_entry(apic, pin, e); | 452 | __ioapic_write_entry(apic, pin, e); |
414 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); | 453 | raw_spin_unlock_irqrestore(&ioapic_lock, flags); |
@@ -435,8 +474,7 @@ static void ioapic_mask_entry(int apic, int pin) | |||
435 | * shared ISA-space IRQs, so we have to support them. We are super | 474 | * shared ISA-space IRQs, so we have to support them. We are super |
436 | * fast in the common case, and fast for shared ISA-space IRQs. | 475 | * fast in the common case, and fast for shared ISA-space IRQs. |
437 | */ | 476 | */ |
438 | static int | 477 | static int __add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin) |
439 | __add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pin) | ||
440 | { | 478 | { |
441 | struct irq_pin_list **last, *entry; | 479 | struct irq_pin_list **last, *entry; |
442 | 480 | ||
@@ -521,6 +559,7 @@ static void io_apic_sync(struct irq_pin_list *entry) | |||
521 | * a dummy read from the IO-APIC | 559 | * a dummy read from the IO-APIC |
522 | */ | 560 | */ |
523 | struct io_apic __iomem *io_apic; | 561 | struct io_apic __iomem *io_apic; |
562 | |||
524 | io_apic = io_apic_base(entry->apic); | 563 | io_apic = io_apic_base(entry->apic); |
525 | readl(&io_apic->data); | 564 | readl(&io_apic->data); |
526 | } | 565 | } |
@@ -3894,6 +3933,11 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics) | |||
3894 | 3933 | ||
3895 | void __init ioapic_and_gsi_init(void) | 3934 | void __init ioapic_and_gsi_init(void) |
3896 | { | 3935 | { |
3936 | io_apic_ops.init(); | ||
3937 | } | ||
3938 | |||
3939 | static void __init __ioapic_init_mappings(void) | ||
3940 | { | ||
3897 | unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; | 3941 | unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0; |
3898 | struct resource *ioapic_res; | 3942 | struct resource *ioapic_res; |
3899 | int i; | 3943 | int i; |