diff options
-rw-r--r-- | sys/arch/amd64/amd64/amd64_mem.c | 24 | ||||
-rw-r--r-- | sys/arch/i386/i386/i686_mem.c | 23 |
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?) */ |