mmu: first attempt to get it enabled

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2020-01-21 18:14:13 +08:00
parent 1ad0961c87
commit b48271308c
13 changed files with 173 additions and 18 deletions

26
asm.S Normal file
View File

@ -0,0 +1,26 @@
#if __riscv_xlen == 64
# define STORE sd
# define LOAD ld
# define LOG_REGBYTES 3
#else
# define STORE sw
# define LOAD lw
# define LOG_REGBYTES 2
#endif
#define REGBYTES (1 << LOG_REGBYTES)
.global start_kmain
.text
start_kmain:
li t0, (1 << 11) | (1 << 5)
csrw mstatus, t0
csrw mepc, a0
add a0, a1, zero
add a1, a2, zero
add a2, a3, zero
add a3, a4, zero
add a4, a5, zero
add a5, a6, zero
add a6, a7, zero
add a7, zero, zero
mret // Return to kmain

17
assemble.ps1 Normal file
View File

@ -0,0 +1,17 @@
# remove existing blobs because otherwise this will append object files to the old blobs
Remove-Item -Force bin/*.a
$crate = "xous-kernel"
riscv64-unknown-elf-gcc -ggdb3 -c -mabi=ilp32 -march=rv32imac asm.S -o bin/$crate.o
riscv64-unknown-elf-ar crs bin/riscv32imac-unknown-none-elf.a bin/$crate.o
riscv64-unknown-elf-ar crs bin/riscv32imc-unknown-none-elf.a bin/$crate.o
riscv64-unknown-elf-gcc -ggdb3 -c -mabi=ilp32 -march=rv32i asm.S -DSKIP_MULTICORE -o bin/$crate.o
riscv64-unknown-elf-ar crs bin/riscv32i-unknown-none-elf.a bin/$crate.o
riscv64-unknown-elf-gcc -ggdb3 -c -mabi=lp64 -march=rv64imac asm.S -o bin/$crate.o
riscv64-unknown-elf-ar crs bin/riscv64imac-unknown-none-elf.a bin/$crate.o
riscv64-unknown-elf-ar crs bin/riscv64gc-unknown-none-elf.a bin/$crate.o
Remove-Item bin/$crate.o

22
assemble.sh Normal file
View File

@ -0,0 +1,22 @@
#!/bin/bash
set -euxo pipefail
crate=xous-kernel
# remove existing blobs because otherwise this will append object files to the old blobs
mkdir -p bin
rm -f bin/*.a
riscv64-unknown-elf-gcc -ggdb3 -c -mabi=ilp32 -march=rv32imac asm.S -o bin/$crate.o
ar crs bin/riscv32imac-unknown-none-elf.a bin/$crate.o
ar crs bin/riscv32imc-unknown-none-elf.a bin/$crate.o
riscv64-unknown-elf-gcc -ggdb3 -c -mabi=ilp32 -march=rv32i asm.S -DSKIP_MULTICORE -o bin/$crate.o
ar crs bin/riscv32i-unknown-none-elf.a bin/$crate.o
riscv64-unknown-elf-gcc -ggdb3 -c -mabi=lp64 -march=rv64imac asm.S -o bin/$crate.o
ar crs bin/riscv64imac-unknown-none-elf.a bin/$crate.o
ar crs bin/riscv64gc-unknown-none-elf.a bin/$crate.o
rm bin/$crate.o

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -6,6 +6,18 @@ use std::path::PathBuf;
fn main() {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let target = env::var("TARGET").unwrap();
let name = env::var("CARGO_PKG_NAME").unwrap();
if target.starts_with("riscv") {
fs::copy(
format!("bin/{}.a", target),
out_dir.join(format!("lib{}.a", name)),
).unwrap();
println!("cargo:rustc-link-lib=static={}", name);
println!("cargo:rustc-link-search={}", out_dir.display());
}
// Put the linker script somewhere the linker can find it
fs::File::create(out_dir.join("memory.x"))

View File

@ -12,6 +12,7 @@ mod macros;
mod mem;
mod processtable;
mod syscalls;
mod timer;
pub use irq::sys_interrupt_claim;
@ -39,6 +40,8 @@ fn xous_main() -> ! {
}
let uart = debug::DEFAULT_UART;
sys_interrupt_claim(0, timer::irq).unwrap();
timer::time_init();
// Enable "RX_EMPTY" interrupt
uart.enable_rx();
@ -50,10 +53,19 @@ fn xous_main() -> ! {
let mut mm = MemoryManager::new();
println!("Creating process table...");
let mut _pt = ProcessTable::new(&mut mm);
ProcessTable::new(mm, kmain);
panic!("fell off main");
}
fn kmain(mm: MemoryManager, pt: ProcessTable) -> ! {
println!("Entering main loop");
let mut last_time = timer::get_time();
loop {
let new_time = timer::get_time();
if new_time >= last_time + 1000 {
last_time = new_time;
println!("Uptime: {} ms", new_time);
}
// unsafe { vexriscv::asm::wfi() };
}
}

View File

@ -25,8 +25,8 @@ const IO_PAGE_COUNT: usize = IO_SIZE;
const LCD_PAGE_COUNT: usize = LCD_SIZE / PAGE_SIZE;
pub struct MemoryManager {
flash: [XousPid; FLASH_PAGE_COUNT],
ram: [XousPid; RAM_PAGE_COUNT],
flash: [XousPid; FLASH_PAGE_COUNT],
io: [XousPid; IO_PAGE_COUNT],
lcd: [XousPid; LCD_PAGE_COUNT],
}
@ -241,22 +241,25 @@ impl MemoryManager {
}
/// Create an identity mapping, copying the kernel to itself
pub fn create_identity(&mut self, process: &Process, pid: XousPid) -> Result<(), XousError> {
pub fn create_identity(&mut self, process: &Process) -> 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
// );
let ranges = [
mem_range!(&_sbss, &_ebss),
mem_range!(&_sdata, &_edata),
mem_range!(&_estack, &_sstack), // NOTE: Stack is reversed
mem_range!(&_stext, &_etext),
];
for range in &ranges {
for region in range.clone() {
// mm.claim_page(region & !0xfff, 1)
// .expect("Unable to claim region for PID 1");
self.map_page(
pt,
flash_idx * PAGE_SIZE + FLASH_START,
flash_idx * PAGE_SIZE + FLASH_START,
region,
region,
)?;
print!("Entries mapped: >");
let mut i = 0;
@ -270,6 +273,18 @@ impl MemoryManager {
println!("");
}
}
// 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
// );
// }
// }
// for (idx, page) in flash_orig.iter().enumerate() {
Ok(())
}

View File

@ -1,7 +1,7 @@
use crate::definitions::{MemoryAddress, XousError, XousPid};
use crate::mem::MemoryManager;
use crate::{filled_array, print, println};
use vexriscv::register::{satp, mstatus};
use vexriscv::register::{mstatus, satp};
const MAX_PROCESS_COUNT: usize = 256;
@ -26,8 +26,16 @@ pub struct ProcessTable {
processes: [Process; MAX_PROCESS_COUNT],
}
extern "Rust" {
fn start_kmain(
kmain: extern "Rust" fn(MemoryManager, ProcessTable) -> !,
mm: MemoryManager,
pt: ProcessTable,
) -> !;
}
impl ProcessTable {
pub fn new(mm: &mut MemoryManager) -> Self {
pub fn new(mut mm: MemoryManager, kmain: fn(MemoryManager, ProcessTable) -> !) -> ! {
let mut pt = ProcessTable {
processes: filled_array![Process { satp: 0 }; 256],
};
@ -36,7 +44,7 @@ impl ProcessTable {
// 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)
mm.create_identity(&pt.processes[1])
.expect("Unable to create identity mapping");
println!("PID 1: {:?} root page @ {:08x}", pt.processes[1], root_page);
println!("Enabling MMU...");
@ -51,7 +59,7 @@ impl ProcessTable {
// Switch to Supervisor mode
mstatus::set_mpp(mstatus::MPP::Supervisor);
};
println!("MMU enabled");
pt
println!("MMU enabled, jumping to kmain");
unsafe { start_kmain(kmain, mm, pt) }
}
}

43
src/timer.rs Normal file
View File

@ -0,0 +1,43 @@
static mut TIME_MS: u32 = 0;
pub fn irq(_irq_number: usize) {
let timer_base = 0xE0002800 as *mut u8;
unsafe {
TIME_MS = TIME_MS + 1;
timer_base.add(0x3c).write_volatile(1);
};
}
pub fn get_time() -> u32 {
unsafe { TIME_MS }
}
pub fn time_init() {
let timer_base = 0xE0002800 as *mut u8;
let period = 12_000_000 / 1000; // 12 MHz, 1 ms timer
unsafe {
// Disable, so we can update it
timer_base.add(0x20).write_volatile(0);
// Update "reload" register
timer_base.add(0x10).write_volatile((period >> 24) as u8);
timer_base.add(0x14).write_volatile((period >> 16) as u8);
timer_base.add(0x18).write_volatile((period >> 8) as u8);
timer_base.add(0x1c).write_volatile((period >> 0) as u8);
// Update "load" register
timer_base.add(0x00).write_volatile((period >> 24) as u8);
timer_base.add(0x04).write_volatile((period >> 16) as u8);
timer_base.add(0x08).write_volatile((period >> 8) as u8);
timer_base.add(0x0c).write_volatile((period >> 0) as u8);
// Enable ISR
timer_base.add(0x40).write_volatile(1);
// Set "pending" as well to clear it
timer_base.add(0x38).write_volatile(1);
// Finally, enable it
timer_base.add(0x20).write_volatile(1);
}
}