Nothing to see here, move along
at main 262 lines 7.7 kB view raw
1#[derive(Debug, Clone, Copy)] 2#[repr(C)] 3#[derive(zerocopy::IntoBytes, zerocopy::Immutable, zerocopy::KnownLayout)] 4pub struct CpuContext { 5 pub(crate) rax: u64, 6 pub(crate) rbx: u64, 7 pub(crate) rcx: u64, 8 pub(crate) rdx: u64, 9 pub(crate) rsi: u64, 10 pub(crate) rdi: u64, 11 pub(crate) rbp: u64, 12 pub(crate) r8: u64, 13 pub(crate) r9: u64, 14 pub(crate) r10: u64, 15 pub(crate) r11: u64, 16 pub(crate) r12: u64, 17 pub(crate) r13: u64, 18 pub(crate) r14: u64, 19 pub(crate) r15: u64, 20 pub(crate) rip: u64, 21 pub(crate) rsp: u64, 22 pub(crate) rflags: u64, 23 pub(crate) cs: u64, 24 pub(crate) ss: u64, 25} 26 27impl CpuContext { 28 pub const fn zero() -> Self { 29 Self { 30 rax: 0, 31 rbx: 0, 32 rcx: 0, 33 rdx: 0, 34 rsi: 0, 35 rdi: 0, 36 rbp: 0, 37 r8: 0, 38 r9: 0, 39 r10: 0, 40 r11: 0, 41 r12: 0, 42 r13: 0, 43 r14: 0, 44 r15: 0, 45 rip: 0, 46 rsp: 0, 47 rflags: 0, 48 cs: 0, 49 ss: 0, 50 } 51 } 52 53 pub fn checksum(&self) -> u64 { 54 const FNV_OFFSET: u64 = 0xcbf29ce484222325; 55 const FNV_PRIME: u64 = 0x100000001b3; 56 zerocopy::IntoBytes::as_bytes(self) 57 .iter() 58 .fold(FNV_OFFSET, |hash, &b| { 59 (hash ^ b as u64).wrapping_mul(FNV_PRIME) 60 }) 61 } 62 63 pub fn validate_user(&self, pid: u16) { 64 const USER_ADDR_LIMIT: u64 = 0x0000_8000_0000_0000; 65 const USER_CS: u64 = 0x23; 66 const USER_SS: u64 = 0x1b; 67 68 assert!( 69 self.rip > 0 && self.rip < USER_ADDR_LIMIT, 70 "[ctx] pid {}: rip={:#x} outside user range", 71 pid, 72 self.rip, 73 ); 74 75 assert!( 76 self.rsp > 0 && self.rsp < USER_ADDR_LIMIT, 77 "[ctx] pid {}: rsp={:#x} outside user range", 78 pid, 79 self.rsp, 80 ); 81 82 assert!( 83 self.cs == USER_CS, 84 "[ctx] pid {}: cs={:#x} expected {:#x}", 85 pid, 86 self.cs, 87 USER_CS, 88 ); 89 90 assert!( 91 self.ss == USER_SS, 92 "[ctx] pid {}: ss={:#x} expected {:#x}", 93 pid, 94 self.ss, 95 USER_SS, 96 ); 97 } 98} 99 100const _: () = { 101 assert!(core::mem::offset_of!(CpuContext, rax) == 0); 102 assert!(core::mem::offset_of!(CpuContext, rbx) == 8); 103 assert!(core::mem::offset_of!(CpuContext, rcx) == 16); 104 assert!(core::mem::offset_of!(CpuContext, rdx) == 24); 105 assert!(core::mem::offset_of!(CpuContext, rsi) == 32); 106 assert!(core::mem::offset_of!(CpuContext, rdi) == 40); 107 assert!(core::mem::offset_of!(CpuContext, rbp) == 48); 108 assert!(core::mem::offset_of!(CpuContext, r8) == 56); 109 assert!(core::mem::offset_of!(CpuContext, r9) == 64); 110 assert!(core::mem::offset_of!(CpuContext, r10) == 72); 111 assert!(core::mem::offset_of!(CpuContext, r11) == 80); 112 assert!(core::mem::offset_of!(CpuContext, r12) == 88); 113 assert!(core::mem::offset_of!(CpuContext, r13) == 96); 114 assert!(core::mem::offset_of!(CpuContext, r14) == 104); 115 assert!(core::mem::offset_of!(CpuContext, r15) == 112); 116 assert!(core::mem::offset_of!(CpuContext, rip) == 120); 117 assert!(core::mem::offset_of!(CpuContext, rsp) == 128); 118 assert!(core::mem::offset_of!(CpuContext, rflags) == 136); 119 assert!(core::mem::offset_of!(CpuContext, cs) == 144); 120 assert!(core::mem::offset_of!(CpuContext, ss) == 152); 121 assert!(core::mem::size_of::<CpuContext>() == 160); 122}; 123 124pub const MAX_XSAVE_AREA: usize = 1024; 125 126#[derive(Clone, Copy)] 127#[repr(C, align(64))] 128pub struct FpuState { 129 pub data: [u8; MAX_XSAVE_AREA], 130} 131 132const FXSAVE_FCW_OFFSET: usize = 0; 133const FXSAVE_MXCSR_OFFSET: usize = 24; 134const XSTATE_BV_OFFSET: usize = 512; 135const DEFAULT_FCW: u16 = 0x037F; 136const DEFAULT_MXCSR: u32 = 0x1F80; 137const XSTATE_BV_X87_SSE: u64 = 0b011; 138 139impl FpuState { 140 pub const fn default_init() -> Self { 141 let mut data = [0u8; MAX_XSAVE_AREA]; 142 let fcw = DEFAULT_FCW.to_le_bytes(); 143 data[FXSAVE_FCW_OFFSET] = fcw[0]; 144 data[FXSAVE_FCW_OFFSET + 1] = fcw[1]; 145 let mxcsr = DEFAULT_MXCSR.to_le_bytes(); 146 data[FXSAVE_MXCSR_OFFSET] = mxcsr[0]; 147 data[FXSAVE_MXCSR_OFFSET + 1] = mxcsr[1]; 148 data[FXSAVE_MXCSR_OFFSET + 2] = mxcsr[2]; 149 data[FXSAVE_MXCSR_OFFSET + 3] = mxcsr[3]; 150 let xstate = XSTATE_BV_X87_SSE.to_le_bytes(); 151 data[XSTATE_BV_OFFSET] = xstate[0]; 152 data[XSTATE_BV_OFFSET + 1] = xstate[1]; 153 data[XSTATE_BV_OFFSET + 2] = xstate[2]; 154 data[XSTATE_BV_OFFSET + 3] = xstate[3]; 155 data[XSTATE_BV_OFFSET + 4] = xstate[4]; 156 data[XSTATE_BV_OFFSET + 5] = xstate[5]; 157 data[XSTATE_BV_OFFSET + 6] = xstate[6]; 158 data[XSTATE_BV_OFFSET + 7] = xstate[7]; 159 Self { data } 160 } 161 162 #[allow(dead_code)] 163 pub fn save(&mut self) { 164 match crate::arch::xsave::fpu_mode() { 165 crate::arch::xsave::FpuMode::Xsave { feature_mask, .. } => unsafe { 166 core::arch::asm!( 167 "xsave64 [{}]", 168 in(reg) self.data.as_mut_ptr(), 169 in("eax") feature_mask as u32, 170 in("edx") (feature_mask >> 32) as u32, 171 options(nostack, preserves_flags) 172 ); 173 }, 174 crate::arch::xsave::FpuMode::Fxsave => unsafe { 175 core::arch::asm!( 176 "fxsave64 [{}]", 177 in(reg) self.data.as_mut_ptr(), 178 options(nostack, preserves_flags) 179 ); 180 }, 181 } 182 } 183 184 pub fn restore(&self) { 185 match crate::arch::xsave::fpu_mode() { 186 crate::arch::xsave::FpuMode::Xsave { feature_mask, .. } => unsafe { 187 core::arch::asm!( 188 "xrstor64 [{}]", 189 in(reg) self.data.as_ptr(), 190 in("eax") feature_mask as u32, 191 in("edx") (feature_mask >> 32) as u32, 192 options(nostack, preserves_flags) 193 ); 194 }, 195 crate::arch::xsave::FpuMode::Fxsave => unsafe { 196 core::arch::asm!( 197 "fxrstor64 [{}]", 198 in(reg) self.data.as_ptr(), 199 options(nostack, preserves_flags) 200 ); 201 }, 202 } 203 } 204} 205 206pub const IPC_MSG_REGS: usize = 6; 207 208mod ipc_seal { 209 pub trait Sealed {} 210} 211 212pub trait IpcKind: ipc_seal::Sealed {} 213 214#[derive(Debug, Clone, Copy)] 215pub struct Full; 216impl ipc_seal::Sealed for Full {} 217impl IpcKind for Full {} 218 219#[derive(Debug, Clone, Copy)] 220pub struct Reply; 221impl ipc_seal::Sealed for Reply {} 222impl IpcKind for Reply {} 223 224#[derive(Debug, Clone, Copy)] 225pub struct IpcMessage<K: IpcKind = Full> { 226 pub regs: [u64; IPC_MSG_REGS], 227 _kind: core::marker::PhantomData<K>, 228} 229 230impl IpcMessage<Full> { 231 pub const fn from_regs(regs: [u64; IPC_MSG_REGS]) -> Self { 232 Self { 233 regs, 234 _kind: core::marker::PhantomData, 235 } 236 } 237 238 pub const fn zero() -> Self { 239 Self { 240 regs: [0u64; IPC_MSG_REGS], 241 _kind: core::marker::PhantomData, 242 } 243 } 244} 245 246const REPLY_REGS: usize = 5; 247 248impl IpcMessage<Reply> { 249 pub const fn from_reply_regs(regs: [u64; REPLY_REGS]) -> Self { 250 Self { 251 regs: [regs[0], regs[1], regs[2], regs[3], regs[4], 0], 252 _kind: core::marker::PhantomData, 253 } 254 } 255 256 pub(crate) const fn into_full(self) -> IpcMessage<Full> { 257 IpcMessage { 258 regs: self.regs, 259 _kind: core::marker::PhantomData, 260 } 261 } 262}