diff options
author | jhb <jhb@FreeBSD.org> | 2008-03-19 16:37:24 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2008-03-19 16:37:24 +0000 |
commit | b1769b65e6ce78d419b349fc3f25f4af8cc367f9 (patch) | |
tree | 636329dafe9e037b737cf836546a4964a2ffe7e4 /sys/i386 | |
parent | 144b6820dc1ee289b4976b1f2e452c77715b7142 (diff) | |
download | FreeBSD-src-b1769b65e6ce78d419b349fc3f25f4af8cc367f9.zip FreeBSD-src-b1769b65e6ce78d419b349fc3f25f4af8cc367f9.tar.gz |
MFC: Use a runtime mask for the PhysBase and PhysMask fields in variable
sized MTRR registers.
Diffstat (limited to 'sys/i386')
-rw-r--r-- | sys/i386/i386/i686_mem.c | 30 | ||||
-rw-r--r-- | sys/i386/include/specialreg.h | 4 |
2 files changed, 26 insertions, 8 deletions
diff --git a/sys/i386/i386/i686_mem.c b/sys/i386/i386/i686_mem.c index f1240b6..b06ce46 100644 --- a/sys/i386/i386/i686_mem.c +++ b/sys/i386/i386/i686_mem.c @@ -82,6 +82,9 @@ static struct mem_range_ops i686_mrops = { /* XXX for AP startup hook */ static u_int64_t mtrrcap, mtrrdef; +/* The bitmask for the PhysBase and PhysMask fields of the variable MTRRs. */ +static u_int64_t mtrr_physmask; + static struct mem_range_desc *mem_range_match(struct mem_range_softc *sc, struct mem_range_desc *mrd); static void i686_mrfetch(struct mem_range_softc *sc); @@ -212,15 +215,15 @@ i686_mrfetch(struct mem_range_softc *sc) msrv = rdmsr(msr); mrd->mr_flags = (mrd->mr_flags & ~MDF_ATTRMASK) | i686_mtrr2mrt(msrv & MTRR_PHYSBASE_TYPE); - mrd->mr_base = msrv & MTRR_PHYSBASE_PHYSBASE; + mrd->mr_base = msrv & mtrr_physmask; msrv = rdmsr(msr + 1); mrd->mr_flags = (msrv & MTRR_PHYSMASK_VALID) ? (mrd->mr_flags | MDF_ACTIVE) : (mrd->mr_flags & ~MDF_ACTIVE); /* Compute the range from the mask. Ick. */ - mrd->mr_len = (~(msrv & MTRR_PHYSMASK_PHYSMASK) & - (MTRR_PHYSMASK_PHYSMASK | 0xfffLL)) + 1; + mrd->mr_len = (~(msrv & mtrr_physmask) & + (mtrr_physmask | 0xfffLL)) + 1; if (!mrvalid(mrd->mr_base, mrd->mr_len)) mrd->mr_flags |= MDF_BOGUS; @@ -359,7 +362,7 @@ i686_mrstoreone(void *arg) /* base/type register */ omsrv = rdmsr(msr); if (mrd->mr_flags & MDF_ACTIVE) { - msrv = mrd->mr_base & MTRR_PHYSBASE_PHYSBASE; + msrv = mrd->mr_base & mtrr_physmask; msrv |= i686_mrt2mtrr(mrd->mr_flags, omsrv); } else { msrv = 0; @@ -369,7 +372,7 @@ i686_mrstoreone(void *arg) /* mask/active register */ if (mrd->mr_flags & MDF_ACTIVE) { msrv = MTRR_PHYSMASK_VALID | - (~(mrd->mr_len - 1) & MTRR_PHYSMASK_PHYSMASK); + (~(mrd->mr_len - 1) & mtrr_physmask); } else { msrv = 0; } @@ -576,7 +579,8 @@ static void i686_mrinit(struct mem_range_softc *sc) { struct mem_range_desc *mrd; - int i, nmdesc = 0; + u_int regs[4]; + int i, nmdesc = 0, pabits; mtrrcap = rdmsr(MSR_MTRRcap); mtrrdef = rdmsr(MSR_MTRRdefType); @@ -591,6 +595,20 @@ i686_mrinit(struct mem_range_softc *sc) if (bootverbose) printf("Pentium Pro MTRR support enabled\n"); + /* + * Determine the size of the PhysMask and PhysBase fields in + * the variable range MTRRs. If the extended CPUID 0x80000008 + * is present, use that to figure out how many physical + * address bits the CPU supports. Otherwise, default to 36 + * address bits. + */ + if (cpu_exthigh >= 0x80000008) { + do_cpuid(0x80000008, regs); + pabits = regs[0] & 0xff; + } else + pabits = 36; + mtrr_physmask = ((1ULL << pabits) - 1) & ~0xfffULL; + /* If fixed MTRRs supported and enabled. */ if ((mtrrcap & MTRR_CAP_FIXED) && (mtrrdef & MTRR_DEF_FIXED_ENABLE)) { sc->mr_cap = MR686_FIXMTRR; diff --git a/sys/i386/include/specialreg.h b/sys/i386/include/specialreg.h index 4e1f5e3..07a74ad 100644 --- a/sys/i386/include/specialreg.h +++ b/sys/i386/include/specialreg.h @@ -266,9 +266,9 @@ #define MTRR_DEF_ENABLE 0x0000000000000800ULL #define MTRR_DEF_FIXED_ENABLE 0x0000000000000400ULL #define MTRR_DEF_TYPE 0x00000000000000ffULL -#define MTRR_PHYSBASE_PHYSBASE 0x0000000ffffff000ULL +#define MTRR_PHYSBASE_PHYSBASE 0x000ffffffffff000ULL #define MTRR_PHYSBASE_TYPE 0x00000000000000ffULL -#define MTRR_PHYSMASK_PHYSMASK 0x0000000ffffff000ULL +#define MTRR_PHYSMASK_PHYSMASK 0x000ffffffffff000ULL #define MTRR_PHYSMASK_VALID 0x0000000000000800ULL /* |