diff --git a/asm.S b/asm.S new file mode 100644 index 0000000..e3de3bd --- /dev/null +++ b/asm.S @@ -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 diff --git a/assemble.ps1 b/assemble.ps1 new file mode 100644 index 0000000..1058229 --- /dev/null +++ b/assemble.ps1 @@ -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 diff --git a/assemble.sh b/assemble.sh new file mode 100644 index 0000000..7d9d444 --- /dev/null +++ b/assemble.sh @@ -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 diff --git a/bin/riscv32i-unknown-none-elf.a b/bin/riscv32i-unknown-none-elf.a new file mode 100644 index 0000000..44d9ade Binary files /dev/null and b/bin/riscv32i-unknown-none-elf.a differ diff --git a/bin/riscv32imac-unknown-none-elf.a b/bin/riscv32imac-unknown-none-elf.a new file mode 100644 index 0000000..59fb560 Binary files /dev/null and b/bin/riscv32imac-unknown-none-elf.a differ diff --git a/bin/riscv32imc-unknown-none-elf.a b/bin/riscv32imc-unknown-none-elf.a new file mode 100644 index 0000000..59fb560 Binary files /dev/null and b/bin/riscv32imc-unknown-none-elf.a differ diff --git a/bin/riscv64gc-unknown-none-elf.a b/bin/riscv64gc-unknown-none-elf.a new file mode 100644 index 0000000..76192b1 Binary files /dev/null and b/bin/riscv64gc-unknown-none-elf.a differ diff --git a/bin/riscv64imac-unknown-none-elf.a b/bin/riscv64imac-unknown-none-elf.a new file mode 100644 index 0000000..76192b1 Binary files /dev/null and b/bin/riscv64imac-unknown-none-elf.a differ diff --git a/build.rs b/build.rs index 84e26f1..4ecb4fa 100644 --- a/build.rs +++ b/build.rs @@ -6,6 +6,18 @@ use std::path::PathBuf; fn main() { 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 fs::File::create(out_dir.join("memory.x")) diff --git a/src/main.rs b/src/main.rs index 318e132..b609553 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,7 @@ mod macros; mod mem; mod processtable; mod syscalls; +mod timer; pub use irq::sys_interrupt_claim; @@ -39,6 +40,8 @@ fn xous_main() -> ! { } let uart = debug::DEFAULT_UART; + sys_interrupt_claim(0, timer::irq).unwrap(); + timer::time_init(); // Enable "RX_EMPTY" interrupt uart.enable_rx(); @@ -50,10 +53,19 @@ fn xous_main() -> ! { let mut mm = MemoryManager::new(); 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"); + 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); + } // unsafe { vexriscv::asm::wfi() }; } } diff --git a/src/mem.rs b/src/mem.rs index b043cf4..93bc078 100644 --- a/src/mem.rs +++ b/src/mem.rs @@ -25,8 +25,8 @@ const IO_PAGE_COUNT: usize = IO_SIZE; const LCD_PAGE_COUNT: usize = LCD_SIZE / PAGE_SIZE; pub struct MemoryManager { - flash: [XousPid; FLASH_PAGE_COUNT], ram: [XousPid; RAM_PAGE_COUNT], + flash: [XousPid; FLASH_PAGE_COUNT], io: [XousPid; IO_PAGE_COUNT], lcd: [XousPid; LCD_PAGE_COUNT], } @@ -241,22 +241,25 @@ impl MemoryManager { } /// 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 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); - 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 - // ); + + let ranges = [ + mem_range!(&_sbss, &_ebss), + mem_range!(&_sdata, &_edata), + mem_range!(&_estack, &_sstack), // NOTE: Stack is reversed + mem_range!(&_stext, &_etext), + ]; + 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( pt, - flash_idx * PAGE_SIZE + FLASH_START, - flash_idx * PAGE_SIZE + FLASH_START, + region, + region, )?; print!("Entries mapped: >"); let mut i = 0; @@ -270,6 +273,18 @@ impl MemoryManager { 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(()) } diff --git a/src/processtable.rs b/src/processtable.rs index 3432ffd..2f0d6d5 100644 --- a/src/processtable.rs +++ b/src/processtable.rs @@ -1,7 +1,7 @@ use crate::definitions::{MemoryAddress, XousError, XousPid}; use crate::mem::MemoryManager; use crate::{filled_array, print, println}; -use vexriscv::register::{satp, mstatus}; +use vexriscv::register::{mstatus, satp}; const MAX_PROCESS_COUNT: usize = 256; @@ -26,8 +26,16 @@ pub struct ProcessTable { processes: [Process; MAX_PROCESS_COUNT], } +extern "Rust" { + fn start_kmain( + kmain: extern "Rust" fn(MemoryManager, ProcessTable) -> !, + mm: MemoryManager, + pt: ProcessTable, + ) -> !; +} + impl ProcessTable { - pub fn new(mm: &mut MemoryManager) -> Self { + pub fn new(mut mm: MemoryManager, kmain: fn(MemoryManager, ProcessTable) -> !) -> ! { let mut pt = ProcessTable { processes: filled_array![Process { satp: 0 }; 256], }; @@ -36,7 +44,7 @@ impl ProcessTable { // for "PID 1" let root_page = mm.alloc_page(1).unwrap().get(); 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"); println!("PID 1: {:?} root page @ {:08x}", pt.processes[1], root_page); println!("Enabling MMU..."); @@ -51,7 +59,7 @@ impl ProcessTable { // Switch to Supervisor mode mstatus::set_mpp(mstatus::MPP::Supervisor); }; - println!("MMU enabled"); - pt + println!("MMU enabled, jumping to kmain"); + unsafe { start_kmain(kmain, mm, pt) } } } diff --git a/src/timer.rs b/src/timer.rs new file mode 100644 index 0000000..6ecd091 --- /dev/null +++ b/src/timer.rs @@ -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); + } +}