twz_rt/runtime/
upcall.rs

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}