diff --git a/arch/x86_64/apic.c b/arch/x86_64/apic.c index 450e5b8..7492ac6 100644 --- a/arch/x86_64/apic.c +++ b/arch/x86_64/apic.c @@ -1,37 +1,40 @@ +#include +#include #include #include #include -#include +#include +#include #include #include #include #include -static uint64_t lapic_read_reg(struct local_apic* lapic, mmio_reg32 reg) { - if (lapic->xapic_regs.base) { - if (reg.offset == APIC_REG_ICR.offset) { +static uint64_t lapic_read_reg(struct local_apic* lapic, uint32_t reg) { + if (lapic->xapic_regs) { + if (reg == APIC_REG_ICR) { uint64_t lo, hi; - lo = mmio_load(&lapic->xapic_regs, APIC_REG_ICR); - hi = mmio_load(&lapic->xapic_regs, APIC_REG_ICR_HI); + lo = mmio_read32(lapic->xapic_regs + APIC_REG_ICR); + hi = mmio_read32(lapic->xapic_regs + APIC_REG_ICR_HI); return (hi << 32) | lo; } else { - return mmio_load(&lapic->xapic_regs, reg); + return mmio_read32(lapic->xapic_regs + reg); } } else { - return asm_rdmsr(0x800 + (reg.offset >> 4)); + return asm_rdmsr(0x800 + (reg >> 4)); } } -static void lapic_write_reg(struct local_apic* lapic, mmio_reg32 reg, uint64_t value) { - if (lapic->xapic_regs.base) { - if (reg.offset == APIC_REG_ICR.offset) { - mmio_store(&lapic->xapic_regs, APIC_REG_ICR_HI, value >> 32); - mmio_store(&lapic->xapic_regs, APIC_REG_ICR, (uint32_t)value); +static void lapic_write_reg(struct local_apic* lapic, uint32_t reg, uint64_t value) { + if (lapic->xapic_regs) { + if (reg == APIC_REG_ICR) { + mmio_write32(lapic->xapic_regs + APIC_REG_ICR_HI, value >> 32); + mmio_write32(lapic->xapic_regs + APIC_REG_ICR, (uint32_t)value); } else { - mmio_store(&lapic->xapic_regs, reg, (uint32_t)value); + mmio_write32(lapic->xapic_regs + reg, (uint32_t)value); } } else { - asm_wrmsr(0x800 + (reg.offset >> 4), value); + asm_wrmsr(0x800 + (reg >> 4), value); } } @@ -43,8 +46,10 @@ void lapic_init(struct local_apic* lapic) { if (cpuid.ecx & CPUID_1C_X2APIC) apic_msr |= 1 << 10; else { - lapic->xapic_regs = mmio_new(apic_msr & 0xFFFF'F000, 0x1000); - assert(lapic->xapic_regs.base, "Failed to allocate virtual memory!\n"); + uintptr_t vaddr = vm_alloc(0x1000); + pmap_map(&kernel_vma.pmap, vaddr, apic_msr & 0xFFFF'F000, PTE_READ | PTE_WRITE, CACHE_MMIO); + lapic->xapic_regs = (void*)vaddr; + assert(lapic->xapic_regs, "Failed to allocate virtual memory!\n"); } asm_wrmsr(0x1B, apic_msr); @@ -54,7 +59,7 @@ void lapic_init(struct local_apic* lapic) { // Enable APIC bit in the SIVR. lapic_write_reg(lapic, APIC_REG_SIVR, lapic_read_reg(lapic, APIC_REG_SIVR) | 0x100); - if (lapic->xapic_regs.base) { + if (lapic->xapic_regs) { lapic_write_reg(lapic, APIC_REG_DFR, 0xF000'0000); // Logical destination = LAPIC ID. lapic_write_reg(lapic, APIC_REG_LDR, lapic_read_reg(lapic, APIC_REG_ID)); diff --git a/arch/x86_64/archctl.c b/arch/x86_64/archctl.c index 1f9e8a5..730a84f 100644 --- a/arch/x86_64/archctl.c +++ b/arch/x86_64/archctl.c @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/arch/x86_64/hpet.c b/arch/x86_64/hpet.c index 080b771..a2953c4 100644 --- a/arch/x86_64/hpet.c +++ b/arch/x86_64/hpet.c @@ -1,9 +1,11 @@ +#include #include #include #include +#include #include #include -#include +#include #include #include #include @@ -17,22 +19,22 @@ CMDLINE_OPTION("hpet", hpet_option); struct hpet { struct clock clock; - struct mmio_view regs; + void* regs; uint32_t period; }; -constexpr mmio_reg32 HPET_CAP = {.offset = 0}; -constexpr mmio_reg32 HPET_CFG = {.offset = 0x10}; -constexpr mmio_reg32 HPET_COUNTER = {.offset = 0xF0}; +constexpr uint32_t HPET_CAP = 0x0; +constexpr uint32_t HPET_CFG = 0x10; +constexpr uint32_t HPET_COUNTER = 0xF0; static void hpet_reset(struct clock* c) { struct hpet* hpet = containerof(c, struct hpet, clock); - mmio_store(&hpet->regs, HPET_COUNTER, 0u); + mmio_write64(hpet->regs + HPET_COUNTER, 0); } static uint64_t hpet_get_elapsed_ns(struct clock* c) { struct hpet* hpet = containerof(c, struct hpet, clock); - uint64_t counter = mmio_load(&hpet->regs, HPET_COUNTER); + uint64_t counter = mmio_read64(hpet->regs + HPET_COUNTER); return (counter * (uint64_t)hpet->period / 1'000'000); } @@ -56,13 +58,17 @@ void hpet_init() { assert(!uacpi_table_find_by_signature("HPET", &table), "HPET table not found!\n"); struct acpi_hpet* hpet = table.ptr; - hpet_clock.regs = mmio_new(hpet->address.address, 0x1000); + + uintptr_t vaddr = vm_alloc(0x1000); + pmap_map(&kernel_vma.pmap, vaddr, hpet->address.address, PTE_READ | PTE_WRITE, CACHE_MMIO); + hpet_clock.regs = (void*)vaddr; + uacpi_table_unref(&table); - kprintf("HPET regs at %p\n", hpet_clock.regs.base); + log("x86_64/hpet", "HPET registers mapped at %p\n", hpet_clock.regs); - mmio_store(&hpet_clock.regs, HPET_CFG, mmio_load(&hpet_clock.regs, HPET_CFG) | 1); + mmio_write64(hpet_clock.regs + HPET_CFG, mmio_read64(hpet_clock.regs + HPET_CFG) | 1); - uint64_t caps = mmio_load(&hpet_clock.regs, HPET_CAP); + uint64_t caps = mmio_read64(hpet_clock.regs + HPET_CAP); hpet_clock.period = (caps >> 32) & 0xFFFF'FFFF; assert(clock_switch(&hpet_clock.clock), "Unable to switch to HPET!\n"); diff --git a/arch/x86_64/idt.c b/arch/x86_64/idt.c index a72b81c..d408866 100644 --- a/arch/x86_64/idt.c +++ b/arch/x86_64/idt.c @@ -1,10 +1,10 @@ +#include #include #include #include #include #include #include -#include #include #include #include diff --git a/arch/x86_64/include/bits/mem.h b/arch/x86_64/include/bits/mem.h deleted file mode 100644 index 689c0f7..0000000 --- a/arch/x86_64/include/bits/mem.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include -#include -#include - -static inline size_t arch_mem_page_size() { - return 1 << 12; -} - -static inline size_t arch_mem_page_bits() { - return 12; -} - -static inline size_t arch_mem_level_bits() { - return 9; -} - -static inline size_t arch_mem_num_levels() { - return 4; -} - -static inline uintptr_t arch_mem_hhdm_addr() { - return 0xFFFF'8000'0000'0000; -} - -static inline uintptr_t arch_vm_pfndb_addr() { - return 0xFFFF'A000'0000'0000; -} - -static inline uintptr_t arch_mem_mapping_addr() { - return 0xFFFF'C000'0000'0000; -} diff --git a/arch/x86_64/include/bits/percpu.h b/arch/x86_64/include/bits/percpu.h index 4f097a6..17d4701 100644 --- a/arch/x86_64/include/bits/percpu.h +++ b/arch/x86_64/include/bits/percpu.h @@ -1,16 +1,10 @@ #pragma once +#include #include #include #include #include -#include - -static inline struct percpu* arch_percpu_get() { - struct percpu* result; - asm volatile("mov %0, gs:0" : "=r"(result)::"memory"); - return result; -} struct arch_percpu { struct gdt gdt; @@ -22,6 +16,3 @@ struct arch_percpu { void (*fpu_restore)(const void*); bool can_smap; }; - -void arch_percpu_bsp_init(); -void arch_percpu_init(); diff --git a/arch/x86_64/include/bits/mmu.h b/arch/x86_64/include/bits/pmap.h similarity index 100% rename from arch/x86_64/include/bits/mmu.h rename to arch/x86_64/include/bits/pmap.h diff --git a/arch/x86_64/include/bits/sched.h b/arch/x86_64/include/bits/sched.h index 2772d26..775a57d 100644 --- a/arch/x86_64/include/bits/sched.h +++ b/arch/x86_64/include/bits/sched.h @@ -1,6 +1,5 @@ #pragma once -#include #include struct arch_task_context { @@ -39,10 +38,8 @@ struct arch_context { #define ARCH_CTX_A0 rdi #define ARCH_CTX_A1 rsi #define ARCH_CTX_A2 rdx -#define ARCH_CTX_A3 r9 +#define ARCH_CTX_A3 r10 #define ARCH_CTX_A4 r8 -#define ARCH_CTX_A5 r10 -#define ARCH_CTX_A6 r12 -#define ARCH_CTX_A7 r13 +#define ARCH_CTX_A5 r9 #define ARCH_CTX_RET0 rax #define ARCH_CTX_RET1 rdx diff --git a/arch/x86_64/include/bits/types.h b/arch/x86_64/include/bits/types.h index 010c952..08807f1 100644 --- a/arch/x86_64/include/bits/types.h +++ b/arch/x86_64/include/bits/types.h @@ -3,4 +3,4 @@ #include typedef uint64_t phys_t; -typedef uint64_t reg_t; +typedef uint64_t virt_t; diff --git a/arch/x86_64/include/x86_64/apic.h b/arch/x86_64/include/x86_64/apic.h index ce4757f..18b73fd 100644 --- a/arch/x86_64/include/x86_64/apic.h +++ b/arch/x86_64/include/x86_64/apic.h @@ -1,12 +1,11 @@ #pragma once #include -#include struct local_apic { uint32_t id; uint32_t ticks_per_10ms; - struct mmio_view xapic_regs; + void* xapic_regs; }; enum apic_delivery_mode { @@ -38,19 +37,21 @@ enum apic_trigger_mode { APIC_TRIGGER_LEVEL = 1, }; -constexpr mmio_reg32 APIC_REG_ID = {.offset = 0x20}; -constexpr mmio_reg32 APIC_REG_TPR = {.offset = 0x80}; -constexpr mmio_reg32 APIC_REG_EOI = {.offset = 0xB0}; -constexpr mmio_reg32 APIC_REG_LDR = {.offset = 0xD0}; -constexpr mmio_reg32 APIC_REG_DFR = {.offset = 0xE0}; -constexpr mmio_reg32 APIC_REG_SIVR = {.offset = 0xF0}; -constexpr mmio_reg32 APIC_REG_ESR = {.offset = 0x280}; -constexpr mmio_reg32 APIC_REG_ICR = {.offset = 0x300}; -constexpr mmio_reg32 APIC_REG_ICR_HI = {.offset = 0x310}; -constexpr mmio_reg32 APIC_REG_LVT_TR = {.offset = 0x320}; -constexpr mmio_reg32 APIC_REG_ICR_TIMER = {.offset = 0x380}; -constexpr mmio_reg32 APIC_REG_CCR = {.offset = 0x390}; -constexpr mmio_reg32 APIC_REG_DCR = {.offset = 0x3E0}; +enum apic_regs { + APIC_REG_ID = 0x20, + APIC_REG_TPR = 0x80, + APIC_REG_EOI = 0xB0, + APIC_REG_LDR = 0xD0, + APIC_REG_DFR = 0xE0, + APIC_REG_SIVR = 0xF0, + APIC_REG_ESR = 0x280, + APIC_REG_ICR = 0x300, + APIC_REG_ICR_HI = 0x310, + APIC_REG_LVT_TR = 0x320, + APIC_REG_ICR_TIMER = 0x380, + APIC_REG_CCR = 0x390, + APIC_REG_DCR = 0x3E0, +}; void lapic_init(struct local_apic* lapic); void lapic_eoi(struct local_apic* lapic); diff --git a/arch/x86_64/include/x86_64/defs.h b/arch/x86_64/include/x86_64/defs.h index 2fb6777..652dfc6 100644 --- a/arch/x86_64/include/x86_64/defs.h +++ b/arch/x86_64/include/x86_64/defs.h @@ -194,8 +194,8 @@ #define MSR_GS_BASE (0xC0000101) #define MSR_KERNEL_GS_BASE (0xC0000102) -#define CPL_USER (0b11) -#define CPL_KERNEL (0b00) +#define CPL_USER (0x3) +#define CPL_KERNEL (0x0) #define IDT_PF (0xE) #define IDT_IPI_RESCHED (0xFF) diff --git a/arch/x86_64/include/bits/irq.h b/arch/x86_64/irq.c similarity index 65% rename from arch/x86_64/include/bits/irq.h rename to arch/x86_64/irq.c index b80da72..f0cfb22 100644 --- a/arch/x86_64/include/bits/irq.h +++ b/arch/x86_64/irq.c @@ -1,21 +1,20 @@ -#pragma once - +#include #include #include -static inline bool arch_irq_get_state() { +bool arch_irq_get_state() { uint64_t flags; asm volatile("pushf; pop %0" : "=r"(flags)::"memory"); return flags & RFLAGS_IF; } -static inline void arch_irq_set_state(bool state) { +void arch_irq_set_state(bool state) { if (state) asm volatile("sti"); else asm volatile("cli"); } -static inline void arch_irq_wait() { +void arch_irq_wait() { asm volatile("hlt"); } diff --git a/arch/x86_64/mem.c b/arch/x86_64/mem.c new file mode 100644 index 0000000..cab4014 --- /dev/null +++ b/arch/x86_64/mem.c @@ -0,0 +1,31 @@ +#include +#include +#include + +size_t arch_mem_page_size() { + return 1 << 12; +} + +size_t arch_mem_page_bits() { + return 12; +} + +size_t arch_mem_level_bits() { + return 9; +} + +size_t arch_mem_num_levels() { + return 4; +} + +uintptr_t arch_mem_hhdm_addr() { + return 0xFFFF'8000'0000'0000; +} + +uintptr_t arch_mem_pfndb_addr() { + return 0xFFFF'A000'0000'0000; +} + +uintptr_t arch_mem_mapping_addr() { + return 0xFFFF'C000'0000'0000; +} diff --git a/arch/x86_64/meson.build b/arch/x86_64/meson.build index c2842e1..070f6fb 100644 --- a/arch/x86_64/meson.build +++ b/arch/x86_64/meson.build @@ -11,8 +11,11 @@ kernel_sources += files( 'gdt.c', 'hpet.c', 'idt.c', + 'irq.c', + 'mem.c', 'percpu.c', 'pmap.c', + 'pmap.c', 'sched.c', 'serial.c', 'smp.c', diff --git a/arch/x86_64/percpu.c b/arch/x86_64/percpu.c index 4d050c6..9339a9d 100644 --- a/arch/x86_64/percpu.c +++ b/arch/x86_64/percpu.c @@ -10,6 +10,12 @@ #include #include +struct percpu* arch_percpu_get() { + struct percpu* result; + asm volatile("mov %0, gs:0" : "=r"(result)::"memory"); + return result; +} + void arch_percpu_bsp_init() { asm_wrmsr(MSR_GS_BASE, (uint64_t)&percpu_bsp); asm_wrmsr(MSR_FS_BASE, 0); @@ -30,12 +36,16 @@ union ia32_star { }; }; +static_assert(sizeof(union ia32_star) == 8); + static void setup_cpu(struct percpu* cpu) { + asm_wrmsr(MSR_KERNEL_GS_BASE, 0); asm_wrmsr(MSR_GS_BASE, (uint64_t)cpu); asm_wrmsr(MSR_FS_BASE, 0); - asm_wrmsr(MSR_KERNEL_GS_BASE, 0); gdt_load(); + + // TODO: not if FRED idt_load(); // Syscall extension. @@ -47,6 +57,8 @@ static void setup_cpu(struct percpu* cpu) { asm_wrmsr(MSR_LSTAR, (uint64_t)arch_syscall_stub); asm_wrmsr(MSR_SFMASK, RFLAGS_AC | RFLAGS_DF | RFLAGS_IF); + // TODO: FRED + uint64_t cr0, cr4; asm volatile("mov %0, cr0" : "=r"(cr0)); asm volatile("mov %0, cr4" : "=r"(cr4)); diff --git a/arch/x86_64/sched.c b/arch/x86_64/sched.c index 3e3d57a..34e03c4 100644 --- a/arch/x86_64/sched.c +++ b/arch/x86_64/sched.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -119,7 +119,7 @@ errno_t arch_task_init( if (is_user) { // Allocate FPU space. const size_t fpu_size = cpu->fpu_size; - void* fpu_base = vm_alloc(fpu_size); + uintptr_t fpu_base = vm_alloc(fpu_size); if (!fpu_base) return ENOMEM; for (size_t i = 0; i < fpu_size; i += arch_mem_page_size()) { @@ -130,9 +130,9 @@ errno_t arch_task_init( return s; } - pmap_map(&kernel_vas.pmap, (uintptr_t)fpu_base, page, PTE_WRITE | PTE_READ, CACHE_WRITE_BACK); + pmap_map(&kernel_vma.pmap, (uintptr_t)fpu_base, page, PTE_WRITE | PTE_READ, CACHE_WRITE_BACK); } - context->fpu_region = fpu_base; + context->fpu_region = (void*)fpu_base; context->ds = asm_read_ds(); context->es = asm_read_es(); diff --git a/arch/x86_64/sys.c b/arch/x86_64/sys.c index f3377ab..d7133a0 100644 --- a/arch/x86_64/sys.c +++ b/arch/x86_64/sys.c @@ -17,5 +17,3 @@ void _start() { : "i"(__ld_stack_top), "r"(kernel_entry) ); } - -void arch_panic() {} diff --git a/arch/x86_64/syscall.c b/arch/x86_64/syscall.c index 1c0a000..d31ca12 100644 --- a/arch/x86_64/syscall.c +++ b/arch/x86_64/syscall.c @@ -10,61 +10,62 @@ [[__naked]] void arch_syscall_stub() { asm volatile( - "swapgs\n" - "mov gs:%c0, rsp\n" - "mov rsp, gs:%c1\n" - "cld\n" - // We're pretending to be an interrupt, so fill the bottom fields of `Context`. - "push %c3\n" // SS and CS are not changed during SYSCALL. Use `gdt::user_data | CPL_USER`. - "push gs:%c0\n" - "push r11\n" // RFLAGS is moved into r11 by the CPU. - "push %c2\n" // Same as SS. Use `gdt::user_code64 | CPL_USER` - "push rcx\n" // RIP is moved into rcx by the CPU. - "push 0x00\n" // arch_context::error field - "push 0x00\n" // arch_context::isr field - "push rax\n" - "push rbx\n" - "push rcx\n" - "push rdx\n" - "push rbp\n" - "push rdi\n" - "push rsi\n" - "push r8\n" - "push r9\n" - "push r10\n" - "push r11\n" - "push r12\n" - "push r13\n" - "push r14\n" - "push r15\n" - "xor rbp, rbp\n" - "mov rdi, rsp\n" // Put the trap frame struct as first argument. - "call %c4\n" // Call syscall handler - "cli\n" - "pop r15\n" - "pop r14\n" - "pop r13\n" - "pop r12\n" - "pop r11\n" - "pop r10\n" - "pop r9\n" - "pop r8\n" - "pop rsi\n" - "pop rdi\n" - "pop rbp\n" - "pop rdx\n" - "pop rcx\n" - "pop rbx\n" - "pop rax\n" - "add rsp, 0x10\n" // Skip .error and .isr fields (2 * sizeof(uint64_t)) - "mov rsp, gs:%c0\n" // Load user stack from `percpu::user_stack`. - "swapgs\n" - "sysretq\n" // Return to user mode. + " swapgs\n" + " mov gs:%c0, rsp\n" // user_stack + " mov rsp, gs:%c1\n" // kernel_stack + " cld\n" + "1:\n" + " push %c3\n" // ss + " push gs:%c0\n" + " push r11\n" // rflags + " push %c2\n" // cs + " push rcx\n" // rip + " push 0x00\n" // arch_context::error + " push 0x00\n" // arch_context::isr + " push rax\n" + " push rbx\n" + " push rcx\n" + " push rdx\n" + " push rbp\n" + " push rdi\n" + " push rsi\n" + " push r8\n" + " push r9\n" + " push r10\n" + " push r11\n" + " push r12\n" + " push r13\n" + " push r14\n" + " push r15\n" + " xor rbp, rbp\n" + " mov rdi, rsp\n" // SysV ABI first argument. + " call %c4\n" // Call syscall handler. + " cli\n" + " pop r15\n" + " pop r14\n" + " pop r13\n" + " pop r12\n" + " pop r11\n" + " pop r10\n" + " pop r9\n" + " pop r8\n" + " pop rsi\n" + " pop rdi\n" + " pop rbp\n" + " pop rdx\n" + " pop rcx\n" + " pop rbx\n" + " pop rax\n" + " add rsp, 0x10\n" // Skip .error and .isr fields + "2:\n" + " mov rsp, gs:%c0\n" // user_stack + " swapgs\n" + " sysretq\n" : - : "i"(offsetof(struct percpu, user_stack)), - "i"(offsetof(struct percpu, kernel_stack)), - "i"(offsetof(struct gdt, user_code64) | CPL_USER), - "i"(offsetof(struct gdt, user_data) | CPL_USER), - "i"(syscall_dispatch) + : "i"(offsetof(struct percpu, user_stack)), // 0 + "i"(offsetof(struct percpu, kernel_stack)), // 1 + "i"(offsetof(struct gdt, user_code64) | CPL_USER), // 2 + "i"(offsetof(struct gdt, user_data) | CPL_USER), // 3 + "i"(syscall_dispatch) // 4 ); } diff --git a/arch/x86_64/tsc.c b/arch/x86_64/tsc.c index 7fc02f4..e8e6839 100644 --- a/arch/x86_64/tsc.c +++ b/arch/x86_64/tsc.c @@ -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))) { - kprintf("No invariant TSC detected!\n"); + log("x86_64/tsc", "No invariant TSC detected!\n"); return; } @@ -34,21 +34,21 @@ 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) { - kprintf("Calibrating TSC using CPUID 0x15"); + log("x86_64/tsc", "Calibrating TSC using CPUID 0x15"); freq = tsc_leaf.ecx * tsc_leaf.ebx / tsc_leaf.eax; } else { - kprintf("Unable to calibrate TSC using CPUID frequency information"); + log("x86_64/tsc", "Unable to calibrate TSC using CPUID frequency information"); return; } } else { - kprintf("Unable to calibrate the TSC without a clock or static frequency info!\n"); + log("x86_64/tsc", "Unable to calibrate the TSC without a clock or static frequency info!\n"); return; } - kprintf("Timer frequency is %lu MHz\n", freq / 1'000'000); + log("x86_64/tsc", "Timer frequency is %lu MHz\n", freq / 1'000'000); } static void tsc_option(bool opt) { use_tsc = opt; } -CMDLINE_OPTION("tsc", tsc_option); +CMDLINE_OPTION("x86_64.tsc", tsc_option); diff --git a/arch/x86_64/usercopy.c b/arch/x86_64/usercopy.c index baee3dd..da68c69 100644 --- a/arch/x86_64/usercopy.c +++ b/arch/x86_64/usercopy.c @@ -1,5 +1,5 @@ -#include #include +#include extern void x86_64_read_start(); extern void x86_64_read_end(); diff --git a/boot/main.c b/boot/main.c index f3f8a93..d33ca6d 100644 --- a/boot/main.c +++ b/boot/main.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -10,67 +11,81 @@ #include #include #include -#include +#include #include -#include #include #include -static const char zinnia_banner[] = - "Zinnia " ZINNIA_VERSION " " CONFIG_VARIANT " (" ZINNIA_ARCH ", " ZINNIA_COMPILER_ID ", " ZINNIA_LINKER_ID ")"; +static const char zinnia_banner[] = "Zinnia " ZINNIA_VERSION " " CONFIG_KERNEL_FLAVOR " (" ZINNIA_ARCH + ", " ZINNIA_COMPILER_ID ", " ZINNIA_LINKER_ID ")"; static void kernel_main_task(uintptr_t arg0) { struct boot_info* info = (struct boot_info*)arg0; - kprintf("%s\n", zinnia_banner); // Say hello! + + log("main", "Hello from main task!\n"); assert(info->num_files >= 1, "No init executable provided\n"); - struct vas* init_space; - assert(vma_new(&init_space) == 0, ""); + struct vma* init_space; + assert(vma_new(&init_space) == EOK, ""); + + assert(false, "TODO!"); struct boot_file* file_data = &info->files[0]; struct paged_vmo* init_file; - assert(vmo_new_phys(&init_file) == 0, ""); + assert(vmo_new_phys(&init_file) == EOK, ""); vmo_write(&init_file->object, 0, HHDM_PTR(file_data->data), file_data->length, nullptr); + log("main", "%s:%i\n", __FUNCTION__, __LINE__); + // Load init. const char* init_argv[] = {"init", nullptr}; const char* init_envp[] = {nullptr}; struct task* init_task = nullptr; errno_t status = 0; + + assert(false, "Not implemented!"); + assert(status == 0, "Failed to load init process (%i)\n", status); sched_add_task(&percpu_get()->sched, init_task); + log("main", "%s:%i\n", __FUNCTION__, __LINE__); + while (true) { - arch_irq_wait(); + irq_wait(); } } -[[noreturn]] -void kmain(struct boot_info* info) { - cmdline_parse(info->cmdline); - - console_init(); - mem_init(info->mem_map, info->num_mem_maps, info->virt_base, info->phys_base, info->hhdm_base); - rsdp_addr = info->rsdp; // TODO - percpu_init(); - sched_init(&percpu_get()->sched); - futex_init(); - - struct task* main_task; - task_create("main", &kernel_vas, nullptr, kernel_main_task, (uintptr_t)info, &main_task); - sched_add_task(&percpu_get()->sched, main_task); - - irq_unlock(); - sched_yield(&percpu_get()->sched); - - unreachable(); -} - [[__init]] void kernel_early_init() { percpu_bsp_init(); percpu_get()->online = true; irq_lock(); } + +[[noreturn]] +void kernel_main(struct boot_info* info) { + // TODO: Initialize log ring. + kprintf("%s\n", zinnia_banner); // Say hello! + + cmdline_parse(info->cmdline); + console_init(); + + kprintf("\ec"); + kprintf("Kernel command line: %s\n", info->cmdline); + mem_init(info->mem_map, info->num_mem_maps, info->virt_base, info->phys_base, info->hhdm_base); + rsdp_addr = info->rsdp; // TODO + percpu_init(); + sched_init(&percpu_get()->sched); + futex_init(); + + struct task* main_task; + task_create("main", &kernel_vma, kernel_main_task, (uintptr_t)info, &main_task); + sched_add_task(&percpu_get()->sched, main_task); + + irq_unlock(); + sched_yield(&percpu_get()->sched); + + unreachable(); +} diff --git a/core/clock.c b/core/clock.c index 4e51a1b..5df6d9d 100644 --- a/core/clock.c +++ b/core/clock.c @@ -31,7 +31,7 @@ bool clock_switch(struct clock* clock) { } } - kprintf("Switching to clock source \"%s\"\n", clock->name); + log("clock", "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) { - kprintf("Unable to sleep for %lu ns, no clock available!\n", ns); + log("clock", "Unable to sleep for %lu ns, no clock available!\n", ns); return; } diff --git a/core/console.c b/core/console.c index adb2b0b..37a92f2 100644 --- a/core/console.c +++ b/core/console.c @@ -37,7 +37,7 @@ void console_init() { if (active) { if (active->init(active) == false) active = nullptr; - else - kprintf("Logging on console \"%s\"\n", active->name); + + log("console", "Logging on console \"%s\"\n", active->name); } } diff --git a/core/elf.c b/core/elf.c index 75e4e69..997a417 100644 --- a/core/elf.c +++ b/core/elf.c @@ -1,18 +1,25 @@ #include +#include #include #include +#include #include #include #include #include #include -#include -#include +#include #include -#include #include #include +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 status; @@ -40,13 +47,13 @@ errno_t elf_load(struct exec_info* info, struct task** out) { struct elf_phdr phdr = {}; vmo_read(info->file_obj, (ehdr.e_phoff + (i * ehdr.e_phentsize)), &phdr, sizeof(phdr), &read); if (phdr.p_type == PT_LOAD) { - enum zn_vm_flags prot = 0; + enum prot_flags prot = 0; if (phdr.p_flags & PF_R) prot |= PROT_READ; if (phdr.p_flags & PF_W) - prot |= ZN_VM_MAP_WRITE; + prot |= PROT_WRITE; if (phdr.p_flags & PF_X) - prot |= ZN_VM_MAP_EXEC; + prot |= PROT_EXEC; assert(phdr.p_offset % phdr.p_align == phdr.p_vaddr % phdr.p_align, ""); @@ -66,7 +73,7 @@ errno_t elf_load(struct exec_info* info, struct task** out) { return status; // We map more than we copied so the rest is filled with zeroed pages. - status = vma_map_vmo(info->space, &phdr_obj->object, phdr.p_vaddr, phdr.p_memsz, prot, phdr.p_offset); + status = vma_map(info->space, &phdr_obj->object, phdr.p_vaddr, phdr.p_memsz, prot, phdr.p_offset); if (status) return status; } @@ -130,14 +137,6 @@ errno_t elf_load(struct exec_info* info, struct task** out) { vmo_write(&stack->object, stack_off, &zero, sizeof(zero), nullptr); } - // Add the init handle to the process namespace. - zn_handle_t init_handle = ZN_HANDLE_INVALID; - if (info->init_handle) { - status = namespace_add_desc(info->ns, *info->init_handle, &init_handle); - if (status) - return status; - } - #define WRITE_AUXV(auxv, value) \ do { \ stack_off -= sizeof(uintptr_t); \ @@ -154,7 +153,6 @@ errno_t elf_load(struct exec_info* info, struct task** out) { WRITE_AUXV(AT_PHNUM, ehdr.e_phnum); WRITE_AUXV(AT_PHENT, ehdr.e_phentsize); WRITE_AUXV(AT_ENTRY, ehdr.e_entry); - WRITE_AUXV(AT_INIT_HANDLE, init_handle); // envp pointers. stack_off -= sizeof(uintptr_t); @@ -181,7 +179,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, PROT_READ | ZN_VM_MAP_WRITE, 0); + status = vma_map(info->space, &stack->object, stack_start, stack_size, PROT_READ | PROT_WRITE, 0); if (status) return status; @@ -191,7 +189,7 @@ errno_t elf_load(struct exec_info* info, struct task** out) { start_info->arg = 0; struct task* result; - status = task_create(info->argv[0], info->space, info->ns, sched_to_user, (uintptr_t)start_info, &result); + status = task_create(info->argv[0], info->space, sched_to_user, (uintptr_t)start_info, &result); if (status) return status; diff --git a/core/irq.c b/core/irq.c index ba56e44..14c1420 100644 --- a/core/irq.c +++ b/core/irq.c @@ -1,6 +1,19 @@ -#include #include #include +#include +#include + +void irq_set_state(bool state) { + arch_irq_set_state(state); +} + +bool irq_get_state() { + return arch_irq_get_state(); +} + +void irq_wait() { + arch_irq_wait(); +} void irq_lock() { struct irq_percpu* cpu = &percpu_get()->irq; diff --git a/lib/meson.build b/core/lib/meson.build similarity index 100% rename from lib/meson.build rename to core/lib/meson.build diff --git a/lib/string.c b/core/lib/string.c similarity index 100% rename from lib/string.c rename to core/lib/string.c diff --git a/device/common/memfiles.c b/core/mem/fault.c similarity index 100% rename from device/common/memfiles.c rename to core/mem/fault.c diff --git a/mem/init.c b/core/mem/init.c similarity index 82% rename from mem/init.c rename to core/mem/init.c index a4eef31..2fb47cc 100644 --- a/mem/init.c +++ b/core/mem/init.c @@ -1,10 +1,10 @@ #include +#include #include #include #include #include -#include -#include +#include #include extern uint8_t __ld_text_start[]; @@ -15,7 +15,7 @@ extern uint8_t __ld_data_start[]; extern uint8_t __ld_data_end[]; extern uint8_t __ld_kernel_start[]; -struct vas kernel_vas = {0}; +struct vma kernel_vma = {0}; [[__init]] void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_t kernel_phys, uintptr_t tmp_hhdm) { @@ -23,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(); - kprintf("Memory map:\n"); + log("mem", "Memory map:\n"); for (size_t i = 0; i < map_len; i++) { if (map[i].length == 0) continue; @@ -44,7 +44,7 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_ break; } - kprintf("[%p - %p] %s\n", (void*)map[i].address, (void*)(map[i].address + map[i].length - 1), label); + log("mem", "[%p - %p] %s\n", (void*)map[i].address, (void*)(map[i].address + map[i].length - 1), label); } // Set up the bootstrap allocator. @@ -54,24 +54,23 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_ largest = &map[i]; } mem_phys_bootstrap(largest); - kprintf( + log("mem", "Using region [%p - %p] for bootstrap allocator\n", (void*)largest->address, - (void*)(largest->address + largest->length - 1) - ); + (void*)(largest->address + largest->length - 1)); // Set the HHDM base address to the address given by the loader. // We must not keep any virtual addresses to this region, // since we're likely going to map it at a different base address. mem_hhdm_base = tmp_hhdm; - kassert(pmap_new_kernel(&kernel_vas.pmap, 0) == 0, "Unable to allocate the kernel page table\n"); + assert(pmap_new_kernel(&kernel_vma.pmap, 0) == 0, "Unable to allocate the kernel page table\n"); // text - kprintf("Mapping text segment at %p\n", __ld_text_start); + log("mem", "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, + &kernel_vma.pmap, (uintptr_t)p, (phys_t)(p - __ld_kernel_start + kernel_phys), PTE_READ | PTE_EXEC, @@ -81,10 +80,10 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_ } // rodata - kprintf("Mapping rodata segment at %p\n", __ld_rodata_start); + log("mem", "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, + &kernel_vma.pmap, (uintptr_t)p, (phys_t)(p - __ld_kernel_start + kernel_phys), PTE_READ, @@ -94,10 +93,10 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_ } // data - kprintf("Mapping data segment at %p\n", __ld_data_start); + log("mem", "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, + &kernel_vma.pmap, (uintptr_t)p, (phys_t)(p - __ld_kernel_start + kernel_phys), PTE_READ | PTE_WRITE, @@ -121,14 +120,14 @@ 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_ANY); + errno_t status = pmap_map(&kernel_vma.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); } } mem_hhdm_base = tmp_hhdm; // Switch to our own page table. - pmap_set(&kernel_vas.pmap); + pmap_set(&kernel_vma.pmap); // We record metadata for every single page of available memory in a large array. // This array is contiguous in virtual memory, but is sparsely populated. @@ -139,7 +138,7 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_ const size_t num_pages = (map[i].length + pgsz - 1) / pgsz; const size_t metadata_size = num_pages * sizeof(struct page); - const uintptr_t metadata_start_vaddr = arch_vm_pfndb_addr() + (map[i].address / pgsz * sizeof(struct page)); + const uintptr_t metadata_start_vaddr = arch_mem_pfndb_addr() + (map[i].address / pgsz * sizeof(struct page)); const uintptr_t metadata_end_vaddr = metadata_start_vaddr + metadata_size; // Find the page-aligned boundaries that contain this metadata. @@ -151,10 +150,10 @@ 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_ANY); + pmap_map(&kernel_vma.pmap, vaddr + page, paddr, PTE_READ | PTE_WRITE, CACHE_ANY); } } - vm_pfndb = (struct page*)arch_vm_pfndb_addr(); + vm_pfndb = (struct page*)arch_mem_pfndb_addr(); // We don't need the bootstrap allocator from this point on. // Initialize the real page allocator. @@ -162,5 +161,5 @@ void mem_init(struct phys_mem* map, size_t map_len, uintptr_t kernel_virt, phys_ slab_init(); - kprintf("Memory initialization complete\n"); + log("mem", "Memory initialization complete\n"); } diff --git a/mem/meson.build b/core/mem/meson.build similarity index 81% rename from mem/meson.build rename to core/mem/meson.build index c12d046..de68ebd 100644 --- a/mem/meson.build +++ b/core/mem/meson.build @@ -1,11 +1,11 @@ kernel_sources += files( + 'fault.c', 'init.c', - 'mmio.c', 'pmap.c', 'pmm.c', 'slab.c', 'usercopy.c', 'virt.c', - 'vas.c', + 'vma.c', 'vmo.c', ) diff --git a/mem/pmap.c b/core/mem/pmap.c similarity index 95% rename from mem/pmap.c rename to core/mem/pmap.c index 90e2e90..d817740 100644 --- a/mem/pmap.c +++ b/core/mem/pmap.c @@ -2,10 +2,10 @@ #include #include #include -#include +#include #include -errno_t pmap_kernel(struct pmap* pt, enum alloc_flags flags) { +errno_t pmap_new_kernel(struct pmap* pt, enum alloc_flags flags) { flags &= ~ALLOC_NOZERO; phys_t addr; @@ -30,7 +30,7 @@ errno_t pmap_new_user(struct pmap* pt, enum alloc_flags flags) { return status; void* user_l1_ptr = HHDM_PTR(user_l1); - void* kernel_l1_ptr = HHDM_PTR(kernel_vas.pmap.root); + void* kernel_l1_ptr = HHDM_PTR(kernel_vma.pmap.root); memcpy(user_l1_ptr, kernel_l1_ptr, arch_mem_page_size()); struct pmap result = { diff --git a/mem/pmm.c b/core/mem/pmm.c similarity index 97% rename from mem/pmm.c rename to core/mem/pmm.c index aa368ee..542e73a 100644 --- a/mem/pmm.c +++ b/core/mem/pmm.c @@ -1,9 +1,9 @@ #include #include -#include #include #include #include +#include #include #include @@ -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()); - kprintf("Total available memory: %zu MiB\n", free_bytes / 1024 / 1024); + log("pmm", "Total available memory: %zu MiB\n", free_bytes / 1024 / 1024); } diff --git a/mem/slab.c b/core/mem/slab.c similarity index 100% rename from mem/slab.c rename to core/mem/slab.c diff --git a/mem/usercopy.c b/core/mem/usercopy.c similarity index 94% rename from mem/usercopy.c rename to core/mem/usercopy.c index 595103c..f46b3a8 100644 --- a/mem/usercopy.c +++ b/core/mem/usercopy.c @@ -1,6 +1,6 @@ -#include #include #include +#include bool usercopy_read(void* dst, const __user void* src, size_t len) { return arch_usercopy_read(dst, src, len, &percpu_get()->sched.current->usercopy_region); diff --git a/mem/virt.c b/core/mem/virt.c similarity index 64% rename from mem/virt.c rename to core/mem/virt.c index ce8d293..b60d91c 100644 --- a/mem/virt.c +++ b/core/mem/virt.c @@ -1,8 +1,8 @@ -#include -#include #include #include #include +#include +#include struct page* vm_pfndb = nullptr; @@ -10,14 +10,15 @@ struct page* vm_pfndb = nullptr; static size_t mapping_offset = 0; -void* vm_alloc(size_t length) { +uintptr_t vm_alloc(size_t length) { uintptr_t base = arch_mem_mapping_addr(); - size_t offset = atomic_fetch_add(&mapping_offset, ALIGN_UP(length, arch_mem_page_size())); + size_t offset = + atomic_fetch_add_explicit(&mapping_offset, ALIGN_UP(length, arch_mem_page_size()), memory_order_acquire); - return (void*)(base + offset); + return base + offset; } -void vm_free(void* ptr, size_t length) { +void vm_free(uintptr_t ptr, size_t length) { // TODO } diff --git a/mem/vas.c b/core/mem/vma.c similarity index 77% rename from mem/vas.c rename to core/mem/vma.c index c48bf75..7effadf 100644 --- a/mem/vas.c +++ b/core/mem/vma.c @@ -1,19 +1,20 @@ #include +#include #include #include +#include #include -#include -#include +#include // Try to create a new, empty virtual address space. -errno_t vma_new(struct vas** out) { +errno_t vma_new(struct vma** out) { debug_assert(out != nullptr, "Missing out"); errno_t res; if (!out) return EINVAL; - struct vas* vmspace = mem_alloc(sizeof(struct vas), 0); + struct vma* vmspace = mem_alloc(sizeof(struct vma), 0); if (!vmspace) return ENOMEM; @@ -31,24 +32,24 @@ err0: } // Delete a virtual address space. -void vma_delete(struct vas* vm) {} +void vma_free(struct vma* v) {} // Remove any mappings in the given address range. // May fail if there is no memory and a mapping needs to be split. -errno_t vma_unmap(struct vas* vm, uintptr_t vaddr, size_t size); +errno_t vma_unmap(struct vma* v, uintptr_t vaddr, size_t size); // Change the protection of an existing mapping. // May fail if there is no memory and a mapping needs to be split. -errno_t vma_protect(struct vas* vm, uintptr_t vaddr, size_t size, enum zn_vm_flags flags); +errno_t vma_protect(struct vma* v, uintptr_t vaddr, size_t size, enum prot_flags flags); // Try to handle a page fault. -bool vma_page_fault(struct vas* vm, uintptr_t vaddr, enum zn_vm_flags access_type) { +bool vma_page_fault(struct vma* v, const struct vma_fault_info* info) { // TODO return false; } -errno_t vma_map_vmo( - struct vas* vas, +errno_t vma_map( + struct vma* vma, struct vmo* vmo, uintptr_t addr, size_t len, @@ -65,7 +66,7 @@ errno_t vma_map_vmo( const size_t pages = ALIGN_UP(addr_offset + len, page_size) / page_size; size_t end_page = start_page + pages; - if (!vas || !vmo) + if (!vma || !vmo) return EINVAL; const size_t first_vmo_page = vmo_offset / page_size; @@ -86,10 +87,10 @@ errno_t vma_map_vmo( pf |= PTE_WRITE; if (flags & PROT_EXEC) pf |= PTE_EXEC; - if (vas->pmap.is_user) + if (vma->pmap.is_user) pf |= PTE_USER; - status = pmap_map(&vas->pmap, p * page_size, paddr, pf, CACHE_ANY); + status = pmap_map(&vma->pmap, p * page_size, paddr, pf, CACHE_ANY); if (status != 0) return status; } diff --git a/mem/vmo.c b/core/mem/vmo.c similarity index 99% rename from mem/vmo.c rename to core/mem/vmo.c index 17a38f2..eab22fc 100644 --- a/mem/vmo.c +++ b/core/mem/vmo.c @@ -1,10 +1,9 @@ -#include #include #include #include #include -#include #include +#include errno_t vmo_read(struct vmo* obj, uintptr_t offset, void* buf, size_t len, size_t* actual_read) { const size_t page_size = arch_mem_page_size(); diff --git a/core/meson.build b/core/meson.build index 89a1445..ad5a4d6 100644 --- a/core/meson.build +++ b/core/meson.build @@ -10,4 +10,7 @@ kernel_sources += files( 'spin.c', ) -kernel_sources += files('sched_dumb.c') +subdir('lib') +subdir('mem') +subdir('sched') +subdir('syscalls') diff --git a/core/panic.c b/core/panic.c index 7d3b255..326657e 100644 --- a/core/panic.c +++ b/core/panic.c @@ -4,19 +4,21 @@ #include #include +#define panic_log(msg, ...) kprintf("[ !!!! ] \e[31m" msg "\e[0m", ##__VA_ARGS__) + [[noreturn]] void panic(const char* msg, ...) { // TODO: Stop all other CPUs with IPI. - arch_irq_set_state(false); + irq_set_state(false); struct percpu* cpu = percpu_get(); struct task* current = cpu->sched.current; kprintf( - "----[ Kernel panic ]----\n" - "In task \"%s\" (TID %zu) on CPU %zu!\n", - current ? current->name : nullptr, + "[ !!!! ] \e[31m" + "Kernel panic on CPU %zu (T%zu, \"%s\"): ", + cpu->id, current ? current->id : 0, - cpu->id + current ? current->name : nullptr ); va_list args; @@ -24,9 +26,11 @@ void panic(const char* msg, ...) { kvprintf(msg, args); va_end(args); - kprintf("----[ End of panic ]----\n"); + kprintf("\e[0m"); + + panic_log("End of panic message\n"); while (1) { - arch_irq_wait(); + irq_wait(); } } diff --git a/core/percpu.c b/core/percpu.c index 6441d63..b0eb977 100644 --- a/core/percpu.c +++ b/core/percpu.c @@ -1,5 +1,6 @@ #include #include +#include [[__used, __section(".percpu")]] struct percpu percpu_bsp = { @@ -12,3 +13,15 @@ struct percpu* percpu_new() { // TODO return nullptr; } + +struct percpu* percpu_get() { + return arch_percpu_get(); +} + +void percpu_bsp_init() { + arch_percpu_bsp_init(); +} + +void percpu_init() { + arch_percpu_init(); +} diff --git a/core/sched/meson.build b/core/sched/meson.build new file mode 100644 index 0000000..0bbd154 --- /dev/null +++ b/core/sched/meson.build @@ -0,0 +1,3 @@ +kernel_sources += files( + 'sched_dumb.c', +) diff --git a/core/sched_dumb.c b/core/sched/sched_dumb.c similarity index 89% rename from core/sched_dumb.c rename to core/sched/sched_dumb.c index 0c1ed52..d83ca2e 100644 --- a/core/sched_dumb.c +++ b/core/sched/sched_dumb.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -8,17 +9,15 @@ #include #include #include -#include -#include -#include +#include #include #include #include static void idle_func(uintptr_t) { while (1) { - arch_irq_set_state(true); - arch_irq_wait(); + irq_set_state(true); + irq_wait(); } } @@ -37,13 +36,13 @@ void sched_to_user_context(uintptr_t ctx) { void sched_init(struct sched_percpu* sched) { struct task* idle_task; - assert(task_create("idle", &kernel_vas, nullptr, idle_func, 0, &idle_task) == 0, "Unable to create idle task!\n"); + assert(task_create("idle", &kernel_vma, idle_func, 0, &idle_task) == 0, "Unable to create idle task!\n"); sched->idle_task = idle_task; sched->current = idle_task; tailq_init(&sched->run_queue); - kprintf("Scheduler initialized\n"); + log("sched", "Scheduler initialized\n"); } void sched_add_task(struct sched_percpu* sched, struct task* task) { @@ -96,14 +95,7 @@ void sched_yield(struct sched_percpu* sched) { do_reschedule(sched); } -errno_t task_create( - const char* name, - struct vas* space, - struct namespace* ns, - 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) { if (!out) return EINVAL; @@ -114,7 +106,6 @@ errno_t task_create( static size_t last_tid = 0; new_task->id = atomic_fetch_add(&last_tid, 1); new_task->space = space; - new_task->namespace = ns; strncpy(new_task->name, name, sizeof(new_task->name)); // Allocate a kernel stack. diff --git a/syscalls/archctl.c b/core/syscalls/archctl.c similarity index 57% rename from syscalls/archctl.c rename to core/syscalls/archctl.c index a7c2705..3573268 100644 --- a/syscalls/archctl.c +++ b/core/syscalls/archctl.c @@ -1,6 +1,6 @@ -#include #include +#include -void syscall_archctl(struct arch_context* ctx) { +void sys_archctl(struct arch_context* ctx) { ctx->ARCH_CTX_RET0 = arch_archctl(ctx->ARCH_CTX_A0, ctx->ARCH_CTX_A1); } diff --git a/core/syscalls/dispatch.c b/core/syscalls/dispatch.c new file mode 100644 index 0000000..c2b5db9 --- /dev/null +++ b/core/syscalls/dispatch.c @@ -0,0 +1,191 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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, 0}, + // [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}, +}; + +[[gnu::no_caller_saved_registers]] +struct syscall_ret syscall_dispatch_fast( + uintptr_t a0, + uintptr_t a1, + uintptr_t a2, + uintptr_t a3, + uintptr_t a4, + uintptr_t a5, + size_t num +) { + // No need to check the table size here. In order to get to this point, + // we already have to check if this is a fast syscall. + if (syscall_table[num].func == nullptr) { + return (struct syscall_ret){.errno = ENOSYS}; + } + + struct syscall_ret (*func)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t) = + syscall_table[num].func; + + return func(a0, a1, a2, a3, a4, a5); +} + +void syscall_dispatch(struct arch_context* ctx) { + const size_t num = ctx->ARCH_CTX_NUM; + + if (num >= ARRAY_SIZE(syscall_table) || syscall_table[num].func == nullptr) { + ctx->ARCH_CTX_RET0 = ENOSYS; + return; + } + + void (*func)(struct arch_context* ctx) = syscall_table[num].func; + func(ctx); +} diff --git a/syscalls/futex.c b/core/syscalls/futex.c similarity index 100% rename from syscalls/futex.c rename to core/syscalls/futex.c diff --git a/core/syscalls/getuname.c b/core/syscalls/getuname.c new file mode 100644 index 0000000..b5e2303 --- /dev/null +++ b/core/syscalls/getuname.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include + +static spinlock_t uname_lock = {}; + +static struct utsname uname_buf = { + .sysname = "Zinnia", + .release = ZINNIA_VERSION, + .version = CONFIG_KERNEL_FLAVOR, + .nodename = "localhost", + .machine = ZINNIA_ARCH, +}; + +struct syscall_ret sys_getuname(__user struct utsname* ptr) { + struct syscall_ret ret = {}; + + if (!ptr) { + ret.errno = EINVAL; + return ret; + } + + spin_lock(&uname_lock); + + if (!usercopy_write(ptr, &uname_buf, sizeof(uname_buf))) + ret.errno = EFAULT; + + spin_unlock(&uname_lock); + + return ret; +} diff --git a/syscalls/meson.build b/core/syscalls/meson.build similarity index 81% rename from syscalls/meson.build rename to core/syscalls/meson.build index c2826eb..2227c42 100644 --- a/syscalls/meson.build +++ b/core/syscalls/meson.build @@ -2,4 +2,5 @@ kernel_sources += files( 'archctl.c', 'dispatch.c', 'futex.c', + 'getuname.c', ) diff --git a/device/Kconfig b/dev/Kconfig similarity index 100% rename from device/Kconfig rename to dev/Kconfig diff --git a/device/acpi/include/uacpi_types.h b/dev/acpi/include/uacpi_types.h similarity index 100% rename from device/acpi/include/uacpi_types.h rename to dev/acpi/include/uacpi_types.h diff --git a/device/acpi/meson.build b/dev/acpi/meson.build similarity index 100% rename from device/acpi/meson.build rename to dev/acpi/meson.build diff --git a/device/acpi/uacpi_glue.c b/dev/acpi/uacpi_glue.c similarity index 68% rename from device/acpi/uacpi_glue.c rename to dev/acpi/uacpi_glue.c index 57cf4d1..fb895f9 100644 --- a/device/acpi/uacpi_glue.c +++ b/dev/acpi/uacpi_glue.c @@ -1,7 +1,11 @@ +#include #include #include +#include #include #include +#include +#include #include #include #include @@ -13,7 +17,12 @@ uacpi_status uacpi_kernel_get_rsdp(uacpi_phys_addr* out_rsdp_address) { } void* uacpi_kernel_map(uacpi_phys_addr addr, uacpi_size len) { - return (void*)mmio_new(addr, len).base; + uintptr_t vaddr = vm_alloc(len); + for (size_t i = 0; i < len; i += arch_mem_page_size()) { + pmap_map(&kernel_vma.pmap, vaddr + i, addr + i, PROT_READ | PROT_WRITE, CACHE_ANY); + } + + return (void*)vaddr; } void uacpi_kernel_unmap(void* addr, uacpi_size len) { @@ -21,6 +30,8 @@ void uacpi_kernel_unmap(void* addr, uacpi_size len) { } void uacpi_kernel_log(uacpi_log_level lvl, const uacpi_char* msg, ...) { + console_write("uacpi: ", 7); + va_list args; va_start(args, msg); diff --git a/device/dt/meson.build b/dev/common/memfiles.c similarity index 100% rename from device/dt/meson.build rename to dev/common/memfiles.c diff --git a/device/common/meson.build b/dev/common/meson.build similarity index 100% rename from device/common/meson.build rename to dev/common/meson.build diff --git a/dev/dt/meson.build b/dev/dt/meson.build new file mode 100644 index 0000000..e69de29 diff --git a/device/meson.build b/dev/meson.build similarity index 100% rename from device/meson.build rename to dev/meson.build diff --git a/include/zinnia/bits/archctl.h b/include/arch/archctl.h similarity index 100% rename from include/zinnia/bits/archctl.h rename to include/arch/archctl.h diff --git a/include/zinnia/bits/elf.h b/include/arch/elf.h similarity index 100% rename from include/zinnia/bits/elf.h rename to include/arch/elf.h diff --git a/include/zinnia/bits/irq.h b/include/arch/irq.h similarity index 100% rename from include/zinnia/bits/irq.h rename to include/arch/irq.h diff --git a/include/zinnia/bits/mem.h b/include/arch/mem.h similarity index 87% rename from include/zinnia/bits/mem.h rename to include/arch/mem.h index d0d60f9..e601b81 100644 --- a/include/zinnia/bits/mem.h +++ b/include/arch/mem.h @@ -8,5 +8,5 @@ size_t arch_mem_page_bits(); size_t arch_mem_level_bits(); size_t arch_mem_num_levels(); uintptr_t arch_mem_hhdm_addr(); -uintptr_t arch_vm_pfndb_addr(); +uintptr_t arch_mem_pfndb_addr(); uintptr_t arch_mem_mapping_addr(); diff --git a/include/arch/percpu.h b/include/arch/percpu.h new file mode 100644 index 0000000..11a839b --- /dev/null +++ b/include/arch/percpu.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +struct percpu* arch_percpu_get(); +void arch_percpu_bsp_init(); +void arch_percpu_init(); diff --git a/include/zinnia/bits/usercopy.h b/include/arch/usercopy.h similarity index 91% rename from include/zinnia/bits/usercopy.h rename to include/arch/usercopy.h index 417e58d..0901577 100644 --- a/include/zinnia/bits/usercopy.h +++ b/include/arch/usercopy.h @@ -1,9 +1,10 @@ #pragma once -#include #include #include +#include +void arch_usercopy_allow(bool state); bool arch_usercopy_read(void* dst, const __user void* src, size_t len, struct usercopy_region** region); bool arch_usercopy_write(__user void* dst, const void* src, size_t len, struct usercopy_region** region); bool arch_usercopy_strlen(const __user char* str, size_t max, size_t* len, struct usercopy_region** region); diff --git a/include/assert.h b/include/assert.h deleted file mode 100644 index 4b36f1c..0000000 --- a/include/assert.h +++ /dev/null @@ -1,25 +0,0 @@ -#pragma once - -#include -#include - -#define assert(expr, msg, ...) \ - ({ \ - if (__unlikely(!(expr))) { \ - panic( \ - "In function \"%s\" (%s:%u):\n" \ - "Assertion \"%s\" failed!\n" msg, \ - __FUNCTION__, \ - __FILE__, \ - __LINE__, \ - #expr, \ - ##__VA_ARGS__ \ - ); \ - } \ - }) - -#ifndef NDEBUG -#define debug_assert(...) assert(__VA_ARGS__) -#else -#define debug_assert(...) ((void)0) -#endif diff --git a/include/uapi/archctl.h b/include/uapi/archctl.h index b86a8c5..be6c8b6 100644 --- a/include/uapi/archctl.h +++ b/include/uapi/archctl.h @@ -5,6 +5,8 @@ #ifdef __x86_64__ #define __ARCHCTL_SET_FSBASE 1 #define __ARCHCTL_SET_GSBASE 2 +#define __ARCHCTL_GET_FSBASE 3 +#define __ARCHCTL_GET_GSBASE 4 #endif #endif diff --git a/include/zinnia/alloc.h b/include/zinnia/alloc.h index c05ce5f..fa3206c 100644 --- a/include/zinnia/alloc.h +++ b/include/zinnia/alloc.h @@ -1,8 +1,9 @@ #pragma once -#include -#include #include +#include +#include +#include enum alloc_flags { ALLOC_NOZERO = 1 << 0, // Don't zero out the allocated memory. @@ -44,14 +45,6 @@ void slab_init(); void mem_phys_bootstrap(struct phys_mem* mem); void mem_phys_init(struct phys_mem* map, size_t length); -uintptr_t arch_mem_hhdm_addr(); -uintptr_t arch_vm_pfndb_addr(); -uintptr_t arch_mem_mapping_addr(); -size_t arch_mem_page_bits(); -size_t arch_mem_page_size(); -size_t arch_mem_level_bits(); -size_t arch_mem_num_levels(); - static inline size_t mem_high_shift() { return arch_mem_level_bits() * arch_mem_num_levels() + arch_mem_page_bits(); } diff --git a/include/zinnia/assert.h b/include/zinnia/assert.h new file mode 100644 index 0000000..4b36e46 --- /dev/null +++ b/include/zinnia/assert.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +#define assert(expr, msg, ...) \ + ({ \ + if (__unlikely(!(expr))) { \ + panic("Assertion \"%s\" failed: \"" msg "\" @ %s:%u\n", #expr, ##__VA_ARGS__, __FILE__, __LINE__); \ + } \ + }) + +#ifndef NDEBUG +#define debug_assert(...) assert(__VA_ARGS__) +#else +#define debug_assert(...) ((void)0) +#endif diff --git a/include/zinnia/btree.h b/include/zinnia/btree.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/include/zinnia/btree.h @@ -0,0 +1 @@ +#pragma once diff --git a/include/zinnia/hashmap.h b/include/zinnia/hashmap.h index 687088b..f00e475 100644 --- a/include/zinnia/hashmap.h +++ b/include/zinnia/hashmap.h @@ -1,10 +1,10 @@ #pragma once +#include +#include #include #include #include -#include -#include // FNV-1a hash over raw bytes. static inline uint64_t hashmap_hash_default(const void* key, size_t len) { @@ -25,7 +25,7 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len) // Ensure a hash is never zero (zero is the empty sentinel). #define _HASHMAP_FIXHASH(h) ((h) == 0 ? (uint64_t)1 : (h)) -#define HASHMAP(K, V) \ +#define hashmap(K, V) \ struct { \ K* keys; \ V* values; \ @@ -34,7 +34,7 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len) size_t count; \ } -#define HASHMAP_INIT(map) \ +#define hashmap_init(map) \ do { \ (map)->keys = nullptr; \ (map)->values = nullptr; \ @@ -43,7 +43,7 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len) (map)->count = 0; \ } while (0) -#define HASHMAP_DESTROY(map) \ +#define hashmap_destroy(map) \ do { \ mem_free((map)->keys); \ mem_free((map)->values); \ @@ -55,7 +55,7 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len) (map)->count = 0; \ } while (0) -#define HASHMAP_COUNT(map) ((map)->count) +#define hashmap_count(map) ((map)->count) // Internal: probe distance from ideal position. #define _HASHMAP_PROBE_DIST(hash, pos, cap) (((pos) - ((hash) & ((cap) - 1))) & ((cap) - 1)) @@ -116,10 +116,10 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len) } \ } while (0) -// Insert or update a key-value pair. Returns 0 or ENOMEM. -#define HASHMAP_INSERT(map, key, val, hash_fn, eq_fn) \ +// Insert or update a key-value pair. Returns 0 or ZN_ERR_NO_MEMORY. +#define hashmap_insert(map, key, val, hash_fn, eq_fn) \ ({ \ - errno_t _status = 0; \ + zn_status_t _status = 0; \ typeof(*(map)->keys) _k = (key); \ uint64_t _h = _HASHMAP_FIXHASH((hash_fn)(&_k, sizeof(_k))); \ /* Check for existing key first. */ \ @@ -144,7 +144,7 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len) if ((map)->count * 4 >= (map)->capacity * 3 || (map)->capacity == 0) { \ _HASHMAP_GROW(map, hash_fn, eq_fn); \ if ((map)->keys == nullptr || (map)->values == nullptr || (map)->hashes == nullptr) { \ - _status = ENOMEM; \ + _status = ZN_ERR_NO_MEMORY; \ } \ } \ if (_status == 0) { \ @@ -155,7 +155,7 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len) }) // Look up a key. Returns a pointer to the value, or nullptr if not found. -#define HASHMAP_GET(map, key, hash_fn, eq_fn) \ +#define hashmap_get(map, key, hash_fn, eq_fn) \ ({ \ typeof(*(map)->values)* _result = nullptr; \ if ((map)->capacity > 0) { \ @@ -180,7 +180,7 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len) // Remove a key. Returns true if the key was found and removed. // Uses backward-shift deletion to avoid tombstones. -#define HASHMAP_REMOVE(map, key, hash_fn, eq_fn) \ +#define hashmap_remove(map, key, hash_fn, eq_fn) \ ({ \ bool _removed = false; \ if ((map)->capacity > 0) { \ @@ -218,6 +218,6 @@ static inline bool hashmap_eq_default(const void* a, const void* b, size_t len) // Iterate over all occupied entries. `idx` is a size_t loop variable. // Access keys and values via (map)->keys[idx] and (map)->values[idx]. -#define HASHMAP_FOREACH(map, idx) \ +#define hashmap_foreach(map, idx) \ for (size_t idx = 0; idx < (map)->capacity; idx++) \ if ((map)->hashes[idx] != 0) diff --git a/include/zinnia/irq.h b/include/zinnia/irq.h index e4f0f71..744799b 100644 --- a/include/zinnia/irq.h +++ b/include/zinnia/irq.h @@ -2,7 +2,6 @@ #include #include -#include #include enum irq_status : uint8_t { @@ -45,4 +44,9 @@ 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); -void irq_raise(); +void irq_line_raise(struct irq_line* line); + +// Hints to stop execution on this CPU until an interrupt happens. +void irq_wait(); +bool irq_get_state(); +void irq_set_state(bool state); diff --git a/include/zinnia/mmio.h b/include/zinnia/mmio.h index 0e0fa29..29fc475 100644 --- a/include/zinnia/mmio.h +++ b/include/zinnia/mmio.h @@ -1,71 +1,35 @@ #pragma once -#include -#include +#include -struct mmio_view { - volatile void* base; - size_t len; -}; +static inline uint8_t mmio_read8(void* ptr) { + return *((volatile uint8_t*)ptr); +} -#define _MMIO_REG(x) \ - typedef struct { \ - size_t offset; \ - bool swapped; \ - } mmio_reg##x; +static inline uint16_t mmio_read16(void* ptr) { + return *((volatile uint16_t*)ptr); +} -_MMIO_REG(8) -_MMIO_REG(16) -_MMIO_REG(32) -_MMIO_REG(64) +static inline uint32_t mmio_read32(void* ptr) { + return *((volatile uint32_t*)ptr); +} -#define bswap_16(x) (uint16_t)x -#define bswap_32(x) (uint32_t)x -#define bswap_64(x) (uint64_t)x +static inline uint64_t mmio_read64(void* ptr) { + return *((volatile uint64_t*)ptr); +} -#define mmio_load(_view, _reg) \ - ({ \ - auto _mmio_ptr = _Generic( \ - (_reg), \ - mmio_reg8: (volatile uint8_t*)((_view)->base + (_reg).offset), \ - mmio_reg16: (volatile uint16_t*)((_view)->base + (_reg).offset), \ - mmio_reg32: (volatile uint32_t*)((_view)->base + (_reg).offset), \ - mmio_reg64: (volatile uint64_t*)((_view)->base + (_reg).offset) \ - ); \ - auto _mmio_val = *_mmio_ptr; \ - if ((_reg).swapped) \ - _Generic( \ - (_mmio_val), \ - char: (void)(_mmio_val), \ - uint8_t: (void)(_mmio_val), \ - uint16_t: (_mmio_val = bswap_16(_mmio_val)), \ - uint32_t: (_mmio_val = bswap_32(_mmio_val)), \ - uint64_t: (_mmio_val = bswap_64(_mmio_val)) \ - ); \ - _mmio_val; \ - }) +static inline void mmio_write8(void* ptr, uint8_t value) { + *((volatile uint8_t*)ptr) = value; +} -#define mmio_store(_view, _reg, _val) \ - ({ \ - auto _mmio_val = _val; \ - if ((_reg).swapped) \ - _Generic( \ - (_mmio_val), \ - char: (void)(_mmio_val), \ - uint8_t: (void)(_mmio_val), \ - uint16_t: (_mmio_val = bswap_16(_mmio_val)), \ - uint32_t: (_mmio_val = bswap_32(_mmio_val)), \ - uint64_t: (_mmio_val = bswap_64(_mmio_val)) \ - ); \ - auto _mmio_ptr = _Generic( \ - (_reg), \ - mmio_reg8: (volatile uint8_t*)((_view)->base + (_reg).offset), \ - mmio_reg16: (volatile uint16_t*)((_view)->base + (_reg).offset), \ - mmio_reg32: (volatile uint32_t*)((_view)->base + (_reg).offset), \ - mmio_reg64: (volatile uint64_t*)((_view)->base + (_reg).offset) \ - ); \ - *_mmio_ptr = _mmio_val; \ - }) +static inline void mmio_write16(void* ptr, uint16_t value) { + *((volatile uint16_t*)ptr) = value; +} -struct mmio_view mmio_new(phys_t addr, size_t length); -void mmio_free(struct mmio_view* view); +static inline void mmio_write32(void* ptr, uint32_t value) { + *((volatile uint32_t*)ptr) = value; +} + +static inline void mmio_write64(void* ptr, uint64_t value) { + *((volatile uint64_t*)ptr) = value; +} diff --git a/include/zinnia/percpu.h b/include/zinnia/percpu.h index af2399c..d054e5b 100644 --- a/include/zinnia/percpu.h +++ b/include/zinnia/percpu.h @@ -7,7 +7,7 @@ #include #include -ASSERT_TYPE(struct arch_percpu); +ASSERT_TYPE(struct arch_percpu); // bits/percpu.h // CPU-relative information. struct percpu { @@ -21,23 +21,10 @@ struct percpu { struct sched_percpu sched; // Scheduler information. }; +struct percpu* percpu_new(); +struct percpu* percpu_get(); +void percpu_bsp_init(); +void percpu_init(); + // Per-CPU data for the bootstrap processor. extern struct percpu percpu_bsp; - -// Allocates a block of memory for a new CPU. -struct percpu* percpu_new(); - -// Gets the per-CPU data on the current CPU. -static inline struct percpu* percpu_get() { - return arch_percpu_get(); -} - -// Initializes the bootstrap processor. -static inline void percpu_bsp_init() { - arch_percpu_bsp_init(); -} - -// Initializes all processors. -static inline void percpu_init() { - arch_percpu_init(); -} diff --git a/include/zinnia/pmap.h b/include/zinnia/pmap.h index 5182eb8..cbf3804 100644 --- a/include/zinnia/pmap.h +++ b/include/zinnia/pmap.h @@ -4,7 +4,7 @@ #include #include #include -#include +#include enum pte_flags : uint8_t { PTE_READ = 1 << 0, // Can read from this page. @@ -28,8 +28,8 @@ struct pmap { bool is_user; }; -errno_t pmap_kernel(struct pmap* pt, enum alloc_flags flags); -errno_t pmap_user(struct pmap* pt, enum alloc_flags flags); +errno_t pmap_new_kernel(struct pmap* pt, enum alloc_flags flags); +errno_t pmap_new_user(struct pmap* pt, enum alloc_flags flags); errno_t pmap_map(struct pmap* pt, uintptr_t vaddr, phys_t paddr, enum pte_flags flags, enum cache_mode cache); errno_t pmap_protect(struct pmap* pt, uintptr_t vaddr, enum pte_flags flags); errno_t pmap_unmap(struct pmap* pt, uintptr_t vaddr); diff --git a/include/zinnia/print.h b/include/zinnia/print.h index e843405..6081d73 100644 --- a/include/zinnia/print.h +++ b/include/zinnia/print.h @@ -7,3 +7,12 @@ void kprintf(const char* message, ...); void kvprintf(const char* message, va_list args); + +#include +#include + +#define log(category, message, ...) \ + do { \ + uint64_t _time = clock_get_elapsed_ns(); \ + kprintf("[%5lu.%06lu] \e[1;34m" category ":\e[0m " message, _time / 1'000'000'000, _time % 1'000'000, ##__VA_ARGS__); \ + } while (0) diff --git a/include/zinnia/sched.h b/include/zinnia/sched.h index 77d1ab5..553e773 100644 --- a/include/zinnia/sched.h +++ b/include/zinnia/sched.h @@ -26,8 +26,7 @@ enum task_state { struct task { size_t id; char name[TASK_NAME_MAX]; - struct vas* space; - struct namespace* namespace; + struct vma* space; enum task_state state; struct arch_task_context context; struct usercopy_region* usercopy_region; @@ -59,14 +58,7 @@ void sched_wake_all(struct sched_percpu* sched, struct wait_queue* wq); typedef void (*task_fn_t)(uintptr_t arg0); -errno_t task_create( - const char* name, - struct vas* space, - struct namespace* ns, - 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); [[noreturn]] void task_entry(task_fn_t entry, uintptr_t arg0); diff --git a/include/zinnia/syscall.h b/include/zinnia/syscall.h index c9469ff..afff80d 100644 --- a/include/zinnia/syscall.h +++ b/include/zinnia/syscall.h @@ -2,32 +2,25 @@ #include -enum syscall_kind : uint8_t { - SYSKIND_CALL = 0, // Regular call, returns error and/or value. - SYSKIND_CONTEXT, // Consumes the entire register image. -}; - -struct syscall_return { +struct syscall_ret { uintptr_t value; int errno; }; struct syscall { - union { - struct syscall_return (*call)(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); - void (*context)(struct arch_context*); - }; - enum syscall_kind kind; + void* func; + int num_args; }; -struct syscall_return syscall_dispatch_call( - size_t num, +[[gnu::no_caller_saved_registers]] +struct syscall_ret syscall_dispatch_fast( uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, - uintptr_t a5 + uintptr_t a5, + size_t num ); void syscall_dispatch(struct arch_context* ctx); diff --git a/include/zinnia/syscall_list.h b/include/zinnia/syscall_list.h index 97d3ddd..0e1e608 100644 --- a/include/zinnia/syscall_list.h +++ b/include/zinnia/syscall_list.h @@ -2,155 +2,151 @@ #include #include -#include -#define __SYSCALL_CALL(name) \ - struct syscall_return sys_##name(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t) +#define SYSCALL_DECLARE(name) extern void sys_##name() -#define __SYSCALL_CONTEXT(name) void sys_##name(struct arch_context*) - -__SYSCALL_CALL(exit); -__SYSCALL_CALL(syslog); -__SYSCALL_CALL(getuname); -__SYSCALL_CALL(setuname); -__SYSCALL_CALL(archctl); -__SYSCALL_CALL(reboot); -__SYSCALL_CALL(mmap); -__SYSCALL_CALL(munmap); -__SYSCALL_CALL(mprotect); -__SYSCALL_CALL(madvise); -__SYSCALL_CALL(sigprocmask); -__SYSCALL_CALL(sigsuspend); -__SYSCALL_CALL(sigpending); -__SYSCALL_CALL(sigaction); -__SYSCALL_CALL(sigtimedwait); -__SYSCALL_CALL(sigaltstack); -__SYSCALL_CALL(sigreturn); -__SYSCALL_CALL(sigqueue); -__SYSCALL_CALL(execve); -__SYSCALL_CALL(fexecve); -__SYSCALL_CONTEXT(fork); -__SYSCALL_CALL(kill); -__SYSCALL_CALL(gettid); -__SYSCALL_CALL(getpid); -__SYSCALL_CALL(getppid); -__SYSCALL_CALL(waitid); -__SYSCALL_CALL(waitpid); -__SYSCALL_CALL(pread); -__SYSCALL_CALL(readv); -__SYSCALL_CALL(pwrite); -__SYSCALL_CALL(writev); -__SYSCALL_CALL(seek); -__SYSCALL_CALL(ioctl); -__SYSCALL_CALL(openat); -__SYSCALL_CALL(close); -__SYSCALL_CALL(fstat); -__SYSCALL_CALL(fstatat); -__SYSCALL_CALL(statvfs); -__SYSCALL_CALL(fstatvfs); -__SYSCALL_CALL(faccessat); -__SYSCALL_CALL(fcntl); -__SYSCALL_CALL(ftruncate); -__SYSCALL_CALL(truncate); -__SYSCALL_CALL(fallocate); -__SYSCALL_CALL(fadvise); -__SYSCALL_CALL(utimensat); -__SYSCALL_CALL(mknodat); -__SYSCALL_CALL(getcwd); -__SYSCALL_CALL(chdir); -__SYSCALL_CALL(fchdir); -__SYSCALL_CALL(mkdirat); -__SYSCALL_CALL(rmdirat); -__SYSCALL_CALL(getdents); -__SYSCALL_CALL(renameat); -__SYSCALL_CALL(fchmod); -__SYSCALL_CALL(fchmodat); -__SYSCALL_CALL(fchownat); -__SYSCALL_CALL(linkat); -__SYSCALL_CALL(symlinkat); -__SYSCALL_CALL(unlinkat); -__SYSCALL_CALL(readlinkat); -__SYSCALL_CALL(flock); -__SYSCALL_CALL(ppoll); -__SYSCALL_CALL(dup); -__SYSCALL_CALL(dup3); -__SYSCALL_CALL(sync); -__SYSCALL_CALL(fsync); -__SYSCALL_CALL(fdatasync); -__SYSCALL_CALL(getgroups); -__SYSCALL_CALL(setgroups); -__SYSCALL_CALL(getsid); -__SYSCALL_CALL(setsid); -__SYSCALL_CALL(setuid); -__SYSCALL_CALL(getuid); -__SYSCALL_CALL(setgid); -__SYSCALL_CALL(getgid); -__SYSCALL_CALL(geteuid); -__SYSCALL_CALL(seteuid); -__SYSCALL_CALL(getegid); -__SYSCALL_CALL(setegid); -__SYSCALL_CALL(getpgid); -__SYSCALL_CALL(setpgid); -__SYSCALL_CALL(getresuid); -__SYSCALL_CALL(setresuid); -__SYSCALL_CALL(getresgid); -__SYSCALL_CALL(setresgid); -__SYSCALL_CALL(setreuid); -__SYSCALL_CALL(setregid); -__SYSCALL_CALL(umask); -__SYSCALL_CALL(pipe); -__SYSCALL_CALL(futex_wait); -__SYSCALL_CALL(futex_wake); -__SYSCALL_CALL(thread_create); -__SYSCALL_CALL(thread_kill); -__SYSCALL_CALL(thread_exit); -__SYSCALL_CALL(thread_setname); -__SYSCALL_CALL(thread_getname); -__SYSCALL_CALL(timer_create); -__SYSCALL_CALL(timer_set); -__SYSCALL_CALL(timer_get); -__SYSCALL_CALL(timer_getoverrun); -__SYSCALL_CALL(timer_delete); -__SYSCALL_CALL(itimer_get); -__SYSCALL_CALL(itimer_set); -__SYSCALL_CALL(clock_get); -__SYSCALL_CALL(clock_getres); -__SYSCALL_CALL(clock_set); -__SYSCALL_CALL(sleep); -__SYSCALL_CALL(yield); -__SYSCALL_CALL(chroot); -__SYSCALL_CALL(mount); -__SYSCALL_CALL(umount); -__SYSCALL_CALL(socket); -__SYSCALL_CALL(socketpair); -__SYSCALL_CALL(shutdown); -__SYSCALL_CALL(bind); -__SYSCALL_CALL(connect); -__SYSCALL_CALL(accept); -__SYSCALL_CALL(listen); -__SYSCALL_CALL(getpeername); -__SYSCALL_CALL(getsockname); -__SYSCALL_CALL(getsockopt); -__SYSCALL_CALL(setsockopt); -__SYSCALL_CALL(sendmsg); -__SYSCALL_CALL(recvmsg); -__SYSCALL_CALL(getentropy); -__SYSCALL_CALL(getrusage); -__SYSCALL_CALL(getrlimit); -__SYSCALL_CALL(setrlimit); -__SYSCALL_CALL(getpriority); -__SYSCALL_CALL(setpriority); -__SYSCALL_CALL(sched_getparam); -__SYSCALL_CALL(sched_setparam); -__SYSCALL_CALL(module_insert); -__SYSCALL_CALL(module_remove); -__SYSCALL_CALL(epoll_create); -__SYSCALL_CALL(epoll_ctl); -__SYSCALL_CALL(epoll_pwait); -__SYSCALL_CALL(timerfd_create); -__SYSCALL_CALL(timerfd_gettime); -__SYSCALL_CALL(timerfd_settime); -__SYSCALL_CALL(signalfd_create); -__SYSCALL_CALL(eventfd_create); -__SYSCALL_CALL(msync); -__SYSCALL_CALL(sysconf); +SYSCALL_DECLARE(exit); +SYSCALL_DECLARE(syslog); +SYSCALL_DECLARE(getuname); +SYSCALL_DECLARE(setuname); +SYSCALL_DECLARE(archctl); +SYSCALL_DECLARE(reboot); +SYSCALL_DECLARE(mmap); +SYSCALL_DECLARE(munmap); +SYSCALL_DECLARE(mprotect); +SYSCALL_DECLARE(madvise); +SYSCALL_DECLARE(sigprocmask); +SYSCALL_DECLARE(sigsuspend); +SYSCALL_DECLARE(sigpending); +SYSCALL_DECLARE(sigaction); +SYSCALL_DECLARE(sigtimedwait); +SYSCALL_DECLARE(sigaltstack); +SYSCALL_DECLARE(sigreturn); +SYSCALL_DECLARE(sigqueue); +SYSCALL_DECLARE(execve); +SYSCALL_DECLARE(fexecve); +SYSCALL_DECLARE(fork); +SYSCALL_DECLARE(kill); +SYSCALL_DECLARE(gettid); +SYSCALL_DECLARE(getpid); +SYSCALL_DECLARE(getppid); +SYSCALL_DECLARE(waitid); +SYSCALL_DECLARE(waitpid); +SYSCALL_DECLARE(pread); +SYSCALL_DECLARE(readv); +SYSCALL_DECLARE(pwrite); +SYSCALL_DECLARE(writev); +SYSCALL_DECLARE(seek); +SYSCALL_DECLARE(ioctl); +SYSCALL_DECLARE(openat); +SYSCALL_DECLARE(close); +SYSCALL_DECLARE(fstat); +SYSCALL_DECLARE(fstatat); +SYSCALL_DECLARE(statvfs); +SYSCALL_DECLARE(fstatvfs); +SYSCALL_DECLARE(faccessat); +SYSCALL_DECLARE(fcntl); +SYSCALL_DECLARE(ftruncate); +SYSCALL_DECLARE(truncate); +SYSCALL_DECLARE(fallocate); +SYSCALL_DECLARE(fadvise); +SYSCALL_DECLARE(utimensat); +SYSCALL_DECLARE(mknodat); +SYSCALL_DECLARE(getcwd); +SYSCALL_DECLARE(chdir); +SYSCALL_DECLARE(fchdir); +SYSCALL_DECLARE(mkdirat); +SYSCALL_DECLARE(rmdirat); +SYSCALL_DECLARE(getdents); +SYSCALL_DECLARE(renameat); +SYSCALL_DECLARE(fchmod); +SYSCALL_DECLARE(fchmodat); +SYSCALL_DECLARE(fchownat); +SYSCALL_DECLARE(linkat); +SYSCALL_DECLARE(symlinkat); +SYSCALL_DECLARE(unlinkat); +SYSCALL_DECLARE(readlinkat); +SYSCALL_DECLARE(flock); +SYSCALL_DECLARE(ppoll); +SYSCALL_DECLARE(dup); +SYSCALL_DECLARE(dup3); +SYSCALL_DECLARE(sync); +SYSCALL_DECLARE(fsync); +SYSCALL_DECLARE(fdatasync); +SYSCALL_DECLARE(getgroups); +SYSCALL_DECLARE(setgroups); +SYSCALL_DECLARE(getsid); +SYSCALL_DECLARE(setsid); +SYSCALL_DECLARE(setuid); +SYSCALL_DECLARE(getuid); +SYSCALL_DECLARE(setgid); +SYSCALL_DECLARE(getgid); +SYSCALL_DECLARE(geteuid); +SYSCALL_DECLARE(seteuid); +SYSCALL_DECLARE(getegid); +SYSCALL_DECLARE(setegid); +SYSCALL_DECLARE(getpgid); +SYSCALL_DECLARE(setpgid); +SYSCALL_DECLARE(getresuid); +SYSCALL_DECLARE(setresuid); +SYSCALL_DECLARE(getresgid); +SYSCALL_DECLARE(setresgid); +SYSCALL_DECLARE(setreuid); +SYSCALL_DECLARE(setregid); +SYSCALL_DECLARE(umask); +SYSCALL_DECLARE(pipe); +SYSCALL_DECLARE(futex_wait); +SYSCALL_DECLARE(futex_wake); +SYSCALL_DECLARE(thread_create); +SYSCALL_DECLARE(thread_kill); +SYSCALL_DECLARE(thread_exit); +SYSCALL_DECLARE(thread_setname); +SYSCALL_DECLARE(thread_getname); +SYSCALL_DECLARE(timer_create); +SYSCALL_DECLARE(timer_set); +SYSCALL_DECLARE(timer_get); +SYSCALL_DECLARE(timer_getoverrun); +SYSCALL_DECLARE(timer_delete); +SYSCALL_DECLARE(itimer_get); +SYSCALL_DECLARE(itimer_set); +SYSCALL_DECLARE(clock_get); +SYSCALL_DECLARE(clock_getres); +SYSCALL_DECLARE(clock_set); +SYSCALL_DECLARE(sleep); +SYSCALL_DECLARE(yield); +SYSCALL_DECLARE(chroot); +SYSCALL_DECLARE(mount); +SYSCALL_DECLARE(umount); +SYSCALL_DECLARE(socket); +SYSCALL_DECLARE(socketpair); +SYSCALL_DECLARE(shutdown); +SYSCALL_DECLARE(bind); +SYSCALL_DECLARE(connect); +SYSCALL_DECLARE(accept); +SYSCALL_DECLARE(listen); +SYSCALL_DECLARE(getpeername); +SYSCALL_DECLARE(getsockname); +SYSCALL_DECLARE(getsockopt); +SYSCALL_DECLARE(setsockopt); +SYSCALL_DECLARE(sendmsg); +SYSCALL_DECLARE(recvmsg); +SYSCALL_DECLARE(getentropy); +SYSCALL_DECLARE(getrusage); +SYSCALL_DECLARE(getrlimit); +SYSCALL_DECLARE(setrlimit); +SYSCALL_DECLARE(getpriority); +SYSCALL_DECLARE(setpriority); +SYSCALL_DECLARE(sched_getparam); +SYSCALL_DECLARE(sched_setparam); +SYSCALL_DECLARE(module_insert); +SYSCALL_DECLARE(module_remove); +SYSCALL_DECLARE(epoll_create); +SYSCALL_DECLARE(epoll_ctl); +SYSCALL_DECLARE(epoll_pwait); +SYSCALL_DECLARE(timerfd_create); +SYSCALL_DECLARE(timerfd_gettime); +SYSCALL_DECLARE(timerfd_settime); +SYSCALL_DECLARE(signalfd_create); +SYSCALL_DECLARE(eventfd_create); +SYSCALL_DECLARE(msync); +SYSCALL_DECLARE(sysconf); diff --git a/include/zinnia/types.h b/include/zinnia/types.h index 0bd2a7b..5c55828 100644 --- a/include/zinnia/types.h +++ b/include/zinnia/types.h @@ -1,8 +1,7 @@ #pragma once -#include #include +#include ASSERT_TYPE(phys_t); -ASSERT_TYPE(uintptr_t); -ASSERT_TYPE(reg_t); +ASSERT_TYPE(virt_t); diff --git a/include/zinnia/usercopy.h b/include/zinnia/usercopy.h index 3a9b48d..b9f343c 100644 --- a/include/zinnia/usercopy.h +++ b/include/zinnia/usercopy.h @@ -1,7 +1,7 @@ #pragma once -#include #include +#include struct usercopy_region { void (*start_ip)(); diff --git a/include/zinnia/vas.h b/include/zinnia/vas.h deleted file mode 100644 index e277423..0000000 --- a/include/zinnia/vas.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -// Virtual address space. -struct vas { - // Architecture-specific virtual memory map implementation. - struct pmap pmap; -}; - -// Try to create a new, empty virtual address space. -errno_t vma_new(struct vas** out); - -// Delete a virtual address space. -void vma_delete(struct vas* vm); - -errno_t vma_map_vmo(struct vas* vm, struct vmo* vmo, uintptr_t addr, size_t len, enum flags, uintptr_t vmo_offset); - -// Remove any mappings in the given address range. -errno_t vma_unmap(struct vas* vm, uintptr_t vaddr, size_t size); - -// Change the protection of an existing mapping. -errno_t vma_protect(struct vas* vm, uintptr_t vaddr, size_t size, enum zn_vm_flags flags); - -// Try to handle a page fault. -bool vma_page_fault(struct vas* vm, uintptr_t vaddr, enum zn_vm_flags access_type); - -extern struct vas kernel_vas; diff --git a/include/zinnia/vfs.h b/include/zinnia/vfs.h index 2f09743..05368e4 100644 --- a/include/zinnia/vfs.h +++ b/include/zinnia/vfs.h @@ -7,35 +7,6 @@ #include #include -struct vfs_mount { - struct refcount rc; -}; - -struct vfs_entry { - struct refcount rc; -}; - -struct vfs_path { - struct vfs_mount* mount; - struct vfs_entry* entry; -}; - -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); -}; - -struct vfs_node { - struct refcount rc; - const struct vfs_regular_ops* ops; - struct vfs_vnode* vnode; - struct vfs_path path; - const char* abs_path; - bool has_path; -}; - enum open_flags : uint32_t { O_RDONLY = __O_RDONLY, O_WRONLY = __O_WRONLY, @@ -62,3 +33,34 @@ enum open_flags : uint32_t { O_SEARCH = __O_SEARCH, O_ACCMODE = __O_ACCMODE, }; + +struct vfs_mount { + struct refcount rc; + // TODO +}; + +struct vfs_entry { + struct refcount rc; + // TODO +}; + +struct vfs_path { + struct vfs_mount* mount; + struct vfs_entry* entry; +}; + +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); +}; + +struct vfs_node { + struct refcount rc; + const struct vfs_regular_ops* ops; + struct vfs_vnode* vnode; + struct vfs_path path; + const char* abs_path; + bool has_path; +}; diff --git a/include/zinnia/page.h b/include/zinnia/virt.h similarity index 71% rename from include/zinnia/page.h rename to include/zinnia/virt.h index e67048c..5690cb1 100644 --- a/include/zinnia/page.h +++ b/include/zinnia/virt.h @@ -1,5 +1,7 @@ #pragma once +#include +#include #include #include @@ -21,10 +23,18 @@ struct page { static_assert(0x1000 % sizeof(struct page) == 0, "struct must fit cleanly inside a page!"); static_assert(sizeof(struct page) <= 64, "struct must be smaller than 64 bytes!"); -void* vm_alloc(size_t length); -void vm_free(void* addr, size_t length); - // Base address of the `struct page` array. extern struct page* vm_pfndb; uintptr_t vm_page_addr(struct page* page); + +// Allocator for virtual memory. +struct vm_alloc { + virt_t start_page; + virt_t end_page; + virt_t next_fit; + hashmap(int, void); +}; + +uintptr_t vm_alloc(size_t length); +void vm_free(uintptr_t addr, size_t length); diff --git a/include/zinnia/vma.h b/include/zinnia/vma.h new file mode 100644 index 0000000..4359fbb --- /dev/null +++ b/include/zinnia/vma.h @@ -0,0 +1,48 @@ +#pragma once + +#include +#include +#include +#include +#include + +// Virtual address space. +struct vma { + // Architecture-specific virtual memory map implementation. + struct pmap pmap; +}; + +// Try to create a new, empty virtual address space. +errno_t vma_new(struct vma** out); + +// Delete a virtual address space. +void vma_free(struct vma* v); + +errno_t vma_map( + struct vma* vm, + struct vmo* vmo, + uintptr_t addr, + size_t len, + enum prot_flags flags, + uintptr_t vmo_offset +); + +// Remove any mappings in the given address range. +errno_t vma_unmap(struct vma* v, uintptr_t vaddr, size_t size); + +// Change the protection of an existing mapping. +errno_t vma_protect(struct vma* v, uintptr_t vaddr, size_t size, enum prot_flags flags); + +struct vma_fault_info { + uintptr_t ip; + uintptr_t addr; + bool caused_by_user; + bool caused_by_write; + bool caused_by_fetch; + bool page_was_present; +}; + +// Try to handle a page fault. +bool vma_page_fault(struct vma* v, const struct vma_fault_info* info); + +extern struct vma kernel_vma; diff --git a/include/zinnia/object.h b/include/zinnia/vmo.h similarity index 98% rename from include/zinnia/object.h rename to include/zinnia/vmo.h index 916aaec..fd6dae1 100644 --- a/include/zinnia/object.h +++ b/include/zinnia/vmo.h @@ -2,8 +2,8 @@ #include #include -#include #include +#include #include #include diff --git a/mem/mmio.c b/mem/mmio.c deleted file mode 100644 index ca3c47c..0000000 --- a/mem/mmio.c +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include -#include -#include -#include - -void* mmio_new(phys_t addr, size_t length) { - void* ptr = vm_alloc(length); - for (size_t i = 0; i < length; i += arch_mem_page_size()) { - - if (pmap_map(&kernel_vas.pmap, (uintptr_t)ptr + i, addr + i, PTE_READ | PTE_WRITE, CACHE_MMIO)) { - vm_free(ptr, length); - return nullptr; - } - } - - return ptr; -} - -void mmio_free(void* ptr, size_t length) { - // TODO -} diff --git a/meson.build b/meson.build index 8014aa7..0b29930 100644 --- a/meson.build +++ b/meson.build @@ -89,25 +89,20 @@ kernel_includes = [ kernel_sources = [] +# Goes first so we can add arch-specific flags to drivers. +subdir('arch' / target_machine.cpu_family()) +subdir('boot') +subdir('core') + +# Device and file system drivers. +subdir('dev') +subdir('fs') + 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()) - -subdir('device') -subdir('fs') - -subdir('boot') -subdir('mem') -subdir('core') -subdir('syscalls') - -subdir('lib') - executable( 'zinnia', include_directories: [ @@ -121,5 +116,5 @@ executable( kernel_sources, ], install: true, - install_dir: '/boot', + install_dir: get_option('datadir') / 'zinnia', ) diff --git a/syscalls/dispatch.c b/syscalls/dispatch.c deleted file mode 100644 index 36ab742..0000000 --- a/syscalls/dispatch.c +++ /dev/null @@ -1,185 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -const struct syscall syscall_table[256] = { - [0] = {.call = sys_exit}, - [1] = {.call = sys_syslog}, - [2] = {.call = sys_getuname}, - [3] = {.call = sys_setuname}, - [4] = {.call = sys_archctl}, - [5] = {.call = sys_reboot}, - [6] = {.call = sys_mmap}, - [7] = {.call = sys_munmap}, - [8] = {.call = sys_mprotect}, - [9] = {.call = sys_madvise}, - [10] = {.call = sys_sigprocmask}, - [11] = {.call = sys_sigsuspend}, - [12] = {.call = sys_sigpending}, - [13] = {.call = sys_sigaction}, - [14] = {.call = sys_sigtimedwait}, - [15] = {.call = sys_sigaltstack}, - [16] = {.call = sys_sigreturn}, - [17] = {.call = sys_sigqueue}, - [18] = {.call = sys_execve}, - [19] = {.call = sys_fexecve}, - [20] = {.context = sys_fork, SYSKIND_CONTEXT}, - [21] = {.call = sys_kill}, - [22] = {.call = sys_gettid}, - [23] = {.call = sys_getpid}, - [24] = {.call = sys_getppid}, - [25] = {.call = sys_waitid}, - [26] = {.call = sys_waitpid}, - [27] = {.call = sys_pread}, - [28] = {.call = sys_readv}, - [29] = {.call = sys_pwrite}, - [30] = {.call = sys_writev}, - [31] = {.call = sys_seek}, - [32] = {.call = sys_ioctl}, - [33] = {.call = sys_openat}, - [34] = {.call = sys_close}, - [35] = {.call = sys_fstat}, - [36] = {.call = sys_fstatat}, - [37] = {.call = sys_statvfs}, - [38] = {.call = sys_fstatvfs}, - [39] = {.call = sys_faccessat}, - [40] = {.call = sys_fcntl}, - [41] = {.call = sys_ftruncate}, - [42] = {.call = sys_truncate}, - [43] = {.call = sys_fallocate}, - [44] = {.call = sys_fadvise}, - [45] = {.call = sys_utimensat}, - [46] = {.call = sys_mknodat}, - [47] = {.call = sys_getcwd}, - [48] = {.call = sys_chdir}, - [49] = {.call = sys_fchdir}, - [50] = {.call = sys_mkdirat}, - [51] = {.call = sys_rmdirat}, - [52] = {.call = sys_getdents}, - [53] = {.call = sys_renameat}, - [54] = {.call = sys_fchmod}, - [55] = {.call = sys_fchmodat}, - [56] = {.call = sys_fchownat}, - [57] = {.call = sys_linkat}, - [58] = {.call = sys_symlinkat}, - [59] = {.call = sys_unlinkat}, - [60] = {.call = sys_readlinkat}, - [61] = {.call = sys_flock}, - [62] = {.call = sys_ppoll}, - [63] = {.call = sys_dup}, - [64] = {.call = sys_dup3}, - [65] = {.call = sys_sync}, - [66] = {.call = sys_fsync}, - [67] = {.call = sys_fdatasync}, - [68] = {.call = sys_getgroups}, - [69] = {.call = sys_setgroups}, - [70] = {.call = sys_getsid}, - [71] = {.call = sys_setsid}, - [72] = {.call = sys_setuid}, - [73] = {.call = sys_getuid}, - [74] = {.call = sys_setgid}, - [75] = {.call = sys_getgid}, - [76] = {.call = sys_geteuid}, - [77] = {.call = sys_seteuid}, - [78] = {.call = sys_getegid}, - [79] = {.call = sys_setegid}, - [80] = {.call = sys_getpgid}, - [81] = {.call = sys_setpgid}, - [82] = {.call = sys_getresuid}, - [83] = {.call = sys_setresuid}, - [84] = {.call = sys_getresgid}, - [85] = {.call = sys_setresgid}, - [86] = {.call = sys_setreuid}, - [87] = {.call = sys_setregid}, - [88] = {.call = sys_umask}, - [89] = {.call = sys_pipe}, - [90] = {.call = sys_futex_wait}, - [91] = {.call = sys_futex_wake}, - [92] = {.call = sys_thread_create}, - [93] = {.call = sys_thread_kill}, - [94] = {.call = sys_thread_exit}, - [95] = {.call = sys_thread_setname}, - [96] = {.call = sys_thread_getname}, - [97] = {.call = sys_timer_create}, - [98] = {.call = sys_timer_set}, - [99] = {.call = sys_timer_get}, - [100] = {.call = sys_timer_getoverrun}, - [101] = {.call = sys_timer_delete}, - [102] = {.call = sys_itimer_get}, - [103] = {.call = sys_itimer_set}, - [104] = {.call = sys_clock_get}, - [105] = {.call = sys_clock_getres}, - [106] = {.call = sys_clock_set}, - [107] = {.call = sys_sleep}, - [108] = {.call = sys_yield}, - [109] = {.call = sys_chroot}, - [110] = {.call = sys_mount}, - [111] = {.call = sys_umount}, - [112] = {.call = sys_socket}, - [113] = {.call = sys_socketpair}, - [114] = {.call = sys_shutdown}, - [115] = {.call = sys_bind}, - [116] = {.call = sys_connect}, - [117] = {.call = sys_accept}, - [118] = {.call = sys_listen}, - [119] = {.call = sys_getpeername}, - [120] = {.call = sys_getsockname}, - [121] = {.call = sys_getsockopt}, - [122] = {.call = sys_setsockopt}, - [123] = {.call = sys_sendmsg}, - [124] = {.call = sys_recvmsg}, - [125] = {.call = sys_getentropy}, - [126] = {.call = sys_getrusage}, - [127] = {.call = sys_getrlimit}, - [128] = {.call = sys_setrlimit}, - [129] = {.call = sys_getpriority}, - [130] = {.call = sys_setpriority}, - [131] = {.call = sys_sched_getparam}, - [132] = {.call = sys_sched_setparam}, - [133] = {.call = sys_module_insert}, - [134] = {.call = sys_module_remove}, - [135] = {.call = sys_epoll_create}, - [136] = {.call = sys_epoll_ctl}, - [137] = {.call = sys_epoll_pwait}, - [138] = {.call = sys_timerfd_create}, - [139] = {.call = sys_timerfd_gettime}, - [140] = {.call = sys_timerfd_settime}, - [141] = {.call = sys_signalfd_create}, - [142] = {.call = sys_eventfd_create}, - [143] = {.call = sys_msync}, - [144] = {.call = sys_sysconf}, -}; - -struct syscall_return syscall_dispatch_call( - size_t num, - uintptr_t a0, - uintptr_t a1, - uintptr_t a2, - uintptr_t a3, - uintptr_t a4, - uintptr_t a5 -) { - // No need to check the table size here. In order to get to this point, - // we already have to check if this is a fast syscall. - if (syscall_table[num].call == nullptr) { - return (struct syscall_return){.errno = ENOSYS}; - } - - return syscall_table[num].call(a0, a1, a2, a3, a4, a5); -} - -void syscall_dispatch(struct arch_context* ctx) { - const size_t num = ctx->ARCH_CTX_NUM; - - if (num >= ARRAY_SIZE(syscall_table) || syscall_table[num].context == nullptr) { - ctx->ARCH_CTX_RET0 = ENOSYS; - return; - } - - syscall_table[num].context(ctx); -}