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;
|
extern crate vexriscv;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
mod debug;
|
mod debug;
|
||||||
|
|
||||||
mod definitions;
|
mod definitions;
|
||||||
mod irq;
|
mod irq;
|
||||||
mod macros;
|
mod macros;
|
||||||
@ -20,7 +22,9 @@ use vexriscv::register::{mcause, mie, mstatus, vmim, vmip};
|
|||||||
use xous_kernel_riscv_rt::xous_kernel_entry;
|
use xous_kernel_riscv_rt::xous_kernel_entry;
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn handle_panic(_arg: &PanicInfo) -> ! {
|
fn handle_panic(arg: &PanicInfo) -> ! {
|
||||||
|
println!("PANIC!");
|
||||||
|
println!("Details: {:?}", arg);
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,10 +46,13 @@ fn xous_main() -> ! {
|
|||||||
println!("Starting up...");
|
println!("Starting up...");
|
||||||
sys_interrupt_claim(2, debug::irq).unwrap();
|
sys_interrupt_claim(2, debug::irq).unwrap();
|
||||||
|
|
||||||
|
println!("Creating memory manager...");
|
||||||
let mut mm = MemoryManager::new();
|
let mut mm = MemoryManager::new();
|
||||||
|
|
||||||
|
println!("Creating process table...");
|
||||||
let mut _pt = ProcessTable::new(&mut mm);
|
let mut _pt = ProcessTable::new(&mut mm);
|
||||||
|
|
||||||
|
println!("Entering main loop");
|
||||||
loop {
|
loop {
|
||||||
// unsafe { vexriscv::asm::wfi() };
|
// unsafe { vexriscv::asm::wfi() };
|
||||||
}
|
}
|
||||||
|
105
src/mem.rs
105
src/mem.rs
@ -1,4 +1,5 @@
|
|||||||
use crate::definitions::{MemoryAddress, XousError, XousPid};
|
use crate::definitions::{MemoryAddress, XousError, XousPid};
|
||||||
|
use crate::processtable::Process;
|
||||||
use crate::{print, println};
|
use crate::{print, println};
|
||||||
use core::num::NonZeroUsize;
|
use core::num::NonZeroUsize;
|
||||||
use vexriscv::register::mstatus;
|
use vexriscv::register::mstatus;
|
||||||
@ -157,9 +158,9 @@ impl MemoryManager {
|
|||||||
pub fn alloc_page(&mut self, pid: XousPid) -> Result<MemoryAddress, XousError> {
|
pub fn alloc_page(&mut self, pid: XousPid) -> Result<MemoryAddress, XousError> {
|
||||||
// Go through all RAM pages looking for a free page.
|
// Go through all RAM pages looking for a free page.
|
||||||
// Optimization: start from the previous address.
|
// 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 {
|
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 {
|
if self.ram[index] == 0 {
|
||||||
self.ram[index] = pid;
|
self.ram[index] = pid;
|
||||||
let page_addr = (index * PAGE_SIZE + RAM_START) as *mut u32;
|
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) };
|
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());
|
return Ok(NonZeroUsize::new(new_page).unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(XousError::OutOfMemory)
|
Err(XousError::OutOfMemory)
|
||||||
}
|
}
|
||||||
|
|
||||||
// /// Create an identity mapping, copying the kernel to itself
|
/// Map the given page to the specified process table. If necessary,
|
||||||
// pub fn create_identity(&mut self, pid: XousPid) -> Result<(), XousError> {
|
/// allocate a new page.
|
||||||
// let pt = unsafe { transmute::<MemoryAddress, &mut PageTable>(satp) };
|
///
|
||||||
|
/// # 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> {
|
let ref mut l1_pt = root.entries;
|
||||||
Err(XousError::OutOfMemory)
|
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
|
/// 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::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;
|
const MAX_PROCESS_COUNT: usize = 256;
|
||||||
|
|
||||||
struct Process {
|
pub struct Process {
|
||||||
satp: Option<MemoryAddress>,
|
pub satp: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::fmt::Debug for Process {
|
impl core::fmt::Debug for Process {
|
||||||
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
|
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 {
|
impl ProcessTable {
|
||||||
pub fn new(mm: &mut MemoryManager) -> Self {
|
pub fn new(mm: &mut MemoryManager) -> Self {
|
||||||
let mut pt = ProcessTable {
|
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
|
// Allocate a root page table for PID 1. Also mark the "ASID" as "1"
|
||||||
// mm.create_identity(1).expect("Unable to create identity mapping");
|
// for "PID 1"
|
||||||
pt.processes[1].satp = Some(mm.alloc_page(1).unwrap());
|
let root_page = mm.alloc_page(1).unwrap().get();
|
||||||
println!("PID 1: {:?}", pt.processes[1]);
|
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
|
pt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user