restructure thread constructor and pagetable

This commit is contained in:
2026-02-25 07:39:32 +01:00
parent 76f782c5ae
commit 22ab2fb2a5
8 changed files with 179 additions and 161 deletions

View File

@@ -92,15 +92,15 @@ extern "C" int main() {
uintptr_t appstart = (0x4000+offset)<<12; uintptr_t appstart = (0x4000+offset)<<12;
DBG << "app " << i << " size " << appsize << " at " << appstart << endl; 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 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().thread_list[thread_ptr->id] = thread_ptr;
g.vault().scheduler.ready(thread_ptr); //TODO fix edgecase on size=4096 g.vault().scheduler.ready(thread_ptr); //TODO fix edgecase on size=4096
offset += 1+(appsize/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().scheduler.ready(thread_ptr);
g.vault().thread_list[thread_ptr->id] = thread_ptr; g.vault().thread_list[thread_ptr->id] = thread_ptr;

View File

@@ -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; 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<stop_v; v++) {
bool space_is_free = true;
for(uint32_t i=0; i<num_pages; i++){
if(isMapped((uintptr_t)(v+i)<<12, search_table)) {
space_is_free = false;
}
}
if(space_is_free){
//next_start_v = v+num_pages;
return (void*) ((uintptr_t) (v <<12));
}
}
//start again from the real start address
for (uint32_t v=start_v; v<next_start_v; v++) {
bool space_is_free = true;
for(uint32_t i=0; i<num_pages; i++){
if(isMapped((uintptr_t)(v+i)<<12, search_table)) {
space_is_free = false;
}
}
if(space_is_free){
next_start_v = v+num_pages;
return (void*) ((uintptr_t) (v <<12));
}
}
return 0;
}
void setMapping(uintptr_t vaddr, void* frame, 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* 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);
}
}
}
}
}
}
}
}

View File

@@ -50,7 +50,10 @@ typedef struct {
void write_identity_map(pagetable_t* identity_table, uint64_t size); 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 create_basic_page_table(four_lvl_paging_t* table, pagetable_t* kernel_identity);
void load_cr3(void* cr3_value); 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 { //typedef struct {
// same // same

View File

@@ -8,6 +8,7 @@
#include "../sync/semaphore.h" #include "../sync/semaphore.h"
#include "../thread/scheduler.h" #include "../thread/scheduler.h"
#include "../memory/pageframealloc.h" #include "../memory/pageframealloc.h"
#include "../memory/pagetable.h"
void *operator new(size_t, void *); void *operator new(size_t, void *);
//#include "../user/app1/appl.h" //#include "../user/app1/appl.h"
@@ -138,119 +139,6 @@ namespace Syscall {
void kill(Vault &vault, size_t pid){ void kill(Vault &vault, size_t pid){
//vault.scheduler.kill(&apps[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<stop_v; v++) {
bool space_is_free = true;
for(uint32_t i=0; i<num_pages; i++){
if(isMapped((uintptr_t)(v+i)<<12, search_table)) {
space_is_free = false;
}
}
if(space_is_free){
//next_start_v = v+num_pages;
return (void*) ((uintptr_t) (v <<12));
}
}
//start again from the real start address
for (uint32_t v=start_v; v<next_start_v; v++) {
bool space_is_free = true;
for(uint32_t i=0; i<num_pages; i++){
if(isMapped((uintptr_t)(v+i)<<12, search_table)) {
space_is_free = false;
}
}
if(space_is_free){
next_start_v = v+num_pages;
return (void*) ((uintptr_t) (v <<12));
}
}
return 0;
}
void setMapping(uintptr_t vaddr, void* frame, 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* 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) { void* map(Vault *vault, size_t size) {
size_t num_pages = (size + 4096 - 1) / 4096; size_t num_pages = (size + 4096 - 1) / 4096;
//pagetable_t* subbytable = vault->scheduler.active()->subtable; //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) { int fork(Vault &vault, InterruptContext *user_context) {
return 0; Thread* parent = vault.scheduler.active();
//Thread* child = new Thread(false,
return 0;
} }

View File

@@ -19,7 +19,7 @@
*/ */
class IdleThread : public Thread { class IdleThread : public Thread {
public: public:
explicit IdleThread() : Thread(true) {} explicit IdleThread() : Thread(true, 0) {}
/*! \brief Wait for a thread to become ready and sleep in the meantime. /*! \brief Wait for a thread to become ready and sleep in the meantime.
* *

View File

@@ -21,7 +21,7 @@ void Thread::kickoff(uintptr_t param1, uintptr_t param2, uintptr_t param3) {
Guard::leave(); Guard::leave();
if(!thread->isKernel) if(!thread->isKernel)
Core::Ring::switchToUsermode(thread->StackPointer.user, (void*)0x4000000, 0); Core::Ring::switchToUsermode(thread->StackPointer.user, thread->start, 0);
else else
if(thread->start == nullptr) if(thread->start == nullptr)
thread->action(); thread->action();
@@ -33,52 +33,27 @@ void Thread::load_paging(Thread* t){
load_cr3((void*)(t->paging_tree->l4)); 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){ void Thread::map_app(void* code_paddr, uint16_t code_page_num, void* stack_vaddr, uint16_t stack_page_num){
StackPointer.isr = reinterpret_cast<void *>((uintptr_t)PageFrameAllocator::alloc(true)+STACK_SIZE);//(reserved_stack_space_isr + STACK_SIZE);
StackPointer.user = (void*)(0x61FF000+STACK_SIZE);
paging_tree = (four_lvl_paging_t*)PageFrameAllocator::alloc(true); paging_tree = (four_lvl_paging_t*)PageFrameAllocator::alloc(true);
memset(paging_tree, 0, 4096); memset(paging_tree, 0, 4096);
create_basic_page_table(paging_tree, &identity_table); create_basic_page_table(paging_tree, &identity_table);
appcode_table = (pagetable_t*) PageFrameAllocator::alloc(true); // insert app code pages at 0x4000000
memset(appcode_table, 0, 4096); for(uintptr_t i=0; i<(code_page_num*4096); i+=4096){
setMapping(0x4000000+i, (void*)((uintptr_t)code_paddr+i), paging_tree);
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; i<num_pages; i++){
appcode_table->entries[i] = {
.present = 1,
.user = 1,
.address = ((uintptr_t)startframe >> 12) + i
};
} }
// 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)); for(uintptr_t i=0; i<(stack_page_num*4096); i+=4096){
appstack_table->entries[511] = { uintptr_t user_stackframe_p = ((uintptr_t)PageFrameAllocator::alloc(false));
.present = 1, setMapping((uintptr_t)(stack_vaddr)+i, (void*)((uintptr_t)user_stackframe_p), paging_tree);
.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
};
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<void *>((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<uintptr_t>(this), 0, 0); prepareContext(StackPointer.isr, context, kickoff, reinterpret_cast<uintptr_t>(this), 0, 0);
} }

View File

@@ -79,7 +79,7 @@ class Thread {
static void kickoff(uintptr_t param1, uintptr_t param2, uintptr_t param3); static void kickoff(uintptr_t param1, uintptr_t param2, uintptr_t param3);
static void kickoffUsermode (Thread *object); 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: public:
struct{ struct{
void* user; void* user;
@@ -120,7 +120,7 @@ class Thread {
* *
*/ */
explicit 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. /*! \brief Activates the first thread on this CPU.
* *

View File

@@ -75,6 +75,7 @@ extern "C" void main() {
if(receive(blubb, sizeof(blubb))){ if(receive(blubb, sizeof(blubb))){
write(1, blubb, strlen(blubb), 25, (int)id); write(1, blubb, strlen(blubb), 25, (int)id);
write(2, "reply\n", 6); write(2, "reply\n", 6);
memset(&blubb[10], ' ', 3);
itoa(cnt, &blubb[1]); itoa(cnt, &blubb[1]);
reply(blubb, sizeof(blubb)); reply(blubb, sizeof(blubb));
} }