Ver Fonte

Save readme for K210

luojia65 há 4 anos atrás
pai
commit
fc77821ca6
3 ficheiros alterados com 46 adições e 10 exclusões
  1. 22 0
      platform/k210/README.md
  2. 23 9
      platform/k210/src/main.rs
  3. 1 1
      rustsbi/Cargo.toml

+ 22 - 0
platform/k210/README.md

@@ -0,0 +1,22 @@
+# K210 support module
+
+Kendryte K210 is a dual-core RISC-V RV64GC chip with hardware accelerated AI peripheral.
+According to its manual, K210 is taped out in TSMC 7nm and can speed up to 400MHz.
+
+The K210 SoC implements version 1.9.1 of RISC-V's privileged specification.
+This version differents from latest version (by current version 1.11) in the following aspects:
+
+1. Register `sstatus.sum` (in 1.11) or `sstatus.pum` (in 1.9) bits;
+2. Instruction `sfence.vma` (1.11) or `sfence.vm` (1.9), register `satp` (1.11) or `sptbr` (1.9);
+3. There's no S-level external interrupt in 1.9, but there is in 1.11;
+4. Independent page fault exceptions does not exist in 1.9, but they exist in 1.11.
+
+To prolong lifecycle of K210 chip we uses RustSBI as a compatible layer. We emulate sfence.vma 
+using sfence.vm to solve issue 2. We modify regster values to solve issue 4. For issue 3, 
+we introduce an SBI call local to RustSBI to register S-level interrupt handler by the supervisor 
+itself. The issue 1 should left to be concerned by supervisors above SBI implementations.
+
+Machine external handler and timer set calls is modified to meet the requirement of custom S-level
+interrupt handlers.
+
+If there are mistakes or missing features in current support module, we welcome further contributions!

+ 23 - 9
platform/k210/src/main.rs

@@ -182,7 +182,7 @@ fn main() -> ! {
         struct Reset;
         impl rustsbi::Reset for Reset {
             fn reset(&self) -> ! {
-                println!("[rustsbi] todo: shutdown all harts on k210; program halt");
+                println!("[rustsbi] reset triggered! todo: shutdown all harts on k210; program halt");
                 loop {}
             }
         }
@@ -362,9 +362,18 @@ extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
     let cause = mcause::read().cause();
     match cause {
         Trap::Exception(Exception::SupervisorEnvCall) => {
-            if trap_frame.a7 == 0x09 {
+            if trap_frame.a7 == 0x09 { 
+                // We use legacy 0x09 for now to register S-level interrupt handler
+                // for K210 chip only. This chip uses 1.9.1 version of privileged spec,
+                // which did not declare any S-level external interrupts. 
                 unsafe { DEVINTRENTRY = trap_frame.a0; }
             } else {
+                // Due to legacy 1.9.1 version of privileged spec, if we are in S-level
+                // timer handler (delegated from M mode), and we call SBI's `set_timer`,
+                // a M-level external interrupt may be triggered. This may try to obtain
+                // data structures locked previously by S-level interrupt handler, which
+                // results in a deadlock. 
+                // Ref: https://github.com/luojia65/rustsbi/pull/5 
                 if trap_frame.a7 == 0x0 {
                     unsafe {
                         let mtip = mip::read().mtimer();
@@ -373,6 +382,7 @@ extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
                         }
                     }
                 }
+                // Actual ecall handler which is common for all RustSBI platforms
                 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;
@@ -381,16 +391,18 @@ extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
             mepc::write(mepc::read().wrapping_add(4));
         }
         Trap::Interrupt(Interrupt::MachineSoft) => {
+            // Forward to S-level software interrupt
             unsafe {
-                mip::set_ssoft();
-                mie::clear_msoft();
+                mip::set_ssoft(); // set S-soft interrupt flag
+                mie::clear_msoft(); // mask M-soft interrupt
             }
         }
         Trap::Interrupt(Interrupt::MachineTimer) => {
+            // Forward to S-level timer interrupt
             unsafe {
-                mip::set_stimer();
-                mie::clear_mext();
-                mie::clear_mtimer();
+                mip::set_stimer(); // set S-timer interrupt flag
+                mie::clear_mext(); // Ref: Pull request #5
+                mie::clear_mtimer(); // mask M-timer interrupt
             }
         }
         Trap::Interrupt(Interrupt::MachineExternal) => {
@@ -448,6 +460,8 @@ extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
                 set_rd(trap_frame, rd, time_usize);
                 mepc::write(mepc::read().wrapping_add(4)); // skip current instruction 
             } else if ins & 0xFE007FFF == 0x12000073 { // sfence.vma instruction
+                // There is no `sfence.vma` in 1.9.1 privileged spec; however there is a `sfence.vm`.
+                // For backward compability, here we emulate the first instruction using the second one.
                 // sfence.vma: | 31..25 funct7=SFENCE.VMA(0001001) | 24..20 rs2/asid | 19..15 rs1/vaddr | 
                 //               14..12 funct3=PRIV(000) | 11..7 rd, =0 | 6..0 opcode=SYSTEM(1110011) |
                 // sfence.vm(1.9):  | 31..=20 SFENCE.VM(000100000100) | 19..15 rs1/vaddr |
@@ -475,11 +489,11 @@ extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
                 // ::"r"(rs1_vaddr)
                 mepc::write(mepc::read().wrapping_add(4)); // skip current instruction
             } else {
-                panic!("invalid instruction, mepc: {:016x?}, instruction: {:08x?}", mepc::read(), ins);
+                panic!("invalid instruction! mepc: {:016x?}, instruction: {:08x?}", mepc::read(), ins);
             }
         }
         cause => panic!(
-            "Unhandled trap! mcause: {:?}, mepc: {:016x?}, mtval: {:016x?}",
+            "unhandled trap! mcause: {:?}, mepc: {:016x?}, mtval: {:016x?}",
             cause,
             mepc::read(),
             mtval::read(),

+ 1 - 1
rustsbi/Cargo.toml

@@ -10,5 +10,5 @@ edition = "2018"
 embedded-hal = "1.0.0-alpha.1"
 nb = "1.0"
 riscv = "0.6"
-spin = "0.5"
+spin = "0.6"
 lazy_static = { version = "1", features = ["spin_no_std"] }