diff options
author | Ian Moffett <ian@osmora.org> | 2024-06-24 22:55:29 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2024-06-24 22:55:29 -0400 |
commit | 236963e7563be3e3f8220dac7bb4af446928e194 (patch) | |
tree | e521ea226db0345bbb3679fffe09d96254b7dc73 /sys/kern | |
parent | 214eadc62b5578f76c98a38a28f8b3d80ac4d6ad (diff) |
Clean out for expt
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/init_main.c | 113 | ||||
-rw-r--r-- | sys/kern/kern_cpu.c | 76 | ||||
-rw-r--r-- | sys/kern/kern_device.c | 84 | ||||
-rw-r--r-- | sys/kern/kern_exec.c | 240 | ||||
-rw-r--r-- | sys/kern/kern_filedesc.c | 494 | ||||
-rw-r--r-- | sys/kern/kern_intr.c | 127 | ||||
-rw-r--r-- | sys/kern/kern_ioctl.c | 72 | ||||
-rw-r--r-- | sys/kern/kern_loader.c | 220 | ||||
-rw-r--r-- | sys/kern/kern_mutex.c | 52 | ||||
-rw-r--r-- | sys/kern/kern_panic.c | 63 | ||||
-rw-r--r-- | sys/kern/kern_reboot.c | 51 | ||||
-rw-r--r-- | sys/kern/kern_sched.c | 490 | ||||
-rw-r--r-- | sys/kern/kern_signal.c | 102 | ||||
-rw-r--r-- | sys/kern/kern_subr.c | 134 | ||||
-rw-r--r-- | sys/kern/kern_syscall.c | 54 | ||||
-rw-r--r-- | sys/kern/kern_syslog.c | 168 | ||||
-rw-r--r-- | sys/kern/kern_timer.c | 112 | ||||
-rw-r--r-- | sys/kern/kern_tty.c | 304 | ||||
-rw-r--r-- | sys/kern/vfs_init.c | 89 | ||||
-rw-r--r-- | sys/kern/vfs_lookup.c | 182 | ||||
-rw-r--r-- | sys/kern/vfs_mount.c | 217 | ||||
-rw-r--r-- | sys/kern/vfs_subr.c | 258 |
22 files changed, 0 insertions, 3702 deletions
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c deleted file mode 100644 index 847f4a6..0000000 --- a/sys/kern/init_main.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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 <sys/cdefs.h> -#include <sys/syslog.h> -#include <sys/machdep.h> -#include <sys/timer.h> -#include <sys/sched.h> -#include <sys/tty.h> -#include <sys/vfs.h> -#include <sys/driver.h> -#include <machine/cpu_mp.h> -#include <firmware/acpi/acpi.h> -#include <vm/physseg.h> -#include <logo.h> - -__MODULE_NAME("init_main"); -__KERNEL_META("$Hyra$: init_main.c, Ian Marco Moffett, " - "Where the Hyra kernel first starts up"); - -static inline void -log_timer(const char *purpose, tmrr_status_t s, const struct timer *tmr) -{ - if (s == TMRR_EMPTY_ENTRY) { - kprintf("init_main: %s not yet registered\n", purpose); - } else if (tmr->name == NULL) { - kprintf("init_main: Nameless %s registered; unknown\n", purpose); - } else { - kprintf("init_main: %s registered: %s\n", purpose, tmr->name); - } -} - -/* - * Logs what timers are registered - * on the system. - */ -static void -list_timers(void) -{ - struct timer timer_tmp; - tmrr_status_t status; - - status = req_timer(TIMER_SCHED, &timer_tmp); - log_timer("SCHED_TMR", status, &timer_tmp); - - status = req_timer(TIMER_GP, &timer_tmp); - log_timer("GENERAL_PURPOSE_TMR", status, &timer_tmp); -} - -void -main(void) -{ - struct cpu_info *ci; - int status; - - __TRY_CALL(pre_init); - syslog_init(); - PRINT_LOGO(); - - kprintf("Hyra/%s v%s: %s (%s)\n", - HYRA_ARCH, HYRA_VERSION, HYRA_BUILDDATE, - HYRA_BUILDBRANCH); - - acpi_init(); - __TRY_CALL(chips_init); - - processor_init(); - list_timers(); - vfs_init(); - - /* Attach the root TTY */ - if ((status = tty_attach(&g_root_tty)) < 0) - kprintf("Failed to attach root TTY (got %d)\n", status); - - DRIVERS_INIT(); - sched_init(); - ci = this_cpu(); - - /* Stop writing kernel messages to TTY */ - g_syslog_use_tty = false; - - __TRY_CALL(ap_bootstrap, ci); - sched_enter(); - - while (1); - __builtin_unreachable(); -} diff --git a/sys/kern/kern_cpu.c b/sys/kern/kern_cpu.c deleted file mode 100644 index 1779244..0000000 --- a/sys/kern/kern_cpu.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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 <sys/cpu.h> -#include <sys/types.h> -#include <sys/panic.h> -#include <sys/machdep.h> -#include <vm/dynalloc.h> -#include <assert.h> - -__MODULE_NAME("kern_cpu"); -__KERNEL_META("$Hyra$: kern_cpu.c, Ian Marco Moffett, " - "Machine independent CPU interface"); - -#define CI_LIST_SZ \ - sizeof(struct cpu_info *) * (MAXCPUS + 1) - -static size_t ncpu = 0; -static struct cpu_info **ci_list = NULL; - -void -cpu_attach(struct cpu_info *ci) -{ - if ((ci->idx = ncpu++) >= (MAXCPUS + 1)) { - panic("Machine core count exceeds MAXCPUS!\n"); - } - - if (ci_list == NULL) { - ci_list = dynalloc(CI_LIST_SZ); - __assert(ci_list != NULL); - } - - ci_list[cpu_index(ci)] = ci; -} - -struct cpu_info * -cpu_get(size_t i) -{ - if (i >= ncpu || ci_list == NULL) { - return NULL; - } - - return ci_list[i]; -} - -size_t -cpu_count(void) -{ - return ncpu; -} diff --git a/sys/kern/kern_device.c b/sys/kern/kern_device.c deleted file mode 100644 index cbba965..0000000 --- a/sys/kern/kern_device.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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 <sys/device.h> -#include <sys/queue.h> -#include <sys/errno.h> -#include <sys/types.h> -#include <sys/spinlock.h> - -static TAILQ_HEAD(, device) devices; -static struct spinlock devices_lock = {0}; -static bool device_list_init = false; - -dev_t -device_alloc_major(void) -{ - static dev_t major = 1; - return major++; -} - -struct device * -device_fetch(dev_t major, dev_t minor) -{ - struct device *dev; - - TAILQ_FOREACH(dev, &devices, link) { - if (dev->major == major && dev->minor == minor) { - return dev; - } - } - - return NULL; -} - -dev_t -device_create(struct device *dev, dev_t major, dev_t minor) -{ - if (dev == NULL || minor == 0) { - return -EINVAL; - } - - if (major == 0) { - return -EINVAL; - } - - if (!device_list_init) { - TAILQ_INIT(&devices); - device_list_init = true; - } - - dev->major = major; - dev->minor = minor; - - spinlock_acquire(&devices_lock); - TAILQ_INSERT_HEAD(&devices, dev, link); - spinlock_release(&devices_lock); - return dev->major; -} diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c deleted file mode 100644 index 202da23..0000000 --- a/sys/kern/kern_exec.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * 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 <sys/sched.h> -#include <sys/system.h> -#include <sys/errno.h> -#include <sys/vfs.h> -#include <sys/exec.h> -#include <sys/filedesc.h> -#include <sys/signal.h> -#include <sys/loader.h> -#include <sys/cdefs.h> -#include <vm/dynalloc.h> -#include <sys/syslog.h> -#include <string.h> - -__MODULE_NAME("exec"); -__KERNEL_META("$Hyra$: kern_exec.c, Ian Marco Moffett, " - "exec() implementation"); - -#define ARG_MAX 1024 - -/* - * Allocates a buffer in in `res' and fetches - * the args from `argv' - * - * @argv: User argv - * @res: Exec args result. - * - * XXX: res->argp is dynamically allocated, remember - * to free it! - */ -static int -exec_get_args(char **argv, struct exec_args *res) -{ - static char *dmmy_envp[] = {NULL}; - const size_t ARG_LEN = sizeof(char) * ARG_MAX; - char *argp = NULL; - void *tmp; - - struct proc *td; - size_t argp_len = 0; - - if (res == NULL) - return -EINVAL; - - /* Allocate argp */ - res->argp = dynalloc(ARG_LEN); - if (res->argp == NULL) - return -ENOMEM; - - td = this_td(); - res->vas = td->addrsp; - res->envp = dmmy_envp; - - /* Read argv */ - copyin((uintptr_t)argv, &argp, sizeof(char *)); - for (;;) { - if (argp == NULL) { - res->argp[argp_len] = NULL; - break; - } - - /* Fetch this arg and get next argp */ - copyinstr((uintptr_t)argp, res->argp[argp_len++], ARG_MAX); - copyin((uintptr_t)++argv, &argp, sizeof(char *)); - - /* Try to resize the argp buffer */ - tmp = dynrealloc(res->argp, ARG_LEN * (argp_len + 1)); - if (tmp == NULL) { - dynfree(res->argp); - return -ENOMEM; - } - res->argp = tmp; - } - - return 0; -} - -/* - * Reset the stack of the process. - * - * @td: Target thread. - * @args: Exec args. - * - * Returns the new stack pointer. - */ -static uintptr_t -exec_set_stack(struct proc *td, struct exec_args args) -{ - struct vm_range *stack_range; - uintptr_t stack_top, sp; - - stack_range = &td->addr_range[ADDR_RANGE_STACK]; - stack_top = stack_range->start + (PROC_STACK_SIZE); - - sp = loader_init_stack((void *)stack_top, args); - return sp; -} - -/* - * execv() implementation. - * - * @pathname: Path of file to execute. - * @argv: Args. - * @sp_res: Pointer to new stack pointer - */ -static int -execv(char *pathname, char **argv, uintptr_t *sp_res) -{ - char *bin = NULL; - struct filedesc *filedes; - struct vm_range *exec_range; - struct exec_args args; - - struct proc *td = this_td(); - int fd, ret = 0; - int status; - size_t bin_size; - - if ((status = exec_get_args(argv, &args)) != 0) - return status; - - spinlock_acquire(&td->lock); - fd = open(pathname, O_RDONLY); - - if (fd < 0) { - ret = -ENOENT; - goto done; - } - - filedes = fd_from_fdnum(td, fd); - if (__unlikely(filedes == NULL)) { - /* - * Should not happen. The kernel might be in some - * erroneous state. - */ - ret = -EIO; - goto done; - } - - lseek(fd, 0, SEEK_END); - bin_size = filedes->offset; - lseek(fd, 0, SEEK_SET); - - /* Allocate memory for the binary */ - bin = dynalloc(bin_size); - if (bin == NULL) { - ret = -ENOMEM; - goto done; - } - - /* Read-in the binary */ - if ((status = read(fd, bin, bin_size)) < 0) { - ret = status; - goto done; - } - - /* - * Unload the current process image. After we do this, - * we cannot return in this state until we replace it. - * - * XXX: This is one of the last things we do in case of - * errors. - */ - exec_range = &td->addr_range[ADDR_RANGE_EXEC]; - loader_unload(td->addrsp, exec_range); - - /* - * Now we try to load the new program and hope everything - * works... If something goes wrong here then we'll be forced - * to send a SIGSEGV to the thread. - */ - status = loader_load(td->addrsp, bin, &args.auxv, 0, NULL, exec_range); - if (status != 0) { - /* Well shit */ - kprintf("exec: Failed to load new process image\n"); - signal_raise(td, SIGSEGV); - for (;;); - } - - *sp_res = exec_set_stack(td, args); - set_frame_ip(td->tf, args.auxv.at_entry); -done: - /* We are done, cleanup and release the thread */ - if (bin != NULL) dynfree(bin); - fd_close_fdnum(td, fd); - dynfree(args.argp); - spinlock_release(&td->lock); - return ret; -} - -/* - * Arg0: Pathname - * Arg1: Argv - */ -uint64_t -sys_execv(struct syscall_args *args) -{ - uintptr_t sp; - char pathname[PATH_MAX]; - char **argv = (char **)args->arg1; - - int status; - struct proc *td = this_td(); - - copyinstr(args->arg0, pathname, PATH_MAX); - if ((status = execv(pathname, argv, &sp)) != 0) - return status; - - args->ip = get_frame_ip(td->tf); - args->sp = sp; - return 0; -} diff --git a/sys/kern/kern_filedesc.c b/sys/kern/kern_filedesc.c deleted file mode 100644 index 17a3d84..0000000 --- a/sys/kern/kern_filedesc.c +++ /dev/null @@ -1,494 +0,0 @@ -/* - * 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 <sys/filedesc.h> -#include <sys/proc.h> -#include <sys/sio.h> -#include <sys/sched.h> -#include <sys/errno.h> -#include <sys/system.h> -#include <sys/syslog.h> -#include <sys/vfs.h> -#include <sys/signal.h> -#include <sys/vnode.h> -#include <vm/dynalloc.h> -#include <dev/vcons/vcons.h> -#include <assert.h> -#include <string.h> - -#define MAX_RW_SIZE 0x7FFFF000 - -/* - * This function is a helper for write(). It creates - * a buffer and copies write data to it. - * - * @td: Current thread. - * @data: Data to copy. - * @buf_out: Pointer to buffer that will store data. - * @count: Number of bytes. - */ -static int -make_write_buf(struct proc *td, const void *data, char **buf_out, size_t count) -{ - char *buf = NULL; - - /* Count cannot be 0 or exceed the max size */ - if (count > MAX_RW_SIZE || count == 0) { - return -EINVAL; - } - - buf = dynalloc(count); - - if (buf == NULL) { - return -ENOMEM; - } - - __assert(buf_out != NULL); - *buf_out = buf; - - memset(buf, 0, count); - - if (td->is_user) { - /* - * A user process called us, so we want to be careful - * and use copyin() - */ - if (copyin((uintptr_t)data, buf, count) != 0) { - signal_raise(NULL, SIGSEGV); - } - } else { - /* Can just memcpy() here */ - memcpy(buf, (char *)data, count); - } - - return 0; -} - -/* - * Helper function for write() - */ -static ssize_t -do_write(struct vnode *vp, char *buf, size_t count) -{ - struct sio_txn sio = { .buf = buf, .len = count }; - struct vops *vops = vp->vops; - int status; - - __assert(vops != NULL); - - /* Can we call the write operation? */ - if (vops->write == NULL) { - return -EACCES; - } - - /* Attempt a write */ - if ((status = vops->write(vp, &sio)) < 0) { - return status; - } - - return count; -} - -/* - * Allocate a file descriptor. - * - * @td: Thread to allocate from, NULL for current thread. - * @fd_out: Pointer to allocated file descriptor output. - * - * This routine will create a new file descriptor - * table entry. - * - * Returns 0 on success. - */ -int -fd_alloc(struct proc *td, struct filedesc **fd_out) -{ - struct filedesc *fd; - - if (td == NULL) { - td = this_td(); - __assert(td != NULL); - } - - /* Find free fd table entry */ - for (size_t i = 0; i < PROC_MAX_FDS; ++i) { - if (td->fds[i] != NULL) { - /* In use */ - continue; - } - - fd = dynalloc(sizeof(struct filedesc)); - memset(fd, 0, sizeof(struct filedesc)); - - if (fd == NULL) { - return -ENOMEM; - } - - fd->fdno = i; - td->fds[i] = fd; - - if (fd_out != NULL) - *fd_out = fd; - - return 0; - } - - return -EMFILE; -} - -/* - * 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; - } - - return td->fds[fdno]; -} - -/* - * 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; - } - - if (fd->vnode != NULL) { - vfs_close(fd->vnode); - } - - dynfree(fd); - td->fds[fdno] = NULL; -} - -ssize_t -write(int fd, const void *buf, size_t count) -{ - struct proc *td = this_td(); - struct filedesc *desc = NULL; - struct vnode *vp = NULL; - char *in_buf = NULL; - - ssize_t ret = count; - int status; - - /* - * Create our write buffer... Memory will be allocated - * and data copied. - */ - if ((status = make_write_buf(td, buf, &in_buf, count)) != 0) { - return status; - } - - /* Is this stdout/stderr? */ - if (fd == 1 || fd == 2) { - /* TODO: Update this when we have PTYs */ - vcons_putstr(&g_syslog_screen, in_buf, count); - return count; - } - - desc = fd_from_fdnum(td, fd); - if (desc == NULL) { - return -EBADF; - } - - mutex_acquire(&desc->lock); - if (desc->oflag != O_WRONLY && desc->oflag != O_WRONLY) { - ret = -EACCES; - goto cleanup; - } - - /* Does this file descriptor exist? */ - if (desc == NULL) { - ret = -EBADF; - goto cleanup; - } - - /* Do we have a vnode? */ - if (desc->vnode == NULL) { - ret = -EACCES; - goto cleanup; - } - - vp = desc->vnode; - status = do_write(vp, in_buf, count); - - if (status < 0) { - ret = status; - goto cleanup; - } -cleanup: - mutex_release(&desc->lock); - dynfree(in_buf); - return ret; -} - -/* - * Open a file and return a file descriptor. - * - * @pathname: File path. - * @oflag: Flags. - */ -int -open(const char *pathname, int oflag) -{ - struct vnode *vp; - struct filedesc *fd; - int status; - - /* - * Attempt to create a vnode, call the open hook then - * allocate a file descriptor - */ - if ((status = vfs_path_to_node(pathname, &vp)) != 0) { - return status; - } - if ((status = vfs_open(vp)) != 0) { - return status; - } - if ((status = fd_alloc(this_td(), &fd)) != 0) { - return status; - } - - fd->oflag = oflag; - fd->vnode = vp; - fd->is_dir = (vp->type == VDIR); - return fd->fdno; -} - -/* - * Read file into a buffer. - * - * @fd: File descriptor number. - * @buf: Buffer to read to. - * @count: Number of bytes to read. - */ -int -read(int fd, void *buf, size_t count) -{ - ssize_t bytes_read; - struct vnode *vnode; - struct filedesc *fd_desc; - struct sio_txn sio = { - .buf = buf, - .len = count, - .type = SIO_NONE - }; - - fd_desc = fd_from_fdnum(this_td(), fd); - if (fd_desc == NULL) { - return -EBADF; - } - - mutex_acquire(&fd_desc->lock); - if (fd_desc->oflag == O_WRONLY) { - bytes_read = -EACCES; - goto done; - } - - sio.offset = fd_desc->offset; - vnode = fd_desc->vnode; - - if (count > MAX_RW_SIZE) { - bytes_read = -EACCES; - goto done; - } - - bytes_read = vfs_read(vnode, &sio); - fd_desc->offset += bytes_read; -done: - mutex_release(&fd_desc->lock); - return bytes_read; -} - -/* - * Reposition the file offset - * - * @fd: File descriptor. - * @offset: Offset for the reposition - * @whence: SEEK_SET, SEEK_CUR, or SEEK_END - * - * TODO: Implement SEEK_END - */ -off_t -lseek(int fd, off_t offset, int whence) -{ - struct filedesc *fd_desc; - struct vattr vattr; - - fd_desc = fd_from_fdnum(this_td(), fd); - - if (fd_desc == NULL) { - return -EBADF; - } - - if (vfs_getattr(fd_desc->vnode, &vattr) != 0) { - return -1; - } - - switch (whence) { - case SEEK_SET: - if (offset > vattr.size) - return -ESPIPE; - - fd_desc->offset = offset; - break; - case SEEK_CUR: - if ((fd_desc->offset + offset) > vattr.size) - return -ESPIPE; - - fd_desc->offset += offset; - break; - case SEEK_END: - fd_desc->offset = vattr.size; - break; - default: - return -EINVAL; - } - - return fd_desc->offset; -} - -/* - * arg0: int fd - * arg1: const void *buf - * arg2: count - */ -uint64_t -sys_write(struct syscall_args *args) -{ - return write(args->arg0, (void *)args->arg1, args->arg2); -} - -/* - * arg0: const char *pathname - * arg1: int oflag - */ -uint64_t -sys_open(struct syscall_args *args) -{ - char *pathbuf = dynalloc(sizeof(char) * PATH_MAX); - int ret; - - if (pathbuf == NULL) { - return -ENOMEM; - } - - if (copyinstr(args->arg0, pathbuf, PATH_MAX) != 0) { - signal_raise(NULL, SIGSEGV); - } - - ret = open(pathbuf, args->arg1); - dynfree(pathbuf); - return ret; -} - -/* - * arg0: fd - */ -uint64_t -sys_close(struct syscall_args *args) -{ - fd_close_fdnum(this_td(), args->arg0); - return 0; -} - -/* - * arg0: fd - * arg1: char *buf - * arg2: size_t count - */ -uint64_t -sys_read(struct syscall_args *args) -{ - char *kbuf; - ssize_t bytes_read; - - if (args->arg2 > MAX_RW_SIZE || args->arg2 == 0) { - return -EINVAL; - } - - kbuf = dynalloc(args->arg2); - if (kbuf == NULL) { - return -ENOMEM; - } - - /* - * Try to read into our kernel buffer then copy out - * to userspace. - */ - if ((bytes_read = read(args->arg0, kbuf, args->arg2)) < 0) { - /* Failure */ - dynfree(kbuf); - return bytes_read; - } - if (copyout(kbuf, args->arg1, bytes_read) != 0) { - signal_raise(NULL, SIGSEGV); - } - - dynfree(kbuf); - return bytes_read; -} - -/* - * arg0: fd - * arg1: offset: - * arg2: whence - */ -uint64_t -sys_lseek(struct syscall_args *args) -{ - return lseek(args->arg0, args->arg1, args->arg2); -} diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c deleted file mode 100644 index 0c80334..0000000 --- a/sys/kern/kern_intr.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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 <sys/intr.h> -#include <sys/queue.h> -#include <sys/mutex.h> -#include <vm/dynalloc.h> -#include <fs/procfs.h> -#include <string.h> -#include <assert.h> - -#define PROC_BUF_SIZE 4096 - -static TAILQ_HEAD(, intr_info) intrlist; -static struct mutex intrlist_lock = {0}; -static struct proc_entry *proc; - -static int -proc_read(struct proc_entry *entry, struct sio_txn *sio) -{ - struct intr_info *info; - char buf[PROC_BUF_SIZE]; - char *p = &buf[0]; - size_t idx = 0, len; - int res; - - mutex_acquire(&intrlist_lock); - TAILQ_FOREACH(info, &intrlist, link) { - __assert((sizeof(buf) - idx) > 0); - res = snprintf(p, sizeof(buf) - idx, - "CPU%d\t\t%d\t\t%s\t\t%s\n", - info->affinity, - info->count, - info->source, - info->device - ); - - if (res > 0) { - idx += res; - p += res; - } - - if (idx >= (PROC_BUF_SIZE - 1)) { - break; - } - } - - len = idx + 1; - buf[idx] = '\0'; - - if (sio->len > PROC_BUF_SIZE) - sio->len = PROC_BUF_SIZE; - if (len > sio->len) - len = sio->len; - - memcpy(sio->buf, buf, len); - mutex_release(&intrlist_lock); - return len; -} - -/* - * Register an interrupt stat - * - * @source: Source of interrupt (e.g IOAPIC) - * @dev: Device (e.g i8042) - */ -struct intr_info * -intr_info_alloc(const char *source, const char *dev) -{ - struct intr_info *intr; - - intr = dynalloc(sizeof(*intr)); - if (intr == NULL) - return NULL; - - memset(intr, 0, sizeof(*intr)); - intr->source = source; - intr->device = dev; - return intr; -} - -void -intr_register(struct intr_info *info) -{ - if (info == NULL) - return; - - TAILQ_INSERT_TAIL(&intrlist, info, link); -} - -void -intr_init_proc(void) -{ - /* Init the interrupt list */ - TAILQ_INIT(&intrlist); - - /* Setup /proc/interrupts */ - proc = procfs_alloc_entry(); - proc->read = proc_read; - procfs_add_entry("interrupts", proc); -} diff --git a/sys/kern/kern_ioctl.c b/sys/kern/kern_ioctl.c deleted file mode 100644 index 4b81983..0000000 --- a/sys/kern/kern_ioctl.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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 <sys/system.h> -#include <sys/vnode.h> -#include <sys/filedesc.h> -#include <sys/syscall.h> -#include <sys/errno.h> -#include <sys/sched.h> -#include <fs/devfs.h> - -static int -do_ioctl(int fd, uint32_t cmd, uintptr_t arg) -{ - struct proc *td = this_td(); - struct filedesc *filedes; - struct vnode *vp; - struct device *dev; - int status; - - filedes = fd_from_fdnum(td, fd); - - /* Fetch the vnode */ - if (filedes == NULL) - return -EBADF; - if ((vp = filedes->vnode) == NULL) - return -EIO; - - if ((status = devfs_get_dev(vp, &dev)) != 0) - return status; - if (dev->ioctl == NULL) - return -EIO; - - return dev->ioctl(dev, cmd, arg); -} - -/* - * Arg0: Fd. - * Arg1: Cmd. - * Arg2: Arg. - */ -uint64_t -sys_ioctl(struct syscall_args *args) -{ - return do_ioctl(args->arg0, args->arg1, args->arg2); -} diff --git a/sys/kern/kern_loader.c b/sys/kern/kern_loader.c deleted file mode 100644 index 8edc160..0000000 --- a/sys/kern/kern_loader.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * 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 <sys/loader.h> -#include <sys/cdefs.h> -#include <sys/elf.h> -#include <sys/types.h> -#include <sys/syslog.h> -#include <sys/errno.h> -#include <sys/proc.h> -#include <vm/vm.h> -#include <vm/map.h> -#include <vm/physseg.h> -#include <vm/dynalloc.h> -#include <string.h> -#include <assert.h> - -__MODULE_NAME("kern_loader"); -__KERNEL_META("$Hyra$: kern_loader.c, Ian Marco Moffett, " - "Kernel ELF loader"); - -#define pr_trace(fmt, ...) kprintf("loader: " fmt, ##__VA_ARGS__) -#define pr_error(...) pr_trace(__VA_ARGS__) - -#define PHDR(hdrptr, IDX) \ - (void *)((uintptr_t)hdr + (hdrptr)->e_phoff + (hdrptr->e_phentsize*IDX)) - -int -loader_unload(struct vas vas, struct vm_range *exec_range) -{ - size_t start, end; - - start = exec_range->start; - end = exec_range->end; - - /* FIXME: Figure out how to free physical memory too */ - return vm_map_destroy(vas, start, (end - start)); -} - -uintptr_t -loader_init_stack(void *stack_top, struct exec_args args) -{ - uintptr_t *sp = stack_top; - uintptr_t old_sp = 0; - size_t argc, envc, len; - char **argvp = args.argp; - char **envp = args.envp; - struct auxval auxv = args.auxv; - - /* Copy strings */ - old_sp = (uintptr_t)sp; - for (argc = 0; argvp[argc] != NULL; ++argc) { - len = strlen(argvp[argc]) + 1; - sp = (void *)((char *)sp - len); - memcpy((char *)sp, argvp[argc], len); - } - for (envc = 0; envp[envc] != NULL; ++envc) { - len = strlen(envp[envc]) + 1; - sp = (void *)((char *)sp - len); - memcpy((char *)sp, envp[envc], len); - } - - /* 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); - AUXVAL(sp, AT_PAGESIZE, vm_get_page_size()); - STACK_PUSH(sp, 0); - - /* Copy envp pointers */ - sp -= envc; - for (int i = 0; i < envc; ++i) { - len = strlen(envp[i]) + 1; - old_sp -= len; - sp[i] = KERN_TO_USER(old_sp); - } - - /* Copy argvp pointers */ - STACK_PUSH(sp, 0); - sp -= argc; - for (int i = 0; i < argc; ++i) { - len = strlen(argvp[i]) + 1; - old_sp -= len; - sp[i] = KERN_TO_USER(old_sp); - } - - STACK_PUSH(sp, argc); - return (uintptr_t)sp; -} - -int loader_load(struct vas vas, const void *dataptr, struct auxval *auxv, - size_t load_base, char **ld_path, struct vm_range *prog_range) -{ - const Elf64_Ehdr *hdr = dataptr; - Elf64_Phdr *phdr; - vm_prot_t prot = PROT_USER; - - uintptr_t physmem; - size_t misalign, page_count, map_len; - int status; - - uintptr_t start_addr = (uintptr_t)-1; - uintptr_t end_addr = 0; - - const size_t GRANULE = vm_get_page_size(); - void *tmp_ptr; - - if (auxv == NULL) { - pr_error("Auxval argument NULL\n"); - return -1; - } - - if (memcmp(hdr->e_ident, ELFMAG, 4) != 0) { - /* Bad ELF header */ - pr_error("ELF header bad! (Magic incorrect)\n"); - return -1; - } - - /* Parse program headers */ - for (size_t i = 0; i < hdr->e_phnum; ++i) { - phdr = PHDR(hdr, i); - switch (phdr->p_type) { - case PT_LOAD: - if (__TEST(phdr->p_flags, PF_W)) - prot |= PROT_WRITE; - if (__TEST(phdr->p_flags, PF_X)) { - prot |= PROT_EXEC; - } - - misalign = phdr->p_vaddr & (GRANULE - 1); - page_count = __DIV_ROUNDUP(phdr->p_memsz + misalign, GRANULE); - physmem = vm_alloc_pageframe(page_count); - map_len = page_count * GRANULE; - - /* - * Now we want to compute the start address of the - * program and the end address. - */ - if (start_addr == (uintptr_t)-1) { - start_addr = phdr->p_vaddr; - } - - end_addr = __MAX(end_addr, phdr->p_vaddr + page_count*GRANULE); - - /* Do we not have enough page frames? */ - if (physmem == 0) { - pr_error("Failed to allocate physical memory\n"); - vm_free_pageframe(physmem, page_count); - return -ENOMEM; - } - - status = vm_map_create(vas, phdr->p_vaddr + load_base, physmem, prot, map_len); - - if (status != 0) { - return status; - } - - /* Now we want to copy the data */ - tmp_ptr = (void *)((uintptr_t)hdr + phdr->p_offset); - memcpy(PHYS_TO_VIRT(physmem), tmp_ptr, phdr->p_filesz); - break; - case PT_INTERP: - if (ld_path == NULL) { - break; - } - - *ld_path = dynalloc(phdr->p_filesz); - - if (ld_path == NULL) { - pr_error("Failed to allocate memory for PT_INTERP path\n"); - return -ENOMEM; - } - - memcpy(*ld_path, (char *)hdr + phdr->p_offset, phdr->p_filesz); - break; - case PT_PHDR: - auxv->at_phdr = phdr->p_vaddr + load_base; - break; - } - } - - auxv->at_entry = hdr->e_entry + load_base; - auxv->at_phent = hdr->e_phentsize; - auxv->at_phnum = hdr->e_phnum; - prog_range->start = start_addr; - prog_range->end = end_addr; - return 0; -} diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c deleted file mode 100644 index ea770b1..0000000 --- a/sys/kern/kern_mutex.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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 <sys/mutex.h> -#include <sys/sched.h> -#include <sys/proc.h> - -void -mutex_acquire(struct mutex *mutex) -{ - struct proc *td = this_td(); - register bool rest = (td != NULL); - - while (__atomic_test_and_set(&mutex->lock, __ATOMIC_ACQUIRE)) { - if (!rest) - continue; - - sched_rest(); - } -} - -void -mutex_release(struct mutex *mutex) -{ - __atomic_clear(&mutex->lock, __ATOMIC_RELEASE); -} diff --git a/sys/kern/kern_panic.c b/sys/kern/kern_panic.c deleted file mode 100644 index 71744af..0000000 --- a/sys/kern/kern_panic.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 <sys/panic.h> -#include <sys/syslog.h> -#include <sys/machdep.h> -#include <sys/spinlock.h> - -/* - * Tells the user something terribly - * wrong happened then halting the system - * as soon as possible. - * - * XXX: There is no need to cleanup stuff here (e.g `va_list ap`) - * as we won't be returning from here anyways and the source - * of the panic could be *anywhere* so it's best not to mess with - * things. - */ -void -panic(const char *fmt, ...) -{ - va_list ap; - static struct spinlock lock = {0}; - - intr_mask(); - spinlock_acquire(&lock); /* Never released */ - __TRY_CALL(cpu_halt_others); - - g_syslog_use_tty = true; - va_start(ap, fmt); - - kprintf(OMIT_TIMESTAMP "panic: "); - vkprintf(fmt, &ap); - - machine_panic(); - __builtin_unreachable(); -} diff --git a/sys/kern/kern_reboot.c b/sys/kern/kern_reboot.c deleted file mode 100644 index 8f7c400..0000000 --- a/sys/kern/kern_reboot.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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 <sys/reboot.h> -#include <sys/panic.h> -#include <sys/cdefs.h> -#include <sys/machdep.h> - -int -reboot(int type) -{ - __TRY_CALL(cpu_reset); - - /* Should be unreachable if the reboot works */ - return -1; -} - -/* - * Arg0: Type - */ -uint64_t -sys_reboot(struct syscall_args *args) -{ - return reboot(args->arg0); -} diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c deleted file mode 100644 index ddc99ca..0000000 --- a/sys/kern/kern_sched.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * 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 <sys/sched.h> -#include <sys/schedvar.h> -#include <sys/machdep.h> -#include <sys/loader.h> -#include <sys/errno.h> -#include <sys/cdefs.h> -#include <sys/filedesc.h> -#include <sys/timer.h> -#include <sys/panic.h> -#include <sys/signal.h> -#include <fs/initramfs.h> -#include <vm/dynalloc.h> -#include <vm/physseg.h> -#include <vm/map.h> -#include <vm/pmap.h> -#include <string.h> -#include <assert.h> - -/* - * Thread ready queues - all threads ready to be - * scheduled should be added to the toplevel queue. - */ -static struct sched_queue qlist[SCHED_NQUEUE]; - -/* - * Global scheduler state. - */ -static size_t nthread = 0; -static schedpolicy_t policy = SCHED_POLICY_MLFQ; - -/* - * Thread queue lock - all operations to `qlist' - * must be done with this lock acquired. - * - * This lock is aligned on a cache line boundary to ensure - * it has its own cache line to reduce contention. This is - * because it is constantly acquired and released on every - * processor. - */ -__cacheline_aligned -static struct spinlock tdq_lock = {0}; - -/* - * Lower thread priority. - */ -static inline void -td_pri_lower(struct proc *td) -{ - if (td->priority < (SCHED_NQUEUE - 1)) - ++td->priority; -} - -/* - * Raise thread priority. - */ -static inline void -td_pri_raise(struct proc *td) -{ - if (td->priority > 0) - --td->priority; -} - -/* - * Called during preemption. We raise the priority - * if the thread has been rested. If the thread has not - * been rested, we lower its priority. - */ -static void -td_pri_update(struct proc *td) -{ - if (td->rested) { - td->rested = 0; - td_pri_raise(td); - return; - } - - td_pri_lower(td); -} - -/* - * Enqueue a thread into the scheduler. - */ -static void -sched_enqueue_td(struct proc *td) -{ - struct sched_queue *queue; - - spinlock_acquire(&tdq_lock); - queue = &qlist[td->priority]; - - TAILQ_INSERT_TAIL(&queue->q, td, link); - spinlock_release(&tdq_lock); -} - -/* - * Dequeue a thread from a queue. - */ -static struct proc * -sched_dequeue_td(void) -{ - struct sched_queue *queue; - struct proc *td = NULL; - - spinlock_acquire(&tdq_lock); - - /* - * Try to pop a thread from a queue. We start at the - * highest priority which is 0. - */ - 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); - break; - } - } - - spinlock_release(&tdq_lock); - return td; -} - -/* - * Create a new thread stack. - * sched_new_td() helper. - */ -static uintptr_t -sched_create_stack(bool is_user, struct exec_args args, struct proc *td) -{ - int status; - uintptr_t stack; - struct vm_range *stack_range; - const vm_prot_t USERSTACK_PROT = PROT_WRITE | PROT_USER; - - stack_range = &td->addr_range[ADDR_RANGE_STACK]; - - /* - * Kernel stacks can be allocated with dynalloc() as they - * are on the higher half. - */ - if (!is_user) { - stack = (uintptr_t)dynalloc(PROC_STACK_SIZE); - stack_range->start = stack; - stack_range->end = stack + PROC_STACK_SIZE; - return loader_init_stack((void *)(stack + PROC_STACK_SIZE), args); - } - - stack = vm_alloc_pageframe(PROC_STACK_PAGES); - if (stack == 0) { - return 0; - } - - status = vm_map_create(args.vas, stack, stack, USERSTACK_PROT, PROC_STACK_SIZE); - if (status != 0) { - vm_free_pageframe(stack, PROC_STACK_PAGES); - return 0; - } - - stack_range->start = stack; - stack_range->end = stack + PROC_STACK_SIZE; - - memset(USER_TO_KERN(stack), 0, PROC_STACK_SIZE); - stack = loader_init_stack((void *)USER_TO_KERN(stack + PROC_STACK_SIZE), args); - return stack; -} - -/* - * Create a new thread. - * - * @ip: Instruction pointer to start at. - * @is_user: True for user program. - * @exec_args: Common exec args. - */ -static int -sched_new_td(uintptr_t ip, bool is_user, struct exec_args args, struct vm_range *prog_range, - struct proc **res) -{ - struct vm_range *exec_range; - struct proc *td; - struct trapframe *tf; - uintptr_t stack; - int retval = 0; - - td = dynalloc(sizeof(struct proc)); - tf = dynalloc(sizeof(struct trapframe)); - if (td == NULL || tf == NULL) { - retval = -ENOMEM; - goto done; - } - - /* Keep them in a known state */ - memset(td, 0, sizeof(*td)); - memset(tf, 0, sizeof(*tf)); - - /* Try to create a stack */ - stack = sched_create_stack(is_user, args, td); - if (stack == 0) { - retval = -ENOMEM; - goto done; - } - - /* Setup initial thread state */ - td->pid = ++nthread; - td->tf = tf; - td->addrsp = args.vas; - td->is_user = is_user; - processor_init_pcb(td); - - /* Setup each mapping table */ - for (size_t i = 0; i < MTAB_ENTRIES; ++i) { - TAILQ_INIT(&td->mapspace.mtab[i]); - } - - /* Setup standard file descriptors */ - __assert(fd_alloc(td, NULL) == 0); /* STDIN */ - __assert(fd_alloc(td, NULL) == 0); /* STDOUT */ - __assert(fd_alloc(td, NULL) == 0); /* STDERR */ - - exec_range = &td->addr_range[ADDR_RANGE_EXEC]; - memcpy(exec_range, prog_range, sizeof(struct vm_range)); - - /* Init the trapframe */ - if (!is_user) { - init_frame(tf, ip, stack); - } else { - init_frame_user(tf, ip, KERN_TO_USER(stack)); - } -done: - if (retval != 0 && td != NULL) - dynfree(td); - if (retval != 0 && tf != NULL) - dynfree(td); - if (retval == 0 && res != NULL) - *res = td; - - return retval; -} - -/* - * Perform timer oneshot - * - * @now: True for shortest timeslice. - */ -static inline void -sched_oneshot(bool now) -{ - struct timer timer; - size_t usec = (now) ? SHORT_TIMESLICE_USEC : DEFAULT_TIMESLICE_USEC; - tmrr_status_t tmr_status; - - tmr_status = req_timer(TIMER_SCHED, &timer); - __assert(tmr_status == TMRR_SUCCESS); - - timer.oneshot_us(usec); -} - -/* - * Enter the schedulera and wait until - * preemption. - */ -void -sched_enter(void) -{ - sched_oneshot(false); - - for (;;) { - hint_spinwait(); - } -} - -/* - * Initialize all of the queues. - */ -static void -sched_init_queues(void) -{ - for (size_t i = 0; i < SCHED_NQUEUE; ++i) { - TAILQ_INIT(&qlist[i].q); - } -} - -/* - * Load the first thread (init) - */ -static void -sched_load_init(void) -{ - struct exec_args args; - struct proc *init; - struct auxval *auxvp = &args.auxv; - struct vm_range init_range; - int tmp; - - char *argv[] = {"/usr/sbin/init", NULL}; - char *envp[] = {NULL}; - const char *init_bin; - - if ((init_bin = initramfs_open("/usr/sbin/init")) == NULL) - panic("Could not open /usr/sbin/init\n"); - - pmap_create_vas(vm_get_ctx(), &args.vas); - args.argp = argv; - args.envp = envp; - - tmp = loader_load(args.vas, init_bin, auxvp, 0, NULL, &init_range); - if (tmp != 0) - panic("Failed to load init\n"); - - if (sched_new_td(auxvp->at_entry, true, args, &init_range, &init) != 0) - panic("Failed to create init thread\n"); - - sched_enqueue_td(init); -} - -static void -sched_destroy_td(struct proc *td) -{ - struct vm_range *stack_range; - struct vm_range *exec_range; - vm_mapq_t *mapq; - - processor_free_pcb(td); - stack_range = &td->addr_range[ADDR_RANGE_STACK]; - exec_range = &td->addr_range[ADDR_RANGE_EXEC]; - - /* - * User thread's have their stack allocated - * with vm_alloc_pageframe() and kernel thread's - * have their stacks allocated with dynalloc() - */ - if (td->is_user) { - vm_free_pageframe(stack_range->start, PROC_STACK_PAGES); - } else { - dynfree((void *)stack_range->start); - } - - for (size_t i = 0; i < MTAB_ENTRIES; ++i) { - mapq = &td->mapspace.mtab[i]; - vm_free_mapq(mapq); - } - - for (size_t i = 0; i < PROC_MAX_FDS; ++i) { - fd_close_fdnum(td, i); - } - - loader_unload(td->addrsp, exec_range); - pmap_free_vas(vm_get_ctx(), td->addrsp); - dynfree(td); -} - -/* - * Cause an early preemption and lets - * the next thread run. - */ -void -sched_rest(void) -{ - struct proc *td = this_td(); - - if (td == NULL) - return; - - td->rested = 1; - sched_oneshot(true); -} - -void -sched_exit(void) -{ - struct proc *td = this_td(); - struct vas kvas = vm_get_kvas(); - - spinlock_acquire(&tdq_lock); - intr_mask(); - - /* Switch to kernel VAS and destroy td */ - pmap_switch_vas(vm_get_ctx(), kvas); - sched_destroy_td(td); - - spinlock_release(&tdq_lock); - intr_unmask(); - 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 - * - * Handles the transition from the currently running - * thread to the next thread. - */ -void -sched_context_switch(struct trapframe *tf) -{ - struct cpu_info *ci = this_cpu(); - struct sched_state *state = &ci->sched_state; - struct proc *next_td, *td = state->td; - - if (td != NULL) { - signal_handle(state->td); - } - - /* - * If a thread is currently running and our policy is - * MLFQ, then we should update the thread's priority. - */ - if (td != NULL && policy == SCHED_POLICY_MLFQ) { - td_pri_update(td); - } - - /* Don't preempt if we have no threads */ - if ((next_td = sched_dequeue_td()) == NULL) { - sched_oneshot(false); - return; - } - - /* - * If we have a thread currently running, then we should save - * its current register state and re-enqueue it. - */ - if (td != NULL) { - memcpy(td->tf, tf, sizeof(struct trapframe)); - sched_enqueue_td(td); - } - - /* Perform the switch */ - memcpy(tf, next_td->tf, sizeof(struct trapframe)); - processor_switch_to(td, next_td); - - state->td = next_td; - pmap_switch_vas(vm_get_ctx(), next_td->addrsp); - sched_oneshot(false); -} - -uint64_t -sys_exit(struct syscall_args *args) -{ - sched_exit(); - __builtin_unreachable(); -} - -void -sched_init(void) -{ - sched_init_queues(); - sched_load_init(); -} diff --git a/sys/kern/kern_signal.c b/sys/kern/kern_signal.c deleted file mode 100644 index 7c31c86..0000000 --- a/sys/kern/kern_signal.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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 <sys/proc.h> -#include <sys/sched.h> -#include <sys/cdefs.h> -#include <sys/syslog.h> -#include <sys/signal.h> -#include <dev/vcons/vcons.h> -#include <string.h> - -__MODULE_NAME("kern_signal"); -__KERNEL_META("$Hyra$: kern_signal.c, Ian Marco Moffett, " - "Signal handling code"); - -static void -signal_log(const char *s) -{ - vcons_putstr(&g_syslog_screen, s, strlen(s)); -} - -/* - * Handle any signals within the current thread - * - * TODO: Add sigaction support, default action - * for all currently is killing the process. - */ -void -signal_handle(struct proc *curtd) -{ - int signo = curtd->signal; - - if (signo == 0) { - return; - } - - spinlock_acquire(&curtd->lock); - curtd->signal = 0; - - switch (signo) { - case SIGFPE: - signal_log("Arithmetic error\n"); - break; - case SIGSEGV: - signal_log("Segmentation fault\n"); - break; - case SIGKILL: - signal_log("Killed\n"); - break; - } - - spinlock_release(&curtd->lock); - sched_exit(); -} - -/* - * Raise a signal for a process - * - * @to: Can be NULL to mean the current process - * @signal: Signal to send - * - * TODO: Add more functionality. - */ -void -signal_raise(struct proc *to, int signal) -{ - if (to == NULL) { - to = this_td(); - } - - to->signal = signal; - if (to == this_td()) { - /* Current process, just preempt */ - sched_context_switch(to->tf); - } -} diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c deleted file mode 100644 index d9b1b3a..0000000 --- a/sys/kern/kern_subr.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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 <sys/system.h> -#include <sys/types.h> -#include <sys/errno.h> -#include <sys/sched.h> -#include <vm/vm.h> -#include <string.h> - -/* - * Check if a user address is valid. - * - * @uaddr: User address to check. - * - * Returns true if valid, otherwise false. - */ -static bool -check_uaddr(uintptr_t uaddr) -{ - struct proc *td = this_td(); - struct vm_range exec_range = td->addr_range[ADDR_RANGE_EXEC]; - struct vm_range stack_range = td->addr_range[ADDR_RANGE_STACK]; - - if (uaddr >= exec_range.start && uaddr <= exec_range.end) { - return true; - } - if (uaddr >= stack_range.start && uaddr <= stack_range.end) { - return true; - } - - return false; -} - -/* - * Copy from userspace to the kernel. - * - * @uaddr: Userspace address. - * @kaddr: Kernelspace address. - * @len: Length of data. - */ -int -copyin(uintptr_t uaddr, void *kaddr, size_t len) -{ - if (!check_uaddr(uaddr) || !check_uaddr(uaddr + len)) { - return -EFAULT; - } - - memcpy(kaddr, (void *)uaddr, len); - return 0; -} - -/* - * Copy from the kernel to userspace. - * - * @kaddr: Kernelspace address. - * @uaddr: Userspace address. - * @len: Length of data. - */ -int -copyout(const void *kaddr, uintptr_t uaddr, size_t len) -{ - if (!check_uaddr(uaddr) || !check_uaddr(uaddr + len)) { - return -EFAULT; - } - - memcpy((void *)uaddr, kaddr, len); - return 0; -} - -/* - * Copy in a string from userspace - * - * Unlike the typical copyin(), this routine will - * copy until we've hit NUL ('\0') - * - * @uaddr: Userspace address. - * @kaddr: Kernelspace address. - * @len: Length of string. - * - * XXX: Please note that if `len' is less than the actual - * string length, the returned value will not be - * NUL terminated. - */ -int -copyinstr(uintptr_t uaddr, char *kaddr, size_t len) -{ - char *dest = (char *)kaddr; - char *src = (char *)uaddr; - - if (!check_uaddr(uaddr)) { - return -EFAULT; - } - - for (size_t i = 0; i < len; ++i) { - if (!check_uaddr(uaddr + i)) { - return -EFAULT; - } - - dest[i] = src[i]; - - if (src[i] == '\0') { - break; - } - } - - return 0; -} diff --git a/sys/kern/kern_syscall.c b/sys/kern/kern_syscall.c deleted file mode 100644 index 35185ea..0000000 --- a/sys/kern/kern_syscall.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 <sys/syscall.h> -#include <sys/sched.h> -#include <sys/cdefs.h> -#include <sys/types.h> -#include <sys/filedesc.h> -#include <sys/system.h> -#include <sys/exec.h> -#include <sys/reboot.h> -#include <sys/vfs.h> -#include <vm/map.h> - -uint64_t(*g_syscall_table[__MAX_SYSCALLS])(struct syscall_args *args) = { - sys_exit, - sys_write, - sys_open, - sys_close, - sys_read, - sys_lseek, - sys_mmap, - sys_munmap, - sys_ioctl, - sys_execv, - sys_mount, - sys_reboot -}; diff --git a/sys/kern/kern_syslog.c b/sys/kern/kern_syslog.c deleted file mode 100644 index 86877e0..0000000 --- a/sys/kern/kern_syslog.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * 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 <sys/syslog.h> -#include <sys/machdep.h> -#include <sys/tty.h> -#include <sys/cdefs.h> -#include <sys/timer.h> -#include <sys/spinlock.h> -#include <dev/vcons/vcons.h> -#include <fs/procfs.h> -#include <string.h> - -#if defined(__KMSG_BUF_SHIFT) -#define KMSG_BUF_SHIFT __KMSG_BUF_SHIFT -#else -#define KMSG_BUF_SHIFT 12 -#endif - -#define KMSG_BUF_SIZE (1 << KMSG_BUF_SHIFT) - -__STATIC_ASSERT(KMSG_BUF_SHIFT <= 16, "Log buffer shift too large!\n"); - -static char kmsg_buf[KMSG_BUF_SIZE]; -static size_t kmsg_buf_idx = 0; -static struct proc_entry *kmsg_proc; -static struct spinlock lock = {0}; - -struct vcons_screen g_syslog_screen = {0}; -bool g_syslog_use_tty = true; - -static inline void -kmsg_buf_putc(char c) -{ - kmsg_buf[kmsg_buf_idx++] = c; - kmsg_buf[kmsg_buf_idx] = '\0'; - if (kmsg_buf_idx >= (KMSG_BUF_SIZE - 1)) - kmsg_buf_idx = 0; -} - -static int -proc_kmsg_read(struct proc_entry *p, struct sio_txn *sio) -{ - if (sio->len > KMSG_BUF_SIZE) - sio->len = KMSG_BUF_SIZE; - - memcpy(sio->buf, kmsg_buf, sio->len); - return sio->len; -} - -static void -syslog_write(const char *s, size_t len) -{ - size_t tmp_len = len; - const char *tmp_s = s; - - while (tmp_len--) { -#if defined(__SERIAL_DEBUG) - serial_dbgch(*tmp_s); -#endif /* defined(__SERIAL_DEBUG) */ - kmsg_buf_putc(*tmp_s); - if (g_syslog_use_tty) - tty_putc(&g_root_tty, *tmp_s, TTY_SOURCE_RAW); - - ++tmp_s; - } - - tty_flush(&g_root_tty); -} - -/* - * XXX: Not serialized - */ -void -vkprintf(const char *fmt, va_list *ap) -{ - char buffer[1024] = {0}; - - vsnprintf(buffer, sizeof(buffer), fmt, *ap); - syslog_write(buffer, strlen(buffer)); -} - -void -kprintf(const char *fmt, ...) -{ - va_list ap; - char timestamp[64] = "[ 0.000000] "; - bool has_counter = true; - bool use_timestamp = true; - const char *fmt_p = fmt; - struct timer tmr = {0}; - - spinlock_acquire(&lock); - - /* - * If the first char is OMIT_TIMESTAMP, then we won't - * print out the timestamp. - */ - if (*fmt_p == OMIT_TIMESTAMP[0]) { - ++fmt_p; - use_timestamp = false; - } - - /* See if we can use the counter */ - if (req_timer(TIMER_GP, &tmr) != 0) - has_counter = false; - - /* If we can use the counter, format the timestamp */ - if (has_counter) { - if (tmr.get_time_sec != NULL && tmr.get_time_usec != NULL) - snprintf(timestamp, sizeof(timestamp), "[ %d.%06d] ", - tmr.get_time_sec(), tmr.get_time_usec()); - - } - - if (use_timestamp) { - syslog_write(timestamp, strlen(timestamp)); - } - - va_start(ap, fmt); - vkprintf(fmt_p, &ap); - va_end(ap); - - spinlock_release(&lock); -} - -void -syslog_init_proc(void) -{ - kmsg_proc = procfs_alloc_entry(); - kmsg_proc->read = proc_kmsg_read; - procfs_add_entry("kmsg", kmsg_proc); -} - -void -syslog_init(void) -{ - g_syslog_screen.bg = 0x000000; - g_syslog_screen.fg = 0x808080; - - vcons_attach(&g_syslog_screen); -} diff --git a/sys/kern/kern_timer.c b/sys/kern/kern_timer.c deleted file mode 100644 index 5cc808f..0000000 --- a/sys/kern/kern_timer.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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 <sys/timer.h> - -/* - * When a timer on the machine has been registered - * to the Hyra kernel, they'll be added to the Hyra timer - * registry. - */ -static const struct timer *tmr_registry[TIMER_ID_COUNT] = { 0 }; - -/* - * Returns true if the timer ID given - * is valid. - * - * @id: ID to verify. - */ -static inline bool -is_timer_id_valid(timer_id_t id) -{ - return id < TIMER_ID_COUNT; -} - -/* - * Adds timer on the machine to the timer registry. To be specific, - * this function writes information about the specific timer to the - * timer registry. However, it will not overwrite an entry. To do this - * you must use tmr_registry_overwrite(), of course with caution. - * - * @id: ID of timer to register. - * @tmr: Timer descriptor to register. - */ -tmrr_status_t -register_timer(timer_id_t id, const struct timer *tmr) -{ - if (!is_timer_id_valid(id)) - return TMRR_INVALID_TYPE; - - if (tmr_registry[id] != NULL) - return TMRR_HAS_ENTRY; - - tmr_registry[id] = tmr; - return TMRR_SUCCESS; -} - -/* - * Overwrites an entry within the timer registery. - * Use with caution. - * - * @id: ID of entry to overwrite. - * @tmr: Timer descriptor to write. - */ -tmrr_status_t -tmr_registry_overwrite(timer_id_t id, const struct timer *tmr) -{ - if (!is_timer_id_valid(id)) - return TMRR_INVALID_TYPE; - - tmr_registry[id] = tmr; - return TMRR_SUCCESS; -} - -/* - * Requests a specific timer descriptor - * with a specific ID. - * - * @id: ID to request. - * @tmr_out: Pointer to memory that'll hold the - * requested descriptor. - */ -tmrr_status_t -req_timer(timer_id_t id, struct timer *tmr_out) -{ - if (!is_timer_id_valid(id)) - return TMRR_INVALID_TYPE; - - if (tmr_registry[id] == NULL) - return TMRR_EMPTY_ENTRY; - - if (tmr_out == NULL) - return TMRR_INVALID_ARG; - - *tmr_out = *tmr_registry[id]; - return TMRR_SUCCESS; -} diff --git a/sys/kern/kern_tty.c b/sys/kern/kern_tty.c deleted file mode 100644 index e47c2e2..0000000 --- a/sys/kern/kern_tty.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * 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 <sys/tty.h> -#include <sys/system.h> -#include <sys/cdefs.h> -#include <sys/errno.h> -#include <sys/syslog.h> -#include <sys/ascii.h> -#include <dev/vcons/vcons_io.h> -#include <fs/devfs.h> -#include <string.h> - -static dev_t tty_major = 0; -struct tty g_root_tty = { - .scr = &g_syslog_screen, - .ring = { - .enq_index = 0, - .deq_index = 0, - }, - .termios = { - .c_lflag = ICANON | ECHO - } -}; - -static inline dev_t -tty_alloc_id(void) -{ - static dev_t id = 1; - - return id++; -} - -static inline bool -tty_is_special(char c) -{ - return c < 0x1F; -} - -static inline void -tty_reset_ring(struct tty_ring *ring) -{ - ring->enq_index = 0; - ring->deq_index = 0; -} - -static void -tty_process(struct tty *tty, char c, bool echo) -{ - const struct termios *termios; - bool canon, special; - - termios = &tty->termios; - canon = __TEST(termios->c_lflag, ICANON); - special = tty_is_special(c); - - if (canon && special) - vcons_process_output(tty->scr, c); - if (echo && !special) - vcons_putch(tty->scr, c); -} - -/* - * Flushes the TTY ring buffer. - * - * @tty: TTY to flush. - * - * Returns number of bytes flushed. - */ -static ssize_t -__tty_flush(struct tty *tty) -{ - struct tty_ring *ring = &tty->ring; - struct tty_ring *outring = &tty->outring; - size_t count = 0; - char tmp; - - /* Do we have any data left? */ - if (ring->deq_index >= ring->enq_index) - return -EAGAIN; - - /* - * Flush the input ring to the output ring - * to allow user programs to fetch from it - * with /dev/ttyN. - */ - while (ring->deq_index < ring->enq_index) { - tmp = ring->data[ring->deq_index++]; - outring->data[outring->enq_index++] = tmp; - - if (outring->enq_index > TTY_RING_SIZE) - tty_reset_ring(outring); - - ++count; - } - - tty_reset_ring(ring); - return count; -} - -static int -tty_dev_read(struct device *dev, struct sio_txn *sio) -{ - struct tty_ring *ring = &g_root_tty.outring; - size_t len, max_len; - - spinlock_acquire(&g_root_tty.rlock); - max_len = (ring->enq_index - ring->deq_index); - len = sio->len; - - if (len > max_len) - len = max_len; - - /* - * Transfer data from the TTY ring with SIO then - * ensure the ring is clean by resetting it. - * - * TODO: As of now we are just reading the root - * TTY, add support for multiple TTYs. - */ - memcpy(sio->buf, ring->data, len); - tty_reset_ring(ring); - spinlock_release(&g_root_tty.rlock); - return len; -} - -static int -tty_dev_ioctl(struct device *dev, uint32_t cmd, uintptr_t arg) -{ - /* TODO: Support multiple TTYs */ - struct termios *tp = &g_root_tty.termios; - - switch (cmd) { - case TCGETS: - copyout(tp, arg, sizeof(struct termios)); - break; - case TCSETS: - copyin(arg, tp, sizeof(struct termios)); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int -tty_dev_open(struct device *dev) -{ - /* TODO: Support multiple TTYs */ - struct tty *tty = &g_root_tty; - struct tty_ring *ring = &tty->outring; - - /* Ensure the ring is clean */ - spinlock_acquire(&tty->rlock); - tty_reset_ring(ring); - spinlock_release(&tty->rlock); - return 0; -} - -/* - * Serialized wrapper over __tty_flush() - */ -ssize_t -tty_flush(struct tty *tty) -{ - ssize_t ret; - - spinlock_acquire(&tty->rlock); - ret = __tty_flush(tty); - spinlock_release(&tty->rlock); - return ret; -} - -/* - * Write a character to a TTY - * - * @tty: TTY to write to. - * @c: Character to write. - */ -int -tty_putc(struct tty *tty, int c, int flags) -{ - struct tty_ring *ring; - const struct termios *termios; - bool canon, echo; - - ring = &tty->ring; - termios = &tty->termios; - - canon = __TEST(termios->c_lflag, ICANON); - echo = __TEST(termios->c_lflag, ECHO); - - spinlock_acquire(&tty->rlock); - ring->data[ring->enq_index++] = c; - - /* - * Process the characters for both device input - * and raw input. Device input will only be echoed - * if the ECHO bit is set within c_lflag - */ - if (__TEST(flags, TTY_SOURCE_DEV) && echo) - tty_process(tty, c, echo); - if (__TEST(flags, TTY_SOURCE_RAW)) - tty_process(tty, c, true); - - /* - * If we are in canonical mode and we have a linefeed ('\n') - * character, we should flush the ring. - */ - if (canon && c == ASCII_LF) { - __tty_flush(tty); - } - - /* - * Just flush the ring if we aren't in canonical - * mode. - */ - if (!canon) { - __tty_flush(tty); - } - - /* Reset the ring if it is full */ - if (ring->enq_index >= TTY_RING_SIZE) { - tty_reset_ring(ring); - } - - spinlock_release(&tty->rlock); - return 0; -} - -/* - * Write a string to a TTY - * - * @tty: TTY to write to. - * @s: String to write. - * @count: Number of bytes to write. - */ -int -tty_putstr(struct tty *tty, const char *s, size_t count) -{ - for (size_t i = 0; i < count; ++i) { - tty_putc(tty, *s++, TTY_SOURCE_RAW); - } - - return 0; -} - -dev_t -tty_attach(struct tty *tty) -{ - int tmp; - char devname[128]; - struct device *dev = device_alloc(); - - if (dev == NULL) - return -ENOMEM; - - /* - * Allocate a major for the driver if we don't - * have one yet. - */ - if (tty_major == 0) - tty_major = device_alloc_major(); - - /* Now try to create the device */ - tty->id = tty_alloc_id(); - if ((tmp = device_create(dev, tty_major, tty->id)) < 0) - return tmp; - - dev->read = tty_dev_read; - dev->ioctl = tty_dev_ioctl; - dev->open = tty_dev_open; - dev->blocksize = 1; - - snprintf(devname, sizeof(devname), "tty%d", tty->id); - return devfs_add_dev(devname, dev); -} diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c deleted file mode 100644 index 6754b1f..0000000 --- a/sys/kern/vfs_init.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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 <sys/vfs.h> -#include <sys/cdefs.h> -#include <sys/mount.h> -#include <sys/types.h> -#include <sys/vnode.h> -#include <fs/initramfs.h> -#include <fs/devfs.h> -#include <fs/procfs.h> -#include <assert.h> -#include <string.h> - -__MODULE_NAME("vfs"); -__KERNEL_META("$Hyra$: vfs.c, Ian Marco Moffett, " - "Hyra Virtual File System"); - -#define INITRAMFS_ID 0 -#define DEVFS_ID 1 -#define PROCFS_ID 2 - -static struct fs_info filesystems[] = { - [INITRAMFS_ID] = { "initramfs", &g_initramfs_ops, NULL}, - [DEVFS_ID] = { "dev", &g_devfs_ops, &g_devfs_vops }, - [PROCFS_ID] = { "proc", &g_procfs_ops, &g_procfs_vops } -}; - -struct vnode *g_root_vnode = NULL; - -struct fs_info * -vfs_byname(const char *name) -{ - for (int i = 0; i < __ARRAY_COUNT(filesystems); ++i) { - if (strcmp(filesystems[i].name, name) == 0) { - return &filesystems[i]; - } - } - - return NULL; -} - -void -vfs_init(void) -{ - struct fs_info *info; - struct vfsops *vfsops; - - vfs_mount_init(); - __assert(vfs_alloc_vnode(&g_root_vnode, NULL, VDIR) == 0); - - for (int i = 0; i < __ARRAY_COUNT(filesystems); ++i) { - info = &filesystems[i]; - vfsops = info->vfsops; - - __assert(vfsops->init != NULL); - __assert(vfs_mount(info->name, 0, info) == 0); - vfsops->init(info, NULL); - } - - g_root_vnode->vops = &g_initramfs_vops; - g_root_vnode->fs = &filesystems[INITRAMFS_ID]; -} diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c deleted file mode 100644 index ea73d1a..0000000 --- a/sys/kern/vfs_lookup.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * 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 <sys/types.h> -#include <sys/vfs.h> -#include <sys/mount.h> -#include <sys/errno.h> -#include <vm/dynalloc.h> -#include <string.h> - -/* - * Fetches the filename within a path at - * the nth index denoted by `idx' - * - * Returns memory allocated by dynalloc() - * containing the filename. - * - * XXX: MUST FREE RETURN VALUE WITH dynfree() WHEN - * DONE! - */ -char * -vfs_get_fname_at(const char *path, size_t idx) -{ - size_t pathlen = strlen(path); - size_t fname_len; - - char *path_tmp = dynalloc(pathlen + 2); - char *ret = NULL; - char *start_ptr, *ptr; - - /* Make one-based */ - ++idx; - - if (path_tmp == NULL) { - return NULL; - } - - ptr = path_tmp; - memcpy(path_tmp, path, pathlen + 1); - - /* - * We want to by default have a '/' at the end - * to keep the parsing logic from getting more - * complicated than it needs to be. - */ - path_tmp[pathlen] = '/'; - path_tmp[pathlen + 1] = '\0'; - - /* Skip any leading slashes */ - while (*ptr == '/') - ++ptr; - - start_ptr = ptr; - - /* Get each filename */ - while (*ptr != '\0') { - /* Handle duplicate delimiter */ - if (*ptr == '/' && *(ptr + 1) == '/') { - /* - * Snip this delimiter and skip, the next - * will be read and filename returned (if of course - * the index is reached). - */ - *(ptr++) = '\0'; - continue; - } - - if (*ptr == '/') { - *(ptr++) = '\0'; - - /* Continue if index not reached */ - if ((--idx) != 0) { - start_ptr = ptr; - continue; - } - - /* Index has been reached, start_ptr contains name */ - fname_len = strlen(start_ptr); - ret = dynalloc(fname_len + 1); - - if (ret != NULL) { - memcpy(ret, start_ptr, fname_len + 1); - } - break; - } - - ++ptr; - } - - dynfree(path_tmp); - return ret; -} - -/* - * 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) -{ - struct vnode *vnode = g_root_vnode; - struct mount *mp; - struct fs_info *fs; - char *name; - int s = 0, fs_caps = 0; - - if (strcmp(path, "/") == 0 || !vfs_is_valid_path(path)) { - return -EINVAL; - } else if (*path != '/') { - return -EINVAL; - } - - /* See if we have a mountpoint with this name */ - name = vfs_get_fname_at(path, 0); - if (vfs_get_mp(name, &mp) == 0) { - fs = mp->fs; - vnode = fs->vnode; - } - - /* 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(vnode, path, &vnode); - goto done; - } - - for (size_t i = 1;; ++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; -} diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c deleted file mode 100644 index 27d0ec3..0000000 --- a/sys/kern/vfs_mount.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * 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 <sys/types.h> -#include <sys/queue.h> -#include <sys/mount.h> -#include <sys/vfs.h> -#include <sys/errno.h> -#include <vm/dynalloc.h> -#include <assert.h> -#include <string.h> - -/* TODO: Make this more flexible */ -#define MOUNTLIST_SIZE 8 - -/* Mountlist entry */ -struct mountlist_entry { - TAILQ_HEAD(, mount) buckets; -}; - -static struct mountlist_entry *mountlist = NULL; - -static int -vfs_create_mp(const char *path, int mntflags, struct mount **mp_out) -{ - struct mount *mp; - - mp = dynalloc(sizeof(struct mount)); - if (mp == NULL) { - return -ENOMEM; - } - - mp->flags = mntflags; - *mp_out = mp; - return 0; -} - -static int -mount(const char *source, const char *target, const char *filesystemtype, - unsigned long mountflags, const void *data) -{ - struct vnode *source_vnode; - struct fs_info *info; - int status; - - if (source == NULL || target == NULL || filesystemtype == NULL) - return -EFAULT; - - /* - * Check mount flags. - * - * XXX: No flags implemented yet. - */ - if (mountflags != 0) - return -EINVAL; - - /* Locate source, if any */ - if (strcmp(source, "none") == 0) { - source_vnode = NULL; - } else { - status = vfs_path_to_node(source, &source_vnode); - if (status != 0) - return status; - } - - /* Locate filesystem */ - info = vfs_byname(filesystemtype); - if (info == NULL) - return -ENODEV; - - /* Create mount point */ - status = vfs_mount(target, 0, info); - if (status != 0) - return status; - - /* Initialize filesystem if needed */ - if (info->vfsops->init != NULL) - return info->vfsops->init(info, source_vnode); - - return 0; -} - -/* - * Mount a mountpoint - * - * @path: Path this mountpoint belongs to - * @mntflags: Flags to mount with - * @fs: Filesystem to mount - * - * If this mount entry already exists, -EEXIST - * will be returned. - */ -int -vfs_mount(const char *path, int mntflags, struct fs_info *fs) -{ - size_t hash; - int status; - struct mountlist_entry *entry; - struct mount *mp; - - /* Exclude leading slash */ - if (*path == '/') { - ++path; - } - - hash = vfs_hash_path(path); - - if ((status = vfs_create_mp(path, mntflags, &mp)) != 0) { - return status; - } - - if (hash == -1) { - /* Something is wrong with the path */ - return -EINVAL; - } - - if (vfs_get_mp(path, NULL) == 0) { - /* mount hit, do not duplicate this entry */ - return -EEXIST; - } - - if ((status = vfs_alloc_vnode(&fs->vnode, mp, VDIR)) != 0) { - return status; - } - - mp->phash = hash; - mp->fs = fs; - fs->vnode->vops = fs->vops; - - entry = &mountlist[hash % MOUNTLIST_SIZE]; - TAILQ_INSERT_TAIL(&entry->buckets, mp, link); - return 0; -} - -/* - * Fetch mountpoint - * - * @path: Path of target mountpoint - * @mp: Pointer of variable where mountpoint fetched will - * be stored - * - * Returns 0 upon a mplist hit, on a mplist miss this - * function returns -ENOENT. - */ -int -vfs_get_mp(const char *path, struct mount **mp) -{ - size_t hash; - struct mountlist_entry *entry; - struct mount *mount_iter; - - /* Exclude leading slash */ - if (*path == '/') { - ++path; - } - - hash = vfs_hash_path(path); - - if (hash == 0) { - /* Something is wrong with the path */ - return -EINVAL; - } - - entry = &mountlist[hash % MOUNTLIST_SIZE]; - TAILQ_FOREACH(mount_iter, &entry->buckets, link) { - if (mount_iter->phash == hash) { - if (mp != NULL) *mp = mount_iter; - return 0; - } - } - - return -ENOENT; -} - -void -vfs_mount_init(void) -{ - mountlist = dynalloc(sizeof(struct mountlist_entry) * MOUNTLIST_SIZE); - __assert(mountlist != NULL); - - for (size_t i = 0; i < MOUNTLIST_SIZE; ++i) { - TAILQ_INIT(&mountlist[i].buckets); - } -} - -uint64_t -sys_mount(struct syscall_args *args) -{ - return mount((void *)args->arg0, (void *)args->arg1, (void *)args->arg2, - (unsigned long)args->arg3, (void *)args->arg4); -} diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c deleted file mode 100644 index 60afa31..0000000 --- a/sys/kern/vfs_subr.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * 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 <sys/types.h> -#include <sys/vfs.h> -#include <sys/errno.h> -#include <sys/mount.h> -#include <vm/dynalloc.h> -#include <string.h> - -/* FNV-1a defines */ -#define FNV_OFFSET 14695981039346656037ULL -#define FNV_PRIME 1099511628211ULL - -/* - * FNV-1a hash function - * https://en.wikipedia.org/wiki/Fowler–Noll–Vo_hash_function - */ -static size_t -vfs_hash(const char *data) -{ - size_t hash = FNV_OFFSET; - const char *p = data; - - while (*p) { - hash ^= (size_t)(uint8_t)(*p); - hash *= FNV_PRIME; - ++p; - } - - return hash; -} - -/* - * Hashes a path - * - * @path: Path to hash. - * - * Returns -1 on failure, >= 0 return values - * are valid. - */ -ssize_t -vfs_hash_path(const char *path) -{ - char *name = NULL; - size_t i = 0, hash = 0; - - if (strcmp(path, "/") == 0 || !vfs_is_valid_path(path)) { - return -1; - } - - do { - name = vfs_get_fname_at(path, i++); - if (name != NULL) { - hash += vfs_hash(name); - dynfree(name); - } - } while (name != NULL); - - return hash; -} - - -/* - * This function checks if a path is valid. - * - * @path: Path to check. - * - * Returns true if valid, otherwise false. - */ -bool -vfs_is_valid_path(const char *path) -{ - const char *ptr = path; - char c; - - while (*ptr != '\0') { - c = *(ptr++); - switch (c) { - case '/': - case '-': - case '_': - case '.': - /* Valid char, can continue */ - continue; - default: - /* - * This could be an alphabetical or "numeric" char which - * is valid. We want to handle this too. To make things - * easier we'll OR the char by 0x20 to convert it to - * lowercase if it is alphabetical. - */ - c |= 0x20; - if (c >= 'a' && c <= 'z') - continue; - else if (c >= '0' && c <= '9') - continue; - - /* We got an invalid char */ - return false; - } - } - - return true; -} - -/* - * Allocates a vnode - * - * @vnode: Pointer to vnode pointer where newly allocated - * vnode will be stored. - * - * @mp: Mountpoint this vnode is associated with. - * @type: Vnode type. - * - * This function will return 0 upon success and < 0 on failure. - */ -int -vfs_alloc_vnode(struct vnode **vnode, struct mount *mp, int type) -{ - struct vnode *new_vnode = dynalloc(sizeof(struct vnode)); - - if (new_vnode == NULL) { - return -ENOMEM; - } - - memset(new_vnode, 0, sizeof(struct vnode)); - new_vnode->type = type; - new_vnode->mp = mp; - - *vnode = new_vnode; - return 0; -} - -/* - * Returns the rootname of a path - * For example, "/foo/bar/" will be "foo" and - * "/foo/bar/baz" will also be "foo" - * - * There will be no slashes in the returned string - * unless "/" is passed. - * - * XXX: Returns memory allocated by dynalloc, - * remember to free the memory with dynfree() - * - * @path: Path to get rootname of - * @new_path: New path will be placed here. - */ -int -vfs_rootname(const char *path, char **new_path) -{ - char *tmp = NULL; - const char *ptr = path; - size_t len = 0; - - if (!vfs_is_valid_path(path)) { - *new_path = NULL; - return -EINVAL; - } - - if (*path == '/') { - /* Skip first '/' */ - ++ptr; - ++path; - } - - for (; *ptr != '\0' && *ptr != '/'; ++ptr) { - if (*ptr == '/') { - break; - } - ++len; - } - - tmp = dynalloc(sizeof(char) * len + 1); - if (tmp == NULL) { - *new_path = NULL; - return -ENOMEM; - } - - if (len == 0) { - /* Handle input that is just "/" */ - tmp[0] = '/'; - tmp[1] = '\0'; - } else { - memcpy(tmp, path, len + 2); - } - - *new_path = tmp; - return 0; -} - - -int -vfs_vget(struct vnode *parent, const char *name, struct vnode **vp) -{ - return parent->vops->vget(parent, name, vp); -} - -ssize_t -vfs_read(struct vnode *vp, struct sio_txn *sio) -{ - return vp->vops->read(vp, sio); -} - -ssize_t -vfs_write(struct vnode *vp, struct sio_txn *sio) -{ - return vp->vops->write(vp, sio); -} - -int -vfs_getattr(struct vnode *vp, struct vattr *vattr) -{ - return vp->vops->getattr(vp, vattr); -} - -int vfs_open(struct vnode *vp) -{ - if (vp->vops->open == NULL) - return -EIO; - - return vp->vops->open(vp); -} - -int -vfs_close(struct vnode *vp) -{ - if (vp->vops->close == NULL) - return -EIO; - - return vp->vops->close(vp); -} |