Signed-off-by: Sean Cross <sean@xobs.io>
master
Sean Cross 3 years ago
parent 95951535e4
commit a06bd2aa0e
  1. 10
      asm.S
  2. BIN
      bin/riscv32i-unknown-none-elf.a
  3. BIN
      bin/riscv32imac-unknown-none-elf.a
  4. BIN
      bin/riscv32imc-unknown-none-elf.a
  5. BIN
      bin/riscv64gc-unknown-none-elf.a
  6. BIN
      bin/riscv64imac-unknown-none-elf.a
  7. 16
      src/debug.rs
  8. 68
      src/main.rs
  9. 56
      src/mem.rs
  10. 14
      src/processtable.rs
  11. 16
      src/syscalls.rs
  12. 66
      src/uart.rs

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.

@ -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(())
}

@ -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 {}
}

@ -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.

@ -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…
Cancel
Save