mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
Handle non-page aligned/sized memory in physmem
In some configurations the firmware may pass memory regions that are
not page sized or aligned, e.g. when using 16k pages on arm64. If this
is the case we will calculate many small regions because the alignment
is applied before being inserted. As we round the start up and end down
this will leave a 1 page hole between what should have been a single
region.
Fix by keeping the original alignment until we are just about to insert
the region into the avail array.
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D34694
(cherry picked from commit d8bff5b67c)
This commit is contained in:
parent
0edb26c3ba
commit
fc5ab0227b
2 changed files with 24 additions and 15 deletions
|
|
@ -180,7 +180,7 @@ regions_to_avail(vm_paddr_t *avail, uint32_t exflags, size_t maxavail,
|
|||
uint64_t maxphyssz, long *pavail, long *prealmem)
|
||||
{
|
||||
size_t acnt, exi, hwi;
|
||||
uint64_t end, start, xend, xstart;
|
||||
uint64_t adj, end, start, xend, xstart;
|
||||
long availmem, totalmem;
|
||||
const struct region *exp, *hwp;
|
||||
uint64_t availsz;
|
||||
|
|
@ -190,8 +190,9 @@ regions_to_avail(vm_paddr_t *avail, uint32_t exflags, size_t maxavail,
|
|||
availsz = 0;
|
||||
acnt = 0;
|
||||
for (hwi = 0, hwp = hwregions; hwi < hwcnt; ++hwi, ++hwp) {
|
||||
start = hwp->addr;
|
||||
end = hwp->size + start;
|
||||
adj = round_page(hwp->addr) - hwp->addr;
|
||||
start = round_page(hwp->addr);
|
||||
end = trunc_page(hwp->size + adj) + start;
|
||||
totalmem += atop((vm_offset_t)(end - start));
|
||||
for (exi = 0, exp = exregions; exi < excnt; ++exi, ++exp) {
|
||||
/*
|
||||
|
|
@ -337,8 +338,6 @@ insert_region(struct region *regions, size_t rcnt, vm_paddr_t addr,
|
|||
void
|
||||
physmem_hardware_region(uint64_t pa, uint64_t sz)
|
||||
{
|
||||
vm_offset_t adj;
|
||||
|
||||
/*
|
||||
* Filter out the page at PA 0x00000000. The VM can't handle it, as
|
||||
* pmap_extract() == 0 means failure.
|
||||
|
|
@ -371,14 +370,6 @@ physmem_hardware_region(uint64_t pa, uint64_t sz)
|
|||
sz -= 1024 * 1024;
|
||||
}
|
||||
|
||||
/*
|
||||
* Round the starting address up to a page boundary, and truncate the
|
||||
* ending page down to a page boundary.
|
||||
*/
|
||||
adj = round_page(pa) - pa;
|
||||
pa = round_page(pa);
|
||||
sz = trunc_page(sz - adj);
|
||||
|
||||
if (sz > 0 && hwcnt < nitems(hwregions))
|
||||
hwcnt = insert_region(hwregions, hwcnt, pa, sz, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,14 +76,12 @@ ATF_TC_BODY(hwregion, tc)
|
|||
ATF_CHECK_EQ(avail[0], 2 * PAGE_SIZE);
|
||||
ATF_CHECK_EQ(avail[1], 6 * PAGE_SIZE);
|
||||
|
||||
#ifdef notyet /* This doesn't currently work */
|
||||
/* Add the remaining part of the page */
|
||||
physmem_hardware_region(6 * PAGE_SIZE + PAGE_SIZE / 2, PAGE_SIZE / 2);
|
||||
len = physmem_avail(avail, 4);
|
||||
ATF_CHECK_EQ(len, 2);
|
||||
ATF_CHECK_EQ(avail[0], 2 * PAGE_SIZE);
|
||||
ATF_CHECK_EQ(avail[1], 7 * PAGE_SIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(hwregion_exclude);
|
||||
|
|
@ -113,10 +111,30 @@ ATF_TC_BODY(hwregion_exclude, tc)
|
|||
ATF_CHECK_EQ(avail[3], 7 * PAGE_SIZE);
|
||||
}
|
||||
|
||||
ATF_TC_WITHOUT_HEAD(hwregion_unordered);
|
||||
ATF_TC_BODY(hwregion_unordered, tc)
|
||||
{
|
||||
vm_paddr_t avail[4];
|
||||
size_t len;
|
||||
|
||||
/* Add a partial page */
|
||||
physmem_hardware_region(PAGE_SIZE, PAGE_SIZE / 2);
|
||||
/* Add a full page not touching the previous */
|
||||
physmem_hardware_region( 2 * PAGE_SIZE, PAGE_SIZE);
|
||||
/* Add the remainder of the first page */
|
||||
physmem_hardware_region(PAGE_SIZE + PAGE_SIZE / 2, PAGE_SIZE / 2);
|
||||
|
||||
len = physmem_avail(avail, 4);
|
||||
ATF_CHECK_EQ(len, 2);
|
||||
ATF_CHECK_EQ(avail[0], PAGE_SIZE);
|
||||
ATF_CHECK_EQ(avail[1], 3 * PAGE_SIZE);
|
||||
}
|
||||
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
|
||||
ATF_TP_ADD_TC(tp, hwregion);
|
||||
ATF_TP_ADD_TC(tp, hwregion_exclude);
|
||||
ATF_TP_ADD_TC(tp, hwregion_unordered);
|
||||
return (atf_no_error());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue