From fc815a9c7a8284a2942c1d804ff5d7d841618981 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Sat, 14 Dec 2024 11:57:01 -0500 Subject: [PATCH] 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. --- src/system/kernel/vm/vm.cpp | 14 ++++++++------ src/system/kernel/vm/vm_page.cpp | 3 +++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/system/kernel/vm/vm.cpp b/src/system/kernel/vm/vm.cpp index feb362a806..fbaab59702 100644 --- a/src/system/kernel/vm/vm.cpp +++ b/src/system/kernel/vm/vm.cpp @@ -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); diff --git a/src/system/kernel/vm/vm_page.cpp b/src/system/kernel/vm/vm_page.cpp index 60851c8058..fd130f3bde 100644 --- a/src/system/kernel/vm/vm_page.cpp +++ b/src/system/kernel/vm/vm_page.cpp @@ -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.