From: Sepherosa Ziehau Date: Wed, 14 Mar 2012 03:18:44 +0000 (+0800) Subject: ioapic: By default, disable I/O APIC if we are booting on a virtual machine X-Git-Tag: v3.2.0~1254 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/e6dee92888cc1f1ee52d36053fabf97cfd2f9518 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 --- diff --git a/sys/platform/pc32/apic/ioapic.c b/sys/platform/pc32/apic/ioapic.c index 55db0e19e6..18d06f1e62 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 85c18db43a..6864c51c77 100644 --- a/sys/platform/pc32/i386/machdep.c +++ b/sys/platform/pc32/i386/machdep.c @@ -1952,6 +1952,19 @@ init386(int first) 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. + */ + 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 a1e6709d6f..6065205594 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 ac879b73dd..4260785e24 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 +