wip commit

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
2020-01-23 10:29:20 +08:00
parent 3c15bd68d3
commit 95951535e4
20 changed files with 506 additions and 183 deletions

View File

@ -1,4 +1,6 @@
use core::fmt::{Error, Write};
use crate::MemoryManager;
use crate::definitions::XousError;
#[macro_export]
macro_rules! print
@ -36,6 +38,10 @@ impl Uart {
// base: base_addr as *mut usize,
// }
// }
pub fn init(&self) -> Result<(), XousError> {
// mm.claim_page(self.base as usize, 1)
Ok(())
}
pub fn enable_rx(self) {
unsafe {

218
src/exception.rs Normal file
View File

@ -0,0 +1,218 @@
use core::fmt;
#[derive(PartialEq)]
pub enum RiscvException {
/// When things are all 0
NoException,
/// 1 0
UserSoftwareInterrupt(usize /* mepc */),
/// 1 1
SupervisorSoftwareInterrupt(usize /* mepc */),
// [reserved]
/// 1 3
MachineSoftwareInterrupt(usize /* mepc */),
/// 1 4
UserTimerInterrupt(usize /* mepc */),
/// 1 5
SupervisorTimerInterrupt(usize /* mepc */),
// [reserved]
/// 1 7
MachineTimerInterrupt(usize /* mepc */),
/// 1 8
UserExternalInterrupt(usize /* mepc */),
/// 1 9
SupervisorExternalInterrupt(usize /* mepc */),
// [reserved]
/// 1 11
MachineExternalInterrupt(usize /* mepc */),
ReservedInterrupt(usize /* unknown cause number */, usize /* mepc */),
/// 0 0
InstructionAddressMisaligned(usize /* mepc */, usize /* target address */),
/// 0 1
InstructionAccessFault(usize /* mepc */, usize /* target address */),
/// 0 2
IllegalInstruction(usize /* mepc */, usize /* instruction value */),
/// 0 3
Breakpoint(usize /* mepc */),
/// 0 4
LoadAddressMisaligned(usize /* mepc */, usize /* target address */),
/// 0 5
LoadAccessFault(usize /* mepc */, usize /* target address */),
/// 0 6
StoreAddressMisaligned(usize /* mepc */, usize /* target address */),
/// 0 7
StoreAccessFault(usize /* mepc */, usize /* target address */),
/// 0 8
CallFromUMode(usize /* mepc */),
/// 0 9
CallFromSMode(usize /* mepc */),
// [reserved]
/// 0 11
CallFromMMode(usize /* mepc */),
/// 0 12
InstructionPageFault(usize /* mepc */, usize /* target address */),
/// 0 13
LoadPageFault(usize /* mepc */, usize /* target address */),
// [reserved]
/// 0 15
StorePageFault(usize /* mepc */, usize /* target address */),
ReservedFault(
usize, /* unknown cause number */
usize, /* mepc */
usize, /* mtval */
),
}
impl fmt::Display for RiscvException {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use RiscvException::*;
match *self {
NoException => write!(f, "No trap"),
UserSoftwareInterrupt(epc) => write!(f, "User swi from 0x{:08x}", epc),
SupervisorSoftwareInterrupt(epc) => write!(f, "Supervisor swi from 0x{:08x}", epc),
// --reserved--
MachineSoftwareInterrupt(epc) => write!(f, "Machine swi at 0x{:08x}", epc),
UserTimerInterrupt(epc) => write!(f, "User timer interrupt at 0x{:08x}", epc),
SupervisorTimerInterrupt(epc) => {
write!(f, "Supervisor timer interrupt at 0x{:08x}", epc)
}
// --reserved--
MachineTimerInterrupt(epc) => write!(f, "Machine timer interrupt at 0x{:08x}", epc),
UserExternalInterrupt(epc) => write!(f, "User external interrupt at 0x{:08x}", epc),
SupervisorExternalInterrupt(epc) => {
write!(f, "Machine external interrupt at 0x{:08x}", epc)
}
// --reserved--
MachineExternalInterrupt(epc) => {
write!(f, "Supervisor external interrupt at 0x{:08x}", epc)
}
ReservedInterrupt(code, epc) => {
write!(f, "Reserved interrupt 0x{:08x} at 0x{:08x}", code, epc)
}
InstructionAddressMisaligned(epc, mtval) => write!(
f,
"Misaligned address instruction 0x{:08x} at 0x{:08x}",
mtval, epc
),
InstructionAccessFault(epc, mtval) => write!(
f,
"Instruction access fault to 0x{:08x} at 0x{:08x}",
mtval, epc
),
IllegalInstruction(epc, mtval) => {
write!(f, "Illegal instruction 0x{:08x} at 0x{:08x}", mtval, epc)
}
Breakpoint(epc) => write!(f, "Breakpoint at 0x{:08x}", epc),
LoadAddressMisaligned(epc, mtval) => write!(
f,
"Misaligned load address of 0x{:08x} at 0x{:08x}",
mtval, epc
),
LoadAccessFault(epc, mtval) => {
write!(f, "Load access fault from 0x{:08x} at 0x{:08x}", mtval, epc)
}
StoreAddressMisaligned(epc, mtval) => write!(
f,
"Misaligned store address of 0x{:08x} at 0x{:08x}",
mtval, epc
),
StoreAccessFault(epc, mtval) => {
write!(f, "Store access fault to 0x{:08x} at 0x{:08x}", mtval, epc)
}
CallFromUMode(epc) => write!(f, "Call from User mode at 0x{:08x}", epc),
CallFromSMode(epc) => write!(f, "Call from Supervisor mode at 0x{:08x}", epc),
// --reserved--
CallFromMMode(epc) => write!(f, "Call from Machine mode at 0x{:08x}", epc),
InstructionPageFault(epc, mtval) => write!(
f,
"Instruction page fault of 0x{:08x} at 0x{:08x}",
mtval, epc
),
LoadPageFault(epc, mtval) => {
write!(f, "Load page fault of 0x{:08x} at 0x{:08x}", mtval, epc)
}
// --reserved--
StorePageFault(epc, mtval) => {
write!(f, "Load page fault of 0x{:08x} at 0x{:08x}", mtval, epc)
}
ReservedFault(code, epc, mtval) => write!(
f,
"Reserved interrupt 0x{:08x} with cause 0x{:08x} at 0x{:08x}",
code, mtval, epc
),
}
}
}
impl RiscvException {
pub fn from_regs(mcause: usize, mepc: usize, mtval: usize) -> RiscvException {
use RiscvException::*;
if mepc == 0 && mtval == 0 {
return NoException;
}
match mcause {
0x80000000 => UserSoftwareInterrupt(mepc),
0x80000001 => SupervisorSoftwareInterrupt(mepc),
// --reserved--
0x80000003 => MachineSoftwareInterrupt(mepc),
0x80000004 => UserTimerInterrupt(mepc),
0x80000005 => SupervisorTimerInterrupt(mepc),
// --reserved--
0x80000007 => MachineTimerInterrupt(mepc),
0x80000008 => UserExternalInterrupt(mepc),
0x80000009 => SupervisorExternalInterrupt(mepc),
// --reserved--
0x8000000b => MachineExternalInterrupt(mepc),
0 => InstructionAddressMisaligned(mepc, mtval),
1 => InstructionAccessFault(mepc, mtval),
2 => IllegalInstruction(mepc, mtval),
3 => Breakpoint(mepc),
4 => LoadAddressMisaligned(mepc, mtval),
5 => LoadAccessFault(mepc, mtval),
6 => StoreAddressMisaligned(mepc, mtval),
7 => StoreAccessFault(mepc, mtval),
8 => CallFromUMode(mepc),
9 => CallFromSMode(mepc),
// --reserved--
11 => CallFromMMode(mepc),
12 => InstructionPageFault(mepc, mtval),
13 => LoadPageFault(mepc, mtval),
// --reserved--
15 => StorePageFault(mepc, mtval),
x @ 10 | x @ 14 | x @ 16..=0x7fffffff => ReservedFault(x, mepc, mtval),
x => {
ReservedInterrupt(x & 0x7fffffff, mepc)
}
}
}
}

View File

@ -7,6 +7,7 @@ extern crate vexriscv;
mod debug;
mod definitions;
mod exception;
mod irq;
mod macros;
mod mem;
@ -19,7 +20,7 @@ pub use irq::sys_interrupt_claim;
use core::panic::PanicInfo;
use mem::MemoryManager;
use processtable::ProcessTable;
use vexriscv::register::{mcause, mepc, mie, mstatus, vmim, vmip};
use vexriscv::register::{mcause, mepc, mie, mstatus, mtval, satp, vmim, vmip};
use xous_kernel_riscv_rt::xous_kernel_entry;
#[panic_handler]
@ -29,42 +30,78 @@ fn handle_panic(arg: &PanicInfo) -> ! {
loop {}
}
extern "Rust" {
fn return_from_interrupt() -> !;
}
extern "C" {
/// Debug function to read the current SATP. Useful since Renode
/// doesn't support reading it any other way.
fn read_satp() -> usize;
}
#[xous_kernel_entry]
fn xous_main() -> ! {
fn mmu_init() -> ! {
let mut mm = MemoryManager::new().expect("Couldn't create memory manager");
mm.init().expect("Couldn't initialize memory manager");
let mut pt = ProcessTable::new().expect("Couldn't create process table");
// Allocate a page to PID 1 to use as the root page table, then create
// an identity mapping in preparation for enabling the MMU.
let process1 = pt
.create_process(&mut mm)
.expect("Couldn't create process for PID1");
let pid1_satp = pt.satp_for(process1).expect("Couldn't find SATP for PID1");
mm.create_identity(pid1_satp)
.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");
println!("SATP: {:08x}", unsafe { read_satp() });
unsafe {
mstatus::set_spp(mstatus::SPP::Supervisor);
mstatus::set_mpp(mstatus::MPP::Supervisor);
println!("kmain: MSTATUS: {:?}", mstatus::read());
return_from_interrupt()
}
}
/// This function runs with the MMU enabled, as part of PID 1
#[no_mangle]
fn kmain() -> ! {
unsafe {
vmim::write(0); // Disable all machine interrupts
mie::set_msoft();
mie::set_mtimer();
mie::set_mext();
mstatus::set_mpp(mstatus::MPP::Supervisor);
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;
sys_interrupt_claim(0, timer::irq).unwrap();
timer::time_init();
uart.init();
// sys_interrupt_claim(0, timer::irq).unwrap();
// timer::time_init();
// Enable "RX_EMPTY" interrupt
uart.enable_rx();
println!("Starting up...");
sys_interrupt_claim(2, debug::irq).unwrap();
sys_interrupt_claim(2, debug::irq).expect("Couldn't claim interrupt 2");
println!("Creating memory manager...");
let mm = MemoryManager::new();
println!("Creating process table...");
ProcessTable::new(mm, kmain);
}
fn kmain(mm: MemoryManager, pt: ProcessTable) -> ! {
println!("Entering main loop");
let mut last_time = timer::get_time();
// 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);
}
// 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() };
}
}
@ -76,7 +113,8 @@ pub fn trap_handler() {
if mc.is_exception() {
println!("CPU Exception");
println!("{:?} @ PC: {:08x}", mc.cause(), mepc::read());
let ex = exception::RiscvException::from_regs(mc.bits(), mepc::read(), mtval::read());
println!("{}", ex);
unsafe { vexriscv::asm::ebreak() };
loop {}
}

View File

@ -24,40 +24,49 @@ 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 {
pub struct MemoryManagerInner {
ram: [XousPid; RAM_PAGE_COUNT],
flash: [XousPid; FLASH_PAGE_COUNT],
io: [XousPid; IO_PAGE_COUNT],
lcd: [XousPid; LCD_PAGE_COUNT],
}
impl core::fmt::Debug for MemoryManager {
pub struct MemoryManager {}
static mut MM: MemoryManagerInner = MemoryManagerInner {
flash: [0; FLASH_PAGE_COUNT],
ram: [0; RAM_PAGE_COUNT],
io: [0; IO_PAGE_COUNT],
lcd: [0; LCD_PAGE_COUNT],
};
impl core::fmt::Debug for MemoryManagerInner {
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
writeln!(fmt, "MemoryManager: ")?;
writeln!(fmt, "Ranges: ")?;
writeln!(
fmt,
" flash: {:08x} .. {:08x} ({})",
" flash: {:08x} .. {:08x} ({} pages)",
FLASH_START,
FLASH_END,
self.flash.len()
)?;
writeln!(
fmt,
" ram: {:08x} .. {:08x} ({})",
" ram: {:08x} .. {:08x} ({} pages)",
RAM_START,
RAM_END,
self.ram.len()
)?;
writeln!(
fmt,
" io: {:08x} .. {:08x} ({})",
" io: {:08x} .. {:08x} ({} pages)",
IO_START,
IO_END,
self.io.len()
)?;
writeln!(
fmt,
" lcd: {:08x} .. {:08x} ({})",
" lcd: {:08x} .. {:08x} ({} pages)",
LCD_START,
LCD_END,
self.lcd.len()
@ -66,6 +75,12 @@ impl core::fmt::Debug for MemoryManager {
}
}
impl core::fmt::Debug for MemoryManager {
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
unsafe { write!(fmt, "{:?}", MM) }
}
}
/// A single RISC-V page table entry. In order to resolve an address,
/// we need two entries: the top level, followed by the lower level.
struct PageTable {
@ -121,48 +136,48 @@ macro_rules! mem_range {
/// and place it at the usual offset. The MMU will not be enabled yet,
/// as the process entry has not yet been created.
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],
};
println!("Created Memory Manager: {:?}", mm);
pub fn new() -> Result<MemoryManager, XousError> {
Ok(MemoryManager {})
}
pub fn init(&mut self) -> Result<(), XousError> {
println!("Initializing Memory Manager: {:?}", self);
// Claim existing pages for PID 1, in preparation for turning on
// the MMU
// the MMU.
unsafe { mstatus::clear_mie() };
let mut ranges = [
mem_range!(&_sbss, &_ebss),
mem_range!(&_sdata, &_edata),
mem_range!(&_estack, &_sstack), // NOTE: Stack is reversed
mem_range!(&_sstack, &_estack),
mem_range!(&_stext, &_etext),
];
for range in &mut ranges {
for region in range {
mm.claim_page(region & !0xfff, 1)
.expect("Unable to claim region for PID 1");
self.claim_page(region & !0xfff, 1)?;
}
}
unsafe { mstatus::set_mie() };
mm
Ok(())
}
/// Allocate a single page to the given process.
/// Ensures the page is zeroed out prior to handing it over to
/// the specified process.
pub fn alloc_page(&mut self, pid: XousPid) -> Result<MemoryAddress, XousError> {
assert!(pid != 0);
let mut mm = unsafe { &mut MM };
// Go through all RAM pages looking for a free page.
// Optimization: start from the previous address.
// println!("Allocating page for PID {}", pid);
for index in 0..RAM_PAGE_COUNT {
// println!(" Checking {:08x}...", index * PAGE_SIZE + RAM_START);
if self.ram[index] == 0 {
self.ram[index] = pid;
if mm.ram[index] == 0 {
mm.ram[index] = pid;
let page_addr = (index * PAGE_SIZE + RAM_START) as *mut u32;
// Zero-out the page
unsafe {
@ -172,7 +187,7 @@ impl MemoryManager {
}
let new_page = unsafe { transmute::<*mut u32, usize>(page_addr) };
// println!(" Page {:08x} is free", new_page);
return Ok(NonZeroUsize::new(new_page).unwrap());
return Ok(NonZeroUsize::new(new_page).expect("Allocated an invalid page"));
}
}
Err(XousError::OutOfMemory)
@ -246,55 +261,36 @@ impl MemoryManager {
}
/// Create an identity mapping, copying the kernel to itself
pub fn create_identity(&mut self, process: &Process) -> Result<(), XousError> {
let root_page = (process.satp & ((1 << 22) - 1)) << 12;
pub fn create_identity(&mut self, satp: MemoryAddress) -> Result<(), XousError> {
let root_page = (satp.get() & ((1 << 22) - 1)) << 12;
assert!(root_page >= RAM_START);
assert!(root_page < RAM_END);
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
"Root page: {:08x} pt: {:p} pt: {:p}",
root_page, &pt, pt
);
let mut ranges = [
mem_range!(&_sbss, &_ebss),
mem_range!(&_sdata, &_edata),
mem_range!(&_estack, &_sstack), // NOTE: Stack is reversed
mem_range!(&_sstack, &_estack),
mem_range!(&_stext, &_etext),
];
for range in &mut ranges {
for region in range {
// mm.claim_page(region & !0xfff, 1)
// .expect("Unable to claim region for PID 1");
self.map_page(pt, region, region)?;
// print!("Entries mapped: >");
// let mut i = 0;
// for (entry_idx, entry) in pt.entries.iter().enumerate() {
// i = i + 1;
// if *entry != 0 {
// print!(" {}:{:08x}", entry_idx, entry);
// }
// }
// println!(" < ({})", i);
println!("");
}
}
self.map_page(pt, 0xE000_1800, 0xE000_1800)?;
// 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(())
}
/// 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 };
fn claim_page_inner(tbl: &mut [u8], addr: usize, pid: XousPid) -> Result<(), XousError> {
let page = addr / PAGE_SIZE;
if page > tbl.len() {
@ -313,10 +309,10 @@ impl MemoryManager {
}
match addr {
FLASH_START..=FLASH_END => claim_page_inner(&mut self.flash, addr - FLASH_START, pid),
RAM_START..=RAM_END => claim_page_inner(&mut self.ram, addr - RAM_START, pid),
IO_START..=IO_END => claim_page_inner(&mut self.io, addr - IO_START, pid),
LCD_START..=LCD_END => claim_page_inner(&mut self.lcd, addr - LCD_START, pid),
FLASH_START..=FLASH_END => claim_page_inner(&mut mm.flash, addr - FLASH_START, pid),
RAM_START..=RAM_END => claim_page_inner(&mut mm.ram, addr - RAM_START, pid),
IO_START..=IO_END => claim_page_inner(&mut mm.io, addr - IO_START, pid),
LCD_START..=LCD_END => claim_page_inner(&mut mm.lcd, addr - LCD_START, pid),
_ => Err(XousError::BadAddress),
}
}

View File

@ -1,14 +1,29 @@
use crate::definitions::{MemoryAddress, XousError, XousPid};
use crate::definitions::{MemoryAddress, MemorySize, XousError, XousPid};
use crate::mem::MemoryManager;
use crate::{filled_array, print, println};
use vexriscv::register::{mstatus, satp};
use vexriscv::register::{mepc, mstatus, satp};
const MAX_PROCESS_COUNT: usize = 256;
static mut CURRENT_SATP: usize = 0;
pub struct Process {
pub satp: usize,
}
pub struct ProcessTableInner {
processes: [Process; MAX_PROCESS_COUNT],
}
pub struct ProcessTable {}
static mut PT: ProcessTableInner = ProcessTableInner {
processes: filled_array![Process { satp: 0 }; 256],
};
extern "Rust" {
fn kmain(mm: MemoryManager, pt: ProcessTable) -> !;
}
impl core::fmt::Debug for Process {
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
write!(
@ -22,48 +37,77 @@ impl core::fmt::Debug for Process {
}
}
pub struct ProcessTable {
processes: [Process; MAX_PROCESS_COUNT],
}
impl ProcessTableInner {
/// Switch to the new PID when we return to supervisor mode
pub fn switch_to(&self, pid: XousPid, pc: usize) -> Result<(), XousError> {
if pid == 0 {
return Err(XousError::ProcessNotFound);
}
if pid >= 255 {
return Err(XousError::ProcessNotFound);
}
extern "Rust" {
fn start_kmain(
kmain: extern "Rust" fn(MemoryManager, ProcessTable) -> !,
mm: MemoryManager,
pt: ProcessTable,
) -> !;
}
extern "C" {
fn read_satp() -> usize;
let pid = pid as usize;
let new_satp = self.processes[pid].satp;
if new_satp & (1 << 31) == 0 {
return Err(XousError::ProcessNotFound);
}
unsafe {
CURRENT_SATP = new_satp;
}
satp::write(new_satp);
mepc::write(pc);
Ok(())
}
pub fn alloc_pid(&mut self) -> Result<XousPid, XousError> {
for (idx, process) in self.processes.iter().enumerate() {
if process.satp == 0 {
return Ok((idx + 1) as XousPid);
}
}
Err(XousError::ProcessNotChild)
}
}
impl ProcessTable {
pub fn new(mut mm: MemoryManager, kmain: fn(MemoryManager, ProcessTable) -> !) -> ! {
let mut pt = ProcessTable {
processes: filled_array![Process { satp: 0 }; 256],
};
pub fn new() -> Result<ProcessTable, XousError> {
Ok(ProcessTable {})
}
// Allocate a root page table for PID 1. Also mark the "ASID" as "1"
// for "PID 1"
let root_page = mm.alloc_page(1).unwrap().get();
pt.processes[1].satp = (root_page >> 12) | (1 << 22);
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...");
unsafe {
// Set the MMU pointer to our identity mapping
satp::set(
satp::Mode::Sv32,
(pt.processes[1].satp >> 22) & ((1 << 9) - 1),
(pt.processes[1].satp >> 0) & ((1 << 22) - 1),
);
pub fn create_process(&mut self, mm: &mut MemoryManager) -> Result<XousPid, XousError> {
let mut pt = unsafe { &mut PT };
let pid = pt.alloc_pid()?;
let root_page = mm.alloc_page(pid).expect("Couldn't allocate memory for new process page tables");
let root_page = root_page.get();
pt.processes[pid as usize].satp = (root_page >> 12) | ((pid as usize) << 22) | (1 << 31);
Ok(pid)
}
// Switch to Supervisor mode
mstatus::set_mpp(mstatus::MPP::Supervisor);
};
println!("MMU enabled, jumping to kmain");
println!("SATP: {:08x}", unsafe { read_satp() });
unsafe { start_kmain(kmain, mm, pt) }
pub fn satp_for(&self, pid: XousPid) -> Result<MemoryAddress, XousError> {
let pt = unsafe { &PT };
match MemoryAddress::new(pt.processes[pid as usize].satp) {
Some(addr) => Ok(addr),
None => Err(XousError::ProcessNotFound)
}
}
pub fn switch_to(&self, pid: XousPid, pc: usize) -> Result<(), XousError> {
let pt = unsafe { &PT };
pt.switch_to(pid, pc)
}
}
pub fn sys_memory_allocate(
phys: Option<MemoryAddress>,
virt: Option<MemoryAddress>,
size: MemorySize,
) -> Result<MemoryAddress, XousError> {
match phys {
Some(addr) => {}
None => {}
}
Ok(MemoryAddress::new(4096).unwrap())
}

View File

@ -13,6 +13,28 @@ pub fn sys_interrupt_claim(irq: usize, f: fn(usize)) -> Result<(), XousError> {
crate::irq::sys_interrupt_claim(irq, f)
}
/// Allocates pages of memory, equal to a total of `size
/// bytes. If a physical address is specified, then this
/// can be used to allocate regions such as memory-mapped I/O.
/// If a virtual address is specified, then the returned
/// pages are located at that address. Otherwise, they
/// are located at an unspecified offset.
///
/// # Errors
///
/// * **BadAlignment**: Either the physical or virtual addresses aren't page-aligned,
/// 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)
}
extern "Rust" {
/// Allocates kernel structures for a new process, and returns the new PID.
/// This removes `page_count` page tables from the calling process at `origin_address`
@ -150,24 +172,6 @@ extern "Rust" {
#[allow(dead_code)]
pub fn sys_process_terminate(process_id: XousPid) -> Result<(), XousError>;
/// Allocates pages of memory, equal to a total of `size
/// bytes. If a physical address is specified, then this
/// can be used to allocate regions such as memory-mapped I/O.
/// If a virtual address is specified, then the returned
/// pages are located at that address. Otherwise, they
/// are located at an unspecified offset.
///
/// # Errors
///
/// * **BadAlignment**: Either the physical or virtual addresses aren't page-aligned, 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>;
/// Equivalent to the Unix `sbrk` call. Adjusts the
/// heap size to be equal to the specified value. Heap
/// sizes start out at 0 bytes in new processes.

View File

@ -1,43 +1,70 @@
static mut TIME_MS: u32 = 0;
pub struct Timer {
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);
};
/// Address of the timer
base: *mut u8,
/// Number of clock cycles before the timer fires
period: u32,
/// Current count of the timer, in milliseconds
time_ms: u32,
}
pub fn get_time() -> u32 {
unsafe { TIME_MS }
}
impl Timer {
pub fn new() -> Timer {
Timer {
base: 0xE0002800 as *mut u8,
period: 12_000_000 / 1000, // 12 MHz, 1 ms timer
time_ms: 0,
}
}
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);
pub fn enable(&self) {
unsafe {
// Disable, so we can update it
self.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 "reload" register
self.base.add(0x10).write_volatile((self.period >> 24) as u8);
self.base.add(0x14).write_volatile((self.period >> 16) as u8);
self.base.add(0x18).write_volatile((self.period >> 8) as u8);
self.base.add(0x1c).write_volatile((self.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);
// Update "load" register
self.base.add(0x00).write_volatile((self.period >> 24) as u8);
self.base.add(0x04).write_volatile((self.period >> 16) as u8);
self.base.add(0x08).write_volatile((self.period >> 8) as u8);
self.base.add(0x0c).write_volatile((self.period >> 0) as u8);
// Enable ISR
timer_base.add(0x40).write_volatile(1);
// Enable ISR
self.base.add(0x40).write_volatile(1);
// Set "pending" as well to clear it
timer_base.add(0x38).write_volatile(1);
// Set "pending" as well to clear it
self.base.add(0x38).write_volatile(1);
// Finally, enable it
timer_base.add(0x20).write_volatile(1);
// Finally, enable it
self.base.add(0x20).write_volatile(1);
}
}
pub fn elapsed_ms(&self) -> u32 {
return self.time_ms;
}
}
// 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
// }