瀏覽代碼

feat: page mapping

fix: buggy memset and memcpy not copying every byte
chore: global searching
fix: move exception handlers to tty_print
change: add new types related to paging:
        page_t pt_i_t etc.
greatbridf 2 年之前
父節點
當前提交
c4c0c61e6b

+ 12 - 0
global_find.sh

@@ -0,0 +1,12 @@
+#!/bin/sh
+
+# $1: text to find
+# $2: file extension
+do_find()
+{
+    for ext in $2; do
+        find src include -name "*.$ext" -exec grep -n -H -T -i "$1" {} \;
+    done
+}
+
+do_find "$1" "c h cpp hpp s"

+ 3 - 0
include/asm/boot.h

@@ -2,6 +2,9 @@
 
 #include <types/stdint.h>
 
+#define KERNEL_EARLY_STACK_ADDR ((phys_ptr_t)0x03fffff0)
+#define KERNEL_EARLY_STACK_SIZE ((size_t) 0xfffff0)
+
 struct __attribute__((__packed__)) gdt_descriptor {
     uint16_t size;
     uint32_t address;

+ 1 - 0
include/kernel/errno.h

@@ -8,3 +8,4 @@ extern uint32_t* _get_errno(void);
 
 #define ENOMEM 0
 #define ENOTFOUND 1
+#define EEXIST (1 << 1)

+ 2 - 3
include/kernel/mem.h

@@ -78,7 +78,7 @@ struct page_directory_entry_in {
     uint32_t d : 1;
     uint32_t ps : 1;
     uint32_t ignored : 4;
-    uint32_t addr : 20;
+    page_t addr : 20;
 };
 
 typedef union page_directory_entry {
@@ -111,7 +111,7 @@ struct page_table_entry_in {
     uint32_t pat : 1;
     uint32_t g : 1;
     uint32_t ignored : 3;
-    uint32_t addr : 20;
+    page_t addr : 20;
 };
 
 typedef union page_table_entry {
@@ -120,7 +120,6 @@ typedef union page_table_entry {
 } page_table_entry;
 
 #define KERNEL_PAGE_DIRECTORY_ADDR ((page_directory_entry*)0x00000000)
-#define KERNEL_PAGE_TABLE_START_ADDR ((page_table_entry*)0x00100000)
 
 void init_paging(void);
 

+ 1 - 0
include/kernel/stdio.h

@@ -15,6 +15,7 @@ extern "C" {
 #endif
 
 void* memcpy(void* dst, const void* src, size_t n);
+void* memset(void* dst, int c, size_t n);
 size_t strlen(const char* str);
 char* strncpy(char* dst, const char* src, size_t max_n);
 

+ 2 - 0
include/kernel_main.h

@@ -5,4 +5,6 @@
 #define KERNEL_STACK_SIZE (16 * 1024)
 #define KERNEL_STACK_SEGMENT (0x10)
 
+#define KERNEL_START_ADDR (0x00100000)
+
 void kernel_main(void);

+ 3 - 0
include/types/size.h

@@ -14,3 +14,6 @@ typedef int64_t diff_t;
 
 typedef ptr_t phys_ptr_t;
 typedef ptr_t virt_ptr_t;
+typedef size_t page_t;
+typedef size_t pd_i_t;
+typedef size_t pt_i_t;

+ 3 - 0
src/kernel/event/event.cpp

@@ -24,6 +24,9 @@ void dispatch_event(void)
     char buf[1024];
     auto& input_event_queue = event::input_event_queue();
 
+    char* ptr = (char*)0x8000000;
+    *ptr = 0xff;
+
     while (!input_event_queue.empty()) {
         for (auto iter = input_event_queue.begin(); iter != input_event_queue.end(); ++iter) {
             const auto& item = *iter;

+ 10 - 18
src/kernel/interrupt.c

@@ -5,6 +5,7 @@
 #include <kernel/hw/timer.h>
 #include <kernel/interrupt.h>
 #include <kernel/stdio.h>
+#include <kernel/tty.h>
 #include <kernel/vga.h>
 #include <kernel_main.h>
 
@@ -67,8 +68,7 @@ void int6_handler(
 {
     char buf[512];
 
-    // TODO: change to tty
-    vga_print("---- INVALID OPCODE ----\n", 0x0fu);
+    tty_print(console, "---- INVALID OPCODE ----\n");
 
     snprintf(
         buf, 512,
@@ -79,11 +79,9 @@ void int6_handler(
         s_regs.edx, s_regs.esp, s_regs.ebp,
         s_regs.esi, s_regs.edi, eip,
         cs, error_code);
-    // TODO: change to tty
-    vga_print(buf, 0x0fu);
+    tty_print(console, buf);
 
-    // TODO: change to tty
-    vga_print("----   HALTING SYSTEM   ----", 0x0fu);
+    tty_print(console, "----   HALTING SYSTEM   ----");
 
     asm_cli();
     asm_hlt();
@@ -99,8 +97,7 @@ void int13_handler(
 {
     char buf[512];
 
-    // TODO: change to tty
-    vga_print("---- SEGMENTATION FAULT ----\n", 0x0fu);
+    tty_print(console, "---- SEGMENTATION FAULT ----\n");
 
     snprintf(
         buf, 512,
@@ -112,11 +109,9 @@ void int13_handler(
         s_regs.edx, s_regs.esp, s_regs.ebp,
         s_regs.esi, s_regs.edi, eip,
         cs, error_code, eflags);
-    // TODO: change to tty
-    vga_print(buf, 0x0fu);
+    tty_print(console, buf);
 
-    // TODO: change to tty
-    vga_print("----   HALTING SYSTEM   ----", 0x0fu);
+    tty_print(console, "----   HALTING SYSTEM   ----");
 
     asm_cli();
     asm_hlt();
@@ -133,8 +128,7 @@ void int14_handler(
 {
     char buf[512];
 
-    // TODO: change to tty
-    vga_print("---- PAGE FAULT ----\n", 0x0fu);
+    tty_print(console, "---- PAGE FAULT ----\n");
 
     snprintf(
         buf, 512,
@@ -146,11 +140,9 @@ void int14_handler(
         s_regs.edx, s_regs.esp, s_regs.ebp,
         s_regs.esi, s_regs.edi, eip,
         cs, error_code, eflags, addr);
-    // TODO: change to tty
-    vga_print(buf, 0x0fu);
+    tty_print(console, buf);
 
-    // TODO: change to tty
-    vga_print("----   HALTING SYSTEM   ----", 0x0fu);
+    tty_print(console, "----   HALTING SYSTEM   ----");
 
     asm_cli();
     asm_hlt();

+ 179 - 34
src/kernel/mem.c

@@ -3,6 +3,7 @@
 #include <asm/sys.h>
 #include <kernel/errno.h>
 #include <kernel/mem.h>
+#include <kernel/stdio.h>
 #include <kernel/task.h>
 #include <kernel/vga.h>
 #include <kernel_main.h>
@@ -162,17 +163,37 @@ void k_free(void* ptr)
     // TODO: fusion free blocks nearby
 }
 
-static inline size_t addr_to_page(phys_ptr_t p)
+static inline page_t phys_addr_to_page(phys_ptr_t ptr)
 {
-    return p >> 12;
+    return ptr >> 12;
 }
 
-static inline void mark_page(size_t n)
+static inline pd_i_t page_to_pd_i(page_t p)
+{
+    return p >> 10;
+}
+
+static inline pt_i_t page_to_pt_i(page_t p)
+{
+    return p & (1024-1);
+}
+
+static inline phys_ptr_t page_to_phys_addr(page_t p)
+{
+    return p << 12;
+}
+
+static inline pd_i_t phys_addr_to_pd_i(phys_ptr_t ptr)
+{
+    return page_to_pd_i(phys_addr_to_page(ptr));
+}
+
+static inline void mark_page(page_t n)
 {
     bm_set(mem_bitmap, n);
 }
 
-static inline void free_page(size_t n)
+static inline void free_page(page_t n)
 {
     bm_clear(mem_bitmap, n);
 }
@@ -180,18 +201,18 @@ static inline void free_page(size_t 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)
+    page_t start_page = phys_addr_to_page(start);
+    page_t end_page   = phys_addr_to_page(start + n + 4095);
+    for (page_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)
+    page_t start_page = phys_addr_to_page(start);
+    page_t end_page   = phys_addr_to_page(start + n + 4095);
+    for (page_t i = start_page; i < end_page; ++i)
         free_page(i);
 }
 
@@ -207,7 +228,7 @@ static inline void free_addr_range(phys_ptr_t start, phys_ptr_t end)
 
 static int alloc_page(void)
 {
-    for (size_t i = 0; i < 1024 * 1024; ++i) {
+    for (page_t i = 0; i < 1024 * 1024; ++i) {
         if (bm_test(mem_bitmap, i) == 0) {
             mark_page(i);
             return i;
@@ -219,48 +240,172 @@ static int alloc_page(void)
 // allocate ONE whole page
 static phys_ptr_t _k_p_malloc(void)
 {
-    return (phys_ptr_t)(alloc_page() << 12);
+    return page_to_phys_addr(alloc_page());
 }
 
 static void _k_p_free(phys_ptr_t ptr)
 {
-    free_page(addr_to_page(ptr));
+    free_page(phys_addr_to_page(ptr));
 }
 
-static inline void _create_pd(page_directory_entry* pde)
+static inline void create_pd(page_directory_entry* pde)
 {
+    for (int i = 0; i < 1024; ++i)
+    {
+        pde->v = 0;
+        ++pde;
+    }
 }
 
 static page_directory_entry* _kernel_pd = KERNEL_PAGE_DIRECTORY_ADDR;
 
-static inline void _create_kernel_pt(page_table_entry* pt, int32_t index)
+// map n pages from p_ptr to v_ptr
+// p_ptr and v_ptr needs to be 4kb-aligned
+static int p_map(
+        page_directory_entry* pd,
+        phys_ptr_t p_ptr,
+        virt_ptr_t v_ptr,
+        size_t n,
+        int rw,
+        int priv);
+
+// map n pages
+static inline int p_n_map(
+        page_directory_entry* pd,
+        phys_ptr_t p_ptr,
+        virt_ptr_t v_ptr,
+        size_t n,
+        int rw,
+        int priv);
+
+// map n bytes identically
+static inline int _p_ident_n_map(
+        page_directory_entry* pd,
+        phys_ptr_t p_ptr,
+        size_t n,
+        int rw,
+        int priv);
+
+static inline void make_page_table(page_directory_entry* pd, page_t p)
 {
-    // 0x00000000 ~ 0x3fffffff is mapped as kernel space
-    // from physical address 0 to
-    int32_t is_kernel = (index < 256);
+    phys_ptr_t pp_pt = page_to_phys_addr(p);
 
-    for (int32_t i = 0; i < 1024; ++i) {
-        if (is_kernel) {
-            pt[i].v = 0b00000011;
-        } else {
-            pt[i].v = 0b00000111;
+    page_table_entry* pt = (page_table_entry*)pp_pt;
+
+    memset(pt, 0x00, sizeof(page_table_entry) * 1024);
+
+    _p_ident_n_map(
+            pd,
+            pp_pt,
+            sizeof(page_table_entry) * 1024, 1, 1
+            );
+}
+
+// map n pages from p_ptr to v_ptr
+// p_ptr and v_ptr needs to be 4kb-aligned
+static int p_map(
+        page_directory_entry* pd,
+        phys_ptr_t p_ptr,
+        virt_ptr_t v_ptr,
+        size_t n,
+        int rw,
+        int priv)
+{
+    // pages to be mapped
+    page_t v_page_start = phys_addr_to_page(v_ptr);
+    page_t v_page_end   = v_page_start + n;
+
+    for (pd_i_t pde_index = page_to_pd_i(v_page_start); pde_index <= page_to_pd_i(v_page_end); ++pde_index)
+    {
+        // page table not present
+        if (pd[pde_index].in.p != 1)
+        {
+            pd[pde_index].in.p = 1;
+            pd[pde_index].in.a = 0;
+            pd[pde_index].in.rw = 1;
+            page_t p_page = alloc_page();
+            pd[pde_index].in.addr = p_page;
+            make_page_table(pd, p_page);
         }
-        pt[i].in.addr = ((index * 0x400000) + i * 0x1000) >> 12;
     }
+
+    for (size_t i = 0; i < n; ++i)
+    {
+        page_t v_page = v_page_start + i;
+        pd_i_t pd_i = page_to_pd_i(v_page);
+        page_table_entry* pt = (page_table_entry*) page_to_phys_addr(pd[pd_i].in.addr);
+        pt += page_to_pt_i(v_page);
+
+        if (pt->in.p == 1)
+        {
+            errno = EEXIST;
+            return GB_FAILED;
+        }
+        pt->in.p = 1;
+        pt->in.rw = (rw == 1);
+        pt->in.us = !(priv == 1);
+        pt->in.a = 0;
+        pt->in.d = 0;
+
+        pt->in.addr = phys_addr_to_page(p_ptr) + i;
+    }
+
+    return GB_OK;
+}
+
+// map n pages
+static inline int p_n_map(
+        page_directory_entry* pd,
+        phys_ptr_t p_ptr,
+        virt_ptr_t v_ptr,
+        size_t n,
+        int rw,
+        int priv)
+{
+    return p_map(
+            pd,
+            p_ptr,
+            v_ptr,
+            (n + 4096 - 1) >> 12,
+            rw,
+            priv
+            );
+}
+
+// map n bytes identically
+static inline int _p_ident_n_map(
+        page_directory_entry* pd,
+        phys_ptr_t p_ptr,
+        size_t n,
+        int rw,
+        int priv)
+{
+    return p_n_map(
+            pd,
+            p_ptr,
+            p_ptr,
+            n,
+            rw,
+            priv
+            );
 }
 
 static inline void _create_kernel_pd(void)
 {
-    for (int32_t i = 0; i < 1024; ++i) {
-        if (i < 256) {
-            _kernel_pd[i].v = 0b00000011;
-        } else {
-            _kernel_pd[i].v = 0b00000111;
-        }
-        page_table_entry* pt = (page_table_entry*)_k_p_malloc();
-        _kernel_pd[i].in.addr = ((size_t)pt >> 12);
-        _create_kernel_pt(pt, i);
-    }
+    create_pd(_kernel_pd);
+
+    _p_ident_n_map(_kernel_pd,
+            (phys_ptr_t)KERNEL_PAGE_DIRECTORY_ADDR,
+            sizeof(page_directory_entry) * 1024, 1, 1);
+    _p_ident_n_map(_kernel_pd,
+            (0x00080000),
+            (0xfffff - 0x80000 + 1), 1, 1);
+    _p_ident_n_map(_kernel_pd,
+            KERNEL_START_ADDR,
+            kernel_size, 1, 1);
+    _p_ident_n_map(_kernel_pd,
+            KERNEL_EARLY_STACK_ADDR - KERNEL_EARLY_STACK_SIZE,
+            KERNEL_EARLY_STACK_SIZE, 1, 1);
 }
 
 static void init_mem_layout(void)

+ 17 - 1
src/kernel/stdio.c

@@ -417,7 +417,9 @@ void* memcpy(void* dst, const void* src, size_t n)
 {
     void* orig_dst = dst;
     for (size_t i = 0; i < n / BYTES_PER_MAX_COPY_UNIT; ++i) {
-        *((uint32_t*)dst++) = *((uint32_t*)src++);
+        *(uint32_t*)dst = *(uint32_t*)src;
+        dst += BYTES_PER_MAX_COPY_UNIT;
+        src += BYTES_PER_MAX_COPY_UNIT;
     }
     for (size_t i = 0; i < (n % BYTES_PER_MAX_COPY_UNIT); ++i) {
         *((char*)dst++) = *((char*)src++);
@@ -425,6 +427,20 @@ void* memcpy(void* dst, const void* src, size_t n)
     return orig_dst;
 }
 
+void* memset(void* dst, int c, size_t n)
+{
+    c &= 0xff;
+    int cc = (c + (c << 8) + (c << 16) + (c << 24));
+    for (size_t i = 0; i < n / BYTES_PER_MAX_COPY_UNIT; ++i) {
+        *(uint32_t*)dst = cc;
+        dst += BYTES_PER_MAX_COPY_UNIT;
+    }
+    for (size_t i = 0; i < (n % BYTES_PER_MAX_COPY_UNIT); ++i) {
+        *((char*)dst++) = c;
+    }
+    return dst;
+}
+
 size_t strlen(const char* str)
 {
     size_t n = 0;

+ 13 - 19
src/kernel_main.c

@@ -93,29 +93,23 @@ static inline void show_mem_info(char* buf)
     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);
-            }
+            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(
+                "[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);