yeah
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
.config*
|
||||
build/
|
||||
.cache/
|
||||
.wraplock
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
mainmenu "Zinnia Kernel Configuration"
|
||||
|
||||
source "device/Kconfig"
|
||||
|
||||
config KERNEL_FLAVOR
|
||||
string "Kernel flavor name"
|
||||
default "vanilla"
|
||||
@@ -3,12 +3,13 @@
|
||||
# Zinnia
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
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
@@ -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);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ kernel_c_args += [
|
||||
'-mgeneral-regs-only',
|
||||
'-mno-red-zone',
|
||||
'-mcmodel=kernel',
|
||||
'-masm=intel',
|
||||
]
|
||||
|
||||
kernel_sources += files(
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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, ...) {
|
||||
@@ -0,0 +1,3 @@
|
||||
kernel_sources += files(
|
||||
'memfiles.c',
|
||||
)
|
||||
+7
-1
@@ -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,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
|
||||
|
||||
|
||||
@@ -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,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,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
|
||||
|
||||
|
||||
+1
-2
@@ -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
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#define __MAP_PRIVATE 0x02
|
||||
#define __MAP_FIXED 0x10
|
||||
#define __MAP_ANON 0x20
|
||||
#define __MAP_ANONYMOUS 0x20
|
||||
|
||||
#define __MS_ASYNC 0x1
|
||||
#define __MS_INVALIDATE 0x2
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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,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
@@ -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,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
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <uapi/archctl.h>
|
||||
@@ -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,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <bits/elf.h>
|
||||
#include <stdint.h>
|
||||
|
||||
constexpr char ELF_MAG[4] = {0x7F, 'E', 'L', 'F'};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
@@ -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);
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
void rcu_read_lock();
|
||||
void rcu_read_unlock();
|
||||
@@ -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,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);
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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);
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+3
-3
@@ -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,7 +10,7 @@ typedef struct {
|
||||
} slab_info;
|
||||
|
||||
struct slab {
|
||||
struct spinlock lock; // Access lock.
|
||||
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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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',
|
||||
)
|
||||
|
||||
+1
-1
Submodule subprojects/uacpi updated: 9c9b26d629...f5f6cc29f8
+3
-5
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,4 +1,5 @@
|
||||
kernel_sources += files(
|
||||
'archctl.c',
|
||||
'dispatch.c',
|
||||
'futex.c',
|
||||
)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user