diff options
author | Freya Murphy <freya@freyacat.org> | 2024-02-03 00:50:07 -0500 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2024-02-03 00:53:58 -0500 |
commit | 90a6065691beee52bf5309916fba98f7580d27be (patch) | |
tree | 0b5375d20c189f62d394c473d371f7bf7f1d3fc5 /src/arch/amd64/paging.c | |
parent | improved debugger, refactored (diff) | |
download | corn-90a6065691beee52bf5309916fba98f7580d27be.tar.gz corn-90a6065691beee52bf5309916fba98f7580d27be.tar.bz2 corn-90a6065691beee52bf5309916fba98f7580d27be.zip |
refactor, new arch dirs, (wip) page alloc on write, hsv screen (convert to userspace later), other fixes
Diffstat (limited to 'src/arch/amd64/paging.c')
-rw-r--r-- | src/arch/amd64/paging.c | 82 |
1 files changed, 74 insertions, 8 deletions
diff --git a/src/arch/amd64/paging.c b/src/arch/amd64/paging.c index 604e0a0..1c1c56c 100644 --- a/src/arch/amd64/paging.c +++ b/src/arch/amd64/paging.c @@ -45,7 +45,8 @@ struct pde { // PAGE TABLE ENTRY struct pte { uint64_t flags : 9; - uint64_t : 3; + uint64_t loaded : 1; + uint64_t : 2; uint64_t address : 40; uint64_t : 7; uint64_t protection_key : 4; @@ -69,7 +70,7 @@ static struct pde *pd_mapped = (void *) (uintptr_t) 0x202000; static struct pte *pt_mapped = (void *) (uintptr_t) 0x203000; static inline void invlpg(void *addr) { - __asm volatile("invlpg (%0)" ::"r" (addr) : "memory"); + __asm__ volatile("invlpg (%0)" ::"r" (addr) : "memory"); } static void load_addr(void *phys_addr) { @@ -297,6 +298,7 @@ static void unmap_page( page->address = 0; page->flags = 0; + page->loaded = 0; try_unmap_pt(); @@ -360,6 +362,7 @@ static void unmap_pages( page->address = 0; page->flags = 0; + page->loaded = 0; } @@ -369,6 +372,31 @@ static void unmap_pages( return; } +static struct pte *get_page( + struct pml4e *root, + void *virt +) { + struct pdpte *pdpt; + struct pde *pd; + struct pte *pt; + struct pte *page; + + unsigned int df = 0; + + if (select_pdpt(virt, df, root, &pdpt, false)) + return NULL; + + if (select_pd(virt, df, pdpt, &pd, false)) + return NULL; + + if (select_pt(virt, df, pd, &pt, false)) + return NULL; + + select_page(virt, pt, &page); + + return page; +} + static int map_page( struct pml4e *root, void *virt, @@ -382,6 +410,9 @@ static int map_page( unsigned int df = F_WRITEABLE; + if (phys == NULL) + df = 0; // alloc page on fault + if (select_pdpt(virt, df, root, &pdpt, true)) return 1; @@ -393,9 +424,16 @@ static int map_page( select_page(virt, pt, &page); - page->address = (uint64_t)phys >> 12; - page->flags = F_PRESENT | flags; - invlpg(virt); + if (phys) { + page->flags = F_PRESENT | flags; + page->address = (uint64_t)phys >> 12; + page->loaded = 1; + invlpg(virt); + } else { + page->flags = flags; + page->address = 0; + page->loaded = 0; + } return 0; } @@ -424,6 +462,9 @@ static int map_pages( unsigned int df = F_WRITEABLE; + if (phys_start == NULL) + df = 0; // alloc page on fault + long i; for (i = 0; i < page_count; i++) { @@ -454,15 +495,22 @@ static int map_pages( select_page(virt, pt, &page); - page->address = (uint64_t)phys >> 12; - page->flags = F_PRESENT | flags; + if (phys_start) { + page->flags = F_PRESENT | flags; + page->address = (uint64_t)phys >> 12; + page->loaded = 1; + } else { + page->flags = flags; + page->address = 0; + page->loaded = 0; + } if (flags & F_GLOBAL) invlpg(virt); } - __asm volatile("mov %cr3, %rax; mov %rax, %cr3;"); + __asm__ volatile("mov %cr3, %rax; mov %rax, %cr3;"); return 0; @@ -575,3 +623,21 @@ int kunmap_page(void *virt_addr) { unmap_page(kernel_pml4, virt_addr); return 0; } + +int kload_page(void *virt_addr) { + struct pte *page = get_page(kernel_pml4, virt_addr); + if (page == NULL) + return -1; + if (page->loaded) + return -1; + void *phys = alloc_phys_page(); + kprintf("0x%p\n", phys); + if (phys == NULL) + return -2; + page->loaded = 1; + page->address = (uint64_t)phys >> 12; + page->flags |= F_PRESENT | F_WRITEABLE; + invlpg(virt_addr); + __asm__ volatile ("movq %cr3, %rax; movq %rax, %cr3;"); + return 0; +} |