diff --git a/sys/kern/subr_physmem.c b/sys/kern/subr_physmem.c --- a/sys/kern/subr_physmem.c +++ b/sys/kern/subr_physmem.c @@ -180,7 +180,7 @@ 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 @@ 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) { /* @@ -417,8 +418,6 @@ 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. @@ -451,14 +450,6 @@ 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); } diff --git a/tests/sys/kern/subr_physmem_test.c b/tests/sys/kern/subr_physmem_test.c --- a/tests/sys/kern/subr_physmem_test.c +++ b/tests/sys/kern/subr_physmem_test.c @@ -76,14 +76,12 @@ 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_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()); }