kernel/vm: Set sAvailableMemory from the reserved physical pages size.

Rather than setting it from the total count of pages, and then reducing
it by the size of the B_ALREADY_WIRED areas incrementally. This means
that other things allocated in the early boot period (like page tables)
will also be accounted for. The downside is that, if they don't have
a corresponding area, then any pages freed later on won't also unreserve
memory at present; but the early boot page tables likely won't be freed
at all (since they'll be in use; or should have already been freed in the
case of the 32-bit to PAE transition.)

(In the future, we should reserve memory as well as pages for the page
tables, and that will take care of that problem anyway.)

Booting x86_64 in QEMU with 1GB of RAM, the old accounting method produced
an initial (after ALREADY_WIRED accounting) sAvailableMemory of 251,368
total pages, while this new accounting method gives 250,812 instead,
a difference of 556 pages. (Some of that is probably the never-freed
bootloader memory, which I think is around ~360 pages.)

Overall this should reduce the amount of "theoretically available but
actually inaccessible" memory, which should hopefully help with the VM
getting itself into trouble thinking memory is available when it
really isn't.
This commit is contained in:
Augustin Cavalier
2024-12-14 12:01:29 -05:00
parent 2c84bc3c0e
commit fc815a9c7a
2 changed files with 11 additions and 6 deletions
+8 -6
View File
@@ -1653,6 +1653,7 @@ vm_create_anonymous_area(team_id team, const char *name, addr_t size,
physical_address_restrictions stackPhysicalRestrictions;
bool doReserveMemory = false;
addr_t reservedMemory = 0;
switch (wiring) {
case B_NO_LOCK:
break;
@@ -1661,8 +1662,6 @@ vm_create_anonymous_area(team_id team, const char *name, addr_t size,
case B_CONTIGUOUS:
doReserveMemory = true;
break;
case B_ALREADY_WIRED:
break;
case B_LOMEM:
stackPhysicalRestrictions = *physicalAddressRestrictions;
stackPhysicalRestrictions.high_address = 16 * 1024 * 1024;
@@ -1680,17 +1679,22 @@ vm_create_anonymous_area(team_id team, const char *name, addr_t size,
// TODO: We don't really support this mode efficiently. Just fall
// through for now ...
case B_32_BIT_CONTIGUOUS:
#if B_HAIKU_PHYSICAL_BITS > 32
#if B_HAIKU_PHYSICAL_BITS > 32
if (vm_page_max_address() >= (phys_addr_t)1 << 32) {
stackPhysicalRestrictions = *physicalAddressRestrictions;
stackPhysicalRestrictions.high_address
= (phys_addr_t)1 << 32;
physicalAddressRestrictions = &stackPhysicalRestrictions;
}
#endif
#endif
wiring = B_CONTIGUOUS;
doReserveMemory = true;
break;
case B_ALREADY_WIRED:
ASSERT(gKernelStartup);
// The used memory will already be accounted for.
reservedMemory = size;
break;
default:
return B_BAD_VALUE;
}
@@ -1728,7 +1732,6 @@ vm_create_anonymous_area(team_id team, const char *name, addr_t size,
// chances of failure, since while holding the write lock to the address
// space (if it is the kernel address space that is), the low memory handler
// won't be able to free anything for us.
addr_t reservedMemory = 0;
if (doReserveMemory) {
bigtime_t timeout = (flags & CREATE_AREA_DONT_WAIT) != 0 ? 0 : 1000000;
if (vm_try_reserve_memory(size, priority, timeout) != B_OK)
@@ -3921,7 +3924,6 @@ vm_init(kernel_args* args)
// initialize some globals
vm_page_init_num_pages(args);
sAvailableMemory = vm_page_num_pages() * B_PAGE_SIZE;
slab_init(args);
+3
View File
@@ -3431,6 +3431,9 @@ vm_page_init(kernel_args *args)
// prevent future allocations from the kernel args ranges
args->num_physical_allocated_ranges = 0;
// report initially available memory
vm_unreserve_memory(vm_page_num_free_pages() * B_PAGE_SIZE);
// The target of actually free pages. This must be at least the system
// reserve, but should be a few more pages, so we don't have to extract
// a cached page with each allocation.