x86_64: implement syscall instruction init and dispatch
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user