summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2008-03-19 16:37:24 +0000
committerjhb <jhb@FreeBSD.org>2008-03-19 16:37:24 +0000
commitb1769b65e6ce78d419b349fc3f25f4af8cc367f9 (patch)
tree636329dafe9e037b737cf836546a4964a2ffe7e4 /sys/i386
parent144b6820dc1ee289b4976b1f2e452c77715b7142 (diff)
downloadFreeBSD-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.c30
-rw-r--r--sys/i386/include/specialreg.h4
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
/*
OpenPOWER on IntegriCloud