diff options
author | dwmalone <dwmalone@FreeBSD.org> | 2002-09-15 15:07:55 +0000 |
---|---|---|
committer | dwmalone <dwmalone@FreeBSD.org> | 2002-09-15 15:07:55 +0000 |
commit | 6acc49e3bd177eb1e4787e9173c8443ceda1c25e (patch) | |
tree | 12e1e1bf10ab9f5cfe0d9b564ef93fbde0e43737 /sys | |
parent | 7819f421f3fd1e80387d5d7a0a52e8018b6f5edd (diff) | |
download | FreeBSD-src-6acc49e3bd177eb1e4787e9173c8443ceda1c25e.zip FreeBSD-src-6acc49e3bd177eb1e4787e9173c8443ceda1c25e.tar.gz |
Some BIOSs are using MTRR values that are only documented under NDA
to control the mapping of things like the ACPI and APM into memory.
The problem is that starting X changes these values, so if something
was using the bits of BIOS mapped into memory (say ACPI or APM),
then next time they access this memory the machine would hang.
This patch refuse to change MTRR values it doesn't understand,
unless a new "force" option is given. This means X doesn't change
them by accident but someone can override that if they really want
to.
PR: 28418
Tested by: Christopher Masto <chris@netmonger.net>,
David Bushong <david@bushong.net>,
Santos <casd@myrealbox.com>
MFC after: 1 week
Diffstat (limited to 'sys')
-rw-r--r-- | sys/amd64/amd64/amd64_mem.c | 11 | ||||
-rw-r--r-- | sys/i386/i386/i686_mem.c | 11 | ||||
-rw-r--r-- | sys/i386/i386/k6_mem.c | 2 | ||||
-rw-r--r-- | sys/sys/memrange.h | 1 |
4 files changed, 24 insertions, 1 deletions
diff --git a/sys/amd64/amd64/amd64_mem.c b/sys/amd64/amd64/amd64_mem.c index 7704f47..672e63f 100644 --- a/sys/amd64/amd64/amd64_mem.c +++ b/sys/amd64/amd64/amd64_mem.c @@ -392,6 +392,13 @@ i686_mrsetlow(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg) ((last_md = i686_mtrrfixsearch(sc, mrd->mr_base + mrd->mr_len - 1)) == NULL)) return(EINVAL); + /* check we aren't doing something risky */ + if (!(mrd->mr_flags & MDF_FORCE)) + for (curr_md = first_md; curr_md <= last_md; curr_md++) { + if ((curr_md->mr_flags & MDF_ATTRMASK) == MDF_UNKNOWN) + return (EACCES); + } + /* set flags, clear set-by-firmware flag */ for (curr_md = first_md; curr_md <= last_md; curr_md++) { curr_md->mr_flags = mrcopyflags(curr_md->mr_flags & ~MDF_FIRMWARE, mrd->mr_flags); @@ -431,6 +438,10 @@ i686_mrsetvariable(struct mem_range_softc *sc, struct mem_range_desc *mrd, int * /* whoops, owned by someone */ if (curr_md->mr_flags & MDF_BUSY) return(EBUSY); + /* check we aren't doing something risky */ + if (!(mrd->mr_flags & MDF_FORCE) && + ((curr_md->mr_flags & MDF_ATTRMASK) == MDF_UNKNOWN)) + return (EACCES); /* Ok, just hijack this entry */ free_md = curr_md; break; diff --git a/sys/i386/i386/i686_mem.c b/sys/i386/i386/i686_mem.c index 7704f47..672e63f 100644 --- a/sys/i386/i386/i686_mem.c +++ b/sys/i386/i386/i686_mem.c @@ -392,6 +392,13 @@ i686_mrsetlow(struct mem_range_softc *sc, struct mem_range_desc *mrd, int *arg) ((last_md = i686_mtrrfixsearch(sc, mrd->mr_base + mrd->mr_len - 1)) == NULL)) return(EINVAL); + /* check we aren't doing something risky */ + if (!(mrd->mr_flags & MDF_FORCE)) + for (curr_md = first_md; curr_md <= last_md; curr_md++) { + if ((curr_md->mr_flags & MDF_ATTRMASK) == MDF_UNKNOWN) + return (EACCES); + } + /* set flags, clear set-by-firmware flag */ for (curr_md = first_md; curr_md <= last_md; curr_md++) { curr_md->mr_flags = mrcopyflags(curr_md->mr_flags & ~MDF_FIRMWARE, mrd->mr_flags); @@ -431,6 +438,10 @@ i686_mrsetvariable(struct mem_range_softc *sc, struct mem_range_desc *mrd, int * /* whoops, owned by someone */ if (curr_md->mr_flags & MDF_BUSY) return(EBUSY); + /* check we aren't doing something risky */ + if (!(mrd->mr_flags & MDF_FORCE) && + ((curr_md->mr_flags & MDF_ATTRMASK) == MDF_UNKNOWN)) + return (EACCES); /* Ok, just hijack this entry */ free_md = curr_md; break; diff --git a/sys/i386/i386/k6_mem.c b/sys/i386/i386/k6_mem.c index 00f9b7f..7065b98 100644 --- a/sys/i386/i386/k6_mem.c +++ b/sys/i386/i386/k6_mem.c @@ -79,7 +79,7 @@ k6_mrmake(struct mem_range_desc *desc, u_int32_t *mtrr) { return EINVAL; if (desc->mr_len < 131072 || !powerof2(desc->mr_len)) return EINVAL; - if (desc->mr_flags &~ (MDF_WRITECOMBINE|MDF_UNCACHEABLE)) + if (desc->mr_flags &~ (MDF_WRITECOMBINE|MDF_UNCACHEABLE|MDF_FORCE)) return EOPNOTSUPP; for (bit = ffs(desc->mr_len >> 17) - 1; bit < 15; bit++) diff --git a/sys/sys/memrange.h b/sys/sys/memrange.h index bd18f59..558ad31 100644 --- a/sys/sys/memrange.h +++ b/sys/sys/memrange.h @@ -20,6 +20,7 @@ #define MDF_BOGUS (1<<28) /* we don't like it */ #define MDF_FIXACTIVE (1<<29) /* can't be turned off */ #define MDF_BUSY (1<<30) /* range is in use */ +#define MDF_FORCE (1<<31) /* force risky changes */ struct mem_range_desc { |