diff options
-rw-r--r-- | src/kernel/arch/amd64/32/paging.c | 78 | ||||
-rw-r--r-- | src/kernel/arch/amd64/pagedir.c | 182 | ||||
-rw-r--r-- | src/kernel/arch/amd64/sysenter.c | 1 | ||||
-rw-r--r-- | src/kernel/mem/alloc.c | 6 | ||||
-rw-r--r-- | src/kernel/mem/alloc.h | 3 | ||||
-rw-r--r-- | src/kernel/proc.c | 1 |
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); |