From 59df7bdadbfd50bfaf95cde442c7380cce535254 Mon Sep 17 00:00:00 2001 From: Quinn Stephens Date: Thu, 7 Mar 2024 13:35:04 -0500 Subject: kern: sched: Refactor queue and ctx switch code Signed-off-by: Quinn Stephens Signed-off-by: Ian Moffett --- sys/kern/kern_sched.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index f61c592..266ce39 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -97,13 +97,11 @@ sched_dequeue_td(void) spinlock_acquire(&tdq_lock); - if (TAILQ_EMPTY(&td_queue)) { - goto done; + if (!TAILQ_EMPTY(&td_queue)) { + td = TAILQ_FIRST(&td_queue); + TAILQ_REMOVE(&td_queue, td, link); } - td = TAILQ_FIRST(&td_queue); - TAILQ_REMOVE(&td_queue, td, link); -done: spinlock_release(&tdq_lock); return td; } @@ -174,11 +172,9 @@ sched_context_switch(struct trapframe *tf) * If we have no threads, we should not * preempt at all. */ - if (nthread == 0) { - goto done; - } else if ((next_td = sched_dequeue_td()) == NULL) { - /* Empty */ - goto done; + if (nthread == 0 || (next_td = sched_dequeue_td()) == NULL) { + sched_oneshot(); + return; } if (state->td != NULL) { @@ -196,7 +192,7 @@ sched_context_switch(struct trapframe *tf) if (td != NULL) { sched_enqueue_td(td); } -done: + sched_oneshot(); } -- cgit v1.2.3 From 39ed0640f0e33b8a48ba82334de219e9fe4ed0e6 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Thu, 7 Mar 2024 22:47:49 -0500 Subject: kernel: sched: Add support for user threads Signed-off-by: Ian Moffett --- Makefile.in | 12 +++- sys/include/arch/amd64/frame.h | 7 ++ sys/include/sys/proc.h | 2 + sys/kern/kern_sched.c | 153 +++++++++++++++++++++++++++++++++++++---- usr.sbin/init/init | Bin 944 -> 0 bytes 5 files changed, 157 insertions(+), 17 deletions(-) delete mode 100755 usr.sbin/init/init (limited to 'sys/kern') diff --git a/Makefile.in b/Makefile.in index daa0cf9..5e99728 100644 --- a/Makefile.in +++ b/Makefile.in @@ -69,16 +69,22 @@ override KERNEL_ASMOBJECTS = $(KERNEL_ASMFILES:.S=.S.o) override KERNEL_HEADER_DEPS = $(KERNEL_CFILES:.c=.d) .PHONY: all -all: base init lib base/usr/lib/ld.so base/boot/hyra-kernel +all: base lib userland base/usr/lib/ld.so base/boot/hyra-kernel rm -f sys/include/machine rm -rf iso_root -base/boot/init: usr.sbin/init/ +base/usr/sbin/init: cd usr.sbin/; make CC=$(CC) LD=$(LD) - cp usr.sbin/init/init base/boot/ + mv usr.sbin/init/init base/usr/sbin/ + +# TODO: Make this more flexible +.PHONY: userland +userland: base/usr/sbin/init base: mkdir -p base/usr/lib/ + mkdir -p base/usr/sbin/ + mkdir -p base/boot/ lib: lib/mlibc base/usr/lib/ld.so diff --git a/sys/include/arch/amd64/frame.h b/sys/include/arch/amd64/frame.h index a2e1a05..298a836 100644 --- a/sys/include/arch/amd64/frame.h +++ b/sys/include/arch/amd64/frame.h @@ -67,5 +67,12 @@ struct trapframe { (FRAME)->rsp = SP; \ (FRAME)->ss = 0x10; \ +#define init_frame_user(FRAME, IP, SP) \ + (FRAME)->rip = IP; \ + (FRAME)->cs = 0x18 | 3; \ + (FRAME)->rflags = 0x202; \ + (FRAME)->rsp = SP; \ + (FRAME)->ss = 0x20 | 3; \ + #endif /* !defined(__ASSEMBLER__) */ #endif /* !_AMD64_FRAME_H_ */ diff --git a/sys/include/sys/proc.h b/sys/include/sys/proc.h index f45e4c6..0d3b45e 100644 --- a/sys/include/sys/proc.h +++ b/sys/include/sys/proc.h @@ -34,6 +34,7 @@ #include #include #include +#include /* * A task running on the CPU e.g., a process or @@ -43,6 +44,7 @@ struct proc { pid_t pid; struct cpu_info *cpu; struct trapframe *tf; + struct vas addrsp; TAILQ_ENTRY(proc) link; }; diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index 266ce39..9231ea2 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -34,10 +34,20 @@ #include #include #include +#include +#include +#include #include +#include +#include +#include +#include #include #include +#define STACK_PAGES 8 +#define STACK_SIZE (STACK_PAGES*vm_get_page_size()) + /* * Thread ready queue - all threads ready to be * scheduled should be added to this queue. @@ -119,12 +129,99 @@ sched_enter(void) } } +static uintptr_t +sched_init_stack(void *stack_top, char *argvp[], char *envp[], struct auxval auxv) +{ + uintptr_t *sp = stack_top; + size_t envp_len, argv_len, len; + uintptr_t old_sp = 0; + uintptr_t ret; + + for (envp_len = 0; envp[envp_len] != NULL; ++envp_len) { + len = strlen(envp[envp_len]); + sp = (void *)((uintptr_t)sp - len - 1); + memcpy(sp, envp[envp_len], len); + } + + for (argv_len = 0; argvp[argv_len] != NULL; ++argv_len) { + len = strlen(argvp[argv_len]); + sp = (void *)((uintptr_t)sp - len - 1); + memcpy(sp, argvp[envp_len], len); + } + + sp = (uint64_t *)(((uintptr_t)sp / 16) * 16); + if (((argv_len + envp_len + 1) & 1) != 0) { + sp--; + } + + *--sp = 0; + *--sp = 0; + *--sp = auxv.at_entry; + *--sp = AT_ENTRY; + *--sp = auxv.at_phent; + *--sp = AT_PHENT; + *--sp = auxv.at_phnum; + *--sp = AT_PHNUM; + *--sp = auxv.at_phdr; + *--sp = AT_PHDR; + + old_sp = (uintptr_t)sp; + + /* End of envp */ + *--sp = 0; + sp -= envp_len; + for (int i = 0; i < envp_len; ++i) { + old_sp -= strlen(envp[i]) + 1; + sp[i] = old_sp; + } + + /* End of argvp */ + *--sp = 0; + sp -= argv_len; + for (int i = 0; i < argv_len; ++i) { + old_sp -= strlen(argvp[i]) + 1; + sp[i] = old_sp; + } + + /* Argc */ + *--sp = argv_len; + + ret = (uintptr_t)stack_top; + ret -= (ret - (uintptr_t)sp); + return ret; +} + +static uintptr_t +sched_create_stack(struct vas vas, bool user) +{ + int status; + uintptr_t user_stack; + const vm_prot_t USER_STACK_PROT = PROT_WRITE | PROT_USER; + + if (!user) { + return (uintptr_t)dynalloc(STACK_SIZE); + } + + user_stack = vm_alloc_pageframe(STACK_PAGES); + + status = vm_map_create(vas, user_stack, user_stack, USER_STACK_PROT, + STACK_SIZE); + + if (status != 0) { + return 0; + } + + memset(PHYS_TO_VIRT(user_stack), 0, STACK_SIZE); + return user_stack; +} + static struct proc * -sched_create_td(uintptr_t rip) +sched_create_td(uintptr_t rip, char *argvp[], char *envp[], struct auxval auxv, + struct vas vas, bool is_user) { - const size_t STACK_SIZE = 0x100000; /* 1 MiB */ struct proc *td; - void *stack; + uintptr_t stack, sp; + void *stack_virt; struct trapframe *tf; tf = dynalloc(sizeof(struct trapframe)); @@ -132,29 +229,37 @@ sched_create_td(uintptr_t rip) return NULL; } - stack = dynalloc(STACK_SIZE); - if (stack == NULL) { + stack = sched_create_stack(vas, is_user); + if (stack == 0) { dynfree(tf); return NULL; } + stack_virt = (is_user) ? PHYS_TO_VIRT(stack) : (void *)stack; + td = dynalloc(sizeof(struct proc)); if (td == NULL) { + /* TODO: Free stack */ dynfree(tf); - dynfree(stack); return NULL; } memset(tf, 0, sizeof(struct trapframe)); - memset(stack, 0, STACK_SIZE); + sp = sched_init_stack((void *)((uintptr_t)stack_virt + STACK_SIZE), + argvp, envp, auxv); /* Setup process itself */ td->pid = 0; /* Don't assign PID until enqueued */ td->cpu = NULL; /* Not yet assigned a core */ td->tf = tf; + td->addrsp = vas; /* Setup trapframe */ - init_frame(tf, rip, (uintptr_t)stack + STACK_SIZE - 1); + if (!is_user) { + init_frame(tf, rip, sp); + } else { + init_frame_user(tf, rip, VIRT_TO_PHYS(sp)); + } return td; } @@ -193,20 +298,40 @@ sched_context_switch(struct trapframe *tf) sched_enqueue_td(td); } + pmap_switch_vas(vm_get_ctx(), next_td->addrsp); sched_oneshot(); } void sched_init(void) { + struct proc *init; + struct auxval auxv = {0}; + struct vas vas = pmap_create_vas(vm_get_ctx()); + const char *init_bin; + + int status; + char *ld_path; + char *argv[] = {"/boot/init", NULL}; + char *envp[] = {NULL}; + TAILQ_INIT(&td_queue); - /* - * TODO: Create init with sched_create_td() - * and enqueue with sched_enqueue_td() - */ - (void)sched_create_td; - (void)sched_enqueue_td; + if ((init_bin = initramfs_open("/boot/init")) == NULL) { + panic("Could not open /boot/init\n"); + } + + status = loader_load(vas, init_bin, &auxv, 0, &ld_path); + if (status != 0) { + panic("Could not load init\n"); + } + + init = sched_create_td((uintptr_t)auxv.at_entry, argv, envp, auxv, vas, true); + if (init == NULL) { + panic("Failed to create thread for init\n"); + } + + sched_enqueue_td(init); } /* diff --git a/usr.sbin/init/init b/usr.sbin/init/init deleted file mode 100755 index 8b83844..0000000 Binary files a/usr.sbin/init/init and /dev/null differ -- cgit v1.2.3 From 9211231b616354537aa447708cb2f90123b8f092 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Sun, 10 Mar 2024 20:09:28 -0400 Subject: kernel: loader: Cleanup Signed-off-by: Ian Moffett --- sys/kern/kern_loader.c | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/kern_loader.c b/sys/kern/kern_loader.c index 53ba8c2..23249ea 100644 --- a/sys/kern/kern_loader.c +++ b/sys/kern/kern_loader.c @@ -61,12 +61,10 @@ int loader_load(struct vas vas, const void *dataptr, struct auxval *auxv, vm_prot_t prot = PROT_USER; uintptr_t physmem; - uintptr_t max_addr, map_addr; - size_t misalign, page_count; - + size_t misalign, page_count, map_len; int status; - const size_t GRANULE = vm_get_page_size(); + const size_t GRANULE = vm_get_page_size(); void *tmp_ptr; if (auxv == NULL) { @@ -93,26 +91,8 @@ int loader_load(struct vas vas, const void *dataptr, struct auxval *auxv, misalign = phdr->p_vaddr & (GRANULE - 1); page_count = __DIV_ROUNDUP(phdr->p_memsz + misalign, GRANULE); - max_addr = phdr->p_vaddr + (GRANULE * page_count); - - /* - * We are assuming this is a user program that we are loading. - * All user programs should be on the lower half of the address - * space. We will check that before we begin doing anything here. - * - * We are also going to check if the virtual address the program - * header refers to overflows into the higher half. If anything - * goes into the higher half, we won't simply drop the phdr, - * we'll instead assume caller error and return -EINVAL. - */ - if (phdr->p_vaddr >= VM_HIGHER_HALF) { - return -EINVAL; - } else if (max_addr >= VM_HIGHER_HALF) { - /* Overflows into higher half */ - return -EINVAL; - } - physmem = vm_alloc_pageframe(page_count); + map_len = page_count * GRANULE; /* Do we not have enough page frames? */ if (physmem == 0) { @@ -121,14 +101,9 @@ int loader_load(struct vas vas, const void *dataptr, struct auxval *auxv, return -ENOMEM; } - map_addr = phdr->p_vaddr + load_base; - status = vm_map_create(vas, map_addr, physmem, prot, page_count*GRANULE); + status = vm_map_create(vas, phdr->p_vaddr + load_base, physmem, prot, map_len); if (status != 0) { - DBG("Failed to map 0x%p - 0x%p\n", - phdr->p_vaddr + load_base, - (phdr->p_vaddr + load_base) + (page_count * GRANULE)); - return status; } -- cgit v1.2.3 From 2cfcba7e6ed64a00ca01dcc7247ecfc5edacfdb2 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Wed, 13 Mar 2024 21:08:50 -0400 Subject: kernel: sched: Improve stack init code Signed-off-by: Ian Moffett --- sys/include/sys/loader.h | 27 +++++---- sys/kern/kern_sched.c | 139 +++++++++++++++++++++++++---------------------- 2 files changed, 91 insertions(+), 75 deletions(-) (limited to 'sys/kern') diff --git a/sys/include/sys/loader.h b/sys/include/sys/loader.h index c1aa426..74a325c 100644 --- a/sys/include/sys/loader.h +++ b/sys/include/sys/loader.h @@ -33,17 +33,22 @@ #include #include -#define AT_NULL 0 -#define AT_IGNORE 1 -#define AT_EXECFD 2 -#define AT_PHDR 3 -#define AT_PHENT 4 -#define AT_PHNUM 5 -#define AT_PAGESZ 6 -#define AT_BASE 7 -#define AT_FLAGS 8 -#define AT_ENTRY 9 -#define AT_SECURE 10 +/* DANGER!: DO NOT CHANGE THESE DEFINES */ +#define AT_NULL 0 +#define AT_ENTRY 1 +#define AT_PHDR 2 +#define AT_PHENT 3 +#define AT_PHNUM 4 +#define AT_EXECPATH 5 +#define AT_SECURE 6 +#define AT_RANDOM 7 +#define AT_EXECFN 8 + +#define STACK_PUSH(ptr, val) *(--ptr) = val +#define AUXVAL(ptr, tag, val) __extension__ ({ \ + STACK_PUSH(ptr, val); \ + STACK_PUSH(ptr, tag); \ +}); /* Auxiliary Vector */ struct auxval { diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index 9231ea2..7be8241 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -48,6 +48,20 @@ #define STACK_PAGES 8 #define STACK_SIZE (STACK_PAGES*vm_get_page_size()) +/* + * The PHYS_TO_VIRT/VIRT_TO_PHYS macros convert + * addresses to lower and higher half addresses. + * Userspace addresses are on the lower half, + * therefore, we can just wrap over these to + * keep things simple. + * + * XXX: TODO: This won't work when not identity mapping + * lowerhalf addresses. Once that is updated, + * get rid of this. + */ +#define USER_TO_KERN(user) PHYS_TO_VIRT(user) +#define KERN_TO_USER(kern) VIRT_TO_PHYS(kern) + /* * Thread ready queue - all threads ready to be * scheduled should be added to this queue. @@ -133,86 +147,87 @@ static uintptr_t sched_init_stack(void *stack_top, char *argvp[], char *envp[], struct auxval auxv) { uintptr_t *sp = stack_top; - size_t envp_len, argv_len, len; - uintptr_t old_sp = 0; - uintptr_t ret; - - for (envp_len = 0; envp[envp_len] != NULL; ++envp_len) { - len = strlen(envp[envp_len]); - sp = (void *)((uintptr_t)sp - len - 1); - memcpy(sp, envp[envp_len], len); + void *env_ptr = NULL, *argv_ptr = NULL; + size_t argc, envc, len; + + /* Copy argument and environment strings */ + for (envc = 0; envp[envc] != NULL; ++envc) { + len = strlen(envp[envc]); + sp -= len - 1; + memcpy(sp, envp[envc], len); } - for (argv_len = 0; argvp[argv_len] != NULL; ++argv_len) { - len = strlen(argvp[argv_len]); - sp = (void *)((uintptr_t)sp - len - 1); - memcpy(sp, argvp[envp_len], len); - } + __assert(envc >= 1); + env_ptr = sp; - sp = (uint64_t *)(((uintptr_t)sp / 16) * 16); - if (((argv_len + envp_len + 1) & 1) != 0) { - sp--; + for (argc = 0; argvp[argc] != NULL; ++argc) { + len = strlen(argvp[argc]); + sp -= len - 1; + memcpy(sp, argvp[argc], len); } - *--sp = 0; - *--sp = 0; - *--sp = auxv.at_entry; - *--sp = AT_ENTRY; - *--sp = auxv.at_phent; - *--sp = AT_PHENT; - *--sp = auxv.at_phnum; - *--sp = AT_PHNUM; - *--sp = auxv.at_phdr; - *--sp = AT_PHDR; - - old_sp = (uintptr_t)sp; - - /* End of envp */ - *--sp = 0; - sp -= envp_len; - for (int i = 0; i < envp_len; ++i) { - old_sp -= strlen(envp[i]) + 1; - sp[i] = old_sp; + __assert(argc >= 1); + argv_ptr = sp; + + /* Ensure the stack is aligned */ + sp = (void *)__ALIGN_DOWN((uintptr_t)sp, 16); + if (((argc + envc + 1) & 1) != 0) + --sp; + + AUXVAL(sp, AT_NULL, 0x0); + AUXVAL(sp, AT_SECURE, 0x0); + AUXVAL(sp, AT_ENTRY, auxv.at_entry); + AUXVAL(sp, AT_PHDR, auxv.at_phdr); + AUXVAL(sp, AT_PHNUM, auxv.at_phnum); + STACK_PUSH(sp, 0); + + /* Push environment string pointers */ + for (int i = 0; i < envc; ++i) { + len = strlen(env_ptr); + sp -= len; + + *sp = (uintptr_t)KERN_TO_USER((uintptr_t)env_ptr); + env_ptr = (char *)env_ptr + len; } - /* End of argvp */ - *--sp = 0; - sp -= argv_len; - for (int i = 0; i < argv_len; ++i) { - old_sp -= strlen(argvp[i]) + 1; - sp[i] = old_sp; + /* Push argument string pointers */ + STACK_PUSH(sp, 0); + for (int i = 0; i < argc; ++i) { + len = strlen(argv_ptr); + sp -= len; + + *sp = (uintptr_t)KERN_TO_USER((uintptr_t)argv_ptr); + argv_ptr = (char *)argv_ptr + len; } - /* Argc */ - *--sp = argv_len; + STACK_PUSH(sp, argc); - ret = (uintptr_t)stack_top; - ret -= (ret - (uintptr_t)sp); - return ret; + return (uintptr_t)sp; } static uintptr_t -sched_create_stack(struct vas vas, bool user) +sched_create_stack(struct vas vas, bool user, char *argvp[], + char *envp[], struct auxval auxv) { int status; - uintptr_t user_stack; + uintptr_t stack; const vm_prot_t USER_STACK_PROT = PROT_WRITE | PROT_USER; if (!user) { - return (uintptr_t)dynalloc(STACK_SIZE); + stack = (uintptr_t)dynalloc(STACK_SIZE); + return sched_init_stack((void *)(stack + STACK_SIZE), argvp, envp, auxv); } - user_stack = vm_alloc_pageframe(STACK_PAGES); - - status = vm_map_create(vas, user_stack, user_stack, USER_STACK_PROT, - STACK_SIZE); + stack = vm_alloc_pageframe(STACK_PAGES); + status = vm_map_create(vas, stack, stack, USER_STACK_PROT, STACK_SIZE); if (status != 0) { return 0; } - memset(PHYS_TO_VIRT(user_stack), 0, STACK_SIZE); - return user_stack; + memset(USER_TO_KERN(stack), 0, STACK_SIZE); + stack = sched_init_stack((void *)USER_TO_KERN(stack + STACK_SIZE), argvp, envp, auxv); + return stack; } static struct proc * @@ -220,8 +235,7 @@ sched_create_td(uintptr_t rip, char *argvp[], char *envp[], struct auxval auxv, struct vas vas, bool is_user) { struct proc *td; - uintptr_t stack, sp; - void *stack_virt; + uintptr_t stack; struct trapframe *tf; tf = dynalloc(sizeof(struct trapframe)); @@ -229,14 +243,12 @@ sched_create_td(uintptr_t rip, char *argvp[], char *envp[], struct auxval auxv, return NULL; } - stack = sched_create_stack(vas, is_user); + stack = sched_create_stack(vas, is_user, argvp, envp, auxv); if (stack == 0) { dynfree(tf); return NULL; } - stack_virt = (is_user) ? PHYS_TO_VIRT(stack) : (void *)stack; - td = dynalloc(sizeof(struct proc)); if (td == NULL) { /* TODO: Free stack */ @@ -245,8 +257,7 @@ sched_create_td(uintptr_t rip, char *argvp[], char *envp[], struct auxval auxv, } memset(tf, 0, sizeof(struct trapframe)); - sp = sched_init_stack((void *)((uintptr_t)stack_virt + STACK_SIZE), - argvp, envp, auxv); + memset(td, 0, sizeof(struct proc)); /* Setup process itself */ td->pid = 0; /* Don't assign PID until enqueued */ @@ -256,9 +267,9 @@ sched_create_td(uintptr_t rip, char *argvp[], char *envp[], struct auxval auxv, /* Setup trapframe */ if (!is_user) { - init_frame(tf, rip, sp); + init_frame(tf, rip, (uintptr_t)stack); } else { - init_frame_user(tf, rip, VIRT_TO_PHYS(sp)); + init_frame_user(tf, rip, KERN_TO_USER(stack)); } return td; } -- cgit v1.2.3 From fc9c7bab5bb64dd2242e9e9dff98060d64af2a32 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Wed, 13 Mar 2024 21:27:39 -0400 Subject: kernel/amd64: machdep: Add pcb init code This commit adds a processor specific routine which sets up the Process Control Block for a thread Signed-off-by: Ian Moffett --- sys/arch/amd64/amd64/machdep.c | 25 +++++++++++++++++++++++++ sys/include/sys/machdep.h | 2 ++ sys/kern/kern_sched.c | 2 ++ 3 files changed, 29 insertions(+) (limited to 'sys/kern') diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index 809e395..0789f5a 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -154,6 +154,31 @@ intr_unmask(void) __ASMV("sti"); } +int +processor_init_pcb(struct proc *proc) +{ + struct pcb *pcb = &proc->pcb; + const uint16_t FPU_FCW = 0x33F; + const uint32_t SSE_MXCSR = 0x1F80; + + /* Allocate FPU save area, aligned on a 16 byte boundary */ + pcb->fpu_state = PHYS_TO_VIRT(vm_alloc_pageframe(1)); + if (pcb->fpu_state == 0) { + return -1; + } + + /* + * Setup x87 FPU control word and SSE MXCSR bits + * as per the sysv ABI + */ + __ASMV("fldcw %0\n" + "ldmxcsr %1" + :: "m" (FPU_FCW), + "m" (SSE_MXCSR) : "memory"); + + amd64_fxsave(pcb->fpu_state); + return 0; +} void processor_init(void) { diff --git a/sys/include/sys/machdep.h b/sys/include/sys/machdep.h index 713b7db..151d5f8 100644 --- a/sys/include/sys/machdep.h +++ b/sys/include/sys/machdep.h @@ -32,11 +32,13 @@ #include #include +#include #if defined(_KERNEL) #define MAXCPUS 32 +int processor_init_pcb(struct proc *proc); void processor_init(void); void processor_halt(void); void intr_mask(void); diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index 7be8241..f8f09c4 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -264,6 +265,7 @@ sched_create_td(uintptr_t rip, char *argvp[], char *envp[], struct auxval auxv, td->cpu = NULL; /* Not yet assigned a core */ td->tf = tf; td->addrsp = vas; + processor_init_pcb(td); /* Setup trapframe */ if (!is_user) { -- cgit v1.2.3 From 39d4aa3a106f898d09b98e41ef44fb4891eda1ce Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Wed, 13 Mar 2024 21:40:06 -0400 Subject: kernel/amd64: machdep: Add context switch helper Signed-off-by: Ian Moffett --- sys/arch/amd64/amd64/machdep.c | 13 +++++++++++++ sys/include/sys/machdep.h | 1 + sys/kern/kern_sched.c | 4 ++++ 3 files changed, 18 insertions(+) (limited to 'sys/kern') diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index 0789f5a..5327189 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -179,6 +179,19 @@ processor_init_pcb(struct proc *proc) amd64_fxsave(pcb->fpu_state); return 0; } + +void +processor_switch_to(struct proc *old_td, struct proc *new_td) +{ + struct pcb *old_pcb = (old_td != NULL) ? &old_td->pcb : NULL; + struct pcb *new_pcb = &new_td->pcb; + + if (old_pcb != NULL) { + amd64_fxsave(old_pcb->fpu_state); + } + amd64_fxrstor(new_pcb->fpu_state); +} + void processor_init(void) { diff --git a/sys/include/sys/machdep.h b/sys/include/sys/machdep.h index 151d5f8..b6edf14 100644 --- a/sys/include/sys/machdep.h +++ b/sys/include/sys/machdep.h @@ -39,6 +39,7 @@ #define MAXCPUS 32 int processor_init_pcb(struct proc *proc); +void processor_switch_to(struct proc *old_td, struct proc *new_td); void processor_init(void); void processor_halt(void); void intr_mask(void); diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index f8f09c4..bc96146 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -311,6 +311,10 @@ sched_context_switch(struct trapframe *tf) sched_enqueue_td(td); } + /* Do architecture specific context switch logic */ + processor_switch_to(td, next_td); + + /* Done, switch out our vas and oneshot */ pmap_switch_vas(vm_get_ctx(), next_td->addrsp); sched_oneshot(); } -- cgit v1.2.3 From 7a32267fcc81af31d595373884911d503b0a9df8 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Thu, 14 Mar 2024 20:55:54 -0400 Subject: kernel: sched: Keep track of stack and privilege Signed-off-by: Ian Moffett --- sys/include/sys/proc.h | 2 ++ sys/kern/kern_sched.c | 16 ++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'sys/kern') diff --git a/sys/include/sys/proc.h b/sys/include/sys/proc.h index 34a5037..7181ecb 100644 --- a/sys/include/sys/proc.h +++ b/sys/include/sys/proc.h @@ -47,6 +47,8 @@ struct proc { struct trapframe *tf; struct pcb pcb; struct vas addrsp; + uintptr_t stack_base; + uint8_t is_user; TAILQ_ENTRY(proc) link; }; diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index bc96146..f985f62 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -208,7 +208,7 @@ sched_init_stack(void *stack_top, char *argvp[], char *envp[], struct auxval aux static uintptr_t sched_create_stack(struct vas vas, bool user, char *argvp[], - char *envp[], struct auxval auxv) + char *envp[], struct auxval auxv, struct proc *td) { int status; uintptr_t stack; @@ -216,10 +216,12 @@ sched_create_stack(struct vas vas, bool user, char *argvp[], if (!user) { stack = (uintptr_t)dynalloc(STACK_SIZE); + td->stack_base = (uintptr_t)stack; return sched_init_stack((void *)(stack + STACK_SIZE), argvp, envp, auxv); } stack = vm_alloc_pageframe(STACK_PAGES); + td->stack_base = stack; status = vm_map_create(vas, stack, stack, USER_STACK_PROT, STACK_SIZE); if (status != 0) { @@ -244,16 +246,17 @@ sched_create_td(uintptr_t rip, char *argvp[], char *envp[], struct auxval auxv, return NULL; } - stack = sched_create_stack(vas, is_user, argvp, envp, auxv); - if (stack == 0) { + td = dynalloc(sizeof(struct proc)); + if (td == NULL) { + /* TODO: Free stack */ dynfree(tf); return NULL; } - td = dynalloc(sizeof(struct proc)); - if (td == NULL) { - /* TODO: Free stack */ + stack = sched_create_stack(vas, is_user, argvp, envp, auxv, td); + if (stack == 0) { dynfree(tf); + dynfree(td); return NULL; } @@ -265,6 +268,7 @@ sched_create_td(uintptr_t rip, char *argvp[], char *envp[], struct auxval auxv, td->cpu = NULL; /* Not yet assigned a core */ td->tf = tf; td->addrsp = vas; + td->is_user = is_user; processor_init_pcb(td); /* Setup trapframe */ -- cgit v1.2.3 From d0f81e3d2afdf7a89fd466799f2d900da9f2ac40 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Thu, 14 Mar 2024 20:57:12 -0400 Subject: kernel: sched: Add exit routine Signed-off-by: Ian Moffett --- sys/include/sys/sched.h | 1 + sys/kern/kern_sched.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) (limited to 'sys/kern') diff --git a/sys/include/sys/sched.h b/sys/include/sys/sched.h index d803df0..f06c104 100644 --- a/sys/include/sys/sched.h +++ b/sys/include/sys/sched.h @@ -38,6 +38,7 @@ #include void sched_init(void); +void sched_exit(void); void sched_context_switch(struct trapframe *tf); __noreturn diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index f985f62..c3d1e09 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -280,6 +280,50 @@ sched_create_td(uintptr_t rip, char *argvp[], char *envp[], struct auxval auxv, return td; } +static void +sched_destroy_td(struct proc *td) +{ + processor_free_pcb(td); + + /* + * User stacks are allocated with vm_alloc_pageframe(), + * while kernel stacks are allocated with dynalloc(). + * We want to check if we are a user program or kernel + * program to perform the proper deallocation method. + */ + if (td->is_user) { + vm_free_pageframe(td->stack_base, STACK_PAGES); + } else { + dynfree((void *)td->stack_base); + } + + pmap_free_vas(vm_get_ctx(), td->addrsp); + dynfree(td); +} + +void +sched_exit(void) +{ + struct sched_state *state; + struct cpu_info *ci; + struct proc *td; + struct vas kvas = vm_get_kvas(); + + intr_mask(); + + /* Get the thread running on the current processor */ + ci = this_cpu(); + state = &ci->sched_state; + td = state->td; + + /* Switch back to the kernel address space and destroy ourself */ + pmap_switch_vas(vm_get_ctx(), kvas); + sched_destroy_td(td); + + intr_unmask(); + sched_enter(); +} + /* * Thread context switch routine */ -- cgit v1.2.3 From cec19cdab21e1eda7ae149792d1529bb03c0714b Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Thu, 14 Mar 2024 21:47:23 -0400 Subject: kernel: Add support for syscalls Signed-off-by: Ian Moffett --- sys/arch/amd64/amd64/machdep.c | 3 +++ sys/arch/amd64/amd64/syscall.S | 43 +++++++++++++++++++++++++++++++ sys/arch/amd64/amd64/syscall.c | 51 +++++++++++++++++++++++++++++++++++++ sys/include/sys/syscall.h | 58 ++++++++++++++++++++++++++++++++++++++++++ sys/kern/kern_syscall.c | 50 ++++++++++++++++++++++++++++++++++++ 5 files changed, 205 insertions(+) create mode 100644 sys/arch/amd64/amd64/syscall.S create mode 100644 sys/arch/amd64/amd64/syscall.c create mode 100644 sys/include/sys/syscall.h create mode 100644 sys/kern/kern_syscall.c (limited to 'sys/kern') diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index fa6c1f5..47d6dd0 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -57,6 +57,8 @@ __KERNEL_META("$Hyra$: machdep.c, Ian Marco Moffett, " #define INIT_FLAG_IOAPIC 0x00000001U #define INIT_FLAG_ACPI 0x00000002U +void syscall_isr(void); + static inline void init_tss(struct cpu_info *cur_cpu) { @@ -82,6 +84,7 @@ interrupts_init(void) idt_set_desc(0xC, IDT_TRAP_GATE_FLAGS, ISR(ss_fault), 0); idt_set_desc(0xD, IDT_TRAP_GATE_FLAGS, ISR(general_prot), 0); idt_set_desc(0xE, IDT_TRAP_GATE_FLAGS, ISR(page_fault), 0); + idt_set_desc(0x80, IDT_INT_GATE_USER, ISR(syscall_isr), 0); idt_load(); } diff --git a/sys/arch/amd64/amd64/syscall.S b/sys/arch/amd64/amd64/syscall.S new file mode 100644 index 0000000..fe70523 --- /dev/null +++ b/sys/arch/amd64/amd64/syscall.S @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + #include + #include + +__KERNEL_META "$Hyra$: syscall.S, Ian Marco Moffett, \ + Syscall ISR code" + +.text +.globl syscall_isr +syscall_isr: + push_trapframe $0 + mov %rsp, %rdi + call __syscall + pop_trapframe + iretq diff --git a/sys/arch/amd64/amd64/syscall.c b/sys/arch/amd64/amd64/syscall.c new file mode 100644 index 0000000..9b1f988 --- /dev/null +++ b/sys/arch/amd64/amd64/syscall.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +void +__syscall(struct trapframe *tf) +{ + struct syscall_args args = { + .code = tf->rax, + .arg0 = tf->rdi, + .arg1 = tf->rsi, + .arg2 = tf->rcx, + .arg3 = tf->r8, + .arg4 = tf->r9, + .sp = tf->rsp, + .ret = tf->rax, + }; + + if (args.code < __MAX_SYSCALLS) { + g_syscall_table[tf->rax](&args); + } + + tf->rax = args.ret; +} diff --git a/sys/include/sys/syscall.h b/sys/include/sys/syscall.h new file mode 100644 index 0000000..98a57f2 --- /dev/null +++ b/sys/include/sys/syscall.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_SYSCALL_H_ +#define _SYS_SYSCALL_H_ + +#include +#if defined(_KERNEL) +#include +#endif + +/* Do not reorder */ +enum { + SYS_debug = 0, + SYS_exit, + __MAX_SYSCALLS +}; + +struct syscall_args { + uint64_t code; + uint64_t arg0, arg1, arg2, arg3, arg4; + uint64_t ip; + uint64_t sp; + uint64_t ret; +}; + +#if defined(_KERNEL) +extern void(*g_syscall_table[__MAX_SYSCALLS])(struct syscall_args *args); +void __syscall(struct trapframe *tf); +#endif + +#endif diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c new file mode 100644 index 0000000..2c7215c --- /dev/null +++ b/sys/kern/kern_syscall.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +static void +sys_debug(struct syscall_args *args) +{ + /* TODO */ +} + +__noreturn static void +sys_exit(struct syscall_args *args) +{ + sched_exit(); + __builtin_unreachable(); +} + +void(*g_syscall_table[__MAX_SYSCALLS])(struct syscall_args *args) = { + sys_debug, + sys_exit, +}; -- cgit v1.2.3 From 3c7958f1df0eefa5a567761f5838d5ed772998e6 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Thu, 14 Mar 2024 22:03:47 -0400 Subject: kernel: sched: Rework sched_init() Signed-off-by: Ian Moffett --- sys/kern/kern_sched.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index c3d1e09..fca3e17 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -371,27 +371,30 @@ void sched_init(void) { struct proc *init; - struct auxval auxv = {0}; + struct auxval auxv = {0}, ld_auxv = {0}; struct vas vas = pmap_create_vas(vm_get_ctx()); - const char *init_bin; + const char *init_bin, *ld_bin; - int status; char *ld_path; - char *argv[] = {"/boot/init", NULL}; - char *envp[] = {NULL}; + char *argv[] = {"/usr/sbin/init", NULL}; + char *envp[] = {"", NULL}; TAILQ_INIT(&td_queue); - if ((init_bin = initramfs_open("/boot/init")) == NULL) { - panic("Could not open /boot/init\n"); + if ((init_bin = initramfs_open("/usr/sbin/init")) == NULL) { + panic("Could not open /usr/boot/init\n"); } - - status = loader_load(vas, init_bin, &auxv, 0, &ld_path); - if (status != 0) { + if (loader_load(vas, init_bin, &auxv, 0, &ld_path) != 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) { + panic("Could not load %s\n", ld_path); + } - init = sched_create_td((uintptr_t)auxv.at_entry, argv, envp, auxv, vas, true); + init = sched_create_td((uintptr_t)ld_auxv.at_entry, argv, envp, ld_auxv, vas, true); if (init == NULL) { panic("Failed to create thread for init\n"); } -- cgit v1.2.3 From 34e2731df268bf44af1e9bb050bae55c94a244db Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Thu, 14 Mar 2024 22:21:30 -0400 Subject: kernel: sched: Remove useless declaration Signed-off-by: Ian Moffett --- sys/kern/kern_sched.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index fca3e17..117e0c1 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -76,9 +76,6 @@ static size_t nthread = 0; */ static struct spinlock tdq_lock = {0}; -/* In sys///switch.S */ -void __sched_switch_to(struct trapframe *tf); - static inline void sched_oneshot(void) { -- cgit v1.2.3 From 49b44f6346df4e25a6e001e7d71534efc197a445 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Fri, 15 Mar 2024 10:27:42 -0400 Subject: kernel: vfs: Fix typo in comment Signed-off-by: Ian Moffett --- sys/kern/vfs_lookup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys/kern') diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 748d5e2..7d20bd2 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -33,7 +33,7 @@ #include /* - * Fetches the filename within a past at + * Fetches the filename within a path at * the nth index denoted by `idx' * * Returns memory allocated by dynalloc() -- cgit v1.2.3 From 81e963b81a99f6b1176b2e316308cebe5f86d3c2 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Fri, 15 Mar 2024 12:04:46 -0400 Subject: kernel: vfs: Allow optional fs store within vnode Signed-off-by: Ian Moffett --- sys/include/sys/vnode.h | 1 + sys/kern/vfs_init.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'sys/kern') diff --git a/sys/include/sys/vnode.h b/sys/include/sys/vnode.h index f584356..545e38f 100644 --- a/sys/include/sys/vnode.h +++ b/sys/include/sys/vnode.h @@ -47,6 +47,7 @@ struct vnode { struct mount *mp; /* Ptr to vfs vnode is in */ struct vops *vops; struct vnode *parent; + struct fs_info *fs; /* Filesystem this vnode belongs to, can be NULL */ void *data; /* Filesystem specific data */ }; diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c index 18ab3ac..0d8d194 100644 --- a/sys/kern/vfs_init.c +++ b/sys/kern/vfs_init.c @@ -40,8 +40,10 @@ __MODULE_NAME("vfs"); __KERNEL_META("$Hyra$: vfs.c, Ian Marco Moffett, " "Hyra Virtual File System"); +#define INITRAMFS_ID 0 + static struct fs_info filesystems[] = { - { "initramfs", &g_initramfs_ops } + [INITRAMFS_ID] = { "initramfs", &g_initramfs_ops } }; struct vnode *g_root_vnode = NULL; @@ -76,4 +78,5 @@ vfs_init(void) } g_root_vnode->vops = &g_initramfs_vops; + g_root_vnode->fs = &filesystems[INITRAMFS_ID]; } -- cgit v1.2.3 From ec2da40e65346bd5d3055777a76852892da21ea7 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Fri, 15 Mar 2024 12:18:16 -0400 Subject: kernel: vfs: Implement vfs_path_to_node() Signed-off-by: Ian Moffett --- sys/include/sys/vfs.h | 2 +- sys/kern/vfs_lookup.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 5 deletions(-) (limited to 'sys/kern') diff --git a/sys/include/sys/vfs.h b/sys/include/sys/vfs.h index a684c3f..c1bef53 100644 --- a/sys/include/sys/vfs.h +++ b/sys/include/sys/vfs.h @@ -42,7 +42,7 @@ void vfs_init(void); struct fs_info *vfs_byname(const char *name); int vfs_vget(struct vnode *parent, const char *name, struct vnode **vp); -struct vnode *vfs_path_to_node(const char *path); +int vfs_path_to_node(const char *path, struct vnode **vp); char *vfs_get_fname_at(const char *path, size_t idx); int vfs_rootname(const char *path, char **new_path); bool vfs_is_valid_path(const char *path); diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 7d20bd2..1398964 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -29,6 +29,8 @@ #include #include +#include +#include #include #include @@ -115,9 +117,58 @@ vfs_get_fname_at(const char *path, size_t idx) return ret; } -struct vnode * -vfs_path_to_node(const char *path) +/* + * Fetches a vnode from a path. + * + * @path: Path to fetch vnode from. + * @vp: Output var for fetched vnode. + * + * Returns 0 on success. + */ +int +vfs_path_to_node(const char *path, struct vnode **vp) { - /* TODO */ - return NULL; + struct vnode *vnode = g_root_vnode; + struct fs_info *fs; + char *name; + int s = 0, fs_caps = 0; + + if (strcmp(path, "/") == 0 || !vfs_is_valid_path(path)) { + return -1; + } else if (*path != '/') { + return -1; + } + + /* Fetch filesystem capabilities if we can */ + if (vnode->fs != NULL) { + fs = vnode->fs; + fs_caps = fs->caps; + } + + /* + * If the filesystem requires full-path lookups, we can try + * throwing the full path at the filesystem to see if + * it'll give us a vnode. + */ + if (__TEST(fs_caps, FSCAP_FULLPATH)) { + s = vfs_vget(g_root_vnode, path, &vnode); + goto done; + } + + for (size_t i = 0;; ++i) { + name = vfs_get_fname_at(path, i); + if (name == NULL) break; + + s = vfs_vget(vnode, name, &vnode); + dynfree(name); + + if (s != 0) break; + } + +done: + if (vp != NULL && s == 0) { + *vp = vnode; + } + + return s; } -- cgit v1.2.3 From 1e7a1c0d90f6eb339e3e68c7b91bb21e81e06d5c Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Fri, 15 Mar 2024 18:39:47 -0400 Subject: kernel: sched: Add routine to get current thread Signed-off-by: Ian Moffett --- sys/include/sys/sched.h | 1 + sys/kern/kern_sched.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+) (limited to 'sys/kern') diff --git a/sys/include/sys/sched.h b/sys/include/sys/sched.h index f06c104..1fa947e 100644 --- a/sys/include/sys/sched.h +++ b/sys/include/sys/sched.h @@ -37,6 +37,7 @@ #include #include +struct proc *this_td(void); void sched_init(void); void sched_exit(void); void sched_context_switch(struct trapframe *tf); diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index 117e0c1..d775e5a 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -321,6 +321,20 @@ sched_exit(void) sched_enter(); } +/* + * Get the current running thread. + */ +struct proc * +this_td(void) +{ + struct sched_state *state; + struct cpu_info *ci; + + ci = this_cpu(); + state = &ci->sched_state; + return state->td; +} + /* * Thread context switch routine */ -- cgit v1.2.3 From ca74cc263f2e7cc94e0216c775a09a52a970d235 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Fri, 15 Mar 2024 18:40:43 -0400 Subject: kernel: sched: Use this_td() to get thread Signed-off-by: Ian Moffett --- sys/kern/kern_sched.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index d775e5a..bd59e41 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -301,17 +301,12 @@ sched_destroy_td(struct proc *td) void sched_exit(void) { - struct sched_state *state; - struct cpu_info *ci; struct proc *td; struct vas kvas = vm_get_kvas(); intr_mask(); - /* Get the thread running on the current processor */ - ci = this_cpu(); - state = &ci->sched_state; - td = state->td; + td = this_td(); /* Switch back to the kernel address space and destroy ourself */ pmap_switch_vas(vm_get_ctx(), kvas); -- cgit v1.2.3 From dd0a88b94744053653a032149ba7d6eb1f392021 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Fri, 15 Mar 2024 19:54:43 -0400 Subject: kernel: Add basic file descriptor support Signed-off-by: Ian Moffett --- sys/include/sys/filedesc.h | 53 +++++++++++++++++++ sys/include/sys/proc.h | 4 ++ sys/kern/kern_filedesc.c | 123 +++++++++++++++++++++++++++++++++++++++++++++ sys/kern/kern_sched.c | 11 ++++ 4 files changed, 191 insertions(+) create mode 100644 sys/include/sys/filedesc.h create mode 100644 sys/kern/kern_filedesc.c (limited to 'sys/kern') diff --git a/sys/include/sys/filedesc.h b/sys/include/sys/filedesc.h new file mode 100644 index 0000000..ef74fb1 --- /dev/null +++ b/sys/include/sys/filedesc.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_FILEDESC_H_ +#define _SYS_FILEDESC_H_ + +#include +#include +#include + +struct proc; + +struct filedesc { + int fdno; + off_t offset; + bool is_dir; + struct vnode *vnode; + struct spinlock lock; +}; + +#if defined(_KERNEL) +struct filedesc *fd_alloc(struct proc *td); +struct filedesc *fd_from_fdnum(const struct proc *td, int fdno); +void fd_close_fdnum(struct proc *td, int fdno); +#endif + +#endif diff --git a/sys/include/sys/proc.h b/sys/include/sys/proc.h index 7181ecb..c6046d7 100644 --- a/sys/include/sys/proc.h +++ b/sys/include/sys/proc.h @@ -32,11 +32,14 @@ #include #include +#include #include #include #include #include +#define PROC_MAX_FDS 256 + /* * A task running on the CPU e.g., a process or * a thread. @@ -49,6 +52,7 @@ struct proc { struct vas addrsp; uintptr_t stack_base; uint8_t is_user; + struct filedesc *fds[PROC_MAX_FDS]; TAILQ_ENTRY(proc) link; }; diff --git a/sys/kern/kern_filedesc.c b/sys/kern/kern_filedesc.c new file mode 100644 index 0000000..a943714 --- /dev/null +++ b/sys/kern/kern_filedesc.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2023-2024 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +/* + * Allocate a file descriptor. + * + * @td: Thread to allocate from, NULL for current thread. + */ +struct filedesc * +fd_alloc(struct proc *td) +{ + struct filedesc *fd; + + if (td == NULL) { + td = this_td(); + __assert(td != NULL); + } + + for (size_t i = 0; i < PROC_MAX_FDS; ++i) { + if (td->fds[i] != NULL) { + continue; + } + + fd = dynalloc(sizeof(struct filedesc)); + memset(fd, 0, sizeof(struct filedesc)); + + if (fd == NULL) { + return NULL; + } + + fd->fdno = i; + td->fds[i] = fd; + return fd; + } + + return NULL; +} + +/* + * Fetch a file descriptor from a file descriptor + * number. + * + * @td: Thread to fetch from, NULL for current thread. + * @fdno: File descriptor to fetch + */ +struct filedesc * +fd_from_fdnum(const struct proc *td, int fdno) +{ + if (td == NULL) { + td = this_td(); + __assert(td != NULL); + } + + if (fdno < 0 || fdno > PROC_MAX_FDS) { + return NULL; + } + + for (size_t i = 0; i < PROC_MAX_FDS; ++i) { + if (i == fdno && td->fds[i] != NULL) { + return td->fds[i]; + } + } + + return NULL; +} + +/* + * Close a file descriptor from its fd number. + * + * @td: Thread to fetch from, NULL for current thread. + * @fdno: File descriptor number to close. + */ +void +fd_close_fdnum(struct proc *td, int fdno) +{ + struct filedesc *fd; + + if (td == NULL) { + td = this_td(); + __assert(td != NULL); + } + + fd = fd_from_fdnum(td, fdno); + if (fd == NULL) { + return; + } + + dynfree(fd); + td->fds[fdno] = NULL; +} diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index bd59e41..77aab54 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -268,6 +269,11 @@ sched_create_td(uintptr_t rip, char *argvp[], char *envp[], struct auxval auxv, td->is_user = is_user; processor_init_pcb(td); + /* Allocate standard file descriptors */ + __assert(fd_alloc(td) != NULL); /* STDIN */ + __assert(fd_alloc(td) != NULL); /* STDOUT */ + __assert(fd_alloc(td) != NULL); /* STDERR */ + /* Setup trapframe */ if (!is_user) { init_frame(tf, rip, (uintptr_t)stack); @@ -294,6 +300,11 @@ sched_destroy_td(struct proc *td) dynfree((void *)td->stack_base); } + /* Close all of the file descriptors */ + for (size_t i = 0; i < PROC_MAX_FDS; ++i) { + fd_close_fdnum(td, i); + } + pmap_free_vas(vm_get_ctx(), td->addrsp); dynfree(td); } -- cgit v1.2.3 From 51a3988ec0ea1de35e47a999a76c14df05737a34 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Sat, 16 Mar 2024 09:42:03 -0400 Subject: kernel: sched: Cleanup context switch comments Signed-off-by: Ian Moffett --- sys/kern/kern_sched.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'sys/kern') diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index 77aab54..7b3776d 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -360,18 +360,23 @@ sched_context_switch(struct trapframe *tf) return; } + /* + * If we have a thread currently running and we are switching + * to another, we shall save our current register state + * by copying the trapframe. + */ if (state->td != NULL) { - /* Save our trapframe */ td = state->td; memcpy(td->tf, tf, sizeof(struct trapframe)); } - /* Copy to stack */ + /* Copy over the next thread's register state to us */ memcpy(tf, next_td->tf, sizeof(struct trapframe)); td = state->td; state->td = next_td; + /* Re-enqueue the previous thread if it exists */ if (td != NULL) { sched_enqueue_td(td); } -- cgit v1.2.3 From 3db86a30644d3eb3a964202dbfd7e91c432bda7b Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Sat, 16 Mar 2024 12:42:25 -0400 Subject: kernel: syscall: Remove syscall_args.ret It is better to just return a value within the syscall handler and have that passed down to __syscall() like that Signed-off-by: Ian Moffett --- sys/arch/amd64/amd64/syscall.c | 7 ++----- sys/include/sys/syscall.h | 3 +-- sys/kern/kern_syscall.c | 8 +++++--- 3 files changed, 8 insertions(+), 10 deletions(-) (limited to 'sys/kern') diff --git a/sys/arch/amd64/amd64/syscall.c b/sys/arch/amd64/amd64/syscall.c index 9b1f988..e80fe94 100644 --- a/sys/arch/amd64/amd64/syscall.c +++ b/sys/arch/amd64/amd64/syscall.c @@ -39,13 +39,10 @@ __syscall(struct trapframe *tf) .arg2 = tf->rcx, .arg3 = tf->r8, .arg4 = tf->r9, - .sp = tf->rsp, - .ret = tf->rax, + .sp = tf->rsp }; if (args.code < __MAX_SYSCALLS) { - g_syscall_table[tf->rax](&args); + tf->rax = g_syscall_table[tf->rax](&args); } - - tf->rax = args.ret; } diff --git a/sys/include/sys/syscall.h b/sys/include/sys/syscall.h index 98a57f2..03eda0b 100644 --- a/sys/include/sys/syscall.h +++ b/sys/include/sys/syscall.h @@ -47,11 +47,10 @@ struct syscall_args { uint64_t arg0, arg1, arg2, arg3, arg4; uint64_t ip; uint64_t sp; - uint64_t ret; }; #if defined(_KERNEL) -extern void(*g_syscall_table[__MAX_SYSCALLS])(struct syscall_args *args); +extern uint64_t(*g_syscall_table[__MAX_SYSCALLS])(struct syscall_args *args); void __syscall(struct trapframe *tf); #endif diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c index 2c7215c..5a88bbb 100644 --- a/sys/kern/kern_syscall.c +++ b/sys/kern/kern_syscall.c @@ -30,21 +30,23 @@ #include #include #include +#include -static void +static uint64_t sys_debug(struct syscall_args *args) { /* TODO */ + return 0; } -__noreturn static void +__noreturn static uint64_t sys_exit(struct syscall_args *args) { sched_exit(); __builtin_unreachable(); } -void(*g_syscall_table[__MAX_SYSCALLS])(struct syscall_args *args) = { +uint64_t(*g_syscall_table[__MAX_SYSCALLS])(struct syscall_args *args) = { sys_debug, sys_exit, }; -- cgit v1.2.3 From f166b2303a96a5e65e235139291df93b2b24bc3e Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Sat, 16 Mar 2024 13:03:19 -0400 Subject: kernel,libc: syscall: Improve syscall code - Remove the SYS_debug syscall - First syscall starts at 1 Signed-off-by: Ian Moffett --- lib/libc/include/sys/syscall.h | 1 - sys/arch/amd64/amd64/syscall.c | 5 +++-- sys/include/sys/syscall.h | 3 +-- sys/kern/kern_syscall.c | 8 -------- 4 files changed, 4 insertions(+), 13 deletions(-) (limited to 'sys/kern') diff --git a/lib/libc/include/sys/syscall.h b/lib/libc/include/sys/syscall.h index b5e5fc2..34f762d 100644 --- a/lib/libc/include/sys/syscall.h +++ b/lib/libc/include/sys/syscall.h @@ -34,7 +34,6 @@ #include #endif -#define SYS_debug 0 #define SYS_exit 1 #if !defined(__ASSEMBLER__) diff --git a/sys/arch/amd64/amd64/syscall.c b/sys/arch/amd64/amd64/syscall.c index e80fe94..68235d5 100644 --- a/sys/arch/amd64/amd64/syscall.c +++ b/sys/arch/amd64/amd64/syscall.c @@ -42,7 +42,8 @@ __syscall(struct trapframe *tf) .sp = tf->rsp }; - if (args.code < __MAX_SYSCALLS) { - tf->rax = g_syscall_table[tf->rax](&args); + if (args.code < __MAX_SYSCALLS && args.code > 0) { + args.code -= 1; + tf->rax = g_syscall_table[args.code](&args); } } diff --git a/sys/include/sys/syscall.h b/sys/include/sys/syscall.h index 03eda0b..66dc5f3 100644 --- a/sys/include/sys/syscall.h +++ b/sys/include/sys/syscall.h @@ -37,8 +37,7 @@ /* Do not reorder */ enum { - SYS_debug = 0, - SYS_exit, + SYS_exit = 1, __MAX_SYSCALLS }; diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c index 5a88bbb..b6e31d1 100644 --- a/sys/kern/kern_syscall.c +++ b/sys/kern/kern_syscall.c @@ -32,13 +32,6 @@ #include #include -static uint64_t -sys_debug(struct syscall_args *args) -{ - /* TODO */ - return 0; -} - __noreturn static uint64_t sys_exit(struct syscall_args *args) { @@ -47,6 +40,5 @@ sys_exit(struct syscall_args *args) } uint64_t(*g_syscall_table[__MAX_SYSCALLS])(struct syscall_args *args) = { - sys_debug, sys_exit, }; -- cgit v1.2.3