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
This commit is contained in:
David Malone 2002-09-15 15:07:55 +00:00
parent 8556ba2b73
commit 93f39ea88a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=103346
6 changed files with 27 additions and 2 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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++)

View File

@ -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
{

View File

@ -83,7 +83,8 @@ Length of memory range in bytes, power of 2
.It Fl o Ar owner
Text identifier for this setting (7 char max)
.It Ar attribute
Attributes applied to this range; one of
Attributes applied to this range; combinations of
.Ar force ,
.Ar uncacheable ,
.Ar write-combine ,
.Ar write-through ,

View File

@ -50,6 +50,7 @@ struct
{"write-through", MDF_WRITETHROUGH, MDF_SETTABLE},
{"write-back", MDF_WRITEBACK, MDF_SETTABLE},
{"write-protect", MDF_WRITEPROTECT, MDF_SETTABLE},
{"force", MDF_FORCE, MDF_SETTABLE},
{"unknown", MDF_UNKNOWN, 0},
{"fixed-base", MDF_FIXBASE, 0},
{"fixed-length", MDF_FIXLEN, 0},