Framework

Hypervisor

Build virtualization solutions on top of a lightweight hypervisor, without the need for third-party kernel extensions.

Overview

The Hypervisor framework provides C APIs for interacting with virtualization technologies in user-space, without the need for writing kernel extensions (KEXTs). As a result, apps created using this framework are suitable for distribution on the Mac App Store.

Hardware-facilitated virtual machines (VMs) and virtual processors (vCPUs) can be created and controlled by an entitled sandboxed user space process, the hypervisor client. The Hypervisor framework abstracts virtual machines as tasks and virtual processors as threads.

Requirements

The Hypervisor framework has the following requirements:

Entitlements

A sandboxed user space process must have the com.apple.vm.hypervisor entitlement in order to use Hypervisor APIs.

Supported Hardware

Generally, machines with an Intel VT-x feature set that includes Extended Page Tables (EPT) and Unrestricted Mode are supported. You can determine the availability of Hypervisor APIs on a particular machine at runtime with the sysctl(8) command, passing kern.hv_support as an argument.

Example VM Life Cycle

The following figure illustrates a simplified life cycle of creating and running a virtual machine with one or more virtual CPUs using the Hypervisor Framework API.

Figure 1

An example life cycle of creating and running a virtual machine with one or more virtual CPUs.

A flow diagram representing the life cycle of a virtual machine.

At the start of a task, create a VM, map a region in the virtual address space of the task into the guest physical address space of the VM, and create POSIX Threads. Then, create one or more virtual CPUs, run the task on a POSIX thread, handle the VMEXIT event, and then destroy the virtual CPU. After virtual CPUs are destroyed, end the POSIX threads, unmap the memory region, and finally destroy the VM.

Topics

Creating and Destroying VM Instances

func hv_vm_create(hv_vm_options_t)

Creates a VM instance for the current task.

func hv_vm_destroy()

Destroys the VM instance associated with the current task.

Managing Memory Regions

func hv_vm_map(hv_uvaddr_t!, hv_gpaddr_t, Int, hv_memory_flags_t)

Maps a region in the virtual address space of the current task into the guest physical address space of the VM.

func hv_vm_unmap(hv_gpaddr_t, Int)

Unmaps a region in the guest physical address space of the VM.

func hv_vm_protect(hv_gpaddr_t, Int, hv_memory_flags_t)

Modifies the permissions of a region in the guest physical address space of the VM.

Creating and Managing vCPU Instances

func hv_vcpu_destroy(hv_vcpuid_t)

Destroys the vCPU instance associated with the current thread.

func hv_vcpu_interrupt(UnsafeMutablePointer<hv_vcpuid_t>!, UInt32)

Forces an immediate VMEXIT of a set of vCPU instances of the VM.

func hv_vcpu_invalidate_tlb(hv_vcpuid_t)

Invalidates the translation look-aside buffer (TLB) of a vCPU.

func hv_vcpu_flush(hv_vcpuid_t)

Flushes the cached state of a vCPU.

func hv_vcpu_enable_native_msr(hv_vcpuid_t, UInt32, Bool)

Enables or disables a machine specific register (MSR) to be used natively by the VM.

func hv_vcpu_get_exec_time(hv_vcpuid_t, UnsafeMutablePointer<UInt64>!)

Returns, by reference, the cumulative execution time of a vCPU, in nanoseconds.

Managing Timestamp-Counters (TSC)

func hv_vm_sync_tsc(UInt64)

Synchronizes guest timestamp-counters (TSC) across all vCPUs.

Accessing Registers

func hv_vcpu_read_register(hv_vcpuid_t, hv_x86_reg_t, UnsafeMutablePointer<UInt64>!)

Returns, by reference, the current value of an architectural x86 register of a vCPU.

func hv_vcpu_write_register(hv_vcpuid_t, hv_x86_reg_t, UInt64)

Sets the value of an architectural x86 register of a vCPU.

Accessing Floating Point (FP) State

func hv_vcpu_read_fpstate(hv_vcpuid_t, UnsafeMutableRawPointer!, Int)

Returns, by reference, the current architectural x86 floating point and SIMD state of a vCPU.

func hv_vcpu_write_fpstate(hv_vcpuid_t, UnsafeMutableRawPointer!, Int)

Sets the architectural x86 floating point and SIMD state of a vCPU.

Accessing Machine Specific Registers (MSRs)

func hv_vcpu_read_msr(hv_vcpuid_t, UInt32, UnsafeMutablePointer<UInt64>!)

Returns, by reference, the current value of a machine specific register (MSR) of a vCPU.

func hv_vcpu_write_msr(hv_vcpuid_t, UInt32, UInt64)

Sets the value of an machine specific register (MSR) of a vCPU.

Managing Virtual Machine Control Structure (VMCS)

func hv_vmx_vcpu_read_vmcs(hv_vcpuid_t, UInt32, UnsafeMutablePointer<UInt64>!)

Returns, by reference, the current value of a virtual machine control structure (VMCS) field of a vCPU.

func hv_vmx_vcpu_write_vmcs(hv_vcpuid_t, UInt32, UInt64)

Sets the value of a virtual machine control structure (VMCS) field of a vCPU.

func hv_vmx_read_capability(hv_vmx_capability_t, UnsafeMutablePointer<UInt64>!)

Returns, by reference, the VMX virtualization capabilities of the host processor.

func hv_vmx_vcpu_set_apic_address(hv_vcpuid_t, hv_gpaddr_t)

Sets the address of the guest APIC for a vCPU in the guest physical address space of the VM.

Data Types

typealias hv_return_t

The return type for Hypervisor Framework functions.

typealias hv_memory_flags_t

Guest physical memory region permissions for the hv_vm_map(_:_:_:_:) and hv_vm_protect(_:_:_:) functions.

struct hv_x86_reg_t

x86 architectural register IDs.

struct hv_vmx_capability_t

VMX capability field IDs.

typealias hv_vcpuid_t

Type of a vCPU ID.

typealias hv_uvaddr_t

Type of a user virtual address.

typealias hv_gpaddr_t

Type of a guest physical address (GPA).