shithub: riscv

Download patch

ref: 99696c414ac1011a59aa4aeb03976c45b1d70856
parent: 4ca5e1b3a33d49d0904b39477149517665a78d8a
author: cinap_lenrek <[email protected]>
date: Sat Dec 5 11:57:12 EST 2020

pc, pc64: exclude memory regions with unusual MTRR cache attributes

Use the MTRR registers to exclude memory ranges that
do not have the expected cache attributes:

RAM -> writeback
UMB -> uncached
UPA -> uncached

--- a/sys/src/9/pc/fns.h
+++ b/sys/src/9/pc/fns.h
@@ -101,6 +101,7 @@
 void	mmuinit(void);
 ulong*	mmuwalk(ulong*, ulong, int, int);
 char*	mtrr(uvlong, uvlong, char *);
+char*	mtrrattr(uvlong, uvlong *);
 void	mtrrclock(void);
 int	mtrrprint(char *, long);
 void	mtrrsync(void);
--- a/sys/src/9/pc/memory.c
+++ b/sys/src/9/pc/memory.c
@@ -320,6 +320,27 @@
 	}
 }
 
+static void
+mtrrexclude(int type, char *expect)
+{
+	uvlong base, top, next, pa;
+	char *attr;
+
+	for(base = memmapnext(-1, type); base != -1; base = memmapnext(base, type)){
+		top = base + memmapsize(base, 0);
+		for(pa = base; pa < top; pa = next){
+			next = top;
+			attr = mtrrattr(pa, &next);
+			if(attr != nil && strcmp(attr, expect) != 0){
+				if(next > top)
+					next = top;
+				memmapadd(pa, next - pa, MemReserved);
+			}
+			base = pa;
+		}
+	}
+}
+
 static int
 e820scan(void)
 {
@@ -362,6 +383,9 @@
 		}
 	}
 
+	/* RAM needs to be writeback */
+	mtrrexclude(MemRAM, "wb");
+
 	for(base = memmapnext(-1, MemRAM); base != -1; base = memmapnext(base, MemRAM)){
 		size = memmapsize(base, BY2PG) & ~(BY2PG-1);
 		if(size != 0)
@@ -376,6 +400,7 @@
 {
 	ulong save, pat, seed, *v, *k0;
 	int i, n, w;
+	char *attr;
 
 	pa += chunk-1;
 	pa &= ~(chunk-1);
@@ -389,6 +414,10 @@
 
 	pat = 0x12345678UL;
 	for(; pa < top; pa += chunk){
+		attr = mtrrattr(pa, nil);
+		if(attr != nil && strcmp(attr, "wb") != 0)
+			goto Skip;
+
 		/* write pattern */
 		seed = pat;
 		if((v = vmap(pa, chunk)) == nil)
@@ -420,6 +449,7 @@
 	Bad:
 		vunmap(v, chunk);
 
+	Skip:
 		if(pa+chunk <= 16*MB)
 			memmapadd(pa, chunk, MemUMB);
 
@@ -488,6 +518,12 @@
 	 */
 	if(e820scan() < 0)
 		ramscan(MemMin, -((uintptr)MemMin), 4*MB);
+
+	/*
+	 * Exclude UMB's and UPA's with unusual cache attributes.
+	 */
+	mtrrexclude(MemUMB, "uc");
+	mtrrexclude(MemUPA, "uc");
 }
 
 /*
--- a/sys/src/9/pc/mtrr.c
+++ b/sys/src/9/pc/mtrr.c
@@ -691,6 +691,16 @@
 	return nil;
 }
 
+char*
+mtrrattr(uvlong pa, uvlong *pnext)
+{
+	if(cpu0state.mask == 0)
+		return nil;
+	if(pnext != nil)
+		*pnext = getnext(&cpu0state, pa, nil);
+	return type2str(gettype(&cpu0state, pa, nil));
+}
+
 int
 mtrrprint(char *buf, long bufsize)
 {
--- a/sys/src/9/pc64/fns.h
+++ b/sys/src/9/pc64/fns.h
@@ -99,6 +99,7 @@
 void	mmuinit(void);
 uintptr	*mmuwalk(uintptr*, uintptr, int, int);
 char*	mtrr(uvlong, uvlong, char *);
+char*	mtrrattr(uvlong, uvlong *);
 void	mtrrclock(void);
 int	mtrrprint(char *, long);
 void	mtrrsync(void);