From e6dee92888cc1f1ee52d36053fabf97cfd2f9518 Mon Sep 17 00:00:00 2001 From: Sepherosa Ziehau Date: Wed, 14 Mar 2012 11:18:44 +0800 Subject: [PATCH] ioapic: By default, disable I/O APIC if we are booting on a virtual machine I/O APIC causes too much trouble on virtual machines; simply disable I/O APIC for virtual machines by default. You could always explicitly enable I/O APIC on virtual machines by setting tunable hw.ioapic_enable to 1 Thank swildner@ for hint on virtual machine detection method. Reported-by: many --- sys/platform/pc32/apic/ioapic.c | 2 +- sys/platform/pc32/i386/machdep.c | 13 +++++++++++++ sys/platform/pc64/apic/ioapic.c | 2 +- sys/platform/pc64/x86_64/machdep.c | 25 +++++++++++++++++++++---- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/sys/platform/pc32/apic/ioapic.c b/sys/platform/pc32/apic/ioapic.c index 55db0e1..18d06f1 100644 --- a/sys/platform/pc32/apic/ioapic.c +++ b/sys/platform/pc32/apic/ioapic.c @@ -80,7 +80,7 @@ static struct ioapic_conf ioapic_conf; static TAILQ_HEAD(, ioapic_enumerator) ioapic_enumerators = TAILQ_HEAD_INITIALIZER(ioapic_enumerators); -int ioapic_enable = 1; /* I/O APIC is enabled by default */ +int ioapic_enable = -1; /* I/O APIC auto-enable mode */ static int ioapic_config(void) diff --git a/sys/platform/pc32/i386/machdep.c b/sys/platform/pc32/i386/machdep.c index 85c18db..6864c51 100644 --- a/sys/platform/pc32/i386/machdep.c +++ b/sys/platform/pc32/i386/machdep.c @@ -1953,6 +1953,19 @@ init386(int first) TUNABLE_INT_FETCH("hw.lapic_enable", &lapic_enable); /* + * Some of the virtaul machines do not work w/ I/O APIC + * enabled. If the user does not explicitly enable or + * disable the I/O APIC (ioapic_enable < 0), then we + * disable I/O APIC on all virtual machines. + */ + if (ioapic_enable < 0) { + if (cpu_feature2 & CPUID2_VMM) + ioapic_enable = 0; + else + ioapic_enable = 1; + } + + /* * start with one cpu. Note: with one cpu, ncpus2_shift, ncpus2_mask, * and ncpus_fit_mask remain 0. */ diff --git a/sys/platform/pc64/apic/ioapic.c b/sys/platform/pc64/apic/ioapic.c index a1e6709..6065205 100644 --- a/sys/platform/pc64/apic/ioapic.c +++ b/sys/platform/pc64/apic/ioapic.c @@ -80,7 +80,7 @@ static struct ioapic_conf ioapic_conf; static TAILQ_HEAD(, ioapic_enumerator) ioapic_enumerators = TAILQ_HEAD_INITIALIZER(ioapic_enumerators); -int ioapic_enable = 1; /* I/O APIC is enabled by default */ +int ioapic_enable = -1; /* I/O APIC auto-enable mode */ static int ioapic_config(void) diff --git a/sys/platform/pc64/x86_64/machdep.c b/sys/platform/pc64/x86_64/machdep.c index ac879b7..4260785 100644 --- a/sys/platform/pc64/x86_64/machdep.c +++ b/sys/platform/pc64/x86_64/machdep.c @@ -1795,10 +1795,6 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) */ MachIntrABI = MachIntrABI_ICU; - TUNABLE_INT_FETCH("hw.apic_io_enable", &ioapic_enable); /* for compat */ - TUNABLE_INT_FETCH("hw.ioapic_enable", &ioapic_enable); - TUNABLE_INT_FETCH("hw.lapic_enable", &lapic_enable); - /* * start with one cpu. Note: with one cpu, ncpus2_shift, ncpus2_mask, * and ncpus_fit_mask remain 0. @@ -1910,6 +1906,27 @@ hammer_time(u_int64_t modulep, u_int64_t physfree) identify_cpu(); /* Final stage of CPU initialization */ initializecpu(); /* Initialize CPU registers */ + TUNABLE_INT_FETCH("hw.apic_io_enable", &ioapic_enable); /* for compat */ + TUNABLE_INT_FETCH("hw.ioapic_enable", &ioapic_enable); + TUNABLE_INT_FETCH("hw.lapic_enable", &lapic_enable); + + /* + * Some of the virtaul machines do not work w/ I/O APIC + * enabled. If the user does not explicitly enable or + * disable the I/O APIC (ioapic_enable < 0), then we + * disable I/O APIC on all virtual machines. + * + * NOTE: + * This must be done after identify_cpu(), which sets + * 'cpu_feature2' + */ + if (ioapic_enable < 0) { + if (cpu_feature2 & CPUID2_VMM) + ioapic_enable = 0; + else + ioapic_enable = 1; + } + /* make an initial tss so cpu can get interrupt stack on syscall! */ gd->gd_common_tss.tss_rsp0 = (register_t)(thread0.td_kstack + -- 1.7.7.2