1use std::{ffi::c_void, sync::OnceLock};
2
3use twizzler_abi::upcall::{UpcallData, UpcallFrame, UpcallHandlerFlags};
4
5pub(crate) fn upcall_rust_entry(frame: &mut UpcallFrame, info: &UpcallData) {
6 let imp = UPCALL_IMPL.get();
7 if let Some(Some(imp)) = imp {
8 unsafe {
9 imp(
10 frame as *mut _ as *mut c_void,
11 info as *const _ as *const c_void,
12 )
13 }
14 } else {
15 upcall_def_handler(frame, info)
16 }
17}
18
19pub type HandlerType = unsafe extern "C-unwind" fn(frame: *mut c_void, info: *const c_void);
20static UPCALL_IMPL: OnceLock<Option<HandlerType>> = OnceLock::new();
21
22pub fn set_upcall_handler(handler: Option<HandlerType>) -> Result<(), HandlerSetError> {
23 UPCALL_IMPL.set(handler).map_err(|_| HandlerSetError)
24}
25
26#[derive(Clone, Copy, Debug)]
27pub struct HandlerSetError;
28
29pub(crate) fn upcall_def_handler(_frame: &mut UpcallFrame, info: &UpcallData) {
30 if info.flags.contains(UpcallHandlerFlags::SWITCHED_CONTEXT) {
31 println!("got supervisor upcall");
32 }
33 println!("got upcall: {:?}", info);
34 panic!("upcall");
35}