summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2024-03-17 23:48:03 -0400
committerIan Moffett <ian@osmora.org>2024-03-17 23:48:03 -0400
commitc489b2e5f072d73d0cf17d555c6483da55718235 (patch)
tree88b686a625ef59a0a517cfe67beef38d96a0fc69
parent3be9e31b6fd78b4a63b13f8a1562be78050774a0 (diff)
kernel: loader: Keep track of program addr range
Signed-off-by: Ian Moffett <ian@osmora.org>
-rw-r--r--sys/include/sys/loader.h3
-rw-r--r--sys/include/sys/proc.h8
-rw-r--r--sys/kern/kern_loader.c17
-rw-r--r--sys/kern/kern_sched.c32
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");
}