summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/src/9/pc/fns.h1
-rw-r--r--sys/src/9/pc/mmu.c4
-rw-r--r--sys/src/9/pc/screen.c3
-rw-r--r--sys/src/9/pc64/fns.h1
-rw-r--r--sys/src/9/pc64/mmu.c36
5 files changed, 44 insertions, 1 deletions
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);
+ }
+}