Commit 36820c03 authored by Jeremy Soller's avatar Jeremy Soller

Add somewhat magical code for syscall instruction

parent 931a7bb2
use arch::x86_64::pti;
use arch::{gdt, pti};
use syscall;
use x86::shared::msr;
pub unsafe fn init() {
msr::wrmsr(msr::IA32_STAR, ((gdt::GDT_KERNEL_CODE as u64) << 3) << 32);
msr::wrmsr(msr::IA32_LSTAR, syscall_instruction as u64);
msr::wrmsr(msr::IA32_FMASK, 1 << 9);
msr::wrmsr(msr::IA32_KERNEL_GS_BASE, &gdt::TSS as *const _ as u64);
let efer = msr::rdmsr(msr::IA32_EFER);
msr::wrmsr(msr::IA32_EFER, efer | 1);
}
#[naked]
pub unsafe extern fn syscall_instruction() {
#[inline(never)]
unsafe fn inner(stack: &mut SyscallStack) -> usize {
let rbp;
asm!("" : "={rbp}"(rbp) : : : "intel", "volatile");
syscall::syscall(stack.rax, stack.rdi, stack.rsi, stack.rdx, stack.r10, stack.r8, rbp, stack)
}
// Yes, this is magic. No, you don't need to understand
asm!("xchg bx, bx
swapgs // Set gs segment to TSS
mov gs:[28], rsp // Save userspace rsp
mov rsp, gs:[4] // Load kernel rsp
push 5 * 8 + 3 // Push userspace data segment
push qword ptr gs:[28] // Push userspace rsp
mov qword ptr gs:[28], 0 // Clear userspace rsp
push r11 // Push rflags
push 4 * 8 + 3 // Push userspace code segment
push rcx // Push userspace return pointer
swapgs // Restore gs
"
:
:
:
: "intel", "volatile");
// Push scratch registers
asm!("push rax
push rbx
push rcx
push rdx
push rdi
push rsi
push r8
push r9
push r10
push r11
push fs
mov r11, 0x18
mov fs, r11"
: : : : "intel", "volatile");
// Get reference to stack variables
let rsp: usize;
asm!("" : "={rsp}"(rsp) : : : "intel", "volatile");
// Map kernel
pti::map();
let a = inner(&mut *(rsp as *mut SyscallStack));
// Unmap kernel
pti::unmap();
asm!("" : : "{rax}"(a) : : "intel", "volatile");
// Interrupt return
asm!("pop fs
pop r11
pop r10
pop r9
pop r8
pop rsi
pop rdi
pop rdx
pop rcx
pop rbx
add rsp, 8
iretq"
: : : : "intel", "volatile");
}
#[naked]
pub unsafe extern fn syscall() {
......
......@@ -90,6 +90,9 @@ pub unsafe extern fn kstart(args_ptr: *const KernelArgs) -> ! {
// Set up IDT
idt::init_paging();
// Set up syscall instruction
interrupt::syscall::init();
// Test tdata and tbss
{
assert_eq!(TBSS_TEST_ZERO, 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment