mem: get memory mapping working, in theory
Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
1fad6b5206
commit
1ad0961c87
11
src/main.rs
11
src/main.rs
@ -3,7 +3,9 @@
|
||||
|
||||
extern crate vexriscv;
|
||||
|
||||
#[macro_use]
|
||||
mod debug;
|
||||
|
||||
mod definitions;
|
||||
mod irq;
|
||||
mod macros;
|
||||
@ -20,7 +22,9 @@ use vexriscv::register::{mcause, mie, mstatus, vmim, vmip};
|
||||
use xous_kernel_riscv_rt::xous_kernel_entry;
|
||||
|
||||
#[panic_handler]
|
||||
fn handle_panic(_arg: &PanicInfo) -> ! {
|
||||
fn handle_panic(arg: &PanicInfo) -> ! {
|
||||
println!("PANIC!");
|
||||
println!("Details: {:?}", arg);
|
||||
loop {}
|
||||
}
|
||||
|
||||
@ -42,10 +46,13 @@ fn xous_main() -> ! {
|
||||
println!("Starting up...");
|
||||
sys_interrupt_claim(2, debug::irq).unwrap();
|
||||
|
||||
println!("Creating memory manager...");
|
||||
let mut mm = MemoryManager::new();
|
||||
|
||||
println!("Creating process table...");
|
||||
let mut _pt = ProcessTable::new(&mut mm);
|
||||
|
||||
|
||||
println!("Entering main loop");
|
||||
loop {
|
||||
// unsafe { vexriscv::asm::wfi() };
|
||||
}
|
||||
|
105
src/mem.rs
105
src/mem.rs
@ -1,4 +1,5 @@
|
||||
use crate::definitions::{MemoryAddress, XousError, XousPid};
|
||||
use crate::processtable::Process;
|
||||
use crate::{print, println};
|
||||
use core::num::NonZeroUsize;
|
||||
use vexriscv::register::mstatus;
|
||||
@ -157,9 +158,9 @@ impl MemoryManager {
|
||||
pub fn alloc_page(&mut self, pid: XousPid) -> Result<MemoryAddress, XousError> {
|
||||
// Go through all RAM pages looking for a free page.
|
||||
// Optimization: start from the previous address.
|
||||
println!("Allocating page for PID {}", pid);
|
||||
// println!("Allocating page for PID {}", pid);
|
||||
for index in 0..RAM_PAGE_COUNT {
|
||||
println!(" Checking {:08x}...", index * PAGE_SIZE + RAM_START);
|
||||
// println!(" Checking {:08x}...", index * PAGE_SIZE + RAM_START);
|
||||
if self.ram[index] == 0 {
|
||||
self.ram[index] = pid;
|
||||
let page_addr = (index * PAGE_SIZE + RAM_START) as *mut u32;
|
||||
@ -170,22 +171,106 @@ impl MemoryManager {
|
||||
}
|
||||
}
|
||||
let new_page = unsafe { transmute::<*mut u32, usize>(page_addr) };
|
||||
println!(" Page {:08x} is free", new_page);
|
||||
// println!(" Page {:08x} is free", new_page);
|
||||
return Ok(NonZeroUsize::new(new_page).unwrap());
|
||||
}
|
||||
}
|
||||
Err(XousError::OutOfMemory)
|
||||
}
|
||||
|
||||
// /// Create an identity mapping, copying the kernel to itself
|
||||
// pub fn create_identity(&mut self, pid: XousPid) -> Result<(), XousError> {
|
||||
// let pt = unsafe { transmute::<MemoryAddress, &mut PageTable>(satp) };
|
||||
/// Map the given page to the specified process table. If necessary,
|
||||
/// allocate a new page.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// * OutOfMemory - Tried to allocate a new pagetable, but ran out of memory.
|
||||
fn map_page(
|
||||
&mut self,
|
||||
root: &mut PageTable,
|
||||
phys: usize,
|
||||
virt: usize,
|
||||
) -> Result<(), XousError> {
|
||||
let ppn1 = (phys >> 20) & ((1 << 12) - 1);
|
||||
let ppn0 = (phys >> 10) & ((1 << 10) - 1);
|
||||
let ppo = (phys >> 0) & ((1 << 12) - 1);
|
||||
let vpn1 = (virt >> 22) & ((1 << 10) - 1);
|
||||
let vpn0 = (virt >> 10) & ((1 << 10) - 1);
|
||||
let vpo = (virt >> 0) & ((1 << 12) - 1);
|
||||
|
||||
// Err(XousError::OutOfMemory)
|
||||
// }
|
||||
println!(
|
||||
"Mapping phys: {:08x} -> virt: {:08x} (vpn1: {:04x} vpn0: {:04x} ppn1: {:04x} ppn0: {:04x})",
|
||||
phys, virt, vpn1, vpn0, ppn1, ppn0
|
||||
);
|
||||
assert!(ppn1 < 4096);
|
||||
assert!(ppn0 < 1024);
|
||||
assert!(ppo < 4096);
|
||||
assert!(vpn1 < 1024);
|
||||
assert!(vpn0 < 1024);
|
||||
assert!(vpo < 4096);
|
||||
|
||||
fn map_page(&mut self, satp: &mut PageTable, pid: XousPid) -> Result<(), XousError> {
|
||||
Err(XousError::OutOfMemory)
|
||||
let ref mut l1_pt = root.entries;
|
||||
println!("l1_pt is at {:p} ({:p})", &l1_pt, &l1_pt[vpn1]);
|
||||
|
||||
// Allocate a new level 1 pagetable entry if one doesn't exist.
|
||||
if l1_pt[vpn1] & 1 == 0 {
|
||||
println!(" top-level VPN1 {:04x}: {:08x} (will allocate a new one)", vpn1, l1_pt[vpn1]);
|
||||
// Allocate the page to the kernel (PID 1)
|
||||
let new_addr = self.alloc_page(1)?.get();
|
||||
println!(
|
||||
" Allocated new top-level page for VPN1 {:04x} in process @ {:08x}",
|
||||
vpn1, new_addr
|
||||
);
|
||||
|
||||
// Mark this entry as a leaf node (WRX as 0), and indicate
|
||||
// it is a valid page by setting "V".
|
||||
l1_pt[vpn1] = (((new_addr >> 10) & ((1 << 22) - 1)) << 10) | 1;
|
||||
println!(" New top-level page entry: {:08x}", l1_pt[vpn1]);
|
||||
}
|
||||
|
||||
let mut l0_pt = unsafe {
|
||||
let tmp = (l1_pt[vpn1] & ((1 << 10) - 1)) as *mut PageTable;
|
||||
(*tmp).entries
|
||||
};
|
||||
|
||||
// Allocate a new level 0 pagetable entry if one doesn't exist.
|
||||
if l0_pt[vpn0] & 1 != 0 {
|
||||
panic!("Page already allocated!");
|
||||
}
|
||||
l0_pt[vpn0] = (ppn1 << 20) | (ppn0 << 10) | 1 | 0xe;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Create an identity mapping, copying the kernel to itself
|
||||
pub fn create_identity(&mut self, process: &Process, pid: XousPid) -> Result<(), XousError> {
|
||||
let root_page = (process.satp & ((1 << 22) - 1)) << 9;
|
||||
let pt = unsafe { &mut (*(root_page as *mut PageTable)) };
|
||||
println!("SATP value: {:08x} Root page: {:08x} pt: {:p} pt: {:p}", process.satp, root_page, &pt, pt);
|
||||
let flash_orig = self.flash.clone();
|
||||
for (flash_idx, flash_pid) in flash_orig.iter().enumerate() {
|
||||
if *flash_pid == pid {
|
||||
// println!(
|
||||
// "Flash addr {:08x} owned by PID {}, mapping it as ident",
|
||||
// flash_idx * PAGE_SIZE + FLASH_START,
|
||||
// pid
|
||||
// );
|
||||
self.map_page(
|
||||
pt,
|
||||
flash_idx * PAGE_SIZE + FLASH_START,
|
||||
flash_idx * PAGE_SIZE + FLASH_START,
|
||||
)?;
|
||||
print!("Entries mapped: >");
|
||||
let mut i = 0;
|
||||
for (entry_idx, entry) in pt.entries.iter().enumerate() {
|
||||
i = i + 1;
|
||||
if *entry != 0 {
|
||||
print!(" {}:{:08x}", entry_idx, entry);
|
||||
}
|
||||
}
|
||||
println!(" < ({})", i);
|
||||
println!("");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Mark a given address as being owned by the specified process ID
|
||||
|
@ -1,16 +1,24 @@
|
||||
use crate::definitions::{XousError, XousPid, MemoryAddress};
|
||||
use crate::definitions::{MemoryAddress, XousError, XousPid};
|
||||
use crate::mem::MemoryManager;
|
||||
use crate::{filled_array, println, print};
|
||||
use crate::{filled_array, print, println};
|
||||
use vexriscv::register::{satp, mstatus};
|
||||
|
||||
const MAX_PROCESS_COUNT: usize = 256;
|
||||
|
||||
struct Process {
|
||||
satp: Option<MemoryAddress>,
|
||||
pub struct Process {
|
||||
pub satp: usize,
|
||||
}
|
||||
|
||||
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})", match self.satp { Some(s) => s.get(), None => 0 })
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,13 +29,29 @@ pub struct ProcessTable {
|
||||
impl ProcessTable {
|
||||
pub fn new(mm: &mut MemoryManager) -> Self {
|
||||
let mut pt = ProcessTable {
|
||||
processes: filled_array![Process { satp: None }; 256],
|
||||
processes: filled_array![Process { satp: 0 }; 256],
|
||||
};
|
||||
|
||||
// Allocate a root page table for PID 1
|
||||
// mm.create_identity(1).expect("Unable to create identity mapping");
|
||||
pt.processes[1].satp = Some(mm.alloc_page(1).unwrap());
|
||||
println!("PID 1: {:?}", pt.processes[1]);
|
||||
// Allocate a root page table for PID 1. Also mark the "ASID" as "1"
|
||||
// for "PID 1"
|
||||
let root_page = mm.alloc_page(1).unwrap().get();
|
||||
pt.processes[1].satp = (root_page >> 9) | (1 << 22);
|
||||
mm.create_identity(&pt.processes[1], 1)
|
||||
.expect("Unable to create identity mapping");
|
||||
println!("PID 1: {:?} root page @ {:08x}", pt.processes[1], root_page);
|
||||
println!("Enabling MMU...");
|
||||
unsafe {
|
||||
// Set the MMU pointer to our identity mapping
|
||||
satp::set(
|
||||
satp::Mode::Sv32,
|
||||
(pt.processes[1].satp >> 22) & ((1 << 9) - 1),
|
||||
(pt.processes[1].satp >> 0) & ((1 << 22) - 1),
|
||||
);
|
||||
|
||||
// Switch to Supervisor mode
|
||||
mstatus::set_mpp(mstatus::MPP::Supervisor);
|
||||
};
|
||||
println!("MMU enabled");
|
||||
pt
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user