user thread/process and elf loader stub

This commit is contained in:
Matheus
2022-08-13 23:16:34 -03:00
parent e7f4245c6d
commit 33a516a611
14 changed files with 399 additions and 7 deletions
+33
View File
@@ -7,6 +7,7 @@
#include <stdbool.h>
#include <limine.h>
#include <arch/cls.h>
#include <kernel/alloc.h>
vmm_cache* caches;
int klock;
@@ -489,6 +490,38 @@ bool vmm_dealwithrequest(void* addr){
}
void vmm_switchcontext(vmm_context* context){
arch_getcls()->context = context;
arch_mmu_switchcontext(context->context);
}
vmm_context* vmm_newcontext(){
vmm_context* context = alloc(sizeof(vmm_context));
if(!context)
return NULL;
vmm_mapping* map = allocatefirst(caches);
if(!map){
free(context);
return NULL;
}
context->context = arch_mmu_newcontext();
if(!context->context){
free(context);
freeentry(map);
return NULL;
}
map->start = USER_SPACE_START;
map->end = USER_SPACE_END;
context->userstart = map;
return context;
}
void vmm_init(){
printf("%lu mappings per cache\n", VMM_CACHE_ENTRY_COUNT);
caches = newcache();
+123
View File
@@ -0,0 +1,123 @@
#include <kernel/elf.h>
#include <kernel/alloc.h>
#include <errno.h>
static bool check_header64(elf_header64* header){
// XXX throw this into arch
if(header->magic != ELF_MAGIC)
return false;
if(header->bits != ELF_BITS_64)
return false;
if(header->endianness != ELF_ENDIANNESS_LITTLE)
return false;
if(header->isa != ELF_ISA_X86_64)
return false;
return true;
}
int elf_load(thread_t* thread, vnode_t* node, char** argv, char** env){
elf_header64 header;
elf_ph64 ph;
int err = 0;
int readc = vfs_read(&err, node, &header, sizeof(elf_header64), 0);
char* interp = NULL;
if(err)
return err;
if(readc != sizeof(elf_header64) || (!check_header64(&header)))
return EINVAL;
// find out if this needs an interpreter
for(size_t currentph = 0; currentph < header.ph_count; ++currentph){
readc = vfs_read(&err, node, &ph, header.ph_size, header.ph_pos + currentph*header.ph_size);
if(err)
return err;
if(readc != header.ph_size)
return EINVAL;
if(ph.type == PH_TYPE_INTERPRETER){
// load the name and elf header of the interpreter
char* interp = alloc(ph.fsize + 1);
if(!interp)
return ENOMEM;
readc = vfs_read(&err, node, interp, ph.fsize, ph.offset);
if(err){
free(interp);
return err;
}
if(ph.fsize != readc){
free(interp);
return EINVAL;
}
err = vfs_open(&node, thread->proc->root, interp);
if(err){
free(interp);
return err;
}
readc = vfs_read(&err, node, &header, sizeof(elf_header64), 0);
if(err)
goto _fail;
if(readc != sizeof(elf_header64) || (!check_header64(&header))){
err = EINVAL;
goto _fail;
}
break;
}
}
// load program into memory
for(size_t currentph = 0; currentph < header.ph_count; ++currentph){
readc = vfs_read(&err, node, &ph, header.ph_size, header.ph_pos + currentph*header.ph_size);
if(err) goto _fail;
if(readc != header.ph_size){
err = EINVAL;
goto _fail;
}
if(ph.type != PH_TYPE_LOAD)
continue;
}
return 0;
_fail:
if(interp){
free(interp);
vfs_close(node);
}
return err;
}
+96 -1
View File
@@ -6,6 +6,8 @@
#include <arch/mmu.h>
#include <kernel/pmm.h>
#include <kernel/timer.h>
#include <string.h>
#include <kernel/elf.h>
#define THREAD_QUANTUM 10000
@@ -19,6 +21,31 @@ sched_queue queues[QUEUE_COUNT];
sched_queue running;
sched_queue blocked;
static proc_t* allocproc(size_t threadcount){
proc_t* proc = alloc(sizeof(proc_t));
if(!proc)
return NULL;
proc->threads = alloc(sizeof(thread_t*) * threadcount);
if(!proc->threads){
free(proc);
return NULL;
}
proc->context = vmm_newcontext();
if(!proc->context){
free(proc->threads);
free(proc);
return NULL;
}
return proc;
}
static thread_t* allocthread(proc_t* proc, state_t state, pid_t tid, size_t kstacksize){
thread_t* thread = alloc(sizeof(thread_t));
@@ -57,6 +84,13 @@ static thread_t* allocthread(proc_t* proc, state_t state, pid_t tid, size_t ksta
}
static thread_t* freethread(thread_t* thread){
free(thread->regs);
// XXX use free() when it's better
pmm_free(thread->kernelstackbase, thread->stacksize / PAGE_SIZE + 1);
free(thread);
}
static void queue_add(sched_queue* queue, thread_t* thread){
thread->next = NULL;
thread->prev = queue->end;
@@ -158,7 +192,7 @@ static void switch_thread(thread_t* thread){
if(current->proc != thread->proc){
// TODO change proc specific stuff
vmm_switchcontext(thread->proc->context);
}
@@ -170,6 +204,37 @@ static void switch_thread(thread_t* thread){
}
thread_t* sched_newuthread(void* ip, size_t kstacksize, void* stack, proc_t* proc, bool run, int prio){
thread_t* thread = allocthread(NULL, THREAD_STATE_WAITING, 0, kstacksize);
if(!proc){
proc = allocproc(1);
if(!proc){
freethread(thread);
return NULL;
}
}
else{
thread_t** tmp = realloc(proc->threads, sizeof(thread_t*) * (proc->threadcount + 1));
if(!tmp){
freethread(thread);
return NULL;
}
proc->threads = tmp;
++proc->threadcount;
}
thread->priority = prio;
arch_regs_setupuser(thread->regs, ip, stack, true);
if(run)
queue_add(&queues[prio], thread);
return thread;
}
thread_t* sched_newkthread(void* ip, size_t stacksize, bool run, int prio){
thread_t* thread = allocthread(NULL, THREAD_STATE_WAITING, 0, stacksize);
@@ -195,3 +260,33 @@ void sched_init(){
}
void sched_runinit(){
printf("Loading /sbin/init\n");
thread_t* thread = sched_newuthread(NULL, PAGE_SIZE*3, NULL, NULL, true, THREAD_PRIORITY_USER);
proc_t* proc = thread->proc;
proc->root = vfs_root();
proc->cwd = vfs_root();
proc->pid = 1;
vnode_t* node;
size_t ret = vfs_open(&node, vfs_root(), "sbin/init");
if(ret){
printf("Open failed: %s\n", strerror(ret));
_panic("Could not load init", 0);
}
char** argv = {"/sbin/init", ""};
char** env = {""};
ret = elf_load(thread, node, argv, env);
if(ret){
printf("ELF load error: %s\n", strerror(ret));
_panic("Could not load init", 0);
}
switch_thread(thread);
}