aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c6
-rw-r--r--xen/arch/x86/dom0_ops.c13
-rw-r--r--xen/arch/x86/io_apic.c8
-rw-r--r--xen/include/asm-x86/io_apic.h6
-rw-r--r--xen/include/public/dom0_ops.h4
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;