x86_64: enable interrupt during syscall. set TSS.sp0 through gs.

master
WangRunji 6 years ago
parent 5bc6395b23
commit 72efa797e5

@ -39,10 +39,6 @@ pub struct Cpu {
} }
impl Cpu { impl Cpu {
pub fn current() -> &'static mut Self {
unsafe { CPUS[super::cpu::id()].as_mut().unwrap() }
}
fn new() -> Self { fn new() -> Self {
Cpu { Cpu {
gdt: GlobalDescriptorTable::new(), gdt: GlobalDescriptorTable::new(),
@ -72,18 +68,9 @@ impl Cpu {
set_cs(KCODE_SELECTOR); set_cs(KCODE_SELECTOR);
// load TSS // load TSS
load_tss(TSS_SELECTOR); load_tss(TSS_SELECTOR);
// for fast syscall: // store address of TSS to GSBase
// store address of TSS to kernel_gsbase let mut gsbase = Msr::new(0xC0000101);
let mut kernel_gsbase = Msr::new(0xC0000102); gsbase.write(&self.tss as *const _ as u64);
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);
} }
} }

@ -213,9 +213,3 @@ fn invalid_opcode(tf: &mut TrapFrame) {
fn error(tf: &TrapFrame) { fn error(tf: &TrapFrame) {
crate::trap::error(tf); 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);
}

@ -49,8 +49,10 @@ __alltraps:
.global trap_ret .global trap_ret
trap_ret: trap_ret:
# store kernel rsp -> TSS.sp0
mov rdi, rsp mov rdi, rsp
call set_return_rsp add rdi, 720
mov gs:[4], rdi
# pop fp state offset # pop fp state offset
pop rcx pop rcx
@ -104,8 +106,6 @@ syscall_entry:
# - store rip -> rcx # - store rip -> rcx
# - load rip # - load rip
# swap in kernel gs
swapgs
# store user rsp -> scratch at TSS.sp1 # store user rsp -> scratch at TSS.sp1
mov gs:[12], rsp mov gs:[12], rsp
# load kernel rsp <- TSS.sp0 # load kernel rsp <- TSS.sp0
@ -119,11 +119,8 @@ syscall_entry:
push 0 # error_code (dummy) push 0 # error_code (dummy)
push 0 # trap_num (dummy) push 0 # trap_num (dummy)
# swap out kernel gs
swapgs
# enable interrupt # enable interrupt
# sti sti
push rax push rax
push rcx push rcx
@ -173,8 +170,10 @@ syscall_return:
# disable interrupt # disable interrupt
cli cli
# store kernel rsp -> TSS.sp0
mov rdi, rsp mov rdi, rsp
call set_return_rsp add rdi, 720
mov gs:[4], rdi
# pop fp state offset # pop fp state offset
pop rcx pop rcx

@ -15,7 +15,7 @@ pub mod rand;
pub mod syscall; pub mod syscall;
pub mod timer; pub mod timer;
static AP_CAN_INIT: AtomicBool = ATOMIC_BOOL_INIT; static AP_CAN_INIT: AtomicBool = AtomicBool::new(false);
/// The entry point of kernel /// The entry point of kernel
#[no_mangle] // don't mangle the name of this function #[no_mangle] // don't mangle the name of this function

Loading…
Cancel
Save