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 --- sys/include/arch/amd64/frame.h | 7 +++++++ sys/include/sys/proc.h | 2 ++ 2 files changed, 9 insertions(+) (limited to 'sys/include') 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; }; -- cgit v1.2.3 From 991f1167df58616f4275c290fd0aa14baf7861f8 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Sun, 10 Mar 2024 19:55:30 -0400 Subject: kernel/amd64: trap: Add stack-segment fault ISR Signed-off-by: Ian Moffett --- sys/arch/amd64/amd64/machdep.c | 1 + sys/arch/amd64/amd64/trap.S | 10 ++++++++++ sys/arch/amd64/amd64/trap.c | 10 ++++++++-- sys/include/arch/amd64/trap.h | 2 ++ 4 files changed, 21 insertions(+), 2 deletions(-) (limited to 'sys/include') diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index 6342aab..e5fe83e 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -78,6 +78,7 @@ interrupts_init(void) idt_set_desc(0x8, IDT_TRAP_GATE_FLAGS, ISR(double_fault), 0); idt_set_desc(0xA, IDT_TRAP_GATE_FLAGS, ISR(invl_tss), 0); idt_set_desc(0xB, IDT_TRAP_GATE_FLAGS, ISR(segnp), 0); + 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_load(); diff --git a/sys/arch/amd64/amd64/trap.S b/sys/arch/amd64/amd64/trap.S index 5a77955..66dd2a9 100644 --- a/sys/arch/amd64/amd64/trap.S +++ b/sys/arch/amd64/amd64/trap.S @@ -144,3 +144,13 @@ nmi: /* TODO */ cli hlt + +.globl ss_fault +ss_fault: + push_trapframe_ec $TRAP_SS + + handle_trap + + /* TODO */ + cli + hlt diff --git a/sys/arch/amd64/amd64/trap.c b/sys/arch/amd64/amd64/trap.c index b73048d..c1cff56 100644 --- a/sys/arch/amd64/amd64/trap.c +++ b/sys/arch/amd64/amd64/trap.c @@ -44,7 +44,8 @@ static const char *trap_type[] = { [TRAP_SEGNP] = "segment not present", [TRAP_PROTFLT] = "general protection", [TRAP_PAGEFLT] = "page fault", - [TRAP_NMI] = "non-maskable interrupt" + [TRAP_NMI] = "non-maskable interrupt", + [TRAP_SS] = "stack-segment fault" }; static const int TRAP_COUNT = __ARRAY_COUNT(trap_type); @@ -54,12 +55,17 @@ dbg_errcode(struct trapframe *tf) { uint64_t ec = tf->error_code; - if (tf->trapno == TRAP_PAGEFLT) { + switch (tf->trapno) { + case TRAP_PAGEFLT: kprintf("bits (pwui): %c%c%c%c\n", __TEST(ec, __BIT(0)) ? 'p' : '-', __TEST(ec, __BIT(1)) ? 'w' : '-', __TEST(ec, __BIT(2)) ? 'u' : '-', __TEST(ec, __BIT(4)) ? 'i' : '-'); + break; + case TRAP_SS: + kprintf("ss: 0x%x\n", ec); + break; } } diff --git a/sys/include/arch/amd64/trap.h b/sys/include/arch/amd64/trap.h index 1019999..c75fa28 100644 --- a/sys/include/arch/amd64/trap.h +++ b/sys/include/arch/amd64/trap.h @@ -47,6 +47,7 @@ #define TRAP_PROTFLT 9 /* General protection */ #define TRAP_PAGEFLT 10 /* Page fault */ #define TRAP_NMI 11 /* Non-maskable interrupt */ +#define TRAP_SS 12 /* Stack-segment fault */ /* Trap is coming from user mode */ #define TRAP_USER 0x100 @@ -65,6 +66,7 @@ void segnp(void *sf); void general_prot(void *sf); void page_fault(void *sf); void nmi(void *sf); +void ss_fault(void *sf); void trap_handler(struct trapframe *tf); #else .macro handle_trap -- cgit v1.2.3 From 50bf5cc0bca1b0cb9dbaf461a41b80725baabba1 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Mon, 11 Mar 2024 12:51:40 -0400 Subject: kernel/amd64: Add control register r/w helpers Signed-off-by: Ian Moffett --- sys/include/arch/amd64/cpu.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'sys/include') diff --git a/sys/include/arch/amd64/cpu.h b/sys/include/arch/amd64/cpu.h index e2ed851..1968569 100644 --- a/sys/include/arch/amd64/cpu.h +++ b/sys/include/arch/amd64/cpu.h @@ -110,6 +110,34 @@ amd64_read_gs_base(void) return rdmsr(IA32_KERNEL_GS_BASE); } +static inline uint64_t +amd64_read_cr0(void) +{ + uint64_t cr0; + __ASMV("mov %%cr0, %0" : "=r" (cr0) :: "memory"); + return cr0; +} + +static inline void +amd64_write_cr0(uint64_t val) +{ + __ASMV("mov %0, %%cr0" :: "r" (val) : "memory"); +} + +static inline uint64_t +amd64_read_cr4(void) +{ + uint64_t cr4; + __ASMV("mov %%cr4, %0" : "=r" (cr4) :: "memory"); + return cr4; +} + +static inline void +amd64_write_cr4(uint64_t val) +{ + __ASMV("mov %0, %%cr4" :: "r" (val) : "memory"); +} + struct cpu_info *amd64_this_cpu(void); #endif /* !_AMD64_CPU_H_ */ -- 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/include') 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 73a209c0f7e350d819ce4b98374d4f2b83f7300d Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Wed, 13 Mar 2024 21:20:53 -0400 Subject: kernel/amd64: cpu: Add fxsave/fxrstor helpers Signed-off-by: Ian Moffett --- sys/include/arch/amd64/cpu.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'sys/include') diff --git a/sys/include/arch/amd64/cpu.h b/sys/include/arch/amd64/cpu.h index 1968569..ee9bad7 100644 --- a/sys/include/arch/amd64/cpu.h +++ b/sys/include/arch/amd64/cpu.h @@ -138,6 +138,18 @@ amd64_write_cr4(uint64_t val) __ASMV("mov %0, %%cr4" :: "r" (val) : "memory"); } +static inline void +amd64_fxsave(void *area) +{ + __ASMV("fxsave (%0)" :: "r" (area) : "memory"); +} + +static inline void +amd64_fxrstor(void *area) +{ + __ASMV("fxrstor (%0)" :: "r" (area) : "memory"); +} + struct cpu_info *amd64_this_cpu(void); #endif /* !_AMD64_CPU_H_ */ -- cgit v1.2.3 From 8b68f956154b43b2b2fe2b8783ae6f23bf90d47b Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Wed, 13 Mar 2024 21:31:25 -0400 Subject: kernel: proc: Add Process Control Block structure This is to be implemented per arch and has arch specific thread information. For example, on the AMD64 port, this can contain things like an x87 FPU save area Signed-off-by: Ian Moffett --- sys/include/arch/amd64/pcb.h | 39 +++++++++++++++++++++++++++++++++++++++ sys/include/sys/proc.h | 2 ++ 2 files changed, 41 insertions(+) create mode 100644 sys/include/arch/amd64/pcb.h (limited to 'sys/include') diff --git a/sys/include/arch/amd64/pcb.h b/sys/include/arch/amd64/pcb.h new file mode 100644 index 0000000..0e0aab8 --- /dev/null +++ b/sys/include/arch/amd64/pcb.h @@ -0,0 +1,39 @@ +/* + * 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 _AMD64_PCB_H_ +#define _AMD64_PCB_H_ + +#include + +struct pcb { + uint8_t *fpu_state; +}; + +#endif /* !_AMD64_PCB_H_ */ diff --git a/sys/include/sys/proc.h b/sys/include/sys/proc.h index 0d3b45e..34a5037 100644 --- a/sys/include/sys/proc.h +++ b/sys/include/sys/proc.h @@ -34,6 +34,7 @@ #include #include #include +#include #include /* @@ -44,6 +45,7 @@ struct proc { pid_t pid; struct cpu_info *cpu; struct trapframe *tf; + struct pcb pcb; struct vas addrsp; TAILQ_ENTRY(proc) link; }; -- 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/include') 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/include') 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 a2b2dbaa71278769e9dbf5ca611cd0d5f3b896ed Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Wed, 13 Mar 2024 23:30:21 -0400 Subject: kernel/amd64: machdep: Add processor_free_pcb() Add routine to deallocate resources within the process control block. Signed-off-by: Ian Moffett --- sys/arch/amd64/amd64/machdep.c | 13 +++++++++++++ sys/include/sys/machdep.h | 1 + 2 files changed, 14 insertions(+) (limited to 'sys/include') diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index 7ad3e6a..fa6c1f5 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -180,6 +180,19 @@ processor_init_pcb(struct proc *proc) return 0; } +int +processor_free_pcb(struct proc *proc) +{ + struct pcb *pcb = &proc->pcb; + + if (pcb->fpu_state == NULL) { + return -1; + } + + vm_free_pageframe(VIRT_TO_PHYS(pcb->fpu_state), 1); + return 0; +} + void processor_switch_to(struct proc *old_td, struct proc *new_td) { diff --git a/sys/include/sys/machdep.h b/sys/include/sys/machdep.h index b6edf14..0c06374 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); +int processor_free_pcb(struct proc *proc); void processor_switch_to(struct proc *old_td, struct proc *new_td); void processor_init(void); void processor_halt(void); -- cgit v1.2.3 From 5a8915f5b36cf3b21c843ef7959c24ac39318aca Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Thu, 14 Mar 2024 20:51:39 -0400 Subject: kernel: vm: Add routine to get kernel vas Signed-off-by: Ian Moffett --- sys/include/vm/vm.h | 1 + sys/vm/vm_init.c | 9 +++++++++ 2 files changed, 10 insertions(+) (limited to 'sys/include') diff --git a/sys/include/vm/vm.h b/sys/include/vm/vm.h index 2a24d76..48e1b8f 100644 --- a/sys/include/vm/vm.h +++ b/sys/include/vm/vm.h @@ -61,5 +61,6 @@ vm_get_page_size(void) void vm_init(void); struct vm_ctx *vm_get_ctx(void); +struct vas vm_get_kvas(void); #endif /* !_VM_H_ */ diff --git a/sys/vm/vm_init.c b/sys/vm/vm_init.c index f15cb0b..6096059 100644 --- a/sys/vm/vm_init.c +++ b/sys/vm/vm_init.c @@ -59,6 +59,15 @@ vm_get_ctx(void) return &bsp_vm_ctx; } +/* + * Return the kernel VAS. + */ +struct vas +vm_get_kvas(void) +{ + return kernel_vas; +} + void vm_init(void) { -- 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/include') 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 3e3ff0acccfbb1d251a9b9bacbf0851c9de69561 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Thu, 14 Mar 2024 21:02:10 -0400 Subject: kernel/amd64: pmap: Add pmap_free_vas() Signed-off-by: Ian Moffett --- sys/arch/amd64/amd64/pmap.c | 13 +++++++++++++ sys/include/vm/pmap.h | 6 ++++++ 2 files changed, 19 insertions(+) (limited to 'sys/include') diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c index 2760532..54d4ca3 100644 --- a/sys/arch/amd64/amd64/pmap.c +++ b/sys/arch/amd64/amd64/pmap.c @@ -228,6 +228,19 @@ pmap_switch_vas(struct vm_ctx *ctx, struct vas vas) : "memory"); } +/* + * TODO: During the mapping of a virtual address, a level + * may be allocated. This function does not handle the + * freeing of allocated levels. We should keep track + * of levels allocated and free them here. + */ +int +pmap_free_vas(struct vm_ctx *ctx, struct vas vas) +{ + vm_free_pageframe(vas.top_level, 1); + return 0; +} + struct vas pmap_read_vas(void) { diff --git a/sys/include/vm/pmap.h b/sys/include/vm/pmap.h index ebabd32..3380199 100644 --- a/sys/include/vm/pmap.h +++ b/sys/include/vm/pmap.h @@ -89,6 +89,12 @@ struct vas pmap_read_vas(void); */ int pmap_map(struct vm_ctx *, struct vas, vaddr_t, paddr_t, vm_prot_t); +/* + * Get rid of a virtual address space and free + * resources. + */ +int pmap_free_vas(struct vm_ctx *, struct vas); + /* * Unmap a page. */ -- 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/include') 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/include') 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 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/include') 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 45547c3a0056ab5732c4ea1e01deee10749ecbcb Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Fri, 15 Mar 2024 12:06:40 -0400 Subject: kernel: vfs: Add fs capabilties Signed-off-by: Ian Moffett --- sys/fs/initramfs.c | 1 + sys/include/sys/mount.h | 7 +++++++ 2 files changed, 8 insertions(+) (limited to 'sys/include') diff --git a/sys/fs/initramfs.c b/sys/fs/initramfs.c index 2a501a1..6da0929 100644 --- a/sys/fs/initramfs.c +++ b/sys/fs/initramfs.c @@ -173,6 +173,7 @@ static int initramfs_init(struct fs_info *info) { initramfs = get_module("/boot/initramfs.tar", &initramfs_size); + info->caps = FSCAP_FULLPATH; if (initramfs == NULL) { panic("Failed to load initramfs\n"); diff --git a/sys/include/sys/mount.h b/sys/include/sys/mount.h index 3ac7ec7..209fa3e 100644 --- a/sys/include/sys/mount.h +++ b/sys/include/sys/mount.h @@ -33,6 +33,7 @@ #include #include #include +#include #define FS_NAME_MAX 16 /* Max length of FS type name including nul */ @@ -54,8 +55,14 @@ struct fs_info { char name[FS_NAME_MAX]; /* Filesystem type name */ struct vfsops *vfsops; /* Filesystem operations */ struct mount *mp_root; + uint16_t caps; }; +/* + * Filesystem capabilities + */ +#define FSCAP_FULLPATH __BIT(0) /* Requires full path per lookup */ + /* * Mount flags */ -- 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/include') 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/include') 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 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/include') 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 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/include') 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/include') 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