فهرست منبع

refactor: 拆分mem和mm,对interrupt使用cpp

greatbridf 2 سال پیش
والد
کامیت
90cc9522ab

+ 3 - 3
CMakeLists.txt

@@ -41,7 +41,7 @@ include_directories(${PROJECT_SOURCE_DIR}/include)
 
 set(KERNEL_MAIN_SOURCES src/kernel_main.c
                         src/kernel/errno.c
-                        src/kernel/interrupt.c
+                        src/kernel/interrupt.cpp
                         src/kernel/process.c
                         src/kernel/tty.c
                         src/kernel/stdio.c
@@ -63,7 +63,8 @@ set(KERNEL_MAIN_SOURCES src/kernel_main.c
                         include/kernel/interrupt.h
                         include/kernel/process.h
                         include/kernel/stdio.h
-                        include/kernel/mem.hpp
+                        include/kernel/mem.h
+                        include/kernel/mm.hpp
                         include/kernel/vfs.h
                         include/kernel/vga.h
                         include/kernel/hw/keyboard.h
@@ -77,7 +78,6 @@ set(KERNEL_MAIN_SOURCES src/kernel_main.c
                         include/types/size.h
                         include/types/status.h
                         include/types/stdint.h
-                        include/types/list.h
                         include/types/allocator.hpp
                         include/types/cplusplus.hpp
                         include/types/list.hpp

+ 1 - 1
include/asm/sys.h

@@ -1,6 +1,6 @@
 #pragma once
 
-#include <kernel/mem.hpp>
+#include <kernel/mem.h>
 #include <types/types.h>
 
 #ifdef __cplusplus

+ 2 - 2
include/kernel/errno.h

@@ -14,10 +14,10 @@ extern uint32_t* _get_errno(void);
 }
 #endif
 
-#define ENOMEM 0
-#define ENOTFOUND 1
+#define ENOMEM (1 << 0)
 #define EEXIST (1 << 1)
 #define ENOENT (1 << 2)
 #define EINVAL (1 << 3)
 #define EISDIR (1 << 4)
 #define ENOTDIR (1 << 5)
+#define ENOTFOUND (1 << 6)

+ 41 - 1
include/kernel/interrupt.h

@@ -2,6 +2,10 @@
 
 #include <types/types.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define INTERRUPT_GATE_TYPE (0x8e)
 
 #define PIC_EOI (0x20)
@@ -38,7 +42,6 @@ struct page_fault_error_code {
 // external interrupt handler function
 // stub in assembly MUST be called irqN
 #define SET_UP_IRQ(N, SELECTOR)        \
-    extern void irq##N();              \
     ptr_t addr_irq##N = (ptr_t)irq##N; \
     SET_IDT_ENTRY(0x20 + (N), (addr_irq##N), (SELECTOR));
 
@@ -105,3 +108,40 @@ void irq12_handler(void);
 void irq13_handler(void);
 void irq14_handler(void);
 void irq15_handler(void);
+
+void int0(void);
+void int1(void);
+void int2(void);
+void int3(void);
+void int4(void);
+void int5(void);
+void int6(void);
+void int7(void);
+void int8(void);
+void int9(void);
+void int10(void);
+void int11(void);
+void int12(void);
+void int13(void);
+void int14(void);
+
+void irq0(void);
+void irq1(void);
+void irq2(void);
+void irq3(void);
+void irq4(void);
+void irq5(void);
+void irq6(void);
+void irq7(void);
+void irq8(void);
+void irq9(void);
+void irq10(void);
+void irq11(void);
+void irq12(void);
+void irq13(void);
+void irq14(void);
+void irq15(void);
+
+#ifdef __cplusplus
+}
+#endif

+ 148 - 0
include/kernel/mem.h

@@ -0,0 +1,148 @@
+#pragma once
+
+#include <types/size.h>
+#include <types/stdint.h>
+
+#define PAGE_SIZE (4096)
+#define KERNEL_IDENTICALLY_MAPPED_AREA_LIMIT ((void*)0x30000000)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// don't forget to add the initial 1m to the total
+struct mem_size_info {
+    uint16_t n_1k_blks; // memory between 1m and 16m in 1k blocks
+    uint16_t n_64k_blks; // memory above 16m in 64k blocks
+};
+
+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;
+};
+
+/*
+ * page directory entry
+ *
+ * p   : present (1)
+ * rw  : allow write (1)
+ * us  : allow user access (1)
+ * pwt : todo
+ * pcd : todo
+ * a   : accessed for linear address translation (1)
+ * d   : dirty (1) (ignored)
+ * ps  : use 4MiB pages (ignored)
+ * addr: page table address
+ */
+struct page_directory_entry_in {
+    uint32_t p : 1;
+    uint32_t rw : 1;
+    uint32_t us : 1;
+    uint32_t pwt : 1;
+    uint32_t pcd : 1;
+    uint32_t a : 1;
+    uint32_t d : 1;
+    uint32_t ps : 1;
+    uint32_t ignored : 4;
+    page_t pt_page : 20;
+};
+
+typedef union page_directory_entry {
+    uint32_t v;
+    struct page_directory_entry_in in;
+} page_directory_entry;
+
+/*
+ * page table entry
+ *
+ * p   : present (1)
+ * rw  : allow write (1)
+ * us  : allow user access (1)
+ * pwt : todo
+ * pcd : todo
+ * a   : accessed for linear address translation (1)
+ * d   : dirty (1)
+ * pat : todo (ignored)
+ * g   : used in cr4 mode (ignored)
+ * addr: physical memory address
+ */
+struct page_table_entry_in {
+    uint32_t p : 1;
+    uint32_t rw : 1;
+    uint32_t us : 1;
+    uint32_t pwt : 1;
+    uint32_t pcd : 1;
+    uint32_t a : 1;
+    uint32_t d : 1;
+    uint32_t pat : 1;
+    uint32_t g : 1;
+    uint32_t ignored : 3;
+    page_t page : 20;
+};
+
+typedef union page_table_entry {
+    uint32_t v;
+    struct page_table_entry_in in;
+} page_table_entry;
+
+// 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 size_t kernel_size;
+extern struct mem_size_info mem_size_info;
+
+#define KERNEL_HEAP_START ((void*)0x30000000)
+#define KERNEL_HEAP_LIMIT ((void*)0x40000000)
+
+void* k_malloc(size_t size);
+
+void k_free(void* ptr);
+
+void* ki_malloc(size_t size);
+
+void ki_free(void* ptr);
+
+#define KERNEL_PAGE_DIRECTORY_ADDR ((page_directory_entry*)0x00000000)
+
+void init_mem(void);
+
+#define KERNEL_CODE_SEGMENT (0x08)
+#define KERNEL_DATA_SEGMENT (0x10)
+#define USER_CODE_SEGMENT (0x18)
+#define USER_DATA_SEGMENT (0x20)
+
+#define SD_TYPE_CODE_SYSTEM (0x9a)
+#define SD_TYPE_DATA_SYSTEM (0x92)
+
+#define SD_TYPE_CODE_USER (0xfa)
+#define SD_TYPE_DATA_USER (0xf2)
+
+#define SD_TYPE_TSS (0x89)
+
+typedef struct segment_descriptor_struct {
+    uint64_t limit_low : 16;
+    uint64_t base_low : 16;
+    uint64_t base_mid : 8;
+    uint64_t access : 8;
+    uint64_t limit_high : 4;
+    uint64_t flags : 4;
+    uint64_t base_high : 8;
+} segment_descriptor;
+
+void create_segment_descriptor(
+    segment_descriptor* sd,
+    uint32_t base,
+    uint32_t limit,
+    uint32_t flags,
+    uint32_t access);
+
+#ifdef __cplusplus
+}
+#endif

+ 0 - 290
include/kernel/mem.hpp

@@ -1,290 +0,0 @@
-#pragma once
-
-#include <types/size.h>
-#include <types/stdint.h>
-
-#define PAGE_SIZE (4096)
-#define KERNEL_IDENTICALLY_MAPPED_AREA_LIMIT ((void*)0x30000000)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// in mem.c
-extern struct mm* kernel_mm_head;
-
-// don't forget to add the initial 1m to the total
-struct mem_size_info {
-    uint16_t n_1k_blks; // memory between 1m and 16m in 1k blocks
-    uint16_t n_64k_blks; // memory above 16m in 64k blocks
-};
-
-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;
-};
-
-/*
- * page directory entry
- *
- * p   : present (1)
- * rw  : allow write (1)
- * us  : allow user access (1)
- * pwt : todo
- * pcd : todo
- * a   : accessed for linear address translation (1)
- * d   : dirty (1) (ignored)
- * ps  : use 4MiB pages (ignored)
- * addr: page table address
- */
-struct page_directory_entry_in {
-    uint32_t p : 1;
-    uint32_t rw : 1;
-    uint32_t us : 1;
-    uint32_t pwt : 1;
-    uint32_t pcd : 1;
-    uint32_t a : 1;
-    uint32_t d : 1;
-    uint32_t ps : 1;
-    uint32_t ignored : 4;
-    page_t pt_page : 20;
-};
-
-typedef union page_directory_entry {
-    uint32_t v;
-    struct page_directory_entry_in in;
-} page_directory_entry;
-
-/*
- * page table entry
- *
- * p   : present (1)
- * rw  : allow write (1)
- * us  : allow user access (1)
- * pwt : todo
- * pcd : todo
- * a   : accessed for linear address translation (1)
- * d   : dirty (1)
- * pat : todo (ignored)
- * g   : used in cr4 mode (ignored)
- * addr: physical memory address
- */
-struct page_table_entry_in {
-    uint32_t p : 1;
-    uint32_t rw : 1;
-    uint32_t us : 1;
-    uint32_t pwt : 1;
-    uint32_t pcd : 1;
-    uint32_t a : 1;
-    uint32_t d : 1;
-    uint32_t pat : 1;
-    uint32_t g : 1;
-    uint32_t ignored : 3;
-    page_t page : 20;
-};
-
-typedef union page_table_entry {
-    uint32_t v;
-    struct page_table_entry_in in;
-} page_table_entry;
-
-struct page_attr {
-    uint32_t read : 1;
-    uint32_t write : 1;
-    uint32_t system : 1;
-    uint32_t cow : 1;
-};
-
-struct page {
-    page_t phys_page_id;
-    size_t* ref_count;
-    struct page_attr attr;
-    struct page* next;
-};
-
-struct mm_attr {
-    uint32_t read : 1;
-    uint32_t write : 1;
-    uint32_t system : 1;
-};
-
-struct mm {
-    linr_ptr_t start;
-    size_t len;
-    struct mm_attr attr;
-    struct page* pgs;
-    struct mm* next;
-    page_directory_entry* pd;
-};
-
-// 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 size_t kernel_size;
-extern struct mem_size_info mem_size_info;
-
-#define KERNEL_HEAP_START ((void*)0x30000000)
-#define KERNEL_HEAP_LIMIT ((void*)0x40000000)
-
-struct mem_blk_flags {
-    uint8_t is_free;
-    uint8_t has_next;
-    uint8_t _unused2;
-    uint8_t _unused3;
-};
-
-struct mem_blk {
-    size_t size;
-    struct mem_blk_flags flags;
-    // the first byte of the memory space
-    // the minimal allocated space is 4 bytes
-    uint8_t data[4];
-};
-
-int init_heap(void);
-
-void* k_malloc(size_t size);
-
-void k_free(void* ptr);
-
-// translate physical address to virtual(mapped) address
-void* p_ptr_to_v_ptr(phys_ptr_t p_ptr);
-
-// translate linear address to physical address
-phys_ptr_t l_ptr_to_p_ptr(struct mm* mm_area, linr_ptr_t v_ptr);
-
-// translate virtual(mapped) address to physical address
-phys_ptr_t v_ptr_to_p_ptr(void* v_ptr);
-
-// check if the l_ptr is contained in the area
-// @return GB_OK if l_ptr is in the area
-//         GB_FAILED if not
-int is_l_ptr_valid(struct mm* mm_area, linr_ptr_t l_ptr);
-
-// find the corresponding page the l_ptr pointing to
-// @return the pointer to the struct if found, NULL if not found
-struct page* find_page_by_l_ptr(struct mm* mm_area, linr_ptr_t l_ptr);
-
-static inline page_t phys_addr_to_page(phys_ptr_t ptr)
-{
-    return ptr >> 12;
-}
-
-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 linr_addr_to_pd_i(linr_ptr_t ptr)
-{
-    return page_to_pd_i(phys_addr_to_page(ptr));
-}
-
-static inline pd_i_t linr_addr_to_pt_i(linr_ptr_t ptr)
-{
-    return page_to_pt_i(phys_addr_to_page(ptr));
-}
-
-static inline page_directory_entry* lptr_to_pde(struct mm* mm, linr_ptr_t l_ptr)
-{
-    return mm->pd + linr_addr_to_pd_i((phys_ptr_t)l_ptr);
-}
-
-static inline page_table_entry* lptr_to_pte(struct mm* mm, linr_ptr_t l_ptr)
-{
-    page_directory_entry* pde = lptr_to_pde(mm, l_ptr);
-    page_table_entry* pte = (page_table_entry*)p_ptr_to_v_ptr(page_to_phys_addr(pde->in.pt_page));
-    return pte + linr_addr_to_pt_i((phys_ptr_t)l_ptr);
-}
-
-static inline page_directory_entry* lp_to_pde(struct mm* mm, linr_ptr_t l_ptr)
-{
-    phys_ptr_t p_ptr = l_ptr_to_p_ptr(mm, l_ptr);
-    page_directory_entry* pde = mm->pd + linr_addr_to_pd_i(p_ptr);
-    return pde;
-}
-
-// get the corresponding pte for the linear address
-// for example: l_ptr = 0x30001000 will return the pte including the page it is mapped to
-static inline page_table_entry* lp_to_pte(struct mm* mm, linr_ptr_t l_ptr)
-{
-    phys_ptr_t p_ptr = l_ptr_to_p_ptr(mm, l_ptr);
-
-    page_directory_entry* pde = lp_to_pde(mm, l_ptr);
-    phys_ptr_t p_pt = page_to_phys_addr(pde->in.pt_page);
-
-    page_table_entry* pte = (page_table_entry*)p_ptr_to_v_ptr(p_pt);
-    pte += linr_addr_to_pt_i(p_ptr);
-
-    return pte;
-}
-
-// map the page to the end of the mm_area in pd
-int k_map(
-    struct mm* mm_area,
-    struct page* page,
-    int read,
-    int write,
-    int priv,
-    int cow);
-
-// allocate a raw page
-page_t alloc_raw_page(void);
-
-// allocate a struct page together with the raw page
-struct page* allocate_page(void);
-
-#define KERNEL_PAGE_DIRECTORY_ADDR ((page_directory_entry*)0x00000000)
-
-void init_mem(void);
-
-#define KERNEL_CODE_SEGMENT (0x08)
-#define KERNEL_DATA_SEGMENT (0x10)
-#define USER_CODE_SEGMENT (0x18)
-#define USER_DATA_SEGMENT (0x20)
-
-#define SD_TYPE_CODE_SYSTEM (0x9a)
-#define SD_TYPE_DATA_SYSTEM (0x92)
-
-#define SD_TYPE_CODE_USER (0xfa)
-#define SD_TYPE_DATA_USER (0xf2)
-
-#define SD_TYPE_TSS (0x89)
-
-typedef struct segment_descriptor_struct {
-    uint64_t limit_low : 16;
-    uint64_t base_low : 16;
-    uint64_t base_mid : 8;
-    uint64_t access : 8;
-    uint64_t limit_high : 4;
-    uint64_t flags : 4;
-    uint64_t base_high : 8;
-} segment_descriptor;
-
-void create_segment_descriptor(
-    segment_descriptor* sd,
-    uint32_t base,
-    uint32_t limit,
-    uint32_t flags,
-    uint32_t access);
-
-#ifdef __cplusplus
-}
-#endif

+ 139 - 0
include/kernel/mm.hpp

@@ -0,0 +1,139 @@
+#pragma once
+
+#include <kernel/mem.h>
+#include <types/allocator.hpp>
+#include <types/list.hpp>
+#include <types/types.h>
+#include <types/vector.hpp>
+
+struct page_attr {
+    uint32_t cow : 1;
+};
+
+struct page {
+    page_t phys_page_id;
+    size_t* ref_count;
+    struct page_attr attr;
+};
+
+using page_arr = types::vector<page, types::kernel_ident_allocator>;
+
+struct mm_attr {
+    uint32_t read : 1;
+    uint32_t write : 1;
+    uint32_t system : 1;
+};
+
+struct mm {
+    linr_ptr_t start;
+    struct mm_attr attr;
+    page_arr* pgs;
+    page_directory_entry* pd;
+};
+
+using mm_list = types::list<mm, types::kernel_ident_allocator>;
+
+// in mem.cpp
+extern mm_list* kernel_mms;
+
+// translate physical address to virtual(mapped) address
+void* p_ptr_to_v_ptr(phys_ptr_t p_ptr);
+
+// translate linear address to physical address
+phys_ptr_t l_ptr_to_p_ptr(const mm_list* mms, linr_ptr_t v_ptr);
+
+// translate virtual(mapped) address to physical address
+phys_ptr_t v_ptr_to_p_ptr(void* v_ptr);
+
+// check if the l_ptr is contained in the area
+// @return GB_OK if l_ptr is in the area
+//         GB_FAILED if not
+int is_l_ptr_valid(const mm_list* mms, linr_ptr_t l_ptr);
+
+// find the corresponding page the l_ptr pointing to
+// @return the pointer to the struct if found, NULL if not found
+struct page* find_page_by_l_ptr(const mm_list* mms, linr_ptr_t l_ptr);
+
+static inline page_t phys_addr_to_page(phys_ptr_t ptr)
+{
+    return ptr >> 12;
+}
+
+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 linr_addr_to_pd_i(linr_ptr_t ptr)
+{
+    return page_to_pd_i(phys_addr_to_page(ptr));
+}
+
+static inline pd_i_t linr_addr_to_pt_i(linr_ptr_t ptr)
+{
+    return page_to_pt_i(phys_addr_to_page(ptr));
+}
+
+static inline page_directory_entry* mms_get_pd(const mm_list* mms)
+{
+    return mms->begin()->pd;
+}
+
+static inline page_directory_entry* lptr_to_pde(const mm_list* mms, linr_ptr_t l_ptr)
+{
+    return mms_get_pd(mms) + linr_addr_to_pd_i((phys_ptr_t)l_ptr);
+}
+
+static inline page_table_entry* lptr_to_pte(const mm_list* mms, linr_ptr_t l_ptr)
+{
+    page_directory_entry* pde = lptr_to_pde(mms, l_ptr);
+    page_table_entry* pte = (page_table_entry*)p_ptr_to_v_ptr(page_to_phys_addr(pde->in.pt_page));
+    return pte + linr_addr_to_pt_i((phys_ptr_t)l_ptr);
+}
+
+static inline page_directory_entry* lp_to_pde(const mm_list* mms, linr_ptr_t l_ptr)
+{
+    phys_ptr_t p_ptr = l_ptr_to_p_ptr(mms, l_ptr);
+    page_directory_entry* pde = mms_get_pd(mms) + linr_addr_to_pd_i(p_ptr);
+    return pde;
+}
+
+// get the corresponding pte for the linear address
+// for example: l_ptr = 0x30001000 will return the pte including the page it is mapped to
+static inline page_table_entry* lp_to_pte(const mm_list* mms, linr_ptr_t l_ptr)
+{
+    phys_ptr_t p_ptr = l_ptr_to_p_ptr(mms, l_ptr);
+
+    page_directory_entry* pde = lp_to_pde(mms, l_ptr);
+    phys_ptr_t p_pt = page_to_phys_addr(pde->in.pt_page);
+
+    page_table_entry* pte = (page_table_entry*)p_ptr_to_v_ptr(p_pt);
+    pte += linr_addr_to_pt_i(p_ptr);
+
+    return pte;
+}
+
+// map the page to the end of the mm_area in pd
+int k_map(
+    mm* mm_area,
+    const struct page* page,
+    int read,
+    int write,
+    int priv,
+    int cow);
+
+// allocate a raw page
+page_t alloc_raw_page(void);
+
+// allocate a struct page together with the raw page
+struct page allocate_page(void);

+ 23 - 1
include/types/allocator.hpp

@@ -1,5 +1,5 @@
 #pragma once
-#include <kernel/mem.hpp>
+#include <kernel/mem.h>
 #include <types/types.h>
 
 inline void* operator new(size_t, void* ptr)
@@ -28,12 +28,34 @@ public:
     }
 };
 
+template <typename T>
+class kernel_ident_allocator {
+public:
+    using value_type = T;
+
+    static value_type* allocate_memory(size_t count)
+    {
+        return static_cast<value_type*>(::ki_malloc(count));
+    }
+
+    static void deallocate_memory(value_type* ptr)
+    {
+        ::ki_free(ptr);
+    }
+};
+
 template <typename T, typename... Args>
 T* kernel_allocator_new(Args... args)
 {
     return allocator_traits<kernel_allocator<T>>::allocate_and_construct(args...);
 }
 
+template <typename T, typename... Args>
+T* kernel_ident_allocator_new(Args... args)
+{
+    return allocator_traits<kernel_ident_allocator<T>>::allocate_and_construct(args...);
+}
+
 template <typename Allocator>
 class allocator_traits {
 public:

+ 0 - 9
include/types/list.h

@@ -1,9 +0,0 @@
-#pragma once
-
-#define LIST_LIKE_AT(type, list_like, pos, result_name) \
-    type* result_name = list_like; \
-    {                   \
-        size_t _tmp_pos = (pos); \
-        while (_tmp_pos--) \
-            result_name = result_name->next; \
-    }

+ 32 - 5
include/types/list.hpp

@@ -1,7 +1,7 @@
 #pragma once
 
-#include <kernel/mem.hpp>
 #include <types/allocator.hpp>
+#include <types/cplusplus.hpp>
 #include <types/types.h>
 
 namespace types {
@@ -14,12 +14,14 @@ private:
     class node;
 
 public:
+    template <typename Pointer>
     class iterator;
 
     using value_type = T;
     using pointer_type = value_type*;
     using reference_type = value_type&;
-    using iterator_type = iterator;
+    using iterator_type = iterator<value_type*>;
+    using const_iterator_type = iterator<const value_type*>;
     using size_type = size_t;
     using difference_type = ssize_t;
     using node_base_type = node_base;
@@ -58,7 +60,12 @@ private:
     };
 
 public:
+    template <typename Pointer>
     class iterator {
+    public:
+        using Value = typename types::traits::remove_pointer<Pointer>::type;
+        using Reference = typename types::traits::add_reference<Value>::type;
+
     public:
         iterator(const iterator& iter) noexcept
             : n(iter.n)
@@ -111,17 +118,17 @@ public:
             return iter;
         }
 
-        reference_type operator*() const noexcept
+        Reference operator*() const noexcept
         {
             return (static_cast<node_type*>(n))->value;
         }
 
-        pointer_type operator->() const noexcept
+        Pointer operator->() const noexcept
         {
             return &(static_cast<node_type*>(n))->value;
         }
 
-        pointer_type ptr(void) const noexcept
+        Pointer ptr(void) const noexcept
         {
             return &(static_cast<node_type*>(n))->value;
         }
@@ -239,6 +246,26 @@ public:
         return iterator_type(tail);
     }
 
+    const_iterator_type begin() const noexcept
+    {
+        return const_iterator_type(head->next);
+    }
+
+    const_iterator_type end() const noexcept
+    {
+        return const_iterator_type(tail);
+    }
+
+    const_iterator_type cbegin() const noexcept
+    {
+        return const_iterator_type(head->next);
+    }
+
+    const_iterator_type cend() const noexcept
+    {
+        return const_iterator_type(tail);
+    }
+
     bool empty(void) const noexcept
     {
         return size() == 0;

+ 0 - 1
include/types/vector.hpp

@@ -1,6 +1,5 @@
 #pragma once
 
-#include <kernel/mem.hpp>
 #include <types/allocator.hpp>
 #include <types/cplusplus.hpp>
 #include <types/types.h>

+ 9 - 7
src/kernel/interrupt.c → src/kernel/interrupt.cpp

@@ -4,7 +4,8 @@
 #include <kernel/hw/keyboard.h>
 #include <kernel/hw/timer.h>
 #include <kernel/interrupt.h>
-#include <kernel/mem.hpp>
+#include <kernel/mem.h>
+#include <kernel/mm.hpp>
 #include <kernel/stdio.h>
 #include <kernel/tty.h>
 #include <kernel/vga.h>
@@ -73,7 +74,7 @@ void init_pic(void)
     asm_sti();
 }
 
-void int6_handler(
+extern "C" void int6_handler(
     struct regs_32 s_regs,
     uint32_t error_code,
     ptr_t eip,
@@ -141,7 +142,6 @@ void int14_handler(
     uint16_t cs,
     uint32_t eflags)
 {
-    MAKE_BREAK_POINT();
     char buf[512];
 
     ++page_fault_times;
@@ -155,15 +155,15 @@ void int14_handler(
 
     // kernel code
     if (cs == KERNEL_CODE_SEGMENT) {
-        if (is_l_ptr_valid(kernel_mm_head, l_addr) != GB_OK) {
+        if (is_l_ptr_valid(kernel_mms, l_addr) != GB_OK) {
             goto kill;
         }
-        struct page* page = find_page_by_l_ptr(kernel_mm_head, l_addr);
+        struct page* page = find_page_by_l_ptr(kernel_mms, l_addr);
 
         // copy on write
         if (error_code.write == 1 && page->attr.cow == 1) {
-            page_directory_entry* pde = kernel_mm_head->pd + linr_addr_to_pd_i(l_addr);
-            page_table_entry* pte = p_ptr_to_v_ptr(page_to_phys_addr(pde->in.pt_page));
+            page_directory_entry* pde = mms_get_pd(kernel_mms) + linr_addr_to_pd_i(l_addr);
+            page_table_entry* pte = (page_table_entry*)p_ptr_to_v_ptr(page_to_phys_addr(pde->in.pt_page));
             pte += linr_addr_to_pt_i(l_addr);
 
             // if it is a dying page
@@ -197,6 +197,8 @@ kill:
         buf, 512,
         "killed: segmentation fault (eip: %x, cr2: %x, error_code: %x)", v_eip, l_addr, error_code);
     tty_print(console, buf);
+
+    MAKE_BREAK_POINT();
     asm_cli();
     asm_hlt();
 }

+ 231 - 253
src/kernel/mem.cpp

@@ -2,18 +2,17 @@
 #include <asm/port_io.h>
 #include <asm/sys.h>
 #include <kernel/errno.h>
-#include <kernel/mem.hpp>
+#include <kernel/mem.h>
+#include <kernel/mm.hpp>
 #include <kernel/stdio.h>
 #include <kernel/task.h>
 #include <kernel/vga.h>
 #include <kernel_main.h>
 #include <types/bitmap.h>
-#include <types/list.h>
 
-// static variables
+// global objects
 
-struct mm kernel_mm;
-struct mm* kernel_mm_head;
+mm_list* kernel_mms;
 
 // ---------------------
 
@@ -22,156 +21,203 @@ struct mm* kernel_mm_head;
 #define EMPTY_PAGE_ADDR ((phys_ptr_t)0x5000)
 #define EMPTY_PAGE_END ((phys_ptr_t)0x6000)
 
-// ---------------------
+#define IDENTICALLY_MAPPED_HEAP_SIZE ((size_t)0x400000)
 
-static void* p_start;
-static void* p_break;
+// ---------------------
 
 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;
-    return 0;
-}
-
-static int32_t brk(void* addr)
-{
-    if (addr >= KERNEL_HEAP_LIMIT) {
-        return GB_FAILED;
+class brk_memory_allocator {
+public:
+    using byte = uint8_t;
+    using size_type = size_t;
+
+    struct mem_blk_flags {
+        uint8_t is_free;
+        uint8_t has_next;
+        uint8_t _unused2;
+        uint8_t _unused3;
+    };
+
+    struct mem_blk {
+        size_t size;
+        struct mem_blk_flags flags;
+        // the first byte of the memory space
+        // the minimal allocated space is 4 bytes
+        uint8_t data[4];
+    };
+
+private:
+    byte* p_start;
+    byte* p_break;
+    byte* p_limit;
+
+    brk_memory_allocator(void) = delete;
+    brk_memory_allocator(const brk_memory_allocator&) = delete;
+    brk_memory_allocator(brk_memory_allocator&&) = delete;
+
+    inline int brk(byte* addr)
+    {
+        if (addr >= p_limit)
+            return GB_FAILED;
+        p_break = addr;
+        return GB_OK;
     }
-    p_break = addr;
-    return 0;
-}
 
-// sets errno when failed to increase heap pointer
-static void* sbrk(size_t increment)
-{
-    if (brk((char*)p_break + increment) != 0) {
-        errno = ENOMEM;
-        return 0;
-    } else {
-        errno = 0;
-        return p_break;
+    // sets errno
+    inline byte* sbrk(size_type increment)
+    {
+        if (brk(p_break + increment) != GB_OK) {
+            errno = ENOMEM;
+            return nullptr;
+        } else {
+            errno = 0;
+            return p_break;
+        }
     }
-}
 
-int init_heap(void)
-{
-    set_heap_start(KERNEL_HEAP_START);
-
-    if (brk(KERNEL_HEAP_START) != 0) {
-        return GB_FAILED;
+    inline mem_blk* _find_next_mem_blk(mem_blk* blk, size_type blk_size)
+    {
+        byte* p = (byte*)blk;
+        p += sizeof(mem_blk);
+        p += blk_size;
+        p -= (4 * sizeof(byte));
+        return (mem_blk*)p;
     }
-    struct mem_blk* p_blk = (struct mem_blk*)sbrk(0);
-    p_blk->size = 4;
-    p_blk->flags.has_next = 0;
-    p_blk->flags.is_free = 1;
-    return GB_OK;
-}
 
-static inline struct mem_blk* _find_next_mem_blk(struct mem_blk* blk, size_t blk_size)
-{
-    char* p = (char*)blk;
-    p += sizeof(struct mem_blk);
-    p += blk_size;
-    p -= (4 * sizeof(uint8_t));
-    return (struct mem_blk*)p;
-}
-
-// @param start_pos position where to start finding
-// @param size the size of the block we're looking for
-// @return found block if suitable block exists, if not, the last block
-static struct mem_blk*
-find_blk(
-    struct mem_blk* start_pos,
-    size_t size)
-{
-    while (1) {
-        if (start_pos->flags.is_free && start_pos->size >= size) {
-            errno = 0;
-            return start_pos;
-        } else {
-            if (!start_pos->flags.has_next) {
-                errno = ENOTFOUND;
+    // sets errno
+    // @param start_pos position where to start finding
+    // @param size the size of the block we're looking for
+    // @return found block if suitable block exists, if not, the last block
+    mem_blk* find_blk(mem_blk* start_pos, size_type size)
+    {
+        while (1) {
+            if (start_pos->flags.is_free && start_pos->size >= size) {
+                errno = 0;
                 return start_pos;
+            } else {
+                if (!start_pos->flags.has_next) {
+                    errno = ENOTFOUND;
+                    return start_pos;
+                }
+                start_pos = _find_next_mem_blk(start_pos, start_pos->size);
             }
-            start_pos = _find_next_mem_blk(start_pos, start_pos->size);
         }
     }
-}
 
-static struct mem_blk*
-allocate_new_block(
-    struct mem_blk* blk_before,
-    size_t size)
-{
-    sbrk(sizeof(struct mem_blk) + size - 4 * sizeof(uint8_t));
-    if (errno) {
-        return 0;
+    // sets errno
+    mem_blk* allocate_new_block(mem_blk* blk_before, size_type size)
+    {
+        sbrk(sizeof(mem_blk) + size - 4 * sizeof(byte));
+        // preserves errno
+        if (errno) {
+            return nullptr;
+        }
+
+        mem_blk* blk = _find_next_mem_blk(blk_before, blk_before->size);
+
+        blk_before->flags.has_next = 1;
+
+        blk->flags.has_next = 0;
+        blk->flags.is_free = 1;
+        blk->size = size;
+
+        errno = 0;
+        return blk;
     }
 
-    struct mem_blk* blk = _find_next_mem_blk(blk_before, blk_before->size);
+    void split_block(mem_blk* blk, size_type this_size)
+    {
+        // block is too small to get split
+        if (blk->size < sizeof(mem_blk) + this_size) {
+            return;
+        }
 
-    blk_before->flags.has_next = 1;
+        mem_blk* blk_next = _find_next_mem_blk(blk, this_size);
 
-    blk->flags.has_next = 0;
-    blk->flags.is_free = 1;
-    blk->size = size;
+        blk_next->size = blk->size
+            - this_size
+            - sizeof(mem_blk)
+            + 4 * sizeof(byte);
 
-    errno = 0;
-    return blk;
-}
+        blk_next->flags.has_next = blk->flags.has_next;
+        blk_next->flags.is_free = 1;
 
-static void split_block(
-    struct mem_blk* blk,
-    size_t this_size)
-{
-    // block is too small to get split
-    if (blk->size < sizeof(struct mem_blk) + this_size) {
-        return;
+        blk->flags.has_next = 1;
+        blk->size = this_size;
     }
 
-    struct mem_blk* blk_next = _find_next_mem_blk(blk, this_size);
+public:
+    brk_memory_allocator(void* start, size_type limit)
+        : p_start((byte*)start)
+        , p_limit(p_start + limit)
+    {
+        brk(p_start);
+        mem_blk* p_blk = (mem_blk*)sbrk(0);
+        p_blk->size = 4;
+        p_blk->flags.has_next = 0;
+        p_blk->flags.is_free = 1;
+    }
 
-    blk_next->size = blk->size
-        - this_size
-        - sizeof(struct mem_blk)
-        + 4 * sizeof(uint8_t);
+    // sets errno
+    void* alloc(size_type size)
+    {
+        struct mem_blk* block_allocated;
+
+        block_allocated = find_blk((mem_blk*)p_start, size);
+        if (errno == ENOTFOUND) {
+            // 'block_allocated' in the argument list is the pointer
+            // pointing to the last block
+            block_allocated = allocate_new_block(block_allocated, size);
+            if (errno) {
+                // preserves errno
+                return nullptr;
+            }
+        } else {
+            split_block(block_allocated, size);
+        }
 
-    blk_next->flags.has_next = blk->flags.has_next;
-    blk_next->flags.is_free = 1;
+        errno = 0;
+        block_allocated->flags.is_free = 0;
+        return block_allocated->data;
+    }
 
-    blk->flags.has_next = 1;
-    blk->size = this_size;
-}
+    void free(void* ptr)
+    {
+        mem_blk* blk = (mem_blk*)((byte*)ptr - (sizeof(mem_blk_flags) + sizeof(size_t)));
+        blk->flags.is_free = 1;
+        // TODO: fusion free blocks nearby
+    }
+};
+
+static brk_memory_allocator* kernel_heap_allocator;
+static brk_memory_allocator
+    kernel_ident_mapped_allocator((void*)bss_section_end_addr,
+        IDENTICALLY_MAPPED_HEAP_SIZE);
 
 void* k_malloc(size_t size)
 {
-    struct mem_blk* block_allocated;
-
-    block_allocated = find_blk((struct mem_blk*)p_start, size);
-    if (errno == ENOTFOUND) {
-        // 'block_allocated' in the argument list is the pointer
-        // pointing to the last block
-        block_allocated = allocate_new_block(block_allocated, size);
-        // no need to check errno and return value
-        // preserve these for the caller
-    } else {
-        split_block(block_allocated, size);
-    }
-
-    block_allocated->flags.is_free = 0;
-    return block_allocated->data;
+    return kernel_heap_allocator->alloc(size);
 }
 
 void k_free(void* ptr)
 {
-    ptr = (void*)((char*)ptr - (sizeof(struct mem_blk_flags) + sizeof(size_t)));
-    struct mem_blk* blk = (struct mem_blk*)ptr;
-    blk->flags.is_free = 1;
-    // TODO: fusion free blocks nearby
+    kernel_heap_allocator->free(ptr);
+}
+
+void* ki_malloc(size_t size)
+{
+    void* ptr = kernel_ident_mapped_allocator.alloc(size);
+    if (!ptr) {
+        MAKE_BREAK_POINT();
+    }
+    return ptr;
+}
+
+void ki_free(void* ptr)
+{
+    kernel_ident_mapped_allocator.free(ptr);
 }
 
 void* p_ptr_to_v_ptr(phys_ptr_t p_ptr)
@@ -186,28 +232,26 @@ void* p_ptr_to_v_ptr(phys_ptr_t p_ptr)
     }
 }
 
-phys_ptr_t l_ptr_to_p_ptr(struct mm* mm, linr_ptr_t v_ptr)
+phys_ptr_t l_ptr_to_p_ptr(const mm_list* mms, linr_ptr_t v_ptr)
 {
-    while (mm != NULL) {
-        if (v_ptr < mm->start || v_ptr >= mm->start + mm->len * 4096) {
-            mm = mm->next;
+    for (const mm& item : *mms) {
+        if (v_ptr < item.start || v_ptr >= item.start + item.pgs->size() * PAGE_SIZE)
             continue;
-        }
-        size_t offset = (size_t)(v_ptr - mm->start);
-        LIST_LIKE_AT(struct page, mm->pgs, offset / PAGE_SIZE, result);
-        return page_to_phys_addr(result->phys_page_id) + (offset % 4096);
+        size_t offset = (size_t)(v_ptr - item.start);
+        const page& p = item.pgs->at(offset / PAGE_SIZE);
+        return page_to_phys_addr(p.phys_page_id) + (offset % PAGE_SIZE);
     }
 
     // TODO: handle error
     return 0xffffffff;
 }
 
-phys_ptr_t v_ptr_to_p_ptr(void* v_ptr)
+phys_ptr_t v_ptr_to_p_ptr(const void* v_ptr)
 {
     if (v_ptr < KERNEL_IDENTICALLY_MAPPED_AREA_LIMIT) {
         return (phys_ptr_t)v_ptr;
     }
-    return l_ptr_to_p_ptr(kernel_mm_head, (linr_ptr_t)v_ptr);
+    return l_ptr_to_p_ptr(kernel_mms, (linr_ptr_t)v_ptr);
 }
 
 static inline void mark_page(page_t n)
@@ -262,13 +306,11 @@ page_t alloc_raw_page(void)
     return 0xffffffff;
 }
 
-struct page* allocate_page(void)
+struct page allocate_page(void)
 {
-    // TODO: allocate memory on identically mapped area
-    struct page* p = (struct page*)k_malloc(sizeof(struct page));
-    memset(p, 0x00, sizeof(struct page));
-    p->phys_page_id = alloc_raw_page();
-    p->ref_count = (size_t*)k_malloc(sizeof(size_t));
+    struct page p { };
+    p.phys_page_id = alloc_raw_page();
+    p.ref_count = types::kernel_ident_allocator_new<size_t>(0);
     return p;
 }
 
@@ -290,6 +332,8 @@ static inline void init_mem_layout(void)
     mark_addr_range(0x80000, 0xfffff);
     // mark kernel
     mark_addr_len(0x00100000, kernel_size);
+    // mark identically mapped heap
+    mark_addr_len(bss_section_end_addr, IDENTICALLY_MAPPED_HEAP_SIZE);
 
     if (e820_mem_map_entry_size == 20) {
         struct e820_mem_map_entry_20* entry = (struct e820_mem_map_entry_20*)e820_mem_map;
@@ -308,35 +352,25 @@ static inline void init_mem_layout(void)
     }
 }
 
-int is_l_ptr_valid(struct mm* mm_area, linr_ptr_t l_ptr)
+int is_l_ptr_valid(const mm_list* mms, linr_ptr_t l_ptr)
 {
-    while (mm_area != NULL) {
-        if (l_ptr >= mm_area->start && l_ptr < mm_area->start + mm_area->len * PAGE_SIZE) {
+    for (const auto& item : *mms)
+        if (l_ptr >= item.start && l_ptr < item.start + item.pgs->size() * PAGE_SIZE)
             return GB_OK;
-        }
-        mm_area = mm_area->next;
-    }
     return GB_FAILED;
 }
 
-struct page* find_page_by_l_ptr(struct mm* mm, linr_ptr_t l_ptr)
+struct page* find_page_by_l_ptr(const mm_list* mms, linr_ptr_t l_ptr)
 {
-    if (mm == kernel_mm_head && l_ptr < (linr_ptr_t)KERNEL_IDENTICALLY_MAPPED_AREA_LIMIT) {
-        // TODO: make mm for identically mapped area
-        MAKE_BREAK_POINT();
-        return (struct page*)0xffffffff;
-    }
-    while (mm != NULL) {
-        if (l_ptr >= mm->start && l_ptr < mm->start + mm->len * 4096) {
-            size_t offset = (size_t)(l_ptr - mm->start);
-            LIST_LIKE_AT(struct page, mm->pgs, offset / PAGE_SIZE, result);
-            return result;
+    for (const mm& item : *mms) {
+        if (l_ptr >= item.start && l_ptr < item.start + item.pgs->size() * PAGE_SIZE) {
+            size_t offset = (size_t)(l_ptr - item.start);
+            return &item.pgs->at(offset / PAGE_SIZE);
         }
-        mm = mm->next;
     }
 
     // TODO: error handling
-    return NULL;
+    return nullptr;
 }
 
 static inline void map_raw_page_to_pte(
@@ -352,13 +386,16 @@ static inline void map_raw_page_to_pte(
     pte->in.page = page;
 }
 
-static void _map_raw_page_to_addr(
+// map page to the end of mm_area in pd
+int k_map(
     struct mm* mm_area,
-    page_t page,
-    int rw,
-    int priv)
+    const struct page* page,
+    int read,
+    int write,
+    int priv,
+    int cow)
 {
-    linr_ptr_t addr = (linr_ptr_t)mm_area->start + mm_area->len * 4096;
+    linr_ptr_t addr = (linr_ptr_t)mm_area->start + mm_area->pgs->size() * PAGE_SIZE;
     page_directory_entry* pde = mm_area->pd + linr_addr_to_pd_i(addr);
     // page table not exist
     if (!pde->in.p) {
@@ -374,64 +411,10 @@ static void _map_raw_page_to_addr(
     // map the page in the page table
     page_table_entry* pte = (page_table_entry*)p_ptr_to_v_ptr(page_to_phys_addr(pde->in.pt_page));
     pte += linr_addr_to_pt_i(addr);
-    map_raw_page_to_pte(pte, page, rw, priv);
-}
+    map_raw_page_to_pte(pte, page->phys_page_id, (write && !cow), priv);
 
-// map page to the end of mm_area in pd
-int k_map(
-    struct mm* mm_area,
-    struct page* page,
-    int read,
-    int write,
-    int priv,
-    int cow)
-{
-    struct page* p_page_end = mm_area->pgs;
-    while (p_page_end != NULL && p_page_end->next != NULL)
-        p_page_end = p_page_end->next;
-
-    if (cow) {
-        // find its ancestor
-        while (page->attr.cow)
-            page = page->next;
-
-        // create a new page node
-        struct page* new_page = (struct page*)k_malloc(sizeof(struct page));
-
-        new_page->attr.read = (read == 1);
-        new_page->attr.write = (write == 1);
-        new_page->attr.system = (priv == 1);
-        new_page->attr.cow = 1;
-        // TODO: move *next out of struct page
-        new_page->next = NULL;
-
-        new_page->phys_page_id = page->phys_page_id;
-        new_page->ref_count = page->ref_count;
-
-        if (p_page_end != NULL)
-            p_page_end->next = new_page;
-        else
-            mm_area->pgs = new_page;
-    } else {
-        page->attr.read = (read == 1);
-        page->attr.write = (write == 1);
-        page->attr.system = (priv == 1);
-        page->attr.cow = 0;
-        // TODO: move *next out of struct page
-        page->next = NULL;
-
-        if (p_page_end != NULL)
-            p_page_end->next = page;
-        else
-            mm_area->pgs = page;
-    }
-    _map_raw_page_to_addr(
-        mm_area,
-        page->phys_page_id,
-        (write && !cow),
-        priv);
-
-    ++mm_area->len;
+    mm_area->pgs->push_back(*page);
+    mm_area->pgs->back()->attr.cow = cow;
     ++*page->ref_count;
     return GB_OK;
 }
@@ -473,9 +456,7 @@ static inline void init_paging_map_low_mem_identically(void)
     }
 }
 
-static struct page empty_page;
-static struct page heap_first_page;
-static size_t heap_first_page_ref_count;
+static page empty_page;
 
 void init_mem(void)
 {
@@ -484,46 +465,43 @@ void init_mem(void)
     // map the 16MiB-768MiB identically
     init_paging_map_low_mem_identically();
 
-    kernel_mm_head = &kernel_mm;
-
-    kernel_mm.attr.read = 1;
-    kernel_mm.attr.write = 1;
-    kernel_mm.attr.system = 1;
-    kernel_mm.len = 0;
-    kernel_mm.next = NULL;
-    kernel_mm.pd = KERNEL_PAGE_DIRECTORY_ADDR;
-    kernel_mm.pgs = NULL;
-    kernel_mm.start = (linr_ptr_t)KERNEL_HEAP_START;
-
-    heap_first_page.attr.cow = 0;
-    heap_first_page.attr.read = 1;
-    heap_first_page.attr.write = 1;
-    heap_first_page.attr.system = 1;
-    heap_first_page.next = NULL;
-    heap_first_page.phys_page_id = alloc_raw_page();
-    heap_first_page.ref_count = &heap_first_page_ref_count;
-
-    *heap_first_page.ref_count = 0;
-
-    k_map(kernel_mm_head, &heap_first_page, 1, 1, 1, 0);
-
-    init_heap();
+    kernel_mms = types::kernel_ident_allocator_new<mm_list>();
+    kernel_mms->push_back(mm {
+        .start = (linr_ptr_t)KERNEL_HEAP_START,
+        .attr = {
+            .read = 1,
+            .write = 1,
+            .system = 1,
+        },
+        .pgs = types::kernel_ident_allocator_new<page_arr>(),
+        .pd = KERNEL_PAGE_DIRECTORY_ADDR,
+    });
+
+    page heap_first_page {
+        .phys_page_id = alloc_raw_page(),
+        .ref_count = types::kernel_ident_allocator_new<size_t>(0),
+        .attr = {
+            .cow = 0,
+        },
+    };
+
+    mm* heap_mm = kernel_mms->begin().ptr();
+
+    k_map(heap_mm, &heap_first_page, 1, 1, 1, 0);
+    memset(KERNEL_HEAP_START, 0x00, PAGE_SIZE);
+    kernel_heap_allocator = types::kernel_ident_allocator_new<brk_memory_allocator>(KERNEL_HEAP_START,
+        (uint32_t)KERNEL_HEAP_LIMIT - (uint32_t)KERNEL_HEAP_START);
 
     // create empty_page struct
     empty_page.attr.cow = 0;
-    empty_page.attr.read = 1;
-    empty_page.attr.write = 0;
-    empty_page.attr.system = 0;
-    empty_page.next = NULL;
     empty_page.phys_page_id = phys_addr_to_page(EMPTY_PAGE_ADDR);
-    empty_page.ref_count = (size_t*)k_malloc(sizeof(size_t));
-    *empty_page.ref_count = 1;
+    empty_page.ref_count = types::kernel_ident_allocator_new<size_t>(1);
 
     // TODO: improve the algorithm SO FREAKING SLOW
     // while (kernel_mm_head->len < 256 * 1024 * 1024 / PAGE_SIZE) {
-    while (kernel_mm_head->len < 16 * 1024 * 1024 / PAGE_SIZE) {
+    while (heap_mm->pgs->size() < 256 * 1024 * 1024 / PAGE_SIZE) {
         k_map(
-            kernel_mm_head, &empty_page,
+            heap_mm, &empty_page,
             1, 1, 1, 1);
     }
 }

+ 1 - 1
src/kernel/tty.c

@@ -1,6 +1,6 @@
 #include <asm/port_io.h>
 #include <kernel/hw/serial.h>
-#include <kernel/mem.hpp>
+#include <kernel/mem.h>
 #include <kernel/stdio.h>
 #include <kernel/tty.h>
 #include <kernel/vga.h>

+ 1 - 1
src/kernel/vfs.cpp

@@ -1,5 +1,5 @@
 #include <kernel/errno.h>
-#include <kernel/mem.hpp>
+#include <kernel/mem.h>
 #include <kernel/stdio.h>
 #include <kernel/tty.h>
 #include <kernel/vfs.h>

+ 10 - 11
src/kernel_main.c

@@ -8,7 +8,7 @@
 #include <kernel/hw/serial.h>
 #include <kernel/hw/timer.h>
 #include <kernel/interrupt.h>
-#include <kernel/mem.hpp>
+#include <kernel/mem.h>
 #include <kernel/stdio.h>
 #include <kernel/tty.h>
 #include <kernel/vfs.h>
@@ -52,13 +52,9 @@ extern constructor start_ctors;
 extern constructor end_ctors;
 void call_constructors_for_cpp(void)
 {
-    if (start_ctors != end_ctors) {
-        tty_print(console, "error: c++ global objects are now allowed");
-        halt_on_init_error();
+    for (constructor* ctor = &start_ctors; ctor != &end_ctors; ++ctor) {
+        (*ctor)();
     }
-    // for (constructor* ctor = &start_ctors; ctor != &end_ctors; ++ctor) {
-    //     (*ctor)();
-    // }
 }
 
 uint8_t e820_mem_map[1024];
@@ -166,14 +162,17 @@ void kernel_main(void)
     init_idt();
     INIT_OK();
 
-    INIT_START("memory allocation");
-    init_mem();
-    INIT_OK();
-
+    // NOTE:
+    // the initializer of c++ global objects MUST NOT contain
+    // all kinds of memory allocations
     INIT_START("C++ global objects");
     call_constructors_for_cpp();
     INIT_OK();
 
+    INIT_START("memory allocation");
+    init_mem();
+    INIT_OK();
+
     INIT_START("programmable interrupt controller and timer");
     init_pic();
     init_pit();