Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ license = "GPL-3.0-or-later OR Apache-2.0 OR MulanPSL-2.0" # MulanPubL2 is not i
[dependencies]
log = "0.4.19"
cfg-if = "1.0"
bilge = "0.2.0"
bitflags = "2.2"
bit_field = "0.10"
paste = "1.0.15"
Expand Down
6 changes: 6 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ cfg_if::cfg_if! {
}
}

cfg_if::cfg_if! {
if #[cfg(feature = "svm")]{
pub mod svm;
}
}

pub use ept::GuestPageWalkInfo;
pub use regs::GeneralRegisters;
pub use vender::has_hardware_support;
290 changes: 290 additions & 0 deletions src/svm/definitions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
use core::fmt::{Debug, Formatter, Result};

pub struct SvmInstructionError(i32);

impl SvmInstructionError {
pub fn as_str(&self) -> &str {
match self.0 {
0x0 | 0x1 | 0x2 | 0x3 | 0x4 | 0x5 | 0x6 | 0x7 | 0x8 | 0x9 | 0xa | 0xb | 0xc | 0xd | 0xe | 0xf => "Cr Read",
0x10 | 0x11 | 0x12 | 0x13 | 0x14 | 0x15 | 0x16 | 0x17 | 0x18 | 0x19 | 0x1a | 0x1b | 0x1c | 0x1d | 0x1e | 0x1f => "Cr Wirte",
0x20 | 0x21 | 0x22 | 0x23 | 0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2a | 0x2b | 0x2c | 0x2d | 0x2e | 0x2f => "Dr Read",
0x30 | 0x31 | 0x32 | 0x33 | 0x34 | 0x35 | 0x36 | 0x37 | 0x38 | 0x39 | 0x3a | 0x3b | 0x3c | 0x3d | 0x3e | 0x3f => "Dr Wirte",
0x40 | 0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x46 | 0x47 | 0x48 | 0x49 | 0x4a | 0x4b | 0x4c | 0x4d | 0x4e | 0x4f => "Exception",
0x50 | 0x51 | 0x52 | 0x53 | 0x54 | 0x55 | 0x56 | 0x57 | 0x58 | 0x59 | 0x5a | 0x5b | 0x5c | 0x5d | 0x5e | 0x5f => "Exception",
0x60 => "Physical INTR",
0x61 => "Physical NMI",
0x62 => "Physical SMI (the EXITINFO1 field provides more information)",
0x63 => "Physical INIT",
0x64 => "Virtual INTR",
0x65 => "Write of CR0 changed bits other than CR0. TS or CR0.MP.",
0x66 => "Read of IDTR",
0x67 => "Read of GDTR",
0x68 => "Read of LDTR",
0x69 => "Read of TR",
0x6a => "Write of IDTR",
0x6b => "Write of GDTR",
0x6c => "Write of LDTR",
0x6d => "Write of TR",
0x6e => "RDTSC instruction",
0x6f => "RDTSCP instruction",
0x70 => "Pushf instruction",
0x71 => "Popf instruction",
0x72 => "CPUID instruction",
0x73 => "RSM instruction",
0x74 => "IRET instruction",
0x75 => "Software interrupt (INTn instruction)",
0x76 => "INVD instruction",
0x77 => "PAUSE instruction",
0x78 => "HLT instruction",
0x79 => "INVLPG instruction",
0x7a => "INVLPGA instruction",
0x7b => "IN or OOUT accessing protected port (the EXITINF1 field provides more information)",
0x7c => "RDMSR or WRMSR access to protexted MSR",
0x7d => "Task switch",
0x7e => "FP legacy handling enabled, and processor is frozen in x87/mmx instruction waiting for an interrupt",
0x7f => "Shutdown",
0x80 => "VMRUN instruction",
0x81 => "VMMCALL instruction",
0x82 => "VMLOAD instruction",
0x83 => "VMSAVE instruction",
0x84 => "STGI instruction",
0x85 => "CLGI instruction",
0x86 => "SKINIT instruction",
0x87 => "RDTSCP instruction",
0x88 => "ICEBP instruction",
0x89 => "WBINVD or WBNINVD instruction",
0x8a => "MONITOR or MONITORX instruction",
0x8b => "MWAIT or MWAITX instruction",
0x8c => "MWAIT or MWAITX instruction, if monitor handware is armed",
0x8d => "XSETBV instruction",
0x8e => "RDPRU instruction",
0x8f => "EFER write trap (occurs after guest instruction is finishes)",
0x90 | 0x91 | 0x92 | 0x93 | 0x94 | 0x95 | 0x96 | 0x97 | 0x98 | 0x99 | 0x9a | 0x9b | 0x9c | 0x9d | 0x9e | 0x9f => "Write of CR0-15, respectively (occurs after guest instruction is finishes)",
0xa0 => "INVLPGB instruction",
0xa1 => "Illegal INVLPGB instruction",
0xa2 => "INVOCID instruction",
0xa3 => "MCOMMIT instruction",
0xa4 => "TLBSYNC instruction",
0xa5 => "Bus lock while Bus Lock Threshold Counter value is 0.",
0xa6 => "HLT instructio if a virtual interrupt is not pending",
0x400 => "Nested paging: host-level page fault occurred (EXITINFO1 contains fault error code; EXITINFO2 contains the guest physical address causing the fault).",
0x401 => "AVIC—Virtual IPI delivery not completed. See \"AVIC IPI Delivery Not Completed\" on page 580 for EXITINFO1–2 definitions.",
0x402 => "AVIC—Attempted access by guest to vAPIC register not handled by AVIC hardware. See \"AVIC Access to Unaccelerated vAPIC register\" on page 581 for EXITINFO1–2 definitions.",
0x403 => "VMGEXIT instruction",
0xF000_000 => "Reserved for Host",
-1 => "Invalid guest state in VMCB.",
-2 => "BUSY bit was set in the VMSA",
-3 => "The sibling thread is not in an idle state",
-4 => "Invalid PMC state",
_ => "[INVALID]",
}
}
}

impl From<i32> for SvmInstructionError {
fn from(value: i32) -> Self {
Self(value)
}
}

impl Debug for SvmInstructionError {
fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "SvmInstructionError({}, {:?})", self.0, self.as_str())
}
}

numeric_enum_macro::numeric_enum! {
#[repr(i32)]
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[allow(non_camel_case_types)]
pub enum SvmExitReason {
Cr0Read = 0x0,
Cr1Read = 0x1,
Cr2Read = 0x2,
Cr3Read = 0x3,
Cr4Read = 0x4,
Cr5Read = 0x5,
Cr6Read = 0x6,
Cr7Read = 0x7,
Cr8Read = 0x8,
Cr9Read = 0x9,
Cr10Read = 0xa,
Cr11Read = 0xb,
Cr12Read = 0xc,
Cr13Read = 0xd,
Cr14Read = 0xe,
Cr15Read = 0xf,
Cr0Write = 0x10,
Cr1Write = 0x11,
Cr2Write = 0x12,
Cr3Write = 0x13,
Cr4Write = 0x14,
Cr5Write = 0x15,
Cr6Write = 0x16,
Cr7Write = 0x17,
Cr8Write = 0x18,
Cr9Write = 0x19,
Cr10Write = 0x1a,
Cr11Write = 0x1b,
Cr12Write = 0x1c,
Cr13Write = 0x1d,
Cr14Write = 0x1e,
Cr15Write = 0x1f,
Dr0Read = 0x20,
Dr1Read = 0x21,
Dr2Read = 0x22,
Dr3Read = 0x23,
Dr4Read = 0x24,
Dr5Read = 0x25,
Dr6Read = 0x26,
Dr7Read = 0x27,
Dr8Read = 0x28,
Dr9Read = 0x29,
Dr10Read = 0x2a,
Dr11Read = 0x2b,
Dr12Read = 0x2c,
Dr13Read = 0x2d,
Dr14Read = 0x2e,
Dr15Read = 0x2f,
Dr0Write = 0x30,
Dr1Write = 0x31,
Dr2Write = 0x32,
Dr3Write = 0x33,
Dr4Write = 0x34,
Dr5Write = 0x35,
Dr6Write = 0x36,
Dr7Write = 0x37,
Dr8Write = 0x38,
Dr9Write = 0x39,
Dr10Write = 0x3a,
Dr11Write = 0x3b,
Dr12Write = 0x3c,
Dr13Write = 0x3d,
Dr14Write = 0x3e,
Dr15Write = 0x3f,
Excp_0 = 0x40,
Excp_1 = 0x41,
Excp_2 = 0x42,
Excp_3 = 0x43,
Excp_4 = 0x44,
Excp_5 = 0x45,
Excp_6 = 0x46,
Excp_7 = 0x47,
Excp_8 = 0x48,
Excp_9 = 0x49,
Excp_10 = 0x4a,
Excp_11 = 0x4b,
Excp_12 = 0x4c,
Excp_13 = 0x4d,
Excp_14 = 0x4e,
Excp_15 = 0x4f,
Excp_16 = 0x50,
Excp_17 = 0x51,
Excp_18 = 0x52,
Excp_19 = 0x53,
Excp_20 = 0x54,
Excp_21 = 0x55,
Excp_22 = 0x56,
Excp_23 = 0x57,
Excp_24 = 0x58,
Excp_25 = 0x59,
Excp_26 = 0x5a,
Excp_27 = 0x5b,
Excp_28 = 0x5c,
Excp_29 = 0x5d,
Excp_30 = 0x5e,
Excp_31 = 0x5f,

Intr = 0x60,
Nmi = 0x61,
Smi = 0x62,
Init = 0x63,
Vintr = 0x64,
Cr0SelWrite = 0x65,
IdtrRead = 0x66,
GdtrRead = 0x67,
LdtrRead = 0x68,
TrRead = 0x69,
IdtrWrite = 0x6a,
GdtrWrite = 0x6b,
LdtrWrite = 0x6c,
TrWrite = 0x6d,
Rdtsc = 0x6e,
Rdpmc = 0x6f,
Pushf = 0x70,
Popf = 0x71,
Cpuid = 0x72,
Rsm = 0x73,
Iret = 0x74,
Swint = 0x75,
Invd = 0x76,
Pause = 0x77,
Hlt = 0x78,
Invlpg = 0x79,
Invlpga = 0x7a,
Ioio = 0x7b,
Msr = 0x7c,
TaskSwitch = 0x7d,
FreeFreeze = 0x7e,
Shutdown = 0x7f,
Vmrun = 0x80,
Vmmcall = 0x81,
Vmload = 0x82,
Vmsave = 0x83,
Stgi = 0x84,
Clgi = 0x85,
Skinit = 0x86,
Rdtscp = 0x87,
Icebp = 0x88,
Wbinvd = 0x89,
Monitor = 0x8a,
Mwait = 0x8b,
MwaitConditioal = 0x8c,
Xsetbv = 0x8d,
Rdpru = 0x8e,
EferWriteTrap = 0x8f,

Cr0WriteTrap = 0x90,
Cr1WriteTrap = 0x91,
Cr2WriteTrap = 0x92,
Cr3WriteTrap = 0x93,
Cr4WriteTrap = 0x94,
Cr5WriteTrap = 0x95,
Cr6WriteTrap = 0x96,
Cr7WriteTrap = 0x97,
Cr8WriteTrap = 0x98,
Cr9WriteTrap = 0x99,
Cr10WriteTrap = 0x9a,
Cr11WriteTrap = 0x9b,
Cr12WriteTrap = 0x9c,
Cr13WriteTrap = 0x9d,
Cr14WriteTrap = 0x9e,
Cr15WriteTrap = 0x9f,

Invlpgb = 0xa0,
InvlpgaIllegal = 0xa1,
Invpcid = 0xa2,
Mcommit = 0xa3,
Tlbsync = 0xa4,
Buslock = 0xa5,
IdleHlt = 0xa6,

Npf = 0x400,
AvicIncompleteIpi = 0x401,
AvicNoaccel = 0x402,
Vmgexit = 0x403,

Invalid = -1,
Busy = -2,
IdleRequired = -3,
InvalidPmc = -4,
}
}

#[derive(Debug)]
pub struct SvmExitInfo {
pub entry_failure: bool,
pub exit_reason: SvmExitReason,
pub exit_instruction_length: u32,
pub guest_rip: usize,
}
1 change: 1 addition & 0 deletions src/svm/instructions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

9 changes: 9 additions & 0 deletions src/svm/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
mod definitions;
mod instructions;
mod percpu;
mod vcpu;
mod vmcb;

pub fn has_hardware_support() -> bool {
raw_cpuid::CpuId::new().get_svm_info().is_some()
}
1 change: 1 addition & 0 deletions src/svm/percpu.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

1 change: 1 addition & 0 deletions src/svm/vcpu.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Loading