diff options
-rw-r--r-- | arch/i386/include/kernel/asm.h | 12 | ||||
-rw-r--r-- | arch/i386/include/kernel/paging.h | 14 | ||||
-rw-r--r-- | arch/i386/include/kernel/vmem.h | 17 | ||||
-rw-r--r-- | arch/i386/kernel/paging.c | 122 |
4 files changed, 88 insertions, 77 deletions
diff --git a/arch/i386/include/kernel/asm.h b/arch/i386/include/kernel/asm.h index a002a44..d692917 100644 --- a/arch/i386/include/kernel/asm.h +++ b/arch/i386/include/kernel/asm.h @@ -4,13 +4,6 @@ #include <kernel/gdt.h> #include <stdint.h> -extern uintptr_t _kernel_start; -extern uintptr_t _kernel_end; -#define KSTART ((uintptr_t)&_kernel_start) -#define KEND ((uintptr_t)&_kernel_end - 0xC0000000) - -#define PAGE_SIZE 4096 - #define PCI_CONFIG_ADDR 0xCF8 #define PCI_CONFIG_DATA 0xCFC @@ -108,7 +101,6 @@ void aquire_lock(int *lock); void release_lock(int *lock); void enable_paging(uint32_t new_cr3); - void flush_gdt(void); static inline void outb(uint16_t port, uint8_t value) { @@ -153,6 +145,10 @@ static inline void flush_tss(void) { __asm__ volatile("movw $0x28, %ax; ltr %ax"); } +static inline void flush_tlb(void) { + __asm__ volatile("movl %cr3, %eax; movl %eax, %cr3"); +} + static inline void invlpg(void *addr) { __asm__ volatile("invlpg (%0)" : : "b"(addr) : "memory"); } diff --git a/arch/i386/include/kernel/paging.h b/arch/i386/include/kernel/paging.h index 5999986..d8bb8f3 100644 --- a/arch/i386/include/kernel/paging.h +++ b/arch/i386/include/kernel/paging.h @@ -5,6 +5,8 @@ #include <kernel/multiboot.h> #include <stdint.h> +#define PAGE_SIZE 4096 + #define PD_PRES 0x0001 #define PD_RW 0x0002 #define PD_USR 0x0004 @@ -28,14 +30,16 @@ #define GET_PADDR(x) (((uint32_t)(x)) - 0xC0000000) #define GET_VADDR(x) (((uint32_t)(x)) + 0xC0000000) -#define GET_PDX(x) (((uintptr_t)(x) >> 22) & 0x3FF) -#define GET_PTX(x) (((uintptr_t)(x) >> 12) & 0x3FF) +#define GET_PDX(x) ((uintptr_t)(x) >> 22) +#define GET_PTX(x) (((uintptr_t)(x) >> 12) & 0x03FF) + +uintptr_t get_physaddr(void *vaddr); -uintptr_t* init_page_table(void); void paging_init(void); -void map_page(uint32_t *pd, uintptr_t paddr, uintptr_t vaddr, uint32_t flags); -void unmap_page(uint32_t *pd, uintptr_t vaddr); +uintptr_t init_page_directory(void); +void map_page(uintptr_t paddr, uintptr_t vaddr, uint32_t flags); +void unmap_page(uintptr_t vaddr); void page_fault_handler(struct isr_frame *frame); diff --git a/arch/i386/include/kernel/vmem.h b/arch/i386/include/kernel/vmem.h new file mode 100644 index 0000000..94aa32d --- /dev/null +++ b/arch/i386/include/kernel/vmem.h @@ -0,0 +1,17 @@ +#ifndef I386_VMEM_H +#define I386_VMEM_H + +extern uintptr_t _kernel_start; +extern uintptr_t _kernel_end; + +#define KSTART ((uintptr_t)&_kernel_start) +#define KEND ((uintptr_t)&_kernel_end - 0xC0000000) + +#define KHEAP_START (GET_VADDR(KEND) + 0x2000) +#define KHEAP_STOP 0xFF7FF000 + +#define PAGE_DIR_MAP 0xFFFFF000 +#define PAGE_TAB_MAP 0xFFC00000 +#define PAGE_TMP_MAP 0xFFBFF000 + +#endif diff --git a/arch/i386/kernel/paging.c b/arch/i386/kernel/paging.c index 96ad2ce..b8e00af 100644 --- a/arch/i386/kernel/paging.c +++ b/arch/i386/kernel/paging.c @@ -1,96 +1,88 @@ #include <kernel/paging.h> #include <kernel/asm.h> +#include <kernel/vmem.h> #include <kernel/pmem.h> #include <kernel/panic.h> #include <kernel/syscall.h> #include <libk/io.h> #include <libk/string.h> -uintptr_t *kpgdir = NULL; - -static uintptr_t kernel_pd[1024] __attribute__((aligned(PAGE_SIZE))); -static uintptr_t kernel_pt[1024] __attribute__((aligned(PAGE_SIZE))); -static uintptr_t accnt_pt[1024] __attribute__((aligned(PAGE_SIZE))); static int paging_enabled = 0; -void _copy_kernel_maps(uintptr_t *new_pd) { - int pdx = GET_PDX(GET_VADDR(KSTART)); - new_pd[pdx] = GET_PADDR(kernel_pt) | PD_PRES | PD_RW; - new_pd[832] = GET_PADDR(accnt_pt) | PD_PRES | PD_RW; -} - -uintptr_t* init_page_table(void) { - uintptr_t *ret = (uintptr_t*)pfa_alloc(); - if ((uintptr_t)ret == PFA_ALLOC_ERR) - return NULL; - - uintptr_t *temp_map = (uintptr_t*)0xD0001000; - map_page(NULL, (uintptr_t)ret, (uintptr_t)temp_map, PD_PRES | PD_RW); - memset((char*)temp_map, 0, PAGE_SIZE); - unmap_page(NULL, (uintptr_t)temp_map); - return ret; -} - -uintptr_t* init_page_directory(void) { - uintptr_t *ret = (uintptr_t*)pfa_alloc(); - if ((uintptr_t)ret == PFA_ALLOC_ERR) - return NULL; - - map_page(NULL, (uintptr_t)ret, (uintptr_t)ret, PD_PRES | PD_RW); - memset(ret, 0, PAGE_SIZE); - _copy_kernel_maps(ret); - unmap_page(NULL, (uintptr_t)ret); - - return ret; -} - void paging_init(void) { if (paging_enabled == 1) return; - - _copy_kernel_maps(kernel_pd); + + uintptr_t phys_pt = pfa_alloc(1); + map_page(phys_pt, PAGE_TMP_MAP, PD_PRES | PD_RW); + uintptr_t *pt = (uintptr_t*)PAGE_TMP_MAP; for (uintptr_t i = KSTART; i < KEND; i += PAGE_SIZE) - map_page(kernel_pd, i, GET_VADDR(i), PD_PRES); + pt[GET_PTX(GET_VADDR(i))] = i | PD_PRES; + unmap_page(PAGE_TMP_MAP); - map_page(kernel_pd, 0xB8000, 0xC03FF000, PD_PRES | PD_RW); - kpgdir = kernel_pd; - enable_paging(GET_PADDR(kpgdir)); + uintptr_t phys_pd = pfa_alloc(1); + map_page(phys_pd, PAGE_TMP_MAP, PD_PRES | PD_RW); + uintptr_t *pd = (uintptr_t*)PAGE_TMP_MAP; + pd[GET_PDX(GET_VADDR(KSTART))] = phys_pt | PD_PRES | PD_RW; + pd[1023] = phys_pd | PD_PRES | PD_RW; + unmap_page(PAGE_TMP_MAP); + + enable_paging(phys_pd); paging_enabled = 1; return; } -void map_page(uint32_t *pd, uintptr_t paddr, uintptr_t vaddr, uint32_t flags) { - if (pd == NULL) - pd = kpgdir; +void init_page_table(int pdindex, uint32_t flags) { + uintptr_t *pd = (uintptr_t*)PAGE_DIR_MAP; + if ((pd[pdindex] & PD_PRES) != 0) + return; + + uintptr_t paddr = pfa_alloc(1); + pd[pdindex] = paddr | PD_PRES | PD_RW | flags; + + uintptr_t *pt = ((uintptr_t*)PAGE_TAB_MAP) + (pdindex << 12); + pd[GET_PDX(pt)] = paddr | PD_PRES | PD_RW; +} + +uintptr_t init_page_directory(void) { + uintptr_t ret = pfa_alloc(1); + map_page(ret, PAGE_TMP_MAP, PD_RW); + + uintptr_t *new_pd = (uintptr_t*)PAGE_TMP_MAP; + uintptr_t *cur_pd = (uintptr_t*)PAGE_DIR_MAP; + int kernel_pdx = GET_PDX(GET_VADDR(KSTART)); + new_pd[kernel_pdx] = cur_pd[kernel_pdx]; + unmap_page(PAGE_TMP_MAP); + return ret; +} + +void map_page(uintptr_t paddr, uintptr_t vaddr, uint32_t flags) { paddr = PGROUNDDN(paddr); vaddr = PGROUNDDN(vaddr); - uintptr_t pdindex = GET_PDX(vaddr); - uintptr_t ptindex = GET_PTX(vaddr); + int pdindex = GET_PDX(vaddr); + int ptindex = GET_PTX(vaddr); - uintptr_t *pt = (uintptr_t*)(GET_VADDR(pd[pdindex]) & 0xFFFFF000); - if (pd[pdindex] == 0) - pd[pdindex] = (uintptr_t)init_page_table(); + uintptr_t *pd = (uintptr_t*)PAGE_DIR_MAP; + if ((pd[pdindex] & PD_PRES) == 0) + init_page_table(pdindex, 0); - uintptr_t *pte = (uintptr_t*)(&pt[ptindex]); - *pte |= paddr | (flags & 0xFFF) | 0x01; + uintptr_t *pt = (uintptr_t*)(PAGE_TAB_MAP + (pdindex << 12)); + pt[ptindex] = paddr | PD_PRES | flags; invlpg((void*)vaddr); } -void unmap_page(uint32_t *pd, uintptr_t vaddr) { - if (pd == NULL) - pd = kpgdir; - +void unmap_page(uintptr_t vaddr) { uintptr_t pdindex = GET_PDX(vaddr); uintptr_t ptindex = GET_PTX(vaddr); - uintptr_t *pt = (uintptr_t*)(GET_VADDR(pd[pdindex]) & 0xFFFFF000); - if (pd[pdindex] == 0) + uintptr_t *pd = (uintptr_t*)PAGE_DIR_MAP; + if ((pd[pdindex] & PD_PRES) == 0) return; - uintptr_t *pte = (uintptr_t*)(&pt[ptindex]); - *pte &= 0; + uintptr_t *pt = (uintptr_t*)(PAGE_TAB_MAP + (pdindex << 12)); + pt[ptindex] = 0; invlpg((void*)vaddr); } @@ -98,28 +90,30 @@ void page_fault_handler(struct isr_frame *frame) { uintptr_t fault_addr; __asm__ volatile("movl %%cr2, %0" : "=r"(fault_addr)); + kprintf("Faulting address: %x\n", fault_addr); + panic("Page fault not operational"); switch (frame->isr_err) { case 0: - map_page((uintptr_t*)GET_VADDR(frame->cr3), pfa_alloc(), fault_addr, PD_PRES); + //map_page((uintptr_t*)GET_VADDR(frame->cr3), pfa_alloc(), fault_addr, PD_PRES); break; case 1: panic("Kernel process caused protection fault on read\n"); break; case 2: - map_page((uintptr_t*)GET_VADDR(frame->cr3), pfa_alloc(), fault_addr, PD_PRES | PD_RW); + //map_page((uintptr_t*)GET_VADDR(frame->cr3), pfa_alloc(), fault_addr, PD_PRES | PD_RW); break; case 3: panic("Kernel process caused protection fault on write\n"); break; case 4: - map_page((uintptr_t*)GET_VADDR(frame->cr3), pfa_alloc(), fault_addr, PD_PRES | PD_USR); + //map_page((uintptr_t*)GET_VADDR(frame->cr3), pfa_alloc(), fault_addr, PD_PRES | PD_USR); break; case 5: // TODO: instead of panicking, kill process panic("User process caused protection fault on read\n"); break; case 6: - map_page((uintptr_t*)GET_VADDR(frame->cr3), pfa_alloc(), fault_addr, PD_PRES | PD_RW | PD_USR); + //map_page((uintptr_t*)GET_VADDR(frame->cr3), pfa_alloc(), fault_addr, PD_PRES | PD_RW | PD_USR); break; case 7: // TODO: see case 101 |