Procházet zdrojové kódy

feat: allocate pages for page tables (BROKEN)

greatbridf před 2 roky
rodič
revize
2396f6a355

+ 2 - 14
include/asm/boot.h

@@ -11,22 +11,10 @@ extern struct gdt_descriptor asm_gdt_descriptor;
 
 extern uint32_t check_a20_on(void);
 
-struct e820_mem_map_entry_20 {
-    uint64_t base;
-    uint64_t len;
-    uint32_t type;
-};
-
-struct e820_mem_map_entry_24 {
-    struct e820_mem_map_entry_20 in;
-    uint32_t acpi_extension_attr;
-};
+extern struct mem_size_info asm_mem_size_info;
 
 extern uint8_t asm_e820_mem_map[1024];
 extern uint32_t asm_e820_mem_map_count;
 extern uint32_t asm_e820_mem_map_entry_size;
 
-extern uint32_t kernel_size;
-
-#define e820_mem_map_20 ((struct e820_mem_map_entry_20*)asm_e820_mem_map)
-#define e820_mem_map_24 ((struct e820_mem_map_entry_24*)asm_e820_mem_map)
+extern uint32_t asm_kernel_size;

+ 2 - 0
include/asm/sys.h

@@ -13,6 +13,8 @@ void asm_load_gdt(uint32_t limit, uint32_t addr);
 
 void asm_load_tr(uint16_t index);
 
+extern void* __real_kernel_end;
+
 #ifdef __cplusplus
 }
 #endif

+ 17 - 1
include/kernel/mem.h

@@ -12,7 +12,23 @@ struct mem_size_info {
     uint16_t n_64k_blks; // memory above 16m in 64k blocks
 };
 
-extern struct mem_size_info asm_mem_size_info;
+struct e820_mem_map_entry_20 {
+    uint64_t base;
+    uint64_t len;
+    uint32_t type;
+};
+
+struct e820_mem_map_entry_24 {
+    struct e820_mem_map_entry_20 in;
+    uint32_t acpi_extension_attr;
+};
+
+// in kernel_main.c
+extern uint8_t e820_mem_map[1024];
+extern uint32_t e820_mem_map_count;
+extern uint32_t e820_mem_map_entry_size;
+extern uint32_t kernel_size;
+extern struct mem_size_info mem_size_info;
 
 // TODO: decide heap start address according
 //   to user's memory size

+ 3 - 12
include/types/bitmap.h

@@ -2,15 +2,6 @@
 
 #include <types/stdint.h>
 
-#define BITMAP_UNDERLYING_TYPE char
-
-struct bitmap {
-    size_t size;
-    BITMAP_UNDERLYING_TYPE v[];
-};
-
-size_t make_bm_size(size_t n);
-
-int bm_test(struct bitmap* bm, size_t n);
-void bm_set(struct bitmap* bm, size_t n);
-void bm_clear(struct bitmap* bm, size_t n);
+int bm_test(char* bm, size_t n);
+void bm_set(char* bm, size_t n);
+void bm_clear(char* bm, size_t n);

+ 3 - 0
include/types/size.h

@@ -11,3 +11,6 @@ typedef int32_t diff_t;
 typedef uint64_t ptr_t;
 typedef int64_t diff_t;
 #endif
+
+typedef ptr_t phys_ptr_t;
+typedef ptr_t virt_ptr_t;

+ 1 - 1
ldscript.ld

@@ -36,7 +36,7 @@ SECTIONS
 
     .data :
     {
-        kernel_size = .;
+        asm_kernel_size = .;
         LONG(__real_kernel_end - ADDR(.text));
 
         start_ctors = .;

+ 111 - 11
src/kernel/mem.c

@@ -6,6 +6,7 @@
 #include <kernel/task.h>
 #include <kernel/vga.h>
 #include <kernel_main.h>
+#include <types/bitmap.h>
 
 static void* p_start;
 static void* p_break;
@@ -14,6 +15,9 @@ static segment_descriptor* gdt;
 // temporary
 static struct tss32_t _tss;
 
+static size_t mem_size;
+static char mem_bitmap[1024 * 1024 / 8];
+
 static int32_t set_heap_start(void* start_addr)
 {
     p_start = start_addr;
@@ -158,22 +162,82 @@ void k_free(void* ptr)
     // TODO: fusion free blocks nearby
 }
 
+static inline size_t addr_to_page(phys_ptr_t p)
+{
+    return p >> 12;
+}
+
+static inline void mark_page(size_t n)
+{
+    bm_set(mem_bitmap, n);
+}
+
+static inline void free_page(size_t n)
+{
+    bm_clear(mem_bitmap, n);
+}
+
+static void mark_addr_len(phys_ptr_t start, size_t n)
+{
+    if (n == 0) return;
+    size_t start_page = addr_to_page(start);
+    size_t end_page   = addr_to_page(start + n + 4095);
+    for (uint32_t i = start_page; i < end_page; ++i)
+        mark_page(i);
+}
+
+static void free_addr_len(phys_ptr_t start, size_t n)
+{
+    if (n == 0) return;
+    size_t start_page = (start >> 12);
+    size_t end_page   = ((start + n + 4095) >> 12);
+    for (uint32_t i = start_page; i < end_page; ++i)
+        free_page(i);
+}
+
+static inline void mark_addr_range(phys_ptr_t start, phys_ptr_t end)
+{
+    mark_addr_len(start, end - start);
+}
+
+static inline void free_addr_range(phys_ptr_t start, phys_ptr_t end)
+{
+    free_addr_len(start, end - start);
+}
+
+static int alloc_page(void)
+{
+    for (size_t i = 0; i < 1024 * 1024; ++i) {
+        if (bm_test(mem_bitmap, i) == 0) {
+            mark_page(i);
+            return i;
+        }
+    }
+    return GB_FAILED;
+}
+
+// allocate ONE whole page
+static phys_ptr_t _k_p_malloc(void)
+{
+    return (phys_ptr_t)(alloc_page() << 12);
+}
+
+static void _k_p_free(phys_ptr_t ptr)
+{
+    free_page(addr_to_page(ptr));
+}
+
 static inline void _create_pd(page_directory_entry* pde)
 {
 }
 
 static page_directory_entry* _kernel_pd = KERNEL_PAGE_DIRECTORY_ADDR;
 
-static inline void _create_kernel_pt(int32_t index)
+static inline void _create_kernel_pt(page_table_entry* pt, int32_t index)
 {
-    page_table_entry* pt = KERNEL_PAGE_TABLE_START_ADDR + index * 0x1000;
-
-    // 0xc0000000 ~ 0xffffffff is mapped as kernel space
+    // 0x00000000 ~ 0x3fffffff is mapped as kernel space
     // from physical address 0 to
-    int32_t is_kernel = (index >= 768);
-    if (is_kernel) {
-        index -= 768;
-    }
+    int32_t is_kernel = (index < 256);
 
     for (int32_t i = 0; i < 1024; ++i) {
         if (is_kernel) {
@@ -188,18 +252,52 @@ static inline void _create_kernel_pt(int32_t index)
 static inline void _create_kernel_pd(void)
 {
     for (int32_t i = 0; i < 1024; ++i) {
-        if (i >= 768) {
+        if (i < 256) {
             _kernel_pd[i].v = 0b00000011;
         } else {
             _kernel_pd[i].v = 0b00000111;
         }
-        _kernel_pd[i].in.addr = ((uint32_t)(KERNEL_PAGE_TABLE_START_ADDR + i * 0x1000) >> 12);
-        _create_kernel_pt(i);
+        page_table_entry* pt = (page_table_entry*)_k_p_malloc();
+        _kernel_pd[i].in.addr = ((size_t)pt >> 12);
+        _create_kernel_pt(pt, i);
+    }
+}
+
+static void init_mem_layout(void)
+{
+    mem_size = 1024 * mem_size_info.n_1k_blks;
+    mem_size += 64 * 1024 * mem_size_info.n_64k_blks;
+
+    // mark kernel page directory
+    mark_addr_range(0x00000000, 0x00001000);
+    // mark EBDA and upper memory as allocated
+    mark_addr_range(0x80000, 0xfffff);
+    // mark kernel
+    mark_addr_len(0x00100000, kernel_size);
+
+    if (e820_mem_map_entry_size == 20) {
+        struct e820_mem_map_entry_20* entry = (struct e820_mem_map_entry_20*)e820_mem_map;
+        for (uint32_t i = 0; i < e820_mem_map_count; ++i, ++entry) {
+            if (entry->type != 1)
+            {
+                mark_addr_len(entry->base, entry->len);
+            }
+        }
+    } else {
+        struct e820_mem_map_entry_24* entry = (struct e820_mem_map_entry_24*)e820_mem_map;
+        for (uint32_t i = 0; i < e820_mem_map_count; ++i, ++entry) {
+            if (entry->in.type != 1)
+            {
+                mark_addr_len(entry->in.base, entry->in.len);
+            }
+        }
     }
 }
 
 void init_paging(void)
 {
+    init_mem_layout();
+
     _create_kernel_pd();
     asm_enable_paging(_kernel_pd);
 }
@@ -223,6 +321,8 @@ set_segment_descriptor(
 
 void init_gdt_with_tss(void* kernel_esp, uint16_t kernel_ss)
 {
+    // TODO: fix this
+    return;
     gdt = k_malloc(sizeof(segment_descriptor) * 6);
     // since the size in the struct is an OFFSET
     // it needs to be added one to get its real size

+ 1 - 1
src/kernel/tty.c

@@ -36,7 +36,7 @@ void tty_print(struct tty* p_tty, const char* str)
 int make_serial_tty(struct tty* p_tty, int id)
 {
     *(port_id_t*)&p_tty->data = id;
-    snprintf(p_tty->name, sizeof(p_tty->name), "ttyS%d", id);
+    snprintf(p_tty->name, sizeof(p_tty->name), "ttyS%x", id);
     p_tty->ops = &serial_tty_ops;
     return GB_OK;
 }

+ 67 - 49
src/kernel_main.c

@@ -36,47 +36,6 @@ static struct tty* console = NULL;
 #define INIT_OK() printkf("ok\n")
 #define INIT_FAILED() printkf("failed\n")
 
-static inline void show_mem_info(char* buf)
-{
-    uint32_t mem_size = 0;
-    mem_size += 1024 * asm_mem_size_info.n_1k_blks;
-    mem_size += 64 * 1024 * asm_mem_size_info.n_64k_blks;
-
-    printkf(
-        "Memory size: %d bytes (%d MB), 16k blocks: %d, 64k blocks: %d\n",
-        mem_size,
-        mem_size / 1024 / 1024,
-        (int32_t)asm_mem_size_info.n_1k_blks,
-        (int32_t)asm_mem_size_info.n_64k_blks);
-
-    printkf(
-        "mem_map_entry_count: %d , mem_map_entry_size: %d \n",
-        asm_e820_mem_map_count,
-        asm_e820_mem_map_entry_size);
-
-    if (asm_e820_mem_map_entry_size == 20) {
-        for (uint32_t i = 0; i < asm_e820_mem_map_count; ++i) {
-            printkf(
-                "[mem] entry %d: %llx ~ %llx, type: %d\n",
-                i,
-                e820_mem_map_20[i].base,
-                e820_mem_map_20[i].base + e820_mem_map_20[i].len,
-                e820_mem_map_20[i].type);
-        }
-    } else {
-        for (uint32_t i = 0; i < asm_e820_mem_map_count; ++i) {
-            printkf(
-                "[mem] entry %d: %lld ~ %lld, type: %d, acpi_attr: %d\n",
-                i,
-                e820_mem_map_24[i].in.base,
-                e820_mem_map_24[i].in.base + e820_mem_map_24[i].in.len,
-                e820_mem_map_24[i].in.type,
-                e820_mem_map_24[i].acpi_extension_attr);
-        }
-    }
-    printkf("kernel size: %x\n", kernel_size);
-}
-
 static inline void check_a20_status(void)
 {
     uint32_t result;
@@ -97,12 +56,79 @@ static inline void halt_on_init_error(void)
         asm_hlt();
 }
 
+uint8_t e820_mem_map[1024];
+uint32_t e820_mem_map_count;
+uint32_t e820_mem_map_entry_size;
+size_t kernel_size;
+struct mem_size_info mem_size_info;
+
+static inline void save_loader_data(void)
+{
+    memcpy(e820_mem_map, asm_e820_mem_map, sizeof(e820_mem_map));
+    e820_mem_map_count = asm_e820_mem_map_count;
+    e820_mem_map_entry_size = asm_e820_mem_map_entry_size;
+    kernel_size = asm_kernel_size;
+    memcpy(&mem_size_info, &asm_mem_size_info, sizeof(struct mem_size_info));
+}
+
+static inline void show_mem_info(char* buf)
+{
+    uint32_t mem_size = 0;
+    mem_size += 1024 * mem_size_info.n_1k_blks;
+    mem_size += 64 * 1024 * mem_size_info.n_64k_blks;
+
+    printkf(
+        "Memory size: %d bytes (%d MB), 16k blocks: %d, 64k blocks: %d\n",
+        mem_size,
+        mem_size / 1024 / 1024,
+        (int32_t)mem_size_info.n_1k_blks,
+        (int32_t)mem_size_info.n_64k_blks);
+
+    printkf(
+        "mem_map_entry_count: %d , mem_map_entry_size: %d \n",
+        e820_mem_map_count,
+        e820_mem_map_entry_size);
+
+    if (e820_mem_map_entry_size == 20) {
+        struct e820_mem_map_entry_20* entry = (struct e820_mem_map_entry_20*)e820_mem_map;
+        for (uint32_t i = 0; i < e820_mem_map_count; ++i, ++entry) {
+            if (entry->type != 1)
+            {
+                printkf(
+                    "[mem] entry %d: %llx ~ %llx, type: %d\n",
+                    i,
+                    entry->base,
+                    entry->base + entry->len,
+                    entry->type);
+            }
+        }
+    } else {
+        struct e820_mem_map_entry_24* entry = (struct e820_mem_map_entry_24*)e820_mem_map;
+        for (uint32_t i = 0; i < e820_mem_map_count; ++i, ++entry) {
+            if (entry->in.type != 1)
+            {
+                printkf(
+                    "[mem] entry %d: %lld ~ %lld, type: %d, acpi_attr: %d\n",
+                    i,
+                    entry->in.base,
+                    entry->in.base + entry->in.len,
+                    entry->in.type,
+                    entry->acpi_extension_attr);
+            }
+        }
+    }
+    printkf("kernel size: %x\n", kernel_size);
+}
+
 void kernel_main(void)
 {
     MAKE_BREAK_POINT();
+    save_loader_data();
 
     char buf[KERNEL_MAIN_BUF_SIZE];
 
+    init_serial_port(PORT_SERIAL0);
+
     struct tty early_console;
     if (make_serial_tty(&early_console, PORT_SERIAL0) != GB_OK) {
         halt_on_init_error();
@@ -142,14 +168,6 @@ void kernel_main(void)
     // vga_printk(k_malloc_buf, 0x0fu);
     k_free(k_malloc_buf);
 
-    INIT_START("serial ports");
-    int result = init_serial_port(PORT_SERIAL0);
-    if (result == 0) {
-        INIT_OK();
-    } else {
-        INIT_FAILED();
-    }
-
     void* kernel_stack = k_malloc(KERNEL_STACK_SIZE);
     init_gdt_with_tss(kernel_stack + KERNEL_STACK_SIZE - 1, KERNEL_STACK_SEGMENT);
     printkf("new GDT and TSS loaded\n");

+ 7 - 8
src/types/bitmap.c

@@ -1,23 +1,22 @@
 #include <types/bitmap.h>
 
-#define B_TYPE BITMAP_UNDERLYING_TYPE
-#define SZ (sizeof(B_TYPE) * 8)
+#define SZ (8)
 
 size_t make_bm_size(size_t n)
 {
     return sizeof(size_t) + (n / SZ) + ((n % SZ) ? 1 : 0);
 }
 
-int bm_test(struct bitmap* bm, size_t n)
+int bm_test(char* bm, size_t n)
 {
-    return (bm->v[n / SZ] & (1 << (n % SZ))) != 0;
+    return (bm[n / SZ] & (1 << (n % SZ))) != 0;
 }
 
-void bm_set(struct bitmap* bm, size_t n)
+void bm_set(char* bm, size_t n)
 {
-    bm->v[n / SZ] |= (1 << (n % SZ));
+    bm[n / SZ] |= (1 << (n % SZ));
 }
-void bm_clear(struct bitmap* bm, size_t n)
+void bm_clear(char* bm, size_t n)
 {
-    bm->v[n / SZ] &= (~(1 << (n % SZ)));
+    bm[n / SZ] &= (~(1 << (n % SZ)));
 }