diff --git a/kernel/src/arch/x86_64/gdt.rs b/kernel/src/arch/x86_64/gdt.rs index e24ef98..0ae266e 100644 --- a/kernel/src/arch/x86_64/gdt.rs +++ b/kernel/src/arch/x86_64/gdt.rs @@ -36,6 +36,10 @@ pub struct Cpu { } impl Cpu { + pub fn current() -> &'static mut Self { + unsafe { CPUS[super::cpu::id()].as_mut().unwrap() } + } + fn new() -> Self { Cpu { gdt: GlobalDescriptorTable::new(), @@ -98,9 +102,18 @@ impl Cpu { set_cs(KCODE_SELECTOR); // load TSS load_tss(TSS_SELECTOR); - // store address of TSS to GSBase - let mut gsbase = Msr::new(0xC0000101); - gsbase.write(&self.tss as *const _ as u64); + // for fast syscall: + // store address of TSS to kernel_gsbase + let mut kernel_gsbase = Msr::new(0xC0000102); + kernel_gsbase.write(&self.tss as *const _ as u64); + } + + /// 设置从Ring3跳到Ring0时,自动切换栈的地址 + /// + /// 每次进入用户态前,都要调用此函数,才能保证正确返回内核态 + pub fn set_ring0_rsp(&mut self, rsp: usize) { + trace!("gdt.set_ring0_rsp: {:#x}", rsp); + self.tss.privilege_stack_table[0] = VirtAddr::new(rsp as u64); } } diff --git a/kernel/src/arch/x86_64/interrupt/handler.rs b/kernel/src/arch/x86_64/interrupt/handler.rs index d6fb976..2b5c099 100644 --- a/kernel/src/arch/x86_64/interrupt/handler.rs +++ b/kernel/src/arch/x86_64/interrupt/handler.rs @@ -229,3 +229,9 @@ fn invalid_opcode(tf: &mut TrapFrame) { fn error(tf: &TrapFrame) { crate::trap::error(tf); } + +#[no_mangle] +pub unsafe extern "C" fn set_return_rsp(tf: *const TrapFrame) { + use crate::arch::gdt::Cpu; + Cpu::current().set_ring0_rsp(tf.add(1) as usize); +} diff --git a/kernel/src/arch/x86_64/interrupt/trap.asm b/kernel/src/arch/x86_64/interrupt/trap.asm index 2f0424b..d20528d 100644 --- a/kernel/src/arch/x86_64/interrupt/trap.asm +++ b/kernel/src/arch/x86_64/interrupt/trap.asm @@ -49,10 +49,8 @@ __alltraps: .global trap_ret trap_ret: - # store kernel rsp -> TSS.sp0 mov rdi, rsp - add rdi, 720 - mov gs:[4], rdi + call set_return_rsp # pop fp state offset pop rcx @@ -106,6 +104,8 @@ syscall_entry: # - store rip -> rcx # - load rip + # swap in kernel gs + swapgs # store user rsp -> scratch at TSS.sp1 mov gs:[12], rsp # load kernel rsp <- TSS.sp0 @@ -119,8 +119,11 @@ syscall_entry: push 0 # error_code (dummy) push 0 # trap_num (dummy) + # swap out kernel gs + swapgs + # enable interrupt - sti + # sti push rax push rcx @@ -170,10 +173,8 @@ syscall_return: # disable interrupt cli - # store kernel rsp -> TSS.sp0 mov rdi, rsp - add rdi, 720 - mov gs:[4], rdi + call set_return_rsp # pop fp state offset pop rcx diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index b6b77fb..b92e5fd 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -16,7 +16,7 @@ pub mod rand; pub mod syscall; pub mod timer; -static AP_CAN_INIT: AtomicBool = AtomicBool::new(false); +static AP_CAN_INIT: AtomicBool = ATOMIC_BOOL_INIT; /// The entry point of kernel #[no_mangle] // don't mangle the name of this function