kernel/vm: Free pages via vm_page_free only, not vm_page_set_state.

All consumers of this API should be adjusted here.

This partially paves the way for use of committed pages for page tables.

Change-Id: Id6fc2edc86fbd80e929c413e23cf8de1509a8215
Reviewed-on: https://review.haiku-os.org/c/haiku/+/8723
Reviewed-by: X512 X512 <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
Augustin Cavalier
2024-12-28 14:47:32 +00:00
committed by waddlesplash
parent bd0f4983c8
commit b1a913c3aa
16 changed files with 59 additions and 41 deletions
@@ -718,7 +718,7 @@ Aperture::_Free(aperture_memory *memory)
vm_page *page = memory->page; vm_page *page = memory->page;
for (uint32 i = 0; i < count; i++, page++) { for (uint32 i = 0; i < count; i++, page++) {
DEBUG_PAGE_ACCESS_TRANSFER(page, memory->allocating_thread); DEBUG_PAGE_ACCESS_TRANSFER(page, memory->allocating_thread);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free(NULL, page);
} }
memory->page = NULL; memory->page = NULL;
@@ -726,7 +726,7 @@ Aperture::_Free(aperture_memory *memory)
for (uint32 i = 0; i < count; i++) { for (uint32 i = 0; i < count; i++) {
DEBUG_PAGE_ACCESS_TRANSFER(memory->pages[i], DEBUG_PAGE_ACCESS_TRANSFER(memory->pages[i],
memory->allocating_thread); memory->allocating_thread);
vm_page_set_state(memory->pages[i], PAGE_STATE_FREE); vm_page_free(NULL, memory->pages[i]);
} }
free(memory->pages); free(memory->pages);
@@ -180,8 +180,7 @@ test_capacity(cd_driver_info *info)
info->scsi->free_ccb(request); info->scsi->free_ccb(request);
for (size_t i = 0; i < numEntries; i++) { for (size_t i = 0; i < numEntries; i++) {
vm_page_set_state(vm_lookup_page(entries[i].address / B_PAGE_SIZE), vm_page_free(NULL, vm_lookup_page(entries[i].address / B_PAGE_SIZE));
PAGE_STATE_FREE);
} }
if (info->capacity != info->original_capacity) { if (info->capacity != info->original_capacity) {
@@ -60,6 +60,7 @@ ARMVMTranslationMap32Bit::~ARMVMTranslationMap32Bit()
if (fPagingStructures->pgdir_virt != NULL) { if (fPagingStructures->pgdir_virt != NULL) {
// cycle through and free all of the user space pgtables // cycle through and free all of the user space pgtables
vm_page_reservation reservation = {};
for (uint32 i = VADDR_TO_PDENT(USER_BASE); for (uint32 i = VADDR_TO_PDENT(USER_BASE);
i <= VADDR_TO_PDENT(USER_BASE + (USER_SIZE - 1)); i++) { i <= VADDR_TO_PDENT(USER_BASE + (USER_SIZE - 1)); i++) {
if ((fPagingStructures->pgdir_virt[i] & ARM_PDE_TYPE_MASK) != 0) { if ((fPagingStructures->pgdir_virt[i] & ARM_PDE_TYPE_MASK) != 0) {
@@ -69,9 +70,10 @@ ARMVMTranslationMap32Bit::~ARMVMTranslationMap32Bit()
if (!page) if (!page)
panic("destroy_tmap: didn't find pgtable page\n"); panic("destroy_tmap: didn't find pgtable page\n");
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free_etc(NULL, page, &reservation);
} }
} }
vm_page_unreserve_pages(&reservation);
} }
fPagingStructures->RemoveReference(); fPagingStructures->RemoveReference();
@@ -143,7 +143,9 @@ VMSAv8TranslationMap::~VMSAv8TranslationMap()
ThreadCPUPinner pinner(thread_get_current_thread()); ThreadCPUPinner pinner(thread_get_current_thread());
InterruptsSpinLocker locker(sAsidLock); InterruptsSpinLocker locker(sAsidLock);
FreeTable(fPageTable, 0, fInitialLevel); vm_page_reservation reservation = {};
FreeTable(fPageTable, 0, fInitialLevel, &reservation);
vm_page_unreserve_pages(&reservation);
if (fASID != -1) { if (fASID != -1) {
sAsidMapping[fASID] = NULL; sAsidMapping[fASID] = NULL;
@@ -285,7 +287,8 @@ VMSAv8TranslationMap::TableFromPa(phys_addr_t pa)
void void
VMSAv8TranslationMap::FreeTable(phys_addr_t ptPa, uint64_t va, int level) VMSAv8TranslationMap::FreeTable(phys_addr_t ptPa, uint64_t va, int level,
vm_page_reservation* reservation)
{ {
ASSERT(level < 4); ASSERT(level < 4);
@@ -302,7 +305,7 @@ VMSAv8TranslationMap::FreeTable(phys_addr_t ptPa, uint64_t va, int level)
uint64_t oldPte = (uint64_t) atomic_get_and_set64((int64*) &pt[i], 0); uint64_t oldPte = (uint64_t) atomic_get_and_set64((int64*) &pt[i], 0);
if (level < 3 && (oldPte & kPteTypeMask) == kPteTypeL012Table) { if (level < 3 && (oldPte & kPteTypeMask) == kPteTypeL012Table) {
FreeTable(oldPte & kPteAddrMask, nextVa, level + 1); FreeTable(oldPte & kPteAddrMask, nextVa, level + 1, reservation);
} else if ((oldPte & kPteTypeMask) != 0) { } else if ((oldPte & kPteTypeMask) != 0) {
uint64_t fullVa = (fIsKernel ? ~vaMask : 0) | nextVa; uint64_t fullVa = (fIsKernel ? ~vaMask : 0) | nextVa;
@@ -316,7 +319,7 @@ VMSAv8TranslationMap::FreeTable(phys_addr_t ptPa, uint64_t va, int level)
vm_page* page = vm_lookup_page(ptPa >> fPageBits); vm_page* page = vm_lookup_page(ptPa >> fPageBits);
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free_etc(NULL, page, reservation);
} }
@@ -361,7 +364,7 @@ VMSAv8TranslationMap::GetOrMakeTable(phys_addr_t ptPa, int level, int index,
// setup and use the one they installed instead. // setup and use the one they installed instead.
ASSERT((oldPteRefetch & kPteTypeMask) == kPteTypeL012Table); ASSERT((oldPteRefetch & kPteTypeMask) == kPteTypeL012Table);
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free_etc(NULL, page, reservation);
return oldPteRefetch & kPteAddrMask; return oldPteRefetch & kPteAddrMask;
} }
@@ -115,7 +115,7 @@ private:
static uint8_t MairIndex(uint8_t type); static uint8_t MairIndex(uint8_t type);
bool ValidateVa(addr_t va); bool ValidateVa(addr_t va);
uint64_t* TableFromPa(phys_addr_t pa); uint64_t* TableFromPa(phys_addr_t pa);
void FreeTable(phys_addr_t ptPa, uint64_t va, int level); void FreeTable(phys_addr_t ptPa, uint64_t va, int level, vm_page_reservation* reservation);
phys_addr_t GetOrMakeTable(phys_addr_t ptPa, int level, int index, vm_page_reservation* reservation); phys_addr_t GetOrMakeTable(phys_addr_t ptPa, int level, int index, vm_page_reservation* reservation);
template<typename UpdatePte> template<typename UpdatePte>
void ProcessRange(phys_addr_t ptPa, int level, addr_t va, size_t size, void ProcessRange(phys_addr_t ptPa, int level, addr_t va, size_t size,
@@ -338,6 +338,8 @@ destroy_tmap(vm_translation_map *map)
restore_interrupts(state); restore_interrupts(state);
if (map->arch_data->rtdir_virt != NULL) { if (map->arch_data->rtdir_virt != NULL) {
vm_page_reservation reservation = {};
// cycle through and free all of the user space pgtables // cycle through and free all of the user space pgtables
// since the size of tables don't match B_PAGE_SIZE, // since the size of tables don't match B_PAGE_SIZE,
// we alloc several at once, based on modulos, // we alloc several at once, based on modulos,
@@ -377,14 +379,15 @@ destroy_tmap(vm_translation_map *map)
return; return;
} }
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free_etc(NULL, page, &reservation);
} }
if (((i + 1) % NUM_DIRTBL_PER_PAGE) == 0) { if (((i + 1) % NUM_DIRTBL_PER_PAGE) == 0) {
DEBUG_PAGE_ACCESS_END(dirpage); DEBUG_PAGE_ACCESS_END(dirpage);
vm_page_set_state(dirpage, PAGE_STATE_FREE); vm_page_free_etc(NULL, dirpage, &reservation);
} }
} }
free(map->arch_data->rtdir_virt); free(map->arch_data->rtdir_virt);
vm_page_unreserve_pages(&reservation);
} }
free(map->arch_data); free(map->arch_data);
@@ -54,6 +54,7 @@ M68KVMTranslationMap040::~M68KVMTranslationMap040()
fPageMapper->Delete(); fPageMapper->Delete();
if (fPagingStructures->pgroot_virt != NULL) { if (fPagingStructures->pgroot_virt != NULL) {
vm_page_reservation reservation = {};
page_root_entry *pgroot_virt = fPagingStructures->pgroot_virt; page_root_entry *pgroot_virt = fPagingStructures->pgroot_virt;
// cycle through and free all of the user space pgdirs & pgtables // cycle through and free all of the user space pgdirs & pgtables
@@ -97,14 +98,14 @@ M68KVMTranslationMap040::~M68KVMTranslationMap040()
return; return;
} }
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free_etc(NULL, page, &reservation);
} }
if (((i + 1) % NUM_DIRTBL_PER_PAGE) == 0) { if (((i + 1) % NUM_DIRTBL_PER_PAGE) == 0) {
DEBUG_PAGE_ACCESS_END(dirpage); DEBUG_PAGE_ACCESS_END(dirpage);
vm_page_set_state(dirpage, PAGE_STATE_FREE); vm_page_free_etc(NULL, dirpage, &reservation);
} }
} }
vm_page_unreserve_pages(&reservation);
#if 0 #if 0
@@ -118,7 +119,7 @@ M68KVMTranslationMap040::~M68KVMTranslationMap040()
if (!page) if (!page)
panic("destroy_tmap: didn't find pgtable page\n"); panic("destroy_tmap: didn't find pgtable page\n");
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free_etc(NULL, page, &reservation);
} }
} }
#endif #endif
@@ -159,7 +159,7 @@ PPCVMTranslationMap460::~PPCVMTranslationMap460()
if (!page) if (!page)
panic("destroy_tmap: didn't find pgtable page\n"); panic("destroy_tmap: didn't find pgtable page\n");
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free_etc(NULL, page, &reservation);
} }
} }
} }
@@ -159,7 +159,7 @@ PPCVMTranslationMapClassic::~PPCVMTranslationMapClassic()
if (!page) if (!page)
panic("destroy_tmap: didn't find pgtable page\n"); panic("destroy_tmap: didn't find pgtable page\n");
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free_etc(NULL, page, &reservation);
} }
} }
} }
@@ -35,7 +35,7 @@ extern uint32 gPlatform;
static void static void
FreePageTable(page_num_t ppn, bool isKernel, uint32 level = 2) FreePageTable(vm_page_reservation* reservation, page_num_t ppn, bool isKernel, uint32 level = 2)
{ {
if (level > 0) { if (level > 0) {
Pte* pte = (Pte*)VirtFromPhys(ppn * B_PAGE_SIZE); Pte* pte = (Pte*)VirtFromPhys(ppn * B_PAGE_SIZE);
@@ -47,12 +47,13 @@ FreePageTable(page_num_t ppn, bool isKernel, uint32 level = 2)
} }
for (uint64 i = beg; i <= end; i++) { for (uint64 i = beg; i <= end; i++) {
if (pte[i].isValid) if (pte[i].isValid)
FreePageTable(pte[i].ppn, isKernel, level - 1); FreePageTable(reservation, pte[i].ppn, isKernel, level - 1);
} }
} }
vm_page* page = vm_lookup_page(ppn); vm_page* page = vm_lookup_page(ppn);
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free_etc(NULL, page, reservation);
} }
@@ -180,7 +181,9 @@ RISCV64VMTranslationMap::~RISCV64VMTranslationMap()
// Can't delete currently used page table // Can't delete currently used page table
ASSERT_ALWAYS(::Satp() != Satp()); ASSERT_ALWAYS(::Satp() != Satp());
FreePageTable(fPageTable / B_PAGE_SIZE, fIsKernel); vm_page_reservation reservation = {};
FreePageTable(&reservation, fPageTable / B_PAGE_SIZE, fIsKernel);
vm_page_unreserve_pages(&reservation);
} }
@@ -53,6 +53,7 @@ X86VMTranslationMap32Bit::~X86VMTranslationMap32Bit()
if (fPageMapper != NULL) if (fPageMapper != NULL)
fPageMapper->Delete(); fPageMapper->Delete();
vm_page_reservation reservation = {};
if (fPagingStructures->pgdir_virt != NULL) { if (fPagingStructures->pgdir_virt != NULL) {
// cycle through and free all of the user space pgtables // cycle through and free all of the user space pgtables
for (uint32 i = VADDR_TO_PDENT(USER_BASE); for (uint32 i = VADDR_TO_PDENT(USER_BASE);
@@ -64,10 +65,11 @@ X86VMTranslationMap32Bit::~X86VMTranslationMap32Bit()
if (!page) if (!page)
panic("destroy_tmap: didn't find pgtable page\n"); panic("destroy_tmap: didn't find pgtable page\n");
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free_etc(NULL, page, &reservation);
} }
} }
} }
vm_page_unreserve_pages(&reservation);
fPagingStructures->RemoveReference(); fPagingStructures->RemoveReference();
} }
@@ -52,6 +52,7 @@ X86VMTranslationMap64Bit::~X86VMTranslationMap64Bit()
return; return;
if (fPageMapper != NULL) { if (fPageMapper != NULL) {
vm_page_reservation reservation = {};
phys_addr_t address; phys_addr_t address;
vm_page* page; vm_page* page;
@@ -81,7 +82,7 @@ X86VMTranslationMap64Bit::~X86VMTranslationMap64Bit()
} }
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free_etc(NULL, page, &reservation);
} }
address = virtualPDPT[j] & X86_64_PDPTE_ADDRESS_MASK; address = virtualPDPT[j] & X86_64_PDPTE_ADDRESS_MASK;
@@ -92,7 +93,7 @@ X86VMTranslationMap64Bit::~X86VMTranslationMap64Bit()
} }
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free_etc(NULL, page, &reservation);
} }
address = virtualPML4[i] & X86_64_PML4E_ADDRESS_MASK; address = virtualPML4[i] & X86_64_PML4E_ADDRESS_MASK;
@@ -103,9 +104,11 @@ X86VMTranslationMap64Bit::~X86VMTranslationMap64Bit()
} }
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free_etc(NULL, page, &reservation);
} }
vm_page_unreserve_pages(&reservation);
fPageMapper->Delete(); fPageMapper->Delete();
} }
@@ -246,6 +246,7 @@ X86VMTranslationMapPAE::~X86VMTranslationMapPAE()
STATIC_ASSERT(KERNEL_BASE == 0x80000000 && KERNEL_SIZE == 0x80000000); STATIC_ASSERT(KERNEL_BASE == 0x80000000 && KERNEL_SIZE == 0x80000000);
// assuming 1-1 split of the address space // assuming 1-1 split of the address space
vm_page_reservation reservation = {};
for (uint32 k = 0; k < 2; k++) { for (uint32 k = 0; k < 2; k++) {
pae_page_directory_entry* pageDir pae_page_directory_entry* pageDir
= fPagingStructures->VirtualPageDirs()[k]; = fPagingStructures->VirtualPageDirs()[k];
@@ -263,10 +264,11 @@ X86VMTranslationMapPAE::~X86VMTranslationMapPAE()
address, address,
(k * kPAEPageDirEntryCount + i) * kPAEPageTableRange); (k * kPAEPageDirEntryCount + i) * kPAEPageTableRange);
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free_etc(NULL, page, &reservation);
} }
} }
} }
vm_page_unreserve_pages(&reservation);
fPagingStructures->RemoveReference(); fPagingStructures->RemoveReference();
} }
+3 -3
View File
@@ -223,7 +223,7 @@ PrecacheIO::IOFinished(status_t status, bool partialTransfer,
DEBUG_PAGE_ACCESS_TRANSFER(fPages[i], fAllocatingThread); DEBUG_PAGE_ACCESS_TRANSFER(fPages[i], fAllocatingThread);
fCache->NotifyPageEvents(fPages[i], PAGE_EVENT_NOT_BUSY); fCache->NotifyPageEvents(fPages[i], PAGE_EVENT_NOT_BUSY);
fCache->RemovePage(fPages[i]); fCache->RemovePage(fPages[i]);
vm_page_set_state(fPages[i], PAGE_STATE_FREE); vm_page_free(fCache, fPages[i]);
} }
delete this; delete this;
@@ -319,7 +319,7 @@ reserve_pages(file_cache_ref* ref, vm_page_reservation* reservation,
ASSERT(!page->IsMapped()); ASSERT(!page->IsMapped());
ASSERT(!page->modified); ASSERT(!page->modified);
cache->RemovePage(page); cache->RemovePage(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free(cache, page);
left--; left--;
} }
} }
@@ -421,7 +421,7 @@ read_into_cache(file_cache_ref* ref, void* cookie, off_t offset,
for (int32 i = 0; i < pageIndex; i++) { for (int32 i = 0; i < pageIndex; i++) {
cache->NotifyPageEvents(pages[i], PAGE_EVENT_NOT_BUSY); cache->NotifyPageEvents(pages[i], PAGE_EVENT_NOT_BUSY);
cache->RemovePage(pages[i]); cache->RemovePage(pages[i]);
vm_page_set_state(pages[i], PAGE_STATE_FREE); vm_page_free(cache, pages[i]);
} }
return status; return status;
+8 -4
View File
@@ -1955,7 +1955,7 @@ err1:
if (page == NULL) if (page == NULL)
panic("couldn't lookup physical page just allocated\n"); panic("couldn't lookup physical page just allocated\n");
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free(NULL, page);
} }
} }
@@ -3462,24 +3462,28 @@ unmap_and_free_physical_pages(VMTranslationMap* map, addr_t start, addr_t end)
{ {
// free all physical pages in the specified range // free all physical pages in the specified range
vm_page_reservation reservation = {};
for (addr_t current = start; current < end; current += B_PAGE_SIZE) { for (addr_t current = start; current < end; current += B_PAGE_SIZE) {
phys_addr_t physicalAddress; phys_addr_t physicalAddress;
uint32 flags; uint32 flags;
if (map->Query(current, &physicalAddress, &flags) == B_OK if (map->Query(current, &physicalAddress, &flags) == B_OK
&& (flags & PAGE_PRESENT) != 0) { && (flags & PAGE_PRESENT) != 0) {
vm_page* page = vm_lookup_page(physicalAddress / B_PAGE_SIZE); vm_page* page = vm_lookup_page(physicalAddress / B_PAGE_SIZE);
if (page != NULL && page->State() != PAGE_STATE_FREE if (page != NULL && page->State() != PAGE_STATE_FREE
&& page->State() != PAGE_STATE_CLEAR && page->State() != PAGE_STATE_CLEAR
&& page->State() != PAGE_STATE_UNUSED) { && page->State() != PAGE_STATE_UNUSED) {
DEBUG_PAGE_ACCESS_START(page); DEBUG_PAGE_ACCESS_START(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free_etc(NULL, page, &reservation);
} }
} }
} }
// unmap the memory // unmap the memory
map->Unmap(start, end); map->Unmap(start, end);
// unreserve the memory
vm_page_unreserve_pages(&reservation);
} }
@@ -4306,7 +4310,7 @@ fault_get_page(PageFaultContext& context)
cache->NotifyPageEvents(page, PAGE_EVENT_NOT_BUSY); cache->NotifyPageEvents(page, PAGE_EVENT_NOT_BUSY);
cache->RemovePage(page); cache->RemovePage(page);
vm_page_set_state(page, PAGE_STATE_FREE); vm_page_free_etc(cache, page, &context.reservation);
cache->ReleaseRefAndUnlock(); cache->ReleaseRefAndUnlock();
return status; return status;
+2 -6
View File
@@ -4103,7 +4103,7 @@ vm_page_free_etc(VMCache* cache, vm_page* page,
PAGE_ASSERT(page, page->State() != PAGE_STATE_FREE PAGE_ASSERT(page, page->State() != PAGE_STATE_FREE
&& page->State() != PAGE_STATE_CLEAR); && page->State() != PAGE_STATE_CLEAR);
if (page->State() == PAGE_STATE_MODIFIED && cache->temporary) if (page->State() == PAGE_STATE_MODIFIED && (cache != NULL && cache->temporary))
atomic_add(&sModifiedTemporaryPages, -1); atomic_add(&sModifiedTemporaryPages, -1);
free_page(page, false); free_page(page, false);
@@ -4120,11 +4120,7 @@ vm_page_set_state(vm_page *page, int pageState)
PAGE_ASSERT(page, page->State() != PAGE_STATE_FREE PAGE_ASSERT(page, page->State() != PAGE_STATE_FREE
&& page->State() != PAGE_STATE_CLEAR); && page->State() != PAGE_STATE_CLEAR);
if (pageState == PAGE_STATE_FREE || pageState == PAGE_STATE_CLEAR) { set_page_state(page, pageState);
free_page(page, pageState == PAGE_STATE_CLEAR);
unreserve_pages(1);
} else
set_page_state(page, pageState);
} }