1pub mod consts;
2pub mod ffi;
3
4use self::consts::*;
5use self::ffi::*;
6use crate::x86_64::vmcs::*;
7use crate::{match_MemPerm, match_error_code, Error, MemPerm};
8use core::fmt;
9use libc::*;
10
11pub fn create_vm() -> Result<(), Error> {
13 match_error_code(unsafe { hv_vm_create(HV_VM_DEFAULT) })
14}
15
16pub fn map_mem(mem: &[u8], gpa: u64, mem_perm: MemPerm) -> Result<(), Error> {
19 match_error_code(unsafe {
20 hv_vm_map(
21 mem.as_ptr() as *const c_void,
22 gpa as hv_gpaddr_t,
23 mem.len() as size_t,
24 match_MemPerm(mem_perm),
25 )
26 })
27}
28
29pub fn protect_mem(gpa: u64, size: usize, mem_perm: MemPerm) -> Result<(), Error> {
32 match_error_code(unsafe {
33 hv_vm_protect(gpa as hv_gpaddr_t, size as size_t, match_MemPerm(mem_perm))
34 })
35}
36
37pub fn unmap_mem(gpa: u64, size: usize) -> Result<(), Error> {
39 match_error_code(unsafe { hv_vm_unmap(gpa as hv_gpaddr_t, size as size_t) })
40}
41
42pub fn sync_tsc(tsc: u64) -> Result<(), Error> {
46 match_error_code(unsafe { hv_vm_sync_tsc(tsc) })
47}
48
49pub fn interrupt_vcpus(vcpu_ids: &[u32]) -> Result<(), Error> {
53 match_error_code(unsafe { hv_vcpu_interrupt(vcpu_ids.as_ptr(), vcpu_ids.len() as c_uint) })
54}
55
56pub struct VirtualCpu {
58 id: u32,
60 vcpu_handle: hv_vcpuid_t,
62}
63
64#[derive(Clone)]
66#[repr(C)]
67pub enum Register {
68 RIP,
69 RFLAGS,
70 RAX,
71 RCX,
72 RDX,
73 RBX,
74 RSI,
75 RDI,
76 RSP,
77 RBP,
78 R8,
79 R9,
80 R10,
81 R11,
82 R12,
83 R13,
84 R14,
85 R15,
86 CS,
87 SS,
88 DS,
89 ES,
90 FS,
91 GS,
92 IDT_BASE,
93 IDT_LIMIT,
94 GDT_BASE,
95 GDT_LIMIT,
96 LDTR,
97 LDT_BASE,
98 LDT_LIMIT,
99 LDT_AR,
100 TR,
101 TSS_BASE,
102 TSS_LIMIT,
103 TSS_AR,
104 CR0,
105 CR1,
106 CR2,
107 CR3,
108 CR4,
109 DR0,
110 DR1,
111 DR2,
112 DR3,
113 DR4,
114 DR5,
115 DR6,
116 DR7,
117 TPR,
118 XCR0,
119 REGISTERS_MAX,
120}
121
122impl VirtualCpu {
123 pub fn new(id: u32) -> Result<VirtualCpu, Error> {
127 let mut vcpu_handle: hv_vcpuid_t = 0;
128
129 match_error_code(unsafe { hv_vcpu_create(&mut vcpu_handle, HV_VCPU_DEFAULT) })?;
130
131 Ok(VirtualCpu { id, vcpu_handle })
132 }
133
134 pub fn get_id(&self) -> u32 {
135 self.id
136 }
137
138 pub fn get_handle(&self) -> hv_vcpuid_t {
139 self.vcpu_handle
140 }
141
142 pub fn interrupt(&self) -> Result<(), Error> {
144 match_error_code(unsafe { hv_vcpu_interrupt(&(self.vcpu_handle), 1 as c_uint) })
145 }
146
147 pub fn exec_time(&self) -> Result<u64, Error> {
149 let mut exec_time: u64 = 0;
150
151 let _error =
152 match_error_code(unsafe { hv_vcpu_get_exec_time(self.vcpu_handle, &mut exec_time) })?;
153
154 Ok(exec_time)
155 }
156
157 pub fn flush(&self) -> Result<(), Error> {
159 match_error_code(unsafe { hv_vcpu_flush(self.vcpu_handle) })
160 }
161
162 pub fn invalidate_tlb(&self) -> Result<(), Error> {
164 match_error_code(unsafe { hv_vcpu_invalidate_tlb(self.vcpu_handle) })
165 }
166
167 pub fn enable_native_msr(&self, msr: u32, enable: bool) -> Result<(), Error> {
169 match_error_code(unsafe { hv_vcpu_enable_native_msr(self.vcpu_handle, msr, enable) })
170 }
171
172 pub fn read_msr(&self, msr: u32) -> Result<u64, Error> {
174 let mut value: u64 = 0;
175
176 let _error =
177 match_error_code(unsafe { hv_vcpu_read_msr(self.vcpu_handle, msr, &mut value) })?;
178
179 Ok(value)
180 }
181
182 pub fn write_msr(&self, msr: u32, value: u64) -> Result<(), Error> {
184 match_error_code(unsafe { hv_vcpu_write_msr(self.vcpu_handle, msr, &(value)) })
185 }
186
187 pub fn read_register(&self, reg: &Register) -> Result<u64, Error> {
190 let mut value: u64 = 0;
191
192 match_error_code(unsafe {
193 hv_vcpu_read_register(self.vcpu_handle, (*reg).clone(), &mut value)
194 })?;
195
196 Ok(value)
197 }
198
199 pub fn write_register(&self, reg: &Register, value: u64) -> Result<(), Error> {
201 match_error_code(unsafe { hv_vcpu_write_register(self.vcpu_handle, (*reg).clone(), value) })
202 }
203
204 pub fn read_vmcs(&self, field: u32) -> Result<u64, Error> {
206 let mut value: u64 = 0;
207
208 match_error_code(unsafe { hv_vmx_vcpu_read_vmcs(self.vcpu_handle, field, &mut value) })?;
209
210 Ok(value)
211 }
212
213 pub fn write_vmcs(&self, field: u32, value: u64) -> Result<(), Error> {
215 match_error_code(unsafe { hv_vmx_vcpu_write_vmcs(self.vcpu_handle, field, value) })
216 }
217
218 pub fn set_apic_addr(&self, gpa: u64) -> Result<(), Error> {
221 match_error_code(unsafe { hv_vmx_vcpu_set_apic_address(self.vcpu_handle, gpa) })
222 }
223
224 pub fn read_fpstate(&self, buffer: &mut [u8]) -> Result<(), Error> {
226 match_error_code(unsafe {
227 hv_vcpu_read_fpstate(
228 self.vcpu_handle,
229 buffer.as_mut_ptr() as *mut c_void,
230 buffer.len() as size_t,
231 )
232 })
233 }
234
235 pub fn write_fpstate(&self, buffer: &[u8]) -> Result<(), Error> {
237 match_error_code(unsafe {
238 hv_vcpu_write_fpstate(
239 self.vcpu_handle,
240 buffer.as_ptr() as *const c_void,
241 buffer.len() as size_t,
242 )
243 })
244 }
245}
246
247impl fmt::Debug for VirtualCpu {
248 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
249 write!(f, "\nDump state of CPU {}", self.id)?;
250 write!(f, "VMCS:")?;
251 write!(f, "-----")?;
252 write!(
253 f,
254 "CR0: mask {:016x} shadow {:016x}",
255 self.read_vmcs(VMCS_CTRL_CR0_MASK).unwrap(),
256 self.read_vmcs(VMCS_CTRL_CR0_SHADOW).unwrap()
257 )?;
258 write!(
259 f,
260 "CR4: mask {:016x} shadow {:016x}",
261 self.read_vmcs(VMCS_CTRL_CR4_MASK).unwrap(),
262 self.read_vmcs(VMCS_CTRL_CR4_SHADOW).unwrap()
263 )?;
264 write!(
265 f,
266 "Pinbased: {:016x}\n1st: {:016x}\n2nd: {:016x}",
267 self.read_vmcs(VMCS_CTRL_PIN_BASED).unwrap(),
268 self.read_vmcs(VMCS_CTRL_CPU_BASED).unwrap(),
269 self.read_vmcs(VMCS_CTRL_CPU_BASED2).unwrap()
270 )?;
271 write!(
272 f,
273 "Entry: {:016x}\nExit: {:016x}",
274 self.read_vmcs(VMCS_CTRL_VMENTRY_CONTROLS).unwrap(),
275 self.read_vmcs(VMCS_CTRL_VMEXIT_CONTROLS).unwrap()
276 )?;
277
278 write!(f, "\nRegisters:")?;
279 write!(f, "----------")?;
280
281 let rip = self.read_register(&Register::RIP).unwrap();
282 let rflags = self.read_register(&Register::RFLAGS).unwrap();
283 let rsp = self.read_register(&Register::RSP).unwrap();
284 let rbp = self.read_register(&Register::RBP).unwrap();
285 let rax = self.read_register(&Register::RAX).unwrap();
286 let rbx = self.read_register(&Register::RBX).unwrap();
287 let rcx = self.read_register(&Register::RCX).unwrap();
288 let rdx = self.read_register(&Register::RDX).unwrap();
289 let rsi = self.read_register(&Register::RSI).unwrap();
290 let rdi = self.read_register(&Register::RDI).unwrap();
291 let r8 = self.read_register(&Register::R8).unwrap();
292 let r9 = self.read_register(&Register::R9).unwrap();
293 let r10 = self.read_register(&Register::R10).unwrap();
294 let r11 = self.read_register(&Register::R11).unwrap();
295 let r12 = self.read_register(&Register::R12).unwrap();
296 let r13 = self.read_register(&Register::R13).unwrap();
297 let r14 = self.read_register(&Register::R14).unwrap();
298 let r15 = self.read_register(&Register::R15).unwrap();
299
300 write!(
301 f,
302 "rip: {rip:016x} rsp: {rsp:016x} flags: {rflags:016x}\n\
303 rax: {rax:016x} rbx: {rbx:016x} rcx: {rcx:016x}\n\
304 rdx: {rdx:016x} rsi: {rsi:016x} rdi: {rdi:016x}\n\
305 rbp: {rbp:016x} r8: {r8:016x} r9: {r9:016x}\n\
306 r10: {r10:016x} r11: {r11:016x} r12: {r12:016x}\n\
307 r13: {r13:016x} r14: {r14:016x} r15: {r15:016x}\n"
308 )?;
309
310 let cr0 = self.read_register(&Register::CR0).unwrap();
311 let cr2 = self.read_register(&Register::CR2).unwrap();
312 let cr3 = self.read_register(&Register::CR3).unwrap();
313 let cr4 = self.read_register(&Register::CR4).unwrap();
314 let efer = self.read_vmcs(VMCS_GUEST_IA32_EFER).unwrap();
315
316 write!(f,
317 "cr0: {cr0:016x} cr2: {cr2:016x} cr3: {cr3:016x}\ncr4: {cr4:016x} efer: {efer:016x}"
318 )?;
319
320 write!(f, "\nSegment registers:")?;
321 write!(f, "------------------")?;
322 write!(
323 f,
324 "register selector base limit type p dpl db s l g avl"
325 )?;
326
327 let cs = self.read_register(&Register::CS).unwrap();
328 let ds = self.read_register(&Register::DS).unwrap();
329 let es = self.read_register(&Register::ES).unwrap();
330 let ss = self.read_register(&Register::SS).unwrap();
331 let fs = self.read_register(&Register::FS).unwrap();
332 let gs = self.read_register(&Register::GS).unwrap();
333 let tr = self.read_register(&Register::TR).unwrap();
334 let ldtr = self.read_register(&Register::LDTR).unwrap();
335
336 let cs_limit = self.read_vmcs(VMCS_GUEST_CS_LIMIT).unwrap();
337 let cs_base = self.read_vmcs(VMCS_GUEST_CS_BASE).unwrap();
338 let cs_ar = self.read_vmcs(VMCS_GUEST_CS_AR).unwrap();
339 let ss_limit = self.read_vmcs(VMCS_GUEST_SS_LIMIT).unwrap();
340 let ss_base = self.read_vmcs(VMCS_GUEST_SS_BASE).unwrap();
341 let ss_ar = self.read_vmcs(VMCS_GUEST_SS_AR).unwrap();
342 let ds_limit = self.read_vmcs(VMCS_GUEST_DS_LIMIT).unwrap();
343 let ds_base = self.read_vmcs(VMCS_GUEST_DS_BASE).unwrap();
344 let ds_ar = self.read_vmcs(VMCS_GUEST_DS_AR).unwrap();
345 let es_limit = self.read_vmcs(VMCS_GUEST_ES_LIMIT).unwrap();
346 let es_base = self.read_vmcs(VMCS_GUEST_ES_BASE).unwrap();
347 let es_ar = self.read_vmcs(VMCS_GUEST_ES_AR).unwrap();
348 let fs_limit = self.read_vmcs(VMCS_GUEST_FS_LIMIT).unwrap();
349 let fs_base = self.read_vmcs(VMCS_GUEST_FS_BASE).unwrap();
350 let fs_ar = self.read_vmcs(VMCS_GUEST_FS_AR).unwrap();
351 let gs_limit = self.read_vmcs(VMCS_GUEST_GS_LIMIT).unwrap();
352 let gs_base = self.read_vmcs(VMCS_GUEST_GS_BASE).unwrap();
353 let gs_ar = self.read_vmcs(VMCS_GUEST_GS_AR).unwrap();
354 let tr_limit = self.read_vmcs(VMCS_GUEST_TR_LIMIT).unwrap();
355 let tr_base = self.read_vmcs(VMCS_GUEST_TR_BASE).unwrap();
356 let tr_ar = self.read_vmcs(VMCS_GUEST_TR_AR).unwrap();
357 let ldtr_limit = self.read_vmcs(VMCS_GUEST_LDTR_LIMIT).unwrap();
358 let ldtr_base = self.read_vmcs(VMCS_GUEST_LDTR_BASE).unwrap();
359 let ldtr_ar = self.read_vmcs(VMCS_GUEST_LDTR_AR).unwrap();
360
361 write!(f, "cs {:04x} {:016x} {:08x} {:02x} {:x} {:x} {:x} {:x} {:x} {:x} {:x}",
378 cs, cs_base, cs_limit, (cs_ar) & 0xf, (cs_ar >> 7) & 0x1, (cs_ar >> 5) & 0x3, (cs_ar >> 14) & 0x1,
379 (cs_ar >> 4) & 0x1, (cs_ar >> 13) & 0x1, (cs_ar >> 15) & 0x1, (cs_ar >> 12) & 1)?;
380 write!(f, "ss {:04x} {:016x} {:08x} {:02x} {:x} {:x} {:x} {:x} {:x} {:x} {:x}",
381 ss, ss_base, ss_limit, (ss_ar) & 0xf, (ss_ar >> 7) & 0x1, (ss_ar >> 5) & 0x3, (ss_ar >> 14) & 0x1,
382 (ss_ar >> 4) & 0x1, (ss_ar >> 13) & 0x1, (ss_ar >> 15) & 0x1, (ss_ar >> 12) & 1)?;
383 write!(f, "ds {:04x} {:016x} {:08x} {:02x} {:x} {:x} {:x} {:x} {:x} {:x} {:x}",
384 ds, ds_base, ds_limit, (ds_ar) & 0xf, (ds_ar >> 7) & 0x1, (ds_ar >> 5) & 0x3, (ds_ar >> 14) & 0x1,
385 (ds_ar >> 4) & 0x1, (ds_ar >> 13) & 0x1, (ds_ar >> 15) & 0x1, (ds_ar >> 12) & 1)?;
386 write!(f, "es {:04x} {:016x} {:08x} {:02x} {:x} {:x} {:x} {:x} {:x} {:x} {:x}",
387 es, es_base, es_limit, (es_ar) & 0xf, (es_ar >> 7) & 0x1, (es_ar >> 5) & 0x3, (es_ar >> 14) & 0x1,
388 (es_ar >> 4) & 0x1, (es_ar >> 13) & 0x1, (es_ar >> 15) & 0x1, (es_ar >> 12) & 1)?;
389 write!(f, "fs {:04x} {:016x} {:08x} {:02x} {:x} {:x} {:x} {:x} {:x} {:x} {:x}",
390 fs, fs_base, fs_limit, (fs_ar) & 0xf, (fs_ar >> 7) & 0x1, (fs_ar >> 5) & 0x3, (fs_ar >> 14) & 0x1,
391 (fs_ar >> 4) & 0x1, (fs_ar >> 13) & 0x1, (fs_ar >> 15) & 0x1, (fs_ar >> 12) & 1)?;
392 write!(f, "gs {:04x} {:016x} {:08x} {:02x} {:x} {:x} {:x} {:x} {:x} {:x} {:x}",
393 gs, gs_base, gs_limit, (gs_ar) & 0xf, (gs_ar >> 7) & 0x1, (gs_ar >> 5) & 0x3, (gs_ar >> 14) & 0x1,
394 (gs_ar >> 4) & 0x1, (gs_ar >> 13) & 0x1, (gs_ar >> 15) & 0x1, (gs_ar >> 12) & 1)?;
395 write!(f, "tr {:04x} {:016x} {:08x} {:02x} {:x} {:x} {:x} {:x} {:x} {:x} {:x}",
396 tr, tr_base, tr_limit, (tr_ar) & 0xf, (tr_ar >> 7) & 0x1, (tr_ar >> 5) & 0x3, (tr_ar >> 14) & 0x1,
397 (tr_ar >> 4) & 0x1, (tr_ar >> 13) & 0x1, (tr_ar >> 15) & 0x1, (tr_ar >> 12) & 1)?;
398 write!(f, "ldt {:04x} {:016x} {:08x} {:02x} {:x} {:x} {:x} {:x} {:x} {:x} {:x}",
399 ldtr, ldtr_base, ldtr_limit, (ldtr_ar) & 0xf, (ldtr_ar >> 7) & 0x1, (ldtr_ar >> 5) & 0x3, (ldtr_ar >> 14) & 0x1,
400 (ldtr_ar >> 4) & 0x1, (ldtr_ar >> 13) & 0x1, (ldtr_ar >> 15) & 0x1, (ldtr_ar >> 12) & 1)?;
401
402 let gdt_base = self.read_vmcs(VMCS_GUEST_GDTR_BASE).unwrap();
403 let gdt_limit = self.read_vmcs(VMCS_GUEST_GDTR_LIMIT).unwrap();
404 write!(f, "gdt {gdt_base:016x} {gdt_limit:08x}")?;
405 let idt_base = self.read_vmcs(VMCS_GUEST_IDTR_BASE).unwrap();
406 let idt_limit = self.read_vmcs(VMCS_GUEST_IDTR_LIMIT).unwrap();
407 write!(f, "idt {idt_base:016x} {idt_limit:08x}")?;
408 write!(
409 f,
410 "VMCS link pointer {:016x}",
411 self.read_vmcs(VMCS_GUEST_LINK_POINTER).unwrap()
412 )
413 }
414}
415
416#[allow(non_camel_case_types)]
418#[derive(Clone, Debug)]
419#[repr(C)]
420pub enum VMXCap {
421 PINBASED = 0,
423 PROCBASED = 1,
425 PROCBASED2 = 2,
427 ENTRY = 3,
429 EXIT = 4,
431 PREEMPTION_TIMER = 32,
433}
434
435pub fn read_vmx_cap(vmx_cap: &VMXCap) -> Result<u64, Error> {
437 let mut value: u64 = 0;
438
439 match_error_code(unsafe { hv_vmx_read_capability((*vmx_cap).clone(), &mut value) })?;
440
441 Ok(value)
442}
443
444impl fmt::Display for VMXCap {
445 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
446 match *self {
447 VMXCap::PINBASED => write!(f, "Pin-based VMX capabilities"),
448 VMXCap::PROCBASED => write!(f, "Primary proc-based VMX capabilities"),
449 VMXCap::PROCBASED2 => write!(f, "Secondary proc-based VMX capabilities"),
450 VMXCap::ENTRY => write!(f, "VM-entry VMX capabilities"),
451 VMXCap::EXIT => write!(f, "VM-exit VMX capabilities"),
452 VMXCap::PREEMPTION_TIMER => write!(f, "VMX preemption timer frequency"),
453 }
454 }
455}