diff --git a/sys/amd64/amd64/amd64_mem.c b/sys/amd64/amd64/amd64_mem.c index 7704f47dca2c..672e63fbe00a 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 7704f47dca2c..672e63fbe00a 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 00f9b7ff07ef..7065b98902f4 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 bd18f590b467..558ad31377e3 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 { diff --git a/usr.sbin/memcontrol/memcontrol.8 b/usr.sbin/memcontrol/memcontrol.8 index 989eb16f2cf2..f9d24a83ff69 100644 --- a/usr.sbin/memcontrol/memcontrol.8 +++ b/usr.sbin/memcontrol/memcontrol.8 @@ -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 , diff --git a/usr.sbin/memcontrol/memcontrol.c b/usr.sbin/memcontrol/memcontrol.c index 2554723733a9..9eb87197eaaa 100644 --- a/usr.sbin/memcontrol/memcontrol.c +++ b/usr.sbin/memcontrol/memcontrol.c @@ -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},