summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/kernel/arch/amd64/32/paging.c78
-rw-r--r--src/kernel/arch/amd64/pagedir.c182
-rw-r--r--src/kernel/arch/amd64/sysenter.c1
-rw-r--r--src/kernel/mem/alloc.c6
-rw-r--r--src/kernel/mem/alloc.h3
-rw-r--r--src/kernel/proc.c1
6 files changed, 129 insertions, 142 deletions
diff --git a/src/kernel/arch/amd64/32/paging.c b/src/kernel/arch/amd64/32/paging.c
index 975dd98..ef65ccf 100644
--- a/src/kernel/arch/amd64/32/paging.c
+++ b/src/kernel/arch/amd64/32/paging.c
@@ -1,69 +1,7 @@
#include <stddef.h>
#include <stdint.h>
-struct pml4e {
- uint64_t present : 1;
- uint64_t writeable : 1;
- uint64_t user : 1;
- uint64_t writethru : 1;
-
- uint64_t uncached : 1;
- uint64_t accessed : 1;
- uint64_t _unused1 : 1;
- uint64_t reserved : 1; // always 0
-
- uint64_t _unused2 : 3;
- uint64_t _unused3 : 1; // HLAT thing
-
- uint64_t address : 40;
-
- uint64_t _unused4 : 11;
- uint64_t noexec : 1;
-} __attribute__((packed));
-
-struct pdpte { // page directory pointer table entry, 1gb page | 512 * pde
- uint64_t present : 1;
- uint64_t writeable : 1;
- uint64_t user : 1;
- uint64_t writethru : 1;
-
- uint64_t uncached : 1;
- uint64_t accessed : 1;
- uint64_t _unused1 : 1;
- uint64_t large : 1; // 1gb page
-
- uint64_t _unused2 : 3;
- uint64_t _unused3 : 1; // HLAT
-
- uint64_t address : 40;
-
- uint64_t _unused4 : 11;
- uint64_t noexec : 1;
-} __attribute__((packed));
-
-struct pde { // page directory entry, 2mb page | 512 * pte
- uint64_t present : 1;
- uint64_t writeable : 1;
- uint64_t user : 1;
- uint64_t writethru : 1;
-
- uint64_t uncached : 1;
- uint64_t accessed : 1;
- uint64_t dirty : 1; // only if large
- uint64_t large : 1; // 2mb
-
- uint64_t global : 1; // only if large ; TODO enable CR4.PGE
- uint64_t _unused2 : 2;
- uint64_t _unused3 : 1; // HLAT
-
- uint64_t address : 40; // highest bit - PAT
-
- uint64_t _unused4 : 7;
- uint64_t pke : 4;
- uint64_t noexec : 1;
-} __attribute__((packed));
-
-struct pte { // page table entry, 4kb page
+struct page_generic {
uint64_t present : 1;
uint64_t writeable : 1;
uint64_t user : 1;
@@ -72,7 +10,7 @@ struct pte { // page table entry, 4kb page
uint64_t uncached : 1;
uint64_t accessed : 1;
uint64_t dirty : 1;
- uint64_t pat : 1;
+ uint64_t large : 1; // also PAT
uint64_t global : 1; // TODO enable CR4.PGE
uint64_t _unused2 : 2;
@@ -86,13 +24,13 @@ struct pte { // page table entry, 4kb page
} __attribute__((packed));
__attribute__((aligned(4096)))
-struct pml4e pml4_identity[512];
+struct page_generic pml4_identity[512];
__attribute__((aligned(4096)))
-struct pdpte pdpte_low[512]; // 0-512gb
+struct page_generic pdpte_low[512]; // 0-512gb
__attribute__((aligned(4096)))
-struct pde pde_low[512]; // 0-1gb
+struct page_generic pde_low[512]; // 0-1gb
static void *memset32(void *s, int c, size_t n) {
@@ -108,20 +46,20 @@ void pml4_identity_init(void) {
memset32(pdpte_low, 0, sizeof pdpte_low);
memset32(pde_low, 0, sizeof pde_low);
- pml4_identity[0] = (struct pml4e) {
+ pml4_identity[0] = (struct page_generic) {
.present = 1,
.writeable = 1,
.address = ((uintptr_t)pdpte_low) >> 12,
};
- pdpte_low[0] = (struct pdpte) {
+ pdpte_low[0] = (struct page_generic) {
.present = 1,
.writeable = 1,
.address = ((uintptr_t)pde_low) >> 12,
};
for (int i = 0; i < 512; i++) {
- pde_low[i] = (struct pde) {
+ pde_low[i] = (struct page_generic) {
.present = 1,
.writeable = 1,
.large = 1,
diff --git a/src/kernel/arch/amd64/pagedir.c b/src/kernel/arch/amd64/pagedir.c
index 334cfc2..135770d 100644
--- a/src/kernel/arch/amd64/pagedir.c
+++ b/src/kernel/arch/amd64/pagedir.c
@@ -1,5 +1,6 @@
#include <kernel/arch/generic.h>
#include <kernel/mem/alloc.h>
+#include <kernel/panic.h>
#include <shared/mem.h>
#include <stdint.h>
@@ -8,45 +9,69 @@
* <heat> you can't change them atomically and the way they're layed out
* in memory is implementation defined iirc
*/
-struct pagetable_entry {
- uint32_t present : 1;
- uint32_t writeable : 1;
- uint32_t user : 1;
- uint32_t writethru : 1;
- uint32_t uncached : 1;
- uint32_t dirty : 1;
- uint32_t always0 : 1; // memory type thing?
- uint32_t global : 1;
- uint32_t _unused : 3;
- uint32_t address : 21;
-};
-
-struct pagedir_entry {
- uint32_t present : 1;
- uint32_t _writeable: 1; // don't use! not checked by multiple functions here
- uint32_t _user : 1; // ^
- uint32_t writethru : 1;
- uint32_t uncached : 1;
- uint32_t accessed : 1;
- uint32_t always0 : 1;
- uint32_t large : 1; // 4 MiB instead of 4 KiB
- uint32_t _unused : 3;
- uint32_t address : 21;
+// TODO move to single shared header file for the 32bit bootstrap
+typedef union pe_generic_t {
+ struct {
+ uint64_t present : 1;
+ uint64_t writeable : 1;
+ uint64_t user : 1;
+ uint64_t writethru : 1;
+
+ uint64_t uncached : 1;
+ uint64_t accessed : 1;
+ uint64_t dirty : 1;
+ uint64_t large : 1; // also PAT
+
+ uint64_t global : 1; // TODO enable CR4.PGE
+ uint64_t _unused2 : 2;
+ uint64_t _unused3 : 1; // HLAT
+
+ uint64_t address : 40;
+
+ uint64_t _unused4 : 7;
+ uint64_t pke : 4;
+ uint64_t noexec : 1;
+ } __attribute__((packed));
+ void *as_ptr;
+} pe_generic_t; // pageentry_generic
+
+struct pagedir { // actually pml4, TODO rename to a more generic name
+ pe_generic_t e[512];
} __attribute__((packed));
-struct pagedir {
- struct pagedir_entry e[1024];
-} __attribute__((packed));
+union virt_addr {
+ void __user *full;
+ struct {
+ uint64_t off_4k : 12; // 4Kb // offset in page
+ uint64_t pt : 9; // 2Mb // page table index
+ uint64_t pd : 9; // 1Gb // page directory index
+ uint64_t pdpt : 9; // 512Gb // page directory pointer table index
+ uint64_t pml4 : 9; // 256Tb // page map level 4 index
+ uint64_t sign : 16;
+ } __attribute__((packed));
+};
+
+static void *addr_extract(pe_generic_t pe) {
+ return (void*)(uintptr_t)(pe.address << 12);
+}
+
+static void *addr_validate(void *addr) {
+ pe_generic_t pe = {.as_ptr = addr};
+ assert(addr_extract(pe) == addr);
+ return addr;
+}
struct pagedir *pagedir_new(void) {
struct pagedir *dir = page_alloc(1);
- for (int i = 0; i < 1024; i++)
- dir->e[i].present = 0;
+ memset(dir, 0, sizeof *dir);
return dir;
}
void pagedir_free(struct pagedir *dir) {
+ (void)dir;
+ panic_unimplemented();
+ /*
// assumes all user pages are unique and can be freed
struct pagetable_entry *pt;
void *page;
@@ -66,8 +91,10 @@ void pagedir_free(struct pagedir *dir) {
page_free(pt, 1);
}
page_free(dir, 1);
+ */
}
+/*
static struct pagetable_entry*
get_entry(struct pagedir *dir, const void __user *virt) {
uint32_t pd_idx = ((uintptr_t)virt) >> 22;
@@ -79,61 +106,63 @@ get_entry(struct pagedir *dir, const void __user *virt) {
pagetable = (void*)(dir->e[pd_idx].address << 11);
return &pagetable[pt_idx];
}
+*/
void *pagedir_unmap(struct pagedir *dir, void __user *virt) {
+ (void)dir; (void)virt;
+ panic_unimplemented();
+ /* unset the present bit
void *phys = pagedir_virt2phys(dir, virt, false, false);
struct pagetable_entry *page = get_entry(dir, virt);
page->present = false;
return phys;
+ */
}
void pagedir_map(struct pagedir *dir, void __user *virt, void *phys,
bool user, bool writeable)
{
- kprintf("in pagedir_map, dir 0x%x\n", dir);
- uintptr_t virt_cast = (uintptr_t) virt;
- uint32_t pd_idx = virt_cast >> 22;
- uint32_t pt_idx = virt_cast >> 12 & 0x03FF;
- struct pagetable_entry *pagetable;
+ pe_generic_t *pml4e, *pdpte, *pde, *pte;
+ const union virt_addr v = {.full = virt};
+
+ // TODO check if sign extension is valid
- kprintf("pre-if, accessing 0x%x because 0x%x\n", &dir->e[pd_idx], pd_idx);
- if (dir->e[pd_idx].present) {
- kprintf("present already\n");
- pagetable = (void*) (dir->e[pd_idx].address << 11);
+ pml4e = &dir->e[v.pml4];
+ if (!pml4e->present) {
+ pml4e->as_ptr = addr_validate(page_zalloc(1));
+ pml4e->present = 1;
+ pml4e->writeable = 1;
+ pml4e->user = 1;
+ }
+ assert(!pml4e->large);
+
+ pdpte = &((pe_generic_t*)addr_extract(*pml4e))[v.pdpt];
+ if (!pdpte->present) {
+ pdpte->as_ptr = addr_validate(page_zalloc(1));
+ pdpte->present = 1;
+ pdpte->writeable = 1;
+ pdpte->user = 1;
+ }
+ assert(!pdpte->large);
+
+ pde = &((pe_generic_t*)addr_extract(*pdpte))[v.pd];
+ if (!pde->present) {
+ pde->as_ptr = addr_validate(page_zalloc(1));
+ pde->present = 1;
+ pde->writeable = 1;
+ pde->user = 1;
+ }
+ assert(!pde->large);
+
+ pte = &((pe_generic_t*)addr_extract(*pde))[v.pt];
+ if (!pte->present) {
+ pte->as_ptr = addr_validate(page_zalloc(1));
+ pte->present = 1;
+ pte->writeable = writeable;
+ pte->user = user;
} else {
- kprintf("allocing\n");
- pagetable = page_alloc(1);
- kprintf("alloc successful\n");
- for (int i = 0; i < 1024; i++)
- pagetable[i].present = 0;
-
- dir->e[pd_idx] = (struct pagedir_entry) {
- .present = 1,
- ._writeable= 1,
- ._user = 1,
- .writethru = 1,
- .uncached = 0,
- .accessed = 0,
- .always0 = 0,
- .large = 0,
- ._unused = 0,
- .address = (uintptr_t) pagetable >> 11
- };
+ panic_invalid_state();
}
-
- pagetable[pt_idx] = (struct pagetable_entry) {
- .present = 1,
- .writeable = writeable,
- .user = user,
- .writethru = 1,
- .uncached = 0,
- .dirty = 0,
- .always0 = 0,
- .global = 0,
- ._unused = 0,
- .address = (uintptr_t) phys >> 11
- };
- kprintf("out pagedir_map\n");
}
extern void *pagedir_current;
@@ -143,6 +172,7 @@ void pagedir_switch(struct pagedir *dir) {
// creates a new pagedir with exact copies of the user pages
struct pagedir *pagedir_copy(const struct pagedir *orig) {
+ /*
struct pagedir *clone = page_alloc(1);
struct pagetable_entry *orig_pt, *clone_pt;
void *orig_page, *clone_page;
@@ -170,16 +200,22 @@ struct pagedir *pagedir_copy(const struct pagedir *orig) {
}
return clone;
+ */
+ panic_unimplemented();
}
bool pagedir_iskern(struct pagedir *dir, const void __user *virt) {
+ /*
struct pagetable_entry *page = get_entry(dir, virt);
return page && page->present && !page->user;
+ */
+ panic_unimplemented();
}
void *pagedir_virt2phys(struct pagedir *dir, const void __user *virt,
bool user, bool writeable)
{
+ /*
struct pagetable_entry *page;
uintptr_t phys;
page = get_entry(dir, virt);
@@ -190,9 +226,12 @@ void *pagedir_virt2phys(struct pagedir *dir, const void __user *virt,
phys = page->address << 11;
phys |= ((uintptr_t)virt) & 0xFFF;
return (void*)phys;
+ */
+ panic_unimplemented();
}
void __user *pagedir_findfree(struct pagedir *dir, char __user *start, size_t len) {
+ /*
struct pagetable_entry *page;
char __user *iter;
start = (userptr_t)(((uintptr_t __force)start + PAGE_MASK) & ~PAGE_MASK); // round up to next page
@@ -208,6 +247,7 @@ void __user *pagedir_findfree(struct pagedir *dir, char __user *start, size_t le
}
iter += PAGE_SIZE;
}
-
return NULL;
+ */
+ panic_unimplemented();
}
diff --git a/src/kernel/arch/amd64/sysenter.c b/src/kernel/arch/amd64/sysenter.c
index e42ec7d..75b825f 100644
--- a/src/kernel/arch/amd64/sysenter.c
+++ b/src/kernel/arch/amd64/sysenter.c
@@ -9,6 +9,7 @@ void sysexit(struct registers regs) {
_sysexit_regs = regs;
_sysexit_regs.ecx = (uintptr_t) regs.esp;
_sysexit_regs.edx = (uintptr_t) regs.eip;
+ kprintf("here we go!\n");
_sysexit_real();
__builtin_unreachable();
}
diff --git a/src/kernel/mem/alloc.c b/src/kernel/mem/alloc.c
index 797b018..e0cc5f4 100644
--- a/src/kernel/mem/alloc.c
+++ b/src/kernel/mem/alloc.c
@@ -93,6 +93,12 @@ void *page_alloc(size_t pages) {
panic_unimplemented();
}
+void *page_zalloc(size_t pages) {
+ void *p = page_alloc(pages);
+ memset(p, 0, pages * PAGE_SIZE);
+ return p;
+}
+
// frees `pages` consecutive pages starting from *first
void page_free(void *first_addr, size_t pages) {
size_t first = (uintptr_t)(first_addr - page_bitmap_start) / PAGE_SIZE;
diff --git a/src/kernel/mem/alloc.h b/src/kernel/mem/alloc.h
index a92d866..14c4361 100644
--- a/src/kernel/mem/alloc.h
+++ b/src/kernel/mem/alloc.h
@@ -9,7 +9,10 @@ void mem_init(struct kmain_info *);
void mem_debugprint(void);
// allocates `pages` consecutive pages
+// TODO deprecate
void *page_alloc(size_t pages);
+// zeroes the allocated pages
+void *page_zalloc(size_t pages);
// frees `pages` consecutive pages starting from *first
void page_free(void *first, size_t pages);
diff --git a/src/kernel/proc.c b/src/kernel/proc.c
index 616bd79..1cb6eb0 100644
--- a/src/kernel/proc.c
+++ b/src/kernel/proc.c
@@ -196,7 +196,6 @@ void process_forget(struct process *p) {
}
static _Noreturn void process_switch(struct process *proc) {
- kprintf("process_switch\n");
assert(proc->state == PS_RUNNING);
process_current = proc;
pagedir_switch(proc->pages);