Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 21 Aug 2015 15:13:26 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r286994 - head/sys/x86/acpica
Message-ID:  <201508211513.t7LFDQri028106@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Fri Aug 21 15:13:25 2015
New Revision: 286994
URL: https://svnweb.freebsd.org/changeset/base/286994

Log:
  Automatically disable x2APIC mode on SandyBridge Lenovo machines.  I
  believe that the bug only affects mobile CPUs, at least I did not see
  other reports, but it is impossible to detect it in madt_setup_local().
  
  While there, reduce duplication in the information strings printed
  when x2APIC is auto-disabled, and do not print the line when user
  manually override the setting.
  
  Tested and reviewed by:	  royger (previous version)
  Sponsored by:	The FreeBSD Foundation

Modified:
  head/sys/x86/acpica/madt.c

Modified: head/sys/x86/acpica/madt.c
==============================================================================
--- head/sys/x86/acpica/madt.c	Fri Aug 21 14:28:14 2015	(r286993)
+++ head/sys/x86/acpica/madt.c	Fri Aug 21 15:13:25 2015	(r286994)
@@ -132,20 +132,27 @@ madt_setup_local(void)
 {
 	ACPI_TABLE_DMAR *dmartbl;
 	vm_paddr_t dmartbl_physaddr;
+	const char *reason;
+	char *hw_vendor;
 	u_int p[4];
 
 	madt = pmap_mapbios(madt_physaddr, madt_length);
 	if ((cpu_feature2 & CPUID2_X2APIC) != 0) {
 		x2apic_mode = 1;
+		reason = NULL;
+
+		/*
+		 * Automatically detect several configurations where
+		 * x2APIC mode is known to cause troubles.  User can
+		 * override the setting with hw.x2apic_enable tunable.
+		 */
 		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) {
 				x2apic_mode = 0;
-				if (bootverbose)
-					printf(
-		"x2APIC available but disabled by DMAR table\n");
+				reason = "by DMAR table";
 			}
 			acpi_unmap_table(dmartbl);
 		}
@@ -154,14 +161,34 @@ madt_setup_local(void)
 			if ((p[0] & VMW_VCPUINFO_VCPU_RESERVED) != 0 ||
 			    (p[0] & VMW_VCPUINFO_LEGACY_X2APIC) == 0) {
 				x2apic_mode = 0;
-				if (bootverbose)
-					printf(
-       "x2APIC available but disabled inside VMWare without intr redirection\n");
+		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) {
+			hw_vendor = kern_getenv("smbios.planar.maker");
+			/*
+			 * It seems that some Lenovo 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 Lenovo
+			 * SandyBridge machines.
+			 */
+			if (hw_vendor != NULL &&
+			    !strcmp(hw_vendor, "LENOVO") &&
+			    CPUID_TO_FAMILY(cpu_id) == 0x6 &&
+			    CPUID_TO_MODEL(cpu_id) == 0x2a) {
+				x2apic_mode = 0;
+		reason = "for a suspected Lenovo SandyBridge BIOS bug";
+			}
+			freeenv(hw_vendor);
 		}
 		TUNABLE_INT_FETCH("hw.x2apic_enable", &x2apic_mode);
+		if (!x2apic_mode && reason != NULL && bootverbose)
+			printf("x2APIC available but disabled %s\n", reason);
 	}
 
 	lapic_init(madt->Address);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201508211513.t7LFDQri028106>