summaryrefslogtreecommitdiff
path: root/src/arch/amd64/paging.c
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2024-02-03 00:50:07 -0500
committerFreya Murphy <freya@freyacat.org>2024-02-03 00:53:58 -0500
commit90a6065691beee52bf5309916fba98f7580d27be (patch)
tree0b5375d20c189f62d394c473d371f7bf7f1d3fc5 /src/arch/amd64/paging.c
parentimproved debugger, refactored (diff)
downloadcorn-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.c82
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;
+}