mmu: almost have it working

Just have major stack issues.

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2020-01-21 20:05:39 +08:00
parent b48271308c
commit 3c15bd68d3
10 changed files with 59 additions and 42 deletions

6
asm.S
View File

@ -24,3 +24,9 @@ start_kmain:
add a6, a7, zero add a6, a7, zero
add a7, zero, zero add a7, zero, zero
mret // Return to kmain mret // Return to kmain
.global read_satp
.text
read_satp:
csrr a0, satp
ret

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -17,6 +17,7 @@ fn main() {
println!("cargo:rustc-link-lib=static={}", name); println!("cargo:rustc-link-lib=static={}", name);
println!("cargo:rustc-link-search={}", out_dir.display()); println!("cargo:rustc-link-search={}", out_dir.display());
println!("cargo:rerun-if-changed=bin/{}.a", target);
} }
// Put the linker script somewhere the linker can find it // Put the linker script somewhere the linker can find it

View File

@ -19,7 +19,7 @@ pub use irq::sys_interrupt_claim;
use core::panic::PanicInfo; use core::panic::PanicInfo;
use mem::MemoryManager; use mem::MemoryManager;
use processtable::ProcessTable; use processtable::ProcessTable;
use vexriscv::register::{mcause, mie, mstatus, vmim, vmip}; use vexriscv::register::{mcause, mepc, mie, mstatus, vmim, vmip};
use xous_kernel_riscv_rt::xous_kernel_entry; use xous_kernel_riscv_rt::xous_kernel_entry;
#[panic_handler] #[panic_handler]
@ -50,11 +50,10 @@ fn xous_main() -> ! {
sys_interrupt_claim(2, debug::irq).unwrap(); sys_interrupt_claim(2, debug::irq).unwrap();
println!("Creating memory manager..."); println!("Creating memory manager...");
let mut mm = MemoryManager::new(); let mm = MemoryManager::new();
println!("Creating process table..."); println!("Creating process table...");
ProcessTable::new(mm, kmain); ProcessTable::new(mm, kmain);
panic!("fell off main");
} }
fn kmain(mm: MemoryManager, pt: ProcessTable) -> ! { fn kmain(mm: MemoryManager, pt: ProcessTable) -> ! {
@ -76,6 +75,8 @@ 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");
println!("{:?} @ PC: {:08x}", mc.cause(), mepc::read());
unsafe { vexriscv::asm::ebreak() }; unsafe { vexriscv::asm::ebreak() };
loop {} loop {}
} }

View File

@ -134,14 +134,14 @@ impl MemoryManager {
// the MMU // the MMU
unsafe { mstatus::clear_mie() }; unsafe { mstatus::clear_mie() };
let ranges = [ let mut ranges = [
mem_range!(&_sbss, &_ebss), mem_range!(&_sbss, &_ebss),
mem_range!(&_sdata, &_edata), mem_range!(&_sdata, &_edata),
mem_range!(&_estack, &_sstack), // NOTE: Stack is reversed mem_range!(&_estack, &_sstack), // NOTE: Stack is reversed
mem_range!(&_stext, &_etext), mem_range!(&_stext, &_etext),
]; ];
for range in &ranges { for range in &mut ranges {
for region in range.clone() { for region in range {
mm.claim_page(region & !0xfff, 1) mm.claim_page(region & !0xfff, 1)
.expect("Unable to claim region for PID 1"); .expect("Unable to claim region for PID 1");
} }
@ -190,11 +190,12 @@ impl MemoryManager {
phys: usize, phys: usize,
virt: usize, virt: usize,
) -> Result<(), XousError> { ) -> Result<(), XousError> {
let ppn1 = (phys >> 20) & ((1 << 12) - 1); let ppn1 = (phys >> 22) & ((1 << 12) - 1);
let ppn0 = (phys >> 10) & ((1 << 10) - 1); let ppn0 = (phys >> 12) & ((1 << 10) - 1);
let ppo = (phys >> 0) & ((1 << 12) - 1); let ppo = (phys >> 0) & ((1 << 12) - 1);
let vpn1 = (virt >> 22) & ((1 << 10) - 1); let vpn1 = (virt >> 22) & ((1 << 10) - 1);
let vpn0 = (virt >> 10) & ((1 << 10) - 1); let vpn0 = (virt >> 12) & ((1 << 10) - 1);
let vpo = (virt >> 0) & ((1 << 12) - 1); let vpo = (virt >> 0) & ((1 << 12) - 1);
println!( println!(
@ -213,7 +214,10 @@ impl MemoryManager {
// Allocate a new level 1 pagetable entry if one doesn't exist. // Allocate a new level 1 pagetable entry if one doesn't exist.
if l1_pt[vpn1] & 1 == 0 { if l1_pt[vpn1] & 1 == 0 {
println!(" top-level VPN1 {:04x}: {:08x} (will allocate a new one)", vpn1, l1_pt[vpn1]); println!(
" top-level VPN1 {:04x}: {:08x} (will allocate a new one)",
vpn1, l1_pt[vpn1]
);
// Allocate the page to the kernel (PID 1) // Allocate the page to the kernel (PID 1)
let new_addr = self.alloc_page(1)?.get(); let new_addr = self.alloc_page(1)?.get();
println!( println!(
@ -223,64 +227,65 @@ impl MemoryManager {
// Mark this entry as a leaf node (WRX as 0), and indicate // Mark this entry as a leaf node (WRX as 0), and indicate
// it is a valid page by setting "V". // it is a valid page by setting "V".
l1_pt[vpn1] = (((new_addr >> 10) & ((1 << 22) - 1)) << 10) | 1; let ppn = new_addr >> 12;
l1_pt[vpn1] = (ppn << 10) | 1;
println!(" New top-level page entry: {:08x}", l1_pt[vpn1]); println!(" New top-level page entry: {:08x}", l1_pt[vpn1]);
} }
let mut l0_pt = unsafe { let l0_pt_idx =
let tmp = (l1_pt[vpn1] & ((1 << 10) - 1)) as *mut PageTable; unsafe { &mut (*(((l1_pt[vpn1] << 2) & !((1 << 12) - 1)) as *mut PageTable)) };
(*tmp).entries let ref mut l0_pt = l0_pt_idx.entries;
}; println!(" l0_pt is at {:p} ({:p})", &l0_pt, &l0_pt[vpn0]);
// Allocate a new level 0 pagetable entry if one doesn't exist. // Allocate a new level 0 pagetable entry if one doesn't exist.
if l0_pt[vpn0] & 1 != 0 { if l0_pt[vpn0] & 1 != 0 {
panic!("Page already allocated!"); println!("Page already allocated!");
} }
l0_pt[vpn0] = (ppn1 << 20) | (ppn0 << 10) | 1 | 0xe; l0_pt[vpn0] = (ppn1 << 20) | (ppn0 << 10) | 1 | 0xe | 0xc0;
Ok(()) Ok(())
} }
/// Create an identity mapping, copying the kernel to itself /// Create an identity mapping, copying the kernel to itself
pub fn create_identity(&mut self, process: &Process) -> Result<(), XousError> { pub fn create_identity(&mut self, process: &Process) -> Result<(), XousError> {
let root_page = (process.satp & ((1 << 22) - 1)) << 9; let root_page = (process.satp & ((1 << 22) - 1)) << 12;
let pt = unsafe { &mut (*(root_page as *mut PageTable)) }; 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); println!(
"SATP value: {:08x} Root page: {:08x} pt: {:p} pt: {:p}",
process.satp, root_page, &pt, pt
);
let ranges = [ let mut ranges = [
mem_range!(&_sbss, &_ebss), mem_range!(&_sbss, &_ebss),
mem_range!(&_sdata, &_edata), mem_range!(&_sdata, &_edata),
mem_range!(&_estack, &_sstack), // NOTE: Stack is reversed mem_range!(&_estack, &_sstack), // NOTE: Stack is reversed
mem_range!(&_stext, &_etext), mem_range!(&_stext, &_etext),
]; ];
for range in &ranges { for range in &mut ranges {
for region in range.clone() { for region in range {
// mm.claim_page(region & !0xfff, 1) // mm.claim_page(region & !0xfff, 1)
// .expect("Unable to claim region for PID 1"); // .expect("Unable to claim region for PID 1");
self.map_page( self.map_page(pt, region, region)?;
pt, // print!("Entries mapped: >");
region, // let mut i = 0;
region, // for (entry_idx, entry) in pt.entries.iter().enumerate() {
)?; // i = i + 1;
print!("Entries mapped: >"); // if *entry != 0 {
let mut i = 0; // print!(" {}:{:08x}", entry_idx, entry);
for (entry_idx, entry) in pt.entries.iter().enumerate() { // }
i = i + 1; // }
if *entry != 0 { // println!(" < ({})", i);
print!(" {}:{:08x}", entry_idx, entry);
}
}
println!(" < ({})", i);
println!(""); println!("");
} }
} }
self.map_page(pt, 0xE000_1800, 0xE000_1800)?;
// let flash_orig = self.flash.clone(); // let flash_orig = self.flash.clone();
// for (flash_idx, flash_pid) in flash_orig.iter().enumerate() { // for (flash_idx, flash_pid) in flash_orig.iter().enumerate() {
// if *flash_pid == pid { // if *flash_pid == pid {
// println!( // println!(
// "Flash addr {:08x} owned by PID {}, mapping it as ident", // "Flash addr {:08x} owned by PID {}, mapping it as ident",
// flash_idx * PAGE_SIZE + FLASH_START, // flash_idx * PAGE_SIZE + FLASH_START,
// pid // pid
// ); // );
// } // }
// } // }

View File

@ -33,6 +33,9 @@ extern "Rust" {
pt: ProcessTable, pt: ProcessTable,
) -> !; ) -> !;
} }
extern "C" {
fn read_satp() -> usize;
}
impl ProcessTable { impl ProcessTable {
pub fn new(mut mm: MemoryManager, kmain: fn(MemoryManager, ProcessTable) -> !) -> ! { pub fn new(mut mm: MemoryManager, kmain: fn(MemoryManager, ProcessTable) -> !) -> ! {
@ -43,7 +46,7 @@ impl ProcessTable {
// Allocate a root page table for PID 1. Also mark the "ASID" as "1" // Allocate a root page table for PID 1. Also mark the "ASID" as "1"
// for "PID 1" // for "PID 1"
let root_page = mm.alloc_page(1).unwrap().get(); let root_page = mm.alloc_page(1).unwrap().get();
pt.processes[1].satp = (root_page >> 9) | (1 << 22); pt.processes[1].satp = (root_page >> 12) | (1 << 22);
mm.create_identity(&pt.processes[1]) mm.create_identity(&pt.processes[1])
.expect("Unable to create identity mapping"); .expect("Unable to create identity mapping");
println!("PID 1: {:?} root page @ {:08x}", pt.processes[1], root_page); println!("PID 1: {:?} root page @ {:08x}", pt.processes[1], root_page);
@ -60,6 +63,7 @@ impl ProcessTable {
mstatus::set_mpp(mstatus::MPP::Supervisor); mstatus::set_mpp(mstatus::MPP::Supervisor);
}; };
println!("MMU enabled, jumping to kmain"); println!("MMU enabled, jumping to kmain");
println!("SATP: {:08x}", unsafe { read_satp() });
unsafe { start_kmain(kmain, mm, pt) } unsafe { start_kmain(kmain, mm, pt) }
} }
} }