From 22ab2fb2a576eac9a520b71f91d21fc5f936b113 Mon Sep 17 00:00:00 2001 From: Eggert Jung Date: Wed, 25 Feb 2026 07:39:32 +0100 Subject: [PATCH] restructure thread constructor and pagetable --- kernel/main.cc | 6 +- kernel/memory/pagetable.cc | 148 +++++++++++++++++++++++++++++++++++++++++++++ kernel/memory/pagetable.h | 5 +- kernel/syscall/skeleton.cc | 119 ++---------------------------------- kernel/thread/idlethread.h | 2 +- kernel/thread/thread.cc | 55 +++++------------ kernel/thread/thread.h | 4 +- user/app1/appl.cc | 1 + 8 files changed, 179 insertions(+), 161 deletions(-) diff --git a/kernel/main.cc b/kernel/main.cc index 2bcbe27..a2b42d6 100644 --- a/kernel/main.cc +++ b/kernel/main.cc @@ -92,15 +92,15 @@ extern "C" int main() { uintptr_t appstart = (0x4000+offset)<<12; DBG << "app " << i << " size " << appsize << " at " << appstart << endl; - Thread* thread_ptr= new Thread(false, (void*)appstart, (appsize/4096)+1); //TODO fix edgecase on size=4096 - g.vault().thread_list[thread_ptr->id] = thread_ptr; + Thread* thread_ptr= new Thread(false, (void*)0x4000000, (void*)appstart, (appsize/4096)+1); //TODO fix edgecase on size=4096 + g.vault().thread_list[thread_ptr->id] = thread_ptr; g.vault().scheduler.ready(thread_ptr); //TODO fix edgecase on size=4096 offset += 1+(appsize/4096); } - Thread* thread_ptr = new Thread(false, (void*)0x4001000, 2); + Thread* thread_ptr = new Thread(false, (void*)0x4000000, (void*)0x4001000, 2); g.vault().scheduler.ready(thread_ptr); g.vault().thread_list[thread_ptr->id] = thread_ptr; diff --git a/kernel/memory/pagetable.cc b/kernel/memory/pagetable.cc index 62ee19e..03c1881 100644 --- a/kernel/memory/pagetable.cc +++ b/kernel/memory/pagetable.cc @@ -104,3 +104,151 @@ void create_basic_page_table(four_lvl_paging_t* table, pagetable_t* kernel_ident kernel_identity[0].entries[0].present = 0; } +uintptr_t isMapped(uintptr_t vaddr, four_lvl_paging_t* flpt){ + uint16_t l4Index = (vaddr>>39) & 0x1FF; + uint16_t l3Index = (vaddr>>30) & 0x1FF; + uint16_t l2Index = (vaddr>>21) & 0x1FF; + uint16_t l1Index = (vaddr>>12) & 0x1FF; + + if(flpt->l4->entries[l4Index].present){ + pagetable_t* lvl3 = (pagetable_t*)(flpt->l4->entries[l4Index].address<<12); + if(lvl3->entries[l3Index].present){ + pagetable_t* lvl2 = (pagetable_t*)(lvl3->entries[l3Index].address<<12); + if(lvl2->entries[l2Index].present){ + pagetable_t* lvl1 = (pagetable_t*)(lvl2->entries[l2Index].address<<12); + if(lvl1->entries[l1Index].present) + return lvl1->entries[l1Index].address<<12; + } + } + } + return 0; +} + +void* getFreeVirtSpace(four_lvl_paging_t* search_table, uint8_t num_pages){ + uint32_t start_v = 0x4000; + uint32_t stop_v = 0x6000; + static uint32_t next_start_v = 0x4000; + //static uint32_t next_start_v = start_v; + + //start from last found address + for (uint32_t v=next_start_v; v>39) & 0x1FF; + uint16_t l3Index = (vaddr>>30) & 0x1FF; + uint16_t l2Index = (vaddr>>21) & 0x1FF; + uint16_t l1Index = (vaddr>>12) & 0x1FF; + + if(!(flpt->l4->entries[l4Index].present)){ + pagetable_t* newl3 = (pagetable_t*)PageFrameAllocator::alloc(true); + memset(newl3, 0, 4096); + flpt->l4->entries[l4Index] = { + .present = 1, + .write = 1, + .user = 1, + .address = (uintptr_t)newl3 >> 12 + }; + } + + pagetable_t* lvl3 = (pagetable_t*)(flpt->l4->entries[l4Index].address<<12); + if(!(lvl3->entries[l3Index].present)){ + pagetable_t* newl2 = (pagetable_t*)PageFrameAllocator::alloc(true); + memset(newl2, 0, 4096); + lvl3->entries[l3Index] = { + .present = 1, + .write = 1, + .user = 1, + .address = (uintptr_t)newl2 >> 12 + }; + } + + pagetable_t* lvl2 = (pagetable_t*)(lvl3->entries[l3Index].address<<12); + if(!(lvl2->entries[l2Index].present)){ + pagetable_t* newl1 = (pagetable_t*)PageFrameAllocator::alloc(true); + memset(newl1, 0, 4096); + lvl2->entries[l2Index] = { + .present = 1, + .write = 1, + .user = 1, + .address = (uintptr_t)newl1 >> 12 + }; + } + + pagetable_t* lvl1 = (pagetable_t*)(lvl2->entries[l2Index].address<<12); + + if(frame){ + assert(!(lvl1->entries[l1Index].present)); // should not be present, bc its a new mapping + lvl1->entries[l1Index] = { + .present = 1, + .write = 1, + .user = 1, + .address = (uintptr_t)frame >> 12 + }; + } + else //unmap if nullptr + lvl1->entries[l1Index].present = 0; +} + +void copy_pagetable(four_lvl_paging_t* parent_table, four_lvl_paging_t* child_table){ + //can safely assume only one lvl4 entry + pagetable_t* lvl3 = (pagetable_t*)(parent_table->l4->entries[0].address<<12); + for(uint16_t i3=0; i3<512; i3++){ + if(lvl3->entries[i3].present){ + pagetable_t* lvl2 = (pagetable_t*)(lvl3->entries[i3].address<<12); + for(uint16_t i2=0; i2<512; i2++){ + if(lvl2->entries[i2].present){ + pagetable_t* lvl1 = (pagetable_t*)(lvl2->entries[i2].address<<12); + for(uint16_t i1=0; i1<512; i1++){ + if(lvl1->entries[i1].present){ + uintptr_t vaddr = + ((uintptr_t)i3<<30) | + ((uintptr_t)i2<<21) | + ((uintptr_t)i1<<12) ; + if(!isMapped(vaddr, child_table)){ + //only copy if not part of basic pagetable + assert( (i3>0) || (i2>=32)); //assert user memory + void* frame = PageFrameAllocator::alloc(false); + setMapping(vaddr, frame, child_table); + + //map to local space for copy + void* dest = getFreeVirtSpace(parent_table, 1); + setMapping((uintptr_t)dest, frame, parent_table); + memcpy(dest, (void*)vaddr, 4096); + setMapping((uintptr_t)dest, 0, parent_table); + } + } + } + } + } + } + } +} + + diff --git a/kernel/memory/pagetable.h b/kernel/memory/pagetable.h index e24fb65..441b77a 100644 --- a/kernel/memory/pagetable.h +++ b/kernel/memory/pagetable.h @@ -50,7 +50,10 @@ typedef struct { void write_identity_map(pagetable_t* identity_table, uint64_t size); void create_basic_page_table(four_lvl_paging_t* table, pagetable_t* kernel_identity); void load_cr3(void* cr3_value); -void map_pageframe(four_lvl_paging_t* table, uintptr_t phys, uintptr_t virt); +void setMapping(uintptr_t vaddr, void* frame, four_lvl_paging_t* flpt); +uintptr_t isMapped(uintptr_t vaddr, four_lvl_paging_t* flpt); +void* getFreeVirtSpace(four_lvl_paging_t* search_table, uint8_t num_pages); +void copy_pagetable(four_lvl_paging_t* parent_table, four_lvl_paging_t* child_table); //typedef struct { // same diff --git a/kernel/syscall/skeleton.cc b/kernel/syscall/skeleton.cc index e1803ce..afb363c 100644 --- a/kernel/syscall/skeleton.cc +++ b/kernel/syscall/skeleton.cc @@ -8,6 +8,7 @@ #include "../sync/semaphore.h" #include "../thread/scheduler.h" #include "../memory/pageframealloc.h" +#include "../memory/pagetable.h" void *operator new(size_t, void *); //#include "../user/app1/appl.h" @@ -138,119 +139,6 @@ namespace Syscall { void kill(Vault &vault, size_t pid){ //vault.scheduler.kill(&apps[pid]); } - - - uintptr_t isMapped(uintptr_t vaddr, four_lvl_paging_t* flpt){ - uint16_t l4Index = (vaddr>>39) & 0x1FF; - uint16_t l3Index = (vaddr>>30) & 0x1FF; - uint16_t l2Index = (vaddr>>21) & 0x1FF; - uint16_t l1Index = (vaddr>>12) & 0x1FF; - - if(flpt->l4->entries[l4Index].present){ - pagetable_t* lvl3 = (pagetable_t*)(flpt->l4->entries[l4Index].address<<12); - if(lvl3->entries[l3Index].present){ - pagetable_t* lvl2 = (pagetable_t*)(lvl3->entries[l3Index].address<<12); - if(lvl2->entries[l2Index].present){ - pagetable_t* lvl1 = (pagetable_t*)(lvl2->entries[l2Index].address<<12); - if(lvl1->entries[l1Index].present) - return lvl1->entries[l1Index].address<<12; - } - } - } - return 0; - } - - void* getFreeVirtSpace(four_lvl_paging_t* search_table, uint8_t num_pages){ - uint32_t start_v = 0x4000; - uint32_t stop_v = 0x6000; - static uint32_t next_start_v = 0x4000; - //static uint32_t next_start_v = start_v; - - //start from last found address - for (uint32_t v=next_start_v; v>39) & 0x1FF; - uint16_t l3Index = (vaddr>>30) & 0x1FF; - uint16_t l2Index = (vaddr>>21) & 0x1FF; - uint16_t l1Index = (vaddr>>12) & 0x1FF; - - if(!(flpt->l4->entries[l4Index].present)){ - pagetable_t* newl3 = (pagetable_t*)PageFrameAllocator::alloc(true); - memset(newl3, 0, 4096); - flpt->l4->entries[l4Index] = { - .present = 1, - .write = 1, - .user = 1, - .address = (uintptr_t)newl3 >> 12 - }; - } - - pagetable_t* lvl3 = (pagetable_t*)(flpt->l4->entries[l4Index].address<<12); - if(!(lvl3->entries[l3Index].present)){ - pagetable_t* newl2 = (pagetable_t*)PageFrameAllocator::alloc(true); - memset(newl2, 0, 4096); - lvl3->entries[l3Index] = { - .present = 1, - .write = 1, - .user = 1, - .address = (uintptr_t)newl2 >> 12 - }; - } - - pagetable_t* lvl2 = (pagetable_t*)(lvl3->entries[l3Index].address<<12); - if(!(lvl2->entries[l2Index].present)){ - pagetable_t* newl1 = (pagetable_t*)PageFrameAllocator::alloc(true); - memset(newl1, 0, 4096); - lvl2->entries[l2Index] = { - .present = 1, - .write = 1, - .user = 1, - .address = (uintptr_t)newl1 >> 12 - }; - } - - pagetable_t* lvl1 = (pagetable_t*)(lvl2->entries[l2Index].address<<12); - - if(frame){ - assert(!(lvl1->entries[l1Index].present)); // should not be present, bc its a new mapping - lvl1->entries[l1Index] = { - .present = 1, - .write = 1, - .user = 1, - .address = (uintptr_t)frame >> 12 - }; - } - else //unmap if nullptr - lvl1->entries[l1Index].present = 0; - } - void* map(Vault *vault, size_t size) { size_t num_pages = (size + 4096 - 1) / 4096; //pagetable_t* subbytable = vault->scheduler.active()->subtable; @@ -393,7 +281,10 @@ bool reply(Vault& v, const void* buffer, size_t size) { } int fork(Vault &vault, InterruptContext *user_context) { - return 0; + Thread* parent = vault.scheduler.active(); + //Thread* child = new Thread(false, + + return 0; } diff --git a/kernel/thread/idlethread.h b/kernel/thread/idlethread.h index 63cae7e..28964cc 100644 --- a/kernel/thread/idlethread.h +++ b/kernel/thread/idlethread.h @@ -19,7 +19,7 @@ */ class IdleThread : public Thread { public: - explicit IdleThread() : Thread(true) {} + explicit IdleThread() : Thread(true, 0) {} /*! \brief Wait for a thread to become ready and sleep in the meantime. * diff --git a/kernel/thread/thread.cc b/kernel/thread/thread.cc index ab2cc71..c3ae3b0 100644 --- a/kernel/thread/thread.cc +++ b/kernel/thread/thread.cc @@ -21,7 +21,7 @@ void Thread::kickoff(uintptr_t param1, uintptr_t param2, uintptr_t param3) { Guard::leave(); if(!thread->isKernel) - Core::Ring::switchToUsermode(thread->StackPointer.user, (void*)0x4000000, 0); + Core::Ring::switchToUsermode(thread->StackPointer.user, thread->start, 0); else if(thread->start == nullptr) thread->action(); @@ -33,52 +33,27 @@ void Thread::load_paging(Thread* t){ load_cr3((void*)(t->paging_tree->l4)); } -Thread::Thread (bool kernel, void * startframe, int num_pages): queue_link(nullptr), isKernel(kernel), start(startframe), id(idCounter++), kill_flag(false){ - StackPointer.isr = reinterpret_cast((uintptr_t)PageFrameAllocator::alloc(true)+STACK_SIZE);//(reserved_stack_space_isr + STACK_SIZE); - StackPointer.user = (void*)(0x61FF000+STACK_SIZE); - +void Thread::map_app(void* code_paddr, uint16_t code_page_num, void* stack_vaddr, uint16_t stack_page_num){ paging_tree = (four_lvl_paging_t*)PageFrameAllocator::alloc(true); memset(paging_tree, 0, 4096); create_basic_page_table(paging_tree, &identity_table); - appcode_table = (pagetable_t*) PageFrameAllocator::alloc(true); - memset(appcode_table, 0, 4096); - - appstack_table = (pagetable_t*) PageFrameAllocator::alloc(true); - memset(appstack_table, 0, 4096); - - assert(num_pages < 512); //limit for application code size is 2M - for(uint8_t i=0; ientries[i] = { - .present = 1, - .user = 1, - .address = ((uintptr_t)startframe >> 12) + i - }; + // insert app code pages at 0x4000000 + for(uintptr_t i=0; i<(code_page_num*4096); i+=4096){ + setMapping(0x4000000+i, (void*)((uintptr_t)code_paddr+i), paging_tree); } - // insert app code pages at 32*512*4096 = 0x4000000 - paging_tree->l2->entries[32] = { - .present = 1, - .write = 1, - .user = 1, - .address = (uintptr_t)(appcode_table) >> 12 - }; - - uintptr_t user_stackframe_p = ((uintptr_t)PageFrameAllocator::alloc(false)); - appstack_table->entries[511] = { - .present = 1, - .write = 1, - .user = 1, - .address = user_stackframe_p >> 12 - }; - // insert stack page at 48*512*4096 = 0x6000000 - paging_tree->l2->entries[48] = { - .present = 1, - .write = 1, - .user = 1, - .address = (uintptr_t)(appstack_table) >> 12 - }; + + for(uintptr_t i=0; i<(stack_page_num*4096); i+=4096){ + uintptr_t user_stackframe_p = ((uintptr_t)PageFrameAllocator::alloc(false)); + setMapping((uintptr_t)(stack_vaddr)+i, (void*)((uintptr_t)user_stackframe_p), paging_tree); + } +} +Thread::Thread (bool kernel, void* start_addr, void * codeframe, int code_frame_num): queue_link(nullptr), isKernel(kernel), start(start_addr), id(idCounter++), kill_flag(false){ + StackPointer.isr = reinterpret_cast((uintptr_t)PageFrameAllocator::alloc(true)+STACK_SIZE);// mapped due to identity mapping + StackPointer.user = (void*)(0x61FF000+STACK_SIZE); + map_app(codeframe, code_frame_num, StackPointer.user, 1); prepareContext(StackPointer.isr, context, kickoff, reinterpret_cast(this), 0, 0); } diff --git a/kernel/thread/thread.h b/kernel/thread/thread.h index 49b0544..e2c5427 100644 --- a/kernel/thread/thread.h +++ b/kernel/thread/thread.h @@ -79,7 +79,7 @@ class Thread { static void kickoff(uintptr_t param1, uintptr_t param2, uintptr_t param3); static void kickoffUsermode (Thread *object); - + void map_app(void* code_paddr, uint16_t code_page_num, void* stack_vaddr, uint16_t stack_page_num); public: struct{ void* user; @@ -120,7 +120,7 @@ class Thread { * */ explicit Thread(); - explicit Thread(bool kernel, void * startframe = nullptr, int num_pages=1); + explicit Thread (bool kernel, void* start_addr, void * codeframe=0, int code_frame_num=1); /*! \brief Activates the first thread on this CPU. * diff --git a/user/app1/appl.cc b/user/app1/appl.cc index 7ca88cb..916bc66 100644 --- a/user/app1/appl.cc +++ b/user/app1/appl.cc @@ -75,6 +75,7 @@ extern "C" void main() { if(receive(blubb, sizeof(blubb))){ write(1, blubb, strlen(blubb), 25, (int)id); write(2, "reply\n", 6); + memset(&blubb[10], ' ', 3); itoa(cnt, &blubb[1]); reply(blubb, sizeof(blubb)); }