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
|
#endif
|
||||||
#define REGBYTES (1 << LOG_REGBYTES)
|
#define REGBYTES (1 << LOG_REGBYTES)
|
||||||
|
|
||||||
|
.global enable_mmu
|
||||||
.global return_from_interrupt
|
.global return_from_interrupt
|
||||||
.text
|
.text
|
||||||
|
enable_mmu:
|
||||||
|
la sp, _estack // Trash the stack and start over
|
||||||
return_from_interrupt:
|
return_from_interrupt:
|
||||||
la sp, _estack
|
|
||||||
mret // Return to kmain
|
mret // Return to kmain
|
||||||
|
|
||||||
|
.global flush_mmu
|
||||||
|
flush_mmu:
|
||||||
|
sfence.vma
|
||||||
|
ret
|
||||||
|
|
||||||
|
.global my_fence
|
||||||
.global read_satp
|
.global read_satp
|
||||||
.text
|
.text
|
||||||
read_satp:
|
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 core::fmt::{Error, Write};
|
||||||
use crate::MemoryManager;
|
|
||||||
use crate::definitions::XousError;
|
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! print
|
macro_rules! print
|
||||||
@ -33,13 +33,13 @@ pub const DEFAULT_UART: Uart = Uart {
|
|||||||
};
|
};
|
||||||
|
|
||||||
impl Uart {
|
impl Uart {
|
||||||
// pub fn new(base_addr: usize) -> Uart {
|
|
||||||
// Uart {
|
|
||||||
// base: base_addr as *mut usize,
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
pub fn init(&self) -> Result<(), XousError> {
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
68
src/main.rs
68
src/main.rs
@ -31,7 +31,7 @@ fn handle_panic(arg: &PanicInfo) -> ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
fn return_from_interrupt() -> !;
|
fn enable_mmu() -> !;
|
||||||
}
|
}
|
||||||
extern "C" {
|
extern "C" {
|
||||||
/// Debug function to read the current SATP. Useful since Renode
|
/// 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");
|
.expect("Couldn't create identity mapping for PID1");
|
||||||
|
|
||||||
println!("MMU enabled, jumping to kmain");
|
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() });
|
println!("SATP: {:08x}", unsafe { read_satp() });
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
mstatus::set_spp(mstatus::SPP::Supervisor);
|
// When we do an "mret", return to supervisor mode.
|
||||||
mstatus::set_mpp(mstatus::MPP::Supervisor);
|
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
|
/// This function runs with the MMU enabled, as part of PID 1
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
fn kmain() -> ! {
|
fn kmain() -> ! {
|
||||||
@ -75,16 +113,14 @@ fn kmain() -> ! {
|
|||||||
mie::set_msoft();
|
mie::set_msoft();
|
||||||
mie::set_mtimer();
|
mie::set_mtimer();
|
||||||
mie::set_mext();
|
mie::set_mext();
|
||||||
mstatus::set_mpp(mstatus::MPP::Supervisor);
|
// mstatus::set_spie();
|
||||||
mstatus::set_spie();
|
|
||||||
mstatus::set_mie(); // Enable CPU interrupts
|
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("kmain: SATP: {:08x}", satp::read().bits());
|
|
||||||
println!("kmain: MSTATUS: {:?}", mstatus::read());
|
|
||||||
|
|
||||||
let uart = debug::DEFAULT_UART;
|
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();
|
// sys_interrupt_claim(0, timer::irq).unwrap();
|
||||||
// timer::time_init();
|
// timer::time_init();
|
||||||
@ -94,6 +130,10 @@ fn kmain() -> ! {
|
|||||||
|
|
||||||
sys_interrupt_claim(2, debug::irq).expect("Couldn't claim interrupt 2");
|
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");
|
println!("Entering main loop");
|
||||||
// let mut last_time = timer::get_time();
|
// let mut last_time = timer::get_time();
|
||||||
loop {
|
loop {
|
||||||
@ -112,9 +152,9 @@ pub fn trap_handler() {
|
|||||||
let irqs_pending = vmip::read();
|
let irqs_pending = vmip::read();
|
||||||
|
|
||||||
if mc.is_exception() {
|
if mc.is_exception() {
|
||||||
println!("CPU Exception");
|
|
||||||
let ex = exception::RiscvException::from_regs(mc.bits(), mepc::read(), mtval::read());
|
let ex = exception::RiscvException::from_regs(mc.bits(), mepc::read(), mtval::read());
|
||||||
println!("{}", ex);
|
// print!("CPU Exception: ");
|
||||||
|
// println!("{}", ex);
|
||||||
unsafe { vexriscv::asm::ebreak() };
|
unsafe { vexriscv::asm::ebreak() };
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
56
src/mem.rs
56
src/mem.rs
@ -158,6 +158,7 @@ impl MemoryManager {
|
|||||||
self.claim_page(region & !0xfff, 1)?;
|
self.claim_page(region & !0xfff, 1)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.claim_page(0xe000_1000, 1)?;
|
||||||
|
|
||||||
unsafe { mstatus::set_mie() };
|
unsafe { mstatus::set_mie() };
|
||||||
|
|
||||||
@ -199,7 +200,7 @@ impl MemoryManager {
|
|||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// * OutOfMemory - Tried to allocate a new pagetable, but ran out of memory.
|
/// * OutOfMemory - Tried to allocate a new pagetable, but ran out of memory.
|
||||||
fn map_page(
|
fn map_page_inner(
|
||||||
&mut self,
|
&mut self,
|
||||||
root: &mut PageTable,
|
root: &mut PageTable,
|
||||||
phys: usize,
|
phys: usize,
|
||||||
@ -272,6 +273,9 @@ impl MemoryManager {
|
|||||||
root_page, &pt, pt
|
root_page, &pt, pt
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// self.map_page_inner(pt, 0xe0001000, 0xe001000)?;
|
||||||
|
// println!("");
|
||||||
|
|
||||||
let mut ranges = [
|
let mut ranges = [
|
||||||
mem_range!(&_sbss, &_ebss),
|
mem_range!(&_sbss, &_ebss),
|
||||||
mem_range!(&_sdata, &_edata),
|
mem_range!(&_sdata, &_edata),
|
||||||
@ -280,13 +284,31 @@ impl MemoryManager {
|
|||||||
];
|
];
|
||||||
for range in &mut ranges {
|
for range in &mut ranges {
|
||||||
for region in range {
|
for region in range {
|
||||||
self.map_page(pt, region, region)?;
|
self.map_page_inner(pt, region, region)?;
|
||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
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
|
/// Mark a given address as being owned by the specified process ID
|
||||||
fn claim_page(&mut self, addr: usize, pid: XousPid) -> Result<(), XousError> {
|
fn claim_page(&mut self, addr: usize, pid: XousPid) -> Result<(), XousError> {
|
||||||
let mut mm = unsafe { &mut MM };
|
let mut mm = unsafe { &mut MM };
|
||||||
@ -316,4 +338,34 @@ impl MemoryManager {
|
|||||||
_ => Err(XousError::BadAddress),
|
_ => 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::mem::MemoryManager;
|
||||||
use crate::{filled_array, print, println};
|
use crate::{filled_array, print, println};
|
||||||
use vexriscv::register::{mepc, mstatus, satp};
|
use vexriscv::register::{mepc, mstatus, satp};
|
||||||
|
use vexriscv::asm::sfence_vma;
|
||||||
|
|
||||||
const MAX_PROCESS_COUNT: usize = 256;
|
const MAX_PROCESS_COUNT: usize = 256;
|
||||||
static mut CURRENT_SATP: usize = 0;
|
static mut CURRENT_SATP: usize = 0;
|
||||||
@ -22,6 +23,7 @@ static mut PT: ProcessTableInner = ProcessTableInner {
|
|||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
fn kmain(mm: MemoryManager, pt: ProcessTable) -> !;
|
fn kmain(mm: MemoryManager, pt: ProcessTable) -> !;
|
||||||
|
fn flush_mmu(r1: usize, r2: usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::fmt::Debug for Process {
|
impl core::fmt::Debug for Process {
|
||||||
@ -58,6 +60,7 @@ impl ProcessTableInner {
|
|||||||
}
|
}
|
||||||
satp::write(new_satp);
|
satp::write(new_satp);
|
||||||
mepc::write(pc);
|
mepc::write(pc);
|
||||||
|
unsafe { flush_mmu(0, 0) };
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,9 +107,16 @@ pub fn sys_memory_allocate(
|
|||||||
virt: Option<MemoryAddress>,
|
virt: Option<MemoryAddress>,
|
||||||
size: MemorySize,
|
size: MemorySize,
|
||||||
) -> Result<MemoryAddress, XousError> {
|
) -> Result<MemoryAddress, XousError> {
|
||||||
|
let mut mm = MemoryManager::new()?;
|
||||||
match phys {
|
match phys {
|
||||||
Some(addr) => {}
|
Some(paddr) => match virt {
|
||||||
None => {}
|
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())
|
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.
|
/// 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
|
/// * **OutOfMemory**: A contiguous chunk of memory couldn't be found, or the system's
|
||||||
/// memory size has been exceeded.
|
/// memory size has been exceeded.
|
||||||
#[allow(dead_code)]
|
// #[allow(dead_code)]
|
||||||
pub fn sys_memory_allocate(
|
// pub fn sys_memory_allocate(
|
||||||
phys: Option<MemoryAddress>,
|
// phys: Option<MemoryAddress>,
|
||||||
virt: Option<MemoryAddress>,
|
// virt: Option<MemoryAddress>,
|
||||||
size: MemorySize,
|
// size: MemorySize,
|
||||||
) -> Result<MemoryAddress, XousError> {
|
// ) -> Result<MemoryAddress, XousError> {
|
||||||
crate::processtable::sys_memory_allocate(phys, virt, size)
|
// crate::processtable::sys_memory_allocate(phys, virt, size)
|
||||||
}
|
// }
|
||||||
|
|
||||||
extern "Rust" {
|
extern "Rust" {
|
||||||
/// Allocates kernel structures for a new process, and returns the new PID.
|
/// 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