diff options
33 files changed, 793 insertions, 122 deletions
diff --git a/Makefile.in b/Makefile.in index 1270a21..508ee1c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -73,12 +73,12 @@ all: stand/boot/ libc sbin bin base/boot/hyra-kernel .PHONY: sbin sbin: $(SBIN_MAKEDIRS) make -C usr.sbin/ LDSCRIPT=$(shell pwd)/usr.sbin/link.ld USRDIR=$(USRDIR)\ - ROOT=$(PROJECT_ROOT)\ + ROOT=$(PROJECT_ROOT) OSVER=$(HYRA_VERSION) OSARCH=$(ARCH) .PHONY: bin bin: $(BIN_MAKEDIRS) make -C usr.bin/ LDSCRIPT=$(shell pwd)/usr.bin/link.ld USRDIR=$(USRDIR)\ - ROOT=$(PROJECT_ROOT) + ROOT=$(PROJECT_ROOT) OSVER=$(HYRA_VERSION) OSARCH=$(ARCH) .PHONY: libc libc: diff --git a/builddeps/user.mk b/builddeps/user.mk index d7ad582..d991ef8 100644 --- a/builddeps/user.mk +++ b/builddeps/user.mk @@ -4,4 +4,5 @@ USRDIR = LDSCRIPT = INTERNAL_CFLAGS = -T$(LDSCRIPT) -znoexecstack -nostdlib -I$(USRDIR)/include/ \ -L$(USRDIR)/lib -lc -pie -no-pie -fno-stack-protector \ - -fno-asynchronous-unwind-tables + -fno-asynchronous-unwind-tables -D_OSVER=\"$(OSVER)\" \ + -D_OSARCH=\"$(OSARCH)\" diff --git a/configure.ac b/configure.ac index 5c19c32..358527a 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([Hyra], [1.7], [ian@osmora.org]) +AC_INIT([Hyra], [1.8], [ian@osmora.org]) TARGET="amd64" PROJECT_ROOT=`pwd` diff --git a/lib/libc/include/stdatomic.h b/lib/libc/include/stdatomic.h new file mode 100644 index 0000000..3f80270 --- /dev/null +++ b/lib/libc/include/stdatomic.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _STDATOMIC_H +#define _STDATOMIC_H 1 + +#include <stddef.h> +#include <stdint.h> + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L +#define __STDC_VERSION_STDATOMIC_H__ 202311L +#endif + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + +#define kill_dependency(y) (y) + +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ < 202311L) || defined(__cplusplus) +/* Deprecated in C17, removed in C23 */ +#define ATOMIC_VAR_INIT(value) (value) +#endif + +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L) || defined(__cplusplus) +#define ATOMIC_FLAG_INIT { false } +typedef _Atomic(bool) atomic_bool; +#else +#define ATOMIC_FLAG_INIT { 0 } +typedef _Atomic(_Bool) atomic_bool; +#endif + +typedef _Atomic(signed char) atomic_schar; + +typedef _Atomic(char) atomic_char; +typedef _Atomic(short) atomic_short; +typedef _Atomic(int) atomic_int; +typedef _Atomic(long) atomic_long; +typedef _Atomic(long long) atomic_llong; + +typedef _Atomic(unsigned char) atomic_uchar; +typedef _Atomic(unsigned short) atomic_ushort; +typedef _Atomic(unsigned int) atomic_uint; +typedef _Atomic(unsigned long) atomic_ulong; +typedef _Atomic(unsigned long long) atomic_ullong; + +typedef _Atomic(uintptr_t) atomic_uintptr_t; +typedef _Atomic(size_t) atomic_size_t; + +typedef struct atomic_flag { + atomic_bool _Value; +} atomic_flag; + +typedef enum memory_order { + memory_order_relaxed = __ATOMIC_RELAXED, + memory_order_consume = __ATOMIC_CONSUME, + memory_order_acquire = __ATOMIC_ACQUIRE, + memory_order_release = __ATOMIC_RELEASE, + memory_order_acq_rel = __ATOMIC_ACQ_REL, + memory_order_seq_cst = __ATOMIC_SEQ_CST +} memory_order; + +#define atomic_is_lock_free(obj) __atomic_is_lock_free(sizeof(*(obj)), 0) +#define atomic_flag_test_and_set(obj) __atomic_test_and_set((obj), memory_order_seq_cst) +#define atomic_flag_clear(obj) __atomic_clear((obj), memory_order_seq_cst) +#define atomic_load(obj) __atomic_load_n((obj), memory_order_seq_cst) +#define atomic_store(obj, desired) __atomic_store_n((obj), (desired), memory_order_seq_cst) +#define atomic_exchange(obj, desired) __atomic_exchange_n((obj), (desired), memory_order_seq_cst) +#define atomic_fetch_add(obj, arg) __atomic_fetch_add((obj), (arg), memory_order_seq_cst) +#define atomic_fetch_sub(obj, arg) __atomic_fetch_sub((obj), (arg), memory_order_seq_cst) +#define atomic_fetch_and(obj, arg) __atomic_fetch_and((obj), (arg), memory_order_seq_cst) +#define atomic_fetch_or(obj, arg) __atomic_fetch_or((obj), (arg), memory_order_seq_cst) +#define atomic_fetch_xor(obj, arg) __atomic_fetch_xor((obj), (arg), memory_order_seq_cst) + +#define atomic_signal_fence __atomic_signal_fence +#define atomic_thread_fence __atomic_thread_fence +#define atomic_flag_test_and_set_explicit __atomic_test_and_set +#define atomic_flag_clear_explicit __atomic_clear +#define atomic_load_explicit __atomic_load_n +#define atomic_store_explicit __atomic_store_n +#define atomic_exchange_explicit __atomic_exchange_n +#define atomic_fetch_add_explicit __atomic_fetch_add +#define atomic_fetch_sub_explicit __atomic_fetch_sub +#define atomic_fetch_and_explicit __atomic_fetch_and +#define atomic_fetch_or_explicit __atomic_fetch_or +#define atomic_fetch_xor_explicit __atomic_fetch_xor + +#define atomic_compare_exchange_strong(obj, expected, desired) __atomic_compare_exchange_n((obj), (expected), (desired), false, memory_order_seq_cst, memory_order_seq_cst) +#define atomic_compare_exchange_weak(obj, expected, desired) __atomic_compare_exchange_n((obj), (expected), (desired), true, memory_order_seq_cst, memory_order_seq_cst) +#define atomic_compare_exchange_strong_explicit __atomic_compare_exchange_n +#define atomic_compare_exchange_weak_explicit __atomic_compare_exchange_n + +#endif + +#endif /* !_STDATOMIC_H */ diff --git a/sys/arch/aarch64/aarch64/pmap.c b/sys/arch/aarch64/aarch64/pmap.c index b5ebda9..7e93959 100644 --- a/sys/arch/aarch64/aarch64/pmap.c +++ b/sys/arch/aarch64/aarch64/pmap.c @@ -66,3 +66,24 @@ pmap_destroy_vas(struct vas vas) /* TODO: STUB */ return; } + +bool +pmap_is_clean(struct vas vas, vaddr_t va) +{ + /* TODO: STUB */ + return false; +} + +void +pmap_mark_clean(struct vas vas, vaddr_t va) +{ + /* TODO: STUB */ + return; +} + +int +pmap_set_cache(struct vas vas, vaddr_t va, int type) +{ + /* TODO: STUB */ + return 0; +} diff --git a/sys/arch/amd64/amd64/intr.c b/sys/arch/amd64/amd64/intr.c index 1529b1c..9f70e88 100644 --- a/sys/arch/amd64/amd64/intr.c +++ b/sys/arch/amd64/amd64/intr.c @@ -96,11 +96,12 @@ intr_register(const char *name, const struct intr_hand *ih) * Try to allocate an interrupt vector. An IPL is made up * of 4 bits so there can be 16 vectors per IPL. * - * XXX: Vector 0x20 is reserved for the Hyra scheduler and - * vector 0x21 is reserved for the CPU halt IPI. + * XXX: Vector 0x20 is reserved for the Hyra scheduler, + * vector 0x21 is reserved for the CPU halt IPI, + * and vector 0x22 is reserved for TLB shootdowns. */ for (int i = vec; i < vec + 16; ++i) { - if (g_intrs[i] != NULL || i < 0x22) { + if (g_intrs[i] != NULL || i < 0x23) { continue; } diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index 3381437..c6fb6c4 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -42,9 +42,11 @@ #include <machine/uart.h> #include <machine/sync.h> #include <machine/intr.h> +#include <machine/cdefs.h> #include <machine/isa/i8042var.h> #define HALT_VECTOR 0x21 +#define TLB_VECTOR 0x22 #if defined(__SPECTRE_IBRS) #define SPECTRE_IBRS __SPECTRE_IBRS @@ -52,8 +54,6 @@ #define SPECTRE_IBRS 0 #endif -static uint8_t halt_vector = 0; - int ibrs_enable(void); void syscall_isr(void); void pin_isr_load(void); @@ -68,6 +68,31 @@ cpu_halt_isr(void *p) __builtin_unreachable(); } +__attribute__((__interrupt__)) +static void +tlb_shootdown_isr(void *p) +{ + struct cpu_info *ci; + int ipl; + + /* + * Get the current CPU and check if we even + * need a shootdown. If `tlb_shootdown' is + * unset, this is not for us. + */ + ci = this_cpu(); + if (!ci->tlb_shootdown) { + return; + } + + ipl = splraise(IPL_HIGH); + __invlpg(ci->shootdown_va); + + ci->shootdown_va = 0; + ci->tlb_shootdown = 0; + splx(ipl); +} + static void setup_vectors(void) { @@ -85,6 +110,7 @@ setup_vectors(void) idt_set_desc(0xE, IDT_TRAP_GATE, ISR(page_fault), 0); idt_set_desc(0x80, IDT_USER_INT_GATE, ISR(syscall_isr), 0); idt_set_desc(HALT_VECTOR, IDT_INT_GATE, ISR(cpu_halt_isr), 0); + idt_set_desc(TLB_VECTOR, IDT_INT_GATE, ISR(tlb_shootdown_isr), 0); pin_isr_load(); } @@ -130,6 +156,26 @@ backtrace_addr_to_name(uintptr_t addr, off_t *off) } void +cpu_shootdown_tlb(vaddr_t va) +{ + uint32_t ncpu = cpu_count(); + struct cpu_info *cip; + + for (uint32_t i = 0; i < ncpu; ++i) { + cip = cpu_get(i); + if (cip == NULL) { + break; + } + + spinlock_acquire(&cip->lock); + cip->shootdown_va = va; + cip->tlb_shootdown = 1; + lapic_send_ipi(cip->apicid, IPI_SHORTHAND_NONE, TLB_VECTOR); + spinlock_release(&cip->lock); + } +} + +void md_backtrace(void) { uintptr_t *rbp; @@ -166,7 +212,7 @@ cpu_halt_all(void) } /* Send IPI to all cores */ - lapic_send_ipi(0, IPI_SHORTHAND_ALL, halt_vector); + lapic_send_ipi(0, IPI_SHORTHAND_ALL, HALT_VECTOR); for (;;); } diff --git a/sys/arch/amd64/amd64/mp.c b/sys/arch/amd64/amd64/mp.c index 22561d7..1e6d8d9 100644 --- a/sys/arch/amd64/amd64/mp.c +++ b/sys/arch/amd64/amd64/mp.c @@ -29,6 +29,7 @@ #include <sys/types.h> #include <sys/limine.h> +#include <sys/limits.h> #include <sys/syslog.h> #include <sys/spinlock.h> #include <sys/sched.h> @@ -45,7 +46,9 @@ static volatile struct limine_smp_request g_smp_req = { .revision = 0 }; -static volatile uint32_t ncpu_up = 0; +static volatile uint32_t ncpu_up = 1; +static struct cpu_info *ci_list[CPU_MAX]; +static struct spinlock ci_list_lock = {0}; static void ap_trampoline(struct limine_smp_info *si) @@ -57,11 +60,31 @@ ap_trampoline(struct limine_smp_info *si) memset(ci, 0, sizeof(*ci)); cpu_startup(ci); + spinlock_acquire(&ci_list_lock); + ci_list[ncpu_up] = ci; + spinlock_release(&ci_list_lock); + atomic_inc_int(&ncpu_up); sched_enter(); while (1); } +struct cpu_info * +cpu_get(uint32_t index) +{ + if (index >= ncpu_up) { + return NULL; + } + + return ci_list[index]; +} + +uint32_t +cpu_count(void) +{ + return ncpu_up; +} + void mp_bootstrap_aps(struct cpu_info *ci) { @@ -74,6 +97,7 @@ mp_bootstrap_aps(struct cpu_info *ci) cpus = resp->cpus; cpu_init_counter = resp->cpu_count - 1; + ci_list[0] = ci; if (resp->cpu_count == 1) { pr_trace("CPU has 1 core, no APs to bootstrap...\n"); @@ -91,5 +115,5 @@ mp_bootstrap_aps(struct cpu_info *ci) } /* Wait for all cores to be ready */ - while (ncpu_up < cpu_init_counter); + while ((ncpu_up - 1) < cpu_init_counter); } diff --git a/sys/arch/amd64/amd64/pmap.c b/sys/arch/amd64/amd64/pmap.c index 2e62a4b..0bdf3b7 100644 --- a/sys/arch/amd64/amd64/pmap.c +++ b/sys/arch/amd64/amd64/pmap.c @@ -33,6 +33,8 @@ #include <sys/errno.h> #include <machine/tlb.h> #include <machine/vas.h> +#include <machine/cpu.h> +#include <machine/cdefs.h> #include <vm/pmap.h> #include <vm/physmem.h> #include <vm/vm.h> @@ -303,3 +305,37 @@ pmap_set_cache(struct vas vas, vaddr_t va, int type) return 0; } + +bool +pmap_is_clean(struct vas vas, vaddr_t va) +{ + uintptr_t *tbl; + int status; + size_t idx; + + if ((status = pmap_get_tbl(vas, va, false, &tbl)) != 0) + return status; + + idx = pmap_get_level_index(1, va); + return ISSET(tbl[idx], PTE_DIRTY) == 0; +} + +void +pmap_mark_clean(struct vas vas, vaddr_t va) +{ + uintptr_t *tbl; + int status; + size_t idx; + + if ((status = pmap_get_tbl(vas, va, false, &tbl)) != 0) + return; + + idx = pmap_get_level_index(1, va); + tbl[idx] &= ~PTE_DIRTY; + + if (cpu_count() > 1) { + cpu_shootdown_tlb(va); + } else { + __invlpg(va); + } +} diff --git a/sys/arch/amd64/amd64/vector.S b/sys/arch/amd64/amd64/vector.S index 32ccd34..d2a3d89 100644 --- a/sys/arch/amd64/amd64/vector.S +++ b/sys/arch/amd64/amd64/vector.S @@ -64,69 +64,69 @@ done: .globl pin_isr_load pin_isr_load: - IDT_SET_VEC 34, ioapic_edge_0 - IDT_SET_VEC 35, ioapic_edge_1 - IDT_SET_VEC 36, ioapic_edge_2 - IDT_SET_VEC 37, ioapic_edge_3 - IDT_SET_VEC 38, ioapic_edge_4 - IDT_SET_VEC 39, ioapic_edge_5 - IDT_SET_VEC 40, ioapic_edge_6 - IDT_SET_VEC 41, ioapic_edge_7 - IDT_SET_VEC 42, ioapic_edge_8 - IDT_SET_VEC 43, ioapic_edge_9 - IDT_SET_VEC 44, ioapic_edge_10 - IDT_SET_VEC 45, ioapic_edge_11 - IDT_SET_VEC 46, ioapic_edge_12 - IDT_SET_VEC 47, ioapic_edge_13 - IDT_SET_VEC 48, ioapic_edge_14 - IDT_SET_VEC 49, ioapic_edge_15 - IDT_SET_VEC 50, ioapic_edge_16 - IDT_SET_VEC 51, ioapic_edge_17 - IDT_SET_VEC 52, ioapic_edge_18 - IDT_SET_VEC 53, ioapic_edge_19 - IDT_SET_VEC 54, ioapic_edge_20 - IDT_SET_VEC 55, ioapic_edge_21 - IDT_SET_VEC 56, ioapic_edge_22 - IDT_SET_VEC 57, ioapic_edge_23 - IDT_SET_VEC 58, ioapic_edge_24 - IDT_SET_VEC 59, ioapic_edge_25 - IDT_SET_VEC 60, ioapic_edge_26 - IDT_SET_VEC 61, ioapic_edge_27 - IDT_SET_VEC 62, ioapic_edge_28 - IDT_SET_VEC 63, ioapic_edge_29 - IDT_SET_VEC 64, ioapic_edge_30 - IDT_SET_VEC 65, ioapic_edge_31 - IDT_SET_VEC 66, ioapic_edge_32 - IDT_SET_VEC 67, ioapic_edge_33 - IDT_SET_VEC 68, ioapic_edge_34 - IDT_SET_VEC 69, ioapic_edge_35 - IDT_SET_VEC 70, ioapic_edge_36 - IDT_SET_VEC 71, ioapic_edge_37 - IDT_SET_VEC 72, ioapic_edge_38 - IDT_SET_VEC 73, ioapic_edge_39 - IDT_SET_VEC 74, ioapic_edge_40 - IDT_SET_VEC 75, ioapic_edge_41 - IDT_SET_VEC 76, ioapic_edge_42 - IDT_SET_VEC 77, ioapic_edge_43 - IDT_SET_VEC 78, ioapic_edge_44 - IDT_SET_VEC 79, ioapic_edge_45 - IDT_SET_VEC 80, ioapic_edge_46 - IDT_SET_VEC 81, ioapic_edge_47 - IDT_SET_VEC 82, ioapic_edge_48 - IDT_SET_VEC 83, ioapic_edge_49 - IDT_SET_VEC 84, ioapic_edge_50 - IDT_SET_VEC 85, ioapic_edge_51 - IDT_SET_VEC 86, ioapic_edge_52 - IDT_SET_VEC 87, ioapic_edge_53 - IDT_SET_VEC 88, ioapic_edge_54 - IDT_SET_VEC 89, ioapic_edge_55 - IDT_SET_VEC 90, ioapic_edge_56 - IDT_SET_VEC 91, ioapic_edge_57 - IDT_SET_VEC 92, ioapic_edge_58 - IDT_SET_VEC 93, ioapic_edge_59 - IDT_SET_VEC 94, ioapic_edge_60 - IDT_SET_VEC 95, ioapic_edge_61 - IDT_SET_VEC 96, ioapic_edge_62 + IDT_SET_VEC 35, ioapic_edge_0 + IDT_SET_VEC 36, ioapic_edge_1 + IDT_SET_VEC 37, ioapic_edge_2 + IDT_SET_VEC 38, ioapic_edge_3 + IDT_SET_VEC 39, ioapic_edge_4 + IDT_SET_VEC 40, ioapic_edge_5 + IDT_SET_VEC 41, ioapic_edge_6 + IDT_SET_VEC 42, ioapic_edge_7 + IDT_SET_VEC 43, ioapic_edge_8 + IDT_SET_VEC 44, ioapic_edge_9 + IDT_SET_VEC 45, ioapic_edge_10 + IDT_SET_VEC 46, ioapic_edge_11 + IDT_SET_VEC 47, ioapic_edge_12 + IDT_SET_VEC 48, ioapic_edge_13 + IDT_SET_VEC 49, ioapic_edge_14 + IDT_SET_VEC 50, ioapic_edge_15 + IDT_SET_VEC 51, ioapic_edge_16 + IDT_SET_VEC 52, ioapic_edge_17 + IDT_SET_VEC 53, ioapic_edge_18 + IDT_SET_VEC 54, ioapic_edge_19 + IDT_SET_VEC 55, ioapic_edge_20 + IDT_SET_VEC 56, ioapic_edge_21 + IDT_SET_VEC 57, ioapic_edge_22 + IDT_SET_VEC 58, ioapic_edge_23 + IDT_SET_VEC 59, ioapic_edge_24 + IDT_SET_VEC 60, ioapic_edge_25 + IDT_SET_VEC 61, ioapic_edge_26 + IDT_SET_VEC 62, ioapic_edge_27 + IDT_SET_VEC 63, ioapic_edge_28 + IDT_SET_VEC 64, ioapic_edge_29 + IDT_SET_VEC 65, ioapic_edge_30 + IDT_SET_VEC 66, ioapic_edge_31 + IDT_SET_VEC 67, ioapic_edge_32 + IDT_SET_VEC 68, ioapic_edge_33 + IDT_SET_VEC 69, ioapic_edge_34 + IDT_SET_VEC 70, ioapic_edge_35 + IDT_SET_VEC 71, ioapic_edge_36 + IDT_SET_VEC 72, ioapic_edge_37 + IDT_SET_VEC 73, ioapic_edge_38 + IDT_SET_VEC 74, ioapic_edge_39 + IDT_SET_VEC 75, ioapic_edge_40 + IDT_SET_VEC 76, ioapic_edge_41 + IDT_SET_VEC 77, ioapic_edge_42 + IDT_SET_VEC 78, ioapic_edge_43 + IDT_SET_VEC 79, ioapic_edge_44 + IDT_SET_VEC 80, ioapic_edge_45 + IDT_SET_VEC 81, ioapic_edge_46 + IDT_SET_VEC 82, ioapic_edge_47 + IDT_SET_VEC 83, ioapic_edge_48 + IDT_SET_VEC 84, ioapic_edge_49 + IDT_SET_VEC 85, ioapic_edge_50 + IDT_SET_VEC 86, ioapic_edge_51 + IDT_SET_VEC 87, ioapic_edge_52 + IDT_SET_VEC 88, ioapic_edge_53 + IDT_SET_VEC 89, ioapic_edge_54 + IDT_SET_VEC 90, ioapic_edge_55 + IDT_SET_VEC 91, ioapic_edge_56 + IDT_SET_VEC 92, ioapic_edge_57 + IDT_SET_VEC 93, ioapic_edge_58 + IDT_SET_VEC 94, ioapic_edge_59 + IDT_SET_VEC 95, ioapic_edge_60 + IDT_SET_VEC 96, ioapic_edge_61 + IDT_SET_VEC 97, ioapic_edge_62 IDT_SET_VEC 97, ioapic_edge_63 ret diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c index 9ab109a..5276eea 100644 --- a/sys/dev/usb/xhci.c +++ b/sys/dev/usb/xhci.c @@ -37,6 +37,7 @@ #include <dev/usb/xhciregs.h> #include <dev/usb/xhcivar.h> #include <dev/pci/pci.h> +#include <dev/pci/pciregs.h> #include <dev/acpi/acpi.h> #include <vm/physmem.h> #include <vm/dynalloc.h> @@ -496,6 +497,16 @@ xhci_init_hc(struct xhci_hc *hc) return 0; } +static void +xhci_init_pci(void) +{ + uint32_t tmp; + + tmp = pci_readl(hci_dev, PCIREG_CMDSTATUS); + tmp |= (PCI_BUS_MASTERING | PCI_MEM_SPACE); + pci_writel(hci_dev, PCIREG_CMDSTATUS, tmp); +} + static int xhci_init(void) { @@ -528,6 +539,7 @@ xhci_init(void) return -ENODEV; } + xhci_init_pci(); return xhci_init_hc(&xhc); } diff --git a/sys/dev/video/fbdev.c b/sys/dev/video/fbdev.c index f21c769..391400c 100644 --- a/sys/dev/video/fbdev.c +++ b/sys/dev/video/fbdev.c @@ -29,16 +29,35 @@ #include <sys/types.h> #include <sys/limine.h> +#include <sys/device.h> +#include <sys/driver.h> #include <dev/video/fbdev.h> +#include <fs/devfs.h> +#include <vm/vm.h> #define FRAMEBUFFER \ framebuffer_req.response->framebuffers[0] +static struct cdevsw fb_cdevsw; static volatile struct limine_framebuffer_request framebuffer_req = { .id = LIMINE_FRAMEBUFFER_REQUEST, .revision = 0 }; +static paddr_t +fbdev_mmap(dev_t dev, off_t off, int flags) +{ + size_t max_bounds; + + max_bounds = FRAMEBUFFER->pitch * FRAMEBUFFER->height; + max_bounds /= 4; + if (off > max_bounds) { + return 0; + } + + return VIRT_TO_PHYS(FRAMEBUFFER->address); +} + struct fbdev fbdev_get(void) { @@ -51,3 +70,26 @@ fbdev_get(void) ret.bpp = FRAMEBUFFER->bpp; return ret; } + +static int +fbdev_init(void) +{ + char devname[] = "fb0"; + devmajor_t major; + dev_t dev; + + /* Register the device here */ + major = dev_alloc_major(); + dev = dev_alloc(major); + dev_register(major, dev, &fb_cdevsw); + devfs_create_entry(devname, major, dev, 0444); + return 0; +} + +static struct cdevsw fb_cdevsw = { + .read = noread, + .write = nowrite, + .mmap = fbdev_mmap +}; + +DRIVER_EXPORT(fbdev_init); diff --git a/sys/fs/devfs.c b/sys/fs/devfs.c index a2ac7e8..0c087f0 100644 --- a/sys/fs/devfs.c +++ b/sys/fs/devfs.c @@ -127,6 +127,8 @@ devfs_lookup(struct vop_lookup_args *args) vp->data = dnp; vp->vops = &g_devfs_vops; + vp->major = dnp->major; + vp->dev = dnp->dev; *args->vpp = vp; return 0; } diff --git a/sys/include/arch/amd64/cdefs.h b/sys/include/arch/amd64/cdefs.h index bab0c89..0a20324 100644 --- a/sys/include/arch/amd64/cdefs.h +++ b/sys/include/arch/amd64/cdefs.h @@ -43,4 +43,13 @@ #define md_inton() __ASMV("sti") /* Enable interrupts */ #define md_hlt() __ASMV("hlt") /* Halt the processor */ +/* + * AMD64 specific defines + */ +#define __invlpg(VA) \ + __ASMV("invlpg %0" \ + : \ + : "m" ((VA)) \ + : "memory") + #endif /* !_AMD64_CDEFS_H_ */ diff --git a/sys/include/arch/amd64/cpu.h b/sys/include/arch/amd64/cpu.h index dd753b7..2d08d6e 100644 --- a/sys/include/arch/amd64/cpu.h +++ b/sys/include/arch/amd64/cpu.h @@ -33,6 +33,7 @@ #include <sys/types.h> #include <sys/cdefs.h> #include <sys/proc.h> +#include <sys/spinlock.h> #include <machine/tss.h> #define CPU_IRQ(IRQ_N) (BIT((IRQ_N)) & 0xFF) @@ -40,11 +41,14 @@ struct cpu_info { uint32_t apicid; uint8_t has_x2apic : 1; + uint8_t tlb_shootdown : 1; uint8_t ipl; size_t lapic_tmr_freq; uint8_t irq_mask; + vaddr_t shootdown_va; struct tss_entry *tss; struct proc *curtd; + struct spinlock lock; struct cpu_info *self; }; @@ -52,6 +56,10 @@ __dead void cpu_halt_all(void); void cpu_halt_others(void); void cpu_startup(struct cpu_info *ci); +struct cpu_info *cpu_get(uint32_t index); +uint32_t cpu_count(void); +void cpu_shootdown_tlb(vaddr_t va); + struct cpu_info *this_cpu(void); void mp_bootstrap_aps(struct cpu_info *ci); diff --git a/sys/include/dev/video/fbdev.h b/sys/include/dev/video/fbdev.h index c80fd92..c9fec94 100644 --- a/sys/include/dev/video/fbdev.h +++ b/sys/include/dev/video/fbdev.h @@ -52,5 +52,6 @@ fbdev_get_index(const struct fbdev *fbdev, uint32_t x, uint32_t y) } struct fbdev fbdev_get(void); +void fbdev_init_dev(void); #endif /* !_DEV_FBDEV_H_ */ diff --git a/sys/include/sys/device.h b/sys/include/sys/device.h index fcafdab..cb2a702 100644 --- a/sys/include/sys/device.h +++ b/sys/include/sys/device.h @@ -36,6 +36,7 @@ #include <sys/queue.h> #include <sys/proc.h> #include <sys/sio.h> +#include <vm/vm_obj.h> typedef uint8_t devmajor_t; @@ -47,6 +48,10 @@ typedef int(*dev_bsize_t)(dev_t); struct cdevsw { int(*read)(dev_t dev, struct sio_txn *sio, int flags); int(*write)(dev_t dev, struct sio_txn *sio, int flags); + paddr_t(*mmap)(dev_t dev, off_t off, int flags); + + /* Private */ + struct vm_object vmobj; }; struct bdevsw { diff --git a/sys/include/sys/limits.h b/sys/include/sys/limits.h index 6185719..198c963 100644 --- a/sys/include/sys/limits.h +++ b/sys/include/sys/limits.h @@ -33,5 +33,7 @@ #define PATH_MAX 1024 #define SSIZE_MAX 32767 #define CHAR_BIT 8 - +#if defined(_KERNEL) +#define CPU_MAX 256 +#endif /* _KERNEL */ #endif /* !_SYS_LIMITS_H_ */ diff --git a/sys/include/sys/spawn.h b/sys/include/sys/spawn.h index 3828d5c..9d823db 100644 --- a/sys/include/sys/spawn.h +++ b/sys/include/sys/spawn.h @@ -31,6 +31,9 @@ #define _SYS_SPAWN_H_ #include <sys/types.h> +#include <sys/param.h> + +#define SPAWN_WAIT BIT(0) #if !defined(_KERNEL) pid_t spawn(const char *pathname, int flags); diff --git a/sys/include/sys/vnode.h b/sys/include/sys/vnode.h index 33092f9..cd71817 100644 --- a/sys/include/sys/vnode.h +++ b/sys/include/sys/vnode.h @@ -32,6 +32,7 @@ #include <sys/types.h> #include <sys/queue.h> +#include <sys/vnode.h> #include <sys/atomic.h> #include <sys/sio.h> #include <vm/vm_obj.h> @@ -47,6 +48,8 @@ struct vnode { const struct vops *vops; struct vm_object vobj; uint32_t refcount; + dev_t major; + dev_t dev; TAILQ_ENTRY(vnode) vcache_link; }; diff --git a/sys/include/vm/pmap.h b/sys/include/vm/pmap.h index 9eed184..e1f3f89 100644 --- a/sys/include/vm/pmap.h +++ b/sys/include/vm/pmap.h @@ -76,6 +76,17 @@ int pmap_map(struct vas vas, vaddr_t va, paddr_t pa, vm_prot_t prot); int pmap_unmap(struct vas vas, vaddr_t va); /* + * Returns true if the page is clean (modified), otherwise + * returns false. + */ +bool pmap_is_clean(struct vas vas, vaddr_t va); + +/* + * Marks a page as clean (unmodified) + */ +void pmap_mark_clean(struct vas vas, vaddr_t va); + +/* * Mark a virtual address with a specific * caching type. */ diff --git a/sys/include/vm/vm_device.h b/sys/include/vm/vm_device.h new file mode 100644 index 0000000..da476e2 --- /dev/null +++ b/sys/include/vm/vm_device.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _VM_DEVICE_H_ +#define _VM_DEVICE_H_ + +#include <sys/types.h> +#include <sys/vnode.h> +#include <sys/device.h> +#include <vm/vm_pager.h> +#include <vm/vm_obj.h> + +extern const struct vm_pagerops vm_vnops; + +struct vm_object *dv_attach(devmajor_t major, dev_t dev, vm_prot_t prot); + +#endif /* !_VM_DEVICE_H_ */ diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index a421e52..b6cbc4e 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -111,6 +111,7 @@ int exit1(struct proc *td, int flags) { struct proc *curtd, *procp; + struct proc *parent; struct cpu_info *ci; pid_t target_pid, curpid; @@ -120,6 +121,7 @@ exit1(struct proc *td, int flags) curpid = curtd->pid; td->flags |= PROC_EXITING; + parent = td->parent; /* If we have any children, kill them too */ if (td->nleaves > 0) { @@ -149,6 +151,13 @@ exit1(struct proc *td, int flags) */ if (target_pid == curpid) { ci->curtd = NULL; + if (parent->pid == 0) + sched_enter(); + if (td->data == NULL) + sched_enter(); + + sched_enqueue_td(parent); + parent->flags &= ~PROC_SLEEP; sched_enter(); } @@ -163,6 +172,7 @@ sys_exit(struct syscall_args *scargs) { struct proc *td = this_td(); + td->data = scargs->tf; td->exit_status = scargs->arg0; exit1(td, 0); __builtin_unreachable(); diff --git a/sys/kern/kern_spawn.c b/sys/kern/kern_spawn.c index 3360443..4105668 100644 --- a/sys/kern/kern_spawn.c +++ b/sys/kern/kern_spawn.c @@ -111,6 +111,7 @@ spawn(struct proc *cur, void(*func)(void), void *p, int flags, struct proc **new struct proc *newproc; struct mmap_lgdr *mlgdr; int error; + pid_t pid; newproc = dynalloc(sizeof(*newproc)); if (newproc == NULL) { @@ -161,7 +162,25 @@ spawn(struct proc *cur, void(*func)(void), void *p, int flags, struct proc **new newproc->pid = ++nthreads; signals_init(newproc); sched_enqueue_td(newproc); - return newproc->pid; + pid = newproc->pid; + + if (ISSET(flags, SPAWN_WAIT)) { + newproc->flags |= PROC_WAITED; + cur->flags |= PROC_SLEEP; + + while (ISSET(cur->flags, PROC_SLEEP)) { + sched_yield(); + } + + if (!ISSET(newproc->flags, PROC_ZOMB)) { + pr_error("spawn: fatal: %d not zombie\n", newproc->pid); + panic("possibly memory corruption\n"); + } + + proc_reap(newproc); + } + + return pid; } /* diff --git a/sys/vm/vm_device.c b/sys/vm/vm_device.c new file mode 100644 index 0000000..e990b47 --- /dev/null +++ b/sys/vm/vm_device.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <sys/device.h> +#include <sys/syslog.h> +#include <vm/vm_device.h> + +#define pr_trace(fmt, ...) kprintf("vm_device: " fmt, ##__VA_ARGS__) +#define pr_error(...) pr_trace(__VA_ARGS__) + +const struct vm_pagerops dv_vnops; + +/* + * Attach a cdev to a vm_object + * + * @major: Char device major + * @minor: Char device minor. + */ +struct vm_object * +dv_attach(devmajor_t major, dev_t dev, vm_prot_t prot) +{ + int error; + struct cdevsw *cdevp; + struct vm_object *vmobj; + + if ((cdevp = dev_get(major, dev)) == NULL) { + pr_error("bad attach (major=%d, dev=%d)\n", major, dev); + return NULL; + } + + if (cdevp->mmap == NULL) { + pr_error("cdev lacks mmap() (major=%d, dev=%d)\n", major, dev); + return NULL; + } + + error = vm_obj_init(&cdevp->vmobj, &dv_vnops, 1); + if (error != 0) { + return NULL; + } + + vmobj = &cdevp->vmobj; + vmobj->prot = prot; + vmobj->data = cdevp; + vmobj->pgops = &dv_vnops; + return vmobj; +} + +/* TODO */ +const struct vm_pagerops dv_vnops = { + .get = NULL, +}; diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index b56e896..b8f4aee 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -35,8 +35,10 @@ #include <sys/syscall.h> #include <sys/syslog.h> #include <sys/mman.h> +#include <sys/filedesc.h> #include <vm/dynalloc.h> #include <vm/vm_pager.h> +#include <vm/vm_device.h> #include <vm/pmap.h> #include <vm/map.h> #include <vm/vm.h> @@ -159,9 +161,12 @@ vm_map_modify(struct vas vas, vaddr_t va, paddr_t pa, vm_prot_t prot, bool unmap void * mmap_at(void *addr, size_t len, int prot, int flags, int fildes, off_t off) { - struct vm_object *map_obj; + struct vm_object *map_obj = NULL; + struct cdevsw *cdevp; struct vm_page *pg; struct mmap_entry *ep; + struct vnode *vp; + struct filedesc *fdp; struct proc *td; struct vas vas; int error, npgs; @@ -172,6 +177,7 @@ mmap_at(void *addr, size_t len, int prot, int flags, int fildes, off_t off) misalign = len & (DEFAULT_PAGESIZE - 1); len = ALIGN_UP(len + misalign, DEFAULT_PAGESIZE); npgs = len / DEFAULT_PAGESIZE; + vas = pmap_read_vas(); if (addr == NULL) { pr_error("mmap: NULL addr not supported\n"); @@ -179,25 +185,68 @@ mmap_at(void *addr, size_t len, int prot, int flags, int fildes, off_t off) } /* Validate flags */ - if (ISSET(flags, MAP_FIXED | MAP_SHARED)) { - pr_error("mmap: fixed/shared mappings not yet supported\n"); + if (ISSET(flags, MAP_FIXED)) { + pr_error("mmap: fixed mappings not yet supported\n"); mmap_dbg(addr, len, prot, flags, fildes, off); return NULL; } - map_obj = dynalloc(sizeof(*map_obj)); - if (map_obj == NULL) { - kprintf("mmap: failed to allocate map object\n"); - return NULL; + + /* + * Attempt to open the file if mapping + * is shared. + */ + if (ISSET(flags, MAP_SHARED)) { + fdp = fd_get(fildes); + if (fdp == NULL) { + pr_error("mmap: no such fd (fd=%d)\n", fildes); + return NULL; + } + + vp = fdp->vp; + if (vp->type != VCHR) { + /* TODO */ + pr_error("mmap: only device files supported\n"); + return NULL; + } + + map_obj = dv_attach(vp->major, vp->dev, prot); + if (map_obj == NULL) { + kprintf("mmap: dv_attach() failure\n"); + return NULL; + } + + cdevp = map_obj->data; + if ((pa = cdevp->mmap(vp->dev, off, 0)) == 0) { + kprintf("mmap: dev mmap() gave 0\n"); + return NULL; + } + + va = ALIGN_DOWN((vaddr_t)addr, DEFAULT_PAGESIZE); + error = vm_map(vas, va, pa, prot, len); + if (error != 0) { + kprintf("mmap: map failed (error=%d)\n", error); + return NULL; + } + + goto done; } - error = vm_obj_init(map_obj, &vm_anonops, 1); - if (error < 0) { - kprintf("mmap: vm_obj_init() returned %d\n", error); - kprintf("mmap: failed to init object\n"); - return NULL; + + /* Only allocate new obj if needed */ + if (map_obj == NULL) { + map_obj = dynalloc(sizeof(*map_obj)); + if (map_obj == NULL) { + kprintf("mmap: failed to allocate map object\n"); + return NULL; + } + error = vm_obj_init(map_obj, &vm_anonops, 1); + if (error < 0) { + kprintf("mmap: vm_obj_init() returned %d\n", error); + kprintf("mmap: failed to init object\n"); + return NULL; + } } /* XXX: Assuming private */ - vas = pmap_read_vas(); va = ALIGN_DOWN((vaddr_t)addr, DEFAULT_PAGESIZE); for (int i = 0; i < npgs; ++i) { @@ -211,13 +260,13 @@ mmap_at(void *addr, size_t len, int prot, int flags, int fildes, off_t off) pa = pg->phys_addr; error = vm_map(vas, va, pa, prot, len); - pr_trace("va=%p, len=%d\n", va, len); if (error < 0) { pr_error("mmap: failed to map page (retval=%x)\n", error); return NULL; } } +done: /* Add entry to ledger */ td = this_td(); ep = dynalloc(sizeof(*ep)); diff --git a/sys/vm/vm_vnode.c b/sys/vm/vm_vnode.c index 2457c97..27defc9 100644 --- a/sys/vm/vm_vnode.c +++ b/sys/vm/vm_vnode.c @@ -162,7 +162,6 @@ vn_attach(struct vnode *vp, vm_prot_t prot) if (vp->type != VREG) { pr_error("vn_attach: vp=%p, prot=%x\n", vp, prot); - pr_error("vn_attach: Special files not supported yet!\n"); return NULL; } diff --git a/usr.bin/Makefile b/usr.bin/Makefile index 1c973ff..09d593d 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -6,3 +6,4 @@ ARGS = -I$(ROOT)/builddeps LDSCRIPT=$(LDSCRIPT) USRDIR=$(USRDIR) ROOT=$(ROOT) .PHONY: all all: make -C osh/ $(ARGS) + make -C kmsg/ $(ARGS) diff --git a/usr.bin/fetch/Makefile b/usr.bin/fetch/Makefile new file mode 100644 index 0000000..4b08e84 --- /dev/null +++ b/usr.bin/fetch/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/fetch: + gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/fetch/fetch.c b/usr.bin/fetch/fetch.c new file mode 100644 index 0000000..98b2d3c --- /dev/null +++ b/usr.bin/fetch/fetch.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> +#include <fcntl.h> +#include <string.h> + +#define prcons(FD, STR) write((FD), (STR), strlen((STR))) + +#define ASCII_ART \ + " ____ \n" \ + " | \\__\\ \n" \ + " | /\\ \\ user: root\n" \ + " |/ \\ \\ OS: Hyra/amd64 v"_OSVER"\n" \ + " \\ R. \\ \\ arch: "_OSARCH"\n" \ + " \\ I. \\ \\\n" + + +int +main(void) +{ + int fd; + + fd = open("/dev/console", O_WRONLY); + if (fd < 0) { + return fd; + } + + prcons(fd, ASCII_ART); + close(fd); + return 0; +} diff --git a/usr.bin/kmsg/Makefile b/usr.bin/kmsg/Makefile new file mode 100644 index 0000000..9b76cc2 --- /dev/null +++ b/usr.bin/kmsg/Makefile @@ -0,0 +1,6 @@ +include user.mk + +CFILES = $(shell find . -name "*.c") + +$(ROOT)/base/usr/bin/kmsg: + gcc $(CFILES) -o $@ $(INTERNAL_CFLAGS) diff --git a/usr.bin/kmsg/kmsg.c b/usr.bin/kmsg/kmsg.c new file mode 100644 index 0000000..678ad8c --- /dev/null +++ b/usr.bin/kmsg/kmsg.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023-2025 Ian Marco Moffett and the Osmora Team. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Hyra nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> + +int +main(void) +{ + int mfd, cons_fd; + ssize_t retval; + char linebuf[256]; + + if ((mfd = open("/dev/kmsg", O_RDONLY)) < 0) { + return mfd; + } + if ((cons_fd = open("/dev/console", O_WRONLY)) < 0) { + close(mfd); + return cons_fd; + } + + for (;;) { + retval = read(mfd, linebuf, sizeof(linebuf) - 1); + if (retval <= 0) { + break; + } + linebuf[retval] = '\0'; + write(cons_fd, linebuf, strlen(linebuf)); + } + + close(cons_fd); + close(mfd); + return 0; +} diff --git a/usr.bin/osh/osh.c b/usr.bin/osh/osh.c index 9b4e9ab..583f29a 100644 --- a/usr.bin/osh/osh.c +++ b/usr.bin/osh/osh.c @@ -30,6 +30,7 @@ #include <sys/types.h> #include <sys/cdefs.h> #include <sys/reboot.h> +#include <sys/spawn.h> #include <fcntl.h> #include <stddef.h> #include <unistd.h> @@ -50,6 +51,7 @@ "reboot - Reboot the machine\n" \ "shutdown - Power off the machine\n" \ "kmsg - Print kernel message buffer\n" \ + "fetch - System information\n" \ "exit - Exit the shell\n" #define PROMPT "[root::osmora]~ " @@ -60,6 +62,7 @@ static int running; struct command { const char *name; + const char *path; void (*func)(int fd, int argc, char *argv[]); }; @@ -88,29 +91,6 @@ cmd_shutdown(int fd, int argc, char *argv[]) } void -cmd_kmsg(int fd, int argc, char *argv[]) -{ - int mfd; - ssize_t retval; - char linebuf[256]; - - if ((mfd = open("/dev/kmsg", O_RDONLY)) < 0) { - return; - } - - for (;;) { - retval = read(mfd, linebuf, sizeof(linebuf) - 1); - if (retval <= 0) { - break; - } - linebuf[retval] = '\0'; - prcons(fd, linebuf); - } - - close(mfd); -} - -void cmd_echo(int fd, int argc, char *argv[]) { for (i = 1; i < argc; i++) { @@ -189,13 +169,27 @@ getstr(int fd) } } +static void +command_run(struct command *cmd, int fd, int argc, char *argv[]) +{ + if (cmd->func != NULL) { + cmd->func(fd, argc, argv); + return; + } + + if (cmd->path != NULL) { + spawn(cmd->path, SPAWN_WAIT); + } +} + struct command cmds[] = { - {"help", cmd_help}, - {"echo", cmd_echo}, - {"exit", cmd_exit}, - {"reboot", cmd_reboot}, - {"shutdown", cmd_shutdown}, - {"kmsg", cmd_kmsg}, + {"help", NULL, cmd_help}, + {"echo", NULL, cmd_echo}, + {"exit", NULL, cmd_exit}, + {"reboot", NULL, cmd_reboot}, + {"shutdown", NULL, cmd_shutdown}, + {"kmsg", "/usr/bin/kmsg", NULL}, + {"fetch", "/usr/bin/fetch", NULL}, {NULL, NULL} }; @@ -230,7 +224,7 @@ main(void) for (i = 0; cmds[i].name != NULL; i++) { if (strcmp(input, cmds[i].name) == 0) { - cmds[i].func(fd, argc, argv); + command_run(&cmds[i], fd, argc, argv); found = 1; break; } |