diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-12-17 16:35:26 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-12-17 16:35:26 +0100 |
commit | ea30cf94a5f247dd00c32c01325b8a47ad5f105a (patch) | |
tree | f9fbad860ac9499b11ad56778069b23ce826ca96 /sys/src/9/pc | |
parent | d48a0894865e810f46e1ef2f07476c4f3101698a (diff) |
pat write combinding support for 386 kernel, honor cpuid bits
Diffstat (limited to 'sys/src/9/pc')
-rw-r--r-- | sys/src/9/pc/dat.h | 1 | ||||
-rw-r--r-- | sys/src/9/pc/mmu.c | 45 |
2 files changed, 45 insertions, 1 deletions
diff --git a/sys/src/9/pc/dat.h b/sys/src/9/pc/dat.h index 581bdf73e..f0157652d 100644 --- a/sys/src/9/pc/dat.h +++ b/sys/src/9/pc/dat.h @@ -316,6 +316,7 @@ enum { Mtrr = 1<<12, /* memory-type range regs. */ Pge = 1<<13, /* page global extension */ Mca = 1<<14, /* machine-check architecture */ + Pat = 1<<16, /* page attribute table */ Pse2 = 1<<17, /* more page size extensions */ Clflush = 1<<19, Acpif = 1<<22, /* therm control msr */ diff --git a/sys/src/9/pc/mmu.c b/sys/src/9/pc/mmu.c index d97c9a5b5..3c79f90a3 100644 --- a/sys/src/9/pc/mmu.c +++ b/sys/src/9/pc/mmu.c @@ -66,11 +66,17 @@ static void memglobal(void); #define VPTX(va) (((ulong)(va))>>12) #define vpd (vpt+VPTX(VPT)) +enum { + /* PAT entry used for write combining */ + PATWC = 7, +}; + void mmuinit(void) { ulong x, *p; ushort ptr[3]; + vlong v; if(0) print("vpt=%#.8ux vpd=%#p kmap=%#.8ux\n", VPT, vpd, KMAP); @@ -119,6 +125,14 @@ mmuinit(void) taskswitch(PADDR(m->pdb), (ulong)m + BY2PG); ltr(TSSSEL); + + /* IA32_PAT write combining */ + if((MACHP(0)->cpuiddx & Pat) != 0 + && rdmsr(0x277, &v) != -1){ + v &= ~(255LL<<(PATWC*8)); + v |= 1LL<<(PATWC*8); /* WC */ + wrmsr(0x277, v); + } } /* @@ -1065,7 +1079,36 @@ cankaddr(ulong pa) return -KZERO - pa; } +/* + * mark pages as write combining (used for framebuffer) + */ void -patwc(void *, int) +patwc(void *a, int n) { + ulong *pte, mask, attr, va; + vlong v; + int z; + + /* check if pat is usable */ + if((MACHP(0)->cpuiddx & Pat) == 0 + || rdmsr(0x277, &v) == -1 + || ((v >> PATWC*8) & 7) != 1) + return; + + /* set the bits for all pages in range */ + for(va = (ulong)a; n > 0; n -= z, va += z){ + pte = mmuwalk(m->pdb, va, 1, 0); + if(pte && (*pte & (PTEVALID|PTESIZE)) == (PTEVALID|PTESIZE)){ + z = 4*MB - (va & (4*MB-1)); + mask = 3<<3 | 1<<12; + } else { + pte = mmuwalk(m->pdb, va, 2, 0); + if(pte == 0 || (*pte & PTEVALID) == 0) + panic("patwc: va=%#p", va); + z = BY2PG - (va & (BY2PG-1)); + mask = 3<<3 | 1<<7; + } + attr = (((PATWC&3)<<3) | ((PATWC&4)<<5) | ((PATWC&4)<<10)); + *pte = (*pte & ~mask) | (attr & mask); + } } |