1use core::fmt::Debug;
4
5use bitflags::bitflags;
6use twizzler_rt_abi::error::RawTwzError;
7
8pub use crate::arch::upcall::UpcallFrame;
9use crate::object::ObjID;
10
11#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
13#[repr(C)]
14pub struct ExceptionInfo {
15 pub code: u64,
17 pub info: u64,
19}
20
21impl ExceptionInfo {
22 pub fn new(code: u64, info: u64) -> Self {
24 Self { code, info }
25 }
26}
27
28#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
30#[repr(C)]
31pub struct ObjectMemoryFaultInfo {
32 pub object_id: ObjID,
34 pub error: ObjectMemoryError,
36 pub access: MemoryAccessKind,
38 pub addr: usize,
40}
41
42impl ObjectMemoryFaultInfo {
43 pub fn new(
45 object_id: ObjID,
46 error: ObjectMemoryError,
47 access: MemoryAccessKind,
48 addr: usize,
49 ) -> Self {
50 Self {
51 object_id,
52 error,
53 access,
54 addr,
55 }
56 }
57}
58
59#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
61#[repr(u8)]
62pub enum ObjectMemoryError {
63 NullPageAccess,
65 OutOfBounds(usize),
67 BackingFailed(RawTwzError),
69}
70
71#[derive(Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
73#[repr(C)]
74pub struct MemoryContextViolationInfo {
75 pub address: u64,
77 pub kind: MemoryAccessKind,
79}
80
81impl Debug for MemoryContextViolationInfo {
82 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
83 write!(
84 f,
85 "MemoryContextViolationInfo {{ {:?}: {:x} }}",
86 self.kind, self.address
87 )
88 }
89}
90
91impl MemoryContextViolationInfo {
92 pub fn new(address: u64, kind: MemoryAccessKind) -> Self {
93 Self { address, kind }
94 }
95}
96
97#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
99#[repr(u8)]
100pub enum MemoryAccessKind {
101 Read,
102 Write,
103 InstructionFetch,
104}
105
106#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
108#[repr(C)]
109pub struct SecurityViolationInfo {
110 pub address: u64,
112 pub access_kind: MemoryAccessKind,
114}
115
116#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
118#[repr(C)]
119pub enum UpcallInfo {
120 Exception(ExceptionInfo),
121 ObjectMemoryFault(ObjectMemoryFaultInfo),
122 MemoryContextViolation(MemoryContextViolationInfo),
123 SecurityViolation(SecurityViolationInfo),
124}
125
126impl UpcallInfo {
127 pub const NR_UPCALLS: usize = 3;
129 pub fn number(&self) -> usize {
131 match self {
132 UpcallInfo::Exception(_) => 0,
133 UpcallInfo::ObjectMemoryFault(_) => 1,
134 UpcallInfo::MemoryContextViolation(_) => 2,
135 UpcallInfo::SecurityViolation(_) => 3,
136 }
137 }
138}
139
140#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
143#[repr(C)]
144pub struct UpcallData {
145 pub info: UpcallInfo,
147 pub flags: UpcallHandlerFlags,
149 pub source_ctx: ObjID,
151 pub thread_id: ObjID,
153}
154
155#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
158#[repr(C)]
159pub struct UpcallTarget {
160 pub self_address: usize,
162 pub super_address: usize,
164 pub super_stack: usize,
166 pub super_stack_size: usize,
168 pub super_thread_ptr: usize,
170 pub super_ctx: ObjID,
172 pub options: [UpcallOptions; UpcallInfo::NR_UPCALLS],
174}
175
176impl UpcallTarget {
177 pub fn new(
179 self_address: Option<
180 unsafe extern "C-unwind" fn(*mut core::ffi::c_void, *const core::ffi::c_void) -> !,
181 >,
182 super_address: Option<
183 unsafe extern "C-unwind" fn(*mut core::ffi::c_void, *const core::ffi::c_void) -> !,
184 >,
185 super_stack: usize,
186 super_stack_size: usize,
187 super_thread_ptr: usize,
188 super_ctx: ObjID,
189 options: [UpcallOptions; UpcallInfo::NR_UPCALLS],
190 ) -> Self {
191 Self {
192 self_address: self_address.map(|addr| addr as usize).unwrap_or_default(),
193 super_address: super_address.map(|addr| addr as usize).unwrap_or_default(),
194 super_stack,
195 super_thread_ptr,
196 super_ctx,
197 options,
198 super_stack_size,
199 }
200 }
201}
202
203pub const UPCALL_EXIT_CODE: u64 = 127;
207
208bitflags::bitflags! {
209 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
211pub struct UpcallFlags : u8 {
212 const SUSPEND = 1;
214}
215}
216
217bitflags::bitflags! {
218 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
220pub struct UpcallHandlerFlags : u8 {
221 const SWITCHED_CONTEXT = 1;
223}
224}
225
226#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
228pub enum UpcallMode {
229 Abort,
232 CallSelf,
236 CallSuper,
242}
243
244#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
246pub struct UpcallOptions {
247 pub flags: UpcallFlags,
249 pub mode: UpcallMode,
251}
252
253bitflags! {
254 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
255 pub struct ResumeFlags: u64 {
256 const SUSPEND = 1;
258 }
259}