aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2021-06-02 22:27:32 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-06-03 19:47:31 +0000
commite9e00cc0c98738f0ce7bface221c920c36a1356e (patch)
tree15fe12835f260a3aa3368df51eb2f537bc879c7c
parent92adf00d0512b674ce18eb1a542ae42e85dd5bca (diff)
downloadsrc-e9e00cc0c98738f0ce7bface221c920c36a1356e.tar.gz
src-e9e00cc0c98738f0ce7bface221c920c36a1356e.zip
madt_setup_local: extract special case checks into a helper
Reviewed by: markj Tested by: David Sebek <dasebek@gmail.com> Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D30624
-rw-r--r--sys/x86/acpica/madt.c114
1 files changed, 64 insertions, 50 deletions
diff --git a/sys/x86/acpica/madt.c b/sys/x86/acpica/madt.c
index 035a618f68a3..e041296d4ca5 100644
--- a/sys/x86/acpica/madt.c
+++ b/sys/x86/acpica/madt.c
@@ -134,70 +134,84 @@ static const char *x2apic_sandy_dis[] = {
};
/*
- * Initialize the local APIC on the BSP.
+ * Automatically detect several configurations where x2APIC mode is
+ * known to cause troubles. User can override the setting with
+ * hw.x2apic_enable tunable.
*/
-static int
-madt_setup_local(void)
+static const char *
+madt_x2apic_disable_reason(void)
{
ACPI_TABLE_DMAR *dmartbl;
vm_paddr_t dmartbl_physaddr;
const char *reason;
char *hw_vendor;
u_int p[4];
- int i, user_x2apic;
- bool bios_x2apic;
+ int i;
- if ((cpu_feature2 & CPUID2_X2APIC) != 0) {
- reason = NULL;
+ reason = NULL;
+ dmartbl_physaddr = acpi_find_table(ACPI_SIG_DMAR);
+ if (dmartbl_physaddr != 0) {
+ dmartbl = acpi_map_table(dmartbl_physaddr, ACPI_SIG_DMAR);
+ if ((dmartbl->Flags & ACPI_DMAR_X2APIC_OPT_OUT) != 0)
+ reason = "by DMAR table";
+ acpi_unmap_table(dmartbl);
+ if (reason != NULL)
+ return (reason);
+ }
+
+ 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)
+ return ("inside VMWare without intr redirection");
+ }
+
+ if (vm_guest == VM_GUEST_XEN)
+ return ("due to running under XEN");
+
+ if (vm_guest == VM_GUEST_NO &&
+ CPUID_TO_FAMILY(cpu_id) == 0x6 &&
+ CPUID_TO_MODEL(cpu_id) == 0x2a) {
+ hw_vendor = kern_getenv("smbios.planar.maker");
/*
- * Automatically detect several configurations where
- * x2APIC mode is known to cause troubles. User can
- * override the setting with hw.x2apic_enable tunable.
+ * It seems that some SandyBridge-based notebook
+ * BIOSes have a bug which prevents booting AP in
+ * x2APIC mode. Since the only way to detect mobile
+ * CPU is to check northbridge pci id, which cannot be
+ * done that early, disable x2APIC for all such
+ * machines.
*/
- dmartbl_physaddr = acpi_find_table(ACPI_SIG_DMAR);
- if (dmartbl_physaddr != 0) {
- dmartbl = acpi_map_table(dmartbl_physaddr,
- ACPI_SIG_DMAR);
- if ((dmartbl->Flags & ACPI_DMAR_X2APIC_OPT_OUT) != 0)
- reason = "by DMAR table";
- acpi_unmap_table(dmartbl);
- }
- if (reason != NULL) {
- /* Already disabled */
- } else 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)
- reason =
- "inside VMWare without intr redirection";
- } else if (vm_guest == VM_GUEST_XEN) {
- reason = "due to running under XEN";
- } else if (vm_guest == VM_GUEST_NO &&
- CPUID_TO_FAMILY(cpu_id) == 0x6 &&
- CPUID_TO_MODEL(cpu_id) == 0x2a) {
- hw_vendor = kern_getenv("smbios.planar.maker");
- /*
- * It seems that some SandyBridge-based
- * notebook BIOSes have a bug which prevents
- * booting AP in x2APIC mode. Since the only
- * way to detect mobile CPU is to check
- * northbridge pci id, which cannot be done
- * that early, disable x2APIC for all such
- * machines.
- */
- if (hw_vendor != NULL) {
- for (i = 0; i < nitems(x2apic_sandy_dis); i++) {
- if (strcmp(hw_vendor,
- x2apic_sandy_dis[i]) == 0) {
- reason =
- "for a suspected SandyBridge BIOS bug";
- break;
- }
+ if (hw_vendor != NULL) {
+ for (i = 0; i < nitems(x2apic_sandy_dis); i++) {
+ if (strcmp(hw_vendor, x2apic_sandy_dis[i]) ==
+ 0) {
+ reason =
+ "for a suspected SandyBridge BIOS bug";
+ break;
}
- freeenv(hw_vendor);
}
+ freeenv(hw_vendor);
}
+ if (reason != NULL)
+ return (reason);
+ }
+
+ return (NULL);
+}
+
+/*
+ * Initialize the local APIC on the BSP.
+ */
+static int
+madt_setup_local(void)
+{
+ const char *reason;
+ int user_x2apic;
+ bool bios_x2apic;
+
+ if ((cpu_feature2 & CPUID2_X2APIC) != 0) {
+ reason = madt_x2apic_disable_reason();
bios_x2apic = lapic_is_x2apic();
if (reason != NULL && bios_x2apic) {
if (bootverbose)