/* * Copyright (c) 2021 Bitdefender * SPDX-License-Identifier: Apache-2.0 */ //! Offers information about the CPU modes in which an instruction is supported. //! //! # Examples //! //! ``` //! # use std::error::Error; //! # //! # fn main() -> Result<(), Box> { //! use bddisasm::decoded_instruction::{DecodedInstruction, DecodeMode, Mnemonic, OperandSize}; //! //! // `VMXON qword ptr [rax]` //! let ins = DecodedInstruction::decode(&[0xf3, 0x0f, 0xc7, 0x30], DecodeMode::Bits64)?; //! let modes = ins.valid_cpu_modes(); //! //! // Check if the instruction is available from user mode //! if modes.privilege_level.ring3 { //! println!("Available in user mode"); //! } else { //! println!("Not available in user mode"); //! } //! //! # Ok(()) //! # } extern crate bddisasm_sys as ffi; // TODO: maybe use something like the `bitflags` crate and have all these as flags? /// Privilege levels (rings) in which an instruction is supported. #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct PrivilegeLevel { pub ring0: bool, pub ring1: bool, pub ring2: bool, pub ring3: bool, } /// Operating modes in which an instruction is supported. #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct OperatingMode { /// The instruction is valid in real mode. pub real: bool, /// The instruction is valid in Virtual 8086 mode. pub v8086: bool, /// The instruction is valid in protected mode (32 bit). pub protected: bool, /// The instruction is valid in compatibility mode (32 bit in 64 bit). pub compat: bool, /// The instruction is valid in long mode. pub long: bool, } /// Special modes - these may be active inside other modes (example: `TSX` in `Long mode`). #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct SpecialModes { /// The instruction is valid in System Management Mode. pub smm: bool, /// The instruction is valid outside System Management Mode. pub smm_off: bool, /// The instruction is valid in SGX mode. pub sgx: bool, /// The instruction is valid outside SGX mode. pub sgx_off: bool, /// The instruction is valid in transactional regions. pub tsx: bool, /// The instruction is valid in transactional regions. pub tsx_off: bool, } /// VMX mode - they engulf all the other modes. #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct VmxMode { /// The instruction is valid in VMX root mode. pub root: bool, /// The instruction is valid in VMX non root mode. pub non_root: bool, /// The instruction is valid in VMX root SEAM. pub root_seam: bool, /// The instruction is valid in VMX non-root SEAM. pub non_root_seam: bool, /// The instruction is valid outside VMX operation. pub off: bool, } /// Indicates in which modes the instruction is valid in #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] pub struct CpuModes { pub privilege_level: PrivilegeLevel, pub operating_mode: OperatingMode, pub special_modes: SpecialModes, pub vmx: VmxMode, } #[doc(hidden)] impl From for CpuModes { fn from(raw: ffi::ND_VALID_MODES) -> CpuModes { let raw = unsafe { raw.__bindgen_anon_1 }; CpuModes { privilege_level: PrivilegeLevel { ring0: raw.Ring0() != 0, ring1: raw.Ring1() != 0, ring2: raw.Ring2() != 0, ring3: raw.Ring3() != 0, }, operating_mode: OperatingMode { real: raw.Real() != 0, v8086: raw.V8086() != 0, protected: raw.Protected() != 0, compat: raw.Compat() != 0, long: raw.Long() != 0, }, special_modes: SpecialModes { smm: raw.Smm() != 0, smm_off: raw.SmmOff() != 0, sgx: raw.Sgx() != 0, sgx_off: raw.SgxOff() != 0, tsx: raw.Tsx() != 0, tsx_off: raw.TsxOff() != 0, }, vmx: VmxMode { root: raw.VmxRoot() != 0, non_root: raw.VmxNonRoot() != 0, root_seam: raw.VmxRootSeam() != 0, non_root_seam: raw.VmxNonRootSeam() != 0, off: raw.VmxOff() != 0, }, } } }