From d0c3c9ff6e8e3612cc696cc4f5f5df93a046c8e2 Mon Sep 17 00:00:00 2001 From: Stephen Marz Date: Wed, 27 Nov 2019 17:02:07 -0500 Subject: [PATCH] Add Process structure and routines. --- risc_v/ch6/src/lib.rs | 38 ++++++------------ risc_v/ch6/src/process.rs | 83 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 26 deletions(-) diff --git a/risc_v/ch6/src/lib.rs b/risc_v/ch6/src/lib.rs index 31142cd..986f69b 100755 --- a/risc_v/ch6/src/lib.rs +++ b/risc_v/ch6/src/lib.rs @@ -9,10 +9,10 @@ alloc_prelude, const_raw_ptr_to_usize_cast)] -#[macro_use] +// #[macro_use] extern crate alloc; // This is experimental and requires alloc_prelude as a feature -use alloc::prelude::v1::*; +// use alloc::prelude::v1::*; // /////////////////////////////////// // / RUST MACROS @@ -327,38 +327,24 @@ extern "C" fn kmain() { // kmain() starts in supervisor mode. So, we should have the trap // vector setup and the MMU turned on when we get here. - // Create a new scope so that we can test the global allocator and - // deallocator - { - // We have the global allocator, so let's see if that works! - let k = Box::::new(100); - println!("Boxed value = {}", *k); - // The following comes from the Rust documentation: - // some bytes, in a vector - let sparkle_heart = vec![240, 159, 146, 150]; - // We know these bytes are valid, so we'll use `unwrap()`. - // This will MOVE the vector. - let sparkle_heart = String::from_utf8(sparkle_heart).unwrap(); - println!("String = {}", sparkle_heart); - println!("\n\nAllocations of a box, vector, and string"); - kmem::print_table(); - } - println!("\n\nEverything should now be free:"); + // Initialize the process list and anything else that needs to be done, + // here. + process::init(); kmem::print_table(); - unsafe { + // unsafe { // Set the next machine timer to fire. - let mtimecmp = 0x0200_4000 as *mut u64; - let mtime = 0x0200_bff8 as *const u64; + // let mtimecmp = 0x0200_4000 as *mut u64; + // let mtime = 0x0200_bff8 as *const u64; // The frequency given by QEMU is 10_000_000 Hz, so this sets // the next interrupt to fire one second from now. - mtimecmp.write_volatile(mtime.read_volatile() + 10_000_000); + // mtimecmp.write_volatile(mtime.read_volatile() + 10_000_000); // Let's cause a page fault and see what happens. This should trap // to m_trap under trap.rs - let v = 0x0 as *mut u64; - v.write_volatile(0); - } + // let v = 0x0 as *mut u64; + // v.write_volatile(0); + // } // If we get here, the Box, vec, and String should all be freed since // they go out of scope. This calls their "Drop" trait. diff --git a/risc_v/ch6/src/process.rs b/risc_v/ch6/src/process.rs index ce49afb..2ea1ba2 100644 --- a/risc_v/ch6/src/process.rs +++ b/risc_v/ch6/src/process.rs @@ -4,6 +4,45 @@ // 27 Nov 2019 use crate::cpu::TrapFrame; +use crate::page::{alloc, dealloc}; +use alloc::collections::linked_list::LinkedList; + +// Here, we store a process list. It uses the global allocator +// that we made before and its job is to store all processes. +// We will have this list OWN the process. So, anytime we want +// the process, we will consult the process list. +static mut PROCESS_LIST: LinkedList = LinkedList::new(); +static mut CURRENT_0: u16 = 0; + +/// We will eventually move this function out of here, but its +/// job is just to take a slot in the process list. +fn init_process() { + loop { + unsafe { + asm!("wfi"); + } + } +} + +/// Add a process given a function address and then +/// push it onto the LinkedList. Uses Process::new_default +/// to create a new stack, etc. +pub fn add_process_default(proc: fn()) { + unsafe { + let p = Process::new_default(proc); + PROCESS_LIST.push_back(p); + } +} + +pub fn init() { + add_process_default(init_process); + unsafe { + let p = PROCESS_LIST.back(); + if let Some(pd) = p { + CURRENT_0 = pd.pid; + } + } +} // Let's represent this in C ABI. We do this // because we need to access some of the fields @@ -14,7 +53,51 @@ use crate::cpu::TrapFrame; pub struct Process { frame: TrapFrame, stack: *mut u8, + program_counter: usize, + pid: u16, + data: ProcessData, } +impl Process { + pub fn new_default(func: fn()) -> Self { + let pd; + unsafe { + let plb = PROCESS_LIST.back(); + if let Some(p) = plb { + pd = p.pid + 1; + } + else { + pd = 1 + } + } + Process { + frame: TrapFrame::zero(), + stack: alloc(1), + program_counter: func as usize, + pid: pd, + data: ProcessData::zero() + } + } +} +impl Drop for Process { + fn drop(&mut self) { + dealloc(self.stack); + } +} + +// The private data in a process contains information +// that is relevant to where we are, including the path +// and open file descriptors. +pub struct ProcessData { + cwd_path: [u8; 128], +} + +impl ProcessData { + pub fn zero() -> Self { + ProcessData { + cwd_path: [0; 128], + } + } +}