#![allow(clippy::unreadable_literal)]
use core::mem::{size_of_val, transmute};
pub use x86_64::structures::idt::ExceptionVector as Vector;
pub use xsave::XSave;
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum ExitType {
Hardware,
Software,
}
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct GenPurposeRegs {
pub rax: u64,
pub rcx: u64,
pub rdx: u64,
pub rbx: u64,
pub rsp: u64,
pub rbp: u64,
pub rsi: u64,
pub rdi: u64,
pub r8: u64,
pub r9: u64,
pub r10: u64,
pub r11: u64,
pub r12: u64,
pub r13: u64,
pub r14: u64,
pub r15: u64,
pub rflags: u64,
pub rip: u64,
pub ursp: u64,
pub urbp: u64,
exitinfo: u32,
reserved: u32,
pub fsbase: u64,
pub gsbase: u64,
}
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct ExInfo {
pub maddr: u64,
pub errcd: u32,
reserved: u32,
}
#[derive(Copy, Clone, Debug)]
#[repr(C)]
pub struct Misc {
pub exinfo: ExInfo,
}
#[derive(Copy, Clone, Debug)]
#[repr(C, align(4096))]
pub struct StateSaveArea<T = [u8; 824]> {
pub xsave: XSave,
pub extra: T,
pub misc: Misc,
pub gpr: GenPurposeRegs,
}
impl<T> StateSaveArea<T> {
const VALID: u32 = 1 << 31;
#[inline]
pub fn exit_type(&self) -> Option<ExitType> {
assert_eq!(size_of_val(self) % 4096, 0);
if self.gpr.exitinfo & Self::VALID == 0 {
return None;
}
match (self.gpr.exitinfo >> 8) & 0b111 {
0b011 => Some(ExitType::Hardware),
0b110 => Some(ExitType::Software),
_ => None,
}
}
#[inline]
pub fn vector(&self) -> Option<Vector> {
match self.gpr.exitinfo & Self::VALID {
0 => None,
_ => Some(unsafe { transmute(self.gpr.exitinfo as u8) }),
}
}
}
#[cfg(test)]
mod test {
use super::*;
use testaso::testaso;
testaso! {
struct GenPurposeRegs: 8, 184 => {
rax: 0,
rcx: 8,
rdx: 16,
rbx: 24,
rsp: 32,
rbp: 40,
rsi: 48,
rdi: 56,
r8: 64,
r9: 72,
r10: 80,
r11: 88,
r12: 96,
r13: 104,
r14: 112,
r15: 120,
rflags: 128,
rip: 136,
ursp: 144,
urbp: 152,
exitinfo: 160,
reserved: 164,
fsbase: 168,
gsbase: 176
}
struct ExInfo: 8, 16 => {
maddr: 0,
errcd: 8,
reserved: 12
}
struct Misc: 8, 16 => {
exinfo: 0
}
struct StateSaveArea<[u8; 824]>: 4096, 4096 => {
xsave: 0,
extra: 3072,
misc: 3896,
gpr: 3912
}
}
}