Forráskód Böngészése

Merge pull request #4 from wyfcyx/master

Fix devintr for k210 platform
Luo Jia 4 éve
szülő
commit
041babe2bc
1 módosított fájl, 39 hozzáadás és 4 törlés
  1. 39 4
      platform/k210/src/main.rs

+ 39 - 4
platform/k210/src/main.rs

@@ -23,6 +23,8 @@ use riscv::register::{
 #[global_allocator]
 static ALLOCATOR: LockedHeap = LockedHeap::empty();
 
+static mut DEVINTRENTRY: usize = 0;
+
 #[cfg(not(test))]
 #[panic_handler]
 fn panic(info: &PanicInfo) -> ! {
@@ -360,10 +362,14 @@ extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
     let cause = mcause::read().cause();
     match cause {
         Trap::Exception(Exception::SupervisorEnvCall) => {
-            let params = [trap_frame.a0, trap_frame.a1, trap_frame.a2, trap_frame.a3];
-            let ans = rustsbi::ecall(trap_frame.a7, trap_frame.a6, params);
-            trap_frame.a0 = ans.error;
-            trap_frame.a1 = ans.value;
+            if trap_frame.a7 == 0x09 {
+                unsafe { DEVINTRENTRY = trap_frame.a0; }
+            } else {
+                let params = [trap_frame.a0, trap_frame.a1, trap_frame.a2, trap_frame.a3];
+                let ans = rustsbi::ecall(trap_frame.a7, trap_frame.a6, params);
+                trap_frame.a0 = ans.error;
+                trap_frame.a1 = ans.value;
+            }
             mepc::write(mepc::read().wrapping_add(4));
         }
         Trap::Interrupt(Interrupt::MachineSoft) => {
@@ -379,6 +385,7 @@ extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
             }
         }
         Trap::Interrupt(Interrupt::MachineExternal) => {
+            /* legacy software delegation
             // to make UARTHS interrupt soft delegation work; ref: pull request #1
             // PLIC target0(Always Hart0-M-Interrupt) acquire
             let irq_id = unsafe { (0x0c20_0004 as *const u32).read_volatile() };
@@ -392,6 +399,33 @@ extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
             unsafe { llvm_asm!("csrw stval, $0" :: "r"(ch as usize) :: "volatile"); }
             // soft delegate to S Mode soft interrupt
             unsafe { mip::set_ssoft(); }
+             */
+            unsafe {
+                let mut mstatus: usize;
+                llvm_asm!("csrr $0, mstatus" : "=r"(mstatus) ::: "volatile");
+                // set mstatus.mprv
+                mstatus |= 1 << 17;
+                // it may trap from U/S Mode
+                // save mpp and set mstatus.mpp to S Mode
+                let mpp = (mstatus >> 11) & 3;
+                mstatus = mstatus & !(3 << 11);
+                mstatus |= 1 << 11;
+                // drop mstatus.mprv protection
+                llvm_asm!("csrw mstatus, $0" :: "r"(mstatus) :: "volatile");
+                fn devintr() {
+                    unsafe {
+                        // call devintr defined in application
+                        // we have to ask compiler save ra explicitly
+                        llvm_asm!("jalr 0($0)" :: "r"(DEVINTRENTRY) : "ra" : "volatile");
+                    }
+                }
+                // compiler helps us save/restore caller-saved registers
+                devintr();
+                // restore mstatus
+                mstatus |= mpp << 11;
+                mstatus -= 1 << 17;
+                llvm_asm!("csrw mstatus, $0" :: "r"(mstatus) :: "volatile");
+            }
         }
         Trap::Exception(Exception::IllegalInstruction) => {
             let vaddr = mepc::read();
@@ -486,3 +520,4 @@ fn set_rd(trap_frame: &mut TrapFrame, rd: u8, value: usize) {
         _ => panic!("invalid target `rd`"),
     }
 }
+