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
This commit is contained in:
cinap_lenrek 2020-12-05 16:57:12 +01:00
parent 4ca5e1b3a3
commit 99696c414a
4 changed files with 48 additions and 0 deletions

View file

@ -101,6 +101,7 @@ void mfence(void);
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);

View file

@ -320,6 +320,27 @@ umbexclude(void)
}
}
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 @@ e820scan(void)
}
}
/* 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 @@ ramscan(uintptr pa, uintptr top, uintptr chunk)
{
ulong save, pat, seed, *v, *k0;
int i, n, w;
char *attr;
pa += chunk-1;
pa &= ~(chunk-1);
@ -389,6 +414,10 @@ ramscan(uintptr pa, uintptr top, uintptr chunk)
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 @@ ramscan(uintptr pa, uintptr top, uintptr chunk)
Bad:
vunmap(v, chunk);
Skip:
if(pa+chunk <= 16*MB)
memmapadd(pa, chunk, MemUMB);
@ -488,6 +518,12 @@ meminit0(void)
*/
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");
}
/*

View file

@ -691,6 +691,16 @@ mtrr(uvlong base, uvlong size, char *tstr)
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)
{

View file

@ -99,6 +99,7 @@ void mfence(void);
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);