svn commit: r306628 - in stable/11/sys/x86: acpica include x86 xen

Konstantin Belousov kib at FreeBSD.org
Mon Oct 3 09:39:48 UTC 2016


Author: kib
Date: Mon Oct  3 09:39:46 2016
New Revision: 306628
URL: https://svnweb.freebsd.org/changeset/base/306628

Log:
  MFC r305978:
  Detect x2APIC mode on boot and obey it.

Modified:
  stable/11/sys/x86/acpica/madt.c
  stable/11/sys/x86/include/apicvar.h
  stable/11/sys/x86/x86/local_apic.c
  stable/11/sys/x86/xen/xen_apic.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/x86/acpica/madt.c
==============================================================================
--- stable/11/sys/x86/acpica/madt.c	Mon Oct  3 09:37:56 2016	(r306627)
+++ stable/11/sys/x86/acpica/madt.c	Mon Oct  3 09:39:46 2016	(r306628)
@@ -135,10 +135,11 @@ madt_setup_local(void)
 	const char *reason;
 	char *hw_vendor;
 	u_int p[4];
+	int user_x2apic;
+	bool bios_x2apic;
 
 	madt = pmap_mapbios(madt_physaddr, madt_length);
 	if ((cpu_feature2 & CPUID2_X2APIC) != 0) {
-		x2apic_mode = 1;
 		reason = NULL;
 
 		/*
@@ -150,21 +151,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,16 +181,33 @@ 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);
 			}
 		}
-		TUNABLE_INT_FETCH("hw.x2apic_enable", &x2apic_mode);
-		if (!x2apic_mode && reason != NULL && bootverbose)
+		bios_x2apic = lapic_is_x2apic();
+		if (reason != NULL && bios_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;
+		else if (bootverbose)
 			printf("x2APIC available but disabled %s\n", reason);
+		user_x2apic = x2apic_mode;
+		TUNABLE_INT_FETCH("hw.x2apic_enable", &user_x2apic);
+		if (user_x2apic != x2apic_mode) {
+			if (bios_x2apic && !user_x2apic)
+				printf("x2APIC disabled by tunable and "
+				    "enabled by BIOS; ignoring tunable.");
+			else
+				x2apic_mode = user_x2apic;
+		}
 	}
 
 	lapic_init(madt->Address);

Modified: stable/11/sys/x86/include/apicvar.h
==============================================================================
--- stable/11/sys/x86/include/apicvar.h	Mon Oct  3 09:37:56 2016	(r306627)
+++ stable/11/sys/x86/include/apicvar.h	Mon Oct  3 09:39:46 2016	(r306628)
@@ -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)
 {

Modified: stable/11/sys/x86/x86/local_apic.c
==============================================================================
--- stable/11/sys/x86/x86/local_apic.c	Mon Oct  3 09:37:56 2016	(r306627)
+++ stable/11/sys/x86/x86/local_apic.c	Mon Oct  3 09:39:46 2016	(r306628)
@@ -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,

Modified: stable/11/sys/x86/xen/xen_apic.c
==============================================================================
--- stable/11/sys/x86/xen/xen_apic.c	Mon Oct  3 09:37:56 2016	(r306627)
+++ stable/11/sys/x86/xen/xen_apic.c	Mon Oct  3 09:39:46 2016	(r306628)
@@ -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,


More information about the svn-src-all mailing list