On Wed, Sep 14, 2016 at 05:02:21PM +0300, Andriy Gapon
wrote:> On 14/09/2016 15:49, Slawa Olhovchenkov wrote:
> > MSR_APICBASE = 0x fee00d00
> > x2APIC is prohibited but turned on by BIOS
>
> Kostik, ^^^^^
Well, the following might work, but I have no good idea what to do
when BIOS does handoff with x2APIC enabled and directs us to not
enable it. Switching to xAPIC mode is not an option, I suspect.
diff --git a/sys/x86/acpica/madt.c b/sys/x86/acpica/madt.c
index 241a769..3a93fd6 100644
--- a/sys/x86/acpica/madt.c
+++ b/sys/x86/acpica/madt.c
@@ -138,7 +138,6 @@ madt_setup_local(void)
madt = pmap_mapbios(madt_physaddr, madt_length);
if ((cpu_feature2 & CPUID2_X2APIC) != 0) {
- x2apic_mode = 1;
reason = NULL;
/*
@@ -150,21 +149,17 @@ madt_setup_local(void)
if (dmartbl_physaddr != 0) {
dmartbl = acpi_map_table(dmartbl_physaddr,
ACPI_SIG_DMAR);
- if ((dmartbl->Flags & ACPI_DMAR_X2APIC_OPT_OUT) != 0) {
- x2apic_mode = 0;
+ if ((dmartbl->Flags & ACPI_DMAR_X2APIC_OPT_OUT) != 0)
reason = "by DMAR table";
- }
acpi_unmap_table(dmartbl);
}
if (vm_guest == VM_GUEST_VMWARE) {
vmware_hvcall(VMW_HVCMD_GETVCPU_INFO, p);
if ((p[0] & VMW_VCPUINFO_VCPU_RESERVED) != 0 ||
- (p[0] & VMW_VCPUINFO_LEGACY_X2APIC) == 0) {
- x2apic_mode = 0;
- reason = "inside VMWare without intr redirection";
- }
+ (p[0] & VMW_VCPUINFO_LEGACY_X2APIC) == 0)
+ reason + "inside VMWare without intr redirection";
} else if (vm_guest == VM_GUEST_XEN) {
- x2apic_mode = 0;
reason = "due to running under XEN";
} else if (vm_guest == VM_GUEST_NO &&
CPUID_TO_FAMILY(cpu_id) == 0x6 &&
@@ -184,13 +179,21 @@ madt_setup_local(void)
if (!strcmp(hw_vendor, "LENOVO") ||
!strcmp(hw_vendor,
"ASUSTeK Computer Inc.")) {
- x2apic_mode = 0;
reason "for a suspected SandyBridge BIOS bug";
}
freeenv(hw_vendor);
}
}
+ if (reason != NULL && lapic_is_x2apic()) {
+ if (bootverbose)
+ printf("x2APIC should be disabled %s but "
+ "already enabled by BIOS; enabling.\n",
+ reason);
+ reason = NULL;
+ }
+ if (reason == NULL)
+ x2apic_mode = 1;
TUNABLE_INT_FETCH("hw.x2apic_enable", &x2apic_mode);
if (!x2apic_mode && reason != NULL && bootverbose)
printf("x2APIC available but disabled %s\n", reason);
diff --git a/sys/x86/include/apicvar.h b/sys/x86/include/apicvar.h
index 1ddb69e..09c3a63 100644
--- a/sys/x86/include/apicvar.h
+++ b/sys/x86/include/apicvar.h
@@ -206,6 +206,7 @@ struct apic_ops {
void (*create)(u_int, int);
void (*init)(vm_paddr_t);
void (*xapic_mode)(void);
+ bool (*is_x2apic)(void);
void (*setup)(int);
void (*dump)(const char *);
void (*disable)(void);
@@ -268,6 +269,13 @@ lapic_xapic_mode(void)
apic_ops.xapic_mode();
}
+static inline bool
+lapic_is_x2apic(void)
+{
+
+ return (apic_ops.is_x2apic());
+}
+
static inline void
lapic_setup(int boot)
{
diff --git a/sys/x86/x86/local_apic.c b/sys/x86/x86/local_apic.c
index cd774df..d9a3453 100644
--- a/sys/x86/x86/local_apic.c
+++ b/sys/x86/x86/local_apic.c
@@ -269,6 +269,16 @@ native_lapic_enable_x2apic(void)
wrmsr(MSR_APICBASE, apic_base);
}
+static bool
+native_lapic_is_x2apic(void)
+{
+ uint64_t apic_base;
+
+ apic_base = rdmsr(MSR_APICBASE);
+ return ((apic_base & (APICBASE_X2APIC | APICBASE_ENABLED)) =+
(APICBASE_X2APIC | APICBASE_ENABLED));
+}
+
static void lapic_enable(void);
static void lapic_resume(struct pic *pic, bool suspend_cancelled);
static void lapic_timer_oneshot(struct lapic *);
@@ -329,6 +339,7 @@ struct apic_ops apic_ops = {
.create = native_lapic_create,
.init = native_lapic_init,
.xapic_mode = native_lapic_xapic_mode,
+ .is_x2apic = native_lapic_is_x2apic,
.setup = native_lapic_setup,
.dump = native_lapic_dump,
.disable = native_lapic_disable,
diff --git a/sys/x86/xen/xen_apic.c b/sys/x86/xen/xen_apic.c
index 4d7a39b..45c3c18 100644
--- a/sys/x86/xen/xen_apic.c
+++ b/sys/x86/xen/xen_apic.c
@@ -139,6 +139,13 @@ xen_pv_lapic_disable(void)
}
+static bool
+xen_pv_lapic_is_x2apic(void)
+{
+
+ return (false);
+}
+
static void
xen_pv_lapic_eoi(void)
{
@@ -351,6 +358,7 @@ struct apic_ops xen_apic_ops = {
.create = xen_pv_lapic_create,
.init = xen_pv_lapic_init,
.xapic_mode = xen_pv_lapic_disable,
+ .is_x2apic = xen_pv_lapic_is_x2apic,
.setup = xen_pv_lapic_setup,
.dump = xen_pv_lapic_dump,
.disable = xen_pv_lapic_disable,