cleanup
This commit is contained in:
+17
-4
@@ -1,19 +1,32 @@
|
||||
#include <zinnia/errno.h>
|
||||
#include <zinnia/syscall.h>
|
||||
#include <arch/archctl.h>
|
||||
#include <arch/mem.h>
|
||||
#include <uapi/archctl.h>
|
||||
#include <x86_64/asm.h>
|
||||
#include <x86_64/defs.h>
|
||||
|
||||
errno_t arch_archctl(uintptr_t op, uintptr_t arg) {
|
||||
struct syscall_ret arch_archctl(uintptr_t op, uintptr_t arg) {
|
||||
struct syscall_ret ret = {};
|
||||
|
||||
switch (op) {
|
||||
case __ARCHCTL_SET_FSBASE:
|
||||
if (!arch_mem_addr_is_user(arg)) {
|
||||
ret.errno = EINVAL;
|
||||
return ret;
|
||||
}
|
||||
asm_wrmsr(MSR_FS_BASE, arg);
|
||||
return 0;
|
||||
return ret;
|
||||
case __ARCHCTL_SET_GSBASE:
|
||||
if (!arch_mem_addr_is_user(arg)) {
|
||||
ret.errno = EINVAL;
|
||||
return ret;
|
||||
}
|
||||
// Update the inactive GSBASE MSR, not ours.
|
||||
asm_wrmsr(MSR_KERNEL_GS_BASE, arg);
|
||||
return 0;
|
||||
return ret;
|
||||
default:
|
||||
return EINVAL;
|
||||
ret.errno = EINVAL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -4,10 +4,11 @@
|
||||
#include <x86_64/asm.h>
|
||||
#include <x86_64/defs.h>
|
||||
#include <x86_64/gdt.h>
|
||||
#include <x86_64/percpu.h>
|
||||
#include <x86_64/tss.h>
|
||||
|
||||
static const struct gdt main_gdt = {
|
||||
.null = {.val = 0},
|
||||
.null = {0},
|
||||
.kernel_code32 = {.val = 0x00cf9b000000ffff},
|
||||
.kernel_data32 = {.val = 0x00cf93000000ffff},
|
||||
.kernel_code64 = {.val = 0x00a09b0000000000},
|
||||
@@ -24,10 +25,10 @@ static const struct gdt main_gdt = {
|
||||
};
|
||||
|
||||
void gdt_load() {
|
||||
struct gdt* gdt = &percpu_get()->arch.gdt;
|
||||
struct gdt* gdt = &percpu_ref(arch_data)->gdt;
|
||||
memcpy(gdt, &main_gdt, sizeof(main_gdt));
|
||||
|
||||
struct tss* tss = &percpu_get()->arch.tss;
|
||||
struct tss* tss = &percpu_ref(arch_data)->tss;
|
||||
tss->iopb = sizeof(struct tss);
|
||||
|
||||
uintptr_t tss_addr = (uintptr_t)tss;
|
||||
|
||||
+4
-2
@@ -12,6 +12,7 @@
|
||||
#include <x86_64/apic.h>
|
||||
#include <x86_64/defs.h>
|
||||
#include <x86_64/gdt.h>
|
||||
#include <x86_64/percpu.h>
|
||||
|
||||
struct [[__packed]] idt_entry {
|
||||
uint16_t base0;
|
||||
@@ -34,6 +35,7 @@ static_assert(sizeof(struct idtr) == 10);
|
||||
|
||||
void interrupt_handler(struct arch_context* ctx) {
|
||||
struct percpu* cpu = percpu_get();
|
||||
struct arch_percpu* arch_cpu = percpu_ref(arch_data);
|
||||
bool old = irq_set_interrupted(true);
|
||||
|
||||
uint64_t isr = ctx->isr;
|
||||
@@ -46,12 +48,12 @@ void interrupt_handler(struct arch_context* ctx) {
|
||||
case IDT_IPI_RESCHED:
|
||||
arch_sched_preempt_disable();
|
||||
if (arch_sched_preempt_enable()) {
|
||||
lapic_eoi(&cpu->arch.lapic);
|
||||
lapic_eoi(&arch_cpu->lapic);
|
||||
sched_reschedule(&cpu->sched);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
struct irq_line* line = cpu->arch.irq_lines[isr - 0x20];
|
||||
struct irq_line* line = arch_cpu->irq_lines[isr - 0x20];
|
||||
assert(line, "Unhandled interrupt on ISR %lu\n", isr);
|
||||
// TODO: irq_raise(line);
|
||||
}
|
||||
|
||||
@@ -16,3 +16,5 @@ struct arch_percpu {
|
||||
void (*fpu_restore)(const void*);
|
||||
bool can_smap;
|
||||
};
|
||||
|
||||
extern struct arch_percpu arch_data;
|
||||
@@ -1,4 +1,5 @@
|
||||
#include <zinnia/types.h>
|
||||
#include <arch/mem.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -29,3 +30,7 @@ uintptr_t arch_mem_pfndb_addr() {
|
||||
uintptr_t arch_mem_mapping_addr() {
|
||||
return 0xFFFF'C000'0000'0000;
|
||||
}
|
||||
|
||||
bool arch_mem_addr_is_user(uintptr_t addr) {
|
||||
return addr < 0x0000'8000'0000'0000;
|
||||
}
|
||||
|
||||
+16
-10
@@ -8,6 +8,7 @@
|
||||
#include <x86_64/gdt.h>
|
||||
#include <x86_64/hpet.h>
|
||||
#include <x86_64/idt.h>
|
||||
#include <x86_64/percpu.h>
|
||||
#include <x86_64/syscall.h>
|
||||
#include <x86_64/tsc.h>
|
||||
|
||||
@@ -39,11 +40,16 @@ union ia32_star {
|
||||
|
||||
static_assert(sizeof(union ia32_star) == 8);
|
||||
|
||||
[[__percpu]]
|
||||
struct arch_percpu arch_data = {0};
|
||||
|
||||
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);
|
||||
|
||||
struct arch_percpu* arch_cpu = percpu_ref(arch_data);
|
||||
|
||||
gdt_load();
|
||||
|
||||
// TODO: not if FRED
|
||||
@@ -88,13 +94,13 @@ static void setup_cpu(struct percpu* cpu) {
|
||||
|
||||
asm_wrxcr(0, xcr0);
|
||||
|
||||
cpu->arch.fpu_size = cpuid13.ecx;
|
||||
cpu->arch.fpu_save = asm_xsave;
|
||||
cpu->arch.fpu_restore = asm_xrstor;
|
||||
arch_cpu->fpu_size = cpuid13.ecx;
|
||||
arch_cpu->fpu_save = asm_xsave;
|
||||
arch_cpu->fpu_restore = asm_xrstor;
|
||||
} else {
|
||||
cpu->arch.fpu_size = 512;
|
||||
cpu->arch.fpu_save = asm_fxsave;
|
||||
cpu->arch.fpu_restore = asm_fxrstor;
|
||||
arch_cpu->fpu_size = 512;
|
||||
arch_cpu->fpu_save = asm_fxsave;
|
||||
arch_cpu->fpu_restore = asm_fxrstor;
|
||||
}
|
||||
|
||||
if (cpuid7.ecx & CPUID_7C_UMIP)
|
||||
@@ -105,16 +111,16 @@ static void setup_cpu(struct percpu* cpu) {
|
||||
|
||||
if (cpuid7.ebx & CPUID_7B_SMAP) {
|
||||
cr4 |= CR4_SMAP;
|
||||
cpu->arch.can_smap = true;
|
||||
arch_cpu->can_smap = true;
|
||||
}
|
||||
|
||||
if (cpuid7.ebx & CPUID_7B_FSGSBASE)
|
||||
cr4 |= CR4_FSGSBASE;
|
||||
|
||||
asm volatile("mov %0, cr0" : "=r"(cr0));
|
||||
asm volatile("mov %0, cr4" : "=r"(cr4));
|
||||
asm volatile("mov cr0, %0" ::"r"(cr0));
|
||||
asm volatile("mov cr4, %0" ::"r"(cr4));
|
||||
|
||||
lapic_init(&cpu->arch.lapic);
|
||||
lapic_init(&arch_cpu->lapic);
|
||||
cpu->online = true;
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -13,6 +13,7 @@
|
||||
#include <x86_64/defs.h>
|
||||
#include <x86_64/gdt.h>
|
||||
#include <x86_64/idt.h>
|
||||
#include <x86_64/percpu.h>
|
||||
|
||||
// The task frame consists of registers that the C ABI marks as callee-saved.
|
||||
// If we don't save them, these registers are lost during a context switch.
|
||||
@@ -53,7 +54,7 @@ static struct task* perform_switch(uint64_t* old_rsp, uint64_t new_rsp, struct t
|
||||
}
|
||||
|
||||
struct task* arch_sched_switch(struct task* from, struct task* to) {
|
||||
struct arch_percpu* cpu = &percpu_get()->arch;
|
||||
struct arch_percpu* cpu = percpu_ref(arch_data);
|
||||
struct arch_task_context* from_ctx = &from->context;
|
||||
struct arch_task_context* to_ctx = &to->context;
|
||||
|
||||
@@ -108,7 +109,7 @@ errno_t arch_task_init(
|
||||
uintptr_t stack_start,
|
||||
bool is_user
|
||||
) {
|
||||
struct arch_percpu* cpu = &percpu_get()->arch;
|
||||
struct arch_percpu* cpu = percpu_ref(arch_data);
|
||||
|
||||
// Prepare a dummy stack with an entry point function to return to.
|
||||
struct task_frame* frame = (struct task_frame*)stack_start - 1;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <bits/sched.h>
|
||||
#include <stddef.h>
|
||||
#include <x86_64/defs.h>
|
||||
#include <x86_64/gdt.h>
|
||||
|
||||
// TODO: Refactor to only push callee-saved registers.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user