x86_64: implement syscall instruction init and dispatch
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
#include <arch/irq.h>
|
#include <arch/irq.h>
|
||||||
|
#include <arch/msr.h>
|
||||||
#include <arch/ports.h>
|
#include <arch/ports.h>
|
||||||
#include <mango/cpu.h>
|
#include <mango/cpu.h>
|
||||||
#include <mango/libc/string.h>
|
#include <mango/libc/string.h>
|
||||||
@@ -20,6 +21,27 @@ static struct idt idt;
|
|||||||
static int idt_initialised = 0;
|
static int idt_initialised = 0;
|
||||||
static uintptr_t int_entry_points[NR_IDT_ENTRIES];
|
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(
|
static void set_idt_gate(
|
||||||
struct idt *idt,
|
struct idt *idt,
|
||||||
uint8_t index,
|
uint8_t index,
|
||||||
@@ -65,33 +87,6 @@ static void pf_handler(struct ml_cpu_context *regs)
|
|||||||
regs->err_no);
|
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)
|
static void init_pic(void)
|
||||||
{
|
{
|
||||||
// Remap the PIC
|
// Remap the PIC
|
||||||
@@ -180,6 +175,36 @@ void irq_dispatch(struct ml_cpu_context *regs)
|
|||||||
|
|
||||||
void syscall_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)
|
void hook_irq(enum irq_vector vec, struct irq_hook *hook)
|
||||||
|
|||||||
Reference in New Issue
Block a user