aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Evans <kevans@FreeBSD.org>2023-03-10 05:27:39 +0000
committerKyle Evans <kevans@FreeBSD.org>2023-03-10 05:27:39 +0000
commitcc0fe048ec39636216ed59fa47eb311b2537cfc5 (patch)
treede278a13616160e1aa617463ce7027a76280be08
parent75798f9b01055261881938326a5c77e55f79c7f7 (diff)
downloadsrc-cc0fe048ec39636216ed59fa47eb311b2537cfc5.tar.gz
src-cc0fe048ec39636216ed59fa47eb311b2537cfc5.zip
kern: physmem: don't create a new exregion for different flags...
... if the region we're adding is an exact match to one that we already have. Simply extend the flags of the existing entry as needed so that we don't end up with duplicate regions. It could be that we got the exclusion through two different means, e.g., FDT memreserve and the EFI memory map, and we may derive different characteristics from each. Apply the most restrictive set to the region. Reported by: Mark Millard <marklmi yahoo com> Reviewed by: mhorne
-rw-r--r--sys/kern/subr_physmem.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/sys/kern/subr_physmem.c b/sys/kern/subr_physmem.c
index 1fb617078625..b76d25ed1ae2 100644
--- a/sys/kern/subr_physmem.c
+++ b/sys/kern/subr_physmem.c
@@ -376,8 +376,8 @@ insert_region(struct region *regions, size_t rcnt, vm_paddr_t addr,
nend = addr + size;
ep = regions + rcnt;
for (i = 0, rp = regions; i < rcnt; ++i, ++rp) {
+ rend = rp->addr + rp->size;
if (flags == rp->flags) {
- rend = rp->addr + rp->size;
if (addr <= rp->addr && nend >= rp->addr) {
/*
* New mapping overlaps at the beginning, shift
@@ -404,7 +404,20 @@ insert_region(struct region *regions, size_t rcnt, vm_paddr_t addr,
}
return (rcnt);
}
+ } else if ((flags != 0) && (rp->flags != 0)) {
+ /*
+ * If we're duplicating an entry that already exists
+ * exactly, just upgrade its flags as needed. We could
+ * do more if we find that we have differently specified
+ * flags clipping existing excluding regions, but that's
+ * probably rare.
+ */
+ if (addr == rp->addr && nend == rend) {
+ rp->flags |= flags;
+ return (rcnt);
+ }
}
+
if (addr < rp->addr) {
bcopy(rp, rp + 1, (ep - rp) * sizeof(*rp));
break;