Simple, unsafe context switch
This commit is contained in:
parent
6715d5c534
commit
6e3f59ba8e
2
Makefile
2
Makefile
|
@ -1,4 +1,4 @@
|
||||||
ARCH?=arm
|
ARCH?=x86_64
|
||||||
|
|
||||||
QEMU=qemu-system-$(ARCH)
|
QEMU=qemu-system-$(ARCH)
|
||||||
QEMUFLAGS=-serial mon:stdio -d guest_errors
|
QEMUFLAGS=-serial mon:stdio -d guest_errors
|
||||||
|
|
|
@ -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)]
|
#[derive(Debug)]
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
/// RFLAGS register
|
/// 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)]
|
#[inline(never)]
|
||||||
#[naked]
|
#[naked]
|
||||||
pub unsafe fn switch_to(&mut self, next: &mut Context) {
|
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 $0, r15" : "=r"(self.r15) : : "memory" : "intel", "volatile");
|
||||||
asm!("mov r15, $0" : : "r"(next.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 $0, rsp" : "=r"(self.rsp) : : "memory" : "intel", "volatile");
|
||||||
asm!("mov rsp, $0" : : "r"(next.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
|
/* TODO
|
||||||
asm!("mov $0, cr3" : "=r"(self.cr3) : : "memory" : "intel", "volatile");
|
asm!("mov $0, cr3" : "=r"(self.cr3) : : "memory" : "intel", "volatile");
|
||||||
asm!("mov cr3, $0" : : "r"(self.cr3) : "memory" : "intel", "volatile");
|
asm!("mov cr3, $0" : : "r"(self.cr3) : "memory" : "intel", "volatile");
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//CONTEXT_SWITCH_LOCK.store(false, Ordering::SeqCst);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ pub unsafe extern fn kstart() -> ! {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize display
|
// Initialize display
|
||||||
display::init(&mut active_table);
|
//display::init(&mut active_table);
|
||||||
|
|
||||||
// Reset AP variables
|
// Reset AP variables
|
||||||
AP_COUNT.store(0, Ordering::SeqCst);
|
AP_COUNT.store(0, Ordering::SeqCst);
|
||||||
|
@ -100,7 +100,7 @@ pub unsafe extern fn kstart() -> ! {
|
||||||
HEAP_FRAME.store(0, Ordering::SeqCst);
|
HEAP_FRAME.store(0, Ordering::SeqCst);
|
||||||
|
|
||||||
// Read ACPI tables, starts APs
|
// Read ACPI tables, starts APs
|
||||||
acpi::init(&mut active_table);
|
//acpi::init(&mut active_table);
|
||||||
|
|
||||||
// Map heap
|
// Map heap
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
//! Context management
|
//! Context management
|
||||||
|
|
||||||
|
use alloc::boxed::Box;
|
||||||
use collections::{BTreeMap, Vec};
|
use collections::{BTreeMap, Vec};
|
||||||
|
use core::mem;
|
||||||
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
use core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
|
||||||
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||||
|
|
||||||
|
@ -61,6 +63,15 @@ impl ContextList {
|
||||||
let context_lock = self.new_context()?;
|
let context_lock = self.new_context()?;
|
||||||
{
|
{
|
||||||
let mut context = context_lock.write();
|
let mut context = context_lock.write();
|
||||||
|
let mut stack = Box::new([0; 4096]);
|
||||||
|
let offset = stack.len() - mem::size_of::<usize>();
|
||||||
|
unsafe {
|
||||||
|
let offset = stack.len() - mem::size_of::<usize>();
|
||||||
|
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));
|
print!("{}", format!("{}: {:X}\n", context.id, func as usize));
|
||||||
}
|
}
|
||||||
Ok(context_lock)
|
Ok(context_lock)
|
||||||
|
@ -108,6 +119,8 @@ pub struct Context {
|
||||||
pub id: usize,
|
pub id: usize,
|
||||||
/// The architecture specific context
|
/// The architecture specific context
|
||||||
pub arch: ArchContext,
|
pub arch: ArchContext,
|
||||||
|
/// Kernel stack
|
||||||
|
pub kstack: Option<Box<[u8]>>,
|
||||||
/// The open files in the scheme
|
/// The open files in the scheme
|
||||||
pub files: Vec<Option<file::File>>
|
pub files: Vec<Option<file::File>>
|
||||||
}
|
}
|
||||||
|
@ -118,6 +131,7 @@ impl Context {
|
||||||
Context {
|
Context {
|
||||||
id: id,
|
id: id,
|
||||||
arch: ArchContext::new(),
|
arch: ArchContext::new(),
|
||||||
|
kstack: None,
|
||||||
files: Vec::new()
|
files: Vec::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,8 +134,24 @@ pub extern fn kmain() {
|
||||||
|
|
||||||
print!("{}", format!("BSP: {:?}\n", syscall::getpid()));
|
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 {
|
loop {
|
||||||
|
|
Loading…
Reference in a new issue