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);