diff options
author | Ian Moffett <ian@osmora.org> | 2024-03-17 23:48:03 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2024-03-17 23:48:03 -0400 |
commit | c489b2e5f072d73d0cf17d555c6483da55718235 (patch) | |
tree | 88b686a625ef59a0a517cfe67beef38d96a0fc69 | |
parent | 3be9e31b6fd78b4a63b13f8a1562be78050774a0 (diff) |
kernel: loader: Keep track of program addr range
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r-- | sys/include/sys/loader.h | 3 | ||||
-rw-r--r-- | sys/include/sys/proc.h | 8 | ||||
-rw-r--r-- | sys/kern/kern_loader.c | 17 | ||||
-rw-r--r-- | sys/kern/kern_sched.c | 32 |
4 files changed, 48 insertions, 12 deletions
diff --git a/sys/include/sys/loader.h b/sys/include/sys/loader.h index 74a325c..b1f06c1 100644 --- a/sys/include/sys/loader.h +++ b/sys/include/sys/loader.h @@ -32,6 +32,7 @@ #include <sys/types.h> #include <vm/pmap.h> +#include <vm/vm.h> /* DANGER!: DO NOT CHANGE THESE DEFINES */ #define AT_NULL 0 @@ -61,7 +62,7 @@ struct auxval { #if defined(_KERNEL) int loader_load(struct vas vas, const void *dataptr, struct auxval *auxv, - size_t load_base, char **ld_path); + size_t load_base, char **ld_path, struct vm_range *prog_range); #endif /* defined(_KERNEL) */ #endif /* !_SYS_LOADER_H_ */ diff --git a/sys/include/sys/proc.h b/sys/include/sys/proc.h index c6046d7..75a5c1b 100644 --- a/sys/include/sys/proc.h +++ b/sys/include/sys/proc.h @@ -39,6 +39,12 @@ #include <vm/vm.h> #define PROC_MAX_FDS 256 +#define PROC_MAX_ADDR_RANGE 4 + +enum { + ADDR_RANGE_EXEC = 0, /* Program address range */ + ADDR_RANGE_STACK /* Stack address range */ +}; /* * A task running on the CPU e.g., a process or @@ -50,7 +56,7 @@ struct proc { struct trapframe *tf; struct pcb pcb; struct vas addrsp; - uintptr_t stack_base; + struct vm_range addr_range[PROC_MAX_ADDR_RANGE]; uint8_t is_user; struct filedesc *fds[PROC_MAX_FDS]; TAILQ_ENTRY(proc) link; diff --git a/sys/kern/kern_loader.c b/sys/kern/kern_loader.c index 23249ea..e62e2b4 100644 --- a/sys/kern/kern_loader.c +++ b/sys/kern/kern_loader.c @@ -54,7 +54,7 @@ __KERNEL_META("$Hyra$: kern_loader.c, Ian Marco Moffett, " (void *)((uintptr_t)hdr + (hdrptr)->e_phoff + (hdrptr->e_phentsize*IDX)) int loader_load(struct vas vas, const void *dataptr, struct auxval *auxv, - size_t load_base, char **ld_path) + size_t load_base, char **ld_path, struct vm_range *prog_range) { const Elf64_Ehdr *hdr = dataptr; Elf64_Phdr *phdr; @@ -64,6 +64,9 @@ int loader_load(struct vas vas, const void *dataptr, struct auxval *auxv, size_t misalign, page_count, map_len; int status; + uintptr_t start_addr = (uintptr_t)-1; + uintptr_t end_addr = 0; + const size_t GRANULE = vm_get_page_size(); void *tmp_ptr; @@ -94,6 +97,16 @@ int loader_load(struct vas vas, const void *dataptr, struct auxval *auxv, physmem = vm_alloc_pageframe(page_count); map_len = page_count * GRANULE; + /* + * Now we want to compute the start address of the + * program and the end address. + */ + if (start_addr == (uintptr_t)-1) { + start_addr = phdr->p_vaddr; + } + + end_addr = __MAX(end_addr, phdr->p_vaddr + page_count*GRANULE); + /* Do we not have enough page frames? */ if (physmem == 0) { DBG("Failed to allocate physical memory\n"); @@ -134,5 +147,7 @@ int loader_load(struct vas vas, const void *dataptr, struct auxval *auxv, auxv->at_entry = hdr->e_entry + load_base; auxv->at_phent = hdr->e_phentsize; auxv->at_phnum = hdr->e_phnum; + prog_range->start = start_addr; + prog_range->end = end_addr; return 0; } diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index 7b3776d..1fca89d 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -211,15 +211,19 @@ sched_create_stack(struct vas vas, bool user, char *argvp[], int status; uintptr_t stack; const vm_prot_t USER_STACK_PROT = PROT_WRITE | PROT_USER; + struct vm_range *stack_range = &td->addr_range[ADDR_RANGE_STACK]; if (!user) { stack = (uintptr_t)dynalloc(STACK_SIZE); - td->stack_base = (uintptr_t)stack; + stack_range->start = (uintptr_t)stack; + stack_range->end = (uintptr_t)stack + STACK_SIZE; return sched_init_stack((void *)(stack + STACK_SIZE), argvp, envp, auxv); } stack = vm_alloc_pageframe(STACK_PAGES); - td->stack_base = stack; + + stack_range->start = stack; + stack_range->end = stack + STACK_SIZE; status = vm_map_create(vas, stack, stack, USER_STACK_PROT, STACK_SIZE); if (status != 0) { @@ -233,9 +237,10 @@ sched_create_stack(struct vas vas, bool user, char *argvp[], static struct proc * sched_create_td(uintptr_t rip, char *argvp[], char *envp[], struct auxval auxv, - struct vas vas, bool is_user) + struct vas vas, bool is_user, struct vm_range *prog_range) { struct proc *td; + struct vm_range *exec_range; uintptr_t stack; struct trapframe *tf; @@ -251,6 +256,8 @@ sched_create_td(uintptr_t rip, char *argvp[], char *envp[], struct auxval auxv, return NULL; } + + memset(td, 0, sizeof(struct proc)); stack = sched_create_stack(vas, is_user, argvp, envp, auxv, td); if (stack == 0) { dynfree(tf); @@ -259,14 +266,17 @@ sched_create_td(uintptr_t rip, char *argvp[], char *envp[], struct auxval auxv, } memset(tf, 0, sizeof(struct trapframe)); - memset(td, 0, sizeof(struct proc)); /* Setup process itself */ + exec_range = &td->addr_range[ADDR_RANGE_EXEC]; td->pid = 0; /* Don't assign PID until enqueued */ td->cpu = NULL; /* Not yet assigned a core */ td->tf = tf; td->addrsp = vas; td->is_user = is_user; + if (prog_range != NULL) { + memcpy(exec_range, prog_range, sizeof(struct vm_range)); + } processor_init_pcb(td); /* Allocate standard file descriptors */ @@ -286,6 +296,8 @@ sched_create_td(uintptr_t rip, char *argvp[], char *envp[], struct auxval auxv, static void sched_destroy_td(struct proc *td) { + const struct vm_range *stack_range = &td->addr_range[ADDR_RANGE_STACK]; + processor_free_pcb(td); /* @@ -295,9 +307,9 @@ sched_destroy_td(struct proc *td) * program to perform the proper deallocation method. */ if (td->is_user) { - vm_free_pageframe(td->stack_base, STACK_PAGES); + vm_free_pageframe(stack_range->start, STACK_PAGES); } else { - dynfree((void *)td->stack_base); + dynfree((void *)stack_range->start); } /* Close all of the file descriptors */ @@ -393,6 +405,7 @@ void sched_init(void) { struct proc *init; + struct vm_range init_range; struct auxval auxv = {0}, ld_auxv = {0}; struct vas vas = pmap_create_vas(vm_get_ctx()); const char *init_bin, *ld_bin; @@ -406,17 +419,18 @@ sched_init(void) if ((init_bin = initramfs_open("/usr/sbin/init")) == NULL) { panic("Could not open /usr/boot/init\n"); } - if (loader_load(vas, init_bin, &auxv, 0, &ld_path) != 0) { + if (loader_load(vas, init_bin, &auxv, 0, &ld_path, &init_range) != 0) { panic("Could not load init\n"); } if ((ld_bin = initramfs_open(ld_path)) == NULL) { panic("Could not open %s\n", ld_path); } - if (loader_load(vas, ld_bin, &ld_auxv, 0x00, NULL) != 0) { + if (loader_load(vas, ld_bin, &ld_auxv, 0x00, NULL, &init_range) != 0) { panic("Could not load %s\n", ld_path); } - init = sched_create_td((uintptr_t)ld_auxv.at_entry, argv, envp, ld_auxv, vas, true); + init = sched_create_td((uintptr_t)ld_auxv.at_entry, argv, envp, + ld_auxv, vas, true, &init_range); if (init == NULL) { panic("Failed to create thread for init\n"); } |