diff options
-rw-r--r-- | Makefile.in | 4 | ||||
-rw-r--r-- | builddeps/user.mk | 3 | ||||
-rw-r--r-- | sys/arch/amd64/amd64/proc_machdep.c | 23 | ||||
-rw-r--r-- | sys/include/sys/driver.h | 2 | ||||
-rw-r--r-- | sys/include/sys/proc.h | 5 | ||||
-rw-r--r-- | sys/include/sys/sched.h | 2 | ||||
-rw-r--r-- | sys/include/sys/spawn.h | 3 | ||||
-rw-r--r-- | sys/kern/kern_descrip.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_exec.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_exit.c | 52 | ||||
-rw-r--r-- | sys/kern/kern_sched.c | 67 | ||||
-rw-r--r-- | sys/kern/kern_spawn.c | 26 | ||||
-rw-r--r-- | usr.bin/Makefile | 1 | ||||
-rw-r--r-- | usr.bin/fetch/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/fetch/fetch.c | 58 | ||||
-rw-r--r-- | usr.bin/kmsg/Makefile | 6 | ||||
-rw-r--r-- | usr.bin/kmsg/kmsg.c | 62 | ||||
-rw-r--r-- | usr.bin/osh/osh.c | 31 |
18 files changed, 304 insertions, 51 deletions
diff --git a/Makefile.in b/Makefile.in index 1270a21..508ee1c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -73,12 +73,12 @@ all: stand/boot/ libc sbin bin base/boot/hyra-kernel .PHONY: sbin sbin: $(SBIN_MAKEDIRS) make -C usr.sbin/ LDSCRIPT=$(shell pwd)/usr.sbin/link.ld USRDIR=$(USRDIR)\ - ROOT=$(PROJECT_ROOT)\ + ROOT=$(PROJECT_ROOT) OSVER=$(HYRA_VERSION) OSARCH=$(ARCH) .PHONY: bin bin: $(BIN_MAKEDIRS) make -C usr.bin/ LDSCRIPT=$(shell pwd)/usr.bin/link.ld USRDIR=$(USRDIR)\ - ROOT=$(PROJECT_ROOT) + ROOT=$(PROJECT_ROOT) OSVER=$(HYRA_VERSION) OSARCH=$(ARCH) .PHONY: libc libc: diff --git a/builddeps/user.mk b/builddeps/user.mk index d7ad582..d991ef8 100644 --- a/builddeps/user.mk +++ b/builddeps/user.mk @@ -4,4 +4,5 @@ USRDIR = LDSCRIPT = INTERNAL_CFLAGS = -T$(LDSCRIPT) -znoexecstack -nostdlib -I$(USRDIR)/include/ \ -L$(USRDIR)/lib -lc -pie -no-pie -fno-stack-protector \ - -fno-asynchronous-unwind-tables + -fno-asynchronous-unwind-tables -D_OSVER=\"$(OSVER)\" \ + -D_OSARCH=\"$(OSARCH)\" diff --git a/sys/arch/amd64/amd64/proc_machdep.c b/sys/arch/amd64/amd64/proc_machdep.c index f6b91f9..4fe8580 100644 --- a/sys/arch/amd64/amd64/proc_machdep.c +++ b/sys/arch/amd64/amd64/proc_machdep.c @@ -123,24 +123,37 @@ md_td_kick(struct proc *td) { struct trapframe *tfp; struct cpu_info *ci; + uint8_t rpl; + uint16_t ds = KERNEL_DS; tfp = &td->tf; + rpl = tfp->cs & 3; ci = this_cpu(); ci->curtd = td; + if (rpl == 3) { + td->flags &= ~PROC_KTD; + ds = USER_DS | 3; + } + __ASMV( - "push %0\n" + "mov %0, %%rax\n" "push %1\n" - "pushf\n" "push %2\n" "push %3\n" + "push %%rax\n" + "push %4\n" + "test $3, %%ax\n" + "jz 1f\n" "lfence\n" "swapgs\n" - "iretq" + "1:\n" + " iretq" : - : "i" (USER_DS | 3), + : "r" (tfp->cs), + "r" (ds), "r" (tfp->rsp), - "i" (USER_CS | 3), + "m" (tfp->rflags), "r" (tfp->rip) ); diff --git a/sys/include/sys/driver.h b/sys/include/sys/driver.h index 6e4a267..8ab9521 100644 --- a/sys/include/sys/driver.h +++ b/sys/include/sys/driver.h @@ -110,7 +110,7 @@ extern char __driversd_init_end[]; } #define DRIVERS_SCHED() \ - spawn(&g_proc0,__driver_init_td, NULL, 0, NULL) + spawn(&g_proc0, __driver_init_td, NULL, 0, NULL) void __driver_init_td(void); diff --git a/sys/include/sys/proc.h b/sys/include/sys/proc.h index 0a7d133..25f5fd3 100644 --- a/sys/include/sys/proc.h +++ b/sys/include/sys/proc.h @@ -64,7 +64,7 @@ struct proc { struct trapframe tf; struct pcb pcb; struct proc *parent; - void *spawn_data; + void *data; size_t priority; int exit_status; bool rested; @@ -84,9 +84,12 @@ struct proc { #define PROC_LEAFQ BIT(3) /* Leaf queue is active */ #define PROC_WAITED BIT(4) /* Being waited on by parent */ #define PROC_KTD BIT(5) /* Kernel thread */ +#define PROC_SLEEP BIT(6) /* Thread execution paused */ struct proc *this_td(void); struct proc *get_child(struct proc *cur, pid_t pid); +void proc_reap(struct proc *td); + int md_spawn(struct proc *p, struct proc *parent, uintptr_t ip); scret_t sys_spawn(struct syscall_args *scargs); diff --git a/sys/include/sys/sched.h b/sys/include/sys/sched.h index 80f4d1c..7d17607 100644 --- a/sys/include/sys/sched.h +++ b/sys/include/sys/sched.h @@ -37,6 +37,8 @@ void sched_init(void); void sched_yield(void); + +void sched_switch_to(struct trapframe *tf, struct proc *td); void sched_detach(struct proc *td); __dead void sched_enter(void); diff --git a/sys/include/sys/spawn.h b/sys/include/sys/spawn.h index 3828d5c..9d823db 100644 --- a/sys/include/sys/spawn.h +++ b/sys/include/sys/spawn.h @@ -31,6 +31,9 @@ #define _SYS_SPAWN_H_ #include <sys/types.h> +#include <sys/param.h> + +#define SPAWN_WAIT BIT(0) #if !defined(_KERNEL) pid_t spawn(const char *pathname, int flags); diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index dd14267..1992d46 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -187,6 +187,7 @@ fd_rw(unsigned int fd, void *buf, size_t count, uint8_t write) sio.buf = kbuf; sio.offset = filedes->offset; + spinlock_acquire(&filedes->lock); if (write) { /* Copy in user buffer */ if (copyin(buf, kbuf, count) < 0) { @@ -224,6 +225,7 @@ done: if (kbuf != NULL) { dynfree(kbuf); } + spinlock_release(&filedes->lock); return retval; } diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index bf6a26e..b760912 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -37,6 +37,7 @@ #include <vm/map.h> #include <vm/physmem.h> #include <machine/pcb.h> +#include <machine/cdefs.h> #include <string.h> /* @@ -87,6 +88,7 @@ execve(struct proc *td, const struct execve_args *args) release_stack(td); /* Save program state */ + md_intoff(); memcpy(&td->exec, &prog, sizeof(td->exec)); /* Set new stack and map it to userspace */ diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 242b221..b6cbc4e 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -78,6 +78,30 @@ unload_td(struct proc *td) } } +void +proc_reap(struct proc *td) +{ + struct pcb *pcbp; + uintptr_t stack; + + pcbp = &td->pcb; + stack = td->stack_base; + + /* + * If this is on the higher half, it is kernel + * mapped and we need to convert it to a physical + * address. + */ + if (stack >= VM_HIGHER_HALF) { + stack -= VM_HIGHER_HALF; + } + + unload_td(td); + vm_unmap(pcbp->addrsp, td->stack_base, PROC_STACK_SIZE); + vm_free_frame(stack, PROC_STACK_PAGES); + pmap_destroy_vas(pcbp->addrsp); +} + /* * Kill a thread and deallocate its resources. * @@ -86,20 +110,18 @@ unload_td(struct proc *td) int exit1(struct proc *td, int flags) { - struct pcb *pcbp; struct proc *curtd, *procp; + struct proc *parent; struct cpu_info *ci; - uintptr_t stack; pid_t target_pid, curpid; ci = this_cpu(); target_pid = td->pid; curtd = this_td(); - pcbp = &td->pcb; curpid = curtd->pid; - stack = td->stack_base; td->flags |= PROC_EXITING; + parent = td->parent; /* If we have any children, kill them too */ if (td->nleaves > 0) { @@ -108,20 +130,10 @@ exit1(struct proc *td, int flags) } } - /* - * If this is on the higher half, it is kernel - * mapped and we need to convert it to a physical - * address. - */ - if (stack >= VM_HIGHER_HALF) { - stack -= VM_HIGHER_HALF; + if (target_pid != curpid) { + proc_reap(td); } - unload_td(td); - vm_unmap(pcbp->addrsp, td->stack_base, PROC_STACK_SIZE); - vm_free_frame(stack, PROC_STACK_PAGES); - pmap_destroy_vas(pcbp->addrsp); - /* * Only free the process structure if we aren't * being waited on, otherwise let it be so the @@ -139,6 +151,13 @@ exit1(struct proc *td, int flags) */ if (target_pid == curpid) { ci->curtd = NULL; + if (parent->pid == 0) + sched_enter(); + if (td->data == NULL) + sched_enter(); + + sched_enqueue_td(parent); + parent->flags &= ~PROC_SLEEP; sched_enter(); } @@ -153,6 +172,7 @@ sys_exit(struct syscall_args *scargs) { struct proc *td = this_td(); + td->data = scargs->tf; td->exit_status = scargs->arg0; exit1(td, 0); __builtin_unreachable(); diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c index 2fe0f32..8e456d2 100644 --- a/sys/kern/kern_sched.c +++ b/sys/kern/kern_sched.c @@ -104,12 +104,22 @@ sched_dequeue_td(void) for (size_t i = 0; i < SCHED_NQUEUE; ++i) { queue = &qlist[i]; - if (!TAILQ_EMPTY(&queue->q)) { - td = TAILQ_FIRST(&queue->q); - TAILQ_REMOVE(&queue->q, td, link); - spinlock_release(&tdq_lock); - return td; + if (TAILQ_EMPTY(&queue->q)) { + continue; } + + td = TAILQ_FIRST(&queue->q); + if (td == NULL) { + continue; + } + + TAILQ_REMOVE(&queue->q, td, link); + if (ISSET(td->flags, PROC_SLEEP)) { + continue; + } + + spinlock_release(&tdq_lock); + return td; } /* We got nothing */ @@ -125,6 +135,10 @@ sched_enqueue_td(struct proc *td) { struct sched_queue *queue; + if (ISSET(td->flags, PROC_SLEEP)) { + return; + } + spinlock_acquire(&tdq_lock); queue = &qlist[td->priority]; @@ -176,15 +190,31 @@ td_pri_update(struct proc *td) } } +void +sched_switch_to(struct trapframe *tf, struct proc *td) +{ + struct cpu_info *ci; + struct pcb *pcbp; + + ci = this_cpu(); + + if (tf != NULL) { + memcpy(tf, &td->tf, sizeof(*tf)); + } + + ci->curtd = td; + pcbp = &td->pcb; + pmap_switch_vas(pcbp->addrsp); +} + /* * Perform a context switch. */ void sched_switch(struct trapframe *tf) { - struct cpu_info *ci; - struct pcb *pcbp; struct proc *next_td, *td; + struct cpu_info *ci; ci = this_cpu(); td = ci->curtd; @@ -203,11 +233,7 @@ sched_switch(struct trapframe *tf) return; } - memcpy(tf, &next_td->tf, sizeof(*tf)); - ci->curtd = next_td; - pcbp = &next_td->pcb; - - pmap_switch_vas(pcbp->addrsp); + sched_switch_to(tf, next_td); sched_oneshot(false); } @@ -217,6 +243,7 @@ sched_switch(struct trapframe *tf) void sched_enter(void) { + md_inton(); sched_oneshot(false); for (;;) { md_pause(); @@ -226,12 +253,20 @@ sched_enter(void) void sched_yield(void) { - struct proc *td = this_td(); + struct proc *td; + struct cpu_info *ci = this_cpu(); - if (td != NULL) { - td->rested = true; - sched_switch(&td->tf); + if ((td = ci->curtd) == NULL) { + return; } + + td->rested = true; + ci->curtd = NULL; + + md_inton(); + sched_oneshot(false); + md_hlt(); + ci->curtd = td; } void diff --git a/sys/kern/kern_spawn.c b/sys/kern/kern_spawn.c index 032ba24..4105668 100644 --- a/sys/kern/kern_spawn.c +++ b/sys/kern/kern_spawn.c @@ -27,6 +27,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include <sys/spawn.h> #include <sys/proc.h> #include <sys/exec.h> #include <sys/mman.h> @@ -70,7 +71,7 @@ spawn_thunk(void) char *envp[] = { NULL }; cur = this_td(); - args = cur->spawn_data; + args = cur->data; path = args->path; memcpy(pathbuf, path, strlen(path)); @@ -110,6 +111,7 @@ spawn(struct proc *cur, void(*func)(void), void *p, int flags, struct proc **new struct proc *newproc; struct mmap_lgdr *mlgdr; int error; + pid_t pid; newproc = dynalloc(sizeof(*newproc)); if (newproc == NULL) { @@ -150,7 +152,7 @@ spawn(struct proc *cur, void(*func)(void), void *p, int flags, struct proc **new TAILQ_INSERT_TAIL(&cur->leafq, newproc, leaf_link); atomic_inc_int(&cur->nleaves); newproc->parent = cur; - newproc->spawn_data = p; + newproc->data = p; /* Initialize the mmap ledger */ mlgdr->nbytes = 0; @@ -160,7 +162,25 @@ spawn(struct proc *cur, void(*func)(void), void *p, int flags, struct proc **new newproc->pid = ++nthreads; signals_init(newproc); sched_enqueue_td(newproc); - return newproc->pid; + pid = newproc->pid; + + if (ISSET(flags, SPAWN_WAIT)) { + newproc->flags |= PROC_WAITED; + cur->flags |= PROC_SLEEP; + + while (ISSET(cur->flags, PROC_SLEEP)) { + sched_yield(); + } + + if (!ISSET(newproc->flags, PROC_ZOMB)) { + pr_error("spawn: fatal: %d not zombie\n", newproc->pid); + panic("possibly memory corruption\n"); + } + + proc_reap(newproc); + } + + return pid; } /* diff --git a/usr.bin/Makefile b/usr.bin/Makefile index 1c973ff..09d593d 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -6,3 +6,4 @@ ARGS = -I$(ROOT)/builddeps LDSCRIPT=$(LDSCRIPT) USRDIR=$(USRDIR) ROOT=$(ROOT) .PHONY: all all: make -C osh/ $(ARGS) + make -C kmsg/ $(ARGS) diff --git a/usr.bin/fetch/Makefile b/usr.bin/fetch/Makefile new file mode 100644 index 0000000..4b08e84 --- /dev/null +++ b/usr.bin/fetch/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/fetch: + gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/fetch/fetch.c b/usr.bin/fetch/fetch.c new file mode 100644 index 0000000..98b2d3c --- /dev/null +++ b/usr.bin/fetch/fetch.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023-2025 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 <unistd.h> +#include <fcntl.h> +#include <string.h> + +#define prcons(FD, STR) write((FD), (STR), strlen((STR))) + +#define ASCII_ART \ + " ____ \n" \ + " | \\__\\ \n" \ + " | /\\ \\ user: root\n" \ + " |/ \\ \\ OS: Hyra/amd64 v"_OSVER"\n" \ + " \\ R. \\ \\ arch: "_OSARCH"\n" \ + " \\ I. \\ \\\n" + + +int +main(void) +{ + int fd; + + fd = open("/dev/console", O_WRONLY); + if (fd < 0) { + return fd; + } + + prcons(fd, ASCII_ART); + close(fd); + return 0; +} diff --git a/usr.bin/kmsg/Makefile b/usr.bin/kmsg/Makefile new file mode 100644 index 0000000..9b76cc2 --- /dev/null +++ b/usr.bin/kmsg/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/kmsg: + gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/kmsg/kmsg.c b/usr.bin/kmsg/kmsg.c new file mode 100644 index 0000000..678ad8c --- /dev/null +++ b/usr.bin/kmsg/kmsg.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023-2025 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 <sys/types.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> + +int +main(void) +{ + int mfd, cons_fd; + ssize_t retval; + char linebuf[256]; + + if ((mfd = open("/dev/kmsg", O_RDONLY)) < 0) { + return mfd; + } + if ((cons_fd = open("/dev/console", O_WRONLY)) < 0) { + close(mfd); + return cons_fd; + } + + for (;;) { + retval = read(mfd, linebuf, sizeof(linebuf) - 1); + if (retval <= 0) { + break; + } + linebuf[retval] = '\0'; + write(cons_fd, linebuf, strlen(linebuf)); + } + + close(cons_fd); + close(mfd); + return 0; +} diff --git a/usr.bin/osh/osh.c b/usr.bin/osh/osh.c index c45d9c8..583f29a 100644 --- a/usr.bin/osh/osh.c +++ b/usr.bin/osh/osh.c @@ -30,6 +30,7 @@ #include <sys/types.h> #include <sys/cdefs.h> #include <sys/reboot.h> +#include <sys/spawn.h> #include <fcntl.h> #include <stddef.h> #include <unistd.h> @@ -49,6 +50,8 @@ "echo - Print the arguments to the console\n" \ "reboot - Reboot the machine\n" \ "shutdown - Power off the machine\n" \ + "kmsg - Print kernel message buffer\n" \ + "fetch - System information\n" \ "exit - Exit the shell\n" #define PROMPT "[root::osmora]~ " @@ -59,6 +62,7 @@ static int running; struct command { const char *name; + const char *path; void (*func)(int fd, int argc, char *argv[]); }; @@ -165,12 +169,27 @@ getstr(int fd) } } +static void +command_run(struct command *cmd, int fd, int argc, char *argv[]) +{ + if (cmd->func != NULL) { + cmd->func(fd, argc, argv); + return; + } + + if (cmd->path != NULL) { + spawn(cmd->path, SPAWN_WAIT); + } +} + struct command cmds[] = { - {"help", cmd_help}, - {"echo", cmd_echo}, - {"exit", cmd_exit}, - {"reboot", cmd_reboot}, - {"shutdown", cmd_shutdown}, + {"help", NULL, cmd_help}, + {"echo", NULL, cmd_echo}, + {"exit", NULL, cmd_exit}, + {"reboot", NULL, cmd_reboot}, + {"shutdown", NULL, cmd_shutdown}, + {"kmsg", "/usr/bin/kmsg", NULL}, + {"fetch", "/usr/bin/fetch", NULL}, {NULL, NULL} }; @@ -205,7 +224,7 @@ main(void) for (i = 0; cmds[i].name != NULL; i++) { if (strcmp(input, cmds[i].name) == 0) { - cmds[i].func(fd, argc, argv); + command_run(&cmds[i], fd, argc, argv); found = 1; break; } |