summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2006-05-01 22:07:00 +0000
committerjhb <jhb@FreeBSD.org>2006-05-01 22:07:00 +0000
commit00bb13261b47adc1a0e5064c6711bdf4e41739c6 (patch)
treea5a5b98ceebb1c0cb55bb29fb1a21eedcde521c5 /sys
parent517c01ed07a72ed13f0bb2fb42f28481a270baa1 (diff)
downloadFreeBSD-src-00bb13261b47adc1a0e5064c6711bdf4e41739c6.zip
FreeBSD-src-00bb13261b47adc1a0e5064c6711bdf4e41739c6.tar.gz
Add various constants for the PAT MSR and the PAT PTE and PDE flags.
Initialize the PAT MSR during boot to map PAT type 2 to Write-Combining (WC) instead of Uncached (UC-). MFC after: 1 month
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/mp_machdep.c3
-rw-r--r--sys/amd64/amd64/pmap.c45
-rw-r--r--sys/amd64/include/pmap.h3
-rw-r--r--sys/amd64/include/specialreg.h12
-rw-r--r--sys/i386/i386/mp_machdep.c3
-rw-r--r--sys/i386/i386/pmap.c45
-rw-r--r--sys/i386/include/pmap.h3
-rw-r--r--sys/i386/include/specialreg.h13
8 files changed, 127 insertions, 0 deletions
diff --git a/sys/amd64/amd64/mp_machdep.c b/sys/amd64/amd64/mp_machdep.c
index b2485c6..f7e9c72 100644
--- a/sys/amd64/amd64/mp_machdep.c
+++ b/sys/amd64/amd64/mp_machdep.c
@@ -514,6 +514,9 @@ init_secondary(void)
while (!aps_ready)
ia32_pause();
+ /* Initialize the PAT MSR. */
+ pmap_init_pat();
+
/* set up CPU registers and state */
cpu_setregs();
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index 238f0b4..8c8267a 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -551,6 +551,51 @@ pmap_bootstrap(firstaddr)
*CMAP1 = 0;
invltlb();
+
+ /* Initialize the PAT MSR. */
+ pmap_init_pat();
+}
+
+/*
+ * Setup the PAT MSR.
+ */
+void
+pmap_init_pat(void)
+{
+ uint64_t pat_msr;
+
+ /* Bail if this CPU doesn't implement PAT. */
+ if (!(cpu_feature & CPUID_PAT))
+ panic("no PAT??");
+
+#ifdef 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);
+#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)
+ */
+ pat_msr = rdmsr(MSR_PAT);
+ pat_msr &= ~PAT_MASK(2);
+ pat_msr |= PAT_VALUE(2, PAT_WRITE_COMBINING);
+#endif
+ wrmsr(MSR_PAT, pat_msr);
}
/*
diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h
index 0a774c7..bfecade 100644
--- a/sys/amd64/include/pmap.h
+++ b/sys/amd64/include/pmap.h
@@ -58,10 +58,12 @@
#define PG_A 0x020 /* A Accessed */
#define PG_M 0x040 /* D Dirty */
#define PG_PS 0x080 /* PS Page size (0=4k,1=4M) */
+#define PG_PTE_PAT 0x080 /* PAT PAT index */
#define PG_G 0x100 /* G Global */
#define PG_AVAIL1 0x200 /* / Available for system */
#define PG_AVAIL2 0x400 /* < programmers use */
#define PG_AVAIL3 0x800 /* \ */
+#define PG_PDE_PAT 0x1000 /* PAT PAT index */
#define PG_NX (1ul<<63) /* No-execute */
@@ -300,6 +302,7 @@ extern vm_offset_t virtual_end;
#define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list))
void pmap_bootstrap(vm_paddr_t *);
+void pmap_init_pat(void);
void pmap_kenter(vm_offset_t va, vm_paddr_t pa);
void *pmap_kenter_temporary(vm_paddr_t pa, int i);
vm_paddr_t pmap_kextract(vm_offset_t);
diff --git a/sys/amd64/include/specialreg.h b/sys/amd64/include/specialreg.h
index e78bc17..24db7da 100644
--- a/sys/amd64/include/specialreg.h
+++ b/sys/amd64/include/specialreg.h
@@ -230,6 +230,18 @@
#define APICBASE_ADDRESS 0xfffff000
/*
+ * PAT modes.
+ */
+#define PAT_UNCACHEABLE 0x00
+#define PAT_WRITE_COMBINING 0x01
+#define PAT_WRITE_THROUGH 0x04
+#define PAT_WRITE_PROTECTED 0x05
+#define PAT_WRITE_BACK 0x06
+#define PAT_UNCACHED 0x07
+#define PAT_VALUE(i, m) ((long)(m) << (8 * (i)))
+#define PAT_MASK(i) PAT_VALUE(i, 0xff)
+
+/*
* Constants related to MTRRs
*/
#define MTRR_N64K 8 /* numbers of fixed-size entries */
diff --git a/sys/i386/i386/mp_machdep.c b/sys/i386/i386/mp_machdep.c
index 5f468c0..665296f 100644
--- a/sys/i386/i386/mp_machdep.c
+++ b/sys/i386/i386/mp_machdep.c
@@ -563,6 +563,9 @@ init_secondary(void)
lidt(&r_idt);
#endif
+ /* Initialize the PAT MSR if present. */
+ pmap_init_pat();
+
/* set up CPU registers and state */
cpu_setregs();
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index d28bf52..1299791 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -419,11 +419,56 @@ pmap_bootstrap(firstaddr, loadaddr)
for (i = 0; i < NKPT; i++)
PTD[i] = 0;
+ /* Initialize the PAT MSR if present. */
+ pmap_init_pat();
+
/* Turn on PG_G on kernel page(s) */
pmap_set_pg();
}
/*
+ * Setup the PAT MSR.
+ */
+void
+pmap_init_pat(void)
+{
+ uint64_t pat_msr;
+
+ /* Bail if this CPU doesn't implement PAT. */
+ if (!(cpu_feature & CPUID_PAT))
+ return;
+
+#ifdef 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);
+#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)
+ */
+ pat_msr = rdmsr(MSR_PAT);
+ pat_msr &= ~PAT_MASK(2);
+ pat_msr |= PAT_VALUE(2, PAT_WRITE_COMBINING);
+#endif
+ wrmsr(MSR_PAT, pat_msr);
+}
+
+/*
* Set PG_G on kernel pages. Only the BSP calls this when SMP is turned on.
*/
void
diff --git a/sys/i386/include/pmap.h b/sys/i386/include/pmap.h
index b60d439..584bc43 100644
--- a/sys/i386/include/pmap.h
+++ b/sys/i386/include/pmap.h
@@ -57,10 +57,12 @@
#define PG_A 0x020 /* A Accessed */
#define PG_M 0x040 /* D Dirty */
#define PG_PS 0x080 /* PS Page size (0=4k,1=4M) */
+#define PG_PTE_PAT 0x080 /* PAT PAT index */
#define PG_G 0x100 /* G Global */
#define PG_AVAIL1 0x200 /* / Available for system */
#define PG_AVAIL2 0x400 /* < programmers use */
#define PG_AVAIL3 0x800 /* \ */
+#define PG_PDE_PAT 0x1000 /* PAT PAT index */
/* Our various interpretations of the above */
@@ -368,6 +370,7 @@ extern vm_offset_t virtual_end;
#define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list))
void pmap_bootstrap(vm_paddr_t, vm_paddr_t);
+void pmap_init_pat(void);
void pmap_kenter(vm_offset_t va, vm_paddr_t pa);
void *pmap_kenter_temporary(vm_paddr_t pa, int i);
void pmap_kremove(vm_offset_t);
diff --git a/sys/i386/include/specialreg.h b/sys/i386/include/specialreg.h
index 8ae1115..e189b22 100644
--- a/sys/i386/include/specialreg.h
+++ b/sys/i386/include/specialreg.h
@@ -185,6 +185,7 @@
#define MSR_MTRR64kBase 0x250
#define MSR_MTRR16kBase 0x258
#define MSR_MTRR4kBase 0x268
+#define MSR_PAT 0x277
#define MSR_MTRRdefType 0x2ff
#define MSR_MC0_CTL 0x400
#define MSR_MC0_STATUS 0x401
@@ -216,6 +217,18 @@
#define APICBASE_ADDRESS 0xfffff000
/*
+ * PAT modes.
+ */
+#define PAT_UNCACHEABLE 0x00
+#define PAT_WRITE_COMBINING 0x01
+#define PAT_WRITE_THROUGH 0x04
+#define PAT_WRITE_PROTECTED 0x05
+#define PAT_WRITE_BACK 0x06
+#define PAT_UNCACHED 0x07
+#define PAT_VALUE(i, m) ((long long)(m) << (8 * (i)))
+#define PAT_MASK(i) PAT_VALUE(i, 0xff)
+
+/*
* Constants related to MTRRs
*/
#define MTRR_N64K 8 /* numbers of fixed-size entries */
OpenPOWER on IntegriCloud