shithub: riscv

Download patch

ref: ea30cf94a5f247dd00c32c01325b8a47ad5f105a
parent: d48a0894865e810f46e1ef2f07476c4f3101698a
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Dec 17 11:35:26 EST 2016

pat write combinding support for 386 kernel, honor cpuid bits

--- a/sys/src/9/pc/dat.h
+++ b/sys/src/9/pc/dat.h
@@ -316,6 +316,7 @@
 	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 */
--- a/sys/src/9/pc/mmu.c
+++ b/sys/src/9/pc/mmu.c
@@ -66,11 +66,17 @@
 #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 @@
 
 	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 @@
 	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);
+	}
 }
--- a/sys/src/9/pc64/dat.h
+++ b/sys/src/9/pc64/dat.h
@@ -279,6 +279,7 @@
 	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 */
--- a/sys/src/9/pc64/mmu.c
+++ b/sys/src/9/pc64/mmu.c
@@ -135,10 +135,12 @@
 	wrmsr(0xc0000084, 0x200);
 
 	/* IA32_PAT write combining */
-	rdmsr(0x277, &v);
-	v &= ~(255LL<<(PATWC*8));
-	v |= 1LL<<(PATWC*8);	/* WC */
-	wrmsr(0x277, v);
+	if((MACHP(0)->cpuiddx & Pat) != 0
+	&& rdmsr(0x277, &v) != -1){
+		v &= ~(255LL<<(PATWC*8));
+		v |= 1LL<<(PATWC*8);	/* WC */
+		wrmsr(0x277, v);
+	}
 }
 
 /*
@@ -549,13 +551,20 @@
  * mark pages as write combining (used for framebuffer)
  */
 void
-patwc(void *v, int n)
+patwc(void *a, int n)
 {
 	uintptr *pte, mask, attr, va;
 	int z, l;
+	vlong v;
 
+	/* 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 = (uintptr)v; n > 0; n -= z, va += z){
+	for(va = (uintptr)a; n > 0; n -= z, va += z){
 		l = 0;
 		pte = mmuwalk(m->pml4, va, l, 0);
 		if(pte == 0)