mem: starting to get memory manager working

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

40
Cargo.lock generated
View File

@ -55,16 +55,6 @@ name = "rand_core"
version = "0.4.2" version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "riscv-rt-macros"
version = "0.1.6"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]] [[package]]
name = "rustc_version" name = "rustc_version"
version = "0.2.3" version = "0.2.3"
@ -105,8 +95,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "xous-kernel" name = "xous-kernel"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"xous-kernel-riscv-rt 0.6.1",
"xous-riscv 0.5.4", "xous-riscv 0.5.4",
"xous-riscv-rt 0.6.1", ]
[[package]]
name = "xous-kernel-riscv-rt"
version = "0.6.1"
dependencies = [
"r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"xous-kernel-riscv-rt-macros 0.1.6",
"xous-riscv 0.5.4",
]
[[package]]
name = "xous-kernel-riscv-rt-macros"
version = "0.1.6"
dependencies = [
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]] [[package]]
@ -117,15 +126,6 @@ dependencies = [
"bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
] ]
[[package]]
name = "xous-riscv-rt"
version = "0.6.1"
dependencies = [
"r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"riscv-rt-macros 0.1.6",
"xous-riscv 0.5.4",
]
[metadata] [metadata]
"checksum bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3caf393d93b2d453e80638d0674597020cef3382ada454faacd43d1a55a735a" "checksum bare-metal 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3caf393d93b2d453e80638d0674597020cef3382ada454faacd43d1a55a735a"
"checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56" "checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56"

View File

@ -9,8 +9,10 @@ REGION_ALIAS("REGION_TEXT", FLASH);
REGION_ALIAS("REGION_RODATA", FLASH); REGION_ALIAS("REGION_RODATA", FLASH);
REGION_ALIAS("REGION_DATA", RAM); REGION_ALIAS("REGION_DATA", RAM);
REGION_ALIAS("REGION_BSS", RAM); REGION_ALIAS("REGION_BSS", RAM);
REGION_ALIAS("REGION_HEAP", RAM);
REGION_ALIAS("REGION_STACK", RAM); REGION_ALIAS("REGION_STACK", RAM);
REGION_ALIAS("REGION_HEAP", RAM);
_lcdfb = ORIGIN(MEMLCD); _lcdfb = ORIGIN(MEMLCD);
_heap_size = LENGTH(RAM) - 1M; /* Size of the main kernel stack */
_stack_size = 16K;
_eheap = ORIGIN(RAM) + LENGTH(RAM);

View File

@ -1,40 +1,7 @@
use crate::syscalls; use crate::syscalls;
use crate::filled_array;
use xous_riscv::register::{mstatus, vmim}; 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]; static mut IRQ_HANDLERS: [Option<fn(usize)>; 32] = filled_array![None; 32];
pub fn handle(irqs_pending: usize) { pub fn handle(irqs_pending: usize) {

View File

@ -2,11 +2,11 @@
extern crate xous_riscv; extern crate xous_riscv;
use core::panic::PanicInfo; // use core::panic::PanicInfo;
#[panic_handler] // #[panic_handler]
fn handle_panic(_arg: &PanicInfo) -> ! { // fn handle_panic(_arg: &PanicInfo) -> ! {
loop {} // loop {}
} // }
// Allow consumers of this library to make syscalls // Allow consumers of this library to make syscalls
pub mod 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; extern crate xous_riscv;
mod syscalls; mod syscalls;
mod irq; mod irq;
mod macros;
mod mem;
pub use irq::sys_interrupt_claim; pub use irq::sys_interrupt_claim;
use core::panic::PanicInfo; use core::panic::PanicInfo;
use xous_kernel_riscv_rt::xous_kernel_entry; use xous_kernel_riscv_rt::xous_kernel_entry;
use xous_riscv::register::{mcause, mstatus, mie, vmim, vmip}; use xous_riscv::register::{mcause, mstatus, mie, vmim, vmip};
use mem::MemoryManager;
#[panic_handler] #[panic_handler]
@ -32,6 +35,7 @@ fn xous_main() -> ! {
mie::set_mext(); mie::set_mext();
mstatus::set_mie(); // Enable CPU interrupts mstatus::set_mie(); // Enable CPU interrupts
} }
let mm = MemoryManager::new();
sys_interrupt_claim(2, |_| { sys_interrupt_claim(2, |_| {
let uart_ptr = 0xE000_1800 as *mut usize; let uart_ptr = 0xE000_1800 as *mut usize;
print_str(uart_ptr, "hello, world!\r\n"); 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(())
}
}

View File

@ -74,23 +74,23 @@ SECTIONS
_ebss = .; _ebss = .;
} > REGION_BSS } > REGION_BSS
/* fictitious region that represents the memory available for the heap */
.heap (NOLOAD) :
{
_sheap = .;
. += _heap_size;
. = ALIGN(4);
_eheap = .;
} > REGION_HEAP
/* fictitious region that represents the memory available for the stack */ /* fictitious region that represents the memory available for the stack */
.stack (NOLOAD) : .stack (NOLOAD) :
{ {
_estack = .; _estack = .;
. = _stack_start; PROVIDE(_stack_start = .);
. += _stack_size;
_sstack = .; _sstack = .;
} > REGION_STACK } > REGION_STACK
/* fictitious region that represents the memory available for the heap */
.heap (NOLOAD) :
{
. = ALIGN(4);
_sheap = .;
/* _eheap is defined elsewhere and is the remainder of RAM */
} > REGION_HEAP
/* fake output .got section */ /* fake output .got section */
/* Dynamic relocations are unsupported. This section is only used to detect /* Dynamic relocations are unsupported. This section is only used to detect
relocatable code in the input files and raise an error if relocatable code relocatable code in the input files and raise an error if relocatable code