This is an esoteric topic that might be of interest to people implementing Intel hypervisors. It assumes you know the basics of the Intel virtualization architecture, see Hypervisor from scratch for a tutorial. The actual full VT architecture is described in Volume 3 of the Intel SDM
Let’s say we write an x86 hypervisor that starts in the UEFI environment and virtualizes the the initialization phase of an OS. But the hypervisor wants to quit eventually to not cause extra overhead during OS run time.
The way the hypervisor works is that it runs in its own memory and with its own page tables which are switched atomically on every VM exit by the VT-x implementation. This way it is isolated from the main OS.
At some exit with the hypervisor running in its own context it decides that it is not needed anymore and wants to quit. To disable VT support the VMXOFF instruction can be used. But what we really need is an atomic VMXOFF + switch to the original OS page plus a jump, and all that without using any registers which need to be already restored to the original state of t
4 Comments
mrnage
Mirror: https://web.archive.org/web/20250321190516/https://halobates…
userbinator
This reminds me of DOS-based Windows which would need to get out of the V86 mode that EMM386 used before going into protected mode itself; a task which was done using the undocumented (at the time) GEMMIS interface.
snvzz
Awful.
Fortunately, we won't have to suffer x86 much longer.
gblargg
Fun stuff. Reminds me of writing code to restore a state snapshot for a sound module with its own processor. It had four byte-wide shared I/O registers in a row. After restoring almost all memory, I put a two-byte infinite-loop branch instruction in the last two bytes and had the sound CPU jump to it, loaded a 1- or 2- byte instruction in the first two bytes, then modified the branch offset to execute this instruction as part of the loop, let it run a few times, then modified the offset to just be a single-instruction loop. I did this multiple times to execute each instruction needed to finish loading memory, restore all registers, and finally jump to the execution address with everything restored.