Skip to content

Commit 1fe56a5

Browse files
committed
Apple Silicon support
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
1 parent b9764d8 commit 1fe56a5

7 files changed

Lines changed: 418 additions & 9 deletions

File tree

hv-sys/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ fn main() {
1212
.allowlist_var("HV.*")
1313
.allowlist_var("VM.*")
1414
.allowlist_var("IRQ.*")
15+
.derive_default(true)
1516
.layout_tests(false)
1617
.generate()
1718
.expect("Failed to generate bindings")

hv/examples/caps.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use hv::x86::{Capability, VmExt, VmOptions};
22

33
fn main() -> Result<(), hv::Error> {
4-
hv::Vm::create(VmOptions::default())?;
4+
hv::Vm::create_vm(VmOptions::default())?;
55

66
println!("Max vCPUs: {}", hv::Vm::capability(Capability::VcpuMax)?);
77

hv/src/arm64/mod.rs

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
//! Apple Silicon extensions support.
2+
3+
use std::ptr;
4+
5+
use crate::{call, sys, Error, Vcpu};
6+
7+
mod regs;
8+
pub use regs::*;
9+
10+
/// Injected interrupt type.
11+
#[repr(u32)]
12+
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
13+
pub enum InterruptType {
14+
IRQ = sys::hv_interrupt_type_t_HV_INTERRUPT_TYPE_IRQ,
15+
FIQ = sys::hv_interrupt_type_t_HV_INTERRUPT_TYPE_FIQ,
16+
}
17+
18+
/// Contains information about an exit from the vcpu to the host.
19+
pub type VcpuExit = sys::hv_vcpu_exit_t;
20+
21+
pub trait VcpuExt {
22+
/// Returns the current value of a vCPU register.
23+
fn get_reg(&self, reg: regs::Reg) -> Result<u64, Error>;
24+
25+
/// Sets the value of a vCPU register.
26+
fn set_reg(&self, reg: regs::Reg, value: u64) -> Result<(), Error>;
27+
28+
/// Returns the current value of a vCPU SIMD & FP register.
29+
fn get_simd_fp_reg(&self, reg: regs::SimdFpReg) -> Result<regs::SimdFpUchar16, Error>;
30+
31+
/// Sets the value of a vCPU SIMD & FP register
32+
fn set_simd_fp_reg(
33+
&self,
34+
reg: regs::SimdFpReg,
35+
value: regs::SimdFpUchar16,
36+
) -> Result<(), Error>;
37+
38+
/// Returns the current value of a vCPU system register.
39+
fn get_sys_reg(&self, reg: regs::SysReg) -> Result<u64, Error>;
40+
41+
/// Sets the value of a vCPU system register.
42+
fn set_sys_reg(&self, reg: regs::SysReg, value: u64) -> Result<(), Error>;
43+
44+
/// Gets pending interrupts for a vcpu.
45+
fn pending_interrupt(&self, ty: InterruptType) -> Result<bool, Error>;
46+
47+
/// Sets pending interrupts for a vcpu.
48+
fn set_pending_interrupt(&self, ty: InterruptType, pending: bool) -> Result<(), Error>;
49+
50+
/// Get whether debug exceptions in the guest are trapped to the host.
51+
fn trap_debug_exceptions(&self) -> Result<bool, Error>;
52+
53+
/// Set whether debug exceptions in the guest are trapped to the host.
54+
fn set_trap_debug_exceptions(&self, enable: bool) -> Result<(), Error>;
55+
56+
/// Get whether debug register accesses in the guest are trapped to the host.
57+
fn trap_debug_reg_accesses(&self) -> Result<bool, Error>;
58+
59+
/// Set whether debug register accesses in the guest are trapped to the host.
60+
fn set_trap_debug_reg_accesses(&self, enable: bool) -> Result<(), Error>;
61+
62+
/// Gets the VTimer mask.
63+
fn vtimer_mask(&self) -> Result<bool, Error>;
64+
65+
/// Sets the VTimer mask.
66+
fn set_vtimer_mask(&self, vtimer_is_masked: bool) -> Result<(), Error>;
67+
68+
/// Gets the VTimer offset.
69+
fn vtimer_offset(&self) -> Result<u64, Error>;
70+
71+
/// Sets the VTimer offset.
72+
fn set_vtimer_offset(&self, vtimer_offset: u64) -> Result<(), Error>;
73+
74+
/// Returns the underlying `hv_vcpu_exit_t` structure.
75+
fn exit_info(&self) -> VcpuExit;
76+
}
77+
78+
impl VcpuExt for Vcpu {
79+
/// Returns the current value of a vCPU register.
80+
fn get_reg(&self, reg: regs::Reg) -> Result<u64, Error> {
81+
let mut out = 0_u64;
82+
call!(sys::hv_vcpu_get_reg(self.cpu, reg as _, &mut out))?;
83+
Ok(out)
84+
}
85+
86+
/// Sets the value of a vCPU register.
87+
fn set_reg(&self, reg: regs::Reg, value: u64) -> Result<(), Error> {
88+
call!(sys::hv_vcpu_set_reg(self.cpu, reg as _, value))
89+
}
90+
91+
/// Returns the current value of a vCPU SIMD & FP register.
92+
fn get_simd_fp_reg(&self, reg: regs::SimdFpReg) -> Result<regs::SimdFpUchar16, Error> {
93+
let mut out = 0_u128;
94+
call!(sys::hv_vcpu_get_simd_fp_reg(self.cpu, reg as _, &mut out))?;
95+
Ok(out)
96+
}
97+
98+
/// Sets the value of a vCPU SIMD & FP register.
99+
fn set_simd_fp_reg(
100+
&self,
101+
reg: regs::SimdFpReg,
102+
value: regs::SimdFpUchar16,
103+
) -> Result<(), Error> {
104+
call!(sys::hv_vcpu_set_simd_fp_reg(self.cpu, reg as _, value))?;
105+
Ok(())
106+
}
107+
108+
/// Returns the current value of a vCPU system register.
109+
fn get_sys_reg(&self, reg: regs::SysReg) -> Result<u64, Error> {
110+
let mut out = 0_u64;
111+
call!(sys::hv_vcpu_get_sys_reg(self.cpu, reg as _, &mut out))?;
112+
Ok(out)
113+
}
114+
115+
/// Sets the value of a vCPU system register.
116+
fn set_sys_reg(&self, reg: regs::SysReg, value: u64) -> Result<(), Error> {
117+
call!(sys::hv_vcpu_set_sys_reg(self.cpu, reg as _, value))
118+
}
119+
120+
/// Gets pending interrupts for a vcpu.
121+
fn pending_interrupt(&self, ty: InterruptType) -> Result<bool, Error> {
122+
let mut out = false;
123+
call!(sys::hv_vcpu_get_pending_interrupt(
124+
self.cpu, ty as u32, &mut out
125+
))?;
126+
Ok(out)
127+
}
128+
129+
/// Sets pending interrupts for a vcpu.
130+
fn set_pending_interrupt(&self, ty: InterruptType, mut pending: bool) -> Result<(), Error> {
131+
call!(sys::hv_vcpu_get_pending_interrupt(
132+
self.cpu,
133+
ty as u32,
134+
&mut pending
135+
))
136+
}
137+
138+
/// Get whether debug exceptions in the guest are trapped to the host.
139+
fn trap_debug_exceptions(&self) -> Result<bool, Error> {
140+
let mut out = false;
141+
call!(sys::hv_vcpu_get_trap_debug_exceptions(self.cpu, &mut out))?;
142+
Ok(out)
143+
}
144+
145+
/// Set whether debug exceptions in the guest are trapped to the host.
146+
fn set_trap_debug_exceptions(&self, enable: bool) -> Result<(), Error> {
147+
call!(sys::hv_vcpu_set_trap_debug_exceptions(self.cpu, enable))
148+
}
149+
150+
/// Get whether debug register accesses in the guest are trapped to the host.
151+
fn trap_debug_reg_accesses(&self) -> Result<bool, Error> {
152+
let mut out = false;
153+
call!(sys::hv_vcpu_get_trap_debug_reg_accesses(self.cpu, &mut out))?;
154+
Ok(out)
155+
}
156+
157+
/// Set whether debug register accesses in the guest are trapped to the host.
158+
fn set_trap_debug_reg_accesses(&self, enable: bool) -> Result<(), Error> {
159+
call!(sys::hv_vcpu_set_trap_debug_reg_accesses(self.cpu, enable))
160+
}
161+
162+
/// Gets the VTimer mask.
163+
fn vtimer_mask(&self) -> Result<bool, Error> {
164+
let mut out = false;
165+
call!(sys::hv_vcpu_get_vtimer_mask(self.cpu, &mut out))?;
166+
Ok(out)
167+
}
168+
169+
/// Sets the VTimer mask.
170+
fn set_vtimer_mask(&self, vtimer_is_masked: bool) -> Result<(), Error> {
171+
call!(sys::hv_vcpu_set_vtimer_mask(self.cpu, vtimer_is_masked))
172+
}
173+
174+
/// Gets the VTimer offset.
175+
fn vtimer_offset(&self) -> Result<u64, Error> {
176+
let mut out = 0_u64;
177+
call!(sys::hv_vcpu_get_vtimer_offset(self.cpu, &mut out))?;
178+
Ok(out)
179+
}
180+
181+
/// Sets the VTimer offset.
182+
fn set_vtimer_offset(&self, vtimer_offset: u64) -> Result<(), Error> {
183+
call!(sys::hv_vcpu_set_vtimer_offset(self.cpu, vtimer_offset))
184+
}
185+
186+
/// Returns the underlying `hv_vcpu_exit_t` structure.
187+
fn exit_info(&self) -> VcpuExit {
188+
if self.exit == ptr::null() {
189+
VcpuExit::default()
190+
} else {
191+
unsafe { *self.exit }
192+
}
193+
}
194+
}

0 commit comments

Comments
 (0)