wip commit
Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
95951535e4
commit
a06bd2aa0e
10
asm.S
10
asm.S
@ -9,12 +9,20 @@
|
||||
#endif
|
||||
#define REGBYTES (1 << LOG_REGBYTES)
|
||||
|
||||
.global enable_mmu
|
||||
.global return_from_interrupt
|
||||
.text
|
||||
enable_mmu:
|
||||
la sp, _estack // Trash the stack and start over
|
||||
return_from_interrupt:
|
||||
la sp, _estack
|
||||
mret // Return to kmain
|
||||
|
||||
.global flush_mmu
|
||||
flush_mmu:
|
||||
sfence.vma
|
||||
ret
|
||||
|
||||
.global my_fence
|
||||
.global read_satp
|
||||
.text
|
||||
read_satp:
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
16
src/debug.rs
16
src/debug.rs
@ -1,6 +1,6 @@
|
||||
use crate::definitions::{XousError, MemoryAddress, MemorySize};
|
||||
// use crate::syscalls::sys_memory_allocate;
|
||||
use core::fmt::{Error, Write};
|
||||
use crate::MemoryManager;
|
||||
use crate::definitions::XousError;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! print
|
||||
@ -33,13 +33,13 @@ pub const DEFAULT_UART: Uart = Uart {
|
||||
};
|
||||
|
||||
impl Uart {
|
||||
// pub fn new(base_addr: usize) -> Uart {
|
||||
// Uart {
|
||||
// base: base_addr as *mut usize,
|
||||
// }
|
||||
// }
|
||||
pub fn init(&self) -> Result<(), XousError> {
|
||||
// mm.claim_page(self.base as usize, 1)
|
||||
// sys_memory_allocate(
|
||||
// Some(MemoryAddress::new(0xe0001800).unwrap()),
|
||||
// Some(MemoryAddress::new(0xe0001800).unwrap()),
|
||||
// MemorySize::new(4096).unwrap(),
|
||||
// )
|
||||
// .expect("Couldn't identity map");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
68
src/main.rs
68
src/main.rs
@ -31,7 +31,7 @@ fn handle_panic(arg: &PanicInfo) -> ! {
|
||||
}
|
||||
|
||||
extern "Rust" {
|
||||
fn return_from_interrupt() -> !;
|
||||
fn enable_mmu() -> !;
|
||||
}
|
||||
extern "C" {
|
||||
/// Debug function to read the current SATP. Useful since Renode
|
||||
@ -56,17 +56,55 @@ fn mmu_init() -> ! {
|
||||
.expect("Couldn't create identity mapping for PID1");
|
||||
|
||||
println!("MMU enabled, jumping to kmain");
|
||||
pt.switch_to(process1, kmain as usize).expect("Couldn't switch to PID1");
|
||||
pt.switch_to(process1, kmain as usize)
|
||||
.expect("Couldn't switch to PID1");
|
||||
println!("SATP: {:08x}", unsafe { read_satp() });
|
||||
|
||||
unsafe {
|
||||
mstatus::set_spp(mstatus::SPP::Supervisor);
|
||||
// When we do an "mret", return to supervisor mode.
|
||||
mstatus::set_mpp(mstatus::MPP::Supervisor);
|
||||
println!("kmain: MSTATUS: {:?}", mstatus::read());
|
||||
return_from_interrupt()
|
||||
|
||||
// Additionally, enable CPU interrupts
|
||||
mstatus::set_mie();
|
||||
|
||||
println!("loader: MSTATUS: {:?}", mstatus::read());
|
||||
enable_mmu()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[inline(never)]
|
||||
fn test_good_write() {
|
||||
let good_ptr = 0x4001_6000 as *mut u32;
|
||||
// print!("Good ptr write:");
|
||||
unsafe { good_ptr.write_volatile(0x12345678) };
|
||||
// print!("Ok\r\nGood ptr read: ");
|
||||
let val = unsafe { good_ptr.read_volatile() };
|
||||
// println!("{:08x}", val);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[inline(never)]
|
||||
fn test_bad_write() {
|
||||
let bad_ptr = 0x4001_f000 as *mut u32;
|
||||
unsafe { bad_ptr.write_volatile(0x98765432) };
|
||||
let val = unsafe { bad_ptr.read_volatile() };
|
||||
// print!("Bad ptr write:");
|
||||
// print!("Ok\r\nBad ptr read: ");
|
||||
// println!("{:08x}", val);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[inline(never)]
|
||||
fn test_uart_write() {
|
||||
let io_ptr = 0xe000_1800 as *mut u32;
|
||||
unsafe { io_ptr.add(0).write_volatile(65) };
|
||||
// print!("UART ptr write: ");
|
||||
// print!(" Ok\r\nUART ptr read: ");
|
||||
let val = unsafe { io_ptr.add(0).read_volatile() };
|
||||
println!("{:08x}", val);
|
||||
}
|
||||
|
||||
/// This function runs with the MMU enabled, as part of PID 1
|
||||
#[no_mangle]
|
||||
fn kmain() -> ! {
|
||||
@ -75,16 +113,14 @@ fn kmain() -> ! {
|
||||
mie::set_msoft();
|
||||
mie::set_mtimer();
|
||||
mie::set_mext();
|
||||
mstatus::set_mpp(mstatus::MPP::Supervisor);
|
||||
mstatus::set_spie();
|
||||
mstatus::set_mie(); // Enable CPU interrupts
|
||||
// mstatus::set_spie();
|
||||
}
|
||||
|
||||
println!("kmain: SATP: {:08x}", satp::read().bits());
|
||||
println!("kmain: MSTATUS: {:?}", mstatus::read());
|
||||
|
||||
let uart = debug::DEFAULT_UART;
|
||||
uart.init();
|
||||
// uart.init();
|
||||
|
||||
// println!("kmain: SATP: {:08x}", satp::read().bits());
|
||||
// println!("kmain: MSTATUS: {:?}", mstatus::read());
|
||||
|
||||
// sys_interrupt_claim(0, timer::irq).unwrap();
|
||||
// timer::time_init();
|
||||
@ -94,6 +130,10 @@ fn kmain() -> ! {
|
||||
|
||||
sys_interrupt_claim(2, debug::irq).expect("Couldn't claim interrupt 2");
|
||||
|
||||
test_good_write();
|
||||
test_uart_write();
|
||||
test_bad_write();
|
||||
|
||||
println!("Entering main loop");
|
||||
// let mut last_time = timer::get_time();
|
||||
loop {
|
||||
@ -112,9 +152,9 @@ pub fn trap_handler() {
|
||||
let irqs_pending = vmip::read();
|
||||
|
||||
if mc.is_exception() {
|
||||
println!("CPU Exception");
|
||||
let ex = exception::RiscvException::from_regs(mc.bits(), mepc::read(), mtval::read());
|
||||
println!("{}", ex);
|
||||
// print!("CPU Exception: ");
|
||||
// println!("{}", ex);
|
||||
unsafe { vexriscv::asm::ebreak() };
|
||||
loop {}
|
||||
}
|
||||
|
56
src/mem.rs
56
src/mem.rs
@ -158,6 +158,7 @@ impl MemoryManager {
|
||||
self.claim_page(region & !0xfff, 1)?;
|
||||
}
|
||||
}
|
||||
self.claim_page(0xe000_1000, 1)?;
|
||||
|
||||
unsafe { mstatus::set_mie() };
|
||||
|
||||
@ -199,7 +200,7 @@ impl MemoryManager {
|
||||
/// # Errors
|
||||
///
|
||||
/// * OutOfMemory - Tried to allocate a new pagetable, but ran out of memory.
|
||||
fn map_page(
|
||||
fn map_page_inner(
|
||||
&mut self,
|
||||
root: &mut PageTable,
|
||||
phys: usize,
|
||||
@ -272,6 +273,9 @@ impl MemoryManager {
|
||||
root_page, &pt, pt
|
||||
);
|
||||
|
||||
// self.map_page_inner(pt, 0xe0001000, 0xe001000)?;
|
||||
// println!("");
|
||||
|
||||
let mut ranges = [
|
||||
mem_range!(&_sbss, &_ebss),
|
||||
mem_range!(&_sdata, &_edata),
|
||||
@ -280,13 +284,31 @@ impl MemoryManager {
|
||||
];
|
||||
for range in &mut ranges {
|
||||
for region in range {
|
||||
self.map_page(pt, region, region)?;
|
||||
self.map_page_inner(pt, region, region)?;
|
||||
println!("");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn map_page(&mut self, satp: usize, phys: usize, virt: usize) -> Result<MemoryAddress, XousError> {
|
||||
let root_page = (satp & ((1 << 22) - 1)) << 12;
|
||||
let pid = ((satp >> 22) & ((1<<9)-1)) as XousPid;
|
||||
assert!(root_page >= RAM_START);
|
||||
assert!(root_page < RAM_END);
|
||||
assert!(pid != 0);
|
||||
let pt = unsafe { &mut (*(root_page as *mut PageTable)) };
|
||||
|
||||
self.claim_page(phys, pid)?;
|
||||
match self.map_page_inner(pt, phys, virt) {
|
||||
Ok(_) => Ok(MemoryAddress::new(virt).expect("Virt address was not 0")),
|
||||
Err(e) => {
|
||||
self.release_page(phys, pid);
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark a given address as being owned by the specified process ID
|
||||
fn claim_page(&mut self, addr: usize, pid: XousPid) -> Result<(), XousError> {
|
||||
let mut mm = unsafe { &mut MM };
|
||||
@ -316,4 +338,34 @@ impl MemoryManager {
|
||||
_ => Err(XousError::BadAddress),
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark a given address as being owned by the specified process ID
|
||||
fn release_page(&mut self, addr: usize, pid: XousPid) -> Result<(), XousError> {
|
||||
let mut mm = unsafe { &mut MM };
|
||||
|
||||
fn release_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] != pid {
|
||||
return Err(XousError::MemoryInUse);
|
||||
}
|
||||
tbl[page] = 0;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Ensure the address lies on a page boundary
|
||||
if addr & 0xfff != 0 {
|
||||
return Err(XousError::BadAlignment);
|
||||
}
|
||||
|
||||
match addr {
|
||||
FLASH_START..=FLASH_END => release_page_inner(&mut mm.flash, addr - FLASH_START, pid),
|
||||
RAM_START..=RAM_END => release_page_inner(&mut mm.ram, addr - RAM_START, pid),
|
||||
IO_START..=IO_END => release_page_inner(&mut mm.io, addr - IO_START, pid),
|
||||
LCD_START..=LCD_END => release_page_inner(&mut mm.lcd, addr - LCD_START, pid),
|
||||
_ => Err(XousError::BadAddress),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ use crate::definitions::{MemoryAddress, MemorySize, XousError, XousPid};
|
||||
use crate::mem::MemoryManager;
|
||||
use crate::{filled_array, print, println};
|
||||
use vexriscv::register::{mepc, mstatus, satp};
|
||||
use vexriscv::asm::sfence_vma;
|
||||
|
||||
const MAX_PROCESS_COUNT: usize = 256;
|
||||
static mut CURRENT_SATP: usize = 0;
|
||||
@ -22,6 +23,7 @@ static mut PT: ProcessTableInner = ProcessTableInner {
|
||||
|
||||
extern "Rust" {
|
||||
fn kmain(mm: MemoryManager, pt: ProcessTable) -> !;
|
||||
fn flush_mmu(r1: usize, r2: usize);
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for Process {
|
||||
@ -58,6 +60,7 @@ impl ProcessTableInner {
|
||||
}
|
||||
satp::write(new_satp);
|
||||
mepc::write(pc);
|
||||
unsafe { flush_mmu(0, 0) };
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -104,9 +107,16 @@ pub fn sys_memory_allocate(
|
||||
virt: Option<MemoryAddress>,
|
||||
size: MemorySize,
|
||||
) -> Result<MemoryAddress, XousError> {
|
||||
let mut mm = MemoryManager::new()?;
|
||||
match phys {
|
||||
Some(addr) => {}
|
||||
None => {}
|
||||
Some(paddr) => match virt {
|
||||
Some(vaddr) => return mm.map_page(unsafe { CURRENT_SATP }, paddr.get(), vaddr.get()),
|
||||
None => {},
|
||||
}
|
||||
None => match virt {
|
||||
Some(vaddr) => {},
|
||||
None => {},
|
||||
}
|
||||
}
|
||||
|
||||
Ok(MemoryAddress::new(4096).unwrap())
|
||||
|
@ -26,14 +26,14 @@ pub fn sys_interrupt_claim(irq: usize, f: fn(usize)) -> Result<(), XousError> {
|
||||
/// or the size isn't a multiple of the page width.
|
||||
/// * **OutOfMemory**: A contiguous chunk of memory couldn't be found, or the system's
|
||||
/// memory size has been exceeded.
|
||||
#[allow(dead_code)]
|
||||
pub fn sys_memory_allocate(
|
||||
phys: Option<MemoryAddress>,
|
||||
virt: Option<MemoryAddress>,
|
||||
size: MemorySize,
|
||||
) -> Result<MemoryAddress, XousError> {
|
||||
crate::processtable::sys_memory_allocate(phys, virt, size)
|
||||
}
|
||||
// #[allow(dead_code)]
|
||||
// pub fn sys_memory_allocate(
|
||||
// phys: Option<MemoryAddress>,
|
||||
// virt: Option<MemoryAddress>,
|
||||
// size: MemorySize,
|
||||
// ) -> Result<MemoryAddress, XousError> {
|
||||
// crate::processtable::sys_memory_allocate(phys, virt, size)
|
||||
// }
|
||||
|
||||
extern "Rust" {
|
||||
/// Allocates kernel structures for a new process, and returns the new PID.
|
||||
|
66
src/uart.rs
66
src/uart.rs
@ -1,66 +0,0 @@
|
||||
use core::fmt::{Error, Write};
|
||||
|
||||
pub struct Uart {}
|
||||
|
||||
impl Uart {
|
||||
pub fn new() -> Uart {
|
||||
Uart {}
|
||||
}
|
||||
|
||||
pub fn putc(&self, c: u8) {
|
||||
let ptr = 0xE000_1800 as *mut u32;
|
||||
unsafe {
|
||||
while ptr.add(1).read_volatile() == 0 {}
|
||||
ptr.add(0).write_volatile(c as u32);
|
||||
}
|
||||
}
|
||||
|
||||
fn get(&self, base_addr: usize) -> Option<u8> {
|
||||
let ptr = 0xE000_1800 as *mut u32;
|
||||
unsafe {
|
||||
if ptr.add(2).read_volatile() == 0 {
|
||||
Some(ptr.add(0).read_volatile() as u8)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is a slightly different syntax. Write is this "trait", meaning it is much like
|
||||
// an interface where we're just guaranteeing a certain function signature. In the Write
|
||||
// trait, one is absolutely required to be implemented, which is write_str. There are other
|
||||
// functions, but they all rely on write_str(), so their default implementation is OK for now.
|
||||
impl Write for Uart {
|
||||
// The trait Write expects us to write the function write_str
|
||||
// which looks like:
|
||||
fn write_str(&mut self, s: &str) -> Result<(), Error> {
|
||||
for c in s.bytes() {
|
||||
self.putc(c);
|
||||
}
|
||||
// Return that we succeeded.
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! print
|
||||
{
|
||||
($($args:tt)+) => ({
|
||||
use core::fmt::Write;
|
||||
let _ = write!(crate::uart::Uart::new(), $($args)+);
|
||||
});
|
||||
}
|
||||
#[macro_export]
|
||||
macro_rules! println
|
||||
{
|
||||
() => ({
|
||||
print!("\r\n")
|
||||
});
|
||||
($fmt:expr) => ({
|
||||
print!(concat!($fmt, "\r\n"))
|
||||
});
|
||||
($fmt:expr, $($args:tt)+) => ({
|
||||
print!(concat!($fmt, "\r\n"), $($args)+)
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue
Block a user