This sets up PAT so we can have WB, WC, WT, and UC memory types via the __PTE flags. The PCD and PWT bits don't necessarily disable caching or set write-through anymore; they are indexes into the PAT table. (This was always happening btw, since anything we run on has PAT support).
Signed-off-by: Barret Rhoden <[email protected]> --- kern/arch/x86/cpuinfo.c | 2 ++ kern/arch/x86/pmap.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/kern/arch/x86/cpuinfo.c b/kern/arch/x86/cpuinfo.c index 1fed0725b54a..b857ee28b633 100644 --- a/kern/arch/x86/cpuinfo.c +++ b/kern/arch/x86/cpuinfo.c @@ -82,6 +82,8 @@ void print_cpuinfo(void) panic("MSRs not supported!"); if (!(edx & 0x00001000)) panic("MTRRs not supported!"); + if (!(edx & (1 << 16))) + panic("PAT not supported!"); if (!(edx & 0x00002000)) panic("Global Pages not supported!"); if (!(edx & 0x00000200)) diff --git a/kern/arch/x86/pmap.c b/kern/arch/x86/pmap.c index 8ca6fb4cf80b..7d59701533b5 100644 --- a/kern/arch/x86/pmap.c +++ b/kern/arch/x86/pmap.c @@ -40,6 +40,49 @@ bool enable_pse(void) return 0; } +#define PAT_UC 0x00 +#define PAT_WC 0x01 +#define PAT_WT 0x04 +#define PAT_WP 0x05 +#define PAT_WB 0x06 +#define PAT_UCm 0x07 + +static inline uint64_t mk_pat(int pat_idx, int type) +{ + return (uint64_t)type << (8 * pat_idx); +} + +static void pat_init(void) +{ + uint64_t pat = 0; + + /* Default PAT at boot: + * 0: WB, 1: WT, 2: UC-, 3: UC, 4: WB, 5: WT, 6: UC-, 7: UC + * + * We won't use PATs 4-7, but we'll at least enforce that they are set up + * the way we think they are. I'd like to avoid using the PAT flag, since + * that is also the PTE_PS (jumbo) flag. That means we can't use __PTE_PAT + * on jumbo pages, and we'd need to be careful whenever using any unorthodox + * types. We're better off just not using it. + * + * We set PAT 2 to WC. People should use PTE_WRITECOMB to choose it. I + * picked 2 since we don't need UC-. The UC- type is UC with the ability to + * override to WC via MTRR. I'm hoping to not muck with MTRRs, so we can + * just use this PAT type whenever we want WC. + * + * No one should be accessing __PTE_{PAT,PCD,PWT} directly, and everyone + * should use things like PTE_NOCACHE. */ + pat |= mk_pat(0, PAT_WB); /* | | */ + pat |= mk_pat(1, PAT_WT); /* | | __PTE_PWT */ + pat |= mk_pat(2, PAT_WC); /* | __PTE_PCD | */ + pat |= mk_pat(3, PAT_UC); /* | __PTE_PCD | __PTE_PWT */ + pat |= mk_pat(4, PAT_WB); /* __PTE_PAT | | */ + pat |= mk_pat(5, PAT_WT); /* __PTE_PAT | | __PTE_PWT */ + pat |= mk_pat(6, PAT_UCm); /* __PTE_PAT | __PTE_PCD | */ + pat |= mk_pat(7, PAT_UC); /* __PTE_PAT | __PTE_PCD | __PTE_PWT */ + write_msr(MSR_IA32_CR_PAT, pat); +} + // could consider having an API to allow these to dynamically change // MTRRs are for physical, static ranges. PAT are linear, more granular, and // more dynamic @@ -87,6 +130,7 @@ void setup_default_mtrrs(barrier_t* smp_barrier) // keeps default type to WB (06), turns MTRRs on, and turns off fixed ranges write_msr(IA32_MTRR_DEF_TYPE, 0x00000806); #endif + pat_init(); // reflush caches and TLB cache_flush(); tlb_flush_global(); -- 2.7.0.rc3.207.g0ac5344 -- You received this message because you are subscribed to the Google Groups "Akaros" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. For more options, visit https://groups.google.com/d/optout.
