[Call for Tests] PAT issue on Apple hardware

Jung-uk Kim jkim at FreeBSD.org
Tue Nov 16 01:37:10 UTC 2010


Often times I hear complaints like "my Mac hangs after upgrading to 
8.1" or "snapshot CD hangs on my brand new Mac".  I know some of 
these complaints started happening when we switched to new PAT 
layout.  It is so puzzling because it never happened on non-Apple 
hardware, AFAIK.  I really like to fix this problem but I cannot 
afford a Mac. :-P

If you are one of those lucky people, please test the attached patch 
and report your hardware model and any improvement or regression.

Also, I added a new tunable "vm.pmap.pat_works" so that you can turn 
it off from loader (i.e., "set vm.pmap.pat_works=0") and restore old 
behaviour without recompiling a new kernel.

Thanks in advance!

Jung-uk Kim
-------------- next part --------------
Index: sys/amd64/amd64/pmap.c
===================================================================
--- sys/amd64/amd64/pmap.c	(revision 215352)
+++ sys/amd64/amd64/pmap.c	(working copy)
@@ -180,10 +180,13 @@ static vm_paddr_t dmaplimit;
 vm_offset_t kernel_vm_end = VM_MIN_KERNEL_ADDRESS;
 pt_entry_t pg_nx;
 
-static int pat_works = 0;		/* Is page attribute table sane? */
-
 SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters");
 
+static int pat_works = 1;
+TUNABLE_INT("vm.pmap.pat_works", &pat_works);
+SYSCTL_INT(_vm_pmap, OID_AUTO, pat_works, CTLFLAG_RDTUN, &pat_works, 1,
+    "Is page attribute table fully functional?");
+
 static int pg_ps_enabled = 1;
 SYSCTL_INT(_vm_pmap, OID_AUTO, pg_ps_enabled, CTLFLAG_RDTUN, &pg_ps_enabled, 0,
     "Are large page mappings enabled?");
@@ -609,35 +612,15 @@ void
 pmap_init_pat(void)
 {
 	uint64_t pat_msr;
-	char *sysenv;
-	static int pat_tested = 0;
 
 	/* Bail if this CPU doesn't implement PAT. */
 	if (!(cpu_feature & CPUID_PAT))
 		panic("no PAT??");
 
-	/*
-	 * Some Apple Macs based on nVidia chipsets cannot enter ACPI mode
-	 * via SMI# when we use upper 4 PAT entries for unknown reason.
-	 */
-	if (!pat_tested) {
-		pat_works = 1;
-		sysenv = getenv("smbios.system.product");
-		if (sysenv != NULL) {
-			if (strncmp(sysenv, "MacBook5,1", 10) == 0 ||
-			    strncmp(sysenv, "MacBookPro5,5", 13) == 0 ||
-			    strncmp(sysenv, "Macmini3,1", 10) == 0 ||
-			    strncmp(sysenv, "iMac9,1", 7) == 0)
-				pat_works = 0;
-			freeenv(sysenv);
-		}
-		pat_tested = 1;
-	}
-
 	/* Initialize default PAT entries. */
 	pat_msr = PAT_VALUE(0, PAT_WRITE_BACK) |
 	    PAT_VALUE(1, PAT_WRITE_THROUGH) |
-	    PAT_VALUE(2, PAT_UNCACHED) |
+	    PAT_VALUE(2, PAT_WRITE_COMBINING) |
 	    PAT_VALUE(3, PAT_UNCACHEABLE) |
 	    PAT_VALUE(4, PAT_WRITE_BACK) |
 	    PAT_VALUE(5, PAT_WRITE_THROUGH) |
@@ -646,19 +629,10 @@ pmap_init_pat(void)
 
 	if (pat_works) {
 		/*
-		 * Leave the indices 0-3 at the default of WB, WT, UC-, and UC.
-		 * Program 4 and 5 as WP and WC.
-		 * Leave 6 and 7 as UC- and UC.
+		 * Just replace PAT Index 5 with WP instead of WT.
 		 */
-		pat_msr &= ~(PAT_MASK(4) | PAT_MASK(5));
-		pat_msr |= PAT_VALUE(4, PAT_WRITE_PROTECTED) |
-		    PAT_VALUE(5, PAT_WRITE_COMBINING);
-	} else {
-		/*
-		 * Just replace PAT Index 2 with WC instead of UC-.
-		 */
-		pat_msr &= ~PAT_MASK(2);
-		pat_msr |= PAT_VALUE(2, PAT_WRITE_COMBINING);
+		pat_msr &= ~PAT_MASK(5);
+		pat_msr |= PAT_VALUE(5, PAT_WRITE_PROTECTED);
 	}
 	wrmsr(MSR_PAT, pat_msr);
 }
@@ -829,13 +803,13 @@ pmap_cache_bits(int mode, boolean_t is_pde)
 			pat_index = 0;
 			break;
 		case PAT_UNCACHED:
-			pat_index = 2;
+			pat_index = 6;
 			break;
 		case PAT_WRITE_COMBINING:
-			pat_index = 5;
+			pat_index = 2;
 			break;
 		case PAT_WRITE_PROTECTED:
-			pat_index = 4;
+			pat_index = 5;
 			break;
 		default:
 			panic("Unknown caching mode %d\n", mode);
Index: sys/i386/i386/pmap.c
===================================================================
--- sys/i386/i386/pmap.c	(revision 215352)
+++ sys/i386/i386/pmap.c	(working copy)
@@ -217,10 +217,13 @@ pt_entry_t pg_nx;
 static uma_zone_t pdptzone;
 #endif
 
-static int pat_works = 0;		/* Is page attribute table sane? */
-
 SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters");
 
+static int pat_works = 1;
+TUNABLE_INT("vm.pmap.pat_works", &pat_works);
+SYSCTL_INT(_vm_pmap, OID_AUTO, pat_works, CTLFLAG_RDTUN, &pat_works, 1,
+    "Is page attribute table fully functional?");
+
 static int pg_ps_enabled = 1;
 SYSCTL_INT(_vm_pmap, OID_AUTO, pg_ps_enabled, CTLFLAG_RDTUN, &pg_ps_enabled, 0,
     "Are large page mappings enabled?");
@@ -491,12 +494,12 @@ void
 pmap_init_pat(void)
 {
 	uint64_t pat_msr;
-	char *sysenv;
-	static int pat_tested = 0;
 
 	/* Bail if this CPU doesn't implement PAT. */
-	if (!(cpu_feature & CPUID_PAT))
+	if (!(cpu_feature & CPUID_PAT)) {
+		pat_works = 0;
 		return;
+	}
 
 	/*
 	 * Due to some Intel errata, we can only safely use the lower 4
@@ -508,32 +511,15 @@ pmap_init_pat(void)
 	 *
 	 *   Intel Pentium IV  Processor Specification Update
 	 * Errata N46 (PAT Index MSB May Be Calculated Incorrectly)
-	 *
-	 * Some Apple Macs based on nVidia chipsets cannot enter ACPI mode
-	 * via SMI# when we use upper 4 PAT entries for unknown reason.
 	 */
-	if (!pat_tested) {
-		if (cpu_vendor_id != CPU_VENDOR_INTEL ||
-		    (CPUID_TO_FAMILY(cpu_id) == 6 &&
-		    CPUID_TO_MODEL(cpu_id) >= 0xe)) {
-			pat_works = 1;
-			sysenv = getenv("smbios.system.product");
-			if (sysenv != NULL) {
-				if (strncmp(sysenv, "MacBook5,1", 10) == 0 ||
-				    strncmp(sysenv, "MacBookPro5,5", 13) == 0 ||
-				    strncmp(sysenv, "Macmini3,1", 10) == 0 ||
-				    strncmp(sysenv, "iMac9,1", 7) == 0)
-					pat_works = 0;
-				freeenv(sysenv);
-			}
-		}
-		pat_tested = 1;
-	}
+	if (cpu_vendor_id == CPU_VENDOR_INTEL &&
+	    !(CPUID_TO_FAMILY(cpu_id) == 6 && CPUID_TO_MODEL(cpu_id) >= 0xe))
+		pat_works = 0;
 
 	/* Initialize default PAT entries. */
 	pat_msr = PAT_VALUE(0, PAT_WRITE_BACK) |
 	    PAT_VALUE(1, PAT_WRITE_THROUGH) |
-	    PAT_VALUE(2, PAT_UNCACHED) |
+	    PAT_VALUE(2, PAT_WRITE_COMBINING) |
 	    PAT_VALUE(3, PAT_UNCACHEABLE) |
 	    PAT_VALUE(4, PAT_WRITE_BACK) |
 	    PAT_VALUE(5, PAT_WRITE_THROUGH) |
@@ -542,19 +528,10 @@ pmap_init_pat(void)
 
 	if (pat_works) {
 		/*
-		 * Leave the indices 0-3 at the default of WB, WT, UC-, and UC.
-		 * Program 4 and 5 as WP and WC.
-		 * Leave 6 and 7 as UC- and UC.
+		 * Just replace PAT Index 5 with WP instead of WT.
 		 */
-		pat_msr &= ~(PAT_MASK(4) | PAT_MASK(5));
-		pat_msr |= PAT_VALUE(4, PAT_WRITE_PROTECTED) |
-		    PAT_VALUE(5, PAT_WRITE_COMBINING);
-	} else {
-		/*
-		 * Just replace PAT Index 2 with WC instead of UC-.
-		 */
-		pat_msr &= ~PAT_MASK(2);
-		pat_msr |= PAT_VALUE(2, PAT_WRITE_COMBINING);
+		pat_msr &= ~PAT_MASK(5);
+		pat_msr |= PAT_VALUE(5, PAT_WRITE_PROTECTED);
 	}
 	wrmsr(MSR_PAT, pat_msr);
 }
@@ -825,13 +802,13 @@ pmap_cache_bits(int mode, boolean_t is_pde)
 			pat_index = 0;
 			break;
 		case PAT_UNCACHED:
-			pat_index = 2;
+			pat_index = 6;
 			break;
 		case PAT_WRITE_COMBINING:
-			pat_index = 5;
+			pat_index = 2;
 			break;
 		case PAT_WRITE_PROTECTED:
-			pat_index = 4;
+			pat_index = 5;
 			break;
 		default:
 			panic("Unknown caching mode %d\n", mode);


More information about the freebsd-current mailing list