From 7d28231f1b45bf53e4702cde2db08de0096591ad Mon Sep 17 00:00:00 2001 From: WangRunji Date: Fri, 27 Apr 2018 00:03:24 +0800 Subject: [PATCH] Can run into another kernel thread --- src/arch/x86_64/interrupt/handler.rs | 5 ++- src/arch/x86_64/interrupt/mod.rs | 2 + src/arch/x86_64/interrupt/template.rs | 15 +++++++ src/lib.rs | 6 +-- src/{test_util.rs => macros.rs} | 9 ++++ src/process.rs | 63 ++++++++++++++++++++------- 6 files changed, 81 insertions(+), 19 deletions(-) rename src/{test_util.rs => macros.rs} (73%) diff --git a/src/arch/x86_64/interrupt/handler.rs b/src/arch/x86_64/interrupt/handler.rs index c1d8cf0..c853026 100644 --- a/src/arch/x86_64/interrupt/handler.rs +++ b/src/arch/x86_64/interrupt/handler.rs @@ -2,6 +2,7 @@ #[path = "./template.rs"] mod template; use self::template::*; +pub type TrapFrame = InterruptStackP; interrupt_stack!(breakpoint, stack, { println!("\nEXCEPTION: Breakpoint"); @@ -60,12 +61,14 @@ interrupt!(com2, { use spin::Mutex; static TICK: Mutex = Mutex::new(0); -interrupt!(timer, { +interrupt_stack_p!(timer, stack, { let mut tick = TICK.lock(); *tick += 1; let tick = *tick; if tick % 100 == 0 { println!("\nInterupt: Timer\ntick = {}", tick); + use process; + process::schedule(stack); } ack(IRQ_TIMER); }); diff --git a/src/arch/x86_64/interrupt/mod.rs b/src/arch/x86_64/interrupt/mod.rs index 7bc24c0..efc692b 100644 --- a/src/arch/x86_64/interrupt/mod.rs +++ b/src/arch/x86_64/interrupt/mod.rs @@ -4,6 +4,8 @@ use arch::driver::{apic::IOAPIC, pic}; pub mod handler; pub mod consts; +pub use self::handler::TrapFrame; + #[inline(always)] pub unsafe fn enable() { x86_64::instructions::interrupts::enable(); diff --git a/src/arch/x86_64/interrupt/template.rs b/src/arch/x86_64/interrupt/template.rs index f323e7b..b1d73dd 100644 --- a/src/arch/x86_64/interrupt/template.rs +++ b/src/arch/x86_64/interrupt/template.rs @@ -2,6 +2,7 @@ #[allow(dead_code)] #[repr(packed)] +#[derive(Clone, Default)] pub struct ScratchRegisters { pub r11: usize, pub r10: usize, @@ -60,6 +61,7 @@ macro_rules! scratch_pop { #[allow(dead_code)] #[repr(packed)] +#[derive(Clone, Default)] pub struct PreservedRegisters { pub r15: usize, pub r14: usize, @@ -122,6 +124,7 @@ macro_rules! fs_pop { #[allow(dead_code)] #[repr(packed)] +#[derive(Clone, Default)] pub struct IretRegisters { pub rip: usize, pub cs: usize, @@ -282,6 +285,7 @@ macro_rules! interrupt_error { #[allow(dead_code)] #[repr(packed)] +#[derive(Clone, Default)] pub struct InterruptStackP { pub fs: usize, pub preserved: PreservedRegisters, @@ -298,6 +302,17 @@ impl InterruptStackP { } } +use core::fmt::Debug; +use core::fmt::Formatter; +use core::fmt::Error; + +impl Debug for InterruptStackP { + fn fmt(&self, f: &mut Formatter) -> Result<(), Error> { + self.dump(); + Ok(()) + } +} + #[macro_export] macro_rules! interrupt_stack_p { ($name:ident, $stack: ident, $func:block) => { diff --git a/src/lib.rs b/src/lib.rs index 1b997cc..78ed98d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -38,8 +38,8 @@ mod io; mod memory; mod lang; mod util; -#[macro_use] // test! -mod test_util; +#[macro_use] +mod macros; mod consts; mod process; @@ -77,7 +77,7 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) -> ! { // memory_controller.print_page_table(); arch::smp::start_other_cores(&acpi, &mut memory_controller); - process::init(memory_controller.kernel_stack.take().unwrap()); + process::init(&mut memory_controller); unsafe{ arch::interrupt::enable(); } diff --git a/src/test_util.rs b/src/macros.rs similarity index 73% rename from src/test_util.rs rename to src/macros.rs index 3e79aa3..3cfea74 100644 --- a/src/test_util.rs +++ b/src/macros.rs @@ -22,4 +22,13 @@ macro_rules! test { println!("Success: {}", stringify!($func)); } ) +} + +macro_rules! no_interrupt { + {$func:block} => { + use arch::interrupt; + unsafe{ interrupt::disable(); } + $func; + unsafe{ interrupt::enable(); } + }; } \ No newline at end of file diff --git a/src/process.rs b/src/process.rs index 9706526..b928dc1 100644 --- a/src/process.rs +++ b/src/process.rs @@ -1,9 +1,17 @@ use alloc::{boxed::Box, string::String, btree_map::BTreeMap}; -use memory::Stack; +use memory::{MemoryController, Stack}; +use arch::interrupt::TrapFrame; +use spin::{Once, Mutex}; -pub fn init(kstack: Stack) { - let processor = Box::new(Processor::new(kstack)); - Box::into_raw(processor); +pub fn init(mc: &mut MemoryController) { + PROCESSOR.call_once(|| {Mutex::new(Processor::new(mc))}); +} + +static PROCESSOR: Once> = Once::new(); + +/// Called by timer handler in arch +pub fn schedule(trap_frame: &mut TrapFrame) { + PROCESSOR.try().unwrap().lock().schedule(trap_frame); } #[derive(Debug)] @@ -13,12 +21,7 @@ pub struct Process { kstack: Stack, // page_table: Box, status: Status, - context: Context, -} - -#[derive(Debug)] -struct Context { - + trap_frame: TrapFrame, } #[derive(Debug)] @@ -28,23 +31,39 @@ enum Status { struct Processor { procs: BTreeMap>, + current_pid: Pid, } type Pid = usize; impl Processor { - fn new(kernel_stack: Stack) -> Self { + fn new(mc: &mut MemoryController) -> Self { let mut processor = Processor { procs: BTreeMap::>::new(), + current_pid: 0, }; let initproc = Box::new(Process{ pid: 0, name: String::from("initproc"), - kstack: kernel_stack, + kstack: mc.kernel_stack.take().unwrap(), status: Status::Running, - context: Context{}, + trap_frame: TrapFrame::default(), + }); + let idleproc = Box::new(Process{ + pid: 1, + name: String::from("idleproc"), + kstack: mc.alloc_stack(7).unwrap(), + status: Status::Ready, + trap_frame: { + let mut tf = TrapFrame::default(); + tf.iret.cs = 8; + tf.iret.rip = idle_thread as usize; + tf.iret.rflags = 0x282; + tf + }, }); processor.procs.insert(0, initproc); + processor.procs.insert(1, idleproc); processor } fn alloc_pid(&self) -> Pid { @@ -58,7 +77,21 @@ impl Processor { } return next; } - fn schedule(&self) { - + fn schedule(&mut self, trap_frame: &mut TrapFrame) { + self.run(1, trap_frame); + } + fn run(&mut self, pid: Pid, trap_frame: &mut TrapFrame) { + if pid == self.current_pid { + return; + } + let process = self.procs.get_mut(&pid).unwrap(); + self.current_pid = pid; + *trap_frame = process.trap_frame.clone(); + // TODO switch page table } +} + +extern fn idle_thread() { + println!("idle ..."); + loop {} } \ No newline at end of file