diff options
-rw-r--r-- | linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c | 6 | ||||
-rw-r--r-- | xen/arch/x86/dom0_ops.c | 13 | ||||
-rw-r--r-- | xen/arch/x86/io_apic.c | 8 | ||||
-rw-r--r-- | xen/include/asm-x86/io_apic.h | 6 | ||||
-rw-r--r-- | xen/include/public/dom0_ops.h | 4 |
5 files changed, 34 insertions, 3 deletions
diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c b/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c index 88a9f2f6f6..cf0e62c5ff 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c +++ b/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c @@ -2483,6 +2483,12 @@ static int __init io_apic_bug_finalize(void) { if(sis_apic_bug == -1) sis_apic_bug = 0; + if (xen_start_info->flags & SIF_INITDOMAIN) { + dom0_op_t op = { .cmd = DOM0_PLATFORM_QUIRK }; + op.u.platform_quirk.quirk_id = sis_apic_bug ? + QUIRK_IOAPIC_BAD_REGSEL : QUIRK_IOAPIC_GOOD_REGSEL; + HYPERVISOR_dom0_op(&op); + } return 0; } diff --git a/xen/arch/x86/dom0_ops.c b/xen/arch/x86/dom0_ops.c index ab76b4e9f5..a77c919733 100644 --- a/xen/arch/x86/dom0_ops.c +++ b/xen/arch/x86/dom0_ops.c @@ -379,13 +379,24 @@ long arch_do_dom0_op(struct dom0_op *op, GUEST_HANDLE(dom0_op_t) u_dom0_op) case DOM0_PLATFORM_QUIRK: { extern int opt_noirqbalance; - switch ( op->u.platform_quirk.quirk_id ) + int quirk_id = op->u.platform_quirk.quirk_id; + switch ( quirk_id ) { case QUIRK_NOIRQBALANCING: printk("Platform quirk -- Disabling IRQ balancing/affinity.\n"); opt_noirqbalance = 1; setup_ioapic_dest(); break; + case QUIRK_IOAPIC_BAD_REGSEL: + case QUIRK_IOAPIC_GOOD_REGSEL: +#ifndef sis_apic_bug + sis_apic_bug = (quirk_id == QUIRK_IOAPIC_BAD_REGSEL); + printk("Platform info -- IO-APIC REGSEL is %s\n", + sis_apic_bug ? "bad" : "good"); +#else + BUG_ON(sis_apic_bug == (quirk_id == QUIRK_IOAPIC_BAD_REGSEL)); +#endif + break; default: ret = -EINVAL; break; diff --git a/xen/arch/x86/io_apic.c b/xen/arch/x86/io_apic.c index 4d74e1900c..a9eb5a8884 100644 --- a/xen/arch/x86/io_apic.c +++ b/xen/arch/x86/io_apic.c @@ -52,6 +52,14 @@ static DEFINE_SPINLOCK(vector_lock); int skip_ioapic_setup; +#ifndef sis_apic_bug +/* + * Is the SiS APIC rmw bug present? + * -1 = don't know, 0 = no, 1 = yes + */ +int sis_apic_bug = -1; +#endif + /* * # of IRQ routing registers */ diff --git a/xen/include/asm-x86/io_apic.h b/xen/include/asm-x86/io_apic.h index 4cacb8b419..47cd148e10 100644 --- a/xen/include/asm-x86/io_apic.h +++ b/xen/include/asm-x86/io_apic.h @@ -139,7 +139,11 @@ static inline void io_apic_write(unsigned int apic, unsigned int reg, unsigned i * * Older SiS APIC requires we rewrite the index regiser */ -#define sis_apic_bug 0 /* This may need propagating from domain0. */ +#ifdef __i386__ +extern int sis_apic_bug; +#else +#define sis_apic_bug 0 +#endif static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned int value) { if (sis_apic_bug) diff --git a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h index 497a1c58d6..345e9f91f4 100644 --- a/xen/include/public/dom0_ops.h +++ b/xen/include/public/dom0_ops.h @@ -404,7 +404,9 @@ typedef struct dom0_getdomaininfolist { DEFINE_GUEST_HANDLE(dom0_getdomaininfolist_t); #define DOM0_PLATFORM_QUIRK 39 -#define QUIRK_NOIRQBALANCING 1 +#define QUIRK_NOIRQBALANCING 1 /* Do not restrict IO-APIC RTE targets */ +#define QUIRK_IOAPIC_BAD_REGSEL 2 /* IO-APIC REGSEL forgets its value */ +#define QUIRK_IOAPIC_GOOD_REGSEL 3 /* IO-APIC REGSEL behaves properly */ typedef struct dom0_platform_quirk { /* IN variables. */ uint32_t quirk_id; |