Simple, unsafe context switch
This commit is contained in:
		
							parent
							
								
									6715d5c534
								
							
						
					
					
						commit
						6e3f59ba8e
					
				
					 5 changed files with 53 additions and 7 deletions
				
			
		
							
								
								
									
										2
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -1,4 +1,4 @@ | |||
| ARCH?=arm | ||||
| ARCH?=x86_64 | ||||
| 
 | ||||
| QEMU=qemu-system-$(ARCH) | ||||
| 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)] | ||||
| 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);
 | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -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
 | ||||
|         { | ||||
|  |  | |||
|  | @ -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::<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)); | ||||
|         } | ||||
|         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<Box<[u8]>>, | ||||
|     /// The open files in the scheme
 | ||||
|     pub files: Vec<Option<file::File>> | ||||
| } | ||||
|  | @ -118,6 +131,7 @@ impl Context { | |||
|         Context { | ||||
|             id: id, | ||||
|             arch: ArchContext::new(), | ||||
|             kstack: None, | ||||
|             files: Vec::new() | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jeremy Soller
						Jeremy Soller