summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/amd64/amd64/amd64_mem.c24
-rw-r--r--sys/arch/i386/i386/i686_mem.c23
2 files changed, 40 insertions, 7 deletions
diff --git a/sys/arch/amd64/amd64/amd64_mem.c b/sys/arch/amd64/amd64/amd64_mem.c
index 086c8c7410c..d7c3f36e516 100644
--- a/sys/arch/amd64/amd64/amd64_mem.c
+++ b/sys/arch/amd64/amd64/amd64_mem.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: amd64_mem.c,v 1.3 2010/02/23 21:54:53 kettenis Exp $ */
+/* $OpenBSD: amd64_mem.c,v 1.4 2010/03/23 19:31:18 kettenis Exp $ */
/*-
* Copyright (c) 1999 Michael Smith <msmith@freebsd.org>
* All rights reserved.
@@ -76,6 +76,7 @@ struct mem_range_ops amd64_mrops = {
/* XXX for AP startup hook */
u_int64_t mtrrcap, mtrrdef;
+u_int64_t mtrrmask = 0x0000000ffffff000ULL;
struct mem_range_desc *mem_range_match(struct mem_range_softc *sc,
struct mem_range_desc *mrd);
@@ -209,13 +210,13 @@ amd64_mrfetch(struct mem_range_softc *sc)
msrv = rdmsr(msr);
mrd->mr_flags = (mrd->mr_flags & ~MDF_ATTRMASK) |
amd64_mtrr2mrt(msrv & 0xff);
- mrd->mr_base = msrv & 0x0000000ffffff000LL;
+ mrd->mr_base = msrv & mtrrmask;
msrv = rdmsr(msr + 1);
mrd->mr_flags = (msrv & 0x800) ?
(mrd->mr_flags | MDF_ACTIVE) :
(mrd->mr_flags & ~MDF_ACTIVE);
/* Compute the range from the mask. Ick. */
- mrd->mr_len = (~(msrv & 0xfffffffffffff000LL) & 0x0000000fffffffffLL) + 1;
+ mrd->mr_len = (~(msrv & mtrrmask) & mtrrmask) + 0x1000;
if (!mrvalid(mrd->mr_base, mrd->mr_len))
mrd->mr_flags |= MDF_BOGUS;
/* If unclaimed and active, must be the BIOS */
@@ -534,6 +535,7 @@ void
amd64_mrinit(struct mem_range_softc *sc)
{
struct mem_range_desc *mrd;
+ uint32_t regs[4];
int nmdesc = 0;
int i;
@@ -580,6 +582,21 @@ amd64_mrinit(struct mem_range_softc *sc)
}
/*
+ * Fetch maximum physical address size supported by the
+ * processor as supported by CPUID leaf function 0x80000008.
+ * If CPUID does not support leaf function 0x80000008, use the
+ * default a 36-bit address size.
+ */
+ CPUID(0x80000000, regs[0], regs[1], regs[2], regs[3]);
+ if (regs[0] >= 0x80000008) {
+ CPUID(0x80000008, regs[0], regs[1], regs[2], regs[3]);
+ if (regs[0] & 0xff) {
+ mtrrmask = (1ULL << (regs[0] & 0xff)) - 1;
+ mtrrmask &= ~0x0000000000000fffULL;
+ }
+ }
+
+ /*
* Get current settings, anything set now is considered to have
* been set by the firmware. (XXX has something already played here?)
*/
@@ -609,4 +626,3 @@ amd64_mrreload_cpu(struct mem_range_softc *sc)
amd64_mrstoreone(sc); /* set MTRRs to match BSP */
enable_intr();
}
-
diff --git a/sys/arch/i386/i386/i686_mem.c b/sys/arch/i386/i386/i686_mem.c
index 49958669c3c..8997e4b35b7 100644
--- a/sys/arch/i386/i386/i686_mem.c
+++ b/sys/arch/i386/i386/i686_mem.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: i686_mem.c,v 1.12 2010/02/23 21:54:53 kettenis Exp $ */
+/* $OpenBSD: i686_mem.c,v 1.13 2010/03/23 19:31:18 kettenis Exp $ */
/*-
* Copyright (c) 1999 Michael Smith <msmith@freebsd.org>
* All rights reserved.
@@ -76,6 +76,7 @@ struct mem_range_ops i686_mrops = {
/* XXX for AP startup hook */
u_int64_t mtrrcap, mtrrdef;
+u_int64_t mtrrmask = 0x0000000ffffff000ULL;
struct mem_range_desc *mem_range_match(struct mem_range_softc *sc,
struct mem_range_desc *mrd);
@@ -209,13 +210,13 @@ i686_mrfetch(struct mem_range_softc *sc)
msrv = rdmsr(msr);
mrd->mr_flags = (mrd->mr_flags & ~MDF_ATTRMASK) |
i686_mtrr2mrt(msrv & 0xff);
- mrd->mr_base = msrv & 0x0000000ffffff000LL;
+ mrd->mr_base = msrv & mtrrmask;
msrv = rdmsr(msr + 1);
mrd->mr_flags = (msrv & 0x800) ?
(mrd->mr_flags | MDF_ACTIVE) :
(mrd->mr_flags & ~MDF_ACTIVE);
/* Compute the range from the mask. Ick. */
- mrd->mr_len = (~(msrv & 0x0000000ffffff000LL) & 0x0000000fffffffffLL) + 1;
+ mrd->mr_len = (~(msrv & mtrrmask) & mtrrmask) + 0x1000;
if (!mrvalid(mrd->mr_base, mrd->mr_len))
mrd->mr_flags |= MDF_BOGUS;
/* If unclaimed and active, must be the BIOS */
@@ -534,6 +535,7 @@ void
i686_mrinit(struct mem_range_softc *sc)
{
struct mem_range_desc *mrd;
+ uint32_t regs[4];
int nmdesc = 0;
int i;
@@ -580,6 +582,21 @@ i686_mrinit(struct mem_range_softc *sc)
}
/*
+ * Fetch maximum physical address size supported by the
+ * processor as supported by CPUID leaf function 0x80000008.
+ * If CPUID does not support leaf function 0x80000008, use the
+ * default a 36-bit address size.
+ */
+ cpuid(0x80000000, regs);
+ if (regs[0] >= 0x80000008) {
+ cpuid(0x80000008, regs);
+ if (regs[0] & 0xff) {
+ mtrrmask = (1ULL << (regs[0] & 0xff)) - 1;
+ mtrrmask &= ~0x0000000000000fffULL;
+ }
+ }
+
+ /*
* Get current settings, anything set now is considered to have
* been set by the firmware. (XXX has something already played here?)
*/