xous: wip commit
printf works now, and we're getting the page table stuff set up. Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
		
							
								
								
									
										23
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "cSpell.words": [
 | 
				
			||||||
 | 
					        "TXFULL",
 | 
				
			||||||
 | 
					        "Uart",
 | 
				
			||||||
 | 
					        "concat",
 | 
				
			||||||
 | 
					        "ebss",
 | 
				
			||||||
 | 
					        "edata",
 | 
				
			||||||
 | 
					        "eheap",
 | 
				
			||||||
 | 
					        "estack",
 | 
				
			||||||
 | 
					        "etext",
 | 
				
			||||||
 | 
					        "getc",
 | 
				
			||||||
 | 
					        "mstatus",
 | 
				
			||||||
 | 
					        "pagetable",
 | 
				
			||||||
 | 
					        "putc",
 | 
				
			||||||
 | 
					        "satp",
 | 
				
			||||||
 | 
					        "sbss",
 | 
				
			||||||
 | 
					        "sdata",
 | 
				
			||||||
 | 
					        "sheap",
 | 
				
			||||||
 | 
					        "sidata",
 | 
				
			||||||
 | 
					        "sstack",
 | 
				
			||||||
 | 
					        "stext"
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										89
									
								
								src/debug.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/debug.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
				
			|||||||
 | 
					use core::fmt::{Error, Write};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[macro_export]
 | 
				
			||||||
 | 
					macro_rules! print
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						($($args:tt)+) => ({
 | 
				
			||||||
 | 
								use core::fmt::Write;
 | 
				
			||||||
 | 
								let _ = write!(crate::debug::DEFAULT_UART, $($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)+)
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct Uart {
 | 
				
			||||||
 | 
					    base: *mut usize,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub const DEFAULT_UART: Uart = Uart {
 | 
				
			||||||
 | 
					    base: 0xE000_1800 as *mut usize,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Uart {
 | 
				
			||||||
 | 
					    // pub fn new(base_addr: usize) -> Uart {
 | 
				
			||||||
 | 
					    //     Uart {
 | 
				
			||||||
 | 
					    //         base: base_addr as *mut usize,
 | 
				
			||||||
 | 
					    //     }
 | 
				
			||||||
 | 
					    // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn enable_rx(self) {
 | 
				
			||||||
 | 
					        unsafe {
 | 
				
			||||||
 | 
					            self.base
 | 
				
			||||||
 | 
					                .add(5)
 | 
				
			||||||
 | 
					                .write_volatile(self.base.add(5).read_volatile() | 2)
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn putc(&self, c: u8) {
 | 
				
			||||||
 | 
					        unsafe {
 | 
				
			||||||
 | 
					            // Wait until TXFULL is `0`
 | 
				
			||||||
 | 
					            while self.base.add(1).read_volatile() != 0 {
 | 
				
			||||||
 | 
					                ()
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            self.base.add(0).write_volatile(c as usize)
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn getc(&self) -> Option<u8> {
 | 
				
			||||||
 | 
					        unsafe {
 | 
				
			||||||
 | 
					            // If EV_PENDING_RX is 1, return the pending character.
 | 
				
			||||||
 | 
					            // Otherwise, return None.
 | 
				
			||||||
 | 
					            match self.base.add(4).read_volatile() & 2 {
 | 
				
			||||||
 | 
					                0 => None,
 | 
				
			||||||
 | 
					                ack => {
 | 
				
			||||||
 | 
					                    let c = Some(self.base.add(0).read_volatile() as u8);
 | 
				
			||||||
 | 
					                    self.base.add(4).write_volatile(ack);
 | 
				
			||||||
 | 
					                    c
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn irq(irq_number: usize) {
 | 
				
			||||||
 | 
					    println!(
 | 
				
			||||||
 | 
					        "Interrupt {}: Key pressed: {}",
 | 
				
			||||||
 | 
					        irq_number,
 | 
				
			||||||
 | 
					        DEFAULT_UART.getc().unwrap() as char
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Write for Uart {
 | 
				
			||||||
 | 
					    fn write_str(&mut self, s: &str) -> Result<(), Error> {
 | 
				
			||||||
 | 
					        for c in s.bytes() {
 | 
				
			||||||
 | 
					            self.putc(c);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										48
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -2,6 +2,8 @@
 | 
				
			|||||||
#![no_main]
 | 
					#![no_main]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern crate vexriscv;
 | 
					extern crate vexriscv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mod debug;
 | 
				
			||||||
mod definitions;
 | 
					mod definitions;
 | 
				
			||||||
mod irq;
 | 
					mod irq;
 | 
				
			||||||
mod macros;
 | 
					mod macros;
 | 
				
			||||||
@@ -12,22 +14,16 @@ mod syscalls;
 | 
				
			|||||||
pub use irq::sys_interrupt_claim;
 | 
					pub use irq::sys_interrupt_claim;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use core::panic::PanicInfo;
 | 
					use core::panic::PanicInfo;
 | 
				
			||||||
use xous_kernel_riscv_rt::xous_kernel_entry;
 | 
					 | 
				
			||||||
use vexriscv::register::{mcause, mstatus, mie, vmim, vmip};
 | 
					 | 
				
			||||||
use mem::MemoryManager;
 | 
					use mem::MemoryManager;
 | 
				
			||||||
use processtable::ProcessTable;
 | 
					use processtable::ProcessTable;
 | 
				
			||||||
 | 
					use vexriscv::register::{mcause, mie, mstatus, vmim, vmip};
 | 
				
			||||||
 | 
					use xous_kernel_riscv_rt::xous_kernel_entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[panic_handler]
 | 
					#[panic_handler]
 | 
				
			||||||
fn handle_panic(_arg: &PanicInfo) -> ! {
 | 
					fn handle_panic(_arg: &PanicInfo) -> ! {
 | 
				
			||||||
    loop {}
 | 
					    loop {}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn print_str(uart: *mut usize, s: &str) {
 | 
					 | 
				
			||||||
    for c in s.bytes() {
 | 
					 | 
				
			||||||
        unsafe { uart.write_volatile(c as usize) };
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[xous_kernel_entry]
 | 
					#[xous_kernel_entry]
 | 
				
			||||||
fn xous_main() -> ! {
 | 
					fn xous_main() -> ! {
 | 
				
			||||||
    unsafe {
 | 
					    unsafe {
 | 
				
			||||||
@@ -37,30 +33,21 @@ fn xous_main() -> ! {
 | 
				
			|||||||
        mie::set_mext();
 | 
					        mie::set_mext();
 | 
				
			||||||
        mstatus::set_mie(); // Enable CPU interrupts
 | 
					        mstatus::set_mie(); // Enable CPU interrupts
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let uart = debug::DEFAULT_UART;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Enable "RX_EMPTY" interrupt
 | 
				
			||||||
 | 
					    uart.enable_rx();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    println!("Starting up...");
 | 
				
			||||||
 | 
					    sys_interrupt_claim(2, debug::irq).unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let mut mm = MemoryManager::new();
 | 
					    let mut mm = MemoryManager::new();
 | 
				
			||||||
    let mut pt = ProcessTable::new(&mut mm);
 | 
					    let mut _pt = ProcessTable::new(&mut mm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sys_interrupt_claim(2, |_| {
 | 
					 | 
				
			||||||
        let uart_ptr = 0xE000_1800 as *mut usize;
 | 
					 | 
				
			||||||
        print_str(uart_ptr, "hello, world!\r\n");
 | 
					 | 
				
			||||||
        // Acknowledge the IRQ
 | 
					 | 
				
			||||||
        unsafe {
 | 
					 | 
				
			||||||
            uart_ptr.add(0).read_volatile();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // Acknowledge the event
 | 
					 | 
				
			||||||
            uart_ptr.add(4).write_volatile(3);
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
    .unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Enable interrupts
 | 
					 | 
				
			||||||
    let uart_ptr = 0xE000_1800 as *mut usize;
 | 
					 | 
				
			||||||
    unsafe { uart_ptr.add(4).write_volatile(3) };
 | 
					 | 
				
			||||||
    unsafe { uart_ptr.add(5).write_volatile(3) };
 | 
					 | 
				
			||||||
    print_str(uart_ptr, "greetings!\r\n");
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    loop {
 | 
					    loop {
 | 
				
			||||||
        unsafe { vexriscv::asm::wfi() };
 | 
					        // unsafe { vexriscv::asm::wfi() };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -69,7 +56,10 @@ pub fn trap_handler() {
 | 
				
			|||||||
    let mc = mcause::read();
 | 
					    let mc = mcause::read();
 | 
				
			||||||
    let irqs_pending = vmip::read();
 | 
					    let irqs_pending = vmip::read();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if mc.is_exception() {}
 | 
					    if mc.is_exception() {
 | 
				
			||||||
 | 
					        unsafe { vexriscv::asm::ebreak() };
 | 
				
			||||||
 | 
					        loop {}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if irqs_pending != 0 {
 | 
					    if irqs_pending != 0 {
 | 
				
			||||||
        irq::handle(irqs_pending);
 | 
					        irq::handle(irqs_pending);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										124
									
								
								src/mem.rs
									
									
									
									
									
								
							
							
						
						
									
										124
									
								
								src/mem.rs
									
									
									
									
									
								
							@@ -1,4 +1,5 @@
 | 
				
			|||||||
use crate::definitions::{XousError, XousPid, MemoryAddress};
 | 
					use crate::definitions::{MemoryAddress, XousError, XousPid};
 | 
				
			||||||
 | 
					use crate::{print, println};
 | 
				
			||||||
use core::num::NonZeroUsize;
 | 
					use core::num::NonZeroUsize;
 | 
				
			||||||
use vexriscv::register::mstatus;
 | 
					use vexriscv::register::mstatus;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -21,6 +22,7 @@ const FLASH_PAGE_COUNT: usize = FLASH_SIZE / PAGE_SIZE;
 | 
				
			|||||||
const RAM_PAGE_COUNT: usize = RAM_SIZE / PAGE_SIZE;
 | 
					const RAM_PAGE_COUNT: usize = RAM_SIZE / PAGE_SIZE;
 | 
				
			||||||
const IO_PAGE_COUNT: usize = IO_SIZE;
 | 
					const IO_PAGE_COUNT: usize = IO_SIZE;
 | 
				
			||||||
const LCD_PAGE_COUNT: usize = LCD_SIZE / PAGE_SIZE;
 | 
					const LCD_PAGE_COUNT: usize = LCD_SIZE / PAGE_SIZE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct MemoryManager {
 | 
					pub struct MemoryManager {
 | 
				
			||||||
    flash: [XousPid; FLASH_PAGE_COUNT],
 | 
					    flash: [XousPid; FLASH_PAGE_COUNT],
 | 
				
			||||||
    ram: [XousPid; RAM_PAGE_COUNT],
 | 
					    ram: [XousPid; RAM_PAGE_COUNT],
 | 
				
			||||||
@@ -28,6 +30,43 @@ pub struct MemoryManager {
 | 
				
			|||||||
    lcd: [XousPid; LCD_PAGE_COUNT],
 | 
					    lcd: [XousPid; LCD_PAGE_COUNT],
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl core::fmt::Debug for MemoryManager {
 | 
				
			||||||
 | 
					    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
 | 
				
			||||||
 | 
					        writeln!(fmt, "MemoryManager: ")?;
 | 
				
			||||||
 | 
					        writeln!(
 | 
				
			||||||
 | 
					            fmt,
 | 
				
			||||||
 | 
					            "    flash: {:08x} .. {:08x} ({})",
 | 
				
			||||||
 | 
					            FLASH_START,
 | 
				
			||||||
 | 
					            FLASH_END,
 | 
				
			||||||
 | 
					            self.flash.len()
 | 
				
			||||||
 | 
					        )?;
 | 
				
			||||||
 | 
					        writeln!(
 | 
				
			||||||
 | 
					            fmt,
 | 
				
			||||||
 | 
					            "    ram:   {:08x} .. {:08x} ({})",
 | 
				
			||||||
 | 
					            RAM_START,
 | 
				
			||||||
 | 
					            RAM_END,
 | 
				
			||||||
 | 
					            self.ram.len()
 | 
				
			||||||
 | 
					        )?;
 | 
				
			||||||
 | 
					        writeln!(
 | 
				
			||||||
 | 
					            fmt,
 | 
				
			||||||
 | 
					            "    io:    {:08x} .. {:08x} ({})",
 | 
				
			||||||
 | 
					            IO_START,
 | 
				
			||||||
 | 
					            IO_END,
 | 
				
			||||||
 | 
					            self.io.len()
 | 
				
			||||||
 | 
					        )?;
 | 
				
			||||||
 | 
					        writeln!(
 | 
				
			||||||
 | 
					            fmt,
 | 
				
			||||||
 | 
					            "    lcd:   {:08x} .. {:08x} ({})",
 | 
				
			||||||
 | 
					            LCD_START,
 | 
				
			||||||
 | 
					            LCD_END,
 | 
				
			||||||
 | 
					            self.lcd.len()
 | 
				
			||||||
 | 
					        )?;
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// 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 {
 | 
					struct PageTable {
 | 
				
			||||||
    entries: [usize; 1024],
 | 
					    entries: [usize; 1024],
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -59,6 +98,14 @@ extern "C" {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use core::mem::transmute;
 | 
					use core::mem::transmute;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Enable transmuting from pointers-to-addresses to addresses.
 | 
				
			||||||
 | 
					/// This is required because the linker creates variables
 | 
				
			||||||
 | 
					/// such as _stext that are located at specific offsets -- such
 | 
				
			||||||
 | 
					/// as the start of the text section -- and their address is
 | 
				
			||||||
 | 
					/// the actual piece of data we want.
 | 
				
			||||||
 | 
					/// Rust really doesn't like going from addresses to values, so
 | 
				
			||||||
 | 
					/// we transmute from one to the other in order to construct a
 | 
				
			||||||
 | 
					/// range that we can loop through.
 | 
				
			||||||
macro_rules! mem_range {
 | 
					macro_rules! mem_range {
 | 
				
			||||||
    ( $s:expr, $e:expr ) => {{
 | 
					    ( $s:expr, $e:expr ) => {{
 | 
				
			||||||
        let start = unsafe { transmute::<&usize, usize>(&$s) };
 | 
					        let start = unsafe { transmute::<&usize, usize>(&$s) };
 | 
				
			||||||
@@ -67,7 +114,7 @@ macro_rules! mem_range {
 | 
				
			|||||||
    }}
 | 
					    }}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// Initialzie the memory map.
 | 
					/// Initialize the memory map.
 | 
				
			||||||
/// This will go through memory and map anything that the kernel is
 | 
					/// This will go through memory and map anything that the kernel is
 | 
				
			||||||
/// using to process 1, then allocate a pagetable for this process
 | 
					/// using to process 1, then allocate a pagetable for this process
 | 
				
			||||||
/// and place it at the usual offset.  The MMU will not be enabled yet,
 | 
					/// and place it at the usual offset.  The MMU will not be enabled yet,
 | 
				
			||||||
@@ -80,35 +127,10 @@ impl MemoryManager {
 | 
				
			|||||||
            io: [0; IO_PAGE_COUNT],
 | 
					            io: [0; IO_PAGE_COUNT],
 | 
				
			||||||
            lcd: [0; LCD_PAGE_COUNT],
 | 
					            lcd: [0; LCD_PAGE_COUNT],
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					        println!("Created Memory Manager: {:?}", mm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        mm
 | 
					        // Claim existing pages for PID 1, in preparation for turning on
 | 
				
			||||||
    }
 | 
					        // the MMU
 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Allocate a single page to the given process.
 | 
					 | 
				
			||||||
    pub fn alloc_page(&mut self, pid: XousPid) -> Result<MemoryAddress, XousError> {
 | 
					 | 
				
			||||||
        // Go through all RAM pages looking for a free page.
 | 
					 | 
				
			||||||
        // Optimization: start from the previous address.
 | 
					 | 
				
			||||||
        for index in 0..RAM_PAGE_COUNT {
 | 
					 | 
				
			||||||
            if self.ram[index] == 0 {
 | 
					 | 
				
			||||||
                self.ram[index] = pid;
 | 
					 | 
				
			||||||
                let page_addr = (index * PAGE_SIZE + RAM_START) as *mut u32;
 | 
					 | 
				
			||||||
                // Zero-out the page
 | 
					 | 
				
			||||||
                unsafe {
 | 
					 | 
				
			||||||
                    for i in 0..PAGE_SIZE/4 {
 | 
					 | 
				
			||||||
                        *page_addr.add(i) = 0;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                let new_page = unsafe { transmute::<*mut u32, usize>(page_addr) };
 | 
					 | 
				
			||||||
                return Ok(NonZeroUsize::new(new_page).unwrap());
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        Err(XousError::OutOfMemory)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /// Create an identity mapping, copying the kernel to itself
 | 
					 | 
				
			||||||
    pub fn create_identity(&mut self, satp: MemoryAddress, pid: XousPid) -> Result<(), XousError> {
 | 
					 | 
				
			||||||
        let pt = unsafe { transmute::<MemoryAddress, &mut PageTable>(satp) };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        unsafe { mstatus::clear_mie() };
 | 
					        unsafe { mstatus::clear_mie() };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let ranges = [
 | 
					        let ranges = [
 | 
				
			||||||
@@ -119,16 +141,49 @@ impl MemoryManager {
 | 
				
			|||||||
        ];
 | 
					        ];
 | 
				
			||||||
        for range in &ranges {
 | 
					        for range in &ranges {
 | 
				
			||||||
            for region in range.clone() {
 | 
					            for region in range.clone() {
 | 
				
			||||||
                self.map_page(pt, pid)?;
 | 
					                mm.claim_page(region & !0xfff, 1)
 | 
				
			||||||
                self.claim_page(region & !0xfff, 1)?;
 | 
					                    .expect("Unable to claim region for PID 1");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        unsafe { mstatus::set_mie() };
 | 
					        unsafe { mstatus::set_mie() };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        mm
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// 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> {
 | 
				
			||||||
 | 
					        // 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;
 | 
				
			||||||
 | 
					                let page_addr = (index * PAGE_SIZE + RAM_START) as *mut u32;
 | 
				
			||||||
 | 
					                // Zero-out the page
 | 
				
			||||||
 | 
					                unsafe {
 | 
				
			||||||
 | 
					                    for i in 0..PAGE_SIZE / 4 {
 | 
				
			||||||
 | 
					                        *page_addr.add(i) = 0;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                let new_page = unsafe { transmute::<*mut u32, usize>(page_addr) };
 | 
				
			||||||
 | 
					                println!("    Page {:08x} is free", new_page);
 | 
				
			||||||
 | 
					                return Ok(NonZeroUsize::new(new_page).unwrap());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        Err(XousError::OutOfMemory)
 | 
					        Err(XousError::OutOfMemory)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // /// Create an identity mapping, copying the kernel to itself
 | 
				
			||||||
 | 
					    // pub fn create_identity(&mut self, pid: XousPid) -> Result<(), XousError> {
 | 
				
			||||||
 | 
					    //     let pt = unsafe { transmute::<MemoryAddress, &mut PageTable>(satp) };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //     Err(XousError::OutOfMemory)
 | 
				
			||||||
 | 
					    // }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn map_page(&mut self, satp: &mut PageTable, pid: XousPid) -> Result<(), XousError> {
 | 
					    fn map_page(&mut self, satp: &mut PageTable, pid: XousPid) -> Result<(), XousError> {
 | 
				
			||||||
        Err(XousError::OutOfMemory)
 | 
					        Err(XousError::OutOfMemory)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -153,14 +208,11 @@ impl MemoryManager {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        match addr {
 | 
					        match addr {
 | 
				
			||||||
            FLASH_START..=FLASH_END => {
 | 
					            FLASH_START..=FLASH_END => claim_page_inner(&mut self.flash, addr - FLASH_START, pid),
 | 
				
			||||||
                claim_page_inner(&mut self.flash, addr - FLASH_START, pid)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            RAM_START..=RAM_END => claim_page_inner(&mut self.ram, addr - RAM_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),
 | 
					            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),
 | 
					            LCD_START..=LCD_END => claim_page_inner(&mut self.lcd, addr - LCD_START, pid),
 | 
				
			||||||
            _ => Err(XousError::BadAddress),
 | 
					            _ => Err(XousError::BadAddress),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
use crate::definitions::{XousError, XousPid, MemoryAddress};
 | 
					use crate::definitions::{XousError, XousPid, MemoryAddress};
 | 
				
			||||||
use crate::mem::MemoryManager;
 | 
					use crate::mem::MemoryManager;
 | 
				
			||||||
use crate::filled_array;
 | 
					use crate::{filled_array, println, print};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const MAX_PROCESS_COUNT: usize = 256;
 | 
					const MAX_PROCESS_COUNT: usize = 256;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -8,6 +8,12 @@ struct Process {
 | 
				
			|||||||
    satp: Option<MemoryAddress>,
 | 
					    satp: Option<MemoryAddress>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl core::fmt::Debug for Process {
 | 
				
			||||||
 | 
					    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::result::Result<(), core::fmt::Error> {
 | 
				
			||||||
 | 
					        write!(fmt, "Process (satp: 0x{:08x})", match self.satp { Some(s) => s.get(), None => 0 })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct ProcessTable {
 | 
					pub struct ProcessTable {
 | 
				
			||||||
    processes: [Process; MAX_PROCESS_COUNT],
 | 
					    processes: [Process; MAX_PROCESS_COUNT],
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -19,8 +25,9 @@ impl ProcessTable {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Allocate a root page table for PID 1
 | 
					        // Allocate a root page table for PID 1
 | 
				
			||||||
 | 
					        // mm.create_identity(1).expect("Unable to create identity mapping");
 | 
				
			||||||
        pt.processes[1].satp = Some(mm.alloc_page(1).unwrap());
 | 
					        pt.processes[1].satp = Some(mm.alloc_page(1).unwrap());
 | 
				
			||||||
        mm.create_identity(pt.processes[1].satp.unwrap(), 1).expect("Unable to create identity mapping");
 | 
					        println!("PID 1: {:?}", pt.processes[1]);
 | 
				
			||||||
        pt
 | 
					        pt
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user