From 3a464d853387e840893e9ac22178e83b3833a8ec Mon Sep 17 00:00:00 2001 From: Alex Martens Date: Fri, 5 Sep 2025 18:50:33 -0700 Subject: [PATCH] x86, riscv64: mark constructors as unsafe --- CHANGELOG.md | 1 + README.md | 10 +++++++--- src/lib.rs | 6 +++--- src/riscv64.rs | 2 +- src/x86.rs | 2 +- tests/exit_13.rs | 4 ++-- 6 files changed, 15 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b393bd..c02d46f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,5 +17,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Moved the repository to [rust-embedded](https://github.com/rust-embedded) under the libs team. +- Changed `X86::new` and `RISCV64::new` to unsafe. [Unreleased]: https://github.com/rust-embedded/qemu-exit/compare/v3.0.2...HEAD diff --git a/README.md b/README.md index 9339d1a..bb6566b 100644 --- a/README.md +++ b/README.md @@ -21,12 +21,12 @@ let qemu_exit_handle = qemu_exit::AArch64::new(); // addr: The address of sifive_test. #[cfg(target_arch = "riscv64")] -let qemu_exit_handle = qemu_exit::RISCV64::new(addr); +let qemu_exit_handle = unsafe { qemu_exit::RISCV64::new(addr) }; // io_base: I/O-base of isa-debug-exit. // custom_exit_success: A custom success code; Must be an odd number. #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -let qemu_exit_handle = qemu_exit::X86::new(io_base, custom_exit_success); +let qemu_exit_handle = unsafe { qemu_exit::X86::new(io_base, custom_exit_success) }; qemu_exit_handle.exit(1337); qemu_exit_handle.exit_success(); @@ -38,6 +38,7 @@ qemu_exit_handle.exit_failure(); ### AArch64/AArch32 Pass the `-semihosting` argument to the QEMU invocation, e.g.: + ``` qemu-system-aarch64 -M raspi3 -serial stdio -semihosting -kernel kernel8.img qemu-system-arm -nographic -M mps2-an500 -cpu cortex-m7 -serial mon:stdio -semihosting -kernel @@ -47,6 +48,7 @@ kernel.img ### RISCV64 You need to chose a machine with the `sifive_test` device, for exemple `-M virt`: + ``` qemu-system-riscv64 -M virt -nographic -monitor none -serial stdio -kernel kernel.elf ``` @@ -54,6 +56,7 @@ qemu-system-riscv64 -M virt -nographic -monitor none -serial stdio -kernel kerne ### x86/x86_64 Add the special ISA debug exit device by passing the flags: + ``` -device isa-debug-exit,iobase=0xf4,iosize=0x04 ``` @@ -67,7 +70,7 @@ binary-OR'ed with `0x1`. This is hardcoded and therefore, with `isa-debug-exit`, possible to let QEMU invoke `exit(0)`. ```rust -let qemu_exit_handle = qemu_exit::X86::new(io_base, custom_exit_success); +let qemu_exit_handle = unsafe { qemu_exit::X86::new(io_base, custom_exit_success) }; ``` #### x86/x86_64 Linux @@ -75,6 +78,7 @@ let qemu_exit_handle = qemu_exit::X86::new(io_base, custom_exit_success); To use this mechanism from Linux userspace, the kernel must be compiled with `CONFIG_X86_IOPL_IOPERM=y` (which is the default) and the process must start with root privileges (or `CAP_SYS_RAWIO`) and call: [`ioperm(2)`](https://man7.org/linux/man-pages/man2/ioperm.2.html): + ```rust nix::errno::Errno::result(unsafe { libc::ioperm( 0xf4, 4, 1 )}).expect("ioperm failed"); ``` diff --git a/src/lib.rs b/src/lib.rs index e278d88..ea2ea7f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,12 +20,12 @@ //! //! // addr: The address of sifive_test. //! #[cfg(target_arch = "riscv64")] -//! let qemu_exit_handle = qemu_exit::RISCV64::new(addr); +//! let qemu_exit_handle = unsafe { qemu_exit::RISCV64::new(addr) }; //! //! // io_base: I/O-base of isa-debug-exit. //! // custom_exit_success: A custom success code; Must be an odd number. //! #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -//! let qemu_exit_handle = qemu_exit::X86::new(io_base, custom_exit_success); +//! let qemu_exit_handle = unsafe { qemu_exit::X86::new(io_base, custom_exit_success) }; //! //! qemu_exit_handle.exit(1337); //! qemu_exit_handle.exit_success(); @@ -74,7 +74,7 @@ //! possible to let QEMU invoke `exit(0)`. //! //! ```ignore -//! let qemu_exit_handle = qemu_exit::X86::new(io_base, custom_exit_success); +//! let qemu_exit_handle = unsafe { qemu_exit::X86::new(io_base, custom_exit_success) }; //! ``` //! //! ## Literature diff --git a/src/riscv64.rs b/src/riscv64.rs index ae1d047..e6ef111 100644 --- a/src/riscv64.rs +++ b/src/riscv64.rs @@ -26,7 +26,7 @@ const fn exit_code_encode(code: u32) -> u32 { impl RISCV64 { /// Create an instance. - pub const fn new(addr: u64) -> Self { + pub const unsafe fn new(addr: u64) -> Self { RISCV64 { addr } } } diff --git a/src/x86.rs b/src/x86.rs index 16f4bf6..ffae6fc 100644 --- a/src/x86.rs +++ b/src/x86.rs @@ -33,7 +33,7 @@ fn outl(io_base: u16, code: u32) { impl X86 { /// Create an instance. - pub const fn new(io_base: u16, custom_exit_success: u32) -> Self { + pub const unsafe fn new(io_base: u16, custom_exit_success: u32) -> Self { assert!((custom_exit_success & 1) == 1); X86 { diff --git a/tests/exit_13.rs b/tests/exit_13.rs index cec0490..c654fee 100644 --- a/tests/exit_13.rs +++ b/tests/exit_13.rs @@ -35,7 +35,7 @@ mod armv7m_mps2an500; //-------------------------------------------------------------------------------------------------- #[cfg(target_arch = "riscv64")] -const QEMU_EXIT_HANDLE: qemu_exit::RISCV64 = qemu_exit::RISCV64::new(0x100000); +const QEMU_EXIT_HANDLE: qemu_exit::RISCV64 = unsafe { qemu_exit::RISCV64::new(0x100000) }; #[cfg(target_arch = "riscv64")] mod riscv64_virt; @@ -45,7 +45,7 @@ mod riscv64_virt; //-------------------------------------------------------------------------------------------------- #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -const QEMU_EXIT_HANDLE: qemu_exit::X86 = qemu_exit::X86::new(0xf4, 5); +const QEMU_EXIT_HANDLE: qemu_exit::X86 = unsafe { qemu_exit::X86::new(0xf4, 5) }; //-------------------------------------------------------------------------------------------------- // Generic code