tock / libtock-rs

Rust userland library for Tock

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Examples in Qemu-7.0.0

dongmu opened this issue Β· comments

Hello there,

When executed in Qemu-7.0.0, an example (compiled with libtock-rs) crashes with Tock 2.1. I tried different methods, but failed to figure out the cause. Any reply would be appreciated. Thanks.

Qemu-7.0.0 is configured with: (Qemu is downloaded from the office website without any modification.)

--python=python3 --target-list="riscv32-softmmu riscv64-softmmu arm-softmmu aarch64-softmmu" --disable-vnc --disable-curses --disable-sdl --disable-hax --disable-rdma --enable-debug

The code with libtock-rs is compiled with:

LIBTOCK_PLATFORM="qemuvirt" cargo run --example "qemuvirtapp" -p libtock --release --target=riscv32imac-unknown-none-elf

Example code: (examples/qemuvirtapp.rs)

#![no_main]
#![no_std]
use libtock::console::Console;
use libtock::runtime::{set_main, stack_size};
use libtock::alarm::{Alarm, Milliseconds};

set_main! {main}
stack_size! {0x200}

fn main() {
    Console::driver_check();
    Alarm::sleep_for(Milliseconds(250)).unwrap();
}

ld file: (runtime/layouts/qemuvirt.ld)

MEMORY {
  FLASH (X) : ORIGIN = 0x80100000, LENGTH = 0x100000
  RAM   (W) : ORIGIN = 0x80202c00, LENGTH = 0x200000
}

TBF_HEADER_SIZE = 0x48;
INCLUDE libtock_layout.ld

One line added into runner/src/elf2tab.rs for function get_platform_architecture(platform: &str) -> Option<&'static str>:

"qemuvirt" => Some("riscv32imac"),

Error message:

QEMU RISC-V 32-bit "virt" machine, initialization complete.
Entering main loop.
Loading processes from flash=0x80100000-0x801FFFFF into sram=0x80202C00-0x803FFFFF
Loaded process[0] from flash=0x80100000-0x8010127B into sram=0x80202C00-0x80203AFF = "qemuvirtapp"
[0] function_call @0x80100068(0x80100048, 0x80202c00, 0xf00, 0x80202c00)
[0] memop(0, 0x80202e00) = Success
[0] memop(10, 0x80202e00) = Success
[0] memop(11, 0x80202e00) = Success
[0] cmd(0x1, 0, 0x0, 0x0) = Success
[0] cmd(0x0, 1, 0x0, 0x0) = SuccessU32(32768)
[0] remove_pending_upcalls[0x0:0] = 0 upcall(s) removed
[0] subscribe(0x0, 0, @0x80100ef0, 0x80202dd8) = SubscribeSuccess(0x0, 0)
[0] cmd(0x0, 5, 0x2000, 0x0) = SuccessU32(418502)
[0] schedule[0x0:0] @0x80100ef0(0x6a725, 0x662c6, 0x0, 0x80202dd8) = Ok(())
[0] yield. which: 1
[0] function_call @0x80100ef0(0x6a725, 0x662c6, 0x0, 0x80202dd8)
[0] remove_pending_upcalls[0x0:0] = 0 upcall(s) removed
[0] subscribe(0x0, 0, @0x0, 0x0) = SubscribeSuccess(0x80100ef0, 2149592536)

panicked at 'Process qemuvirtapp had a fault', kernel/src/process_standard.rs:333:17
        Kernel version 1827bba

---| No debug queue found. You can set it with the DebugQueue component.

---| RISC-V Machine State |---
Last cause (mcause): Machine external interrupt (interrupt=1, exception code=0x0000000B)
Last value (mtval):  0x00000000

System register dump:
 mepc:    0x800051DA    mstatus:     0x00000088
 mcycle:  0xCEA6F058    minstret:    0xCEA7CB0E
 mtvec:   0x80000100
 mstatus: 0x00000088
  uie:    false  upie:   false
  sie:    false  spie:   false
  mie:    true   mpie:   true
  spp:    false
 mie:   0x00000888   mip:   0x00000000
  usoft:  false               false
  ssoft:  false               false
  msoft:  true                false
  utimer: false               false
  stimer: false               false
  mtimer: true                false
  uext:   false               false
  sext:   false               false
  mext:   true                false

---| App Status |---
𝐀𝐩𝐩: qemuvirtapp   -   [Faulted]
 Events Queued: 0   Syscall Count: 9   Dropped Upcall Count: 0
 Restart Count: 0
 Last Syscall: Subscribe { driver_number: 0, subdriver_number: 0, upcall_ptr: 0x0, appdata: 0 }
 Completion Code: None
 
 ╔═══════════╀══════════════════════════════════════════╗
 β•‘  Address  β”‚ Region Name    Used | Allocated (bytes)  β•‘
 β•š0x80203B00═β•ͺ══════════════════════════════════════════╝
             β”‚ Grant Ptrs       32
             β”‚ Upcalls         360
             β”‚ Process         888
  0x80203600 ┼───────────────────────────────────────────
             β”‚ β–Ό Grant         100
  0x8020359C ┼───────────────────────────────────────────
             β”‚ Unused
  0x80202E00 ┼───────────────────────────────────────────
             β”‚ β–² Heap            0 |   1948               S
  0x80202E00 ┼─────────────────────────────────────────── R
             β”‚ Data              0 |      0               A
  0x80202E00 ┼─────────────────────────────────────────── M
             β”‚ β–Ό Stack          48 |    512
  0x80202DD0 ┼───────────────────────────────────────────
             β”‚ Unused
  0x80202C00 ┴───────────────────────────────────────────
             .....
  0x8010127C ┬─────────────────────────────────────────── F
             β”‚ App Flash      4660                        L
  0x80100048 ┼─────────────────────────────────────────── A
             β”‚ Protected        72                        S
  0x80100000 ┴─────────────────────────────────────────── H

 R0 : 0x00000000    R16: 0x00000001
 R1 : 0x80100FEA    R17: 0x007D0000
 R2 : 0x80202DD0    R18: 0x00000000
 R3 : 0x00000000    R19: 0x00000000
 R4 : 0x00000000    R20: 0x00000000
 R5 : 0x00000000    R21: 0x00000000
 R6 : 0x00000000    R22: 0x00000000
 R7 : 0x00000000    R23: 0x00000000
 R8 : 0x00000001    R24: 0x00000000
 R9 : 0x80100068    R25: 0x00000000
 R10: 0x00000082    R26: 0x00000000
 R11: 0x80100EF0    R27: 0x00000000
 R12: 0x80202DD8    R28: 0x00000000
 R13: 0x00000000    R29: 0x00000000
 R14: 0x00000001    R30: 0x00000000
 R15: 0x00000000    R31: 0x00000000
 PC : 0x80101000

 mcause: 0x00000001 (Instruction access fault)
 mtval:  0x80101000


 Total number of grant regions defined: 4
  Grant  0 0x0: 0x8020359c  Grant  2 : --
  Grant  1 0x1: 0x802035b4  Grant  3 : --
 PMP regions:
  [0]: addr=0x80100000, size=0x0000127C, cfg=0xD (r-x)
  [1]: addr=0x80202c00, size=0x00000200, cfg=0xB (rw-)
  <unset>
  <unset>
  <unset>
  <unset>
  <unset>
  <unset>

To debug, run `make lst` in the app's folder
and open the arch.0x80100048.0x80202c00.lst file.

@lschuermann -- I'll walk through what I see, would you mind double-checking my work?

In the app status dump, I see:

 mcause: 0x00000001 (Instruction access fault)

which makes me think that PC is pointing at non-executable memory. mtval is 0x80101000 and PC is 0x80101000 which further supports my theory. However, 0x80101000 falls within the first PMP region in the PMP region dump:

 PMP regions:
  [0]: addr=0x80100000, size=0x0000127C, cfg=0xD (r-x)
  [1]: addr=0x80202c00, size=0x00000200, cfg=0xB (rw-)

which is RX, so I think the fetch should've worked? Maybe this is a kernel bug in PMP configuration?

I could easily be missing or misunderstanding something -- QEMU virtio is not my forte.

It seems like this issue is related to a known-bug in QEMU (starting with at least v7.0.0): tock/tock#3316. This bug unfortunately breaks QEMU's enforcement of the PMP memory protection rules on platforms which feature an MMU (which the QEMU virt board does), independent of whether the MMU is used or not. Even though these accesses are valid, QEMU raises a fault when an address is accessed but the matching PMP region does not span an entire page of memory.

This bug appears to have been fixed in QEMU mainline as part of a larger refactoring effort around QEMU's Tiny Code Generator (TCG). @dongmu Can you try to reproduce this on QEMU master or v7.2.0-rc2 and see whether the issue is resolved?

This issue is already documented in the board's README, but perhaps we can make it more obvious that application support is broken. As soon as QEMU issues a release containing this fix (likely v7.2.0), we may be able to check the QEMU version and issue a warning accordingly.

Thank you, @lschuermann and @jrvanwhy . I used Tock-2.1 version and did not check Tock-master. Sorry to duplicate the question here.

Several examples work correctly on Qemu-v7.2.0-rc2. I will let you know if new issues arise. Thanks.