use core::mem;
use hyperlight_common::vmem::{BasicMapping, MappingKind, PAGE_SIZE};
use super::layout::PROC_CONTROL_GVA;
#[derive(Copy, Clone)]
#[repr(C, align(8))]
pub(super) struct GdtEntry {
limit_low: u16,
base_low: u16,
base_middle: u8,
access: u8,
flags_limit: u8,
base_high: u8,
}
const _: () = assert!(mem::size_of::<GdtEntry>() == 0x8);
impl GdtEntry {
pub const fn new(base: u32, limit: u32, access: u8, flags: u8) -> Self {
Self {
base_low: (base & 0xffff) as u16,
base_middle: ((base >> 16) & 0xff) as u8,
base_high: ((base >> 24) & 0xff) as u8,
limit_low: (limit & 0xffff) as u16,
flags_limit: (((limit >> 16) & 0x0f) as u8) | ((flags & 0x0f) << 4),
access,
}
}
pub const fn tss(base: u64, limit: u32) -> [Self; 2] {
[
Self {
limit_low: (limit & 0xffff) as u16,
base_low: (base & 0xffff) as u16,
base_middle: ((base >> 16) & 0xff) as u8,
access: 0x89,
flags_limit: ((limit >> 16) & 0x0f) as u8,
base_high: ((base >> 24) & 0xff) as u8,
},
Self {
limit_low: ((base >> 32) & 0xffff) as u16,
base_low: ((base >> 48) & 0xffff) as u16,
base_middle: 0,
access: 0,
flags_limit: 0,
base_high: 0,
},
]
}
}
#[repr(C, packed)]
pub(super) struct GdtPointer {
pub(super) limit: u16,
pub(super) base: u64,
}
#[allow(clippy::upper_case_acronyms)]
#[repr(C, packed)]
pub(super) struct TSS {
_rsvd0: [u8; 4],
_rsp0: u64,
_rsp1: u64,
_rsp2: u64,
_rsvd1: [u8; 8],
pub(super) ist1: u64,
_ist2: u64,
_ist3: u64,
_ist4: u64,
_ist5: u64,
_ist6: u64,
_ist7: u64,
_rsvd2: [u8; 8],
}
const _: () = assert!(mem::size_of::<TSS>() == 0x64);
const _: () = assert!(mem::offset_of!(TSS, ist1) == 0x24);
#[repr(C, align(16))]
pub(crate) struct IdtEntry {
offset_low: u16, selector: u16, interrupt_stack_table_offset: u8, type_attr: u8, offset_mid: u16, offset_high: u32, _rsvd: u32, }
const _: () = assert!(mem::size_of::<IdtEntry>() == 0x10);
impl IdtEntry {
pub(super) fn new(handler: u64) -> Self {
Self {
offset_low: (handler & 0xFFFF) as u16,
selector: 0x08, interrupt_stack_table_offset: 1,
type_attr: 0x8E,
offset_mid: ((handler >> 16) & 0xFFFF) as u16,
offset_high: ((handler >> 32) & 0xFFFFFFFF) as u32,
_rsvd: 0,
}
}
}
#[repr(C, packed)]
pub(super) struct IdtPointer {
pub limit: u16,
pub base: u64,
}
const _: () = assert!(mem::size_of::<IdtPointer>() == 10);
#[allow(clippy::upper_case_acronyms)]
pub(super) type GDT = [GdtEntry; 5];
#[allow(clippy::upper_case_acronyms)]
#[repr(align(0x1000))]
pub(super) struct IDT {
pub(super) entries: [IdtEntry; 256],
}
const _: () = assert!(mem::size_of::<IDT>() == 0x1000);
const PADDING_BEFORE_TSS: usize = 64 - mem::size_of::<GDT>();
#[repr(C, align(0x1000))]
pub(super) struct ProcCtrl {
pub(super) gdt: GDT,
_pad: mem::MaybeUninit<[u8; PADDING_BEFORE_TSS]>,
pub(super) tss: TSS,
pub(super) idt: IDT,
}
const _: () = assert!(mem::size_of::<ProcCtrl>() == 0x2000);
const _: () = assert!(mem::size_of::<ProcCtrl>() <= PAGE_SIZE * 2);
const _: () = assert!(mem::offset_of!(ProcCtrl, gdt) == 0);
const _: () = assert!(mem::offset_of!(ProcCtrl, tss) == 64);
const _: () = assert!(mem::offset_of!(ProcCtrl, idt) == 0x1000);
impl ProcCtrl {
pub(super) unsafe fn init() -> *mut Self {
unsafe {
let ptr = PROC_CONTROL_GVA as *mut u8;
crate::paging::map_region(
hyperlight_guest::prim_alloc::alloc_phys_pages(2),
ptr,
PAGE_SIZE as u64 * 2,
MappingKind::Basic(BasicMapping {
readable: true,
writable: true,
executable: false,
}),
);
crate::paging::barrier::first_valid_same_ctx();
let ptr = ptr as *mut Self;
(&raw mut (*ptr).gdt).write_bytes(0u8, 1);
(&raw mut (*ptr).tss).write_bytes(0u8, 1);
(&raw mut (*ptr).idt).write_bytes(0u8, 1);
ptr
}
}
}
#[repr(C)]
pub struct ExceptionInfo {
pub error_code: u64,
pub rip: u64,
pub cs: u64,
pub rflags: u64,
pub rsp: u64,
pub ss: u64,
}
const _: () = assert!(size_of::<ExceptionInfo>() == 8 * 6);
const _: () = assert!(mem::offset_of!(ExceptionInfo, rip) == 8);
const _: () = assert!(mem::offset_of!(ExceptionInfo, rsp) == 32);