Browse Source

Add instruction emulation test in SBI

luojia65 4 years ago
parent
commit
fd68b09e1e
3 changed files with 34 additions and 19 deletions
  1. 1 0
      CHANGELOG.md
  2. 26 19
      platform/qemu/src/main.rs
  3. 7 0
      test-kernel/src/main.rs

+ 1 - 0
CHANGELOG.md

@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Remove use of `global_asm` and `llvm_asm` in test kernel
 - Align to 4 bytes for interrupt handler on QEMU and test kernel
 - Update `riscv` crate dependency for QEMU platform
+- Use `mtval` to read instruction on QEMU; still need to be kept on K210 as 1.9.1 does not define this register behavior
 
 ### Fixed
 - Test kernel console now will lock before `println` line is finished

+ 26 - 19
platform/qemu/src/main.rs

@@ -378,6 +378,30 @@ struct TrapFrame {
     a7: usize,
 }
 
+impl TrapFrame {
+    #[inline]
+    fn set_register_xi(&mut self, i: u8, data: usize) {
+        match i {
+            10 => self.a0 = data,
+            11 => self.a1 = data,
+            12 => self.a2 = data,
+            13 => self.a3 = data,
+            14 => self.a4 = data,
+            15 => self.a5 = data,
+            16 => self.a6 = data,
+            17 => self.a7 = data,
+            5 =>  self.t0 = data,
+            6 =>  self.t1 = data,
+            7 =>  self.t2 = data,
+            28 => self.t3 = data,
+            29 => self.t4 = data,
+            30 => self.t5 = data,
+            31 => self.t6 = data,
+            _ => panic!("invalid target"),
+        }
+    }
+}
+
 #[export_name = "_start_trap_rust"]
 extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
     let cause = mcause::read().cause();
@@ -430,26 +454,9 @@ extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
                 // todo: one instance only
                 let clint = hal::Clint::new(0x2000000 as *mut u8);
                 let time_usize = clint.get_mtime() as usize;
-                match rd {
-                    10 => trap_frame.a0 = time_usize,
-                    11 => trap_frame.a1 = time_usize,
-                    12 => trap_frame.a2 = time_usize,
-                    13 => trap_frame.a3 = time_usize,
-                    14 => trap_frame.a4 = time_usize,
-                    15 => trap_frame.a5 = time_usize,
-                    16 => trap_frame.a6 = time_usize,
-                    17 => trap_frame.a7 = time_usize,
-                    5 => trap_frame.t0 = time_usize,
-                    6 => trap_frame.t1 = time_usize,
-                    7 => trap_frame.t2 = time_usize,
-                    28 => trap_frame.t3 = time_usize,
-                    29 => trap_frame.t4 = time_usize,
-                    30 => trap_frame.t5 = time_usize,
-                    31 => trap_frame.t6 = time_usize,
-                    _ => panic!("invalid target"),
-                }
+                trap_frame.set_register_xi(rd, time_usize);
                 mepc::write(mepc::read().wrapping_add(4)); // 跳过指令
-            } else if mstatus::read().mpp() != MPP::Machine { // can't emulate, raise invalid instruction to supervisor
+            } else if mstatus::read().mpp() != MPP::Machine { // invalid instruction, can't emulate, raise to supervisor
                 // 出现非法指令异常,转发到S特权层
                 unsafe { 
                     // 设置S层异常原因为:非法指令

+ 7 - 0
test-kernel/src/main.rs

@@ -12,6 +12,7 @@ use riscv::register::{sepc, stvec::{self, TrapMode}};
 pub extern "C" fn rust_main(hartid: usize, dtb_pa: usize) -> ! {
     println!("<< Test-kernel: Hart id = {}, DTB physical address = {:#x}", hartid, dtb_pa);
     test_base_extension();
+    test_sbi_ins_emulation();
     unsafe { stvec::write(start_trap as usize, TrapMode::Direct) };
     println!(">> Test-kernel: Trigger illegal exception");
     unsafe { asm!("csrw mcycle, x0") }; // mcycle cannot be written, this is always a 4-byte illegal instruction
@@ -37,6 +38,12 @@ fn test_base_extension() {
     println!("<< Test-kernel: Device mimpid: {:x}", sbi::get_mimpid());
 }
 
+fn test_sbi_ins_emulation() {
+    println!(">> Test-kernel: Testing SBI instruction emulation");
+    let time = riscv::register::time::read64();
+    println!("<< Test-kernel: Current time: {:x}", time);
+}
+
 pub extern "C" fn rust_trap_exception() {
     println!("<< Test-kernel: Illegal exception delegate success");
     sepc::write(sepc::read().wrapping_add(4));