xous-kernel/src/processtable.rs

114 lines
3.3 KiB
Rust

use crate::definitions::{MemoryAddress, MemorySize, XousError, XousPid};
use crate::mem::MemoryManager;
use crate::{filled_array, print, println};
use vexriscv::register::{mepc, mstatus, satp};
const MAX_PROCESS_COUNT: usize = 256;
static mut CURRENT_SATP: usize = 0;
pub struct Process {
pub satp: usize,
}
pub struct ProcessTableInner {
processes: [Process; MAX_PROCESS_COUNT],
}
pub struct ProcessTable {}
static mut PT: ProcessTableInner = ProcessTableInner {
processes: filled_array![Process { satp: 0 }; 256],
};
extern "Rust" {
fn kmain(mm: MemoryManager, pt: ProcessTable) -> !;
}
impl core::fmt::Debug for Process {
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
write!(
fmt,
"Process (satp: 0x{:08x}, mode: {}, ASID: {}, PPN: {:08x})",
self.satp,
self.satp >> 31,
self.satp >> 22 & ((1 << 9) - 1),
(self.satp >> 0 & ((1 << 22) - 1)) << 9,
)
}
}
impl ProcessTableInner {
/// Switch to the new PID when we return to supervisor mode
pub fn switch_to(&self, pid: XousPid, pc: usize) -> Result<(), XousError> {
if pid == 0 {
return Err(XousError::ProcessNotFound);
}
if pid >= 255 {
return Err(XousError::ProcessNotFound);
}
let pid = pid as usize;
let new_satp = self.processes[pid].satp;
if new_satp & (1 << 31) == 0 {
return Err(XousError::ProcessNotFound);
}
unsafe {
CURRENT_SATP = new_satp;
}
satp::write(new_satp);
mepc::write(pc);
Ok(())
}
pub fn alloc_pid(&mut self) -> Result<XousPid, XousError> {
for (idx, process) in self.processes.iter().enumerate() {
if process.satp == 0 {
return Ok((idx + 1) as XousPid);
}
}
Err(XousError::ProcessNotChild)
}
}
impl ProcessTable {
pub fn new() -> Result<ProcessTable, XousError> {
Ok(ProcessTable {})
}
pub fn create_process(&mut self, mm: &mut MemoryManager) -> Result<XousPid, XousError> {
let mut pt = unsafe { &mut PT };
let pid = pt.alloc_pid()?;
let root_page = mm.alloc_page(pid).expect("Couldn't allocate memory for new process page tables");
let root_page = root_page.get();
pt.processes[pid as usize].satp = (root_page >> 12) | ((pid as usize) << 22) | (1 << 31);
Ok(pid)
}
pub fn satp_for(&self, pid: XousPid) -> Result<MemoryAddress, XousError> {
let pt = unsafe { &PT };
match MemoryAddress::new(pt.processes[pid as usize].satp) {
Some(addr) => Ok(addr),
None => Err(XousError::ProcessNotFound)
}
}
pub fn switch_to(&self, pid: XousPid, pc: usize) -> Result<(), XousError> {
let pt = unsafe { &PT };
pt.switch_to(pid, pc)
}
}
pub fn sys_memory_allocate(
phys: Option<MemoryAddress>,
virt: Option<MemoryAddress>,
size: MemorySize,
) -> Result<MemoryAddress, XousError> {
match phys {
Some(addr) => {}
None => {}
}
Ok(MemoryAddress::new(4096).unwrap())
}