Selaa lähdekoodia

feat: move kernel to 0xc0000000

greatbridf 2 vuotta sitten
vanhempi
commit
304ecefefb

+ 1 - 1
include/asm/sys.h

@@ -7,7 +7,7 @@
 extern "C" {
 #endif
 
-void asm_switch_pd(pd_t pd_addr);
+void asm_switch_pd(page_t pd_addr);
 void asm_enable_paging(pd_t pd_addr);
 
 pptr_t current_pd(void);

+ 4 - 1
include/kernel/errno.h

@@ -1,4 +1,5 @@
-#pragma once
+#ifndef __GBOS_ERRNO_H
+#define __GBOS_ERRNO_H
 
 #include <types/types.h>
 
@@ -22,3 +23,5 @@ extern uint32_t* _get_errno(void);
 #define ENOTDIR (1 << 5)
 #define ENOTFOUND (1 << 6)
 #define ECHILD (1 << 7)
+
+#endif

+ 4 - 14
include/kernel/mem.h

@@ -3,9 +3,7 @@
 #include <stdint.h>
 #include <types/size.h>
 
-#define PAGE_SIZE (4096)
-#define IDENTICALLY_MAPPED_HEAP_SIZE ((size_t)0x400000)
-#define KERNEL_IDENTICALLY_MAPPED_AREA_LIMIT ((void*)0x30000000)
+#define PAGE_SIZE (0x1000)
 
 #ifdef __cplusplus
 extern "C" {
@@ -96,18 +94,10 @@ extern uint32_t e820_mem_map_count;
 extern uint32_t e820_mem_map_entry_size;
 extern struct mem_size_info mem_size_info;
 
-#define KERNEL_HEAP_START ((void*)0x30000000)
-#define KERNEL_HEAP_LIMIT ((void*)0x40000000)
+#define KERNEL_HEAP_START ((void*)0xd0000000)
+#define KERNEL_HEAP_LIMIT ((void*)0xd4000000)
 
-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 ((pd_t)0x00001000)
+#define EARLY_KERNEL_PD_PAGE ((page_t)0x000001)
 
 void init_mem(void);
 

+ 120 - 105
include/kernel/mm.hpp

@@ -20,8 +20,10 @@ constexpr size_t THREAD_KERNEL_STACK_SIZE = 2 * PAGE_SIZE;
 
 struct page {
     page_t phys_page_id;
-    pte_t* pte;
     size_t* ref_count;
+    // 0 :11 : pte_index
+    // 12:31 : pt_page
+    uint32_t pg_pteidx;
     union {
         uint32_t v;
         struct {
@@ -46,17 +48,6 @@ int mmap(
 
 using page_arr = types::vector<page, types::kernel_ident_allocator>;
 
-// allocate n raw page(s)
-// @return the id of the first page allocated
-page_t alloc_n_raw_pages(size_t n);
-void free_n_raw_pages(page_t start_pg, size_t n);
-
-pd_t alloc_pd(void);
-pt_t alloc_pt(void);
-
-void dealloc_pd(pd_t pd);
-void dealloc_pt(pt_t pt);
-
 // forward declaration
 namespace kernel {
 class mm_list;
@@ -86,6 +77,17 @@ inline constexpr uint32_t align_up(uint32_t v)
     return align_down<n>(v + pow<2, n>() - 1);
 }
 
+void dealloc_pd(page_t pd);
+
+// allocate a struct page together with the raw page
+page allocate_page(void);
+void free_page(page* pg);
+
+// TODO: this is for alloc_kstack()
+// CHANGE THIS
+page_t __alloc_raw_page(void);
+void __free_raw_page(page_t pg);
+
 struct mm {
 public:
     void* start;
@@ -108,9 +110,9 @@ public:
         return (char*)this->start + this->pgs->size() * PAGE_SIZE;
     }
 
-    inline bool is_ident(void) const
+    inline bool is_kernel_space(void) const
     {
-        return this->end() <= (void*)0x40000000U;
+        return this->start >= (void*)0xc0000000;
     }
 
     constexpr bool is_avail(void* start, void* end) const
@@ -126,6 +128,34 @@ public:
 
 namespace kernel {
 
+uint8_t* pmap(page_t pg);
+void pfree(page_t pg);
+
+class paccess : public types::non_copyable {
+private:
+    page_t m_pg;
+    void* m_ptr;
+
+public:
+    paccess(void) = delete;
+    paccess(paccess&&) = delete;
+    paccess& operator=(paccess&&) = delete;
+
+    constexpr explicit paccess(page_t pg)
+        : m_pg(pg)
+    {
+        m_ptr = pmap(pg);
+    }
+    constexpr void* ptr(void) const
+    {
+        return m_ptr;
+    }
+    ~paccess()
+    {
+        pfree(m_pg);
+    }
+};
+
 class mm_list {
 public:
     using list_type = ::types::list<mm, types::kernel_ident_allocator>;
@@ -136,10 +166,10 @@ private:
     list_type m_areas;
 
 public:
-    pd_t m_pd;
+    page_t m_pd;
 
 public:
-    explicit constexpr mm_list(pd_t pd)
+    explicit constexpr mm_list(page_t pd)
         : m_pd(pd)
     {
     }
@@ -148,7 +178,7 @@ public:
         : m_areas(::types::move(v.m_areas))
         , m_pd(v.m_pd)
     {
-        v.m_pd = nullptr;
+        v.m_pd = 0;
     }
     ~mm_list()
     {
@@ -203,7 +233,7 @@ public:
     constexpr void clear_user()
     {
         for (auto iter = this->begin(); iter != this->end();) {
-            if (iter->is_ident()) {
+            if (iter->is_kernel_space()) {
                 ++iter;
                 continue;
             }
@@ -237,7 +267,7 @@ public:
         return GB_OK;
     }
 
-    constexpr void unmap(iterator_type area)
+    inline void unmap(iterator_type area)
     {
         int i = 0;
 
@@ -247,16 +277,13 @@ public:
         // bool should_invlpg = (area->pgs->size() > 4);
 
         for (auto& pg : *area->pgs) {
-            if (*pg.ref_count == 1) {
-                ki_free(pg.ref_count);
-                free_n_raw_pages(pg.phys_page_id, 1);
-            } else {
-                --*pg.ref_count;
-            }
+            kernel::paccess pa(pg.pg_pteidx >> 12);
+            auto pt = (pt_t)pa.ptr();
+            assert(pt);
+            auto* pte = *pt + (pg.pg_pteidx & 0xfff);
+            pte->v = 0;
 
-            pg.phys_page_id = 0;
-            pg.attr.v = 0;
-            pg.pte->v = 0;
+            free_page(&pg);
 
             invalidate_tlb((uint32_t)area->start + (i++) * PAGE_SIZE);
         }
@@ -295,88 +322,76 @@ inline kernel::mm_list* kernel_mms;
 inline page empty_page;
 // --------------------------------
 
-// translate physical address to virtual(mapped) address
-void* ptovp(pptr_t p_ptr);
-
 inline constexpr size_t vptrdiff(void* p1, void* p2)
 {
     return (uint8_t*)p1 - (uint8_t*)p2;
 }
-inline constexpr page* lto_page(mm* mm_area, void* l_ptr)
+// inline constexpr page* lto_page(mm* mm_area, void* l_ptr)
+// {
+//     size_t offset = vptrdiff(l_ptr, mm_area->start);
+//     return &mm_area->pgs->at(offset / PAGE_SIZE);
+// }
+// inline constexpr page_t to_page(pptr_t ptr)
+// {
+//     return ptr >> 12;
+// }
+// inline constexpr size_t to_pdi(page_t pg)
+// {
+//     return pg >> 10;
+// }
+// inline constexpr size_t to_pti(page_t pg)
+// {
+//     return pg & (1024 - 1);
+// }
+// inline constexpr pptr_t to_pp(page_t p)
+// {
+//     return p << 12;
+// }
+inline size_t v_to_pdi(void* addr)
 {
-    size_t offset = vptrdiff(l_ptr, mm_area->start);
-    return &mm_area->pgs->at(offset / PAGE_SIZE);
+    return (uint32_t)addr >> 22;
 }
-inline constexpr page_t to_page(pptr_t ptr)
+inline size_t v_to_pti(void* addr)
 {
-    return ptr >> 12;
+    return ((uint32_t)addr >> 12) & 0x3ff;
 }
-inline constexpr size_t to_pdi(page_t pg)
-{
-    return pg >> 10;
-}
-inline constexpr size_t to_pti(page_t pg)
-{
-    return pg & (1024 - 1);
-}
-inline constexpr pptr_t to_pp(page_t p)
-{
-    return p << 12;
-}
-inline constexpr size_t lto_pdi(pptr_t ptr)
-{
-    return to_pdi(to_page(ptr));
-}
-inline constexpr size_t lto_pti(pptr_t ptr)
-{
-    return to_pti(to_page(ptr));
-}
-inline constexpr pte_t* to_pte(pt_t pt, page_t pg)
-{
-    return *pt + to_pti(pg);
-}
-inline void* to_vp(page_t pg)
-{
-    return ptovp(to_pp(pg));
-}
-inline pd_t to_pd(page_t pg)
-{
-    return reinterpret_cast<pd_t>(to_vp(pg));
-}
-inline pt_t to_pt(page_t pg)
-{
-    return reinterpret_cast<pt_t>(to_vp(pg));
-}
-inline pt_t to_pt(pde_t* pde)
-{
-    return to_pt(pde->in.pt_page);
-}
-inline pde_t* to_pde(pd_t pd, void* addr)
-{
-    return *pd + lto_pdi((pptr_t)addr);
-}
-inline pte_t* to_pte(pt_t pt, void* addr)
-{
-    return *pt + lto_pti((pptr_t)addr);
-}
-inline pte_t* to_pte(pde_t* pde, void* addr)
-{
-    return to_pte(to_pt(pde), addr);
-}
-inline pte_t* to_pte(pd_t pd, void* addr)
-{
-    return to_pte(to_pde(pd, addr), addr);
-}
-inline pte_t* to_pte(pde_t* pde, page_t pg)
-{
-    return to_pte(to_pt(pde), pg);
-}
-
-// allocate a raw page
-inline page_t alloc_raw_page(void)
-{
-    return alloc_n_raw_pages(1);
-}
-
-// allocate a struct page together with the raw page
-struct page allocate_page(void);
+// inline constexpr pte_t* to_pte(pt_t pt, page_t pg)
+// {
+//     return *pt + to_pti(pg);
+// }
+// inline void* to_vp(page_t pg)
+// {
+//     return ptovp(to_pp(pg));
+// }
+// inline pd_t to_pd(page_t pg)
+// {
+//     return reinterpret_cast<pd_t>(to_vp(pg));
+// }
+// inline pt_t to_pt(page_t pg)
+// {
+//     return reinterpret_cast<pt_t>(to_vp(pg));
+// }
+// inline pt_t to_pt(pde_t* pde)
+// {
+//     return to_pt(pde->in.pt_page);
+// }
+// inline pde_t* to_pde(pd_t pd, void* addr)
+// {
+//     return *pd + lto_pdi((pptr_t)addr);
+// }
+// inline pte_t* to_pte(pt_t pt, void* addr)
+// {
+//     return *pt + lto_pti((pptr_t)addr);
+// }
+// inline pte_t* to_pte(pde_t* pde, void* addr)
+// {
+//     return to_pte(to_pt(pde), addr);
+// }
+// inline pte_t* to_pte(pd_t pd, void* addr)
+// {
+//     return to_pte(to_pde(pd, addr), addr);
+// }
+// inline pte_t* to_pte(pde_t* pde, page_t pg)
+// {
+//     return to_pte(to_pt(pde), pg);
+// }

+ 8 - 15
include/kernel/process.hpp

@@ -46,17 +46,12 @@ struct thread_attr {
 
 struct thread {
 private:
-    inline void alloc_kstack(void)
-    {
-        // TODO: alloc low mem
-        kstack = to_pp(alloc_n_raw_pages(2));
-        kstack += THREAD_KERNEL_STACK_SIZE;
-        esp = reinterpret_cast<uint32_t*>(kstack);
-    }
+    void alloc_kstack(void);
+    void free_kstack(uint32_t p);
 
 public:
     uint32_t* esp;
-    pptr_t kstack;
+    uint32_t pkstack;
     process* owner;
     thread_attr attr;
 
@@ -73,13 +68,13 @@ public:
 
     constexpr thread(thread&& val)
         : esp { val.esp }
-        , kstack { val.kstack }
+        , pkstack { val.pkstack }
         , owner { val.owner }
         , attr { val.attr }
     {
         val.attr = {};
         val.esp = 0;
-        val.kstack = 0;
+        val.pkstack = 0;
         val.owner = nullptr;
     }
 
@@ -98,8 +93,8 @@ public:
 
     constexpr ~thread()
     {
-        if (kstack)
-            free_n_raw_pages(to_page(kstack - THREAD_KERNEL_STACK_SIZE), 2);
+        if (pkstack)
+            free_kstack(pkstack);
     }
 };
 
@@ -124,9 +119,7 @@ public:
             thd.owner = new_parent;
     }
 
-    explicit constexpr thdlist(void)
-    {
-    }
+    explicit constexpr thdlist(void) = default;
 
     // implementation is below
     constexpr ~thdlist();

+ 186 - 18
include/types/allocator.hpp

@@ -1,5 +1,5 @@
 #pragma once
-#include <kernel/mem.h>
+#include <assert.h>
 #include <stdint.h>
 #include <types/cplusplus.hpp>
 #include <types/types.h>
@@ -11,6 +11,160 @@ constexpr void* operator new(size_t, void* ptr)
 
 namespace types {
 
+namespace __allocator {
+    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;
+
+        constexpr int brk(byte* addr)
+        {
+            if (unlikely(addr >= p_limit))
+                return GB_FAILED;
+            p_break = addr;
+            return GB_OK;
+        }
+
+        // sets errno
+        inline byte* sbrk(size_type increment)
+        {
+            if (unlikely(brk(p_break + increment) != GB_OK))
+                return nullptr;
+            else
+                return p_break;
+        }
+
+        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;
+        }
+
+        // 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
+        inline mem_blk* find_blk(mem_blk* start_pos, size_type size)
+        {
+            while (1) {
+                if (start_pos->flags.is_free && start_pos->size >= size) {
+                    return start_pos;
+                } else {
+                    if (unlikely(!start_pos->flags.has_next))
+                        return start_pos;
+
+                    start_pos = _find_next_mem_blk(start_pos, start_pos->size);
+                }
+            }
+        }
+
+        inline mem_blk* allocate_new_block(mem_blk* blk_before, size_type size)
+        {
+            auto ret = sbrk(sizeof(mem_blk) + size - 4 * sizeof(byte));
+            if (!ret)
+                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;
+
+            return blk;
+        }
+
+        inline 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;
+            }
+
+            mem_blk* blk_next = _find_next_mem_blk(blk, this_size);
+
+            blk_next->size = blk->size
+                - this_size
+                - sizeof(mem_blk)
+                + 4 * sizeof(byte);
+
+            blk_next->flags.has_next = blk->flags.has_next;
+            blk_next->flags.is_free = 1;
+
+            blk->flags.has_next = 1;
+            blk->size = this_size;
+        }
+
+    public:
+        inline brk_memory_allocator(byte* start, size_type limit)
+            : p_start(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;
+        }
+
+        // sets errno
+        inline void* alloc(size_type size)
+        {
+            struct mem_blk* block_allocated;
+
+            block_allocated = find_blk((mem_blk*)p_start, size);
+            if (!block_allocated->flags.has_next
+                && (!block_allocated->flags.is_free || block_allocated->size < size)) {
+                // 'block_allocated' in the argument list is the pointer
+                // pointing to the last block
+                block_allocated = allocate_new_block(block_allocated, size);
+                if (!block_allocated)
+                    return nullptr;
+            } else {
+                split_block(block_allocated, size);
+            }
+
+            block_allocated->flags.is_free = 0;
+            return block_allocated->data;
+        }
+
+        inline 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
+        }
+    };
+}; // namespace __allocator
+
 template <typename T>
 concept Allocator = requires(size_t size, typename T::value_type* ptr)
 {
@@ -26,21 +180,11 @@ concept Allocator = requires(size_t size, typename T::value_type* ptr)
 template <Allocator T>
 class allocator_traits;
 
-template <typename T>
-class kernel_allocator {
-public:
-    using value_type = T;
-
-    static constexpr value_type* allocate_memory(size_t count)
-    {
-        return static_cast<value_type*>(::k_malloc(count));
-    }
-
-    static constexpr void deallocate_memory(value_type* ptr)
-    {
-        ::k_free(ptr);
-    }
-};
+namespace __allocator {
+    inline char __ident_heap[0x100000];
+    inline __allocator::brk_memory_allocator
+        m_alloc { (uint8_t*)__ident_heap, sizeof(__ident_heap) };
+} // namespace __allocator
 
 template <typename T>
 class kernel_ident_allocator {
@@ -49,12 +193,12 @@ public:
 
     static constexpr value_type* allocate_memory(size_t count)
     {
-        return static_cast<value_type*>(::ki_malloc(count));
+        return static_cast<value_type*>(__allocator::m_alloc.alloc(count));
     }
 
     static constexpr void deallocate_memory(value_type* ptr)
     {
-        ::ki_free(ptr);
+        __allocator::m_alloc.free(ptr);
     }
 };
 
@@ -125,4 +269,28 @@ public:
         deallocate(ptr);
     }
 };
+
+namespace __allocator {
+    inline __allocator::brk_memory_allocator* m_palloc;
+    inline void init_kernel_heap(void* start, size_t sz)
+    {
+        m_palloc = pnew<kernel_ident_allocator>(m_palloc, (uint8_t*)start, sz);
+    }
+} // namespace __allocator
+
+template <typename T>
+class kernel_allocator {
+public:
+    using value_type = T;
+
+    static constexpr value_type* allocate_memory(size_t count)
+    {
+        return static_cast<value_type*>(__allocator::m_palloc->alloc(count));
+    }
+
+    static constexpr void deallocate_memory(value_type* ptr)
+    {
+        __allocator::m_palloc->free(ptr);
+    }
+};
 } // namespace types

+ 3 - 3
include/types/bitmap.h

@@ -6,9 +6,9 @@
 extern "C" {
 #endif
 
-int bm_test(char* bm, size_t n);
-void bm_set(char* bm, size_t n);
-void bm_clear(char* bm, size_t n);
+int bm_test(uint8_t* bm, size_t n);
+void bm_set(uint8_t* bm, size_t n);
+void bm_clear(uint8_t* bm, size_t n);
 
 #ifdef __cplusplus
 }

+ 1 - 1
include/types/elf.hpp

@@ -14,7 +14,7 @@ using elf32_off_t = uint32_t;
 using elf_addr_t = elf32_addr_t;
 using elf_off_t = elf32_off_t;
 
-constexpr elf32_addr_t ELF_STACK_BOTTOM = 0xfffff000;
+constexpr elf32_addr_t ELF_STACK_BOTTOM = 0xbffff000;
 constexpr elf32_off_t ELF_STACK_SIZE = 8 * 1024 * 1024;
 constexpr elf32_addr_t ELF_STACK_TOP = ELF_STACK_BOTTOM - ELF_STACK_SIZE;
 

+ 1 - 1
include/types/size.h

@@ -19,4 +19,4 @@ typedef int64_t diff_t;
 #endif
 
 typedef ptr_t pptr_t;
-typedef size_t page_t;
+typedef ssize_t page_t;

+ 1 - 0
src/asm/sys.s

@@ -6,6 +6,7 @@
 .type   asm_switch_pd @function
 asm_switch_pd:
     movl 4(%esp), %eax
+    shll $12, %eax
     movl %eax, %cr3
     ret
 

+ 5 - 5
src/fs/fat.cpp

@@ -40,7 +40,7 @@ char* fat32::read_cluster(cluster_t no)
         ++iter->value.ref;
         return iter->value.data;
     }
-    auto* data = (char*)k_malloc(sectors_per_cluster * SECTOR_SIZE);
+    auto* data = new char[sectors_per_cluster * SECTOR_SIZE];
     _raw_read_cluster(data, no);
     buf.emplace(no,
         buf_object {
@@ -123,7 +123,7 @@ fat32::fat32(inode* _device)
     : device(_device)
     , label { 0 }
 {
-    char* buf = (char*)k_malloc(SECTOR_SIZE);
+    auto* buf = new char[SECTOR_SIZE];
     _raw_read_sector(buf, 0);
 
     auto* info = reinterpret_cast<ext_boot_sector*>(buf);
@@ -137,7 +137,7 @@ fat32::fat32(inode* _device)
     fat_copies = info->old.fat_copies;
 
     data_region_offset = reserved_sectors + fat_copies * sectors_per_fat;
-    fat = (cluster_t*)k_malloc(SECTOR_SIZE * sectors_per_fat);
+    fat = (cluster_t*)new char[SECTOR_SIZE * sectors_per_fat];
     // TODO: optimize
     for (uint32_t i = 0; i < 4; ++i)
         _raw_read_sector((char*)fat + i * SECTOR_SIZE, reserved_sectors + i);
@@ -157,7 +157,7 @@ fat32::fat32(inode* _device)
     free_clusters = fsinfo->free_clusters;
     next_free_cluster_hint = fsinfo->next_free_cluster;
 
-    k_free(buf);
+    delete[] buf;
 
     size_t _root_dir_clusters = 1;
     cluster_t next = root_dir;
@@ -173,7 +173,7 @@ fat32::fat32(inode* _device)
 
 fat32::~fat32()
 {
-    k_free(fat);
+    delete[]((char*)fat);
 }
 
 size_t fat32::inode_read(inode* file, char* buf, size_t buf_size, size_t offset, size_t n)

+ 12 - 7
src/kernel/interrupt.cpp

@@ -184,8 +184,11 @@ extern "C" void int14_handler(int14_data* d)
     if (unlikely(d->error_code.user && mm_area->attr.in.system))
         _int14_kill_user();
 
-    pte_t* pte = to_pte(mms->m_pd, d->l_addr);
-    page* page = lto_page(&mm_area, d->l_addr);
+    page* page = &mm_area->pgs->at(vptrdiff(d->l_addr, mm_area->start) / PAGE_SIZE);
+    kernel::paccess pa(page->pg_pteidx >> 12);
+    auto pt = (pt_t)pa.ptr();
+    assert(pt);
+    pte_t* pte = *pt + (page->pg_pteidx & 0xfff);
 
     if (unlikely(d->error_code.present == 0 && !mm_area->mapped_file))
         _int14_panic(d->v_eip, d->l_addr, d->error_code);
@@ -200,14 +203,17 @@ extern "C" void int14_handler(int14_data* d)
             return;
         }
         // duplicate the page
-        page_t new_page = alloc_raw_page();
+        page_t new_page = __alloc_raw_page();
 
         // memory mapped
         if (d->error_code.present == 0)
             pte->in.p = 1;
 
-        char* new_page_data = (char*)to_vp(new_page);
-        memcpy(new_page_data, to_vp(page->phys_page_id), PAGE_SIZE);
+        kernel::paccess pdst(new_page), psrc(page->phys_page_id);
+        auto* new_page_data = (char*)pdst.ptr();
+        auto* src = psrc.ptr();
+        assert(new_page_data && src);
+        memcpy(new_page_data, src, PAGE_SIZE);
 
         pte->in.page = new_page;
         pte->in.rw = mm_area->attr.in.write;
@@ -215,8 +221,7 @@ extern "C" void int14_handler(int14_data* d)
 
         --*page->ref_count;
 
-        page->ref_count = (size_t*)ki_malloc(sizeof(size_t));
-        *page->ref_count = 1;
+        page->ref_count = types::pnew<types::kernel_ident_allocator>(page->ref_count, 1);
         page->attr.in.cow = 0;
         page->phys_page_id = new_page;
 

+ 185 - 318
src/kernel/mem.cpp

@@ -16,13 +16,12 @@
 
 // constant values
 
-#define EMPTY_PAGE_ADDR ((pptr_t)0x0000)
-#define EMPTY_PAGE_END ((pptr_t)0x1000)
+#define EMPTY_PAGE ((page_t)0)
 
 // ---------------------
 
 static size_t mem_size;
-static char mem_bitmap[1024 * 1024 / 8];
+static uint8_t mem_bitmap[1024 * 1024 / 8];
 
 // global
 segment_descriptor gdt[6];
@@ -32,211 +31,44 @@ uint32_t e820_mem_map_count;
 uint32_t e820_mem_map_entry_size;
 struct mem_size_info mem_size_info;
 
-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 constexpr int brk(byte* addr)
-    {
-        if (unlikely(addr >= p_limit))
-            return GB_FAILED;
-        p_break = addr;
-        return GB_OK;
-    }
-
-    // sets errno
-    inline byte* sbrk(size_type increment)
-    {
-        if (unlikely(brk(p_break + increment) != GB_OK)) {
-            errno = ENOMEM;
-            return nullptr;
-        } else {
-            errno = 0;
-            return p_break;
-        }
-    }
-
-    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;
-    }
-
-    // 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 (unlikely(!start_pos->flags.has_next)) {
-                    errno = ENOTFOUND;
-                    return start_pos;
-                }
-                start_pos = _find_next_mem_blk(start_pos, start_pos->size);
-            }
-        }
-    }
-
-    // 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 (unlikely(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;
-    }
-
-    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;
-        }
-
-        mem_blk* blk_next = _find_next_mem_blk(blk, this_size);
-
-        blk_next->size = blk->size
-            - this_size
-            - sizeof(mem_blk)
-            + 4 * sizeof(byte);
-
-        blk_next->flags.has_next = blk->flags.has_next;
-        blk_next->flags.is_free = 1;
-
-        blk->flags.has_next = 1;
-        blk->size = 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;
-    }
-
-    // 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);
-        }
-
-        errno = 0;
-        block_allocated->flags.is_free = 0;
-        return block_allocated->data;
-    }
-
-    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(bss_addr + bss_len,
-        IDENTICALLY_MAPPED_HEAP_SIZE);
+void* operator new(size_t sz)
+{
+    void* ptr = types::__allocator::m_palloc->alloc(sz);
+    assert(ptr);
+    return ptr;
+}
 
-void* k_malloc(size_t size)
+void* operator new[](size_t sz)
 {
-    void* ptr = kernel_heap_allocator->alloc(size);
-    assert(likely(ptr));
+    void* ptr = types::__allocator::m_palloc->alloc(sz);
+    assert(ptr);
     return ptr;
 }
 
-void k_free(void* ptr)
+void operator delete(void* ptr)
 {
-    kernel_heap_allocator->free(ptr);
+    types::__allocator::m_palloc->free(ptr);
 }
 
-void* ki_malloc(size_t size)
+void operator delete(void* ptr, size_t)
 {
-    void* ptr = kernel_ident_mapped_allocator.alloc(size);
-    assert(likely(ptr));
-    return ptr;
+    types::__allocator::m_palloc->free(ptr);
 }
 
-void ki_free(void* ptr)
+void operator delete[](void* ptr)
 {
-    kernel_ident_mapped_allocator.free(ptr);
+    types::__allocator::m_palloc->free(ptr);
 }
 
-void* ptovp(pptr_t p_ptr)
+void operator delete[](void* ptr, size_t)
 {
-    // memory below 768MiB is identically mapped
-    // TODO: address translation for high mem
-    assert(p_ptr <= 0x30000000);
-    return (void*)p_ptr;
+    types::__allocator::m_palloc->free(ptr);
 }
 
 inline void mark_page(page_t n)
 {
     bm_set(mem_bitmap, n);
 }
-
 inline void free_page(page_t n)
 {
     bm_clear(mem_bitmap, n);
@@ -244,113 +76,89 @@ inline void free_page(page_t n)
 
 constexpr void mark_addr_len(pptr_t start, size_t n)
 {
-    if (unlikely(n == 0))
+    if (n == 0)
         return;
-    page_t start_page = to_page(start);
-    page_t end_page = to_page(start + n + 4095);
+    page_t start_page = align_down<12>(start) >> 12;
+    page_t end_page = align_up<12>(start + n) >> 12;
     for (page_t i = start_page; i < end_page; ++i)
         mark_page(i);
 }
 
 constexpr void free_addr_len(pptr_t start, size_t n)
 {
-    if (unlikely(n == 0))
+    if (n == 0)
         return;
-    page_t start_page = to_page(start);
-    page_t end_page = to_page(start + n + 4095);
+    page_t start_page = align_down<12>(start) >> 12;
+    page_t end_page = align_up<12>(start + n) >> 12;
     for (page_t i = start_page; i < end_page; ++i)
         free_page(i);
 }
 
-inline constexpr void mark_addr_range(pptr_t start, pptr_t end)
+constexpr void mark_addr_range(pptr_t start, pptr_t end)
 {
     mark_addr_len(start, end - start);
 }
 
-inline constexpr void free_addr_range(pptr_t start, pptr_t end)
+constexpr void free_addr_range(pptr_t start, pptr_t end)
 {
     free_addr_len(start, end - start);
 }
 
-// @return the max count (but less than n) of the pages continuously available
-static inline size_t _test_n_raw_pages(page_t start, size_t n)
+page_t __alloc_raw_page(void)
 {
-    // *start is already allocated
-    if (bm_test(mem_bitmap, start))
-        return 0;
-
-    return 1 + ((n > 1) ? _test_n_raw_pages(start + 1, n - 1) : 0);
-}
+    for (size_t i = 0; i < sizeof(mem_bitmap); ++i) {
+        if (mem_bitmap[i] == 0xff)
+            continue;
 
-page_t alloc_n_raw_pages(size_t n)
-{
-    page_t first = 0;
-    while (first <= 1024 * 1024 - n) {
-        size_t max = _test_n_raw_pages(first, n);
-        if (max != n) {
-            first += (max + 1);
-        } else {
-            for (page_t i = first; i < first + n; ++i)
-                mark_page(i);
-            return first;
+        if (mem_bitmap[i] == (uint8_t)0xff) {
+            bm_set(mem_bitmap, i << 3);
+            return i << 3;
         }
+
+        bm_set(mem_bitmap, (i << 3) + __builtin_ctz(~mem_bitmap[i]));
+        return (i << 3) + __builtin_ctz(~mem_bitmap[i]);
     }
-    assert(false);
-    return 0xffffffff;
+    return -1;
 }
 
-void free_n_raw_pages(page_t start_pg, size_t n)
+void __free_raw_page(page_t pg)
 {
-    while (n--)
-        free_page(start_pg++);
+    bm_clear(mem_bitmap, pg);
 }
 
-struct page allocate_page(void)
+page allocate_page(void)
 {
     return page {
-        .phys_page_id = alloc_raw_page(),
-        .pte = nullptr,
+        .phys_page_id = __alloc_raw_page(),
         .ref_count = types::_new<types::kernel_ident_allocator, size_t>(0),
+        .pg_pteidx = 0,
         .attr { 0 },
     };
 }
 
-pd_t alloc_pd(void)
+void free_page(page* pg)
 {
-    // TODO: alloc page in low mem and gen struct page for it
-    page_t pd_page = alloc_raw_page();
-    pd_t pd = to_pd(pd_page);
-    memset(pd, 0x00, PAGE_SIZE);
-    return pd;
-}
-
-pt_t alloc_pt(void)
-{
-    // TODO: alloc page in low mem and gen struct page for it
-    page_t pt_page = alloc_raw_page();
-    pt_t pt = to_pt(pt_page);
-    memset(pt, 0x00, PAGE_SIZE);
-    return pt;
+    if (*pg->ref_count == 1) {
+        types::pdelete<types::kernel_ident_allocator>(pg->ref_count);
+        __free_raw_page(pg->phys_page_id);
+    } else {
+        --*pg->ref_count;
+    }
 }
 
-void dealloc_pd(pd_t pd)
+void dealloc_pd(page_t pd)
 {
-    for (pde_t* ent = (*pd) + 256; ent < (*pd) + 1024; ++ent) {
-        if (!ent->in.p)
-            continue;
-        dealloc_pt(to_pt(ent));
+    {
+        kernel::paccess pa(pd);
+        auto p_pd = (pd_t)pa.ptr();
+        assert(p_pd);
+        for (pde_t* ent = (*p_pd); ent < (*p_pd) + 768; ++ent) {
+            if (!ent->in.p)
+                continue;
+            __free_raw_page(ent->in.pt_page);
+        }
     }
-    memset(pd, 0x00, sizeof(*pd));
-
-    page_t pg = to_page((pptr_t)pd);
-    free_page(pg);
-}
-void dealloc_pt(pt_t pt)
-{
-    memset(pt, 0x00, sizeof(*pt));
-
-    page_t pg = to_page((pptr_t)pt);
-    free_page(pg);
+    __free_raw_page(pd);
 }
 
 SECTION(".text.kinit")
@@ -359,16 +167,28 @@ static inline 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(0x00001000, 0x00006000);
     // mark empty page
-    mark_addr_range(EMPTY_PAGE_ADDR, EMPTY_PAGE_END);
+    mark_addr_range(0x00000000, 0x00001000);
+    // mark kernel page directory
+    mark_addr_range(0x00001000, 0x00002000);
+    // mark kernel page table
+    mark_addr_range(0x00002000, 0x00006000);
+    // mark kernel early stack
+    mark_addr_range(0x00006000, 0x00008000);
     // mark EBDA and upper memory as allocated
     mark_addr_range(0x80000, 0x100000);
-    // mark kernel
-    mark_addr_len(0x00100000, kernel_size + bss_len);
-    // mark identically mapped heap
-    mark_addr_len((pptr_t)bss_addr + bss_len, IDENTICALLY_MAPPED_HEAP_SIZE);
+    extern char __stage1_start[];
+    extern char __kinit_end[];
+    extern char __text_start[];
+    extern char __data_end[];
+
+    constexpr pptr_t PHYS_BSS_START = 0x100000;
+    // mark .stage1 and .kinit
+    mark_addr_range((pptr_t)__stage1_start, (pptr_t)__kinit_end);
+    // mark kernel .text to .data
+    mark_addr_len((pptr_t)__kinit_end, __data_end - __text_start);
+    // mark kernel .bss
+    mark_addr_len(PHYS_BSS_START, bss_len);
 
     if (e820_mem_map_entry_size == 20) {
         struct e820_mem_map_entry_20* entry = (struct e820_mem_map_entry_20*)e820_mem_map;
@@ -391,9 +211,12 @@ using kernel::mm_list;
 mm_list::mm_list(const mm_list& v)
     : m_areas(v.m_areas)
 {
-    pd_t pd = alloc_pd();
-    memcpy(pd, v.m_pd, PAGE_SIZE);
-    m_pd = pd;
+    m_pd = __alloc_raw_page();
+    kernel::paccess pdst(m_pd), psrc(v.m_pd);
+    auto* dst = pdst.ptr();
+    auto* src = psrc.ptr();
+    assert(dst && src);
+    memcpy(dst, src, PAGE_SIZE);
 }
 
 inline void map_raw_page_to_pte(
@@ -414,32 +237,56 @@ inline void map_raw_page_to_pte(
 int mm::append_page(page* pg, bool present, bool write, bool priv, bool cow)
 {
     void* addr = this->end();
-    pde_t* pde = to_pde(this->owner->m_pd, addr);
+    kernel::paccess pa(this->owner->m_pd);
+    auto pd = (pd_t)pa.ptr();
+    assert(pd);
+    pde_t* pde = *pd + v_to_pdi(addr);
+
+    page_t pt_pg = 0;
+    pte_t* pte = nullptr;
     // page table not exist
     if (unlikely(!pde->in.p)) {
         // allocate a page for the page table
+        pt_pg = __alloc_raw_page();
         pde->in.p = 1;
         pde->in.rw = 1;
         pde->in.us = 1;
-        pde->in.pt_page = alloc_raw_page();
+        pde->in.pt_page = pt_pg;
 
-        memset(to_pt(pde), 0x00, PAGE_SIZE);
+        auto pt = (pt_t)kernel::pmap(pt_pg);
+        assert(pt);
+        pte = *pt;
+
+        memset(pt, 0x00, PAGE_SIZE);
+    } else {
+        pt_pg = pde->in.pt_page;
+        auto pt = (pt_t)kernel::pmap(pt_pg);
+        assert(pt);
+        pte = *pt;
     }
 
     // map the page in the page table
-    pte_t* pte = to_pte(pde, addr);
+    int pti = v_to_pti(addr);
+    pte += pti;
+
     map_raw_page_to_pte(pte, pg->phys_page_id, present, (write && !cow), priv);
 
+    kernel::pfree(pt_pg);
+
     if (unlikely(cow && !pg->attr.in.cow)) {
+        kernel::paccess pa(pg->pg_pteidx >> 12);
+        auto* pg_pte = (pte_t*)pa.ptr();
+        assert(pg_pte);
+        pg_pte += (pg->pg_pteidx & 0xfff);
         pg->attr.in.cow = 1;
-        pg->pte->in.rw = 0;
-        pg->pte->in.a = 0;
+        pg_pte->in.rw = 0;
+        pg_pte->in.a = 0;
         invalidate_tlb(addr);
     }
     ++*pg->ref_count;
 
     auto iter = this->pgs->emplace_back(*pg);
-    iter->pte = pte;
+    iter->pg_pteidx = (pt_pg << 12) + pti;
     return GB_OK;
 }
 
@@ -490,67 +337,27 @@ int mmap(
     return _mmap(&current_process->mms, hint, len, file, offset, write, priv);
 }
 
-// map a page identically
-// this function is only meant to be used in the initialization process
-// it checks the pde's P bit so you need to make sure it's already set
-// to avoid dead loops
-static inline void _init_map_page_identically(page_t page)
-{
-    pde_t* pde = *KERNEL_PAGE_DIRECTORY_ADDR + to_pdi(page);
-    // page table not exist
-    if (unlikely(!pde->in.p)) {
-        // allocate a page for the page table
-        // set the P bit of the pde in advance
-        pde->in.p = 1;
-        pde->in.rw = 1;
-        pde->in.us = 0;
-        pde->in.pt_page = alloc_raw_page();
-        _init_map_page_identically(pde->in.pt_page);
-        memset(to_pt(pde), 0x00, PAGE_SIZE);
-    }
-
-    // map the page in the page table
-    pte_t* pt = to_pte(pde, page);
-    pt->v = 0x00000003;
-    pt->in.page = page;
-}
-
-SECTION(".text.kinit")
-static inline void init_paging_map_low_mem_identically(void)
-{
-    for (pptr_t addr = 0x01000000; addr < 0x30000000; addr += 0x1000) {
-        // check if the address is valid and not mapped
-        if (bm_test(mem_bitmap, to_page(addr)))
-            continue;
-        _init_map_page_identically(to_page(addr));
-    }
-}
-
 SECTION(".text.kinit")
 void init_mem(void)
 {
     init_mem_layout();
 
-    // map the 16MiB-768MiB identically
-    init_paging_map_low_mem_identically();
-
-    kernel_mms = types::pnew<types::kernel_ident_allocator>(kernel_mms, KERNEL_PAGE_DIRECTORY_ADDR);
+    // TODO: replace early kernel pd
+    kernel_mms = types::pnew<types::kernel_ident_allocator>(kernel_mms, 0x00001);
     auto heap_mm = kernel_mms->addarea(KERNEL_HEAP_START, true, true);
 
     // create empty_page struct
     empty_page.attr.in.cow = 0;
-    empty_page.phys_page_id = to_page(EMPTY_PAGE_ADDR);
+    empty_page.phys_page_id = EMPTY_PAGE;
     empty_page.ref_count = types::_new<types::kernel_ident_allocator, size_t>(1);
-    empty_page.pte = to_pte(*KERNEL_PAGE_DIRECTORY_ADDR, empty_page.phys_page_id);
-    empty_page.pte->in.rw = 0;
-    invalidate_tlb(0x00000000);
+    empty_page.pg_pteidx = 0x00002000;
 
-    // 0x30000000 to 0x40000000 or 768MiB to 1GiB
-    while (heap_mm->pgs->size() < 256 * 1024 * 1024 / PAGE_SIZE)
+    // 0xd0000000 to 0xd4000000 or 3.5GiB, size 64MiB
+    while (heap_mm->pgs->size() < 64 * 1024 * 1024 / PAGE_SIZE)
         heap_mm->append_page(&empty_page, true, true, true, true);
 
-    kernel_heap_allocator = types::pnew<types::kernel_ident_allocator>(kernel_heap_allocator,
-        KERNEL_HEAP_START, vptrdiff(KERNEL_HEAP_LIMIT, KERNEL_HEAP_START));
+    types::__allocator::init_kernel_heap(KERNEL_HEAP_START,
+        vptrdiff(KERNEL_HEAP_LIMIT, KERNEL_HEAP_START));
 }
 
 SECTION(".text.kinit")
@@ -569,3 +376,63 @@ void create_segment_descriptor(
     sd->access = access;
     sd->flags = flags;
 }
+
+namespace __physmapper {
+struct mapped_area {
+    size_t ref;
+    uint8_t* ptr;
+};
+
+static types::hash_map<page_t, mapped_area,
+    types::linux_hasher<page_t>, types::kernel_ident_allocator>
+    mapped;
+static uint8_t freebm[0x400 / 8];
+} // namespace __physmapper
+
+uint8_t* kernel::pmap(page_t pg)
+{
+    auto iter = __physmapper::mapped.find(pg);
+    if (iter) {
+        ++iter->value.ref;
+        return iter->value.ptr;
+    }
+
+    for (int i = 2; i < 0x400; ++i) {
+        if (bm_test(__physmapper::freebm, i) == 0) {
+            auto* pte = (pte_t*)(0xff001000) + i;
+            pte->v = 0x3;
+            pte->in.page = pg;
+
+            uint8_t* ptr = (uint8_t*)0xff000000 + 0x1000 * i;
+            invalidate_tlb(ptr);
+
+            bm_set(__physmapper::freebm, i);
+            __physmapper::mapped.emplace(pg,
+                __physmapper::mapped_area { 1, ptr });
+            return ptr;
+        }
+    }
+
+    return nullptr;
+}
+void kernel::pfree(page_t pg)
+{
+    auto iter = __physmapper::mapped.find(pg);
+    if (!iter)
+        return;
+
+    if (iter->value.ref > 1) {
+        --iter->value.ref;
+        return;
+    }
+
+    int i = (uint32_t)iter->value.ptr - 0xff000000;
+    i /= 0x1000;
+
+    auto* pte = (pte_t*)(0xff001000) + i;
+    pte->v = 0;
+    invalidate_tlb(iter->value.ptr);
+
+    bm_clear(__physmapper::freebm, i);
+    __physmapper::mapped.remove(iter);
+}

+ 54 - 11
src/kernel/process.cpp

@@ -12,6 +12,7 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <types/allocator.hpp>
+#include <types/bitmap.h>
 #include <types/cplusplus.hpp>
 #include <types/elf.hpp>
 #include <types/hash_map.hpp>
@@ -44,6 +45,47 @@ struct no_irq_guard {
 
 } // namespace kernel
 
+namespace __thd {
+inline uint8_t __kstack_bmp[(0x1000000 - 0xc00000) / 0x2000 / 8];
+inline int __allocated;
+} // namespace __thd
+
+void thread::alloc_kstack(void)
+{
+    for (int i = 0; i < __thd::__allocated; ++i) {
+        if (bm_test(__thd::__kstack_bmp, i) == 0) {
+            pkstack = 0xffc00000 + THREAD_KERNEL_STACK_SIZE * (i + 1);
+            esp = reinterpret_cast<uint32_t*>(pkstack);
+            return;
+        }
+    }
+
+    // kernel stack pt is at page#0x00005
+    kernel::paccess pa(0x00005);
+    auto pt = (pt_t)pa.ptr();
+    assert(pt);
+    pte_t* pte = *pt + __thd::__allocated * 2;
+
+    pte[0].v = 0x3;
+    pte[0].in.page = __alloc_raw_page();
+    pte[1].v = 0x3;
+    pte[1].in.page = __alloc_raw_page();
+
+    pkstack = 0xffc00000 + THREAD_KERNEL_STACK_SIZE * (__thd::__allocated + 1);
+    esp = reinterpret_cast<uint32_t*>(pkstack);
+
+    bm_set(__thd::__kstack_bmp, __thd::__allocated);
+    ++__thd::__allocated;
+}
+
+void thread::free_kstack(uint32_t p)
+{
+    p -= 0xffc00000;
+    p /= THREAD_KERNEL_STACK_SIZE;
+    p -= 1;
+    bm_clear(__thd::__kstack_bmp, p);
+}
+
 process::process(process&& val)
     : mms(types::move(val.mms))
     , thds { types::move(val.thds), this }
@@ -67,7 +109,7 @@ process::process(const process& parent)
     : process { parent.pid, parent.is_system(), types::string<>(parent.pwd) }
 {
     for (auto& area : parent.mms) {
-        if (area.is_ident())
+        if (area.is_kernel_space() || area.attr.in.system)
             continue;
 
         mms.mirror_area(area);
@@ -160,14 +202,15 @@ void kernel_threadd_main(void)
 
 void NORETURN _kernel_init(void)
 {
-    // free kinit memory
-    {
-        extern char __kinit_start[];
-        extern char __kinit_end[];
-        free_n_raw_pages(
-            to_page((pptr_t)__kinit_start),
-            (__kinit_end - __kinit_start) >> 12);
-    }
+    // TODO: free kinit memory
+    //       we should do this before we create any process
+    //       or processes should share kernel space pt
+    // {
+    //     extern char __kinit_start[];
+    //     extern char __kinit_end[];
+    //     auto iter = kernel_mms->find(__kinit_start);
+    //     kernel_mms->unmap(iter);
+    // }
 
     // pid 2 is kernel thread daemon
     auto* proc = &procs->emplace(1)->value;
@@ -271,7 +314,7 @@ void NORETURN init_scheduler(void)
     readythds->push(current_thread);
 
     tss.ss0 = KERNEL_DATA_SEGMENT;
-    tss.esp0 = current_thread->kstack;
+    tss.esp0 = current_thread->pkstack;
 
     asm_switch_pd(current_process->mms.m_pd);
 
@@ -321,7 +364,7 @@ void schedule()
     auto* curr_thd = current_thread;
 
     current_thread = thd;
-    tss.esp0 = current_thread->kstack;
+    tss.esp0 = current_thread->pkstack;
 
     asm_ctx_switch(&curr_thd->esp, thd->esp);
 }

+ 1 - 0
src/kernel/syscall.cpp

@@ -195,6 +195,7 @@ void _syscall_wait(interrupt_stack* data)
 {
     auto* arg1 = reinterpret_cast<int*>(data->s_regs.edi);
 
+    // TODO: check valid address
     if (arg1 < (int*)0x40000000) {
         SYSCALL_SET_RETURN_VAL(-1, EINVAL);
         return;

+ 4 - 2
src/kernel/vfs.cpp

@@ -53,8 +53,10 @@ fs::vfs::dentry::dentry(dentry&& val)
     , flags { val.flags }
     , name(types::move(val.name))
 {
-    for (auto& item : *children)
-        item.parent = this;
+    if (children) {
+        for (auto& item : *children)
+            item.parent = this;
+    }
     memset(&val, 0x00, sizeof(dentry));
 }
 fs::vfs::dentry::~dentry()

+ 3 - 3
src/types/bitmap.c

@@ -7,16 +7,16 @@ size_t make_bm_size(size_t n)
     return sizeof(size_t) + (n / SZ) + ((n % SZ) ? 1 : 0);
 }
 
-int bm_test(char* bm, size_t n)
+int bm_test(uint8_t* bm, size_t n)
 {
     return (bm[n / SZ] & (1 << (n % SZ))) != 0;
 }
 
-void bm_set(char* bm, size_t n)
+void bm_set(uint8_t* bm, size_t n)
 {
     bm[n / SZ] |= (1 << (n % SZ));
 }
-void bm_clear(char* bm, size_t n)
+void bm_clear(uint8_t* bm, size_t n)
 {
     bm[n / SZ] &= (~(1 << (n % SZ)));
 }

+ 23 - 18
src/types/elf.cpp

@@ -50,7 +50,7 @@ int types::elf::elf32_load(types::elf::elf32_load_data* d)
 
     size_t phents_size = hdr.phentsize * hdr.phnum;
     size_t shents_size = hdr.shentsize * hdr.shnum;
-    auto* phents = (types::elf::elf32_program_header_entry*)k_malloc(phents_size);
+    auto* phents = new types::elf::elf32_program_header_entry[hdr.phnum];
     n_read = fs::vfs_read(
         ent_exec->ind,
         (char*)phents,
@@ -59,13 +59,13 @@ int types::elf::elf32_load(types::elf::elf32_load_data* d)
 
     // broken file or I/O error
     if (n_read != phents_size) {
-        k_free(phents);
+        delete[] phents;
 
         d->errcode = EINVAL;
         return GB_FAILED;
     }
 
-    auto* shents = (types::elf::elf32_section_header_entry*)k_malloc(shents_size);
+    auto* shents = new types::elf::elf32_section_header_entry[hdr.shnum];
     n_read = fs::vfs_read(
         ent_exec->ind,
         (char*)shents,
@@ -74,8 +74,8 @@ int types::elf::elf32_load(types::elf::elf32_load_data* d)
 
     // broken file or I/O error
     if (n_read != shents_size) {
-        k_free(phents);
-        k_free(shents);
+        delete[] phents;
+        delete[] shents;
 
         d->errcode = EINVAL;
         return GB_FAILED;
@@ -96,8 +96,8 @@ int types::elf::elf32_load(types::elf::elf32_load_data* d)
     {
         auto* dent = fs::vfs_open("/dev/null");
         if (!dent) {
-            k_free(shents);
-            k_free(phents);
+            delete[] phents;
+            delete[] shents;
             kill_current(-1);
         }
         null_ind = dent->ind;
@@ -107,23 +107,28 @@ int types::elf::elf32_load(types::elf::elf32_load_data* d)
         if (phents[i].type != types::elf::elf32_program_header_entry::PT_LOAD)
             continue;
 
+        auto vaddr = align_down<12>(phents[i].vaddr);
+        auto vlen = align_up<12>(phents[i].vaddr + phents[i].memsz) - vaddr;
+        auto flen = align_up<12>(phents[i].vaddr + phents[i].filesz) - vaddr;
+        auto fileoff = align_down<12>(phents[i].offset);
+
         auto ret = mmap(
-            (char*)phents[i].vaddr,
-            phents[i].filesz,
+            (char*)vaddr,
+            phents[i].filesz + (phents[i].vaddr & 0xfff),
             ent_exec->ind,
-            phents[i].offset,
+            fileoff,
             1,
             d->system);
 
         if (ret != GB_OK)
             goto error;
 
-        if (phents[i].memsz > align_up<12>(phents[i].filesz)) {
+        if (vlen > flen) {
             ret = mmap(
-                (char*)phents[i].vaddr + align_up<12>(phents[i].filesz),
-                align_up<12>(phents[i].memsz) - align_up<12>(phents[i].filesz),
+                (char*)vaddr + flen,
+                vlen - flen,
                 null_ind,
-                phents[i].offset + align_up<12>(phents[i].filesz),
+                0,
                 1,
                 d->system);
 
@@ -134,8 +139,8 @@ int types::elf::elf32_load(types::elf::elf32_load_data* d)
         continue;
 
     error:
-        k_free(phents);
-        k_free(shents);
+        delete[] phents;
+        delete[] shents;
         kill_current(-1);
     }
 
@@ -187,8 +192,8 @@ int types::elf::elf32_load(types::elf::elf32_load_data* d)
     // push argc
     _user_push(sp, args.size());
 
-    k_free(shents);
-    k_free(phents);
+    delete[] phents;
+    delete[] shents;
 
     return GB_OK;
 }

+ 0 - 9
src/types/libstdcpp.cpp

@@ -5,15 +5,6 @@
 #include <stdio.h>
 #include <types/types.h>
 
-void operator delete(void*)
-{
-    assert(false);
-}
-void operator delete(void*, unsigned int)
-{
-    assert(false);
-}
-
 extern "C" void NORETURN __stack_chk_fail(void)
 {
     assert(false);

+ 2 - 4
user-space-program/CMakeLists.txt

@@ -1,12 +1,10 @@
 cmake_minimum_required(VERSION 3.15)
 project(user_space_program C ASM)
 
-set(CMAKE_C_FLAGS "-nostdinc -nostdlib -static -m32 -W -Wall -Wextra -Werror -mstack-protector-guard=global")
-set(CMAKE_ASM_FLAGS "-m32 -static -mstack-protector-guard=global -g0")
+set(CMAKE_C_FLAGS "-nostdlib -nostdinc -static -m32 -W -Wall -Wextra -Werror -mstack-protector-guard=global")
+set(CMAKE_ASM_FLAGS "-nostdlib -m32 -static -mstack-protector-guard=global -g0")
 
 link_libraries(gblibc)
-add_link_options(-nostdlib -T ${CMAKE_CURRENT_SOURCE_DIR}/script.ld)
-# set(LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/script.ld)
 
 set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "")
 set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "")

+ 0 - 27
user-space-program/script.ld

@@ -1,27 +0,0 @@
-OUTPUT_FORMAT(elf32-i386)
-OUTPUT_ARCH(i386:i386)
-
-ENTRY(_start)
-
-MEMORY
-{
-    MEM : org = 0x40000000, l = 3072M
-
-}
-
-SECTIONS
-{
-    .text 0x40000000 :
-    {
-        *(.text)
-        *(.text*)
-
-        __stack_chk_guard = .;
-        LONG(0x11451419);
-    } > MEM
-
-    /DISCARD/ :
-    {
-        *(.note.gnu.property*)
-    }
-}