mmu: almost have it working
Just have major stack issues. Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
b48271308c
commit
3c15bd68d3
6
asm.S
6
asm.S
@ -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.
1
build.rs
1
build.rs
@ -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
|
||||||
|
@ -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 {}
|
||||||
}
|
}
|
||||||
|
71
src/mem.rs
71
src/mem.rs
@ -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,56 +227,57 @@ 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 {
|
||||||
|
@ -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) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user