mirror of
https://github.com/rcore-os/rCore.git
synced 2024-11-23 08:26:17 +04:00
Fix set TSS in SMP
This commit is contained in:
parent
2f71eab39b
commit
ffb7e194f9
@ -35,6 +35,9 @@ pub fn start_ap(apicid: u8, addr: u32) {
|
|||||||
|
|
||||||
pub fn lapic_id() -> u8 {
|
pub fn lapic_id() -> u8 {
|
||||||
unsafe{
|
unsafe{
|
||||||
|
if lapic.is_null() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
(*(lapic as *const u32).offset(0x0020/4) >> 24) as u8
|
(*(lapic as *const u32).offset(0x0020/4) >> 24) as u8
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -3,9 +3,10 @@ use core::fmt::Debug;
|
|||||||
use x86_64::structures::tss::TaskStateSegment;
|
use x86_64::structures::tss::TaskStateSegment;
|
||||||
use x86_64::structures::gdt::SegmentSelector;
|
use x86_64::structures::gdt::SegmentSelector;
|
||||||
use x86_64::{PrivilegeLevel, VirtualAddress};
|
use x86_64::{PrivilegeLevel, VirtualAddress};
|
||||||
use spin::Once;
|
use spin::{Once, Mutex, MutexGuard};
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use core::ptr::Unique;
|
use arch::driver::apic::lapic_id;
|
||||||
|
use consts::MAX_CPU_NUM;
|
||||||
|
|
||||||
/// Alloc TSS & GDT at kernel heap, then init and load it.
|
/// Alloc TSS & GDT at kernel heap, then init and load it.
|
||||||
/// The double fault stack will be allocated at kernel heap too.
|
/// The double fault stack will be allocated at kernel heap too.
|
||||||
@ -26,8 +27,7 @@ pub fn init() {
|
|||||||
|
|
||||||
tss
|
tss
|
||||||
});
|
});
|
||||||
unsafe{ TSS_PTR = Unique::new_unchecked(Box::into_raw(tss)); }
|
let tss = Box::into_raw(tss);
|
||||||
let tss = unsafe{ TSS_PTR.as_ref() };
|
|
||||||
|
|
||||||
let gdt = Box::new({
|
let gdt = Box::new({
|
||||||
let mut gdt = Gdt::new();
|
let mut gdt = Gdt::new();
|
||||||
@ -37,7 +37,7 @@ pub fn init() {
|
|||||||
gdt.add_entry(UDATA);
|
gdt.add_entry(UDATA);
|
||||||
gdt.add_entry(UCODE32);
|
gdt.add_entry(UCODE32);
|
||||||
gdt.add_entry(UDATA32);
|
gdt.add_entry(UDATA32);
|
||||||
gdt.add_entry(Descriptor::tss_segment(&tss));
|
gdt.add_entry(Descriptor::tss_segment(unsafe { &*tss }));
|
||||||
gdt
|
gdt
|
||||||
});
|
});
|
||||||
let gdt = unsafe{ &*Box::into_raw(gdt) };
|
let gdt = unsafe{ &*Box::into_raw(gdt) };
|
||||||
@ -49,19 +49,35 @@ pub fn init() {
|
|||||||
// load TSS
|
// load TSS
|
||||||
load_tss(TSS_SELECTOR);
|
load_tss(TSS_SELECTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CPUS[lapic_id() as usize].call_once(||
|
||||||
|
Mutex::new(Cpu { gdt, tss: unsafe { &mut *tss } }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: more elegant?
|
static CPUS: [Once<Mutex<Cpu>>; MAX_CPU_NUM] = [
|
||||||
static mut TSS_PTR: Unique<TaskStateSegment> = unsafe{ Unique::new_unchecked(0 as *mut _) };
|
// TODO: More elegant ?
|
||||||
|
Once::new(), Once::new(), Once::new(), Once::new(),
|
||||||
|
Once::new(), Once::new(), Once::new(), Once::new(),
|
||||||
|
];
|
||||||
|
|
||||||
|
pub struct Cpu {
|
||||||
|
gdt: &'static Gdt,
|
||||||
|
tss: &'static mut TaskStateSegment,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cpu {
|
||||||
|
pub fn current() -> MutexGuard<'static, Cpu> {
|
||||||
|
CPUS[lapic_id() as usize].try().unwrap().lock()
|
||||||
|
}
|
||||||
|
|
||||||
/// 设置从Ring3跳到Ring0时,自动切换栈的地址
|
/// 设置从Ring3跳到Ring0时,自动切换栈的地址
|
||||||
///
|
///
|
||||||
/// 每次进入用户态前,都要调用此函数,才能保证正确返回内核态
|
/// 每次进入用户态前,都要调用此函数,才能保证正确返回内核态
|
||||||
pub fn set_ring0_rsp(rsp: usize) {
|
pub fn set_ring0_rsp(&mut self, rsp: usize) {
|
||||||
trace!("gdt.set_ring0_rsp: {:#x}", rsp);
|
trace!("gdt.set_ring0_rsp: {:#x}", rsp);
|
||||||
unsafe {
|
unsafe {
|
||||||
TSS_PTR.as_mut().privilege_stack_table[0] = VirtualAddress(rsp);
|
self.tss.privilege_stack_table[0] = VirtualAddress(rsp);
|
||||||
trace!("TSS:\n{:?}", TSS_PTR.as_ref());
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,10 +126,10 @@ pub extern fn rust_trap(tf: &mut TrapFrame) -> usize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn set_return_rsp(tf: &TrapFrame) {
|
fn set_return_rsp(tf: &TrapFrame) {
|
||||||
use arch::gdt;
|
use arch::gdt::Cpu;
|
||||||
use core::mem::size_of;
|
use core::mem::size_of;
|
||||||
if tf.cs & 0x3 == 3 {
|
if tf.cs & 0x3 == 3 {
|
||||||
gdt::set_ring0_rsp(tf as *const _ as usize + size_of::<TrapFrame>());
|
Cpu::current().set_ring0_rsp(tf as *const _ as usize + size_of::<TrapFrame>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,8 +81,7 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) -> ! {
|
|||||||
|addr: usize| memory_controller.map_page_identity(addr));
|
|addr: usize| memory_controller.map_page_identity(addr));
|
||||||
// memory_controller.print_page_table();
|
// memory_controller.print_page_table();
|
||||||
|
|
||||||
// FIXME: 开启SMP后,导致switch_to_user中设置rsp无效
|
arch::smp::start_other_cores(&acpi, &mut memory_controller);
|
||||||
// arch::smp::start_other_cores(&acpi, &mut memory_controller);
|
|
||||||
process::init(memory_controller);
|
process::init(memory_controller);
|
||||||
|
|
||||||
fs::load_sfs();
|
fs::load_sfs();
|
||||||
|
Loading…
Reference in New Issue
Block a user