diff options
| author | John Baldwin <jhb@FreeBSD.org> | 2008-03-12 22:09:19 +0000 |
|---|---|---|
| committer | John Baldwin <jhb@FreeBSD.org> | 2008-03-12 22:09:19 +0000 |
| commit | 391664b110bf2ff36ae7454751116b17ebe79bda (patch) | |
| tree | b78c9ec05ed6a1f16731030f669f0a2ee540e28d /sys/amd64 | |
| parent | 4cbd0e89840f0c2b851b2dc2bc3c19a3cfdfbe1a (diff) | |
Notes
Diffstat (limited to 'sys/amd64')
| -rw-r--r-- | sys/amd64/amd64/amd64_mem.c | 30 | ||||
| -rw-r--r-- | sys/amd64/include/specialreg.h | 4 |
2 files changed, 26 insertions, 8 deletions
diff --git a/sys/amd64/amd64/amd64_mem.c b/sys/amd64/amd64/amd64_mem.c index 5874496a9baa..36c4045ae20a 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 94d70adfb7ed..760d2c5d9539 100644 --- a/sys/amd64/include/specialreg.h +++ b/sys/amd64/include/specialreg.h @@ -275,9 +275,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). */ |
