diff --git a/Makefile b/Makefile index 82e97b1..2a0f1d2 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -ARCH?=arm +ARCH?=x86_64 QEMU=qemu-system-$(ARCH) QEMUFLAGS=-serial mon:stdio -d guest_errors diff --git a/arch/x86_64/src/context.rs b/arch/x86_64/src/context.rs index cbfde75..8c06f18 100644 --- a/arch/x86_64/src/context.rs +++ b/arch/x86_64/src/context.rs @@ -1,3 +1,12 @@ +use core::mem; +use core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; + +/// This must be used by the kernel to ensure that context switches are done atomically +/// Compare and exchange this to true when beginning a context switch on any CPU +/// The Context::switch_to function will set it back to false, allowing other CPU's to switch +/// This must be done, as no locks can be held on the stack during switch +pub static CONTEXT_SWITCH_LOCK: AtomicBool = ATOMIC_BOOL_INIT; + #[derive(Debug)] pub struct Context { /// RFLAGS register @@ -35,6 +44,11 @@ impl Context { } } + pub fn set_stack(&mut self, address: usize) { + self.rsp = address; + } + + /// Switch to the next context by restoring its stack and registers #[inline(never)] #[naked] pub unsafe fn switch_to(&mut self, next: &mut Context) { @@ -68,15 +82,17 @@ impl Context { asm!("mov $0, r15" : "=r"(self.r15) : : "memory" : "intel", "volatile"); asm!("mov r15, $0" : : "r"(next.r15) : "memory" : "intel", "volatile"); - asm!("mov $0, rbp" : "=r"(self.rbp) : : "memory" : "intel", "volatile"); - asm!("mov rbp, $0" : : "r"(next.rbp) : "memory" : "intel", "volatile"); - asm!("mov $0, rsp" : "=r"(self.rsp) : : "memory" : "intel", "volatile"); asm!("mov rsp, $0" : : "r"(next.rsp) : "memory" : "intel", "volatile"); + asm!("mov $0, rbp" : "=r"(self.rbp) : : "memory" : "intel", "volatile"); + asm!("mov rbp, $0" : : "r"(next.rbp) : "memory" : "intel", "volatile"); + /* TODO asm!("mov $0, cr3" : "=r"(self.cr3) : : "memory" : "intel", "volatile"); asm!("mov cr3, $0" : : "r"(self.cr3) : "memory" : "intel", "volatile"); */ + + //CONTEXT_SWITCH_LOCK.store(false, Ordering::SeqCst); } } diff --git a/arch/x86_64/src/start.rs b/arch/x86_64/src/start.rs index 1b80e93..fb4ebd6 100644 --- a/arch/x86_64/src/start.rs +++ b/arch/x86_64/src/start.rs @@ -92,7 +92,7 @@ pub unsafe extern fn kstart() -> ! { } // Initialize display - display::init(&mut active_table); + //display::init(&mut active_table); // Reset AP variables AP_COUNT.store(0, Ordering::SeqCst); @@ -100,7 +100,7 @@ pub unsafe extern fn kstart() -> ! { HEAP_FRAME.store(0, Ordering::SeqCst); // Read ACPI tables, starts APs - acpi::init(&mut active_table); + //acpi::init(&mut active_table); // Map heap { diff --git a/kernel/context/mod.rs b/kernel/context/mod.rs index 3e5e849..5487780 100644 --- a/kernel/context/mod.rs +++ b/kernel/context/mod.rs @@ -1,6 +1,8 @@ //! Context management +use alloc::boxed::Box; use collections::{BTreeMap, Vec}; +use core::mem; use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering}; use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; @@ -61,6 +63,15 @@ impl ContextList { let context_lock = self.new_context()?; { let mut context = context_lock.write(); + let mut stack = Box::new([0; 4096]); + let offset = stack.len() - mem::size_of::(); + unsafe { + let offset = stack.len() - mem::size_of::(); + let func_ptr = stack.as_mut_ptr().offset(offset as isize); + *(func_ptr as *mut usize) = func as usize; + } + context.arch.set_stack(stack.as_ptr() as usize + offset); + context.kstack = Some(stack); print!("{}", format!("{}: {:X}\n", context.id, func as usize)); } Ok(context_lock) @@ -108,6 +119,8 @@ pub struct Context { pub id: usize, /// The architecture specific context pub arch: ArchContext, + /// Kernel stack + pub kstack: Option>, /// The open files in the scheme pub files: Vec> } @@ -118,6 +131,7 @@ impl Context { Context { id: id, arch: ArchContext::new(), + kstack: None, files: Vec::new() } } diff --git a/kernel/lib.rs b/kernel/lib.rs index 3b1d6eb..acdf028 100644 --- a/kernel/lib.rs +++ b/kernel/lib.rs @@ -134,8 +134,24 @@ pub extern fn kmain() { print!("{}", format!("BSP: {:?}\n", syscall::getpid())); - if let Ok(context) = context::contexts_mut().spawn(context_test) { + let to_ptr = if let Ok(context_lock) = context::contexts_mut().spawn(context_test) { + print!("Spawned context\n"); + let mut context = context_lock.write(); + &mut context.arch as *mut arch::context::Context + } else { + 0 as *mut arch::context::Context + }; + let from_ptr = if let Some(context_lock) = context::contexts().current() { + let mut context = context_lock.write(); + &mut context.arch as *mut arch::context::Context + } else { + 0 as *mut arch::context::Context + }; + + if to_ptr as usize != 0 && from_ptr as usize != 0 { + print!("Switching\n"); + unsafe { (&mut *from_ptr).switch_to(&mut *to_ptr); } } loop {