浏览代码

Use latest `riscv` crate as dependency for QEMU platform

luojia65 4 年之前
父节点
当前提交
3bf8eb53e5
共有 5 个文件被更改,包括 69 次插入36 次删除
  1. 2 0
      CHANGELOG.md
  2. 1 1
      platform/qemu/Cargo.toml
  3. 2 2
      platform/qemu/justfile
  4. 21 24
      platform/qemu/src/main.rs
  5. 43 9
      test-kernel/src/main.rs

+ 2 - 0
CHANGELOG.md

@@ -12,6 +12,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 ### Modified
 - Enhanced in-line code documents from SBI standard
 - 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
 
 ### Fixed
 - Test kernel console now will lock before `println` line is finished

+ 1 - 1
platform/qemu/Cargo.toml

@@ -13,7 +13,7 @@ rustsbi = { path = "../../rustsbi" }
 linked_list_allocator = "0.8"
 lazy_static = { version = "1", features = ["spin_no_std"] }
 spin = "0.7"
-riscv = { git = "https://github.com/rust-embedded/riscv", features = ["inline-asm"] }
+riscv = { git = "https://github.com/rust-embedded/riscv", rev = "7358eda6", features = ["inline-asm"] }
 device_tree = { git = "https://github.com/rcore-os/device_tree-rs/" }
 
 # 这几个其实不用,应该使用对应的hal库实现

+ 2 - 2
platform/qemu/justfile

@@ -3,8 +3,8 @@ mode := "debug"
 build-path := "../../target/" + target + "/" + mode + "/"
 rustsbi-elf := build-path + "rustsbi-qemu"
 rustsbi-bin := build-path + "rustsbi-qemu.bin"
-test-kernel-elf := build-path + "rustsbi-test-kernel"
-test-kernel-bin := build-path + "rustsbi-test-kernel.bin"
+test-kernel-elf := build-path + "test-kernel"
+test-kernel-bin := build-path + "test-kernel.bin"
 
 objdump := "riscv64-unknown-elf-objdump"
 objcopy := "rust-objcopy --binary-architecture=riscv64"

+ 21 - 24
platform/qemu/src/main.rs

@@ -22,7 +22,7 @@ use riscv::register::{
     mstatus::{self, MPP, SPP},
     mtval,
     mtvec::{self, TrapMode},
-    stvec,
+    stvec, scause, stval, sepc,
 };
 
 #[global_allocator]
@@ -410,17 +410,16 @@ extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
             #[inline]
             unsafe fn get_vaddr_u32(vaddr: usize) -> u32 {
                 let mut ans: u32;
-                llvm_asm!("
-                    li      t0, (1 << 17)
-                    mv      t1, $1
-                    csrrs   t0, mstatus, t0
-                    lwu     t1, 0(t1)
-                    csrw    mstatus, t0
-                    mv      $0, t1
-                "
-                    :"=r"(ans) 
-                    :"r"(vaddr)
-                    :"t0", "t1");
+                asm!("
+                    li      {tmp}, (1 << 17)
+                    csrrs   {tmp}, mstatus, {tmp}
+                    lwu     {ans}, 0({vaddr})
+                    csrw    mstatus, {tmp}
+                    ",
+                    tmp = out(reg) _,
+                    vaddr = in(reg) vaddr,
+                    ans = lateout(reg) ans
+                );
                 ans
             }
             let vaddr = mepc::read();
@@ -452,26 +451,24 @@ extern "C" fn start_trap_rust(trap_frame: &mut TrapFrame) {
                 mepc::write(mepc::read().wrapping_add(4)); // 跳过指令
             } else if mstatus::read().mpp() != MPP::Machine { // can't emulate, raise invalid instruction to supervisor
                 // 出现非法指令异常,转发到S特权层
-                let cause: usize = 2; // Interrupt = 0, Exception Code = 2 (Illegal Exception)
-                let val: usize = mtval::read();
-                let epc: usize = mepc::read();
-                unsafe { asm!("
-                    csrw    scause, {cause}
-                    csrw    stval, {val}
-                    csrw    sepc, {epc}
-                ", cause = in(reg) cause, val = in(reg) val, epc = in(reg) epc) };
-                // 设置中断位
                 unsafe { 
+                    // 设置S层异常原因为:非法指令
+                    scause::set(scause::Trap::Exception(scause::Exception::IllegalInstruction));
+                    // 填写异常指令的指令内容
+                    stval::write(mtval::read());
+                    // 填写S层需要返回到的地址,这里的mepc会被随后的代码覆盖掉
+                    sepc::write(mepc::read());
+                    // 设置中断位
                     mstatus::set_mpp(MPP::Supervisor);
                     mstatus::set_spp(SPP::Supervisor);
                     if mstatus::read().sie() {
                         mstatus::set_spie()
                     }
                     mstatus::clear_sie();
+                    // 设置返回地址,返回到S层
+                    // 注意,无论是Direct还是Vectored模式,所有异常的向量偏移都是0,不需要处理中断向量,跳转到入口地址即可
+                    mepc::write(stvec::read().address());
                 };
-                // 设置返回地址,返回到S层
-                // 注意,无论是Direct还是Vectored模式,非法指令异常永远属于异常,不需要处理中断向量,跳转到入口地址即可
-                mepc::write(stvec::read().address());
             } else {
                 // 真·非法指令异常,是M层出现的
                 #[cfg(target_pointer_width = "64")]

+ 43 - 9
test-kernel/src/main.rs

@@ -79,17 +79,51 @@ unsafe extern "C" fn entry() -> ! {
     options(noreturn))
 }
 
+
+#[cfg(target_pointer_width = "128")]
+macro_rules! define_store_load {
+    () => {
+        ".altmacro
+        .macro STORE reg, offset
+            sq  \\reg, \\offset* {REGBYTES} (sp)
+        .endm
+        .macro LOAD reg, offset
+            lq  \\reg, \\offset* {REGBYTES} (sp)
+        .endm"
+    };
+}
+
+#[cfg(target_pointer_width = "64")]
+macro_rules! define_store_load {
+    () => {
+        ".altmacro
+        .macro STORE reg, offset
+            sd  \\reg, \\offset* {REGBYTES} (sp)
+        .endm
+        .macro LOAD reg, offset
+            ld  \\reg, \\offset* {REGBYTES} (sp)
+        .endm"
+    };
+}
+
+#[cfg(target_pointer_width = "32")]
+macro_rules! define_store_load {
+    () => {
+        ".altmacro
+        .macro STORE reg, offset
+            sw  \\reg, \\offset* {REGBYTES} (sp)
+        .endm
+        .macro LOAD reg, offset
+            lw  \\reg, \\offset* {REGBYTES} (sp)
+        .endm"
+    };
+}
+
 #[naked]
 #[link_section = ".text"]
 unsafe extern "C" fn start_trap() {
-    asm!("
-.altmacro
-.macro STORE reg, offset
-    sd  \\reg, \\offset* {REGBYTES} (sp)
-.endm
-.macro LOAD reg, offset
-    ld  \\reg, \\offset* {REGBYTES} (sp)
-.endm
+    asm!(concat!(define_store_load!(), "
+    .p2align 2
     addi    sp, sp, -16 * {REGBYTES}
     STORE   ra, 0
     STORE   t0, 1
@@ -127,7 +161,7 @@ unsafe extern "C" fn start_trap() {
     LOAD    a7, 15
     addi    sp, sp, 16 * {REGBYTES}
     sret
-    ",
+    "),
     REGBYTES = const core::mem::size_of::<usize>(),
     rust_trap_exception = sym rust_trap_exception,
     options(noreturn))