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:
parent
4ca5e1b3a3
commit
99696c414a
4 changed files with 48 additions and 0 deletions
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue