Next Generation WASM Microkernel Operating System
wasm os rust microkernel
fork

Configure Feed

Select the types of activity you want to include in your feed.

at trap_handler 151 lines 5.3 kB view raw
1// Copyright 2025 Jonas Kruckenberg 2// 3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or 4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or 5// http://opensource.org/licenses/MIT>, at your option. This file may not be 6// copied, modified, or distributed except according to those terms. 7 8#[macro_export] 9#[doc(hidden)] 10macro_rules! syscall { 11 ($nr:path) => { 12 $crate::semihosting::syscall_inner($nr, 0) 13 }; 14 ($nr:path, $a1:expr) => { 15 $crate::semihosting::syscall_inner($nr, ::core::ptr::from_ref(&[$a1 as usize]) as usize) 16 }; 17 ($nr:path, $a1:expr, $a2:expr) => { 18 $crate::semihosting::syscall_inner( 19 $nr, 20 ::core::ptr::from_ref(&[$a1 as usize, $a2 as usize]) as usize, 21 ) 22 }; 23 ($nr:path, $a1:expr, $a2:expr, $a3:expr) => { 24 $crate::semihosting::syscall_inner( 25 $nr, 26 ::core::ptr::from_ref(&[$a1 as usize, $a2 as usize, $a3 as usize]) as usize, 27 ) 28 }; 29 ($nr:path, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => { 30 $crate::semihosting::syscall_inner( 31 $nr, 32 ptr::from_ref(&[$a1 as usize, $a2 as usize, $a3 as usize, $a4 as usize]) as usize, 33 ) 34 }; 35} 36 37#[inline(always)] 38#[expect( 39 clippy::used_underscore_binding, 40 reason = "compiler thinks nr and arg are unused otherwise" 41)] 42pub(crate) unsafe fn syscall_inner(_nr: usize, _arg: usize) -> usize { 43 cfg_if::cfg_if! { 44 if #[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))] { 45 use core::arch::asm; 46 47 let mut nr = _nr; 48 let arg = _arg; 49 // The instructions below must always be uncompressed, otherwise 50 // it will be treated as a regular break, hence the norvc option. 51 // 52 // See https://github.com/riscv/riscv-semihosting-spec for more details. 53 // Safety: inline assembly 54 unsafe { 55 asm! { 56 ".balign 16", 57 ".option push", 58 ".option norvc", 59 "slli x0, x0, 0x1f", 60 "ebreak", 61 "srai x0, x0, 0x7", 62 ".option pop", 63 inout("a0") nr, 64 inout("a1") arg => _, 65 options(nostack, preserves_flags), 66 }; 67 } 68 nr 69 } else { 70 unimplemented!(); 71 } 72 } 73} 74 75pub use syscall; 76 77/// [SYS_EXIT (0x18)](https://github.com/ARM-software/abi-aa/blob/HEAD/semihosting/semihosting.rst#sys_exit-0x18) 78pub const SYS_EXIT: usize = 0x18; 79 80#[cfg(target_pointer_width = "32")] 81/// [SYS_EXIT_EXTENDED (0x20)](https://github.com/ARM-software/abi-aa/blob/HEAD/semihosting/semihosting.rst#sys_exit_extended-0x20) 82pub const SYS_EXIT_EXTENDED: usize = 0x20; 83 84#[derive(Debug, Clone, Copy)] 85#[repr(usize)] 86#[non_exhaustive] 87pub enum ExitReason { 88 // Reason codes related to hardware exceptions: 89 // AdpStoppedBranchThroughZero = 0x20000, 90 // AdpStoppedUndefinedInstr = 0x20001, 91 // AdpStoppedSoftwareInterrupt = 0x20002, 92 // AdpStoppedPrefetchAbort = 0x20003, 93 // AdpStoppedDataAbort = 0x20004, 94 // AdpStoppedAddressException = 0x20005, 95 // AdpStoppedIrq = 0x20006, 96 // AdpStoppedFiq = 0x20007, 97 98 // Reason codes related to software events: 99 // AdpStoppedBreakPoint = 0x20020, 100 // AdpStoppedWatchPoint = 0x20021, 101 // AdpStoppedStepComplete = 0x20022, 102 AdpStoppedRunTimeErrorUnknown = 0x20023, 103 // AdpStoppedInternalError = 0x20024, 104 // AdpStoppedUserInterruption = 0x20025, 105 AdpStoppedApplicationExit = 0x20026, 106 // AdpStoppedStackOverflow = 0x20027, 107 // AdpStoppedDivisionByZero = 0x20028, 108 // AdpStoppedOsspecific = 0x20029, 109} 110 111#[expect( 112 clippy::cast_sign_loss, 113 reason = "sign extended conversion from i32 to usize" 114)] 115pub(crate) fn exit(code: i32) { 116 // TODO: check sh_ext_exit_extended first 117 sys_exit_extended( 118 ExitReason::AdpStoppedApplicationExit, 119 code as isize as usize, 120 ); 121 // If SYS_EXIT_EXTENDED is not supported, above call doesn't exit program, 122 // so try again with SYS_EXIT. 123 let reason = match code { 124 0i32 => ExitReason::AdpStoppedApplicationExit, 125 _ => ExitReason::AdpStoppedRunTimeErrorUnknown, 126 }; 127 sys_exit(reason); 128} 129 130/// [SYS_EXIT (0x18)](https://github.com/ARM-software/abi-aa/blob/HEAD/semihosting/semihosting.rst#sys_exit-0x18) 131pub fn sys_exit(reason: ExitReason) { 132 // Safety: syscall 133 unsafe { 134 #[cfg(target_pointer_width = "32")] 135 syscall!(SYS_EXIT, reason as usize); 136 #[cfg(target_pointer_width = "64")] 137 syscall!(SYS_EXIT, reason as usize, 0); 138 } 139} 140 141/// [SYS_EXIT_EXTENDED (0x20)](https://github.com/ARM-software/abi-aa/blob/HEAD/semihosting/semihosting.rst#sys_exit_extended-0x20) 142pub fn sys_exit_extended(reason: ExitReason, subcode: usize) { 143 // Safety: syscall 144 unsafe { 145 #[cfg(target_pointer_width = "32")] 146 syscall!(SYS_EXIT_EXTENDED, reason as usize, subcode); 147 // On 64-bit system, SYS_EXIT_EXTENDED call is identical to the behavior of the mandatory SYS_EXIT. 148 #[cfg(target_pointer_width = "64")] 149 syscall!(SYS_EXIT, reason as usize, subcode); 150 } 151}