From b1769b65e6ce78d419b349fc3f25f4af8cc367f9 Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 19 Mar 2008 16:37:24 +0000 Subject: [PATCH] MFC: Use a runtime mask for the PhysBase and PhysMask fields in variable sized MTRR registers. --- sys/amd64/amd64/amd64_mem.c | 30 ++++++++++++++++++++++++------ sys/amd64/include/specialreg.h | 4 ++-- sys/i386/i386/i686_mem.c | 30 ++++++++++++++++++++++++------ sys/i386/include/specialreg.h | 4 ++-- 4 files changed, 52 insertions(+), 16 deletions(-) diff --git a/sys/amd64/amd64/amd64_mem.c b/sys/amd64/amd64/amd64_mem.c index 5874496a9ba..36c4045ae20 100644 --- a/sys/amd64/amd64/amd64_mem.c +++ b/sys/amd64/amd64/amd64_mem.c @@ -82,6 +82,9 @@ static struct mem_range_ops amd64_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 amd64_mrfetch(struct mem_range_softc *sc); @@ -214,15 +217,15 @@ amd64_mrfetch(struct mem_range_softc *sc) msrv = rdmsr(msr); mrd->mr_flags = (mrd->mr_flags & ~MDF_ATTRMASK) | amd64_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 | 0xfffL)) + 1; + mrd->mr_len = (~(msrv & mtrr_physmask) & + (mtrr_physmask | 0xfffL)) + 1; if (!mrvalid(mrd->mr_base, mrd->mr_len)) mrd->mr_flags |= MDF_BOGUS; @@ -361,7 +364,7 @@ amd64_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 |= amd64_mrt2mtrr(mrd->mr_flags, omsrv); } else { msrv = 0; @@ -371,7 +374,7 @@ amd64_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; } @@ -578,7 +581,8 @@ static void amd64_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 @@ amd64_mrinit(struct mem_range_softc *sc) } nmdesc = mtrrcap & MTRR_CAP_VCNT; + /* + * 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 = ((1UL << pabits) - 1) & ~0xfffUL; + /* 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/amd64/include/specialreg.h b/sys/amd64/include/specialreg.h index e2c7b4d2d68..27d326ffcab 100644 --- a/sys/amd64/include/specialreg.h +++ b/sys/amd64/include/specialreg.h @@ -269,9 +269,9 @@ #define MTRR_DEF_ENABLE 0x0000000000000800UL #define MTRR_DEF_FIXED_ENABLE 0x0000000000000400UL #define MTRR_DEF_TYPE 0x00000000000000ffUL -#define MTRR_PHYSBASE_PHYSBASE 0x000000fffffff000UL +#define MTRR_PHYSBASE_PHYSBASE 0x000ffffffffff000UL #define MTRR_PHYSBASE_TYPE 0x00000000000000ffUL -#define MTRR_PHYSMASK_PHYSMASK 0x000000fffffff000UL +#define MTRR_PHYSMASK_PHYSMASK 0x000ffffffffff000UL #define MTRR_PHYSMASK_VALID 0x0000000000000800UL /* Performance Control Register (5x86 only). */ diff --git a/sys/i386/i386/i686_mem.c b/sys/i386/i386/i686_mem.c index f1240b6dc58..b06ce4694ae 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 4e1f5e3b2ed..07a74ad1dee 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 /* -- 2.45.0