From a06bd2aa0e118a55d4e97c8717dbc1aeb75fb6a8 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Fri, 24 Jan 2020 11:34:56 +0800 Subject: [PATCH] wip commit Signed-off-by: Sean Cross --- asm.S | 10 ++++- bin/riscv32i-unknown-none-elf.a | Bin 2024 -> 2238 bytes bin/riscv32imac-unknown-none-elf.a | Bin 2032 -> 2254 bytes bin/riscv32imc-unknown-none-elf.a | Bin 2032 -> 2254 bytes bin/riscv64gc-unknown-none-elf.a | Bin 2964 -> 3290 bytes bin/riscv64imac-unknown-none-elf.a | Bin 2964 -> 3290 bytes src/debug.rs | 16 +++---- src/main.rs | 68 +++++++++++++++++++++++------ src/mem.rs | 56 +++++++++++++++++++++++- src/processtable.rs | 14 +++++- src/syscalls.rs | 16 +++---- src/uart.rs | 66 ---------------------------- 12 files changed, 145 insertions(+), 101 deletions(-) delete mode 100644 src/uart.rs diff --git a/asm.S b/asm.S index f1cbb70..5ab81be 100644 --- a/asm.S +++ b/asm.S @@ -9,12 +9,20 @@ #endif #define REGBYTES (1 << LOG_REGBYTES) +.global enable_mmu .global return_from_interrupt .text +enable_mmu: + la sp, _estack // Trash the stack and start over return_from_interrupt: - la sp, _estack mret // Return to kmain +.global flush_mmu +flush_mmu: + sfence.vma + ret + +.global my_fence .global read_satp .text read_satp: diff --git a/bin/riscv32i-unknown-none-elf.a b/bin/riscv32i-unknown-none-elf.a index 105557d8c4c89fc097e2bfc57d9c3f5f8ea5228e..2182ef2df3dd40f773f3b6a13c3528e672ebcb80 100644 GIT binary patch delta 766 zcmZuuJ#5oZ5WeSMC@o3b1P5W%r&`z@fI3b|1Z-4=0ZU|n0Vz@%TBjYF2E|kYQ3N9k z2y+Vq6RH?M?64qpWk9enmyMNyojdzUq!K6Hz3=XQKHq)sSLyTg3-@ZP6*cOSl%ZrB zk5aal@*;)R2>>w2pO1U8-Mh1ubO(bS?CDOWzqONYat5QMx86;A_wGVAtjhoWq8^6L zW>d;2Y&5gI1uZtSuXAO9nT;m^=^3c;+0Oo)J5dt4b`(J9Mjk~TEj%k?+!cOx`BLXr znvBv;I#?SGJIllMq;ntNi~XvgQETLd3E;dt1ynh}6+#tN<9j$ChY}7cGk5u)GJ^-*ezLumj7h{FJ112OIvNVH+_hPJ zr}rPP5S&+2GWP9)bDirX2peNxac&Tv=O-g$>?@8%Sn$SVyp)*9VZNwPTkW9a+tl%m>5Df0HXS@L%Q*_n zHt}xaY0EQT=>V^B#qz`+*6mr`wJO?@fiEpze8EpvAP(@S6=+WloUnb9g^%!p?TH9) d+rd;!`8RSN*THA@DbuBXF@7M%NBnL(e*uQLbG!fm delta 634 zcmZuvzfap>5dF@Me&ja`kN$Uc#zy1m@;XD3Rrtn;`@LrMd6m#m{be=T+F^k9)VK`1$0)!~7dJ^x{ z$--aB(d$e)E~79X(*(ur7_KF@4r)Z7nNgm(V?YK*3$zfjWNF-Oy+7w{B^5 zs;lFzZflk*L=$s{4JY`*aFu-(-x&^k!DGXP3;ar{3l#^3qutOq4i1?%q;b}Ciyj^B hkidIR5cn=Ej5SizNBc~_NePckJIf`fk9k@x<_`eeU}69O diff --git a/bin/riscv32imac-unknown-none-elf.a b/bin/riscv32imac-unknown-none-elf.a index bf40cf2e20ffe3d4553c4e574da46922e2e828ca..b332d263dc48d1d156906a57973b3f92a1a01fdc 100644 GIT binary patch delta 807 zcmZuv&ubG=5Pq}2Qni{iHpvPFA6>dz#oFyw6I8rdrJxaesJDfn0577KVlSS(dK3HyoOyYrRs7(a_szU{v-9Tduj2N|ld<_mBbuFw zqzolvzm>9aMg_^-Iw*v&h>!O(T}zf$(^jXmA@YUlXnS=dyRE!lnyj?4>*H7BK{7(oA)QmA zoIq<{O2la*^`*f3=d|X9_b(C4>=1ZgoNk6v{5=`$n?o1&rqj9KYNu<~v_I1t;(&PMW1lGRJaYzH-n!pzW-929h z^i4-uA0|U^iEu>BD`$+IqLM6TgcOexM(np@2&6j0FP|X*fjB-?L!lH z>_FKXmYkB^q`XC(a6J1hz4A-E?s)JD*PXz)Y~c&XhtK%Q3E&6*q|h@9%LU)&!AE$p s;6a2*A()EE|3>6iYeb$S_r){dUuPGm$Z6uog6Dprl&8C4TIsODAG$ws2LJ#7 delta 632 zcmZuvO-mbL5PoMj`;pkjC~dRYKwezk6(w%J@nj5Jqcby|3D#!Qt}fzv%97}IPlCoJ3Bk`%&@m(gVD>vnO|M1)E1=l zB-{U9%EiSfNp2@2gir`=Mi_LuVY6`%wvHOFo1GvGyX}q$gWdhc@ouLrPFmgL(wiV` z28ZR=yp)v}OSOmQR6H;3`#u#^eede~jPfaU^}DD~3+wIqD(0b-$$|=LAwbn|3)b-( zob>AQ_DX9%*xtlnaECo*3a^zMW>g6iIH#UY7f9i~<%moX9wmvK03pg7o6FN3clAJsN)yijeH*e=sB%Ub!(^^ zwq~h99O9f|!v(%FT;-jLCx!!G@w4H=4gR3iPZbA-qxI<<2cMfZWbvixma25Pa{}-A el)!gkVXTpw4(%KLBxOX?woEGdILy;(3I7Y9k6#x6 diff --git a/bin/riscv32imc-unknown-none-elf.a b/bin/riscv32imc-unknown-none-elf.a index bf40cf2e20ffe3d4553c4e574da46922e2e828ca..b332d263dc48d1d156906a57973b3f92a1a01fdc 100644 GIT binary patch delta 807 zcmZuv&ubG=5Pq}2Qni{iHpvPFA6>dz#oFyw6I8rdrJxaesJDfn0577KVlSS(dK3HyoOyYrRs7(a_szU{v-9Tduj2N|ld<_mBbuFw zqzolvzm>9aMg_^-Iw*v&h>!O(T}zf$(^jXmA@YUlXnS=dyRE!lnyj?4>*H7BK{7(oA)QmA zoIq<{O2la*^`*f3=d|X9_b(C4>=1ZgoNk6v{5=`$n?o1&rqj9KYNu<~v_I1t;(&PMW1lGRJaYzH-n!pzW-929h z^i4-uA0|U^iEu>BD`$+IqLM6TgcOexM(np@2&6j0FP|X*fjB-?L!lH z>_FKXmYkB^q`XC(a6J1hz4A-E?s)JD*PXz)Y~c&XhtK%Q3E&6*q|h@9%LU)&!AE$p s;6a2*A()EE|3>6iYeb$S_r){dUuPGm$Z6uog6Dprl&8C4TIsODAG$ws2LJ#7 delta 632 zcmZuvO-mbL5PoMj`;pkjC~dRYKwezk6(w%J@nj5Jqcby|3D#!Qt}fzv%97}IPlCoJ3Bk`%&@m(gVD>vnO|M1)E1=l zB-{U9%EiSfNp2@2gir`=Mi_LuVY6`%wvHOFo1GvGyX}q$gWdhc@ouLrPFmgL(wiV` z28ZR=yp)v}OSOmQR6H;3`#u#^eede~jPfaU^}DD~3+wIqD(0b-$$|=LAwbn|3)b-( zob>AQ_DX9%*xtlnaECo*3a^zMW>g6iIH#UY7f9i~<%moX9wmvK03pg7o6FN3clAJsN)yijeH*e=sB%Ub!(^^ zwq~h99O9f|!v(%FT;-jLCx!!G@w4H=4gR3iPZbA-qxI<<2cMfZWbvixma25Pa{}-A el)!gkVXTpw4(%KLBxOX?woEGdILy;(3I7Y9k6#x6 diff --git a/bin/riscv64gc-unknown-none-elf.a b/bin/riscv64gc-unknown-none-elf.a index c1e5504f62b494061d9e6d9dd686ec491c15e471..d07711b420aa423380abac1e02b2054c1410bb60 100644 GIT binary patch delta 817 zcmZuvO=uHA6rMNPY<4$^X|qiy3l&$z7!d0wE!nh(6s)KPL0VhLAtg=QEgteCSp)S} zix)4_<$3U+hd{3tMG8H5=~;z(5%J*JQ^AXP)0wcVTj&S#-n{RC{`T9?nZ_WTV-0?+c4`oyL0IZ9IHH zyiUeEtwh1HN~Mx%PFUr#w`rQPGKftngBw?Pu$0k)^6qhN3taqs64>}21 zJR7+MIbm)_c8y`4aEJg=g2cYQjG*Z}P4t=wz&_PsDxj_psLymHHGao3$%z*^m;V1E ztw;3@r@iK2N6N$qVf>gO>b{i5K*zqM<45VhnDZ-M;5yvJ9KMROrMn?7e~Etx_#9`# zr|$U?BAb|BfPfeAD$dIchVd}UjC2sd^^m`(Tqp1+_a;ML)87NvXYjntlBtk4kDsCp zYjVN}Pw8aF$GmEi=hdTmelqdytsDV9kNucUUr2Zyt3Va|!0?8W_jgZ}yju0ERB>Oi zwcp}Ha+CpoDJ6J=SJfG6$=Fsa@E!NKK>&}{3jHeMxK>du(Jn_3dzuZaxTnozc6{zY bT$DrHgCWGP(AyHeR&ux)&(d-X+wt6Ar`C|K delta 687 zcmZ`#%}X0m5P!4JP4aeAjV*Ca3HZ<|f|zdNx@$yYp@JTSf*^Q^#Gotqm4wZv2p$xV zo{Zz!dg#HUpf`K!(e}`zc(MHpJXqR;m%bMhOhJDz^JacC^XB6^c4+L!x9t%pnI7WY z>75JgByis$+juaH~ziW|9=g711>rQ{RO%`fH3dA~$9i60-IMZU+r$mHz{K_8(cHoM8%fNTM6V6Y9 zmYz{gRrK`?i^$Og`tU+`z{Wd$Ji1Wl-pQo|C{`T9?nZ_WTV-0?+c4`oyL0IZ9IHH zyiUeEtwh1HN~Mx%PFUr#w`rQPGKftngBw?Pu$0k)^6qhN3taqs64>}21 zJR7+MIbm)_c8y`4aEJg=g2cYQjG*Z}P4t=wz&_PsDxj_psLymHHGao3$%z*^m;V1E ztw;3@r@iK2N6N$qVf>gO>b{i5K*zqM<45VhnDZ-M;5yvJ9KMROrMn?7e~Etx_#9`# zr|$U?BAb|BfPfeAD$dIchVd}UjC2sd^^m`(Tqp1+_a;ML)87NvXYjntlBtk4kDsCp zYjVN}Pw8aF$GmEi=hdTmelqdytsDV9kNucUUr2Zyt3Va|!0?8W_jgZ}yju0ERB>Oi zwcp}Ha+CpoDJ6J=SJfG6$=Fsa@E!NKK>&}{3jHeMxK>du(Jn_3dzuZaxTnozc6{zY bT$DrHgCWGP(AyHeR&ux)&(d-X+wt6Ar`C|K delta 687 zcmZ`#%}X0m5P!4JP4aeAjV*Ca3HZ<|f|zdNx@$yYp@JTSf*^Q^#Gotqm4wZv2p$xV zo{Zz!dg#HUpf`K!(e}`zc(MHpJXqR;m%bMhOhJDz^JacC^XB6^c4+L!x9t%pnI7WY z>75JgByis$+juaH~ziW|9=g711>rQ{RO%`fH3dA~$9i60-IMZU+r$mHz{K_8(cHoM8%fNTM6V6Y9 zmYz{gRrK`?i^$Og`tU+`z{Wd$Ji1Wl-pQo| Uart { - // Uart { - // base: base_addr as *mut usize, - // } - // } pub fn init(&self) -> Result<(), XousError> { - // mm.claim_page(self.base as usize, 1) + // sys_memory_allocate( + // Some(MemoryAddress::new(0xe0001800).unwrap()), + // Some(MemoryAddress::new(0xe0001800).unwrap()), + // MemorySize::new(4096).unwrap(), + // ) + // .expect("Couldn't identity map"); Ok(()) } diff --git a/src/main.rs b/src/main.rs index 22ffea2..4c1a547 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,7 +31,7 @@ fn handle_panic(arg: &PanicInfo) -> ! { } extern "Rust" { - fn return_from_interrupt() -> !; + fn enable_mmu() -> !; } extern "C" { /// Debug function to read the current SATP. Useful since Renode @@ -56,17 +56,55 @@ fn mmu_init() -> ! { .expect("Couldn't create identity mapping for PID1"); println!("MMU enabled, jumping to kmain"); - pt.switch_to(process1, kmain as usize).expect("Couldn't switch to PID1"); + pt.switch_to(process1, kmain as usize) + .expect("Couldn't switch to PID1"); println!("SATP: {:08x}", unsafe { read_satp() }); unsafe { - mstatus::set_spp(mstatus::SPP::Supervisor); + // When we do an "mret", return to supervisor mode. mstatus::set_mpp(mstatus::MPP::Supervisor); - println!("kmain: MSTATUS: {:?}", mstatus::read()); - return_from_interrupt() + + // Additionally, enable CPU interrupts + mstatus::set_mie(); + + println!("loader: MSTATUS: {:?}", mstatus::read()); + enable_mmu() } } +#[no_mangle] +#[inline(never)] +fn test_good_write() { + let good_ptr = 0x4001_6000 as *mut u32; + // print!("Good ptr write:"); + unsafe { good_ptr.write_volatile(0x12345678) }; + // print!("Ok\r\nGood ptr read: "); + let val = unsafe { good_ptr.read_volatile() }; + // println!("{:08x}", val); +} + +#[no_mangle] +#[inline(never)] +fn test_bad_write() { + let bad_ptr = 0x4001_f000 as *mut u32; + unsafe { bad_ptr.write_volatile(0x98765432) }; + let val = unsafe { bad_ptr.read_volatile() }; + // print!("Bad ptr write:"); + // print!("Ok\r\nBad ptr read: "); + // println!("{:08x}", val); +} + +#[no_mangle] +#[inline(never)] +fn test_uart_write() { + let io_ptr = 0xe000_1800 as *mut u32; + unsafe { io_ptr.add(0).write_volatile(65) }; + // print!("UART ptr write: "); + // print!(" Ok\r\nUART ptr read: "); + let val = unsafe { io_ptr.add(0).read_volatile() }; + println!("{:08x}", val); +} + /// This function runs with the MMU enabled, as part of PID 1 #[no_mangle] fn kmain() -> ! { @@ -75,16 +113,14 @@ fn kmain() -> ! { mie::set_msoft(); mie::set_mtimer(); mie::set_mext(); - mstatus::set_mpp(mstatus::MPP::Supervisor); - mstatus::set_spie(); - mstatus::set_mie(); // Enable CPU interrupts + // mstatus::set_spie(); } - println!("kmain: SATP: {:08x}", satp::read().bits()); - println!("kmain: MSTATUS: {:?}", mstatus::read()); - let uart = debug::DEFAULT_UART; - uart.init(); + // uart.init(); + + // println!("kmain: SATP: {:08x}", satp::read().bits()); + // println!("kmain: MSTATUS: {:?}", mstatus::read()); // sys_interrupt_claim(0, timer::irq).unwrap(); // timer::time_init(); @@ -94,6 +130,10 @@ fn kmain() -> ! { sys_interrupt_claim(2, debug::irq).expect("Couldn't claim interrupt 2"); + test_good_write(); + test_uart_write(); + test_bad_write(); + println!("Entering main loop"); // let mut last_time = timer::get_time(); loop { @@ -112,9 +152,9 @@ pub fn trap_handler() { let irqs_pending = vmip::read(); if mc.is_exception() { - println!("CPU Exception"); let ex = exception::RiscvException::from_regs(mc.bits(), mepc::read(), mtval::read()); - println!("{}", ex); + // print!("CPU Exception: "); + // println!("{}", ex); unsafe { vexriscv::asm::ebreak() }; loop {} } diff --git a/src/mem.rs b/src/mem.rs index ce7113a..1ec297c 100644 --- a/src/mem.rs +++ b/src/mem.rs @@ -158,6 +158,7 @@ impl MemoryManager { self.claim_page(region & !0xfff, 1)?; } } + self.claim_page(0xe000_1000, 1)?; unsafe { mstatus::set_mie() }; @@ -199,7 +200,7 @@ impl MemoryManager { /// # Errors /// /// * OutOfMemory - Tried to allocate a new pagetable, but ran out of memory. - fn map_page( + fn map_page_inner( &mut self, root: &mut PageTable, phys: usize, @@ -272,6 +273,9 @@ impl MemoryManager { root_page, &pt, pt ); + // self.map_page_inner(pt, 0xe0001000, 0xe001000)?; + // println!(""); + let mut ranges = [ mem_range!(&_sbss, &_ebss), mem_range!(&_sdata, &_edata), @@ -280,13 +284,31 @@ impl MemoryManager { ]; for range in &mut ranges { for region in range { - self.map_page(pt, region, region)?; + self.map_page_inner(pt, region, region)?; println!(""); } } Ok(()) } + pub fn map_page(&mut self, satp: usize, phys: usize, virt: usize) -> Result { + let root_page = (satp & ((1 << 22) - 1)) << 12; + let pid = ((satp >> 22) & ((1<<9)-1)) as XousPid; + assert!(root_page >= RAM_START); + assert!(root_page < RAM_END); + assert!(pid != 0); + let pt = unsafe { &mut (*(root_page as *mut PageTable)) }; + + self.claim_page(phys, pid)?; + match self.map_page_inner(pt, phys, virt) { + Ok(_) => Ok(MemoryAddress::new(virt).expect("Virt address was not 0")), + Err(e) => { + self.release_page(phys, pid); + Err(e) + } + } + } + /// Mark a given address as being owned by the specified process ID fn claim_page(&mut self, addr: usize, pid: XousPid) -> Result<(), XousError> { let mut mm = unsafe { &mut MM }; @@ -316,4 +338,34 @@ impl MemoryManager { _ => Err(XousError::BadAddress), } } + + /// Mark a given address as being owned by the specified process ID + fn release_page(&mut self, addr: usize, pid: XousPid) -> Result<(), XousError> { + let mut mm = unsafe { &mut MM }; + + fn release_page_inner(tbl: &mut [u8], addr: usize, pid: XousPid) -> Result<(), XousError> { + let page = addr / PAGE_SIZE; + if page > tbl.len() { + return Err(XousError::BadAddress); + } + if tbl[page] != pid { + return Err(XousError::MemoryInUse); + } + tbl[page] = 0; + Ok(()) + } + + // Ensure the address lies on a page boundary + if addr & 0xfff != 0 { + return Err(XousError::BadAlignment); + } + + match addr { + FLASH_START..=FLASH_END => release_page_inner(&mut mm.flash, addr - FLASH_START, pid), + RAM_START..=RAM_END => release_page_inner(&mut mm.ram, addr - RAM_START, pid), + IO_START..=IO_END => release_page_inner(&mut mm.io, addr - IO_START, pid), + LCD_START..=LCD_END => release_page_inner(&mut mm.lcd, addr - LCD_START, pid), + _ => Err(XousError::BadAddress), + } + } } diff --git a/src/processtable.rs b/src/processtable.rs index df36821..25a979b 100644 --- a/src/processtable.rs +++ b/src/processtable.rs @@ -2,6 +2,7 @@ use crate::definitions::{MemoryAddress, MemorySize, XousError, XousPid}; use crate::mem::MemoryManager; use crate::{filled_array, print, println}; use vexriscv::register::{mepc, mstatus, satp}; +use vexriscv::asm::sfence_vma; const MAX_PROCESS_COUNT: usize = 256; static mut CURRENT_SATP: usize = 0; @@ -22,6 +23,7 @@ static mut PT: ProcessTableInner = ProcessTableInner { extern "Rust" { fn kmain(mm: MemoryManager, pt: ProcessTable) -> !; + fn flush_mmu(r1: usize, r2: usize); } impl core::fmt::Debug for Process { @@ -58,6 +60,7 @@ impl ProcessTableInner { } satp::write(new_satp); mepc::write(pc); + unsafe { flush_mmu(0, 0) }; Ok(()) } @@ -104,9 +107,16 @@ pub fn sys_memory_allocate( virt: Option, size: MemorySize, ) -> Result { + let mut mm = MemoryManager::new()?; match phys { - Some(addr) => {} - None => {} + Some(paddr) => match virt { + Some(vaddr) => return mm.map_page(unsafe { CURRENT_SATP }, paddr.get(), vaddr.get()), + None => {}, + } + None => match virt { + Some(vaddr) => {}, + None => {}, + } } Ok(MemoryAddress::new(4096).unwrap()) diff --git a/src/syscalls.rs b/src/syscalls.rs index 7d753e1..39455dd 100644 --- a/src/syscalls.rs +++ b/src/syscalls.rs @@ -26,14 +26,14 @@ pub fn sys_interrupt_claim(irq: usize, f: fn(usize)) -> Result<(), XousError> { /// or the size isn't a multiple of the page width. /// * **OutOfMemory**: A contiguous chunk of memory couldn't be found, or the system's /// memory size has been exceeded. -#[allow(dead_code)] -pub fn sys_memory_allocate( - phys: Option, - virt: Option, - size: MemorySize, -) -> Result { - crate::processtable::sys_memory_allocate(phys, virt, size) -} +// #[allow(dead_code)] +// pub fn sys_memory_allocate( +// phys: Option, +// virt: Option, +// size: MemorySize, +// ) -> Result { +// crate::processtable::sys_memory_allocate(phys, virt, size) +// } extern "Rust" { /// Allocates kernel structures for a new process, and returns the new PID. diff --git a/src/uart.rs b/src/uart.rs deleted file mode 100644 index 645911b..0000000 --- a/src/uart.rs +++ /dev/null @@ -1,66 +0,0 @@ -use core::fmt::{Error, Write}; - -pub struct Uart {} - -impl Uart { - pub fn new() -> Uart { - Uart {} - } - - pub fn putc(&self, c: u8) { - let ptr = 0xE000_1800 as *mut u32; - unsafe { - while ptr.add(1).read_volatile() == 0 {} - ptr.add(0).write_volatile(c as u32); - } - } - - fn get(&self, base_addr: usize) -> Option { - let ptr = 0xE000_1800 as *mut u32; - unsafe { - if ptr.add(2).read_volatile() == 0 { - Some(ptr.add(0).read_volatile() as u8) - } else { - None - } - } - } -} - -// This is a slightly different syntax. Write is this "trait", meaning it is much like -// an interface where we're just guaranteeing a certain function signature. In the Write -// trait, one is absolutely required to be implemented, which is write_str. There are other -// functions, but they all rely on write_str(), so their default implementation is OK for now. -impl Write for Uart { - // The trait Write expects us to write the function write_str - // which looks like: - fn write_str(&mut self, s: &str) -> Result<(), Error> { - for c in s.bytes() { - self.putc(c); - } - // Return that we succeeded. - Ok(()) - } -} - -#[macro_export] -macro_rules! print -{ - ($($args:tt)+) => ({ - use core::fmt::Write; - let _ = write!(crate::uart::Uart::new(), $($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)+) - }); -}