x86_64: implement syscall instruction init and dispatch

This commit is contained in:
2026-02-08 12:47:28 +00:00
parent 4de1463e7c
commit 9e223ca5d0

View File

@@ -1,4 +1,5 @@
#include <arch/irq.h>
#include <arch/msr.h>
#include <arch/ports.h>
#include <mango/cpu.h>
#include <mango/libc/string.h>
@@ -20,6 +21,27 @@ static struct idt idt;
static int idt_initialised = 0;
static uintptr_t int_entry_points[NR_IDT_ENTRIES];
static void set_syscall_gate(uintptr_t rip)
{
uint64_t user_cs = 0x13;
uint64_t kernel_cs = 0x8;
uintptr_t star_reg = 0xC0000081;
uintptr_t lstar_reg = 0xC0000082;
uintptr_t sfmask_reg = 0xC0000084;
uint64_t selectors = 0;
selectors |= (user_cs) << 48;
selectors |= (kernel_cs) << 32;
/* disable interrupts */
uint64_t flag_mask = 0x200;
wrmsr(star_reg, selectors);
wrmsr(lstar_reg, rip);
wrmsr(sfmask_reg, flag_mask);
}
static void set_idt_gate(
struct idt *idt,
uint8_t index,
@@ -65,33 +87,6 @@ static void pf_handler(struct ml_cpu_context *regs)
regs->err_no);
}
#if 0
static void set_syscall_gate(uintptr_t rip)
{
/* sysret adds 0x10 to this to get cs, and 0x8 to get ss
* note that the CPU should force the RPL to 3 when loading
* the selector by using user_cs | 3. However, this doesn't happen
* in certain scenarios (specifically, QEMU + KVM on a Ryzen 5 1600X). */
uint64_t user_cs = 0x13;
uint64_t kernel_cs = 0x8;
uintptr_t star_reg = 0xC0000081;
uintptr_t lstar_reg = 0xC0000082;
uintptr_t sfmask_reg = 0xC0000084;
uint64_t selectors = 0;
selectors |= (user_cs) << 48;
selectors |= (kernel_cs) << 32;
/* disable interrupts */
uint64_t flag_mask = 0x200;
write_msr(star_reg, selectors);
write_msr(lstar_reg, rip);
write_msr(sfmask_reg, flag_mask);
}
#endif
static void init_pic(void)
{
// Remap the PIC
@@ -180,6 +175,36 @@ void irq_dispatch(struct ml_cpu_context *regs)
void syscall_dispatch(struct ml_cpu_context *regs)
{
unsigned int sysid = regs->rax;
virt_addr_t syscall_impl = 0; // TODO
if (syscall_impl == 0) {
regs->rax = KERN_UNSUPPORTED;
return;
}
#define SYSCALL_SIGNATURE(...) \
intptr_t (*__VA_ARGS__)( \
uintptr_t, \
uintptr_t, \
uintptr_t, \
uintptr_t, \
uintptr_t, \
uintptr_t, \
uintptr_t, \
uintptr_t)
SYSCALL_SIGNATURE(fn) = (SYSCALL_SIGNATURE())syscall_impl;
regs->rax
= fn(regs->rdi,
regs->rsi,
regs->rdx,
regs->r12,
regs->r8,
regs->r9,
regs->r13,
regs->r14);
}
void hook_irq(enum irq_vector vec, struct irq_hook *hook)