How virtualization framework works internally

Hello,

I am trying to understand how macOS virtualization framework and Virtualization products work on M1 chips.

I have tried Parallels Desktop. There are no third party kernel extensions (kext) installed with this product. When i plug an USB device on my mac, i get a popup asking me if i want to plug this device to my host mac or to the current Parallels virtual machine. How can this be possible without kext ? Device management is handled at kernel level... and there are no virtualization framework API for that...

I have create a Linux virtual machine with Virtualization framework (similar to GNULinuxVirtualMachineSampleApp project):

  • It works but I don't understand why i can't run Windows Virtual machines. Parallels Desktop seems to work with Virtualization framework too and this product can run ARM Windows Virtual Machine. How can they do that ?
  • Is there a way to simulate key sending with Virtualization framework ?
  • I have create a 64Gb disk (VZDiskImageStorageDeviceAttachment). I have a 64Gb file on my host mac, but i am using only 10Gb on the virtual machine at this moment. Is there a way to optimize the disk image file size ?
  • VZVirtualMachine provides a "pause" method. I don't understand where the virtual machine state (RAM memory, ...) is saved on the host.

Thanks a lot

Replies

There are multiple frameworks at different levels of abstractions in macOS:

  • Hypervisor framework is a low level framework to provide abstractions for CPU (vCPU) and memory (intermediate physical address).
  • IOUSBHost framework is a low level framework to capture USB devices.
  • vmnet framework is a low level framework that abstract networking operations for virtual machines.
  • Virtualization framework is a high level framework that provides abstraction for complete virtual machine, with all the hardware emulation, CPU emulation, etc

Developers are building apps on top of Hypervisor, Virtualization or both, to provide various level of integration, features, and performance.

Is there a way to simulate key sending with Virtualization framework?

Injecting events in the VZVirtualMachineView should work like any other view.

I have create a 64Gb disk (VZDiskImageStorageDeviceAttachment). I have a 64Gb file on my host mac, but i am using only 10Gb on the virtual machine at this moment. Is there a way to optimize the disk image file size ?

APFS files are sparse so you have to look at the actual disk usage for that file. If you open the file information for a file, it will indicate the logical size, and the size on disk. If there are only 10Gb of space actually used, the file would use 10Gb on disk despite having a logical size of 64Gb.

Virtualization framework always uses sparse APFS files if the guest OS issues the trim/unmap commands. There is no configuration needed.

VZVirtualMachine provides a "pause" method. I don't understand where the virtual machine state (RAM memory, ...) is saved on the host.

The "pause" method suspends the execution of the virtual machine. It does not save it on disk. When paused, the virtual machine doesn't use the CPU to execute the guest, and it can be resumed as needed.

To save the state of a paused virtual machine to disk, you can use saveMachineStateTo: https://developer.apple.com/documentation/virtualization/vzvirtualmachine/4168516-savemachinestateto. As of macOS Sonomac 14.0, that API doesn't support the Virtio GPU used by GUI Linux.

Saving and restoring a live virtual machine is covered in "Create seamless experiences with Virtualization"..

I hope this helps!

  • Hello, i don't agree about APFS: For example, i can't create a 2 Tb empty dmg file with disk utility application. If i create a 64Gb file it takes a lot of time and i think disk utility is writing 64Gb of bytes on disk. Is there another filesystem or tool that can optimize disk space ?

    Thanks

  • The dmg file you create with disk utility is a different kind of disk image.

    The disk images used by VMs are just RAW files. Here is an example:

    "% truncate -s +1000G empty_file"

    "% ls -l empty_file --- 1073741824000 --- empty_file"

    "% du -hs empty_file 0B empty_file"

Add a Comment

Thanks a lot !