diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h index 69c4fc01c..14c30ef21 100644 --- a/sys/src/9/pc/fns.h +++ b/sys/src/9/pc/fns.h @@ -123,6 +123,7 @@ void outss(int, void*, int); void outl(int, ulong); void outsl(int, void*, int); ulong paddr(void*); +void patwc(void*, int); ulong pcibarsize(Pcidev*, int); void pcibussize(Pcidev*, ulong*, ulong*); int pcicfgr8(Pcidev*, int); diff --git a/sys/src/9/pc/mmu.c b/sys/src/9/pc/mmu.c index b48155084..d97c9a5b5 100644 --- a/sys/src/9/pc/mmu.c +++ b/sys/src/9/pc/mmu.c @@ -1065,3 +1065,7 @@ cankaddr(ulong pa) return -KZERO - pa; } +void +patwc(void *, int) +{ +} diff --git a/sys/src/9/pc/screen.c b/sys/src/9/pc/screen.c index c74d2da71..69018c4fe 100644 --- a/sys/src/9/pc/screen.c +++ b/sys/src/9/pc/screen.c @@ -492,6 +492,9 @@ vgalinearaddr0(VGAscr *scr, ulong paddr, int size) scr->vaddr = vmap(npaddr, nsize); if(scr->vaddr == 0) return "cannot allocate vga frame buffer"; + + patwc(scr->vaddr, nsize); + scr->vaddr = (char*)scr->vaddr+x; scr->paddr = paddr; scr->apsize = nsize; diff --git a/sys/src/9/pc64/fns.h b/sys/src/9/pc64/fns.h index 4b55e7399..41e3380ec 100644 --- a/sys/src/9/pc64/fns.h +++ b/sys/src/9/pc64/fns.h @@ -117,6 +117,7 @@ void outss(int, void*, int); void outl(int, ulong); void outsl(int, void*, int); uintptr paddr(void*); +void patwc(void*, int); ulong pcibarsize(Pcidev*, int); void pcibussize(Pcidev*, ulong*, ulong*); int pcicfgr8(Pcidev*, int); diff --git a/sys/src/9/pc64/mmu.c b/sys/src/9/pc64/mmu.c index 18b8878f7..ffd077e31 100644 --- a/sys/src/9/pc64/mmu.c +++ b/sys/src/9/pc64/mmu.c @@ -31,13 +31,16 @@ static struct { ulong nfree; } mmupool; -/* level */ enum { + /* level */ PML4E = 2, PDPE = 1, PDE = 0, MAPBITS = 8*sizeof(m->mmumap[0]), + + /* PAT entry used for write combining */ + PATWC = 7, }; static void @@ -130,6 +133,12 @@ mmuinit(void) /* SYSCALL flags mask */ wrmsr(0xc0000084, 0x200); + + /* IA32_PAT write combining */ + rdmsr(0x277, &v); + v &= ~(255LL<<(PATWC*8)); + v |= 1LL<<(PATWC*8); /* WC */ + wrmsr(0x277, v); } /* @@ -535,3 +544,28 @@ vunmap(void *v, int) { paddr(v); /* will panic on error */ } + +/* + * mark pages as write combining (used for framebuffer) + */ +void +patwc(void *v, int n) +{ + uintptr *pte, mask, attr, va; + int z, l; + + /* set the bits for all pages in range */ + for(va = (uintptr)v; n > 0; n -= z, va += z){ + l = 0; + pte = mmuwalk(m->pml4, va, l, 0); + if(pte == 0) + pte = mmuwalk(m->pml4, va, ++l, 0); + if(pte == 0 || (*pte & PTEVALID) == 0) + panic("patwc: va=%#p", va); + z = PGLSZ(l); + z -= va & (z-1); + mask = l == 0 ? 3<<3 | 1<<7 : 3<<3 | 1<<12; + attr = (((PATWC&3)<<3) | ((PATWC&4)<<5) | ((PATWC&4)<<10)); + *pte = (*pte & ~mask) | (attr & mask); + } +}