/// do a vmgexit with the ghcb block
///
/// # Safety
/// undefined behaviour if not everything is setup according to the GHCB protocol
do a vmgexit with the ghcb block
do a vmgexit with the ghcb block
unsafe fn vmgexit(
        &mut self,
        exit_code: u64,
        exit_info_1: u64,
        exit_info_2: u64,
    ) -> Result<(), GhcbError> {
        // const GHCB_PROTOCOL_MIN: u16 = 1;
        const GHCB_PROTOCOL_MAX: u16 = 2;
        const GHCB_DEFAULT_USAGE: u32 = 0;
        self.ghcb.save_area.sw_exit_code = exit_code;
        self.set_offset_valid(ptr::addr_of!(self.ghcb.save_area.sw_exit_code) as _);
        self.ghcb.save_area.sw_exit_info1 = exit_info_1;
        self.set_offset_valid(ptr::addr_of!(self.ghcb.save_area.sw_exit_info1) as _);
        self.ghcb.save_area.sw_exit_info2 = exit_info_2;
        self.set_offset_valid(ptr::addr_of!(self.ghcb.save_area.sw_exit_info2) as _);
        self.ghcb.ghcb_usage = GHCB_DEFAULT_USAGE;
        // FIXME: do protocol negotiation
        self.ghcb.protocol_version = GHCB_PROTOCOL_MAX;
        // prevent earlier writes from being moved beyond this point
        core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::Release);
        let gpa = (VirtAddr::from_ptr(self.ghcb) - SHIM_VIRT_OFFSET).as_u64();
        let mut msr = GhcbMsr::MSR;
        msr.write(gpa);
        asm!("rep vmmcall", options(nostack));
        // prevent later reads from being moved before this point
        core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::Acquire);
        if (self.ghcb.save_area.sw_exit_info1 & 0xffff_ffff) == 1 {
            const SVM_EVTINJ_VALID: u64 = 1 << 31;
            const SVM_EVTINJ_TYPE_SHIFT: u64 = 8;
            const SVM_EVTINJ_TYPE_MASK: u64 = 7 << SVM_EVTINJ_TYPE_SHIFT;
            const SVM_EVTINJ_TYPE_EXEPT: u64 = 3 << SVM_EVTINJ_TYPE_SHIFT;
            const SVM_EVTINJ_VEC_MASK: u64 = 0xff;
            const UD: u64 = 6;
            const GP: u64 = 13;
            // VmgExitErrorCheck, see
            // https://github.com/AMDESE/ovmf/blob/sev-snp-v6/OvmfPkg/Library/VmgExitLib/VmgExitLib.c
            // or linux kernel arch/x86/kernel/sev-shared.c
            let exit_info2 = self.ghcb.save_area.sw_exit_info2;
            let vector = exit_info2 & SVM_EVTINJ_VEC_MASK;
            if (exit_info2 & SVM_EVTINJ_VALID != 0)
                && (exit_info2 & SVM_EVTINJ_TYPE_MASK == SVM_EVTINJ_TYPE_EXEPT)
                && (vector == GP || vector == UD)
            {
                return Err(GhcbError::Exception);
            }
            Err(GhcbError::VmmError)
        } else {
            Ok(())
        }
    }
unsafe fn vmgexit ( & mut self , exit_code : u64 , exit_info_1 : u64 , exit_info_2 : u64 , ) -> Result < ( ) , GhcbError > { // const GHCB_PROTOCOL_MIN: u16 = 1; const GHCB_PROTOCOL_MAX : u16 = 2 ; const GHCB_DEFAULT_USAGE : u32 = 0 ; self . ghcb . save_area . sw_exit_code = exit_code ; self . set_offset_valid ( ptr :: addr_of ! ( self ghcb save_area sw_exit_code ) as _ ) ; self . ghcb . save_area . sw_exit_info1 = exit_info_1 ; self . set_offset_valid ( ptr :: addr_of ! ( self ghcb save_area sw_exit_info1 ) as _ ) ; self . ghcb . save_area . sw_exit_info2 = exit_info_2 ; self . set_offset_valid ( ptr :: addr_of ! ( self ghcb save_area sw_exit_info2 ) as _ ) ; self . ghcb . ghcb_usage = GHCB_DEFAULT_USAGE ; // FIXME: do protocol negotiation self . ghcb . protocol_version = GHCB_PROTOCOL_MAX ; // prevent earlier writes from being moved beyond this point core :: sync :: atomic :: compiler_fence ( core :: sync :: atomic :: Ordering :: Release ) ; let gpa = ( VirtAddr :: from_ptr ( self . ghcb ) - SHIM_VIRT_OFFSET ) . as_u64 ( ) ; let mut msr = GhcbMsr :: MSR ; msr . write ( gpa ) ; asm ! ( " " options ( nostack ) ) ; // prevent later reads from being moved before this point core :: sync :: atomic :: compiler_fence ( core :: sync :: atomic :: Ordering :: Acquire ) ; if ( self . ghcb . save_area . sw_exit_info1 & 0xffff_ffff ) == 1 { const SVM_EVTINJ_VALID : u64 = 1 << 31 ; const SVM_EVTINJ_TYPE_SHIFT : u64 = 8 ; const SVM_EVTINJ_TYPE_MASK : u64 = 7 << SVM_EVTINJ_TYPE_SHIFT ; const SVM_EVTINJ_TYPE_EXEPT : u64 = 3 << SVM_EVTINJ_TYPE_SHIFT ; const SVM_EVTINJ_VEC_MASK : u64 = 0xff ; const UD : u64 = 6 ; const GP : u64 = 13 ; // VmgExitErrorCheck, see // https://github.com/AMDESE/ovmf/blob/sev-snp-v6/OvmfPkg/Library/VmgExitLib/VmgExitLib.c // or linux kernel arch/x86/kernel/sev-shared.c let exit_info2 = self . ghcb . save_area . sw_exit_info2 ; let vector = exit_info2 & SVM_EVTINJ_VEC_MASK ; if ( exit_info2 & SVM_EVTINJ_VALID != 0 ) && ( exit_info2 & SVM_EVTINJ_TYPE_MASK == SVM_EVTINJ_TYPE_EXEPT ) && ( vector == GP || vector == UD ) { return Err ( GhcbError :: Exception ) ; } Err ( GhcbError :: VmmError ) } else { Ok ( ( ) ) } }
do a vmgexit with the ghcb block
do a vmgexit with the ghcb block
&mut self
exit_code
u64
exit_info_1
u64
exit_info_2
u64
safety
undefined behaviour if not everything is setup according to the GHCB protocol
undefined behaviour if not everything is setup according to the GHCB protocol