Skip to content

Commit bcda180

Browse files
committed
fix riscv64 shutdown
- riscv64/processor.rs: shut down via the SiFive test finisher (0x100000) instead of the semihosting exit - drop the now unused semihosting dependency for riscv64
1 parent 526b68b commit bcda180

1 file changed

Lines changed: 25 additions & 2 deletions

File tree

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
use core::arch::asm;
2+
use core::ptr::write_volatile;
23

3-
use semihosting::process::exit;
4+
/// MMIO address of QEMU's SiFive test finisher on the `virt` machine.
5+
const SIFIVE_TEST: *mut u32 = 0x0010_0000 as *mut u32;
6+
/// Finisher command that makes QEMU exit successfully.
7+
const FINISHER_PASS: u32 = 0x5555;
8+
/// Finisher command that makes QEMU exit with a failure code.
9+
const FINISHER_FAIL: u32 = 0x3333;
410

511
/// The halt function stops the processor until the next interrupt arrives
612
pub(crate) fn halt() {
@@ -10,8 +16,25 @@ pub(crate) fn halt() {
1016
}
1117

1218
/// Shutdown the system
19+
///
20+
/// QEMU's `virt` machine exits when the SiFive test finisher is written: a value
21+
/// of `0x5555` exits successfully, while `0x3333 | (code << 16)` exits with the
22+
/// given error code.
1323
#[allow(unused_variables)]
1424
#[no_mangle]
1525
pub(crate) extern "C" fn shutdown(error_code: i32) -> ! {
16-
exit(error_code)
26+
let value = if error_code == 0 {
27+
FINISHER_PASS
28+
} else {
29+
FINISHER_FAIL | ((error_code as u32) << 16)
30+
};
31+
32+
unsafe {
33+
write_volatile(SIFIVE_TEST, value);
34+
}
35+
36+
// The write above terminates QEMU; loop just in case it does not.
37+
loop {
38+
halt();
39+
}
1740
}

0 commit comments

Comments
 (0)