1extern crate libc;
46extern crate core;
47
48#[allow(non_camel_case_types)]
49pub mod ffi;
50pub mod consts;
51
52use self::core::fmt;
53use libc::*;
54
55use self::ffi::*;
56
57pub enum Error {
59 Success,
61 Error,
63 Busy,
65 BadArg,
67 NoRes,
69 NoDev,
71 Unsupp
73}
74
75impl fmt::Debug for Error {
76 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77 match *self {
78 Error::Success => write!(f, "Success"),
79 Error::Error => write!(f, "Error"),
80 Error::Busy => write!(f, "Busy"),
81 Error::BadArg => write!(f, "Bad argument"),
82 Error::NoRes => write!(f, "No resources"),
83 Error::NoDev => write!(f, "No device"),
84 Error::Unsupp => write!(f, "Unsupported"),
85 }
86 }
87}
88
89fn match_error_code(code: hv_return_t) -> Error {
91 match code {
92 HV_SUCCESS => Error::Success,
93 HV_BUSY => Error::Busy,
94 HV_BAD_ARGUMENT => Error::BadArg,
95 HV_NO_RESOURCES => Error::NoRes,
96 HV_NO_DEVICE => Error::NoDev,
97 HV_UNSUPPORTED => Error::Unsupp,
98 _ => Error::Error
99 }
100}
101
102pub fn create_vm() -> Error {
104 match_error_code(unsafe {
105 hv_vm_create(HV_VM_DEFAULT)
106 })
107}
108
109pub fn destroy_vm() -> Error {
111 match_error_code(unsafe {
112 hv_vm_destroy()
113 })
114}
115
116pub enum MemPerm {
118 Read,
120 Write,
122 Exec,
124 ExecAndWrite,
126 ExecAndRead
128}
129
130#[allow(non_snake_case)]
131#[inline(always)]
132fn match_MemPerm(mem_perm: &MemPerm) -> uint64_t {
133 match mem_perm {
134 &MemPerm::Read => HV_MEMORY_READ,
135 &MemPerm::Write => HV_MEMORY_WRITE | HV_MEMORY_READ,
136 &MemPerm::Exec => HV_MEMORY_EXEC,
137 &MemPerm::ExecAndWrite => HV_MEMORY_EXEC | HV_MEMORY_WRITE | HV_MEMORY_READ,
138 &MemPerm::ExecAndRead => HV_MEMORY_EXEC | HV_MEMORY_READ,
139 }
140}
141
142pub fn map_mem(mem: &[u8], gpa: u64, mem_perm: &MemPerm) -> Error {
145 match_error_code(unsafe {
146 hv_vm_map(
147 mem.as_ptr() as *const c_void, gpa as hv_gpaddr_t, mem.len() as size_t,
148 match_MemPerm(mem_perm)
149 )
150 })
151}
152
153pub fn unmap_mem(gpa: u64, size: usize) -> Error {
155 match_error_code(unsafe {
156 hv_vm_unmap(gpa as hv_gpaddr_t, size as size_t)
157 })
158}
159
160pub fn protect_mem(gpa: u64, size: usize, mem_perm: &MemPerm) -> Error {
163 match_error_code(unsafe {
164 hv_vm_protect(gpa as hv_gpaddr_t, size as size_t, match_MemPerm(mem_perm))
165 })
166}
167
168pub fn sync_tsc(tsc: u64) -> Error {
172 match_error_code(unsafe {
173 hv_vm_sync_tsc(tsc as uint64_t)
174 })
175}
176
177pub fn interrupt_vcpus(vcpu_ids: &[u32]) -> Error {
181 match_error_code(unsafe {
182 hv_vcpu_interrupt(vcpu_ids.as_ptr(), vcpu_ids.len() as c_uint)
183 })
184}
185
186#[allow(non_camel_case_types)]
188pub struct vCPU {
189 pub id: u32
191}
192
193#[allow(non_camel_case_types)]
195#[derive(Clone)]
196#[repr(C)]
197pub enum x86Reg {
198 RIP,
199 RFLAGS,
200 RAX,
201 RCX,
202 RDX,
203 RBX,
204 RSI,
205 RDI,
206 RSP,
207 RBP,
208 R8,
209 R9,
210 R10,
211 R11,
212 R12,
213 R13,
214 R14,
215 R15,
216 CS,
217 SS,
218 DS,
219 ES,
220 FS,
221 GS,
222 IDT_BASE,
223 IDT_LIMIT,
224 GDT_BASE,
225 GDT_LIMIT,
226 LDTR,
227 LDT_BASE,
228 LDT_LIMIT,
229 LDT_AR,
230 TR,
231 TSS_BASE,
232 TSS_LIMIT,
233 TSS_AR,
234 CR0,
235 CR1,
236 CR2,
237 CR3,
238 CR4,
239 DR0,
240 DR1,
241 DR2,
242 DR3,
243 DR4,
244 DR5,
245 DR6,
246 DR7,
247 TPR,
248 XCR0,
249 REGISTERS_MAX,
250}
251
252impl vCPU {
253
254 pub fn new() -> Result<vCPU, Error> {
256 let mut vcpuid: hv_vcpuid_t = 0;
257
258 let error = match_error_code(unsafe {
259 hv_vcpu_create(&mut vcpuid, HV_VCPU_DEFAULT)
260 });
261
262 match error {
263 Error::Success => Ok(vCPU {
264 id: vcpuid as u32
265 }),
266 _ => Err(error)
267 }
268 }
269
270 pub fn destroy(&self) -> Error {
272 match_error_code(unsafe {
273 hv_vcpu_destroy(self.id as hv_vcpuid_t)
274 })
275 }
276
277 pub fn run(&self) -> Error {
279 match_error_code(unsafe {
280 hv_vcpu_run(self.id as hv_vcpuid_t)
281 })
282 }
283
284 pub fn interrupt(&self) -> Error {
286 match_error_code(unsafe {
287 hv_vcpu_interrupt(&(self.id), 1 as c_uint)
288 })
289 }
290
291 pub fn exec_time(&self) -> Result<u64, Error> {
293 let mut exec_time: uint64_t = 0;
294
295 let error = match_error_code(unsafe {
296 hv_vcpu_get_exec_time(self.id, &mut exec_time)
297 });
298
299 match error {
300 Error::Success => Ok(exec_time as u64),
301 _ => Err(error)
302 }
303 }
304
305 pub fn flush(&self) -> Error {
307 match_error_code(unsafe {
308 hv_vcpu_flush(self.id as hv_vcpuid_t)
309 })
310 }
311
312 pub fn invalidate_tlb(&self) -> Error {
314 match_error_code(unsafe {
315 hv_vcpu_invalidate_tlb(self.id as hv_vcpuid_t)
316 })
317 }
318
319 pub fn enable_native_msr(&self, msr: u32, enable: bool) -> Error {
321 match_error_code(unsafe {
322 hv_vcpu_enable_native_msr(self.id as hv_vcpuid_t, msr as uint32_t, enable)
323 })
324 }
325
326 pub fn read_msr(&self, msr: u32) -> Result<u64, Error> {
328 let mut value: uint64_t = 0;
329
330 let error = match_error_code(unsafe {
331 hv_vcpu_read_msr(self.id as hv_vcpuid_t, msr as uint32_t, &mut value)
332 });
333
334 match error {
335 Error::Success => Ok(value as u64),
336 _ => Err(error)
337 }
338 }
339
340 pub fn write_msr(&self, msr: u32, value: u64) -> Error {
342 match_error_code(unsafe {
343 hv_vcpu_write_msr(self.id as hv_vcpuid_t, msr as uint32_t, &(value as uint64_t))
344 })
345 }
346
347 pub fn read_register(&self, reg: &x86Reg) -> Result<u64, Error> {
350 let mut value: uint64_t = 0;
351
352 let error = match_error_code(unsafe {
353 hv_vcpu_read_register(self.id as hv_vcpuid_t, (*reg).clone(), &mut value)
354 });
355
356 match error {
357 Error::Success => Ok(value as u64),
358 _ => Err(error)
359 }
360 }
361
362 pub fn write_register(&self, reg: &x86Reg, value: u64) -> Error {
364 match_error_code(unsafe {
365 hv_vcpu_write_register(self.id as hv_vcpuid_t, (*reg).clone(), value as uint64_t)
366 })
367 }
368
369 pub fn read_vmcs(&self, field: u32) -> Result<u64, Error> {
371 let mut value: uint64_t = 0;
372
373 let error = match_error_code(unsafe {
374 hv_vmx_vcpu_read_vmcs(self.id as hv_vcpuid_t, field as uint32_t, &mut value)
375 });
376
377 match error {
378 Error::Success => Ok(value as u64),
379 _ => Err(error)
380 }
381 }
382
383 pub fn write_vmcs(&self, field: u32, value: u64) -> Error {
385 match_error_code(unsafe {
386 hv_vmx_vcpu_write_vmcs(self.id as hv_vcpuid_t, field as uint32_t, value as uint64_t)
387 })
388 }
389
390 pub fn set_apic_addr(&self, gpa: u64) -> Error {
393 match_error_code(unsafe {
394 hv_vmx_vcpu_set_apic_address(self.id as hv_vcpuid_t, gpa as uint64_t)
395 })
396 }
397
398 pub fn read_fpstate(&self, buffer: &mut [u8]) -> Error {
400 match_error_code(unsafe {
401 hv_vcpu_read_fpstate(self.id as hv_vcpuid_t, buffer.as_mut_ptr() as *mut c_void,
402 buffer.len() as size_t)
403 })
404 }
405
406 pub fn write_fpstate(&self, buffer: &[u8]) -> Error {
408 match_error_code(unsafe {
409 hv_vcpu_write_fpstate(self.id as hv_vcpuid_t, buffer.as_ptr() as *const c_void,
410 buffer.len() as size_t)
411 })
412 }
413
414}
415
416impl fmt::Debug for vCPU {
417 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
418 write!(f, "vCPU ID: {}", (*self).id)
419 }
420}
421
422#[allow(non_camel_case_types)]
424#[derive(Clone)]
425#[repr(C)]
426pub enum VMXCap {
427 PINBASED = 0,
429 PROCBASED = 1,
431 PROCBASED2 = 2,
433 ENTRY = 3,
435 EXIT = 4,
437 PREEMPTION_TIMER = 32,
439}
440
441pub fn read_vmx_cap(vmx_cap: &VMXCap) -> Result<u64, Error> {
443 let mut value: uint64_t = 0;
444
445 let error = match_error_code(unsafe {
446 hv_vmx_read_capability((*vmx_cap).clone(), &mut value)
447 });
448
449 match error {
450 Error::Success => Ok(value as u64),
451 _ => Err(error)
452 }
453}