136 lines
4.2 KiB
Diff
136 lines
4.2 KiB
Diff
|
From: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
|
||
|
|
||
|
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.
|
||
|
|
||
|
[ Impact: indirect IO APIC access via io_apic_ops ]
|
||
|
|
||
|
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>
|
||
|
---
|
||
|
arch/x86/include/asm/io_apic.h | 9 +++++++
|
||
|
arch/x86/kernel/apic/io_apic.c | 50 +++++++++++++++++++++++++++++++++++++--
|
||
|
2 files changed, 56 insertions(+), 3 deletions(-)
|
||
|
|
||
|
diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h
|
||
|
index 690d1cc..190d8c2 100644
|
||
|
--- a/arch/x86/include/asm/io_apic.h
|
||
|
+++ b/arch/x86/include/asm/io_apic.h
|
||
|
@@ -21,6 +21,15 @@
|
||
|
#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:
|
||
|
*/
|
||
|
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
|
||
|
index fb07275..bf120234 100644
|
||
|
--- a/arch/x86/kernel/apic/io_apic.c
|
||
|
+++ b/arch/x86/kernel/apic/io_apic.c
|
||
|
@@ -67,6 +67,25 @@
|
||
|
#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;
|
||
|
+}
|
||
|
+
|
||
|
/*
|
||
|
* Is the SiS APIC rmw bug present ?
|
||
|
* -1 = don't know, 0 = no, 1 = yes
|
||
|
@@ -294,6 +313,24 @@ 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;
|
||
|
unsigned int unused[3];
|
||
|
@@ -314,14 +351,15 @@ static inline void io_apic_eoi(unsigned int apic, unsigned int vector)
|
||
|
writel(vector, &io_apic->eoi);
|
||
|
}
|
||
|
|
||
|
-static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg)
|
||
|
+static unsigned int __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 inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned int value)
|
||
|
+static void __io_apic_write(unsigned int apic, unsigned int reg,
|
||
|
+ unsigned int value)
|
||
|
{
|
||
|
struct io_apic __iomem *io_apic = io_apic_base(apic);
|
||
|
writel(reg, &io_apic->index);
|
||
|
@@ -334,7 +372,8 @@ static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned i
|
||
|
*
|
||
|
* Older SiS APIC requires we rewrite the index register
|
||
|
*/
|
||
|
-static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value)
|
||
|
+static void __io_apic_modify(unsigned int apic, unsigned int reg,
|
||
|
+ unsigned int value)
|
||
|
{
|
||
|
struct io_apic __iomem *io_apic = io_apic_base(apic);
|
||
|
|
||
|
@@ -3873,6 +3912,11 @@ static struct resource * __init ioapic_setup_resources(int nr_ioapics)
|
||
|
|
||
|
void __init ioapic_and_gsi_init(void)
|
||
|
{
|
||
|
+ io_apic_ops.init();
|
||
|
+}
|
||
|
+
|
||
|
+static void __init __ioapic_init_mappings(void)
|
||
|
+{
|
||
|
unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
|
||
|
struct resource *ioapic_res;
|
||
|
int i;
|
||
|
--
|
||
|
1.7.7.5
|
||
|
|