more fixes

This commit is contained in:
2026-10-05 23:55:10 +02:00
committed by Marvin Friedrich
parent 8f0c73f4dc
commit 4dd59ef79a
32 changed files with 403 additions and 59 deletions
+2
View File
@@ -1,10 +1,12 @@
#pragma once #pragma once
#include <zinnia/types.h>
#include <stdint.h> #include <stdint.h>
struct arch_task_context { struct arch_task_context {
uint64_t rsp; uint64_t rsp;
uint8_t* fpu_region; uint8_t* fpu_region;
phys_t fpu_phys;
uint16_t ds, es, fs, gs; uint16_t ds, es, fs, gs;
uint64_t fs_base, gs_base; uint64_t fs_base, gs_base;
}; };
+8
View File
@@ -185,6 +185,7 @@
#define MSR_EFER_FFXSR (1 << 14) #define MSR_EFER_FFXSR (1 << 14)
#define MSR_EFER_TCE (1 << 15) #define MSR_EFER_TCE (1 << 15)
#define MSR_PAT (0x277)
#define MSR_EFER (0xC0000080) #define MSR_EFER (0xC0000080)
#define MSR_STAR (0xC0000081) #define MSR_STAR (0xC0000081)
#define MSR_LSTAR (0xC0000082) #define MSR_LSTAR (0xC0000082)
@@ -194,6 +195,13 @@
#define MSR_GS_BASE (0xC0000101) #define MSR_GS_BASE (0xC0000101)
#define MSR_KERNEL_GS_BASE (0xC0000102) #define MSR_KERNEL_GS_BASE (0xC0000102)
#define PAT_UC (0x0)
#define PAT_WC (0x1)
#define PAT_WT (0x4)
#define PAT_WP (0x5)
#define PAT_WB (0x6)
#define PAT_UCM (0x7)
#define CPL_USER (0x3) #define CPL_USER (0x3)
#define CPL_KERNEL (0x0) #define CPL_KERNEL (0x0)
+1 -1
View File
@@ -12,7 +12,7 @@ enum : pte_t {
ARCH_FLAG_SIZE = 1 << 7, ARCH_FLAG_SIZE = 1 << 7,
ARCH_FLAG_GLOBAL = 1 << 8, ARCH_FLAG_GLOBAL = 1 << 8,
ARCH_FLAG_AVAILABLE = 1 << 9, ARCH_FLAG_AVAILABLE = 1 << 9,
ARCH_FLAG_ATTRIBUTE_TABLE = 1 << 10, ARCH_FLAG_ATTRIBUTE_TABLE = 1 << 7,
ARCH_FLAG_EXECUTE_DISABLE = 1LU << 63, ARCH_FLAG_EXECUTE_DISABLE = 1LU << 63,
ARCH_PTE_ADDR_MASK = 0x000F'FFFF'FFFF'F000, ARCH_PTE_ADDR_MASK = 0x000F'FFFF'FFFF'F000,
+6
View File
@@ -56,6 +56,12 @@ void x86_64_cpu_setup(struct percpu* cpu) {
// TODO: not if FRED // TODO: not if FRED
idt_load(); idt_load();
asm_wrmsr(
MSR_PAT,
PAT_WB | PAT_WT << 8 | PAT_UCM << 16 | PAT_UC << 24 | (uint64_t)PAT_WP << 32 | (uint64_t)PAT_WC << 40 |
(uint64_t)PAT_UCM << 48 | (uint64_t)PAT_UC << 56
);
// Syscall extension. // Syscall extension.
asm_wrmsr(MSR_EFER, asm_rdmsr(MSR_EFER) | MSR_EFER_SCE); asm_wrmsr(MSR_EFER, asm_rdmsr(MSR_EFER) | MSR_EFER_SCE);
union ia32_star star = {0}; union ia32_star star = {0};
+19
View File
@@ -6,6 +6,10 @@ void pte_clear(pte_t* pte) {
*pte = 0; *pte = 0;
} }
void pte_flush(uintptr_t vaddr) {
asm volatile("invlpg [%0]" ::"r"(vaddr) : "memory");
}
pte_t pte_build(phys_t addr, enum pte_flags flags, enum cache_mode cache) { pte_t pte_build(phys_t addr, enum pte_flags flags, enum cache_mode cache) {
pte_t result = ((pte_t)addr & ARCH_PTE_ADDR_MASK) | ARCH_FLAG_PRESENT; pte_t result = ((pte_t)addr & ARCH_PTE_ADDR_MASK) | ARCH_FLAG_PRESENT;
@@ -19,6 +23,21 @@ pte_t pte_build(phys_t addr, enum pte_flags flags, enum cache_mode cache) {
result |= ARCH_FLAG_READ_WRITE; result |= ARCH_FLAG_READ_WRITE;
if (!(flags & PTE_EXEC)) if (!(flags & PTE_EXEC))
result |= ARCH_FLAG_EXECUTE_DISABLE; result |= ARCH_FLAG_EXECUTE_DISABLE;
switch (cache) {
case CACHE_ANY:
case CACHE_WRITE_BACK:
break;
case CACHE_WRITE_THROUGH:
result |= ARCH_FLAG_WRITE_THROUGH;
break;
case CACHE_MMIO:
result |= ARCH_FLAG_CACHE_DISABLE | ARCH_FLAG_WRITE_THROUGH;
break;
case CACHE_WRITE_COMBINE:
result |= ARCH_FLAG_ATTRIBUTE_TABLE | ARCH_FLAG_WRITE_THROUGH;
break;
}
} }
return result; return result;
} }
+24 -3
View File
@@ -1,4 +1,5 @@
#include <zinnia/alloc.h> #include <zinnia/alloc.h>
#include <zinnia/assert.h>
#include <zinnia/compiler.h> #include <zinnia/compiler.h>
#include <zinnia/errno.h> #include <zinnia/errno.h>
#include <zinnia/percpu.h> #include <zinnia/percpu.h>
@@ -58,7 +59,7 @@ struct task* arch_sched_switch(struct task* from, struct task* to) {
struct arch_task_context* from_ctx = &from->context; struct arch_task_context* from_ctx = &from->context;
struct arch_task_context* to_ctx = &to->context; struct arch_task_context* to_ctx = &to->context;
cpu->tss.rsp0 = to->kernel_stack + KERNEL_STACK_SIZE; cpu->tss.rsp0 = kernel_stack_top(&to->kernel_stack);
if (from_ctx->fpu_region != nullptr) { if (from_ctx->fpu_region != nullptr) {
cpu->fpu_save(from_ctx->fpu_region); cpu->fpu_save(from_ctx->fpu_region);
@@ -90,15 +91,17 @@ struct task* arch_sched_switch(struct task* from, struct task* to) {
return perform_switch(&from_ctx->rsp, to_ctx->rsp, from); return perform_switch(&from_ctx->rsp, to_ctx->rsp, from);
} }
// Calls task_entry with the correct parameters.
[[__naked]] [[__naked]]
void task_entry_thunk() { void task_entry_thunk() {
asm volatile( asm volatile(
"mov rdi, rbx\n" "mov rdi, rbx\n"
"mov rsi, r12\n" "mov rsi, r12\n"
"mov rdx, rax\n"
"jmp %0" "jmp %0"
: :
: "r"(task_entry) : "r"(task_entry)
: "memory" : "memory", "rdi", "rsi", "rdx"
); );
} }
@@ -111,8 +114,10 @@ errno_t arch_task_init(
) { ) {
struct arch_percpu* cpu = percpu_ref(arch_data); struct arch_percpu* cpu = percpu_ref(arch_data);
assert((stack_start & 0xF) == 0, "Task stack is not 16-byte aligned!\n");
// Prepare a dummy stack with an entry point function to return to. // Prepare a dummy stack with an entry point function to return to.
struct task_frame* frame = (struct task_frame*)stack_start - 1; struct task_frame* frame = (struct task_frame*)(stack_start - sizeof(uint64_t)) - 1;
frame->rbx = (uint64_t)entry; frame->rbx = (uint64_t)entry;
frame->r12 = arg0; frame->r12 = arg0;
frame->rip = (uint64_t)task_entry_thunk; frame->rip = (uint64_t)task_entry_thunk;
@@ -133,6 +138,7 @@ errno_t arch_task_init(
for (size_t i = 0; i < fpu_size; i += arch_mem_page_size()) for (size_t i = 0; i < fpu_size; i += arch_mem_page_size())
pmap_map(&kernel_vma.pmap, fpu_base + i, pages + i, PTE_WRITE | PTE_READ, CACHE_WRITE_BACK); pmap_map(&kernel_vma.pmap, fpu_base + i, pages + i, PTE_WRITE | PTE_READ, CACHE_WRITE_BACK);
context->fpu_region = (void*)fpu_base; context->fpu_region = (void*)fpu_base;
context->fpu_phys = pages;
context->ds = asm_read_ds(); context->ds = asm_read_ds();
context->es = asm_read_es(); context->es = asm_read_es();
@@ -145,6 +151,21 @@ errno_t arch_task_init(
return 0; return 0;
} }
void arch_task_fini(struct arch_task_context* context) {
if (context->fpu_region == nullptr)
return;
const size_t page_size = arch_mem_page_size();
const size_t fpu_size = percpu_ref(arch_data)->fpu_size;
const uintptr_t fpu_base = (uintptr_t)context->fpu_region;
for (size_t i = 0; i < fpu_size; i += page_size)
pmap_unmap(&kernel_vma.pmap, fpu_base + i);
mem_phys_free(context->fpu_phys, ALIGN_UP(fpu_size, page_size) / page_size);
vm_free(fpu_base, fpu_size);
context->fpu_region = nullptr;
}
[[__naked]] [[__naked]]
void arch_sched_preempt_disable() { void arch_sched_preempt_disable() {
asm volatile( asm volatile(
+1 -1
View File
@@ -192,7 +192,7 @@ static bool start_ap(phys_t trampoline, uint32_t temp_cr3, uint32_t lapic_id) {
return false; return false;
} }
log("smp: Starting CPU %zu (LAPIC %u)\n", cpu->id, lapic_id); log("smp: Starting CPU %zu\n", cpu->id);
memcpy(HHDM_PTR(trampoline), smp_trampoline_start, trampoline_size); memcpy(HHDM_PTR(trampoline), smp_trampoline_start, trampoline_size);
+7 -1
View File
@@ -28,11 +28,17 @@ SECTIONS
__ld_cmdline_start = .; __ld_cmdline_start = .;
KEEP(*(.cmdline)) KEEP(*(.cmdline))
__ld_cmdline_end = .; __ld_cmdline_end = .;
} :rodata } :rodata
.rodata : { .rodata : {
*(.rodata .rodata.*) *(.rodata .rodata.*)
/* Builtin module entry points */
. = ALIGN(8);
__ld_mod_entry_start = .;
KEEP(*(.mod.entry .mod.entry.*))
__ld_mod_entry_end = .;
*(.got .got.*) *(.got .got.*)
__ld_rodata_end = .; __ld_rodata_end = .;
+15 -10
View File
@@ -7,9 +7,11 @@
#include <zinnia/elf.h> #include <zinnia/elf.h>
#include <zinnia/init.h> #include <zinnia/init.h>
#include <zinnia/irq.h> #include <zinnia/irq.h>
#include <zinnia/module.h>
#include <zinnia/percpu.h> #include <zinnia/percpu.h>
#include <zinnia/print.h> #include <zinnia/print.h>
#include <zinnia/sched.h> #include <zinnia/sched.h>
#include <zinnia/utils.h>
#include <zinnia/vma.h> #include <zinnia/vma.h>
#include <zinnia/vmo.h> #include <zinnia/vmo.h>
#include <config.h> #include <config.h>
@@ -27,34 +29,37 @@ static void kernel_main_task(uintptr_t arg0) {
log("main: Hello from main task!\n"); log("main: Hello from main task!\n");
assert(info->num_files >= 1, "No init executable provided\n"); // Initialize built-in modules.
module_init();
assert(info->num_files >= 1, "No init executable provided");
struct vma* init_space; struct vma* init_space;
assert(vma_new(&init_space) == EOK, ""); assert(vma_new(&init_space) == EOK, "");
assert(false, "TODO!");
struct boot_file* file_data = &info->files[0]; struct boot_file* file_data = &info->files[0];
struct paged_vmo* init_file; struct paged_vmo* init_file;
assert(vmo_new_phys(&init_file) == EOK, ""); assert(vmo_new_phys(&init_file) == EOK, "");
vmo_write(&init_file->object, 0, HHDM_PTR(file_data->data), file_data->length, nullptr); vmo_write(&init_file->object, 0, HHDM_PTR(file_data->data), file_data->length, nullptr);
log("main: %s:%i\n", __FUNCTION__, __LINE__);
// Load init. // Load init.
const char* init_argv[] = {"init", nullptr}; const char* init_argv[] = {"init", nullptr};
const char* init_envp[] = {nullptr}; const char* init_envp[] = {nullptr};
struct task* init_task = nullptr; struct exec_info exec = {
errno_t status = 0; .space = init_space,
.file_obj = &init_file->object,
.argv = init_argv,
.envp = init_envp,
};
assert(false, "Not implemented!"); struct task* init_task = nullptr;
errno_t status = elf_load(&exec, &init_task);
vmo_unref(&init_file->object);
assert(status == 0, "Failed to load init process (%i)\n", status); assert(status == 0, "Failed to load init process (%i)\n", status);
sched_add_task(&percpu_get()->sched, init_task); sched_add_task(&percpu_get()->sched, init_task);
log("main: %s:%i\n", __FUNCTION__, __LINE__);
while (true) { while (true) {
irq_wait(); irq_wait();
} }
+2 -2
View File
@@ -39,8 +39,6 @@ bool clock_switch(struct clock* clock) {
} }
} }
log("clock: Switching to clock source \"%s\"\n", clock->name);
uint64_t elapsed = clock_get_elapsed_ns_locked(); uint64_t elapsed = clock_get_elapsed_ns_locked();
clock->reset(clock); clock->reset(clock);
@@ -48,6 +46,8 @@ bool clock_switch(struct clock* clock) {
active_clock = clock; active_clock = clock;
spin_unlock(&lock); spin_unlock(&lock);
log("clock: Switching to clock source \"%s\"\n", clock->name);
return true; return true;
} }
-7
View File
@@ -14,13 +14,6 @@
#include <bits/elf.h> #include <bits/elf.h>
#include <stdckdint.h> #include <stdckdint.h>
struct exec_info {
struct vma* space;
struct vmo* file_obj;
const char** argv;
const char** envp;
};
errno_t elf_load(struct exec_info* info, struct task** out) { errno_t elf_load(struct exec_info* info, struct task** out) {
errno_t err; errno_t err;
+1
View File
@@ -3,6 +3,7 @@ kernel_sources += files(
'init.c', 'init.c',
'pmm.c', 'pmm.c',
'slab.c', 'slab.c',
'stack.c',
'usercopy.c', 'usercopy.c',
'virt.c', 'virt.c',
'vma.c', 'vma.c',
+18
View File
@@ -116,3 +116,21 @@ fail:
spin_unlock(&pt->lock); spin_unlock(&pt->lock);
return status; return status;
} }
errno_t pmap_unmap(struct pmap* pt, uintptr_t vaddr) {
spin_lock(&pt->lock);
errno_t status = 0;
pte_t* pte = get_pte(pt, vaddr, false, true);
if (pte == nullptr || !pte_is_present(pte)) {
status = ENOENT;
goto fail;
}
pte_clear(pte);
pte_flush(vaddr);
fail:
spin_unlock(&pt->lock);
return status;
}
+60
View File
@@ -0,0 +1,60 @@
#include <zinnia/alloc.h>
#include <zinnia/errno.h>
#include <zinnia/pmap.h>
#include <zinnia/stack.h>
#include <zinnia/utils.h>
#include <zinnia/virt.h>
#include <zinnia/vma.h>
#include <arch/mem.h>
errno_t stack_init(struct stack* ks, size_t size) {
if (!ks || size == 0)
return EINVAL;
const size_t page_size = arch_mem_page_size();
size = ALIGN_UP(size, page_size);
uintptr_t va = vm_alloc(size + page_size);
if (!va)
return ENOMEM;
phys_t phys;
errno_t status = mem_phys_alloc(size / page_size, 0, &phys);
if (status)
goto err_vm;
const uintptr_t base = va + page_size;
size_t mapped = 0;
for (; mapped < size; mapped += page_size) {
status = pmap_map(&kernel_vma.pmap, base + mapped, phys + mapped, PTE_READ | PTE_WRITE, CACHE_WRITE_BACK);
if (status)
goto err_map;
}
ks->base = base;
ks->phys = phys;
ks->size = size;
return 0;
err_map:
for (size_t i = 0; i < mapped; i += page_size)
pmap_unmap(&kernel_vma.pmap, base + i);
mem_phys_free(phys, size / page_size);
err_vm:
vm_free(va, size + page_size);
return status;
}
void stack_destroy(struct stack* ks) {
if (!ks || !ks->base)
return;
const size_t page_size = arch_mem_page_size();
for (size_t i = 0; i < ks->size; i += page_size)
pmap_unmap(&kernel_vma.pmap, ks->base + i);
mem_phys_free(ks->phys, ks->size / page_size);
vm_free(ks->base - page_size, ks->size + page_size);
*ks = (struct stack){0};
}
+1
View File
@@ -3,6 +3,7 @@ kernel_sources += files(
'console.c', 'console.c',
'elf.c', 'elf.c',
'irq.c', 'irq.c',
'module.c',
'panic.c', 'panic.c',
'percpu.c', 'percpu.c',
'print.c', 'print.c',
+12
View File
@@ -0,0 +1,12 @@
#include <zinnia/assert.h>
#include <zinnia/module.h>
extern errno_t (*__ld_mod_entry_start[])(struct module*);
extern errno_t (*__ld_mod_entry_end[])(struct module*);
void module_init() {
for (auto start = __ld_mod_entry_start; start < __ld_mod_entry_end; start += 1) {
errno_t mod_status = (*start)(nullptr);
assert(mod_status == EOK, "Built-in entry point returned %i", mod_status);
}
}
+13 -2
View File
@@ -2,11 +2,12 @@
#include <zinnia/console.h> #include <zinnia/console.h>
#include <zinnia/panic.h> #include <zinnia/panic.h>
#include <zinnia/print.h> #include <zinnia/print.h>
#include <zinnia/spin.h>
#include <zinnia/stdlib.h>
#include <zinnia/string.h>
#include <stdarg.h> #include <stdarg.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <zinnia/stdlib.h>
#include <zinnia/string.h>
typedef void (*log_fn_t)(void* ctx, const char* buf, size_t len); typedef void (*log_fn_t)(void* ctx, const char* buf, size_t len);
@@ -312,13 +313,23 @@ static void printf_console(void*, const char* msg, size_t len) {
console_write(msg, len); console_write(msg, len);
} }
static struct spinlock print_lock = {};
void kprintf(const char* message, ...) { void kprintf(const char* message, ...) {
spin_lock(&print_lock);
va_list args; va_list args;
va_start(args, message); va_start(args, message);
do_print(printf_console, nullptr, message, args); do_print(printf_console, nullptr, message, args);
va_end(args); va_end(args);
spin_unlock(&print_lock);
} }
void kvprintf(const char* message, va_list args) { void kvprintf(const char* message, va_list args) {
spin_lock(&print_lock);
do_print(printf_console, nullptr, message, args); do_print(printf_console, nullptr, message, args);
spin_unlock(&print_lock);
} }
+23 -8
View File
@@ -8,6 +8,7 @@
#include <zinnia/print.h> #include <zinnia/print.h>
#include <zinnia/sched.h> #include <zinnia/sched.h>
#include <zinnia/spin.h> #include <zinnia/spin.h>
#include <zinnia/stack.h>
#include <zinnia/string.h> #include <zinnia/string.h>
#include <zinnia/tailq.h> #include <zinnia/tailq.h>
#include <zinnia/vma.h> #include <zinnia/vma.h>
@@ -67,6 +68,11 @@ static struct task* next_task(struct scheduler* sched) {
return t; return t;
} }
static void finish_switch(struct task* prev) {
if (prev->state == TASK_STATE_DEAD)
task_destroy(prev);
}
static void do_reschedule(struct scheduler* sched) { static void do_reschedule(struct scheduler* sched) {
struct task* from = sched->current; struct task* from = sched->current;
struct task* to = next_task(sched); struct task* to = next_task(sched);
@@ -82,12 +88,13 @@ static void do_reschedule(struct scheduler* sched) {
struct percpu* cpu = percpu_get(); struct percpu* cpu = percpu_get();
from->user_stack = cpu->user_stack; from->user_stack = cpu->user_stack;
cpu->kernel_stack = to->kernel_stack + KERNEL_STACK_SIZE; cpu->kernel_stack = kernel_stack_top(&to->kernel_stack);
cpu->user_stack = to->user_stack; cpu->user_stack = to->user_stack;
struct irq_percpu irq_state = *percpu_ref(irq_data); struct irq_percpu irq_state = *percpu_ref(irq_data);
arch_sched_switch(from, to); struct task* prev = arch_sched_switch(from, to);
*percpu_ref(irq_data) = irq_state; *percpu_ref(irq_data) = irq_state;
finish_switch(prev);
irq_unlock(); irq_unlock();
} }
@@ -117,17 +124,17 @@ errno_t task_create(const char* name, struct vma* space, task_fn_t entry, uintpt
strncpy(new_task->name, name, sizeof(new_task->name)); strncpy(new_task->name, name, sizeof(new_task->name));
// Allocate a kernel stack. // Allocate a kernel stack.
new_task->kernel_stack = (uintptr_t)mem_alloc(KERNEL_STACK_SIZE, 0); errno_t s = stack_init(&new_task->kernel_stack, KERNEL_STACK_SIZE);
if (!new_task->kernel_stack) { if (s != 0) {
mem_free(new_task); mem_free(new_task);
return ENOMEM; return s;
} }
new_task->user_stack = 0; new_task->user_stack = 0;
// Initialize the arch-dependent parts. // Initialize the arch-dependent parts.
errno_t s = arch_task_init(&new_task->context, entry, arg0, new_task->kernel_stack + KERNEL_STACK_SIZE, true); s = arch_task_init(&new_task->context, entry, arg0, kernel_stack_top(&new_task->kernel_stack), true);
if (s != 0) { if (s != 0) {
mem_free((void*)new_task->kernel_stack); stack_destroy(&new_task->kernel_stack);
mem_free(new_task); mem_free(new_task);
return s; return s;
} }
@@ -136,7 +143,15 @@ errno_t task_create(const char* name, struct vma* space, task_fn_t entry, uintpt
return 0; return 0;
} }
void task_entry(task_fn_t entry, uintptr_t arg0) { void task_destroy(struct task* task) {
arch_task_fini(&task->context);
stack_destroy(&task->kernel_stack);
mem_free(task);
}
void task_entry(task_fn_t entry, uintptr_t arg0, struct task* prev) {
finish_switch(prev);
*percpu_ref(irq_data) = (struct irq_percpu){ *percpu_ref(irq_data) = (struct irq_percpu){
.depth = 1, .depth = 1,
.saved_state = true, .saved_state = true,
+12
View File
@@ -1,10 +1,22 @@
#include <zinnia/acpi.h> #include <zinnia/acpi.h>
#include <zinnia/cmdline.h>
#include <zinnia/print.h> #include <zinnia/print.h>
#include <zinnia/types.h> #include <zinnia/types.h>
phys_t acpi_rsdp_addr = 0; phys_t acpi_rsdp_addr = 0;
static bool use_acpi = true;
void use_acpi_option(bool use) {
use_acpi = use;
}
CMDLINE_OPTION("acpi", "Enable ACPI firmware subsystem", use_acpi_option);
void acpi_init(struct boot_info* info) { void acpi_init(struct boot_info* info) {
if (!use_acpi) {
log("acpi: ACPI disabled on the command line!\n");
return;
}
if (!info->rsdp) { if (!info->rsdp) {
log("acpi: No RSDP was passed, unable to start ACPI subsystem!\n"); log("acpi: No RSDP was passed, unable to start ACPI subsystem!\n");
return; return;
+15 -4
View File
@@ -2,11 +2,22 @@
#include <zinnia/module.h> #include <zinnia/module.h>
#include <zinnia/print.h> #include <zinnia/print.h>
void nvme_init(struct module* mod) { errno_t nvme_init(struct module* mod) {
log("Hello world from NVMe!\n"); log("Hello world from NVMe!\n");
return 0;
} }
void do_nvme(bool on) {} errno_t nvme_exit(struct module* mod) {
CMDLINE_OPTION("nvme_on", "My description", do_nvme); log("Good bye from NVMe!\n");
MODULE("NVME", "Marvin Friedrich", "ISC", "1.0", nvme_init); return 0;
}
MODULE_ENTRY(nvme_init);
MODULE_EXIT(nvme_exit);
MODULE_DESC("NVMe Block Devices");
MODULE_AUTHOR("Marvin Friedrich");
MODULE_LICENSE("ISC");
MODULE_VERSION("1.0");
+14 -6
View File
@@ -1,7 +1,5 @@
/* Linker script for kernel modules */ /* Linker script for kernel modules */
ENTRY(__module_start)
PHDRS PHDRS
{ {
text PT_LOAD FLAGS(5); text PT_LOAD FLAGS(5);
@@ -13,6 +11,8 @@ PHDRS
moddesc 0x60000003; moddesc 0x60000003;
modlicense 0x60000004; modlicense 0x60000004;
modcmdline 0x60000005; modcmdline 0x60000005;
modentry 0x60000006;
modexit 0x60000007;
} }
SECTIONS SECTIONS
@@ -37,10 +37,6 @@ SECTIONS
*(.got.plt .got.plt.*) *(.got.plt .got.plt.*)
} :rodata } :rodata
.cmdline : {
KEEP(*(.cmdline))
} :rodata :modcmdline
.mod.version : { .mod.version : {
KEEP(*(.mod.version)) KEEP(*(.mod.version))
} :rodata :modversion } :rodata :modversion
@@ -57,6 +53,18 @@ SECTIONS
KEEP(*(.mod.license)) KEEP(*(.mod.license))
} :rodata :modlicense } :rodata :modlicense
.cmdline : {
KEEP(*(.cmdline))
} :rodata :modcmdline
.mod.entry : {
KEEP(*(.mod.entry))
} :rodata :modentry
.mod.exit : {
KEEP(*(.mod.exit))
} :rodata :modexit
. = ALIGN(CONSTANT(MAXPAGESIZE)); . = ALIGN(CONSTANT(MAXPAGESIZE));
/* Read-Write data */ /* Read-Write data */
+1
View File
@@ -13,6 +13,7 @@ errno_t arch_task_init(
uintptr_t stack_start, uintptr_t stack_start,
bool is_user bool is_user
); );
void arch_task_fini(struct arch_task_context* context);
[[noreturn]] [[noreturn]]
void arch_sched_jump_to_context(struct arch_context* context); void arch_sched_jump_to_context(struct arch_context* context);
[[noreturn]] [[noreturn]]
+9 -1
View File
@@ -14,7 +14,15 @@
#define __format(like, ...) gnu::format(like, __VA_ARGS__) #define __format(like, ...) gnu::format(like, __VA_ARGS__)
#define __always_inline gnu::always_inline #define __always_inline gnu::always_inline
#define __visibility gnu::visibility #define __visibility gnu::visibility
#define __pure gnu::pure
// TODO: Workaround for clang which doesn't have these C23 standard attributes yet.
#if !__has_c_attribute(unsequenced)
#define unsequenced gnu::const
#endif
#if !__has_c_attribute(reproducible)
#define reproducible gnu::pure
#endif
// Only clang has these hints, GCC would throw a warning here. // Only clang has these hints, GCC would throw a warning here.
// clang::noderef also don't support the C23 attribute format. // clang::noderef also don't support the C23 attribute format.
+14
View File
@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <zinnia/errno.h>
#include <bits/elf.h> #include <bits/elf.h>
#include <stdint.h> #include <stdint.h>
@@ -339,3 +340,16 @@ static inline uint32_t ELF64_R_SYM(uint64_t info) {
static inline uint32_t ELF64_R_TYPE(uint64_t info) { static inline uint32_t ELF64_R_TYPE(uint64_t info) {
return info & 0xFFFFFFFF; return info & 0xFFFFFFFF;
} }
struct vma;
struct vmo;
struct task;
struct exec_info {
struct vma* space;
struct vmo* file_obj;
const char** argv;
const char** envp;
};
errno_t elf_load(struct exec_info* info, struct task** out);
+23 -9
View File
@@ -1,24 +1,38 @@
#pragma once #pragma once
#include <zinnia/compiler.h> #include <zinnia/compiler.h>
#include <zinnia/errno.h>
#include <zinnia/utils.h> #include <zinnia/utils.h>
#include <stdint.h> #include <stdint.h>
#define MODULE_PROPERTY(name, data) \ #define MODULE_PROPERTY(name, data) \
[[__used, __section(".mod." name)]] \ [[__used, __section(".mod." name)]] \
static const char UNIQUE_IDENT(_name)[] = data; static const char UNIQUE_IDENT(_name)[] = data
#define MODULE(desc, author, license, version, entry) \ #define MODULE_AUTHOR(author) MODULE_PROPERTY("author", author)
void __module_start(struct module* _module) { \ #define MODULE_DESC(desc) MODULE_PROPERTY("desc", desc)
entry(_module); \ #define MODULE_VERSION(version) MODULE_PROPERTY("version", version)
#define MODULE_LICENSE(license) MODULE_PROPERTY("license", license)
#define MODULE_ENTRY(func) \
[[__used]] \
errno_t __module_entry(struct module* __module) { \
return func(__module); \
} \ } \
MODULE_PROPERTY("author", author); \ [[__used, __section(".mod.entry")]] \
MODULE_PROPERTY("desc", desc); \ static const void* __entry_fn = &__module_entry
MODULE_PROPERTY("version", version); \
MODULE_PROPERTY("license", license); #define MODULE_EXIT(func) \
[[__used]] \
errno_t __module_exit(struct module* __module) { \
return func(__module); \
} \
[[__used, __section(".mod.exit")]] \
static const void* __exit_fn = &__module_exit
struct module { struct module {
const char* name; const char* name;
struct module* owner;
}; };
#define THIS_MODULE (struct module*)nullptr #define THIS_MODULE (struct module*)nullptr
void module_init();
+1
View File
@@ -36,6 +36,7 @@ errno_t pmap_unmap(struct pmap* pt, uintptr_t vaddr);
void pmap_set(struct pmap* pt); void pmap_set(struct pmap* pt);
void pte_clear(pte_t* pte); void pte_clear(pte_t* pte);
void pte_flush(uintptr_t vaddr);
pte_t pte_build(phys_t addr, enum pte_flags flags, enum cache_mode cache); pte_t pte_build(phys_t addr, enum pte_flags flags, enum cache_mode cache);
bool pte_is_present(pte_t* pte); bool pte_is_present(pte_t* pte);
bool pte_is_dir(pte_t* pte); bool pte_is_dir(pte_t* pte);
+4 -2
View File
@@ -2,6 +2,7 @@
#include <zinnia/errno.h> #include <zinnia/errno.h>
#include <zinnia/init.h> #include <zinnia/init.h>
#include <zinnia/stack.h>
#include <zinnia/tailq.h> #include <zinnia/tailq.h>
#include <zinnia/types.h> #include <zinnia/types.h>
#include <bits/sched.h> #include <bits/sched.h>
@@ -29,7 +30,7 @@ struct task {
enum task_state state; enum task_state state;
struct arch_task_context context; struct arch_task_context context;
struct usercopy_region* usercopy_region; struct usercopy_region* usercopy_region;
uintptr_t kernel_stack; struct stack kernel_stack;
uintptr_t user_stack; uintptr_t user_stack;
size_t time_slice; size_t time_slice;
int8_t priority; int8_t priority;
@@ -48,8 +49,9 @@ struct scheduler {
typedef void (*task_fn_t)(uintptr_t arg0); typedef void (*task_fn_t)(uintptr_t arg0);
errno_t task_create(const char* name, struct vma* space, task_fn_t entry, uintptr_t arg0, struct task** out); errno_t task_create(const char* name, struct vma* space, task_fn_t entry, uintptr_t arg0, struct task** out);
void task_destroy(struct task* task);
[[noreturn]] [[noreturn]]
void task_entry(task_fn_t entry, uintptr_t arg0); void task_entry(task_fn_t entry, uintptr_t arg0, struct task* prev);
void sched_init(struct scheduler* sched); void sched_init(struct scheduler* sched);
void sched_reschedule(struct scheduler* sched); void sched_reschedule(struct scheduler* sched);
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include <zinnia/errno.h>
#include <zinnia/types.h>
#include <stddef.h>
#include <stdint.h>
struct stack {
uintptr_t base;
phys_t phys;
size_t size;
};
errno_t stack_init(struct stack* ks, size_t size);
void stack_destroy(struct stack* ks);
static inline uintptr_t kernel_stack_top(struct stack* ks) {
return ks->base + ks->size;
}
+2 -2
View File
@@ -2,8 +2,8 @@
#define SYSCALL_DECLARE(number, name, num_args) extern void sys_##name(...); #define SYSCALL_DECLARE(number, name, num_args) extern void sys_##name(...);
#endif #endif
// SYSCALL_DECLARE(0, exit, -1) SYSCALL_DECLARE(0, exit, 1)
// SYSCALL_DECLARE(1, syslog, -1) SYSCALL_DECLARE(1, syslog, 3)
SYSCALL_DECLARE(2, getuname, 1) SYSCALL_DECLARE(2, getuname, 1)
SYSCALL_DECLARE(3, setuname, 1) SYSCALL_DECLARE(3, setuname, 1)
SYSCALL_DECLARE(4, archctl, 2) SYSCALL_DECLARE(4, archctl, 2)
+12
View File
@@ -0,0 +1,12 @@
#include <zinnia/panic.h>
#include <zinnia/syscall.h>
struct syscall_ret sys_exit(int err) {
struct syscall_ret ret = {};
ret.errno = ENOSYS;
panic("sys::exit() not implemented!\n");
return ret;
}
+2
View File
@@ -1,5 +1,7 @@
kernel_sources += files( kernel_sources += files(
'archctl.c', 'archctl.c',
'dispatch.c', 'dispatch.c',
'exit.c',
'syslog.c',
'uname.c', 'uname.c',
) )
+62
View File
@@ -0,0 +1,62 @@
#include <zinnia/alloc.h>
#include <zinnia/panic.h>
#include <zinnia/print.h>
#include <zinnia/syscall.h>
#include <zinnia/usercopy.h>
#include <stdint.h>
enum syslog_kind : uintptr_t {
SYSLOG_EMERG = 0,
SYSLOG_ALERT = 1,
SYSLOG_CRIT = 2,
SYSLOG_ERR = 3,
SYSLOG_WARNING = 4,
SYSLOG_NOTICE = 5,
SYSLOG_INFO = 6,
SYSLOG_DEBUG = 7,
};
struct syscall_ret sys_syslog(enum syslog_kind kind, __user char* message, size_t len) {
struct syscall_ret ret = {};
const size_t buf_len = MIN(len + 1, 0x1000);
char* buf = mem_alloc(buf_len, ALLOC_NOZERO);
usercopy_read(buf, message, buf_len - 1);
buf[buf_len] = 0;
const char* log_level;
switch (kind) {
case SYSLOG_EMERG:
log_level = "emerg";
break;
case SYSLOG_ALERT:
log_level = "alert";
break;
case SYSLOG_CRIT:
log_level = "crit";
break;
case SYSLOG_ERR:
log_level = "err";
break;
case SYSLOG_WARNING:
log_level = "warning";
break;
case SYSLOG_NOTICE:
log_level = "notice";
break;
case SYSLOG_INFO:
log_level = "info";
break;
case SYSLOG_DEBUG:
log_level = "debug";
break;
default:
log_level = "invalid";
}
log("syslog(%s): %s\n", log_level, buf);
mem_free(buf);
return ret;
}