1use core::fmt::Debug;
4
5use bitflags::bitflags;
6use twizzler_rt_abi::error::{RawTwzError, TwzError};
7
8pub use crate::arch::upcall::UpcallFrame;
9use crate::{
10 object::ObjID,
11 syscall::{sys_thread_get_upcall, sys_thread_set_upcall},
12};
13
14#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
16#[repr(C)]
17pub struct ExceptionInfo {
18 pub code: u64,
20 pub info: u64,
22}
23
24impl ExceptionInfo {
25 pub fn new(code: u64, info: u64) -> Self {
27 Self { code, info }
28 }
29}
30
31#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
33#[repr(C)]
34pub struct ObjectMemoryFaultInfo {
35 pub object_id: ObjID,
37 pub error: ObjectMemoryError,
39 pub access: MemoryAccessKind,
41 pub addr: usize,
43}
44
45impl ObjectMemoryFaultInfo {
46 pub fn new(
48 object_id: ObjID,
49 error: ObjectMemoryError,
50 access: MemoryAccessKind,
51 addr: usize,
52 ) -> Self {
53 Self {
54 object_id,
55 error,
56 access,
57 addr,
58 }
59 }
60}
61
62#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
64#[repr(u8)]
65pub enum ObjectMemoryError {
66 NullPageAccess,
68 OutOfBounds(usize),
70 BackingFailed(RawTwzError),
72}
73
74#[derive(Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
76#[repr(C)]
77pub struct MemoryContextViolationInfo {
78 pub address: u64,
80 pub kind: MemoryAccessKind,
82}
83
84impl Debug for MemoryContextViolationInfo {
85 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
86 write!(
87 f,
88 "MemoryContextViolationInfo {{ {:?}: {:x} }}",
89 self.kind, self.address
90 )
91 }
92}
93
94impl MemoryContextViolationInfo {
95 pub fn new(address: u64, kind: MemoryAccessKind) -> Self {
96 Self { address, kind }
97 }
98}
99
100#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
102#[repr(u8)]
103pub enum MemoryAccessKind {
104 Read,
105 Write,
106 InstructionFetch,
107}
108
109#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
111#[repr(C)]
112pub struct SecurityViolationInfo {
113 pub address: u64,
115 pub access_kind: MemoryAccessKind,
117}
118
119#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
121#[repr(C)]
122pub enum UpcallInfo {
123 Exception(ExceptionInfo),
124 ObjectMemoryFault(ObjectMemoryFaultInfo),
125 MemoryContextViolation(MemoryContextViolationInfo),
126 SecurityViolation(SecurityViolationInfo),
127 Mailbox(u64),
128}
129
130impl UpcallInfo {
131 pub const NR_UPCALLS: usize = 5;
133 pub fn number(&self) -> usize {
135 match self {
136 UpcallInfo::Exception(_) => 0,
137 UpcallInfo::ObjectMemoryFault(_) => 1,
138 UpcallInfo::MemoryContextViolation(_) => 2,
139 UpcallInfo::SecurityViolation(_) => 3,
140 UpcallInfo::Mailbox(_) => 4,
141 }
142 }
143}
144
145#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
148#[repr(C)]
149pub struct UpcallData {
150 pub info: UpcallInfo,
152 pub flags: UpcallHandlerFlags,
154 pub source_ctx: ObjID,
156 pub thread_id: ObjID,
158}
159
160#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
163#[repr(C)]
164pub struct UpcallTarget {
165 pub self_address: usize,
167 pub super_address: usize,
169 pub super_stack: usize,
171 pub super_stack_size: usize,
173 pub super_thread_ptr: usize,
175 pub super_ctx: ObjID,
177 pub self_ctx: ObjID,
179 pub options: [UpcallOptions; UpcallInfo::NR_UPCALLS],
181}
182
183impl UpcallTarget {
184 pub fn new(
186 self_address: Option<
187 unsafe extern "C-unwind" fn(*mut core::ffi::c_void, *const core::ffi::c_void) -> !,
188 >,
189 super_address: Option<
190 unsafe extern "C-unwind" fn(*mut core::ffi::c_void, *const core::ffi::c_void) -> !,
191 >,
192 super_stack: usize,
193 super_stack_size: usize,
194 super_thread_ptr: usize,
195 super_ctx: ObjID,
196 self_ctx: ObjID,
197 options: [UpcallOptions; UpcallInfo::NR_UPCALLS],
198 ) -> Self {
199 Self {
200 self_address: self_address.map(|addr| addr as usize).unwrap_or_default(),
201 super_address: super_address.map(|addr| addr as usize).unwrap_or_default(),
202 super_stack,
203 super_thread_ptr,
204 super_ctx,
205 self_ctx,
206 options,
207 super_stack_size,
208 }
209 }
210}
211
212pub const UPCALL_EXIT_CODE: u64 = 127;
216
217bitflags::bitflags! {
218 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
220pub struct UpcallFlags : u8 {
221 const SUSPEND = 1;
223}
224}
225
226bitflags::bitflags! {
227 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
229pub struct UpcallHandlerFlags : u8 {
230 const SWITCHED_CONTEXT = 1;
232}
233}
234
235#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
237pub enum UpcallMode {
238 Abort,
241 CallSelf,
245 CallSuper,
251}
252
253#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
255pub struct UpcallOptions {
256 pub flags: UpcallFlags,
258 pub mode: UpcallMode,
260}
261
262bitflags! {
263 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
264 pub struct ResumeFlags: u64 {
265 const SUSPEND = 1;
267 }
268}
269
270pub fn set_self_upcall_ptr(
271 target: unsafe extern "C-unwind" fn(*mut UpcallFrame, *const UpcallData) -> !,
272) -> Result<(), TwzError> {
273 let mut upcall = sys_thread_get_upcall()?;
274 upcall.self_address = target as usize;
275 sys_thread_set_upcall(upcall)?;
276 Ok(())
277}