From 78579419442f22641368db777120d7e75cbaee94 Mon Sep 17 00:00:00 2001 From: Aleksa Vuckovic Date: Tue, 9 Aug 2022 09:05:02 +0200 Subject: map on page fault --- kernel/include/libk/string.h | 1 + kernel/include/paging.h | 7 +++++ kernel/src/boot/multiboot2.c | 6 +++- kernel/src/cpu/irq.c | 2 +- kernel/src/libk/stdio.c | 8 +++++ kernel/src/libk/string.c | 29 +++++++++++++++++-- kernel/src/main.c | 2 +- kernel/src/mem/paging.c | 69 ++++++++++++++++++++++++++++++-------------- 8 files changed, 98 insertions(+), 26 deletions(-) diff --git a/kernel/include/libk/string.h b/kernel/include/libk/string.h index 64a7f81..9fe8448 100644 --- a/kernel/include/libk/string.h +++ b/kernel/include/libk/string.h @@ -6,6 +6,7 @@ size_t strlen(const char* s); uint64_t stoi(const char *s); void itos(uint64_t num, char* s); +void itoh(uint64_t num, char* s); void strrev(char *s); #endif diff --git a/kernel/include/paging.h b/kernel/include/paging.h index a61d34d..7c9fcd5 100644 --- a/kernel/include/paging.h +++ b/kernel/include/paging.h @@ -3,7 +3,14 @@ #include +#define PAGE_SIZE 0x00200000 +#define FLAG_PRESENT 0x1 +#define FLAG_WRITABLE 0x2 +#define FLAG_HUGE 0x80 +#define KERNEL_VMA 0xc0000000 + void init_paging(void); +void map_addr(uint64_t virt, uint64_t phys, uint32_t flags); void page_fault(uint64_t error); #endif diff --git a/kernel/src/boot/multiboot2.c b/kernel/src/boot/multiboot2.c index 75a1f8d..9c2998f 100644 --- a/kernel/src/boot/multiboot2.c +++ b/kernel/src/boot/multiboot2.c @@ -3,6 +3,7 @@ #include #include +#include #define KERNEL_VMA 0xc0000000 @@ -20,7 +21,6 @@ void init_fb(mb2_tag_header* multiboot_bootinfo, uint32_t multiboot_magic) // skip first 8 bytes (total_size + reserved) mb2_tag_header* tag_header = (mb2_tag_header*)((char*)multiboot_bootinfo + 8 + KERNEL_VMA); - bochs_breakpoint(); while (tag_header->type != MB2_TAG_END) { // process tag_type @@ -41,4 +41,8 @@ void init_fb(mb2_tag_header* multiboot_bootinfo, uint32_t multiboot_magic) main_fb.height = tag_fb->framebuffer_height; main_fb.pitch = tag_fb->framebuffer_pitch; main_fb.bpp = tag_fb->framebuffer_bpp; + + // identity map framebuffer address + map_addr(main_fb.addr, main_fb.addr, FLAG_PRESENT + FLAG_WRITABLE + FLAG_HUGE); + map_addr(main_fb.addr + PAGE_SIZE, main_fb.addr + PAGE_SIZE, FLAG_PRESENT + FLAG_WRITABLE + FLAG_HUGE); } diff --git a/kernel/src/cpu/irq.c b/kernel/src/cpu/irq.c index be0d2a2..dd87b61 100644 --- a/kernel/src/cpu/irq.c +++ b/kernel/src/cpu/irq.c @@ -119,8 +119,8 @@ void isr13_handler(uint64_t error) void isr14_handler(uint64_t error) { + page_fault(error); printf("%s\n", exception_name[14]); - printf("error: %d\n", error); } void isr15_handler(void) diff --git a/kernel/src/libk/stdio.c b/kernel/src/libk/stdio.c index b8ddb67..be75b73 100644 --- a/kernel/src/libk/stdio.c +++ b/kernel/src/libk/stdio.c @@ -47,6 +47,13 @@ inline void print_int(uint64_t num) print_string(a); } +inline void print_hex(uint64_t num) +{ + char a[100]; + itoh(num, a); + print_string(a); +} + void printf(const char *s, ...) { size_t count = 0; @@ -63,6 +70,7 @@ void printf(const char *s, ...) if(s[i] == 'c') print_char((char)va_arg(list, uint32_t)); else if(s[i] == 's') print_string(va_arg(list, char*)); else if(s[i] == 'd') print_int((uint64_t)va_arg(list, uint64_t)); + else if(s[i] == 'x') print_hex((uint64_t)va_arg(list, uint64_t)); else { print_string("Wrong format using printf\n"); diff --git a/kernel/src/libk/string.c b/kernel/src/libk/string.c index fde9645..6d7ab69 100644 --- a/kernel/src/libk/string.c +++ b/kernel/src/libk/string.c @@ -35,9 +35,34 @@ void strrev(char *s) void itos(uint64_t num, char* s) { + if (num == 0) { + s[0] = '0'; + s[1] = '\0'; + return; + } + + size_t i; + for (i = 0; num; num /= 10, i++) { + s[i] = (char)('0' + num % 10); + } + s[i] = '\0'; + strrev(s); +} + +void itoh(uint64_t num, char* s) +{ + if (num == 0) { + s[0] = '0'; + s[1] = '\0'; + return; + } + size_t i; - for (i = 0; num; num/=10, i++) { - s[i] = (char)('0' + num%10); + for (i = 0; num; num /= 16, i++) { + if (num % 16 < 10) + s[i] = (char)('0' + num % 16); + else + s[i] = (char)('A' + num % 16 - 10); } s[i] = '\0'; strrev(s); diff --git a/kernel/src/main.c b/kernel/src/main.c index 80b0d6a..b562c74 100644 --- a/kernel/src/main.c +++ b/kernel/src/main.c @@ -16,7 +16,7 @@ int kernel_main(mb2_tag_header* multiboot_bootinfo, uint32_t multiboot_magic) init_idt(); init_fb(multiboot_bootinfo, multiboot_magic); - __asm__ volatile ("int $2;"); + __asm__ volatile ("movl $4, 0x500000"); for(;;) { __asm__ volatile ("hlt;"); diff --git a/kernel/src/mem/paging.c b/kernel/src/mem/paging.c index fdd1dd2..cd1cb68 100644 --- a/kernel/src/mem/paging.c +++ b/kernel/src/mem/paging.c @@ -2,42 +2,69 @@ #include #include +#include void load_pt_lvl4(uint64_t*); __attribute__((aligned(4096))) uint64_t page_table_lvl4[512]; __attribute__((aligned(4096))) uint64_t page_table_lvl3[512]; -__attribute__((aligned(4096))) uint64_t page_table_lvl2_hh[512]; +__attribute__((aligned(4096))) uint64_t page_table_lvl2_0[512]; +__attribute__((aligned(4096))) uint64_t page_table_lvl2_1[512]; +__attribute__((aligned(4096))) uint64_t page_table_lvl2_2[512]; +__attribute__((aligned(4096))) uint64_t page_table_lvl2_3[512]; -#define PAGE_SIZE 0x00200000 -#define FLAG_PRESENT 0x1 -#define FLAG_WRITABLE 0x2 -#define FLAG_HUGE 0x80 -#define KERNEL_VMA 0xc0000000 - -void init_paging(void) +void map_addr(uint64_t virt, uint64_t phys, uint32_t flags) { - page_table_lvl4[0] = (uint64_t)page_table_lvl3 + FLAG_PRESENT + FLAG_WRITABLE - KERNEL_VMA; - page_table_lvl3[3] = (uint64_t)page_table_lvl2_hh + FLAG_PRESENT + FLAG_WRITABLE - KERNEL_VMA; + virt -= virt % 0x00200000; + phys -= phys % 0x00200000; - // higher half kernel - // 0xc0000000 - 0xc0400000 : 0xc0000000 - 0xc0400000 - for (uint64_t i = 0; i < 2; i++) { - page_table_lvl2_hh[i] = i * PAGE_SIZE + FLAG_PRESENT + FLAG_WRITABLE + FLAG_HUGE; + // i is in range [0, 511] + size_t pt_lvl4_i = (virt >> 39) % 0x200; // 512gb entry + size_t pt_lvl3_i = (virt >> 30) % 0x200; // 1gb entry + size_t pt_lvl2_i = (virt >> 21) % 0x200; // 2mb entry +// size_t pt_lvl1_i = (virt >> 12) % 0x200; // 4kb entry + + // first 4gb + if (pt_lvl4_i == 0) { + switch(pt_lvl3_i) { + case 0: + page_table_lvl2_0[pt_lvl2_i] = phys | flags; + break; + case 1: + page_table_lvl2_1[pt_lvl2_i] = phys | flags; + break; + case 2: + page_table_lvl2_2[pt_lvl2_i] = phys | flags; + break; + case 3: + page_table_lvl2_3[pt_lvl2_i] = phys | flags; + break; + } } +} - // TODO: remove initial mapping for fb and instead page on demand +void init_paging(void) +{ + page_table_lvl4[0] = (uint64_t)page_table_lvl3 + FLAG_PRESENT + FLAG_WRITABLE - KERNEL_VMA; + page_table_lvl3[0] = (uint64_t)page_table_lvl2_0 + FLAG_PRESENT + FLAG_WRITABLE - KERNEL_VMA; + page_table_lvl3[1] = (uint64_t)page_table_lvl2_1 + FLAG_PRESENT + FLAG_WRITABLE - KERNEL_VMA; + page_table_lvl3[2] = (uint64_t)page_table_lvl2_2 + FLAG_PRESENT + FLAG_WRITABLE - KERNEL_VMA; + page_table_lvl3[3] = (uint64_t)page_table_lvl2_3 + FLAG_PRESENT + FLAG_WRITABLE - KERNEL_VMA; - // identity paged for fb - // 0xe0000000 - 0xffffffff : 0xe0000000 - 0xffffffff - for (uint64_t i = 2; i < 512; i++) { - page_table_lvl2_hh[i] = i * PAGE_SIZE + 0xc0000000 + FLAG_PRESENT + FLAG_WRITABLE + FLAG_HUGE; - } + // higher half map first 4mb + map_addr(KERNEL_VMA, 0x00000000, FLAG_PRESENT + FLAG_WRITABLE + FLAG_HUGE); + map_addr(KERNEL_VMA + PAGE_SIZE, 0x00000000 + PAGE_SIZE, FLAG_PRESENT + FLAG_WRITABLE + FLAG_HUGE); load_pt_lvl4(page_table_lvl4); } + void page_fault(uint64_t error) { - printf("%d\n", error); + uint64_t addr; + __asm__ volatile ("mov %%cr2, %0" : "=r"(addr) : : "memory"); + + map_addr(addr, addr, FLAG_PRESENT | FLAG_WRITABLE | FLAG_HUGE); + + printf("address: 0x%x, error code: %d\n", addr, error); } -- cgit v1.2.3