vm_phys: Check for overlap when adding a segment

Segments are passed by machine-dependent routines, so explicit checks
will make debugging much easier on very weird machines or when someone
is tweaking these machine-dependent routines.  Additionally, this
operation is not performance-sensitive.

For the same reasons, test that we don't reach the maximum number of
physical segments (the compile-time of the internal storage) in
production kernels (replaces the existing KASSERT()).

Reviewed by:    markj
MFC after:      1 week
Sponsored by:   The FreeBSD Foundation
Differential Revision:  https://reviews.freebsd.org/D48628
This commit is contained in:
Olivier Certner 2024-10-10 09:41:40 +02:00
parent f30309abcc
commit 8a14ddcc1d
No known key found for this signature in database
GPG key ID: 8CA13040971E2627

View file

@ -421,18 +421,26 @@ _vm_phys_create_seg(vm_paddr_t start, vm_paddr_t end, int domain)
{ {
struct vm_phys_seg *seg; struct vm_phys_seg *seg;
KASSERT(vm_phys_nsegs < VM_PHYSSEG_MAX, if (!(0 <= domain && domain < vm_ndomains))
("vm_phys_create_seg: increase VM_PHYSSEG_MAX")); panic("%s: Invalid domain %d ('vm_ndomains' is %d)",
KASSERT(domain >= 0 && domain < vm_ndomains, __func__, domain, vm_ndomains);
("vm_phys_create_seg: invalid domain provided")); if (vm_phys_nsegs >= VM_PHYSSEG_MAX)
panic("Not enough storage for physical segments, "
"increase VM_PHYSSEG_MAX");
seg = &vm_phys_segs[vm_phys_nsegs++]; seg = &vm_phys_segs[vm_phys_nsegs++];
while (seg > vm_phys_segs && (seg - 1)->start >= end) { while (seg > vm_phys_segs && seg[-1].start >= end) {
*seg = *(seg - 1); *seg = *(seg - 1);
seg--; seg--;
} }
seg->start = start; seg->start = start;
seg->end = end; seg->end = end;
seg->domain = domain; seg->domain = domain;
if (seg != vm_phys_segs && seg[-1].end > start)
panic("Overlapping physical segments: Current [%#jx,%#jx) "
"at index %zu, previous [%#jx,%#jx)",
(uintmax_t)start, (uintmax_t)end, seg - vm_phys_segs,
(uintmax_t)seg[-1].start, (uintmax_t)seg[-1].end);
} }
static void static void