From 00bb13261b47adc1a0e5064c6711bdf4e41739c6 Mon Sep 17 00:00:00 2001 From: jhb Date: Mon, 1 May 2006 22:07:00 +0000 Subject: 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 --- sys/amd64/amd64/mp_machdep.c | 3 +++ sys/amd64/amd64/pmap.c | 45 ++++++++++++++++++++++++++++++++++++++++++ sys/amd64/include/pmap.h | 3 +++ sys/amd64/include/specialreg.h | 12 +++++++++++ 4 files changed, 63 insertions(+) (limited to 'sys/amd64') 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 */ -- cgit v1.1