[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