1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
/*
* Copyright (c) 2021 Bitdefender
* SPDX-License-Identifier: Apache-2.0
*/
//! Offers information about the CPU modes in which an instruction is supported.
//!
//! # Examples
//!
//! ```
//! # use bddisasm::DecodeError;
//! #
//! # fn main() -> Result<(), DecodeError> {
//! use bddisasm::{DecodedInstruction, DecodeMode, Mnemonic};
//!
//! // `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(())
//! # }
// TODO: maybe use something like the `bitflags` crate and have all these as flags?
/// Privilege levels (rings) in which an instruction is supported.
#[allow(clippy::struct_excessive_bools)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct PrivilegeLevel {
/// Instruction is valid in ring 0.
pub ring0: bool,
/// Instruction is valid in ring 1.
pub ring1: bool,
/// Instruction is valid in ring 2.
pub ring2: bool,
/// Instruction is valid in ring 3.
pub ring3: bool,
}
/// Operating modes in which an instruction is supported.
#[allow(clippy::struct_excessive_bools)]
#[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`).
#[allow(clippy::struct_excessive_bools)]
#[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.
#[allow(clippy::struct_excessive_bools)]
#[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 CpuModes {
pub(crate) fn from_raw(raw: ffi::ND_VALID_MODES) -> Self {
let raw = unsafe { raw.__bindgen_anon_1 };
Self {
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,
},
}
}
}