mmu: first attempt to get it enabled
Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
1ad0961c87
commit
b48271308c
26
asm.S
Normal file
26
asm.S
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#if __riscv_xlen == 64
|
||||||
|
# define STORE sd
|
||||||
|
# define LOAD ld
|
||||||
|
# define LOG_REGBYTES 3
|
||||||
|
#else
|
||||||
|
# define STORE sw
|
||||||
|
# define LOAD lw
|
||||||
|
# define LOG_REGBYTES 2
|
||||||
|
#endif
|
||||||
|
#define REGBYTES (1 << LOG_REGBYTES)
|
||||||
|
|
||||||
|
.global start_kmain
|
||||||
|
.text
|
||||||
|
start_kmain:
|
||||||
|
li t0, (1 << 11) | (1 << 5)
|
||||||
|
csrw mstatus, t0
|
||||||
|
csrw mepc, a0
|
||||||
|
add a0, a1, zero
|
||||||
|
add a1, a2, zero
|
||||||
|
add a2, a3, zero
|
||||||
|
add a3, a4, zero
|
||||||
|
add a4, a5, zero
|
||||||
|
add a5, a6, zero
|
||||||
|
add a6, a7, zero
|
||||||
|
add a7, zero, zero
|
||||||
|
mret // Return to kmain
|
17
assemble.ps1
Normal file
17
assemble.ps1
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# remove existing blobs because otherwise this will append object files to the old blobs
|
||||||
|
Remove-Item -Force bin/*.a
|
||||||
|
|
||||||
|
$crate = "xous-kernel"
|
||||||
|
|
||||||
|
riscv64-unknown-elf-gcc -ggdb3 -c -mabi=ilp32 -march=rv32imac asm.S -o bin/$crate.o
|
||||||
|
riscv64-unknown-elf-ar crs bin/riscv32imac-unknown-none-elf.a bin/$crate.o
|
||||||
|
riscv64-unknown-elf-ar crs bin/riscv32imc-unknown-none-elf.a bin/$crate.o
|
||||||
|
|
||||||
|
riscv64-unknown-elf-gcc -ggdb3 -c -mabi=ilp32 -march=rv32i asm.S -DSKIP_MULTICORE -o bin/$crate.o
|
||||||
|
riscv64-unknown-elf-ar crs bin/riscv32i-unknown-none-elf.a bin/$crate.o
|
||||||
|
|
||||||
|
riscv64-unknown-elf-gcc -ggdb3 -c -mabi=lp64 -march=rv64imac asm.S -o bin/$crate.o
|
||||||
|
riscv64-unknown-elf-ar crs bin/riscv64imac-unknown-none-elf.a bin/$crate.o
|
||||||
|
riscv64-unknown-elf-ar crs bin/riscv64gc-unknown-none-elf.a bin/$crate.o
|
||||||
|
|
||||||
|
Remove-Item bin/$crate.o
|
22
assemble.sh
Normal file
22
assemble.sh
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euxo pipefail
|
||||||
|
|
||||||
|
crate=xous-kernel
|
||||||
|
|
||||||
|
# remove existing blobs because otherwise this will append object files to the old blobs
|
||||||
|
mkdir -p bin
|
||||||
|
rm -f bin/*.a
|
||||||
|
|
||||||
|
riscv64-unknown-elf-gcc -ggdb3 -c -mabi=ilp32 -march=rv32imac asm.S -o bin/$crate.o
|
||||||
|
ar crs bin/riscv32imac-unknown-none-elf.a bin/$crate.o
|
||||||
|
ar crs bin/riscv32imc-unknown-none-elf.a bin/$crate.o
|
||||||
|
|
||||||
|
riscv64-unknown-elf-gcc -ggdb3 -c -mabi=ilp32 -march=rv32i asm.S -DSKIP_MULTICORE -o bin/$crate.o
|
||||||
|
ar crs bin/riscv32i-unknown-none-elf.a bin/$crate.o
|
||||||
|
|
||||||
|
riscv64-unknown-elf-gcc -ggdb3 -c -mabi=lp64 -march=rv64imac asm.S -o bin/$crate.o
|
||||||
|
ar crs bin/riscv64imac-unknown-none-elf.a bin/$crate.o
|
||||||
|
ar crs bin/riscv64gc-unknown-none-elf.a bin/$crate.o
|
||||||
|
|
||||||
|
rm bin/$crate.o
|
BIN
bin/riscv32i-unknown-none-elf.a
Normal file
BIN
bin/riscv32i-unknown-none-elf.a
Normal file
Binary file not shown.
BIN
bin/riscv32imac-unknown-none-elf.a
Normal file
BIN
bin/riscv32imac-unknown-none-elf.a
Normal file
Binary file not shown.
BIN
bin/riscv32imc-unknown-none-elf.a
Normal file
BIN
bin/riscv32imc-unknown-none-elf.a
Normal file
Binary file not shown.
BIN
bin/riscv64gc-unknown-none-elf.a
Normal file
BIN
bin/riscv64gc-unknown-none-elf.a
Normal file
Binary file not shown.
BIN
bin/riscv64imac-unknown-none-elf.a
Normal file
BIN
bin/riscv64imac-unknown-none-elf.a
Normal file
Binary file not shown.
12
build.rs
12
build.rs
@ -6,6 +6,18 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||||
|
let target = env::var("TARGET").unwrap();
|
||||||
|
let name = env::var("CARGO_PKG_NAME").unwrap();
|
||||||
|
|
||||||
|
if target.starts_with("riscv") {
|
||||||
|
fs::copy(
|
||||||
|
format!("bin/{}.a", target),
|
||||||
|
out_dir.join(format!("lib{}.a", name)),
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
println!("cargo:rustc-link-lib=static={}", name);
|
||||||
|
println!("cargo:rustc-link-search={}", out_dir.display());
|
||||||
|
}
|
||||||
|
|
||||||
// Put the linker script somewhere the linker can find it
|
// Put the linker script somewhere the linker can find it
|
||||||
fs::File::create(out_dir.join("memory.x"))
|
fs::File::create(out_dir.join("memory.x"))
|
||||||
|
14
src/main.rs
14
src/main.rs
@ -12,6 +12,7 @@ mod macros;
|
|||||||
mod mem;
|
mod mem;
|
||||||
mod processtable;
|
mod processtable;
|
||||||
mod syscalls;
|
mod syscalls;
|
||||||
|
mod timer;
|
||||||
|
|
||||||
pub use irq::sys_interrupt_claim;
|
pub use irq::sys_interrupt_claim;
|
||||||
|
|
||||||
@ -39,6 +40,8 @@ fn xous_main() -> ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let uart = debug::DEFAULT_UART;
|
let uart = debug::DEFAULT_UART;
|
||||||
|
sys_interrupt_claim(0, timer::irq).unwrap();
|
||||||
|
timer::time_init();
|
||||||
|
|
||||||
// Enable "RX_EMPTY" interrupt
|
// Enable "RX_EMPTY" interrupt
|
||||||
uart.enable_rx();
|
uart.enable_rx();
|
||||||
@ -50,10 +53,19 @@ fn xous_main() -> ! {
|
|||||||
let mut mm = MemoryManager::new();
|
let mut mm = MemoryManager::new();
|
||||||
|
|
||||||
println!("Creating process table...");
|
println!("Creating process table...");
|
||||||
let mut _pt = ProcessTable::new(&mut mm);
|
ProcessTable::new(mm, kmain);
|
||||||
|
panic!("fell off main");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn kmain(mm: MemoryManager, pt: ProcessTable) -> ! {
|
||||||
println!("Entering main loop");
|
println!("Entering main loop");
|
||||||
|
let mut last_time = timer::get_time();
|
||||||
loop {
|
loop {
|
||||||
|
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() };
|
// unsafe { vexriscv::asm::wfi() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
39
src/mem.rs
39
src/mem.rs
@ -25,8 +25,8 @@ 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],
|
|
||||||
ram: [XousPid; RAM_PAGE_COUNT],
|
ram: [XousPid; RAM_PAGE_COUNT],
|
||||||
|
flash: [XousPid; FLASH_PAGE_COUNT],
|
||||||
io: [XousPid; IO_PAGE_COUNT],
|
io: [XousPid; IO_PAGE_COUNT],
|
||||||
lcd: [XousPid; LCD_PAGE_COUNT],
|
lcd: [XousPid; LCD_PAGE_COUNT],
|
||||||
}
|
}
|
||||||
@ -241,22 +241,25 @@ impl MemoryManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 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, pid: XousPid) -> 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)) << 9;
|
||||||
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 flash_orig = self.flash.clone();
|
|
||||||
for (flash_idx, flash_pid) in flash_orig.iter().enumerate() {
|
let ranges = [
|
||||||
if *flash_pid == pid {
|
mem_range!(&_sbss, &_ebss),
|
||||||
// println!(
|
mem_range!(&_sdata, &_edata),
|
||||||
// "Flash addr {:08x} owned by PID {}, mapping it as ident",
|
mem_range!(&_estack, &_sstack), // NOTE: Stack is reversed
|
||||||
// flash_idx * PAGE_SIZE + FLASH_START,
|
mem_range!(&_stext, &_etext),
|
||||||
// pid
|
];
|
||||||
// );
|
for range in &ranges {
|
||||||
|
for region in range.clone() {
|
||||||
|
// mm.claim_page(region & !0xfff, 1)
|
||||||
|
// .expect("Unable to claim region for PID 1");
|
||||||
self.map_page(
|
self.map_page(
|
||||||
pt,
|
pt,
|
||||||
flash_idx * PAGE_SIZE + FLASH_START,
|
region,
|
||||||
flash_idx * PAGE_SIZE + FLASH_START,
|
region,
|
||||||
)?;
|
)?;
|
||||||
print!("Entries mapped: >");
|
print!("Entries mapped: >");
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
@ -270,6 +273,18 @@ impl MemoryManager {
|
|||||||
println!("");
|
println!("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::definitions::{MemoryAddress, XousError, XousPid};
|
use crate::definitions::{MemoryAddress, XousError, XousPid};
|
||||||
use crate::mem::MemoryManager;
|
use crate::mem::MemoryManager;
|
||||||
use crate::{filled_array, print, println};
|
use crate::{filled_array, print, println};
|
||||||
use vexriscv::register::{satp, mstatus};
|
use vexriscv::register::{mstatus, satp};
|
||||||
|
|
||||||
const MAX_PROCESS_COUNT: usize = 256;
|
const MAX_PROCESS_COUNT: usize = 256;
|
||||||
|
|
||||||
@ -26,8 +26,16 @@ pub struct ProcessTable {
|
|||||||
processes: [Process; MAX_PROCESS_COUNT],
|
processes: [Process; MAX_PROCESS_COUNT],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "Rust" {
|
||||||
|
fn start_kmain(
|
||||||
|
kmain: extern "Rust" fn(MemoryManager, ProcessTable) -> !,
|
||||||
|
mm: MemoryManager,
|
||||||
|
pt: ProcessTable,
|
||||||
|
) -> !;
|
||||||
|
}
|
||||||
|
|
||||||
impl ProcessTable {
|
impl ProcessTable {
|
||||||
pub fn new(mm: &mut MemoryManager) -> Self {
|
pub fn new(mut mm: MemoryManager, kmain: fn(MemoryManager, ProcessTable) -> !) -> ! {
|
||||||
let mut pt = ProcessTable {
|
let mut pt = ProcessTable {
|
||||||
processes: filled_array![Process { satp: 0 }; 256],
|
processes: filled_array![Process { satp: 0 }; 256],
|
||||||
};
|
};
|
||||||
@ -36,7 +44,7 @@ impl ProcessTable {
|
|||||||
// 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 >> 9) | (1 << 22);
|
||||||
mm.create_identity(&pt.processes[1], 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);
|
||||||
println!("Enabling MMU...");
|
println!("Enabling MMU...");
|
||||||
@ -51,7 +59,7 @@ impl ProcessTable {
|
|||||||
// Switch to Supervisor mode
|
// Switch to Supervisor mode
|
||||||
mstatus::set_mpp(mstatus::MPP::Supervisor);
|
mstatus::set_mpp(mstatus::MPP::Supervisor);
|
||||||
};
|
};
|
||||||
println!("MMU enabled");
|
println!("MMU enabled, jumping to kmain");
|
||||||
pt
|
unsafe { start_kmain(kmain, mm, pt) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
43
src/timer.rs
Normal file
43
src/timer.rs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
static mut TIME_MS: u32 = 0;
|
||||||
|
|
||||||
|
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
|
||||||
|
unsafe {
|
||||||
|
// Disable, so we can update it
|
||||||
|
timer_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 "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);
|
||||||
|
|
||||||
|
// Enable ISR
|
||||||
|
timer_base.add(0x40).write_volatile(1);
|
||||||
|
|
||||||
|
// Set "pending" as well to clear it
|
||||||
|
timer_base.add(0x38).write_volatile(1);
|
||||||
|
|
||||||
|
// Finally, enable it
|
||||||
|
timer_base.add(0x20).write_volatile(1);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user