mem: starting to get memory manager working

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
2019-12-24 09:33:02 +08:00
parent 9a4d002832
commit 8521093f6d
8 changed files with 217 additions and 71 deletions

View File

@ -1,40 +1,7 @@
use crate::syscalls;
use crate::filled_array;
use xous_riscv::register::{mstatus, vmim};
// Shamelessly taken from
// https://stackoverflow.com/questions/36258417/using-a-macro-to-initialize-a-big-array-of-non-copy-elements
// Allows us to fill an array with a predefined value.
macro_rules! filled_array {
(@accum (0, $($_es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@as_expr [$($body)*])};
(@accum (1, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (0, $($es),*) -> ($($body)* $($es,)*))};
(@accum (2, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (0, $($es),*) -> ($($body)* $($es,)* $($es,)*))};
(@accum (3, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (2, $($es),*) -> ($($body)* $($es,)*))};
(@accum (4, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (2, $($es,)* $($es),*) -> ($($body)*))};
(@accum (5, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (4, $($es),*) -> ($($body)* $($es,)*))};
(@accum (6, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (4, $($es),*) -> ($($body)* $($es,)* $($es,)*))};
(@accum (7, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (4, $($es),*) -> ($($body)* $($es,)* $($es,)* $($es,)*))};
(@accum (8, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (4, $($es,)* $($es),*) -> ($($body)*))};
(@accum (16, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (8, $($es,)* $($es),*) -> ($($body)*))};
(@accum (32, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (16, $($es,)* $($es),*) -> ($($body)*))};
(@accum (64, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (32, $($es,)* $($es),*) -> ($($body)*))};
(@as_expr $e:expr) => {$e};
[$e:expr; $n:tt] => { filled_array!(@accum ($n, $e) -> ()) };
}
static mut IRQ_HANDLERS: [Option<fn(usize)>; 32] = filled_array![None; 32];
pub fn handle(irqs_pending: usize) {

View File

@ -2,11 +2,11 @@
extern crate xous_riscv;
use core::panic::PanicInfo;
#[panic_handler]
fn handle_panic(_arg: &PanicInfo) -> ! {
loop {}
}
// use core::panic::PanicInfo;
// #[panic_handler]
// fn handle_panic(_arg: &PanicInfo) -> ! {
// loop {}
// }
// Allow consumers of this library to make syscalls
pub mod syscalls;

46
src/macros.rs Normal file
View File

@ -0,0 +1,46 @@
// Shamelessly taken from
// https://stackoverflow.com/questions/36258417/using-a-macro-to-initialize-a-big-array-of-non-copy-elements
// Allows us to fill an array with a predefined value.
#[macro_export]
macro_rules! filled_array {
(@accum (0, $($_es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@as_expr [$($body)*])};
(@accum (1, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (0, $($es),*) -> ($($body)* $($es,)*))};
(@accum (2, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (0, $($es),*) -> ($($body)* $($es,)* $($es,)*))};
(@accum (3, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (2, $($es),*) -> ($($body)* $($es,)*))};
(@accum (4, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (2, $($es,)* $($es),*) -> ($($body)*))};
(@accum (5, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (4, $($es),*) -> ($($body)* $($es,)*))};
(@accum (6, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (4, $($es),*) -> ($($body)* $($es,)* $($es,)*))};
(@accum (7, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (4, $($es),*) -> ($($body)* $($es,)* $($es,)* $($es,)*))};
(@accum (8, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (4, $($es,)* $($es),*) -> ($($body)*))};
(@accum (16, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (8, $($es,)* $($es),*) -> ($($body)*))};
(@accum (32, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (16, $($es,)* $($es),*) -> ($($body)*))};
(@accum (64, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (32, $($es,)* $($es),*) -> ($($body)*))};
(@accum (128, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (64, $($es,)* $($es),*) -> ($($body)*))};
(@accum (256, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (128, $($es,)* $($es),*) -> ($($body)*))};
(@accum (512, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (256, $($es,)* $($es),*) -> ($($body)*))};
(@accum (1024, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (512, $($es,)* $($es),*) -> ($($body)*))};
(@accum (2048, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (1024, $($es,)* $($es),*) -> ($($body)*))};
(@accum (4096, $($es:expr),*) -> ($($body:tt)*))
=> {filled_array!(@accum (2048, $($es,)* $($es),*) -> ($($body)*))};
(@as_expr $e:expr) => {$e};
[$e:expr; $n:tt] => { filled_array!(@accum ($n, $e) -> ()) };
}

View File

@ -4,12 +4,15 @@
extern crate xous_riscv;
mod syscalls;
mod irq;
mod macros;
mod mem;
pub use irq::sys_interrupt_claim;
use core::panic::PanicInfo;
use xous_kernel_riscv_rt::xous_kernel_entry;
use xous_riscv::register::{mcause, mstatus, mie, vmim, vmip};
use mem::MemoryManager;
#[panic_handler]
@ -32,6 +35,7 @@ fn xous_main() -> ! {
mie::set_mext();
mstatus::set_mie(); // Enable CPU interrupts
}
let mm = MemoryManager::new();
sys_interrupt_claim(2, |_| {
let uart_ptr = 0xE000_1800 as *mut usize;
print_str(uart_ptr, "hello, world!\r\n");

127
src/mem.rs Normal file
View File

@ -0,0 +1,127 @@
use crate::syscalls::{XousError, XousPid};
use xous_riscv::register::mstatus;
const FLASH_START: usize = 0x20000000;
const FLASH_SIZE: usize = 16_777_216;
const FLASH_END: usize = FLASH_START + FLASH_SIZE;
const RAM_START: usize = 0x40000000;
const RAM_SIZE: usize = 16_777_216;
const RAM_END: usize = RAM_START + RAM_SIZE;
const IO_START: usize = 0xe0000000;
const IO_SIZE: usize = 65_536;
const IO_END: usize = IO_START + IO_SIZE;
const LCD_START: usize = 0xB0000000;
const LCD_SIZE: usize = 32_768;
const LCD_END: usize = LCD_START + LCD_SIZE;
const PAGE_SIZE: usize = 4096;
const FLASH_PAGE_COUNT: usize = FLASH_SIZE / PAGE_SIZE;
const RAM_PAGE_COUNT: usize = RAM_SIZE / PAGE_SIZE;
const IO_PAGE_COUNT: usize = IO_SIZE;
const LCD_PAGE_COUNT: usize = LCD_SIZE / PAGE_SIZE;
pub struct MemoryManager {
flash: [u8; FLASH_PAGE_COUNT],
ram: [u8; RAM_PAGE_COUNT],
io: [u8; IO_PAGE_COUNT],
lcd: [u8; LCD_PAGE_COUNT],
}
extern "C" {
// Boundaries of the .bss section
static mut _ebss: usize;
static mut _sbss: usize;
// Boundaries of the .data section
static mut _edata: usize;
static mut _sdata: usize;
// Boundaries of the stack
static mut _estack: usize;
static mut _sstack: usize;
// Boundaries of the heap
static _sheap: usize;
static _eheap: usize;
// Initial values of the .data section (stored in Flash)
static _sidata: usize;
}
use core::mem::transmute;
/// Initialzie the memory map.
/// This will go through memory and map anything that the kernel is
/// using to process 0xff, then allocate a pagetable for this process
/// and place it at the usual offset.
/// Finally, it will enable the MMU.
impl MemoryManager {
pub fn new() -> MemoryManager {
let mut mm = MemoryManager {
flash: [0; FLASH_PAGE_COUNT],
ram: [0; RAM_PAGE_COUNT],
io: [0; IO_PAGE_COUNT],
lcd: [0; LCD_PAGE_COUNT],
};
unsafe { mstatus::clear_mie() };
// Map the bss section
let start_bss = unsafe { transmute::<&usize, usize>(&_sbss) };
let end_bss = unsafe { transmute::<&usize, usize>(&_ebss) };
let bss_range = (start_bss..end_bss).step_by(PAGE_SIZE);
let start_data = unsafe { transmute::<&usize, usize>(&_sdata) };
let end_data = unsafe { transmute::<&usize, usize>(&_edata) };
let data_range = (start_data..end_data).step_by(PAGE_SIZE);
// Note: stack grows downwards so these are swapped.
let start_stack = unsafe { transmute::<&usize, usize>(&_estack) };
let end_stack = unsafe { transmute::<&usize, usize>(&_sstack) };
let stack_range = (start_stack..end_stack).step_by(PAGE_SIZE);
for region in bss_range {
mm.claim_page(region & !0xfff, 1).unwrap();
}
for region in data_range {
mm.claim_page(region & !0xfff, 1).unwrap();
}
for region in stack_range {
mm.claim_page(region & !0xfff, 1).unwrap();
}
unsafe { mstatus::set_mie() };
mm
}
fn claim_page(&mut self, addr: usize, pid: XousPid) -> Result<(), XousError> {
// Ensure the address lies on a page boundary
if addr & 0xfff != 0 {
return Err(XousError::BadAlignment);
}
match addr {
FLASH_START..=FLASH_END => {
Self::claim_page_inner(&mut self.flash, addr - FLASH_START, pid)
}
RAM_START..=RAM_END => Self::claim_page_inner(&mut self.ram, addr - RAM_START, pid),
IO_START..=IO_END => Self::claim_page_inner(&mut self.io, addr - IO_START, pid),
LCD_START..=LCD_END => Self::claim_page_inner(&mut self.lcd, addr - LCD_START, pid),
_ => Err(XousError::BadAddress),
}
}
fn claim_page_inner(tbl: &mut [u8], addr: usize, pid: XousPid) -> Result<(), XousError> {
let page = addr / PAGE_SIZE;
if page > tbl.len() {
return Err(XousError::BadAddress);
}
if tbl[page] != 0 {
return Err(XousError::OutOfMemory);
}
tbl[page] = pid;
Ok(())
}
}