This commit is contained in:
2026-09-16 04:37:37 +02:00
parent e71245c082
commit 3e9bdf72c9
74 changed files with 555 additions and 567 deletions
+1
View File
@@ -1,3 +1,4 @@
.config*
build/
.cache/
.wraplock
+7
View File
@@ -0,0 +1,7 @@
mainmenu "Zinnia Kernel Configuration"
source "device/Kconfig"
config KERNEL_FLAVOR
string "Kernel flavor name"
default "vanilla"
+2 -1
View File
@@ -3,12 +3,13 @@
# Zinnia
![GitHub License](https://img.shields.io/github/license/zinnia-os/zinnia?style=flat&color=green)
![GitHub top language](https://img.shields.io/github/languages/top/zinnia-os/zinnia)
![GitHub Repo stars](https://img.shields.io/github/stars/zinnia-os/zinnia?style=flat)
![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/zinnia-os/zinnia/ci.yml)
![GitHub Issues or Pull Requests](https://img.shields.io/github/issues/zinnia-os/zinnia?style=flat)
![Discord](https://img.shields.io/discord/1305893510704267327?logo=discord&logoColor=white&label=discord)
Zinnia is a lightweight BSD-like monolithic kernel targeting 64-bit devices.
Zinnia is a lightweight Unix-like monolithic kernel targeting 64-bit devices.
## Building Zinnia
+1 -1
View File
@@ -58,7 +58,7 @@ void hpet_init() {
struct acpi_hpet* hpet = table.ptr;
hpet_clock.regs = mmio_new(hpet->address.address, 0x1000);
uacpi_table_unref(&table);
printf("HPET regs at %p\n", hpet_clock.regs.base);
kprintf("HPET regs at %p\n", hpet_clock.regs.base);
mmio_store(&hpet_clock.regs, HPET_CFG, mmio_load(&hpet_clock.regs, HPET_CFG) | 1);
+1
View File
@@ -2,6 +2,7 @@ kernel_c_args += [
'-mgeneral-regs-only',
'-mno-red-zone',
'-mcmodel=kernel',
'-masm=intel',
]
kernel_sources += files(
+2
View File
@@ -5,6 +5,8 @@
#include <stddef.h>
#include <x86_64/defs.h>
// TODO: Refactor to only push callee-saved registers.
[[__naked]]
void arch_syscall_stub() {
asm volatile(
+5 -5
View File
@@ -11,7 +11,7 @@ void tsc_init() {
return;
if (!(asm_cpuid(1, 0).edx & CPUID_1D_TSC) || !(asm_cpuid(0x8000'0007, 0).edx & (1 << 8))) {
printf("No invariant TSC detected!\n");
kprintf("No invariant TSC detected!\n");
return;
}
@@ -34,18 +34,18 @@ void tsc_init() {
// On a normal system, this should usually never be called and is a last resort
// since at this point we have at least the HPET timer.
if (tsc_leaf.ecx != 0 && tsc_leaf.ebx != 0 && tsc_leaf.eax != 0) {
printf("Calibrating TSC using CPUID 0x15");
kprintf("Calibrating TSC using CPUID 0x15");
freq = tsc_leaf.ecx * tsc_leaf.ebx / tsc_leaf.eax;
} else {
printf("Unable to calibrate TSC using CPUID frequency information");
kprintf("Unable to calibrate TSC using CPUID frequency information");
return;
}
} else {
printf("Unable to calibrate the TSC without a clock or static frequency info!\n");
kprintf("Unable to calibrate the TSC without a clock or static frequency info!\n");
return;
}
printf("Timer frequency is %lu MHz\n", freq / 1'000'000);
kprintf("Timer frequency is %lu MHz\n", freq / 1'000'000);
}
static void tsc_option(bool opt) {
+9 -9
View File
@@ -17,7 +17,7 @@ bool arch_usercopy_read(void* dst, const __user void* src, size_t len, struct us
// Setup regs for `rep movsb`.
"xchg rcx, rdx\n"
"mov rax, [rip + %0]\n"
"mov [rdx], rax\n"
"xchg [rdx], rax\n"
".global x86_64_read_start\n"
"x86_64_read_start:\n"
@@ -26,7 +26,7 @@ bool arch_usercopy_read(void* dst, const __user void* src, size_t len, struct us
".global x86_64_read_end\n"
"x86_64_read_end:\n"
"xor rax, rax\n"
"mov [rdx], rax\n"
"xchg [rdx], rax\n"
"mov rax, 1\n"
"clac\n"
"ret\n"
@@ -34,7 +34,7 @@ bool arch_usercopy_read(void* dst, const __user void* src, size_t len, struct us
".global x86_64_read_fault\n"
"x86_64_read_fault:\n"
"xor rax, rax\n"
"mov [rdx], rax\n"
"xchg [rdx], rax\n"
"clac\n"
"ret\n"
:
@@ -69,7 +69,7 @@ bool arch_usercopy_write(__user void* dst, const void* src, size_t len, struct u
".global x86_64_write_end\n"
"x86_64_write_end:\n"
"xor rax, rax\n"
"mov [rdx], rax\n"
"xchg [rdx], rax\n"
"mov rax, 1\n"
"clac\n"
"ret\n"
@@ -77,11 +77,11 @@ bool arch_usercopy_write(__user void* dst, const void* src, size_t len, struct u
".global x86_64_write_fault\n"
"x86_64_write_fault:\n"
"xor rax, rax\n"
"mov [rdx], rax\n"
"xchg [rdx], rax\n"
"clac\n"
"ret\n"
:
: "i"(&read_region)
: "i"(&write_region)
: "memory"
);
return false;
@@ -102,7 +102,7 @@ bool arch_usercopy_strlen(const __user char* str, size_t max, size_t* len, struc
asm volatile(
"stac\n"
"mov rax, [rip + %0]\n"
"mov [rcx], rax\n"
"xchg [rcx], rax\n"
".global x86_64_strlen_start\n"
"x86_64_strlen_start:\n"
@@ -119,7 +119,7 @@ bool arch_usercopy_strlen(const __user char* str, size_t max, size_t* len, struc
".global x86_64_strlen_end\n"
"x86_64_strlen_end:\n"
"xor rax, rax\n"
"mov [rcx], rax\n"
"xchg [rcx], rax\n"
"mov rax, 1\n"
"clac\n"
"ret\n"
@@ -127,7 +127,7 @@ bool arch_usercopy_strlen(const __user char* str, size_t max, size_t* len, struc
".global x86_64_strlen_fault\n"
"x86_64_strlen_fault:\n"
"xor rax, rax\n"
"mov [rcx], rax\n"
"xchg [rcx], rax\n"
"clac\n"
"ret\n"
:
+2 -2
View File
@@ -17,11 +17,11 @@
#include <stdint.h>
static const char zinnia_banner[] =
"Zinnia " ZINNIA_VERSION " (" ZINNIA_ARCH ", " ZINNIA_COMPILER_ID ", " ZINNIA_LINKER_ID ")";
"Zinnia " ZINNIA_VERSION " " CONFIG_VARIANT " (" ZINNIA_ARCH ", " ZINNIA_COMPILER_ID ", " ZINNIA_LINKER_ID ")";
static void kernel_main_task(uintptr_t arg0) {
struct boot_info* info = (struct boot_info*)arg0;
printf("%s\n", zinnia_banner); // Say hello!
kprintf("%s\n", zinnia_banner); // Say hello!
assert(info->num_files >= 1, "No init executable provided\n");
+3 -3
View File
@@ -7,7 +7,7 @@
static struct clock* active_clock = nullptr;
static uint64_t counter_base = 0;
static struct spinlock lock = {};
static spinlock_t lock = {};
bool clock_available() {
return active_clock != nullptr;
@@ -31,7 +31,7 @@ bool clock_switch(struct clock* clock) {
}
}
printf("Switching to clock source \"%s\"\n", clock->name);
kprintf("Switching to clock source \"%s\"\n", clock->name);
uint64_t elapsed = clock_get_elapsed_ns();
counter_base += elapsed;
@@ -43,7 +43,7 @@ bool clock_switch(struct clock* clock) {
void clock_spin_ns(uint64_t ns) {
if (active_clock == nullptr) {
printf("Unable to sleep for %lu ns, no clock available!\n", ns);
kprintf("Unable to sleep for %lu ns, no clock available!\n", ns);
return;
}
+1 -1
View File
@@ -38,6 +38,6 @@ void console_init() {
if (active->init(active) == false)
active = nullptr;
else
printf("Logging on console \"%s\"\n", active->name);
kprintf("Logging on console \"%s\"\n", active->name);
}
}
+3 -3
View File
@@ -1,6 +1,6 @@
#include <zinnia/alloc.h>
#include <zinnia/elf.h>
#include <zinnia/errno.h>
#include <zinnia/mem/alloc.h>
#include <zinnia/percpu.h>
#include <zinnia/pmap.h>
#include <zinnia/print.h>
@@ -42,7 +42,7 @@ errno_t elf_load(struct exec_info* info, struct task** out) {
if (phdr.p_type == PT_LOAD) {
enum zn_vm_flags prot = 0;
if (phdr.p_flags & PF_R)
prot |= ZN_VM_MAP_READ;
prot |= PROT_READ;
if (phdr.p_flags & PF_W)
prot |= ZN_VM_MAP_WRITE;
if (phdr.p_flags & PF_X)
@@ -181,7 +181,7 @@ errno_t elf_load(struct exec_info* info, struct task** out) {
uintptr_t argc = num_argv;
vmo_write(&stack->object, stack_off, &argc, sizeof(argc), nullptr);
status = vma_map_vmo(info->space, &stack->object, stack_start, stack_size, ZN_VM_MAP_READ | ZN_VM_MAP_WRITE, 0);
status = vma_map_vmo(info->space, &stack->object, stack_start, stack_size, PROT_READ | ZN_VM_MAP_WRITE, 0);
if (status)
return status;
+2 -2
View File
@@ -15,10 +15,10 @@ struct futex_bucket {
#define FUTEX_BUCKET_COUNT 64
static struct futex_bucket futex_table[FUTEX_BUCKET_COUNT];
static struct spinlock futex_table_lock;
static spinlock_t futex_table_lock;
void futex_init(void) {
futex_table_lock = (struct spinlock){0};
futex_table_lock = (spinlock_t){0};
for (size_t i = 0; i < FUTEX_BUCKET_COUNT; i++) {
wait_queue_init(&futex_table[i].wq);
futex_table[i].key = 0;
+1 -4
View File
@@ -8,9 +8,6 @@ kernel_sources += files(
'percpu.c',
'print.c',
'spin.c',
'uacpi_glue.c',
)
if get_option('sched') == 'simple'
kernel_sources += files('sched_simple.c')
endif
kernel_sources += files('sched_dumb.c')
+2 -2
View File
@@ -11,7 +11,7 @@ void panic(const char* msg, ...) {
struct percpu* cpu = percpu_get();
struct task* current = cpu->sched.current;
printf(
kprintf(
"----[ Kernel panic ]----\n"
"In task \"%s\" (TID %zu) on CPU %zu!\n",
current ? current->name : nullptr,
@@ -24,7 +24,7 @@ void panic(const char* msg, ...) {
kvprintf(msg, args);
va_end(args);
printf("----[ End of panic ]----\n");
kprintf("----[ End of panic ]----\n");
while (1) {
arch_irq_wait();
+1 -1
View File
@@ -387,7 +387,7 @@ static void printf_console(void*, const char* msg, size_t len) {
console_write(msg, len);
}
void printf(const char* message, ...) {
void kprintf(const char* message, ...) {
va_list args;
va_start(args, message);
do_print(printf_console, nullptr, message, args);
+2 -2
View File
@@ -43,7 +43,7 @@ void sched_init(struct sched_percpu* sched) {
tailq_init(&sched->run_queue);
printf("Scheduler initialized\n");
kprintf("Scheduler initialized\n");
}
void sched_add_task(struct sched_percpu* sched, struct task* task) {
@@ -143,7 +143,7 @@ void task_entry(task_fn_t entry, uintptr_t arg0) {
void wait_queue_init(struct wait_queue* wq) {
tailq_init(&wq->waiters);
wq->lock = (struct spinlock){0};
wq->lock = (spinlock_t){0};
}
void sched_block(struct sched_percpu* sched, struct wait_queue* wq) {
+2 -2
View File
@@ -1,7 +1,7 @@
#include <zinnia/spin.h>
#include <stdatomic.h>
void spin_lock(struct spinlock* spin) {
void spin_lock(spinlock_t* spin) {
uint32_t my = atomic_fetch_add_explicit(&spin->next, 1, memory_order_relaxed);
while (atomic_load_explicit(&spin->owner, memory_order_acquire) != my) {
@@ -9,7 +9,7 @@ void spin_lock(struct spinlock* spin) {
}
}
void spin_unlock(struct spinlock* spin) {
void spin_unlock(spinlock_t* spin) {
uint32_t val = atomic_load_explicit(&spin->owner, memory_order_relaxed);
atomic_store_explicit(&spin->owner, val + 1, memory_order_release);
}
+15
View File
@@ -0,0 +1,15 @@
menu "Device Drivers"
config OF
bool "Support for OpenFirmware"
default y
help
Adds support for flattened device trees and OF platform drivers.
config ACPI
bool "Support for ACPI firmware"
default y
help
Adds support for ACPI firmware, tables and devices.
endmenu
+9 -4
View File
@@ -1,10 +1,15 @@
# uACPI
uacpi = subproject('uacpi')
uacpi_sources = uacpi.get_variable('sources')
uacpi_includes = uacpi.get_variable('includes')
kernel_sources += uacpi.get_variable('sources')
kernel_includes += uacpi.get_variable('includes')
kernel_c_args += [
'-DUACPI_FORMATTED_LOGGING',
'-DUACPI_BAREBONES_MODE',
'-DUACPI_BAREBONES_MODE', # TODO
'-DUACPI_OVERRIDE_TYPES',
]
# For uacpi_types.h
kernel_includes += include_directories('include')
kernel_sources += files(
'uacpi_glue.c',
)
@@ -1,11 +1,11 @@
#include <stdarg.h>
#include <uacpi/kernel_api.h>
#include <uacpi/status.h>
#include <uacpi/types.h>
#include <zinnia/init.h>
#include <zinnia/mmio.h>
#include <zinnia/print.h>
#include <zinnia/utils.h>
#include <stdarg.h>
#include <uacpi/kernel_api.h>
#include <uacpi/status.h>
#include <uacpi/types.h>
uacpi_status uacpi_kernel_get_rsdp(uacpi_phys_addr* out_rsdp_address) {
*out_rsdp_address = (uacpi_phys_addr)rsdp_addr;
@@ -13,11 +13,11 @@ uacpi_status uacpi_kernel_get_rsdp(uacpi_phys_addr* out_rsdp_address) {
}
void* uacpi_kernel_map(uacpi_phys_addr addr, uacpi_size len) {
return mmio_new(addr, len);
return (void*)mmio_new(addr, len).base;
}
void uacpi_kernel_unmap(void* addr, uacpi_size len) {
mmio_free(addr, len);
// TODO
}
void uacpi_kernel_log(uacpi_log_level lvl, const uacpi_char* msg, ...) {
View File
+3
View File
@@ -0,0 +1,3 @@
kernel_sources += files(
'memfiles.c',
)
View File
+7 -1
View File
@@ -1,3 +1,9 @@
if get_option('acpi')
subdir('common')
if cfg.get('CONFIG_ACPI', 0) == 1
subdir('acpi')
endif
if cfg.get('CONFIG_DT', 0) == 1
subdir('dt')
endif
+1 -1
View File
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ZINNIA_UAPI_ARCHCTL_H
#define __ZINNIA_UAPI_ARCHCTL_H
+3 -3
View File
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ZINNIA_UAPI_EPOLL_H
#define __ZINNIA_UAPI_EPOLL_H
@@ -24,7 +24,7 @@
#define __EPOLL_CTL_DEL 2
#define __EPOLL_CTL_MOD 3
union epoll_data {
union __epoll_data {
void* ptr;
int fd;
uint32_t u32;
@@ -33,7 +33,7 @@ union epoll_data {
struct epoll_event {
uint32_t events;
union epoll_data data;
union __epoll_data data;
};
#endif
+1 -1
View File
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ZINNIA_UAPI_ERRNO_H
#define __ZINNIA_UAPI_ERRNO_H
+1 -1
View File
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ZINNIA_UAPI_FCNTL_H
#define __ZINNIA_UAPI_FCNTL_H
+7 -8
View File
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ZINNIA_UAPI_MMAN_H
#define __ZINNIA_UAPI_MMAN_H
@@ -7,13 +7,12 @@
#define __PROT_WRITE 0x02
#define __PROT_EXEC 0x04
#define __MAP_FAILED ((void*)-1)
#define __MAP_FILE 0x00
#define __MAP_SHARED 0x01
#define __MAP_PRIVATE 0x02
#define __MAP_FIXED 0x10
#define __MAP_ANON 0x20
#define __MAP_ANONYMOUS 0x20
#define __MAP_FAILED ((void*)-1)
#define __MAP_FILE 0x00
#define __MAP_SHARED 0x01
#define __MAP_PRIVATE 0x02
#define __MAP_FIXED 0x10
#define __MAP_ANON 0x20
#define __MS_ASYNC 0x1
#define __MS_INVALIDATE 0x2
+1 -1
View File
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ZINNIA_UAPI_MOUNT_H
#define __ZINNIA_UAPI_MOUNT_H
+3 -3
View File
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ZINNIA_UAPI_POLL_H
#define __ZINNIA_UAPI_POLL_H
@@ -16,9 +16,9 @@
#define __POLLWRNORM 0x200
#define __POLLWRBAND 0x400
typedef intptr_t nfds_t;
typedef intptr_t __nfds_t;
struct pollfd {
struct __pollfd {
int fd;
int16_t events;
int16_t revents;
+2 -2
View File
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ZINNIA_UAPI_STAT_H
#define __ZINNIA_UAPI_STAT_H
@@ -32,7 +32,7 @@
#define __S_IWRITE __S_IWUSR
#define __S_IEXEC __S_IXUSR
struct stat {
struct __stat {
dev_t st_dev;
ino_t st_ino;
mode_t st_mode;
-151
View File
@@ -1,151 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
#ifndef __ZINNIA_UAPI_SYSCALL_NUMBERS_H
#define __ZINNIA_UAPI_SYSCALL_NUMBERS_H
#define __SYS_exit 0
#define __SYS_syslog 1
#define __SYS_getuname 2
#define __SYS_setuname 3
#define __SYS_archctl 4
#define __SYS_reboot 5
#define __SYS_mmap 6
#define __SYS_munmap 7
#define __SYS_mprotect 8
#define __SYS_madvise 9
#define __SYS_sigprocmask 10
#define __SYS_sigsuspend 11
#define __SYS_sigpending 12
#define __SYS_sigaction 13
#define __SYS_sigtimedwait 14
#define __SYS_sigaltstack 15
#define __SYS_sigreturn 16
#define __SYS_sigqueue 17
#define __SYS_execve 18
#define __SYS_fexecve 19
#define __SYS_fork 20
#define __SYS_kill 21
#define __SYS_gettid 22
#define __SYS_getpid 23
#define __SYS_getppid 24
#define __SYS_waitid 25
#define __SYS_waitpid 26
#define __SYS_pread 27
#define __SYS_readv 28
#define __SYS_pwrite 29
#define __SYS_writev 30
#define __SYS_seek 31
#define __SYS_ioctl 32
#define __SYS_openat 33
#define __SYS_close 34
#define __SYS_fstat 35
#define __SYS_fstatat 36
#define __SYS_statvfs 37
#define __SYS_fstatvfs 38
#define __SYS_faccessat 39
#define __SYS_fcntl 40
#define __SYS_ftruncate 41
#define __SYS_truncate 42
#define __SYS_fallocate 43
#define __SYS_fadvise 44
#define __SYS_utimensat 45
#define __SYS_mknodat 46
#define __SYS_getcwd 47
#define __SYS_chdir 48
#define __SYS_fchdir 49
#define __SYS_mkdirat 50
#define __SYS_rmdirat 51
#define __SYS_getdents 52
#define __SYS_renameat 53
#define __SYS_fchmod 54
#define __SYS_fchmodat 55
#define __SYS_fchownat 56
#define __SYS_linkat 57
#define __SYS_symlinkat 58
#define __SYS_unlinkat 59
#define __SYS_readlinkat 60
#define __SYS_flock 61
#define __SYS_ppoll 62
#define __SYS_dup 63
#define __SYS_dup3 64
#define __SYS_sync 65
#define __SYS_fsync 66
#define __SYS_fdatasync 67
#define __SYS_getgroups 68
#define __SYS_setgroups 69
#define __SYS_getsid 70
#define __SYS_setsid 71
#define __SYS_setuid 72
#define __SYS_getuid 73
#define __SYS_setgid 74
#define __SYS_getgid 75
#define __SYS_geteuid 76
#define __SYS_seteuid 77
#define __SYS_getegid 78
#define __SYS_setegid 79
#define __SYS_getpgid 80
#define __SYS_setpgid 81
#define __SYS_getresuid 82
#define __SYS_setresuid 83
#define __SYS_getresgid 84
#define __SYS_setresgid 85
#define __SYS_setreuid 86
#define __SYS_setregid 87
#define __SYS_umask 88
#define __SYS_pipe 89
#define __SYS_futex_wait 90
#define __SYS_futex_wake 91
#define __SYS_thread_create 92
#define __SYS_thread_kill 93
#define __SYS_thread_exit 94
#define __SYS_thread_setname 95
#define __SYS_thread_getname 96
#define __SYS_timer_create 97
#define __SYS_timer_set 98
#define __SYS_timer_get 99
#define __SYS_timer_getoverrun 100
#define __SYS_timer_delete 101
#define __SYS_itimer_get 102
#define __SYS_itimer_set 103
#define __SYS_clock_get 104
#define __SYS_clock_getres 105
#define __SYS_clock_set 106
#define __SYS_sleep 107
#define __SYS_yield 108
#define __SYS_chroot 109
#define __SYS_mount 110
#define __SYS_umount 111
#define __SYS_socket 112
#define __SYS_socketpair 113
#define __SYS_shutdown 114
#define __SYS_bind 115
#define __SYS_connect 116
#define __SYS_accept 117
#define __SYS_listen 118
#define __SYS_getpeername 119
#define __SYS_getsockname 120
#define __SYS_getsockopt 121
#define __SYS_setsockopt 122
#define __SYS_sendmsg 123
#define __SYS_recvmsg 124
#define __SYS_getentropy 125
#define __SYS_getrusage 126
#define __SYS_getrlimit 127
#define __SYS_setrlimit 128
#define __SYS_getpriority 129
#define __SYS_setpriority 130
#define __SYS_sched_getparam 131
#define __SYS_sched_setparam 132
#define __SYS_module_insert 133
#define __SYS_module_remove 134
#define __SYS_epoll_create 135
#define __SYS_epoll_ctl 136
#define __SYS_epoll_pwait 137
#define __SYS_timerfd_create 138
#define __SYS_timerfd_gettime 139
#define __SYS_timerfd_settime 140
#define __SYS_signalfd_create 141
#define __SYS_eventfd_create 142
#define __SYS_msync 143
#define __SYS_sysconf 144
#endif
+1 -1
View File
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ZINNIA_UAPI_TIME_H
#define __ZINNIA_UAPI_TIME_H
+1 -1
View File
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ZINNIA_UAPI_TYPES_H
#define __ZINNIA_UAPI_TYPES_H
+1 -1
View File
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ZINNIA_UAPI_UIO_H
#define __ZINNIA_UAPI_UIO_H
+1 -1
View File
@@ -1,4 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ZINNIA_UAPI_UTSNAME_H
#define __ZINNIA_UAPI_UTSNAME_H
-3
View File
@@ -1,3 +0,0 @@
#pragma once
#include <uapi/archctl.h>
+7
View File
@@ -0,0 +1,7 @@
#pragma once
#include <zinnia/errno.h>
#include <stdint.h>
#include <uapi/archctl.h>
errno_t arch_archctl(uintptr_t op, uintptr_t value);
+1
View File
@@ -1,5 +1,6 @@
#pragma once
#include <bits/elf.h>
#include <stdint.h>
constexpr char ELF_MAG[4] = {0x7F, 'E', 'L', 'F'};
+4 -4
View File
@@ -1,9 +1,9 @@
#pragma once
#include <bits/irq.h>
#include <stdint.h>
#include <zinnia/compiler.h>
#include <zinnia/list.h>
#include <bits/irq.h>
#include <stdint.h>
enum irq_status : uint8_t {
IRQ_STATUS_HANDLED,
@@ -35,13 +35,13 @@ struct irq_line {
bool is_busy;
};
void irq_line_attach(struct irq_line* self, struct irq_handler* handler);
struct irq_percpu {
uint32_t level;
bool in_interrupt;
};
void irq_line_attach(struct irq_line* self, struct irq_handler* handler);
void irq_lock();
void irq_unlock();
bool irq_set_interrupted(bool is_interrupted);
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include <stdint.h>
#include <uapi/mman.h>
enum prot_flags : uint8_t {
PROT_NONE = __PROT_NONE,
PROT_READ = __PROT_READ,
PROT_WRITE = __PROT_WRITE,
PROT_EXEC = __PROT_EXEC,
};
enum map_flags : uint8_t {
MAP_FILE = __MAP_FILE,
MAP_SHARED = __MAP_SHARED,
MAP_PRIVATE = __MAP_PRIVATE,
MAP_FIXED = __MAP_FIXED,
MAP_ANON = __MAP_ANON,
};
enum ms_flags : uint8_t {
MS_ASYNC = __MS_ASYNC,
MS_INVALIDATE = __MS_INVALIDATE,
MS_SYNC = __MS_SYNC,
};
@@ -2,7 +2,7 @@
#include <zinnia/errno.h>
#include <zinnia/list.h>
#include <zinnia/mem/page.h>
#include <zinnia/page.h>
#include <zinnia/spin.h>
#include <stddef.h>
#include <stdint.h>
@@ -37,7 +37,7 @@ struct paged_vmo {
struct vmo object;
struct pager_ops source;
list_head(struct page_list*) cache;
struct spinlock lock;
spinlock_t lock;
};
errno_t vmo_new_paged(struct pager_ops ops, struct paged_vmo** out);
@@ -3,7 +3,7 @@
#include <stddef.h>
#include <stdint.h>
enum page_type : uint32_t {
enum page_type : uint8_t {
PAGE_PHYS = 0, // Regular physical memory.
};
@@ -1,7 +1,7 @@
#pragma once
#include <stdint.h>
#include <zinnia/errno.h>
#include <stdint.h>
struct pager {
errno_t (*try_get_page)(struct pager* pager, uintptr_t offset);
+2 -2
View File
@@ -1,11 +1,11 @@
#pragma once
#include <bits/percpu.h>
#include <stddef.h>
#include <zinnia/compiler.h>
#include <zinnia/irq.h>
#include <zinnia/sched.h>
#include <zinnia/usercopy.h>
#include <bits/percpu.h>
#include <stddef.h>
ASSERT_TYPE(struct arch_percpu);
@@ -1,12 +1,12 @@
#pragma once
#include <zinnia/alloc.h>
#include <zinnia/errno.h>
#include <zinnia/mem/alloc.h>
#include <zinnia/spin.h>
#include <zinnia/utils.h>
#include <bits/mmu.h>
enum pte_flags {
enum pte_flags : uint8_t {
PTE_READ = 1 << 0, // Can read from this page.
PTE_WRITE = 1 << 1, // Can write to this page.
PTE_EXEC = 1 << 2, // Can execute code on this page.
@@ -14,8 +14,8 @@ enum pte_flags {
PTE_DIR = 1 << 4, // Is a non-leaf page.
};
enum cache_mode {
CACHE_NONE, // None means "nothing explicit" here.
enum cache_mode : uint8_t {
CACHE_ANY,
CACHE_WRITE_COMBINE,
CACHE_WRITE_THROUGH,
CACHE_WRITE_BACK,
@@ -24,7 +24,7 @@ enum cache_mode {
struct pmap {
phys_t root;
struct spinlock lock;
spinlock_t lock;
bool is_user;
};
@@ -35,8 +35,6 @@ errno_t pmap_protect(struct pmap* pt, uintptr_t vaddr, enum pte_flags flags);
errno_t pmap_unmap(struct pmap* pt, uintptr_t vaddr);
void pmap_set(struct pmap* pt);
pte_t* pmap_pte_resolve(struct pmap* pt, virt_t virt);
void pte_clear(pte_t* pte);
pte_t pte_build(phys_t addr, enum pte_flags flags, enum cache_mode cache);
bool pte_is_present(pte_t* pte);
+1 -1
View File
@@ -4,6 +4,6 @@
#include <stdarg.h>
[[__format(printf, 1, 2)]]
void printf(const char* message, ...);
void kprintf(const char* message, ...);
void kvprintf(const char* message, va_list args);
+4
View File
@@ -0,0 +1,4 @@
#pragma once
void rcu_read_lock();
void rcu_read_unlock();
+2 -14
View File
@@ -7,17 +7,5 @@ struct refcount {
size_t count;
};
static inline void refcount_inc(struct refcount* rc) {
rc->count++;
}
struct foo {
int a;
struct refcount rc;
};
static void do_foo() {
struct foo f = {.a = 4, .rc = {0}};
refcount_inc(&f.rc);
}
void refcount_inc(struct refcount* rc);
void refcount_dec(struct refcount* rc);
+4 -4
View File
@@ -4,13 +4,13 @@
// Busy-waits in a loop until the lock is freed.
// Does not put the CPU to sleep.
struct spinlock {
typedef struct {
uint32_t owner;
uint32_t next;
};
} spinlock_t;
// Attempts to lock a spinlock. If it's already locked, waits until it's freed.
void spin_lock(struct spinlock* spin);
void spin_lock(spinlock_t* spin);
// Unlocks a spinlock.
void spin_unlock(struct spinlock* spin);
void spin_unlock(spinlock_t* spin);
+18 -4
View File
@@ -2,10 +2,24 @@
#include <zinnia/sched.h>
typedef void (*syscall_fn_t)(struct arch_context* ctx);
enum syscall_kind {
SYSKIND_CALL = 0, // Regular call, returns error and/or value.
SYSKIND_CONTEXT, // Consumes the entire register image.
SYSKIND_NORETURN, // Does not resume control to the calling process.
};
struct syscall {
void (*handler)(struct arch_context*);
enum syscall_kind kind;
};
struct syscall_return {
int errno;
uintptr_t value;
};
void syscall_dispatch(struct arch_context* ctx);
#define __SYSCALL_DEFINE(_idx, name) void syscall_##name(struct arch_context* ctx);
#include <uapi/syscall_numbers.h>
#undef __SYSCALL_DEFINE
#include <zinnia/syscall_list.h>
extern const struct syscall syscall_table[256];
+149
View File
@@ -0,0 +1,149 @@
#pragma once
#include <zinnia/sched.h>
extern void sys_exit(struct arch_context* ctx);
extern void sys_syslog(struct arch_context* ctx);
extern void sys_getuname(struct arch_context* ctx);
extern void sys_setuname(struct arch_context* ctx);
extern void sys_archctl(struct arch_context* ctx);
extern void sys_reboot(struct arch_context* ctx);
extern void sys_mmap(struct arch_context* ctx);
extern void sys_munmap(struct arch_context* ctx);
extern void sys_mprotect(struct arch_context* ctx);
extern void sys_madvise(struct arch_context* ctx);
extern void sys_sigprocmask(struct arch_context* ctx);
extern void sys_sigsuspend(struct arch_context* ctx);
extern void sys_sigpending(struct arch_context* ctx);
extern void sys_sigaction(struct arch_context* ctx);
extern void sys_sigtimedwait(struct arch_context* ctx);
extern void sys_sigaltstack(struct arch_context* ctx);
extern void sys_sigreturn(struct arch_context* ctx);
extern void sys_sigqueue(struct arch_context* ctx);
extern void sys_execve(struct arch_context* ctx);
extern void sys_fexecve(struct arch_context* ctx);
extern void sys_fork(struct arch_context* ctx);
extern void sys_kill(struct arch_context* ctx);
extern void sys_gettid(struct arch_context* ctx);
extern void sys_getpid(struct arch_context* ctx);
extern void sys_getppid(struct arch_context* ctx);
extern void sys_waitid(struct arch_context* ctx);
extern void sys_waitpid(struct arch_context* ctx);
extern void sys_pread(struct arch_context* ctx);
extern void sys_readv(struct arch_context* ctx);
extern void sys_pwrite(struct arch_context* ctx);
extern void sys_writev(struct arch_context* ctx);
extern void sys_seek(struct arch_context* ctx);
extern void sys_ioctl(struct arch_context* ctx);
extern void sys_openat(struct arch_context* ctx);
extern void sys_close(struct arch_context* ctx);
extern void sys_fstat(struct arch_context* ctx);
extern void sys_fstatat(struct arch_context* ctx);
extern void sys_statvfs(struct arch_context* ctx);
extern void sys_fstatvfs(struct arch_context* ctx);
extern void sys_faccessat(struct arch_context* ctx);
extern void sys_fcntl(struct arch_context* ctx);
extern void sys_ftruncate(struct arch_context* ctx);
extern void sys_truncate(struct arch_context* ctx);
extern void sys_fallocate(struct arch_context* ctx);
extern void sys_fadvise(struct arch_context* ctx);
extern void sys_utimensat(struct arch_context* ctx);
extern void sys_mknodat(struct arch_context* ctx);
extern void sys_getcwd(struct arch_context* ctx);
extern void sys_chdir(struct arch_context* ctx);
extern void sys_fchdir(struct arch_context* ctx);
extern void sys_mkdirat(struct arch_context* ctx);
extern void sys_rmdirat(struct arch_context* ctx);
extern void sys_getdents(struct arch_context* ctx);
extern void sys_renameat(struct arch_context* ctx);
extern void sys_fchmod(struct arch_context* ctx);
extern void sys_fchmodat(struct arch_context* ctx);
extern void sys_fchownat(struct arch_context* ctx);
extern void sys_linkat(struct arch_context* ctx);
extern void sys_symlinkat(struct arch_context* ctx);
extern void sys_unlinkat(struct arch_context* ctx);
extern void sys_readlinkat(struct arch_context* ctx);
extern void sys_flock(struct arch_context* ctx);
extern void sys_ppoll(struct arch_context* ctx);
extern void sys_dup(struct arch_context* ctx);
extern void sys_dup3(struct arch_context* ctx);
extern void sys_sync(struct arch_context* ctx);
extern void sys_fsync(struct arch_context* ctx);
extern void sys_fdatasync(struct arch_context* ctx);
extern void sys_getgroups(struct arch_context* ctx);
extern void sys_setgroups(struct arch_context* ctx);
extern void sys_getsid(struct arch_context* ctx);
extern void sys_setsid(struct arch_context* ctx);
extern void sys_setuid(struct arch_context* ctx);
extern void sys_getuid(struct arch_context* ctx);
extern void sys_setgid(struct arch_context* ctx);
extern void sys_getgid(struct arch_context* ctx);
extern void sys_geteuid(struct arch_context* ctx);
extern void sys_seteuid(struct arch_context* ctx);
extern void sys_getegid(struct arch_context* ctx);
extern void sys_setegid(struct arch_context* ctx);
extern void sys_getpgid(struct arch_context* ctx);
extern void sys_setpgid(struct arch_context* ctx);
extern void sys_getresuid(struct arch_context* ctx);
extern void sys_setresuid(struct arch_context* ctx);
extern void sys_getresgid(struct arch_context* ctx);
extern void sys_setresgid(struct arch_context* ctx);
extern void sys_setreuid(struct arch_context* ctx);
extern void sys_setregid(struct arch_context* ctx);
extern void sys_umask(struct arch_context* ctx);
extern void sys_pipe(struct arch_context* ctx);
extern void sys_futex_wait(struct arch_context* ctx);
extern void sys_futex_wake(struct arch_context* ctx);
extern void sys_thread_create(struct arch_context* ctx);
extern void sys_thread_kill(struct arch_context* ctx);
extern void sys_thread_exit(struct arch_context* ctx);
extern void sys_thread_setname(struct arch_context* ctx);
extern void sys_thread_getname(struct arch_context* ctx);
extern void sys_timer_create(struct arch_context* ctx);
extern void sys_timer_set(struct arch_context* ctx);
extern void sys_timer_get(struct arch_context* ctx);
extern void sys_timer_getoverrun(struct arch_context* ctx);
extern void sys_timer_delete(struct arch_context* ctx);
extern void sys_itimer_get(struct arch_context* ctx);
extern void sys_itimer_set(struct arch_context* ctx);
extern void sys_clock_get(struct arch_context* ctx);
extern void sys_clock_getres(struct arch_context* ctx);
extern void sys_clock_set(struct arch_context* ctx);
extern void sys_sleep(struct arch_context* ctx);
extern void sys_yield(struct arch_context* ctx);
extern void sys_chroot(struct arch_context* ctx);
extern void sys_mount(struct arch_context* ctx);
extern void sys_umount(struct arch_context* ctx);
extern void sys_socket(struct arch_context* ctx);
extern void sys_socketpair(struct arch_context* ctx);
extern void sys_shutdown(struct arch_context* ctx);
extern void sys_bind(struct arch_context* ctx);
extern void sys_connect(struct arch_context* ctx);
extern void sys_accept(struct arch_context* ctx);
extern void sys_listen(struct arch_context* ctx);
extern void sys_getpeername(struct arch_context* ctx);
extern void sys_getsockname(struct arch_context* ctx);
extern void sys_getsockopt(struct arch_context* ctx);
extern void sys_setsockopt(struct arch_context* ctx);
extern void sys_sendmsg(struct arch_context* ctx);
extern void sys_recvmsg(struct arch_context* ctx);
extern void sys_getentropy(struct arch_context* ctx);
extern void sys_getrusage(struct arch_context* ctx);
extern void sys_getrlimit(struct arch_context* ctx);
extern void sys_setrlimit(struct arch_context* ctx);
extern void sys_getpriority(struct arch_context* ctx);
extern void sys_setpriority(struct arch_context* ctx);
extern void sys_sched_getparam(struct arch_context* ctx);
extern void sys_sched_setparam(struct arch_context* ctx);
extern void sys_module_insert(struct arch_context* ctx);
extern void sys_module_remove(struct arch_context* ctx);
extern void sys_epoll_create(struct arch_context* ctx);
extern void sys_epoll_ctl(struct arch_context* ctx);
extern void sys_epoll_pwait(struct arch_context* ctx);
extern void sys_timerfd_create(struct arch_context* ctx);
extern void sys_timerfd_gettime(struct arch_context* ctx);
extern void sys_timerfd_settime(struct arch_context* ctx);
extern void sys_signalfd_create(struct arch_context* ctx);
extern void sys_eventfd_create(struct arch_context* ctx);
extern void sys_msync(struct arch_context* ctx);
extern void sys_sysconf(struct arch_context* ctx);
+3 -3
View File
@@ -1,10 +1,10 @@
#pragma once
#include <zinnia/alloc.h>
#include <zinnia/errno.h>
#include <zinnia/mem/alloc.h>
#include <zinnia/mem/object.h>
#include <zinnia/mem/pmap.h>
#include <zinnia/mutex.h>
#include <zinnia/object.h>
#include <zinnia/pmap.h>
// Virtual address space.
struct vas {
+5 -6
View File
@@ -1,12 +1,11 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <uapi/fcntl.h>
#include <zinnia/errno.h>
#include <zinnia/iovec.h>
#include <zinnia/refcount.h>
#include <zinnia/string.h>
#include <stddef.h>
#include <stdint.h>
#include <uapi/fcntl.h>
struct vfs_mount {
struct refcount rc;
@@ -25,7 +24,7 @@ struct vfs_node;
struct vfs_regular_ops {
errno_t (*read)(struct vfs_node* file, struct iovec_iter* buffer, uint64_t offset, ssize_t* out_read);
errno_t (*write)(struct vfs_node* file, struct iovec_iter* buffer, uint64_t offset, ssize_t* out_written);
errno_t (*devctl)(struct vfs_node* file, );
errno_t (*devctl)(struct vfs_node* file);
};
struct vfs_node {
@@ -33,7 +32,7 @@ struct vfs_node {
const struct vfs_regular_ops* ops;
struct vfs_vnode* vnode;
struct vfs_path path;
struct string abs_path;
const char* abs_path;
bool has_path;
};
+1 -1
View File
@@ -8,7 +8,7 @@ struct task;
// A queue of tasks waiting for an event.
struct wait_queue {
tailq_head(struct task) waiters;
struct spinlock lock;
spinlock_t lock;
};
void wait_queue_init(struct wait_queue* wq);
+13 -14
View File
@@ -5,7 +5,6 @@
#include <zinnia/utils.h>
#include <zinnia/vas.h>
#include <zinnia/virt.h>
#include <assert.h>
#include <string.h>
extern uint8_t __ld_text_start[];
@@ -24,7 +23,7 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_
const size_t pgsz = arch_mem_page_size();
printf("Memory map:\n");
kprintf("Memory map:\n");
for (size_t i = 0; i < map_len; i++) {
if (map[i].length == 0)
continue;
@@ -45,7 +44,7 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_
break;
}
printf("[%p - %p] %s\n", (void*)map[i].address, (void*)(map[i].address + map[i].length - 1), label);
kprintf("[%p - %p] %s\n", (void*)map[i].address, (void*)(map[i].address + map[i].length - 1), label);
}
// Set up the bootstrap allocator.
@@ -55,7 +54,7 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_
largest = &map[i];
}
mem_phys_bootstrap(largest);
printf(
kprintf(
"Using region [%p - %p] for bootstrap allocator\n",
(void*)largest->address,
(void*)(largest->address + largest->length - 1)
@@ -66,43 +65,43 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_
// since we're likely going to map it at a different base address.
mem_hhdm_base = tmp_hhdm;
assert(pmap_new_kernel(&kernel_vas.pmap, 0) == 0, "Unable to allocate the kernel page table\n");
kassert(pmap_new_kernel(&kernel_vas.pmap, 0) == 0, "Unable to allocate the kernel page table\n");
// text
printf("Mapping text segment at %p\n", __ld_text_start);
kprintf("Mapping text segment at %p\n", __ld_text_start);
for (uint8_t* p = __ld_text_start; p <= __ld_text_end; p += pgsz) {
errno_t status = pmap_map(
&kernel_vas.pmap,
(uintptr_t)p,
(phys_t)(p - __ld_kernel_start + kernel_phys),
PTE_READ | PTE_EXEC,
CACHE_NONE
CACHE_ANY
);
assert(!status, "Failed to map %p with error %i\n", p, status);
}
// rodata
printf("Mapping rodata segment at %p\n", __ld_rodata_start);
kprintf("Mapping rodata segment at %p\n", __ld_rodata_start);
for (uint8_t* p = __ld_rodata_start; p < __ld_rodata_end; p += pgsz) {
errno_t status = pmap_map(
&kernel_vas.pmap,
(uintptr_t)p,
(phys_t)(p - __ld_kernel_start + kernel_phys),
PTE_READ,
CACHE_NONE
CACHE_ANY
);
assert(!status, "Failed to map %p with error %i\n", p, status);
}
// data
printf("Mapping data segment at %p\n", __ld_data_start);
kprintf("Mapping data segment at %p\n", __ld_data_start);
for (uint8_t* p = __ld_data_start; p < __ld_data_end; p += pgsz) {
errno_t status = pmap_map(
&kernel_vas.pmap,
(uintptr_t)p,
(phys_t)(p - __ld_kernel_start + kernel_phys),
PTE_READ | PTE_WRITE,
CACHE_NONE
CACHE_ANY
);
assert(!status, "Failed to map %p with error %i\n", p, status);
}
@@ -122,7 +121,7 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_
for (size_t p = 0; p <= map[i].length; p += pgsz) {
uintptr_t vaddr = (uintptr_t)(map[i].address + p + tmp_hhdm);
phys_t paddr = (phys_t)(map[i].address + p);
errno_t status = pmap_map(&kernel_vas.pmap, vaddr, paddr, PTE_READ | PTE_WRITE, CACHE_NONE);
errno_t status = pmap_map(&kernel_vas.pmap, vaddr, paddr, PTE_READ | PTE_WRITE, CACHE_ANY);
assert(!status, "Failed to map HHDM page %p to %p with error %i\n", (void*)vaddr, (void*)paddr, status);
}
}
@@ -152,7 +151,7 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_
for (size_t page = 0; page < length; page += pgsz) {
phys_t paddr;
assert(!mem_phys_alloc(1, 0, &paddr), "Failed to allocate memory for PFNDB!\n");
pmap_map(&kernel_vas.pmap, vaddr + page, paddr, PTE_READ | PTE_WRITE, CACHE_NONE);
pmap_map(&kernel_vas.pmap, vaddr + page, paddr, PTE_READ | PTE_WRITE, CACHE_ANY);
}
}
vm_pfndb = (struct page*)arch_vm_pfndb_addr();
@@ -163,5 +162,5 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_
slab_init();
printf("Memory initialization complete\n");
kprintf("Memory initialization complete\n");
}
+6 -6
View File
@@ -1,6 +1,6 @@
#include <zinnia/alloc.h>
#include <zinnia/errno.h>
#include <zinnia/mem/alloc.h>
#include <zinnia/mem/pmap.h>
#include <zinnia/pmap.h>
#include <zinnia/spin.h>
#include <zinnia/vas.h>
#include <string.h>
@@ -15,7 +15,7 @@ errno_t pmap_kernel(struct pmap* pt, enum alloc_flags flags) {
struct pmap result = {
.root = addr,
.lock = (struct spinlock){0},
.lock = (spinlock_t){0},
.is_user = false,
};
@@ -35,7 +35,7 @@ errno_t pmap_new_user(struct pmap* pt, enum alloc_flags flags) {
struct pmap result = {
.root = user_l1,
.lock = (struct spinlock){0},
.lock = (spinlock_t){0},
.is_user = true,
};
@@ -67,7 +67,7 @@ static pte_t* get_pte(struct pmap* pt, uintptr_t vaddr, bool is_user, bool check
if (pte_is_present(pte)) {
// Get the next level.
*pte = pte_build(pte_address(pte), level_flags, CACHE_NONE);
*pte = pte_build(pte_address(pte), level_flags, CACHE_ANY);
current_head = HHDM_PTR(pte_address(pte));
} else {
// If the current level isn't present, we can skip the rest.
@@ -78,7 +78,7 @@ static pte_t* get_pte(struct pmap* pt, uintptr_t vaddr, bool is_user, bool check
if (mem_phys_alloc(1, 0, &addr) != 0)
return nullptr;
*pte = pte_build(addr, level_flags, CACHE_NONE);
*pte = pte_build(addr, level_flags, CACHE_ANY);
current_head = HHDM_PTR(addr);
}
}
+4 -4
View File
@@ -1,6 +1,6 @@
#include <zinnia/alloc.h>
#include <zinnia/compiler.h>
#include <zinnia/mem/alloc.h>
#include <zinnia/mem/page.h>
#include <zinnia/page.h>
#include <zinnia/panic.h>
#include <zinnia/print.h>
#include <zinnia/spin.h>
@@ -56,7 +56,7 @@ void mem_phys_bootstrap(struct phys_mem* mem) {
}
static struct page* pmm_head = nullptr;
static struct spinlock pmm_lock = {0};
static spinlock_t pmm_lock = {0};
static size_t pmm_total_free = 0;
static errno_t freelist_alloc(size_t num_pages, enum alloc_flags flags, phys_t* out) {
@@ -150,5 +150,5 @@ void mem_phys_init(struct phys_mem* map, size_t length) {
}
const size_t free_bytes = (pmm_total_free * arch_mem_page_size());
printf("Total available memory: %zu MiB\n", free_bytes / 1024 / 1024);
kprintf("Total available memory: %zu MiB\n", free_bytes / 1024 / 1024);
}
+4 -4
View File
@@ -1,8 +1,8 @@
#include <string.h>
#include <zinnia/alloc.h>
#include <zinnia/compiler.h>
#include <zinnia/errno.h>
#include <zinnia/spin.h>
#include <string.h>
typedef struct {
size_t num_pages; // Amount of pages connected to this slab.
@@ -10,8 +10,8 @@ typedef struct {
} slab_info;
struct slab {
struct spinlock lock; // Access lock.
size_t ent_size; // Size of one entry.
spinlock_t lock; // Access lock.
size_t ent_size; // Size of one entry.
void** head;
};
@@ -24,7 +24,7 @@ typedef struct {
static struct slab slabs[8] = {0};
static errno_t slab_new(struct slab* slab, size_t size) {
slab->lock = (struct spinlock){0};
slab->lock = (spinlock_t){0};
// Allocate a new page for the head.
phys_t addr;
+7 -6
View File
@@ -1,8 +1,9 @@
#include <assert.h>
#include <zinnia/alloc.h>
#include <zinnia/errno.h>
#include <zinnia/mman.h>
#include <zinnia/utils.h>
#include <zinnia/vas.h>
#include <assert.h>
// Try to create a new, empty virtual address space.
errno_t vma_new(struct vas** out) {
@@ -51,7 +52,7 @@ errno_t vma_map_vmo(
struct vmo* vmo,
uintptr_t addr,
size_t len,
enum zn_vm_flags flags,
enum prot_flags flags,
uintptr_t vmo_offset
) {
const size_t page_size = arch_mem_page_size();
@@ -79,16 +80,16 @@ errno_t vma_map_vmo(
phys_t paddr = (phys_t)vm_page_addr(page_obj);
enum pte_flags pf = 0;
if (flags & ZN_VM_MAP_READ)
if (flags & PROT_READ)
pf |= PTE_READ;
if (flags & ZN_VM_MAP_WRITE)
if (flags & PROT_WRITE)
pf |= PTE_WRITE;
if (flags & ZN_VM_MAP_EXEC)
if (flags & PROT_EXEC)
pf |= PTE_EXEC;
if (vas->pmap.is_user)
pf |= PTE_USER;
status = pmap_map(&vas->pmap, p * page_size, paddr, pf, CACHE_NONE);
status = pmap_map(&vas->pmap, p * page_size, paddr, pf, CACHE_ANY);
if (status != 0)
return status;
}
+17 -11
View File
@@ -48,10 +48,6 @@ add_project_link_arguments(
language: 'c',
)
if target_machine.cpu_family() == 'x86_64'
add_project_arguments('-masm=intel', language: 'c')
endif
common_includes = include_directories('include')
cfg = configuration_data()
@@ -60,11 +56,21 @@ cfg.set_quoted('ZINNIA_ARCH', target_machine.cpu_family())
cfg.set_quoted('ZINNIA_COMPILER_ID', c_compiler.get_id() + ' ' + c_compiler.version())
cfg.set_quoted('ZINNIA_LINKER_ID', c_compiler.get_linker_id())
# Parse kernel config
kv = import('keyval')
kconfig = kv.load(get_option('config_path'))
foreach k, v : kconfig
if v == 'y'
cfg.set10(k, true)
else
cfg.set(k, v)
endif
endforeach
kernel_c_args = [
'-ffreestanding',
'-nostdinc', # We provide our own headers.
'-fno-stack-protector',
'-fno-omit-frame-pointer',
'-fno-pie',
]
@@ -78,14 +84,16 @@ kernel_link_args = [
]
kernel_includes = [
include_directories(
'arch' / target_machine.cpu_family() / 'include',
),
include_directories('arch' / target_machine.cpu_family() / 'include'),
]
kernel_sources = []
configure_file(configuration: cfg, output: 'config.h')
configure_file(
configuration: cfg,
output: 'config.h',
depfile: get_option('config_path'),
)
# Goes first so we can add arch-specific flags to drivers.
subdir('arch' / target_machine.cpu_family())
@@ -105,14 +113,12 @@ executable(
include_directories: [
common_includes,
kernel_includes,
uacpi_includes,
],
c_args: kernel_c_args,
link_args: kernel_link_args,
link_depends: kernel_lds,
sources: [
kernel_sources,
uacpi_sources,
],
install: true,
install_dir: '/boot',
+6 -7
View File
@@ -1,4 +1,3 @@
# Meta options
option(
'headers_only',
type: 'boolean',
@@ -6,9 +5,9 @@ option(
description: 'Only install headers',
)
# Core options
option('sched', type: 'combo', choices: ['simple'], value: 'simple')
# Firmware
option('acpi', type: 'boolean', value: true)
option('open_firmware', type: 'boolean', value: true)
option(
'config_path',
type: 'string',
value: '.config',
description: 'Relative path to the generated Kconfig file',
)
+3 -5
View File
@@ -1,8 +1,6 @@
#include <zinnia/archctl.h>
#include <zinnia/syscalls.h>
#include <zinnia/syscall.h>
errno_t arch_archctl(zn_archctl_t op, uintptr_t value);
errno_t syscall_archctl(struct arch_context* ctx) {
return arch_archctl((zn_archctl_t)ctx->ARCH_CTX_A0, (uintptr_t)ctx->ARCH_CTX_A1);
void syscall_archctl(struct arch_context* ctx) {
ctx->ARCH_CTX_RET0 = arch_archctl(ctx->ARCH_CTX_A0, ctx->ARCH_CTX_A1);
}
+148 -7
View File
@@ -6,20 +6,161 @@
#include <zinnia/types.h>
#include <zinnia/utils.h>
static const syscall_fn_t dispatch_table[] = {
#undef __ZINNIA_UAPI_SYSCALL_NUMBERS_H // We want to include the header again
#define __SYSCALL_DEFINE(idx, name) [idx] = syscall_##name,
#include <uapi/syscall_numbers.h>
#undef __SYSCALL_DEFINE
const struct syscall syscall_table[256] = {
[0] = {sys_exit, 0},
[1] = {sys_syslog, 0},
[2] = {sys_getuname, 0},
[3] = {sys_setuname, 0},
[4] = {sys_archctl, 0},
[5] = {sys_reboot, 0},
[6] = {sys_mmap, 0},
[7] = {sys_munmap, 0},
[8] = {sys_mprotect, 0},
[9] = {sys_madvise, 0},
[10] = {sys_sigprocmask, 0},
[11] = {sys_sigsuspend, 0},
[12] = {sys_sigpending, 0},
[13] = {sys_sigaction, 0},
[14] = {sys_sigtimedwait, 0},
[15] = {sys_sigaltstack, 0},
[16] = {sys_sigreturn, 0},
[17] = {sys_sigqueue, 0},
[18] = {sys_execve, 0},
[19] = {sys_fexecve, 0},
[20] = {sys_fork, SYSKIND_CONTEXT},
[21] = {sys_kill, 0},
[22] = {sys_gettid, 0},
[23] = {sys_getpid, 0},
[24] = {sys_getppid, 0},
[25] = {sys_waitid, 0},
[26] = {sys_waitpid, 0},
[27] = {sys_pread, 0},
[28] = {sys_readv, 0},
[29] = {sys_pwrite, 0},
[30] = {sys_writev, 0},
[31] = {sys_seek, 0},
[32] = {sys_ioctl, 0},
[33] = {sys_openat, 0},
[34] = {sys_close, 0},
[35] = {sys_fstat, 0},
[36] = {sys_fstatat, 0},
[37] = {sys_statvfs, 0},
[38] = {sys_fstatvfs, 0},
[39] = {sys_faccessat, 0},
[40] = {sys_fcntl, 0},
[41] = {sys_ftruncate, 0},
[42] = {sys_truncate, 0},
[43] = {sys_fallocate, 0},
[44] = {sys_fadvise, 0},
[45] = {sys_utimensat, 0},
[46] = {sys_mknodat, 0},
[47] = {sys_getcwd, 0},
[48] = {sys_chdir, 0},
[49] = {sys_fchdir, 0},
[50] = {sys_mkdirat, 0},
[51] = {sys_rmdirat, 0},
[52] = {sys_getdents, 0},
[53] = {sys_renameat, 0},
[54] = {sys_fchmod, 0},
[55] = {sys_fchmodat, 0},
[56] = {sys_fchownat, 0},
[57] = {sys_linkat, 0},
[58] = {sys_symlinkat, 0},
[59] = {sys_unlinkat, 0},
[60] = {sys_readlinkat, 0},
[61] = {sys_flock, 0},
[62] = {sys_ppoll, 0},
[63] = {sys_dup, 0},
[64] = {sys_dup3, 0},
[65] = {sys_sync, 0},
[66] = {sys_fsync, 0},
[67] = {sys_fdatasync, 0},
[68] = {sys_getgroups, 0},
[69] = {sys_setgroups, 0},
[70] = {sys_getsid, 0},
[71] = {sys_setsid, 0},
[72] = {sys_setuid, 0},
[73] = {sys_getuid, 0},
[74] = {sys_setgid, 0},
[75] = {sys_getgid, 0},
[76] = {sys_geteuid, 0},
[77] = {sys_seteuid, 0},
[78] = {sys_getegid, 0},
[79] = {sys_setegid, 0},
[80] = {sys_getpgid, 0},
[81] = {sys_setpgid, 0},
[82] = {sys_getresuid, 0},
[83] = {sys_setresuid, 0},
[84] = {sys_getresgid, 0},
[85] = {sys_setresgid, 0},
[86] = {sys_setreuid, 0},
[87] = {sys_setregid, 0},
[88] = {sys_umask, 0},
[89] = {sys_pipe, 0},
[90] = {sys_futex_wait, 0},
[91] = {sys_futex_wake, 0},
[92] = {sys_thread_create, 0},
[93] = {sys_thread_kill, 0},
[94] = {sys_thread_exit, 0},
[95] = {sys_thread_setname, 0},
[96] = {sys_thread_getname, 0},
[97] = {sys_timer_create, 0},
[98] = {sys_timer_set, 0},
[99] = {sys_timer_get, 0},
[100] = {sys_timer_getoverrun, 0},
[101] = {sys_timer_delete, 0},
[102] = {sys_itimer_get, 0},
[103] = {sys_itimer_set, 0},
[104] = {sys_clock_get, 0},
[105] = {sys_clock_getres, 0},
[106] = {sys_clock_set, 0},
[107] = {sys_sleep, 0},
[108] = {sys_yield, 0},
[109] = {sys_chroot, 0},
[110] = {sys_mount, 0},
[111] = {sys_umount, 0},
[112] = {sys_socket, 0},
[113] = {sys_socketpair, 0},
[114] = {sys_shutdown, 0},
[115] = {sys_bind, 0},
[116] = {sys_connect, 0},
[117] = {sys_accept, 0},
[118] = {sys_listen, 0},
[119] = {sys_getpeername, 0},
[120] = {sys_getsockname, 0},
[121] = {sys_getsockopt, 0},
[122] = {sys_setsockopt, 0},
[123] = {sys_sendmsg, 0},
[124] = {sys_recvmsg, 0},
[125] = {sys_getentropy, 0},
[126] = {sys_getrusage, 0},
[127] = {sys_getrlimit, 0},
[128] = {sys_setrlimit, 0},
[129] = {sys_getpriority, 0},
[130] = {sys_setpriority, 0},
[131] = {sys_sched_getparam, 0},
[132] = {sys_sched_setparam, 0},
[133] = {sys_module_insert, 0},
[134] = {sys_module_remove, 0},
[135] = {sys_epoll_create, 0},
[136] = {sys_epoll_ctl, 0},
[137] = {sys_epoll_pwait, 0},
[138] = {sys_timerfd_create, 0},
[139] = {sys_timerfd_gettime, 0},
[140] = {sys_timerfd_settime, 0},
[141] = {sys_signalfd_create, 0},
[142] = {sys_eventfd_create, 0},
[143] = {sys_msync, 0},
[144] = {sys_sysconf, 0},
};
void syscall_dispatch(struct arch_context* ctx) {
const size_t num = ctx->ARCH_CTX_NUM;
if (num >= ARRAY_SIZE(dispatch_table)) {
if (num >= ARRAY_SIZE(syscall_table) || syscall_table[num].handler == nullptr) {
ctx->ARCH_CTX_RET0 = ENOSYS;
return;
}
dispatch_table[num](ctx);
syscall_table[num].handler(ctx);
}
-48
View File
@@ -1,48 +0,0 @@
#include <zinnia/errno.h>
#include <zinnia/handle.h>
#include <zinnia/namespace.h>
#include <zinnia/percpu.h>
#include <zinnia/rights.h>
#include <zinnia/syscalls.h>
#include <zinnia/usercopy.h>
errno_t syscall_handle_clone(struct arch_context* ctx) {
zn_handle_t handle = ctx->ARCH_CTX_A0;
zn_rights_t cloned_rights = ctx->ARCH_CTX_A1;
__user zn_handle_t* cloned = (__user zn_handle_t*)ctx->ARCH_CTX_A2;
struct task* current = percpu_get()->sched.current;
struct namespace* ns = current->namespace;
struct namespace_desc desc;
errno_t status = namespace_get(ns, handle, &desc);
if (status != 0)
return status;
zn_handle_t new_handle;
status = namespace_clone_desc(ns, &desc, cloned_rights, &new_handle);
if (status != 0)
return status;
if (!usercopy_write(cloned, &new_handle, sizeof(new_handle))) {
namespace_del_desc(ns, new_handle);
return ZN_ERR_BAD_BUFFER;
}
return 0;
}
errno_t syscall_handle_drop(struct arch_context* ctx) {
zn_handle_t handle = ctx->ARCH_CTX_A0;
struct task* current = percpu_get()->sched.current;
return namespace_del_desc(current->namespace, handle);
}
errno_t syscall_handle_validate(struct arch_context* ctx) {
zn_handle_t handle = ctx->ARCH_CTX_A0;
struct task* current = percpu_get()->sched.current;
struct namespace_desc desc;
return namespace_get(current->namespace, handle, &desc);
}
+1
View File
@@ -1,4 +1,5 @@
kernel_sources += files(
'archctl.c',
'dispatch.c',
'futex.c',
)
-10
View File
@@ -1,10 +0,0 @@
#include <zinnia/errno.h>
#include <zinnia/syscalls.h>
errno_t syscall_random_entropy(struct arch_context* ctx) {
return ZN_ERR_UNSUPPORTED;
}
errno_t syscall_random_get(struct arch_context* ctx) {
return ZN_ERR_UNSUPPORTED;
}
-46
View File
@@ -1,46 +0,0 @@
#include <zinnia/alloc.h>
#include <zinnia/clock.h>
#include <zinnia/console.h>
#include <zinnia/errno.h>
#include <zinnia/syscalls.h>
#include <zinnia/usercopy.h>
errno_t syscall_log(struct arch_context* ctx) {
__user const char* msg = (__user const char*)ctx->ARCH_CTX_A0;
size_t len = ctx->ARCH_CTX_A1;
char* buf = mem_alloc(len, ALLOC_NOZERO);
if (!buf) {
return ENOMEM;
}
if (usercopy_read(buf, msg, len)) {
console_write(buf, len);
mem_free(buf);
return 0;
}
mem_free(buf);
return ZN_ERR_BAD_BUFFER;
}
errno_t syscall_page_size(struct arch_context* ctx) {
__user size_t* out = (__user size_t*)ctx->ARCH_CTX_A0;
size_t size = arch_mem_page_size();
if (!usercopy_write(out, &size, sizeof(size)))
return ZN_ERR_BAD_BUFFER;
return 0;
}
errno_t syscall_time(struct arch_context* ctx) {
__user uint64_t* out = (__user uint64_t*)ctx->ARCH_CTX_A0;
uint64_t time = clock_get_elapsed_ns();
if (!usercopy_write(out, &time, sizeof(time)))
return ZN_ERR_BAD_BUFFER;
return 0;
}
-115
View File
@@ -1,115 +0,0 @@
#include <string.h>
#include <zinnia/alloc.h>
#include <zinnia/compiler.h>
#include <zinnia/errno.h>
#include <zinnia/handle.h>
#include <zinnia/percpu.h>
#include <zinnia/print.h>
#include <zinnia/sched.h>
#include <zinnia/syscall.h>
#include <zinnia/usercopy.h>
errno_t syscall_thread_create(struct arch_context* ctx) {
zn_handle_t ns_handle = ctx->ARCH_CTX_A0;
__user const char* name = (__user const char*)ctx->ARCH_CTX_A1;
size_t name_len = ctx->ARCH_CTX_A2;
enum zn_thread_flags flags = ctx->ARCH_CTX_A3;
__user zn_handle_t* out = (__user zn_handle_t*)ctx->ARCH_CTX_A4;
struct task* current = percpu_get()->sched.current;
// Resolve namespace.
struct namespace* ns;
if (ns_handle == ZN_HANDLE_THIS_NS) {
ns = current->namespace;
} else {
struct namespace_desc ns_desc;
errno_t status = namespace_get(current->namespace, ns_handle, &ns_desc);
if (status != 0)
return status;
if (ns_desc.type != NAMESPACE_DESC_NS)
return ZN_ERR_BAD_HANDLE;
ns = ns_desc.value.namespace;
}
// Copy name from userspace.
if (name_len == 0 || name_len >= TASK_NAME_MAX)
return EINVAL;
char task_name[TASK_NAME_MAX] = {};
if (!usercopy_read(task_name, name, name_len))
return ZN_ERR_BAD_BUFFER;
// Create the task sharing the caller's address space.
// Uses sched_to_user as a placeholder entry — the real IP/SP come from thread_start.
struct task* new_task;
errno_t status = task_create(task_name, current->space, ns, sched_to_user, 0, &new_task);
if (status != 0)
return status;
// Register the task as a handle in the caller's namespace.
struct namespace_desc desc = {
.type = NAMESPACE_DESC_TASK,
.rights = ZN_RIGHTS_ALL,
.value.task = new_task,
};
zn_handle_t handle;
status = namespace_add_desc(current->namespace, desc, &handle);
if (status != 0)
return status;
if (!usercopy_write(out, &handle, sizeof(handle))) {
namespace_del_desc(current->namespace, handle);
return ZN_ERR_BAD_BUFFER;
}
return 0;
}
errno_t syscall_thread_start(struct arch_context* ctx) {
zn_handle_t thread_handle = ctx->ARCH_CTX_A0;
uintptr_t ip = ctx->ARCH_CTX_A1;
uintptr_t sp = ctx->ARCH_CTX_A2;
uintptr_t arg = ctx->ARCH_CTX_A3;
struct task* current = percpu_get()->sched.current;
struct sched_percpu* sched = &percpu_get()->sched;
// Look up the task.
struct namespace_desc desc;
errno_t status = namespace_get(current->namespace, thread_handle, &desc);
if (status != 0)
return status;
if (desc.type != NAMESPACE_DESC_TASK)
return ZN_ERR_BAD_HANDLE;
struct task* task = desc.value.task;
// Allocate a start info block for the thread entry.
struct task_start_info* info = mem_alloc(sizeof(struct task_start_info), 0);
if (!info)
return ENOMEM;
info->ip = ip;
info->sp = sp;
info->arg = arg;
// Re-initialize the task's arch context to enter user mode via sched_to_user_arg.
status =
arch_task_init(&task->context, sched_to_user, (uintptr_t)info, task->kernel_stack + KERNEL_STACK_SIZE, true);
if (status != 0) {
mem_free(info);
return status;
}
// Add to run queue.
sched_add_task(sched, task);
return 0;
}
errno_t syscall_thread_exit(struct arch_context* ctx) {
struct sched_percpu* sched = &percpu_get()->sched;
sched->current->state = TASK_STATE_DEAD;
sched_yield(sched);
unreachable();
}
-6
View File
@@ -1,6 +0,0 @@
#include <zinnia/errno.h>
#include <zinnia/syscalls.h>
errno_t syscall_vas_create(struct arch_context* ctx) {
return ZN_ERR_UNSUPPORTED;
}