Skip to content

Commit b9764d8

Browse files
committed
Align common API for platforms
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
1 parent 8ff4b46 commit b9764d8

5 files changed

Lines changed: 131 additions & 102 deletions

File tree

hv/src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! `hv` is a high level safe Rust crate to access Hypervisor Framework.
22
33
use std::error;
4+
use std::ffi::c_void;
45
use std::fmt;
56

67
/// Low level access to generated bindings.
@@ -14,6 +15,14 @@ pub mod vm;
1415
#[cfg(target_arch = "x86_64")]
1516
pub mod x86;
1617

18+
pub type Size = u64;
19+
20+
/// Type of a user virtual address.
21+
pub type Addr = *const c_void;
22+
23+
/// Type of a guest physical address.
24+
pub type GPAddr = u64;
25+
1726
/// Helper macro to call unsafe Hypervisor functions and map returned error codes to [Error] type.
1827
#[macro_export]
1928
macro_rules! call {

hv/src/vcpu.rs

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,73 @@
11
use crate::{call, sys, Error};
22

3-
#[cfg(target_arch = "x86_64")]
4-
type Handle = sys::hv_vcpuid_t;
5-
#[cfg(target_arch = "aarch64")]
6-
type Handle = sys::hv_vcpu_t;
7-
83
/// Represents a single virtual CPU.
94
///
105
/// [Vcpu] object is not thread safe, all calls must be performed from
116
/// the owning thread.
12-
pub struct Vcpu(pub(crate) Handle);
7+
pub struct Vcpu {
8+
#[cfg(target_arch = "x86_64")]
9+
pub(crate) cpu: sys::hv_vcpuid_t,
10+
#[cfg(target_arch = "aarch64")]
11+
pub(crate) cpu: sys::hv_vcpu_t,
12+
#[cfg(target_arch = "aarch64")]
13+
/// The pointer to the vCPU exit information.
14+
/// The function `hv_vcpu_run` updates this structure on return.
15+
/// Apple silicon only.
16+
pub(crate) exit: *const sys::hv_vcpu_exit_t,
17+
}
1318

1419
impl Vcpu {
1520
/// Creates a vCPU instance for the current thread.
1621
pub(crate) fn new() -> Result<Vcpu, Error> {
17-
let mut handle = 0;
1822
#[cfg(target_arch = "x86_64")]
19-
call!(sys::hv_vcpu_create(&mut handle, 0))?;
20-
Ok(Vcpu(handle))
23+
{
24+
let mut cpu = 0;
25+
call!(sys::hv_vcpu_create(&mut cpu, 0))?;
26+
Ok(Vcpu { cpu })
27+
}
28+
29+
#[cfg(target_arch = "aarch64")]
30+
{
31+
let mut cpu = 0;
32+
let mut exit = std::ptr::null_mut();
33+
call!(sys::hv_vcpu_create(
34+
&mut cpu,
35+
&mut exit,
36+
std::ptr::null_mut()
37+
))?;
38+
Ok(Vcpu { cpu, exit })
39+
}
2140
}
2241

2342
/// Executes a vCPU.
43+
///
44+
/// Call blocks until the next exit of the vCPU [1].
45+
/// The owning thread must call this function.
46+
///
47+
/// # Intel
48+
/// On an Intel-based Mac, `hv_vcpu_run` exits from causes external to the guest.
49+
/// To avoid the overhead of spurious exits use `hv_vcpu_run_until` with the deadline `HV_DEADLINE_FOREVER`.
50+
///
51+
/// # Apple Silicon
52+
/// If the exit is of type `HV_EXIT_REASON_VTIMER_ACTIVATED`, the VTimer is automatically masked.
53+
/// As a result, no timer fires until the timer is unmasked with `hv_vcpu_set_vtimer_mask`.
54+
///
55+
/// [1]: https://developer.apple.com/documentation/hypervisor/1441231-hv_vcpu_run
2456
pub fn run(&self) -> Result<(), Error> {
25-
call!(sys::hv_vcpu_run(self.0))
26-
}
27-
28-
/// Executes a vCPU until the given deadline.
29-
#[cfg(feature = "hv_10_15")]
30-
pub fn run_until(&self, deadline: u64) -> Result<(), Error> {
31-
call!(sys::hv_vcpu_run_until(self.0, deadline))
57+
call!(sys::hv_vcpu_run(self.cpu))
3258
}
3359

3460
/// Returns the cumulative execution time of a vCPU in nanoseconds.
3561
pub fn exec_time(&self) -> Result<u64, Error> {
3662
let mut out = 0_u64;
37-
call!(sys::hv_vcpu_get_exec_time(self.0, &mut out))?;
63+
call!(sys::hv_vcpu_get_exec_time(self.cpu, &mut out))?;
3864
Ok(out)
3965
}
4066
}
4167

4268
impl Drop for Vcpu {
4369
/// Destroys the vCPU instance associated with the current thread.
4470
fn drop(&mut self) {
45-
let _ = call!(sys::hv_vcpu_destroy(self.0));
71+
let _ = call!(sys::hv_vcpu_destroy(self.cpu));
4672
}
4773
}

hv/src/vm.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use crate::{call, sys, Error, Vcpu};
1+
use std::ffi::c_void;
2+
3+
use crate::{call, sys, Addr, Error, GPAddr, Size, Vcpu};
24

35
bitflags::bitflags! {
46
/// Guest physical memory region permissions.
@@ -19,6 +21,48 @@ impl Vm {
1921
Vcpu::new()
2022
}
2123

24+
/// Maps a region in the virtual address space of the current task into the guest physical
25+
/// address space of the VM.
26+
///
27+
/// The host memory must encompass a single VM region, typically allocated with `mmap` or
28+
/// `mach_vm_allocate` instead of `malloc`. [1]
29+
///
30+
/// # Arguments
31+
/// * `uva` - Page aligned virtual address in the current task.
32+
/// * `gpa` - Page aligned address in the guest physical address space.
33+
/// * `size` - Size in bytes of the region to be mapped.
34+
/// * `flags` - READ, WRITE and EXECUTE permissions of the region
35+
///
36+
/// [1]: https://developer.apple.com/documentation/hypervisor/1441187-hv_vm_map
37+
///
38+
pub fn map(uva: Addr, gpa: GPAddr, size: Size, flags: Memory) -> Result<(), Error> {
39+
call!(sys::hv_vm_map(
40+
uva as *mut c_void,
41+
gpa,
42+
size,
43+
flags.bits().into()
44+
))
45+
}
46+
47+
/// Unmaps a region in the guest physical address space of the VM
48+
///
49+
/// # Arguments
50+
/// * `gpa` - Page aligned address in the guest physical address space.
51+
/// * `size` - Size in bytes of the region to be unmapped.
52+
pub fn unmap(gpa: GPAddr, size: Size) -> Result<(), Error> {
53+
call!(sys::hv_vm_unmap(gpa, size))
54+
}
55+
56+
/// Modifies the permissions of a region in the guest physical address space of the VM.
57+
///
58+
/// # Arguments
59+
/// * `gpa` - Page aligned address in the guest physical address space.
60+
/// * `size` - Size in bytes of the region to be modified.
61+
/// * `flags` - New READ, WRITE and EXECUTE permissions of the region.
62+
pub fn protect(gpa: GPAddr, size: Size, flags: Memory) -> Result<(), Error> {
63+
call!(sys::hv_vm_protect(gpa, size, flags.bits().into()))
64+
}
65+
2266
/// Destroys the VM instance associated with the current process.
2367
pub fn destroy() -> Result<(), Error> {
2468
call!(sys::hv_vm_destroy())

0 commit comments

Comments
 (0)