Mac OS X guest and VirtualBox 5 on AMD CPU

Before you proceed: there is NO working solution yet, and I was not able to run unmodified Mac OS X guest on AMD CPU under VirtualBox. It runs fine under KVM however.

Installing it on a machine with Intel CPU is not a problem. While VirtualBox does not officially support OS X guests on non-Mac hardware, it is still trivial to do so, as described in the following post.

However this will not be enough on AMD CPU, where the OS X kernel will halt (Mavericks) or crash (Yosemite) on boot. More changes are needed.

First, we need to tell VirtualBox to present its CPU as Intel. The OS X checks the CPU brand by using CPUID instruction, so we can modify its output in VirtualBox to masquerade our CPU as Intel:

VBoxManage modifyvm "$1" --cpuidset 00000000 00000001 756e6547 6c65746e 49656e69

Note that the second instruction from the script above (setting –cpuidset 00000001) should NOT be executed on AMD CPU.

This will bring us further in the OS X load process – now it crashes with Guru Meditation 1155 (VINF_EM_TRIPLE_FAULT). This is a rather tough error to debug as this means the CPU encountered an exception while already reacting on the exception. Fortunately we can spot in the log we see the following reason for crash:

IEM: wrmsr(0x8b,0x0`00000000) -> #GP(0)

Which means the CPU attempted to write the MSR register 0x8B the instruction wrmsr 0x8b, 0 – and the reason for the crash. If we could ignore this write, we should be able to proceed further!

Fortunately this is possible. VirtualBox contains (internal) settings to override MSRs, see function src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp – the format is the following:

VBoxManage setextradata VM “VBoxInternal/CPUM/MSRs/name/First value
VBoxManage setextradata VM “VBoxInternal/CPUM/MSRs/name/Last value
VBoxManage setextradata VM “VBoxInternal/CPUM/MSRs/name/Value value

Here name is a user-defined name (it is used for logging and retrieval of subsequent values). First value must be the first MSR register value to override, in our case 0x8B. If you want to override the register range, you can put the last register in the range into Last value key, which would cover the First-Last range. And if you want a specific value to be read from MSR, you can add it as Value.

What is however more important in our case is that any MSR override added this way will also ignore all writes into that MSR – and this is exactly what we need, as VirtualBox has this register marked as read-only.  So to override it,  run the following code:

VBoxManage setextradata VM “VBoxInternal/CPUM/MSRs/MsrBiosSign/First” 0x0000008B

Now the Guru Meditation error is gone, and boot process will continue.

If you run Mavericks, you must also disable the audio in your VM configuration. Then the machine will load all the way to the installation UI, which will crash. Did not investigate it further.

If you run Yosemite, the next crash would be still during the kernel load, and will crash in in _ccsha256_vng_intel_avx1_compress function, which is likely related to SSE3/AVX instructions your CPU doesn’t have, and VirtualBox won’t emulate.

If you want to rebuilt and/or debug VirtualBox:

  • Configure it with ./configure –enable-vnc –disable-java –enable-vde -d –disable-hardening –disable-docs –nofatal –ose
    • Note that -d and –disable-hardening are mandatory
  • Build with source; kmk
  • If you have a different version from the one you running, you need to rebuild/reload the kernel module as well.
  • The output binary would only start under root, even though your VirtualBox runs under user. It is normal.

When debugging:

  • Keep in mind that a lot of VirtualBox code is shared between kernel and userspace; the userspace component loads the binary blob into kernel via ioctl. This means code such as if ( something ) asm ("int $3"); cannot be used, and your logging might not go into the log file. Prefix the code with #ifdef IN_RING3 … #endif to limit it into the userspace component.
  • If your VirtualBox crashes in its kernel module (as a result of you screwing up with the above), it will not be able to load the blob, and this will result in some strange errors such as your changes not working, or VM refuses to start. Keep a dmesg -w opened in a separate window to look up for in-kernel crashes, and if happen, unfortunately you have to reboot.
This entry was posted in Linux, virtualbox.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.