summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.in4
-rw-r--r--builddeps/user.mk3
-rw-r--r--configure.ac2
-rw-r--r--lib/libc/include/stdatomic.h119
-rw-r--r--sys/arch/aarch64/aarch64/pmap.c21
-rw-r--r--sys/arch/amd64/amd64/intr.c7
-rw-r--r--sys/arch/amd64/amd64/machdep.c52
-rw-r--r--sys/arch/amd64/amd64/mp.c28
-rw-r--r--sys/arch/amd64/amd64/pmap.c36
-rw-r--r--sys/arch/amd64/amd64/vector.S126
-rw-r--r--sys/dev/usb/xhci.c12
-rw-r--r--sys/dev/video/fbdev.c42
-rw-r--r--sys/fs/devfs.c2
-rw-r--r--sys/include/arch/amd64/cdefs.h9
-rw-r--r--sys/include/arch/amd64/cpu.h8
-rw-r--r--sys/include/dev/video/fbdev.h1
-rw-r--r--sys/include/sys/device.h5
-rw-r--r--sys/include/sys/limits.h4
-rw-r--r--sys/include/sys/spawn.h3
-rw-r--r--sys/include/sys/vnode.h3
-rw-r--r--sys/include/vm/pmap.h11
-rw-r--r--sys/include/vm/vm_device.h43
-rw-r--r--sys/kern/kern_exit.c10
-rw-r--r--sys/kern/kern_spawn.c21
-rw-r--r--sys/vm/vm_device.c78
-rw-r--r--sys/vm/vm_map.c77
-rw-r--r--sys/vm/vm_vnode.c1
-rw-r--r--usr.bin/Makefile1
-rw-r--r--usr.bin/fetch/Makefile6
-rw-r--r--usr.bin/fetch/fetch.c58
-rw-r--r--usr.bin/kmsg/Makefile6
-rw-r--r--usr.bin/kmsg/kmsg.c62
-rw-r--r--usr.bin/osh/osh.c54
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;
}