This commit is contained in:
2026-09-14 02:50:35 +02:00
parent cf3f1f9e99
commit 9e5ed517bc
45 changed files with 210 additions and 212 deletions
+12 -7
View File
@@ -2,6 +2,9 @@
#include <kernel/clock.h>
#include <kernel/mmio.h>
#include <kernel/percpu.h>
#include <kernel/pmap.h>
#include <kernel/vas.h>
#include <kernel/virt.h>
#include <assert.h>
#include <stdint.h>
#include <x86_64/apic.h>
@@ -12,11 +15,11 @@ 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 = lapic->xapic_regs[APIC_REG_ICR / sizeof(uint32_t)];
hi = lapic->xapic_regs[APIC_REG_ICR_HI / sizeof(uint32_t)];
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 lapic->xapic_regs[reg / sizeof(uint32_t)];
return mmio_read32(lapic->xapic_regs + reg);
}
} else {
return asm_rdmsr(0x800 + (reg >> 4));
@@ -26,10 +29,10 @@ static uint64_t lapic_read_reg(struct local_apic* lapic, uint32_t reg) {
static void lapic_write_reg(struct local_apic* lapic, uint32_t reg, uint64_t value) {
if (lapic->xapic_regs) {
if (reg == APIC_REG_ICR) {
lapic->xapic_regs[APIC_REG_ICR_HI / sizeof(uint32_t)] = value >> 32;
lapic->xapic_regs[APIC_REG_ICR / sizeof(uint32_t)] = value & 0xFFFF'FFFF;
mmio_write32(lapic->xapic_regs + APIC_REG_ICR_HI, value >> 32);
mmio_write32(lapic->xapic_regs + APIC_REG_ICR, (uint32_t)value);
} else {
lapic->xapic_regs[reg / sizeof(uint32_t)] = value & 0xFFFF'FFFF;
mmio_write32(lapic->xapic_regs + reg, (uint32_t)value);
}
} else {
asm_wrmsr(0x800 + (reg >> 4), value);
@@ -44,7 +47,9 @@ 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);
uintptr_t vaddr = vm_alloc(0x1000);
pmap_map(&kernel_vas.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");
}
+8 -2
View File
@@ -1,8 +1,10 @@
#include <common/utils.h>
#include <kernel/clock.h>
#include <kernel/cmdline.h>
#include <kernel/mmio.h>
#include <kernel/pmap.h>
#include <kernel/print.h>
#include <kernel/vas.h>
#include <kernel/virt.h>
#include <assert.h>
#include <uacpi/acpi.h>
#include <uacpi/status.h>
@@ -56,7 +58,11 @@ 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_vas.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);
-33
View File
@@ -1,33 +0,0 @@
#pragma once
#include <kernel/types.h>
#include <stddef.h>
#include <stdint.h>
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;
}
-9
View File
@@ -6,12 +6,6 @@
#include <x86_64/gdt.h>
#include <x86_64/tss.h>
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;
struct tss tss;
@@ -22,6 +16,3 @@ struct arch_percpu {
void (*fpu_restore)(const void*);
bool can_smap;
};
void arch_percpu_bsp_init();
void arch_percpu_init();
+1 -1
View File
@@ -5,7 +5,7 @@
struct local_apic {
uint32_t id;
uint32_t ticks_per_10ms;
volatile uint32_t* xapic_regs;
void* xapic_regs;
};
enum apic_delivery_mode {
@@ -1,21 +1,19 @@
#pragma once
#include <stdint.h>
#include <x86_64/defs.h>
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");
}
+31
View File
@@ -0,0 +1,31 @@
#include <kernel/types.h>
#include <stddef.h>
#include <stdint.h>
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;
}
+2
View File
@@ -9,6 +9,8 @@ kernel_sources += files(
'gdt.c',
'hpet.c',
'idt.c',
'irq.c',
'mem.c',
'percpu.c',
'pmap.c',
'sched.c',
+9 -1
View File
@@ -10,6 +10,12 @@
#include <x86_64/syscall.h>
#include <x86_64/tsc.h>
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);
@@ -33,9 +39,9 @@ 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();
idt_load();
@@ -49,6 +55,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));
+6 -5
View File
@@ -1,6 +1,7 @@
#include <zinnia/status.h>
#include <common/compiler.h>
#include <kernel/alloc.h>
#include <kernel/arch.h>
#include <kernel/percpu.h>
#include <kernel/sched.h>
#include <kernel/virt.h>
@@ -53,8 +54,8 @@ static void perform_switch(uint64_t* old_rsp, uint64_t new_rsp) {
void arch_sched_switch(struct task* from, struct task* to) {
struct arch_percpu* cpu = &percpu_get()->arch;
struct arch_task_context* from_ctx = &from->context;
struct arch_task_context* to_ctx = &to->context;
struct arch_task_context* from_ctx = &from->task_ctx;
struct arch_task_context* to_ctx = &to->task_ctx;
cpu->tss.rsp0 = to->kernel_stack + KERNEL_STACK_SIZE;
@@ -119,7 +120,7 @@ zn_status_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 ZN_ERR_NO_MEMORY;
for (size_t i = 0; i < fpu_size; i += arch_mem_page_size()) {
@@ -130,9 +131,9 @@ zn_status_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_vas.pmap, 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();
+6 -1
View File
@@ -1,6 +1,7 @@
#include <zinnia/archctl.h>
#include <zinnia/status.h>
#include <common/compiler.h>
#include <kernel/arch.h>
#include <kernel/init.h>
#include <kernel/percpu.h>
#include <x86_64/apic.h>
@@ -9,7 +10,7 @@
#include <x86_64/gdt.h>
[[__init, __naked, __used]]
void _start() {
void arch_start() {
asm volatile(
"lea rsp, [rip + %0]\n"
"jmp %1"
@@ -25,6 +26,10 @@ zn_status_t arch_archctl(zn_archctl_t op, uintptr_t arg) {
case ZN_ARCHCTL_SET_FSBASE:
asm_wrmsr(MSR_FS_BASE, arg);
return 0;
case ZN_ARCHCTL_SET_GSBASE:
// Slightly misleading, but KERNEL_GS_BASE is the currently inactive register.
asm_wrmsr(MSR_KERNEL_GS_BASE, arg);
return 0;
default:
return ZN_ERR_INVALID;
}
+4 -53
View File
@@ -18,7 +18,7 @@ bool arch_usercopy_read(void* dst, const __user void* src, size_t len, struct us
// Setup regs for `rep movsb`.
"xchg rcx, rdx\n"
"mov rax, [rip + %0]\n"
"mov [rdx], rax\n"
"xchg [rdx], rax\n"
".global x86_64_read_start\n"
"x86_64_read_start:\n"
@@ -35,7 +35,7 @@ bool arch_usercopy_read(void* dst, const __user void* src, size_t len, struct us
".global x86_64_read_fault\n"
"x86_64_read_fault:\n"
"xor rax, rax\n"
"mov [rdx], rax\n"
"xchg [rdx], rax\n"
"clac\n"
"ret\n"
:
@@ -61,7 +61,7 @@ bool arch_usercopy_write(__user void* dst, const void* src, size_t len, struct u
// Setup regs for `rep movsb`.
"xchg rcx, rdx\n"
"mov rax, [rip + %0]\n"
"mov [rdx], rax\n"
"xchg [rdx], rax\n"
".global x86_64_write_start\n"
"x86_64_write_start:\n"
@@ -78,7 +78,7 @@ bool arch_usercopy_write(__user void* dst, const void* src, size_t len, struct u
".global x86_64_write_fault\n"
"x86_64_write_fault:\n"
"xor rax, rax\n"
"mov [rdx], rax\n"
"xchg [rdx], rax\n"
"clac\n"
"ret\n"
:
@@ -86,52 +86,3 @@ bool arch_usercopy_write(__user void* dst, const void* src, size_t len, struct u
: "memory"
);
}
extern void x86_64_strlen_start();
extern void x86_64_strlen_end();
extern void x86_64_strlen_fault();
static const struct usercopy_region strlen_region = {
.start_ip = x86_64_strlen_start,
.end_ip = x86_64_strlen_end,
.fault_ip = x86_64_strlen_fault,
};
[[__naked]]
bool arch_usercopy_strlen(const __user char* str, size_t max, size_t* len, struct usercopy_region** region) {
asm volatile(
"stac\n"
"mov rax, [rip + %0]\n"
"mov [rcx], rax\n"
".global x86_64_strlen_start\n"
"x86_64_strlen_start:\n"
"xor r8, r8\n"
".Lloop:\n"
"cmp byte ptr [rdi + r8], 0\n"
"je .Lleave\n"
"inc r8\n"
"cmp rsi, r8\n"
"jne .Lloop\n"
".Lleave:\n"
"mov [rdx], r8\n"
".global x86_64_strlen_end\n"
"x86_64_strlen_end:\n"
"xor rax, rax\n"
"mov [rcx], rax\n"
"mov rax, 1\n"
"clac\n"
"ret\n"
".global x86_64_strlen_fault\n"
"x86_64_strlen_fault:\n"
"xor rax, rax\n"
"mov [rcx], rax\n"
"clac\n"
"ret\n"
:
: "i"(&strlen_region)
: "memory"
);
}