

A VM exit is a hypervisor-class exception, i.e. This call runs the virtual CPU (while blocking the calling thread) until its time slice expires or a “VM exit” happens. The virtual CPU is fully set up, we can now run it! Hv_vcpu_write_register(vcpu, HV_X86_RSP, 0x0) Hv_vcpu_write_register(vcpu, HV_X86_RFLAGS, 0x2) Hv_vcpu_write_register(vcpu, HV_X86_RIP, 0x100) …and assign the GPRs the proper initial state – including the instruction pointer, which will point to the code:
Mac ox s 10.10 emulator code#
Hv_vmx_vcpu_write_vmcs(vcpu, VMCS_GUEST_CR4, 0x2000) Īfter that, we should populate RAM with the code we want to execute:įread((char *)vm_mem + 0x100, 1, 64 * 1024, f)

Hv_vmx_vcpu_write_vmcs(vcpu, VMCS_GUEST_CR3, 0x0) Hv_vmx_vcpu_write_vmcs(vcpu, VMCS_GUEST_CR0, 0x20) Hv_vmx_vcpu_write_vmcs(vcpu, VMCS_GUEST_DS_BASE, 0) Hv_vmx_vcpu_write_vmcs(vcpu, VMCS_GUEST_DS_ACCESS_RIGHTS, 0x93) Hv_vmx_vcpu_write_vmcs(vcpu, VMCS_GUEST_DS_LIMIT, 0xffff) Hv_vmx_vcpu_write_vmcs(vcpu, VMCS_GUEST_DS_SELECTOR, 0) Hv_vmx_vcpu_write_vmcs(vcpu, VMCS_GUEST_CS_BASE, 0) Hv_vmx_vcpu_write_vmcs(vcpu, VMCS_GUEST_CS_ACCESS_RIGHTS, 0x9b) Hv_vmx_vcpu_write_vmcs(vcpu, VMCS_GUEST_CS_LIMIT, 0xffff) Hv_vmx_vcpu_write_vmcs(vcpu, VMCS_GUEST_CS_SELECTOR, 0) Real mode state setup looks something like this: Luckily, most virtual machines start from 16 bit real mode, and mode changes will be done by the boot loader or operating system inside the VM, so you won’t have to worry about setting up any other state than real mode state.
Mac ox s 10.10 emulator manual#
You will need to refer to the Intel Manual 3C for all the context. If the state is illegal or inconsistent, the CPU will refuse to run. Now comes the annoying part: Set up the CPU state. Hv_vm_map(vm_mem, 0, VM_MEM_SIZE, HV_MEMORY_READ |Īnd we need to create a virtual CPU: hv_vcpuid_t vcpu Then we allocate some memory and assign it to the VM: #define VM_MEM_SIZE (1 * 1024 * 1024) It’s implicit, so it doesn’t return anything. This creates a VM for the current Mach task (i.e. So let’s create a virtual machine that runs simple DOS applications in 16 bit real mode, and trap all “ int” DOS system calls – similar to DOSBox.įirst, we need to create a VM: hv_vm_create(HV_VM_DEFAULT) * Call blocks until the next VMEXIT of the vCPUĮxtern hv_return_t hv_vcpu_run(hv_vcpuid_t vcpu) _HV_10_10 * vcpu Pointer to the vCPU ID (written on success)Įxtern hv_return_t hv_vcpu_create(hv_vcpuid_t *vcpu, * Creates a vCPU instance for the current thread * flags READ, WRITE and EXECUTE permissions of the regionĮxtern hv_return_t hv_vm_map(hv_uvaddr_t uva, hv_gpaddr_t gpa, size_t size, * size Size in bytes of the region to be mapped * gpa Page aligned address in the guest physical address space * uva Page aligned virtual address in the current task * into the guest physical address space of the VM * Maps a region in the virtual address space of the current task * Creates a VM instance for the current taskĮxtern hv_return_t hv_vm_create(hv_vm_options_t flags) _HV_10_10

Here are some declarations from Hypervisor/hv.h: There is no real documentation, but the headers contain a decent amount of information.

All we have to do is create a virtual CPU (or more!), set up all its state, assign it some memory, and run it… and then handle all “VM exits” – Intel lingo for hypervisor traps. The idea is that the OS takes care of memory management (including nested paging) as well as scheduling virtual CPUs like normal threads. It enables apps to use virtualization without the need of a kernel extension (KEXT) – which makes them compatible with the OS X App Store guidelines. Since Version 10.10 (Yosemite), OS X contains amework, which provides a thin user mode abstraction of the Intel VT features.
