aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJung-uk Kim <jkim@FreeBSD.org>2009-09-02 16:02:48 +0000
committerJung-uk Kim <jkim@FreeBSD.org>2009-09-02 16:02:48 +0000
commitc9e881790201d01428ad2d6e5ae2d0659bfc778b (patch)
treeead83bc5660385a659d44a0f7ee7dedbdf36d456 /sys
parentf038eb6d37facddd0b3af7d09419e240667e2fc5 (diff)
Notes
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/pmap.c115
-rw-r--r--sys/i386/i386/pmap.c63
2 files changed, 133 insertions, 45 deletions
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 4e35ef4aedb5b..368513b687e36 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -178,6 +178,8 @@ 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 pg_ps_enabled = 1;
@@ -590,20 +592,56 @@ 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??");
/*
- * 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-.
+ * Some Apple Macs based on nVidia chipsets cannot enter ACPI mode
+ * via SMI# when we use upper 4 PAT entries for unknown reason.
*/
- pat_msr = rdmsr(MSR_PAT);
- pat_msr &= ~(PAT_MASK(4) | PAT_MASK(5));
- pat_msr |= PAT_VALUE(4, PAT_WRITE_PROTECTED) |
- PAT_VALUE(5, PAT_WRITE_COMBINING);
+ 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)
+ 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(3, PAT_UNCACHEABLE) |
+ PAT_VALUE(4, PAT_WRITE_BACK) |
+ PAT_VALUE(5, PAT_WRITE_THROUGH) |
+ PAT_VALUE(6, PAT_UNCACHED) |
+ PAT_VALUE(7, PAT_UNCACHEABLE);
+
+ 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-.
+ */
+ 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);
+ }
wrmsr(MSR_PAT, pat_msr);
}
@@ -754,27 +792,48 @@ pmap_cache_bits(int mode, boolean_t is_pde)
pat_flag = is_pde ? PG_PDE_PAT : PG_PTE_PAT;
/* Map the caching mode to a PAT index. */
- switch (mode) {
- case PAT_UNCACHEABLE:
- pat_index = 3;
- break;
- case PAT_WRITE_THROUGH:
- pat_index = 1;
- break;
- case PAT_WRITE_BACK:
- pat_index = 0;
- break;
- case PAT_UNCACHED:
- pat_index = 2;
- break;
- case PAT_WRITE_COMBINING:
- pat_index = 5;
- break;
- case PAT_WRITE_PROTECTED:
- pat_index = 4;
- break;
- default:
- panic("Unknown caching mode %d\n", mode);
+ if (pat_works) {
+ switch (mode) {
+ case PAT_UNCACHEABLE:
+ pat_index = 3;
+ break;
+ case PAT_WRITE_THROUGH:
+ pat_index = 1;
+ break;
+ case PAT_WRITE_BACK:
+ pat_index = 0;
+ break;
+ case PAT_UNCACHED:
+ pat_index = 2;
+ break;
+ case PAT_WRITE_COMBINING:
+ pat_index = 5;
+ break;
+ case PAT_WRITE_PROTECTED:
+ pat_index = 4;
+ break;
+ default:
+ panic("Unknown caching mode %d\n", mode);
+ }
+ } else {
+ switch (mode) {
+ case PAT_UNCACHED:
+ case PAT_UNCACHEABLE:
+ case PAT_WRITE_PROTECTED:
+ pat_index = 3;
+ break;
+ case PAT_WRITE_THROUGH:
+ pat_index = 1;
+ break;
+ case PAT_WRITE_BACK:
+ pat_index = 0;
+ break;
+ case PAT_WRITE_COMBINING:
+ pat_index = 2;
+ break;
+ default:
+ panic("Unknown caching mode %d\n", mode);
+ }
}
/* Map the 3-bit index value into the PAT, PCD, and PWT bits. */
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index 548dbdb2ac6f8..1648126233e51 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -212,7 +212,7 @@ pt_entry_t pg_nx;
static uma_zone_t pdptzone;
#endif
-static int pat_works; /* Is page attribute table sane? */
+static int pat_works = 0; /* Is page attribute table sane? */
SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters");
@@ -478,40 +478,69 @@ 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))
return;
- if (cpu_vendor_id != CPU_VENDOR_INTEL ||
- (I386_CPU_FAMILY(cpu_id) == 6 && I386_CPU_MODEL(cpu_id) >= 0xe)) {
+ /*
+ * Due to some Intel errata, we can only safely use the lower 4
+ * PAT entries.
+ *
+ * Intel Pentium III Processor Specification Update
+ * Errata E.27 (Upper Four PAT Entries Not Usable With Mode B
+ * or Mode C Paging)
+ *
+ * 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 ||
+ (I386_CPU_FAMILY(cpu_id) == 6 &&
+ I386_CPU_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)
+ 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(3, PAT_UNCACHEABLE) |
+ PAT_VALUE(4, PAT_WRITE_BACK) |
+ PAT_VALUE(5, PAT_WRITE_THROUGH) |
+ PAT_VALUE(6, PAT_UNCACHED) |
+ PAT_VALUE(7, PAT_UNCACHEABLE);
+
+ 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-.
*/
- pat_msr = rdmsr(MSR_PAT);
pat_msr &= ~(PAT_MASK(4) | PAT_MASK(5));
pat_msr |= PAT_VALUE(4, PAT_WRITE_PROTECTED) |
PAT_VALUE(5, PAT_WRITE_COMBINING);
- pat_works = 1;
} else {
/*
- * Due to some Intel errata, we can only safely use the lower 4
- * PAT entries. Thus, just replace PAT Index 2 with WC instead
- * of UC-.
- *
- * Intel Pentium III Processor Specification Update
- * Errata E.27 (Upper Four PAT Entries Not Usable With Mode B
- * or Mode C Paging)
- *
- * Intel Pentium IV Processor Specification Update
- * Errata N46 (PAT Index MSB May Be Calculated Incorrectly)
+ * Just replace PAT Index 2 with WC instead of UC-.
*/
- pat_msr = rdmsr(MSR_PAT);
pat_msr &= ~PAT_MASK(2);
pat_msr |= PAT_VALUE(2, PAT_WRITE_COMBINING);
- pat_works = 0;
}
wrmsr(MSR_PAT, pat_msr);
}