From 404c9f669aee8cbe4fab395d04b99dc71b599e12 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Thu, 29 Feb 2024 16:07:33 -0500 Subject: kernel/amd64: pmap: Allocate new pmap if needed This commit also removes the unnecessary usage of "volatile" Signed-off-by: Ian Moffett --- sys/arch/amd64/amd64/pmap.c | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) (limited to 'sys/arch') diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c index 2fcab57..a7a4eaa 100644 --- a/sys/arch/amd64/amd64/pmap.c +++ b/sys/arch/amd64/amd64/pmap.c @@ -94,46 +94,64 @@ pmap_get_level_index(uint8_t level, vaddr_t va) } } -static inline volatile uintptr_t * -pmap_extract(uint8_t level, vaddr_t va, volatile uintptr_t *pmap) +static inline uintptr_t * +pmap_extract(uint8_t level, vaddr_t va, uintptr_t *pmap, bool allocate) { - uintptr_t *next; + uintptr_t next; + uintptr_t level_alloc; size_t idx; idx = pmap_get_level_index(level, va); - next = PHYS_TO_VIRT(pmap[idx] & PTE_ADDR_MASK); - return next; + + if (__TEST(pmap[idx], PTE_P)) { + next = pmap[idx] & PTE_ADDR_MASK; + return PHYS_TO_VIRT(next); + } + + if (!allocate) { + return 0; + } + + /* + * TODO: If we are out of pageframes here, we don't want to panic + * here. We need to have some sort of clean error reporting. + */ + level_alloc = vm_alloc_pageframe(1); + __assert(level_alloc != 0); + + /* Zero the memory */ + memset(PHYS_TO_VIRT(level_alloc), 0, vm_get_page_size()); + + pmap[idx] = level_alloc | (PTE_P | PTE_RW | PTE_US); + return PHYS_TO_VIRT(level_alloc); } /* * Modify a page table by writing `val' to it. * * TODO: Ensure operations here are serialized. - * - * TODO: Create pmap if they don't exist - * i.e., them being null. */ static int pmap_modify_tbl(struct vm_ctx *ctx, vaddr_t va, size_t val) { struct vas vas = pmap_read_vas(); - volatile uintptr_t *pml4 = PHYS_TO_VIRT(vas.top_level); - volatile uintptr_t *pdpt, *pd, *tbl; + uintptr_t *pml4 = PHYS_TO_VIRT(vas.top_level); + uintptr_t *pdpt, *pd, *tbl; int status = 0; - pdpt = pmap_extract(4, va, pml4); + pdpt = pmap_extract(4, va, pml4, true); if (pdpt == NULL) { status = 1; goto done; } - pd = pmap_extract(3, va, pdpt); + pd = pmap_extract(3, va, pdpt, true); if (pd == NULL) { status = 1; goto done; } - tbl = pmap_extract(2, va, pd); + tbl = pmap_extract(2, va, pd, true); if (tbl == NULL) { status = 1; goto done; -- cgit v1.2.3