rsp -> Context.

master
WangRunji 7 years ago
parent 37d2497de3
commit b715cecf8d

@ -63,7 +63,7 @@ impl TrapFrame {
#[derive(Debug, Default)] #[derive(Debug, Default)]
#[repr(C)] #[repr(C)]
struct Context { struct ContextData {
r15: usize, r15: usize,
r14: usize, r14: usize,
r13: usize, r13: usize,
@ -73,9 +73,9 @@ struct Context {
rip: usize, rip: usize,
} }
impl Context { impl ContextData {
fn new() -> Self { fn new() -> Self {
let mut context = Context::default(); let mut context = ContextData::default();
context.rip = forkret as usize; context.rip = forkret as usize;
context context
} }
@ -85,7 +85,7 @@ impl Context {
#[derive(Debug)] #[derive(Debug)]
#[repr(C)] #[repr(C)]
pub struct InitStack { pub struct InitStack {
context: Context, context: ContextData,
trapret: usize, trapret: usize,
tf: TrapFrame, tf: TrapFrame,
} }
@ -93,21 +93,21 @@ pub struct InitStack {
impl InitStack { impl InitStack {
pub fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, rsp: usize) -> Self { pub fn new_kernel_thread(entry: extern fn(usize) -> !, arg: usize, rsp: usize) -> Self {
InitStack { InitStack {
context: Context::new(), context: ContextData::new(),
trapret: trap_ret as usize, trapret: trap_ret as usize,
tf: TrapFrame::new_kernel_thread(entry, arg, rsp), tf: TrapFrame::new_kernel_thread(entry, arg, rsp),
} }
} }
pub fn new_user_thread(entry_addr: usize, rsp: usize, is32: bool) -> Self { pub fn new_user_thread(entry_addr: usize, rsp: usize, is32: bool) -> Self {
InitStack { InitStack {
context: Context::new(), context: ContextData::new(),
trapret: trap_ret as usize, trapret: trap_ret as usize,
tf: TrapFrame::new_user_thread(entry_addr, rsp, is32), tf: TrapFrame::new_user_thread(entry_addr, rsp, is32),
} }
} }
pub fn new_fork(tf: &TrapFrame) -> Self { pub fn new_fork(tf: &TrapFrame) -> Self {
InitStack { InitStack {
context: Context::new(), context: ContextData::new(),
trapret: trap_ret as usize, trapret: trap_ret as usize,
tf: { tf: {
let mut tf = tf.clone(); let mut tf = tf.clone();
@ -116,6 +116,11 @@ impl InitStack {
}, },
} }
} }
pub unsafe fn push_at(self, stack_top: usize) -> Context {
let ptr = (stack_top as *mut Self).offset(-1);
*ptr = self;
Context(ptr as usize)
}
} }
extern { extern {
@ -128,41 +133,50 @@ extern fn forkret() {
// Will return to `trapret` // Will return to `trapret`
} }
/// Switch to another kernel thread. #[derive(Debug)]
/// pub struct Context(usize);
/// Defined in `trap.asm`.
/// impl Context {
/// Push all callee-saved registers at the current kernel stack. /// Switch to another kernel thread.
/// Store current rsp at `from_rsp`. Switch kernel stack to `to_rsp`. ///
/// Pop all callee-saved registers, then return to the target. /// Defined in `trap.asm`.
#[naked] ///
#[inline(never)] /// Push all callee-saved registers at the current kernel stack.
pub unsafe extern fn switch(from_rsp: &mut usize, to_rsp: usize) { /// Store current rsp, switch to target.
asm!( /// Pop all callee-saved registers, then return to the target.
" #[naked]
// push rip (by caller) #[inline(never)]
pub unsafe extern fn switch(&mut self, target: &mut Self) {
// Save old callee-save registers asm!(
push rbx "
push rbp // push rip (by caller)
push r12
push r13 // Save old callee-save registers
push r14 push rbx
push r15 push rbp
push r12
// Switch stacks push r13
mov [rdi], rsp // rdi = from_rsp push r14
mov rsp, rsi // rsi = to_rsp push r15
// Save old callee-save registers // Switch stacks
pop r15 mov [rdi], rsp // rdi = from_rsp
pop r14 mov rsp, [rsi] // rsi = to_rsp
pop r13
pop r12 // Save old callee-save registers
pop rbp pop r15
pop rbx pop r14
pop r13
// pop rip pop r12
ret" pop rbp
: : : : "intel" "volatile" ) pop rbx
// pop rip
ret"
: : : : "intel" "volatile" )
}
pub unsafe fn null() -> Self {
Context(0)
}
} }

@ -10,11 +10,11 @@ pub struct Process {
pub(in process) pid: Pid, pub(in process) pid: Pid,
pub(in process) parent: Pid, pub(in process) parent: Pid,
pub(in process) name: String, pub(in process) name: String,
kstack: Stack, kstack: Stack,
pub(in process) memory_set: Option<MemorySet>, pub(in process) memory_set: Option<MemorySet>,
pub(in process) page_table: Option<InactivePageTable>, pub(in process) page_table: Option<InactivePageTable>,
pub(in process) status: Status, pub(in process) status: Status,
pub(in process) rsp: usize, pub(in process) context: Context,
pub(in process) is_user: bool, pub(in process) is_user: bool,
} }
@ -35,7 +35,7 @@ impl Process {
pub fn new(name: &str, entry: extern fn(usize) -> !, arg: usize, mc: &mut MemoryController) -> Self { pub fn new(name: &str, entry: extern fn(usize) -> !, arg: usize, mc: &mut MemoryController) -> Self {
let kstack = mc.alloc_stack(7).unwrap(); let kstack = mc.alloc_stack(7).unwrap();
let data = InitStack::new_kernel_thread(entry, arg, kstack.top()); let data = InitStack::new_kernel_thread(entry, arg, kstack.top());
let rsp = kstack.push_at_top(data); let context = unsafe { data.push_at(kstack.top()) };
Process { Process {
pid: 0, pid: 0,
@ -45,7 +45,7 @@ impl Process {
memory_set: None, memory_set: None,
page_table: None, page_table: None,
status: Status::Ready, status: Status::Ready,
rsp, context,
is_user: false, is_user: false,
} }
} }
@ -62,7 +62,7 @@ impl Process {
memory_set: None, memory_set: None,
page_table: None, page_table: None,
status: Status::Running, status: Status::Running,
rsp: 0, // will be set at first schedule context: unsafe { Context::null() }, // will be set at first schedule
is_user: false, is_user: false,
} }
} }
@ -120,9 +120,8 @@ impl Process {
// Allocate kernel stack and push trap frame // Allocate kernel stack and push trap frame
let kstack = mc.alloc_stack(7).unwrap(); let kstack = mc.alloc_stack(7).unwrap();
let tf = InitStack::new_user_thread(entry_addr, user_stack_top - 8, is32); let data = InitStack::new_user_thread(entry_addr, user_stack_top - 8, is32);
let rsp = kstack.push_at_top(tf); let context = unsafe { data.push_at(kstack.top()) };
trace!("rsp = {:#x}", rsp);
Process { Process {
pid: 0, pid: 0,
@ -132,7 +131,7 @@ impl Process {
memory_set: Some(memory_set), memory_set: Some(memory_set),
page_table: Some(page_table), page_table: Some(page_table),
status: Status::Ready, status: Status::Ready,
rsp, context,
is_user: true, is_user: true,
} }
} }
@ -161,7 +160,7 @@ impl Process {
// Allocate kernel stack and push trap frame // Allocate kernel stack and push trap frame
let kstack = mc.alloc_stack(7).unwrap(); let kstack = mc.alloc_stack(7).unwrap();
let data = InitStack::new_fork(tf); let data = InitStack::new_fork(tf);
let rsp = kstack.push_at_top(data); let context = unsafe { data.push_at(kstack.top()) };
Process { Process {
pid: 0, pid: 0,
@ -171,7 +170,7 @@ impl Process {
memory_set: Some(memory_set), memory_set: Some(memory_set),
page_table: Some(page_table), page_table: Some(page_table),
status: Status::Ready, status: Status::Ready,
rsp, context,
is_user: true, is_user: true,
} }
} }

@ -153,12 +153,12 @@ impl Processor {
*from_pt = Some(old_table); *from_pt = Some(old_table);
} }
info!("switch from {} to {}\n rsp: ??? -> {:#x}", pid0, pid, to.rsp); info!("switch from {} to {}\n rsp: ??? -> {:?}", pid0, pid, to.context);
unsafe { unsafe {
// FIXME: safely pass MutexGuard // FIXME: safely pass MutexGuard
use core::mem::forget; use core::mem::forget;
super::PROCESSOR.try().unwrap().force_unlock(); super::PROCESSOR.try().unwrap().force_unlock();
switch(&mut from.rsp, to.rsp); from.context.switch(&mut to.context);
forget(super::PROCESSOR.try().unwrap().lock()); forget(super::PROCESSOR.try().unwrap().lock());
} }
} }

Loading…
Cancel
Save