Depending on circumstances, a number of different techniques can be used for building virtual machines.
Traditional virtual-machine monitors (VMMs) rely on an architectural separation between system state and user state. Any attempt to read or modify system state (via what is called a sensitive instruction) causes a fault that can be caught by the VMM. The VMM can then emulate the change to system state and then cause the guest to continue. This approach is called full (or pure) virtualization. Full virtualization is possible if all of the machine's sensitive instructions are privileged, i.e., cause a trap when executed in unprivileged mode.
Unfortunately, most contemporary architectures are not fully virtualisable. Furthermore, full virtualization can be very expensive, as each privileged instruction causes an expensive trap into the hypervisor (essentially a system call). It is therefore desirable to minimise the number of such traps.
Some VMMs (e.g. VMware) virtualise the OS on a non-virtualisable architectures by scanning the OS binary at load time and replacing sensitive instructions on-the-fly with instructions that will trap. This approach achieves the effect of full virtualization, by allowing an unmodified OS (executable on bare hardware) to run on the virtual machine without (visible) changes.
Unfortunately, writing a binary instruction recogniser is fairly hard; transparently replacing parts of the binary is difficult for many instruction sets.
Virtualization also requires emulating devices, or allowing pass-through access to them. The result is relatively slow, because every privileged operation traps to the VMM.
Para-virtualization is a pragmatic approach to achieving a high-performance virtual machine on non-virtualisable hardware: Modify the guest operating system source by replacing all sensitive instructions by explicit hypervisor calls (hypercalls), or direct access to virtualised resources. This also allows overcoming performance problems associated with pure virtualization, at the expense of more invasive changes to the guest OS source.
Para-virtualization buys this increased efficiency at the expense of a change of the machine interface (architecture). The virtual machine is no longer a faithful replica of the real machine. This means that software will behave differently, reducing the value of virtualization to a degree. In particular, this also means that a para-virtualised guest OS will only run on one particular hypervisor, and no longer on bare hardware.
Para-virtualization requires that at least the OS will have to be explicitly ported to the VMM, as to a separate architecture. This manual replacement of sensitive instructions by hypercalls is obviously cumbersome, expensive and error-prone. It implies significant up-front as well as on-going engineering cost.
Disabling or enabling interrupts on Itanium
involves flipping a bit in the processor status register (PSR).
If the VMM provides a memory location that represents the
virtual PSR, the
rsm psr.i instruction can be
replaced with instructions that flip the I bit in the virtual
PSR. The VMM then can look at the virtual PSR when it wants to
deliver a virtual interrupt, to see if it is able to.
A paravirtualised system can gain performance by using higher-level constructs. For example, instead of changing five region registers one at a time to switch address spaces, it could make a hypervisor call to switch address spaces, changing all in one fell swoop.
Devices can be handled in one of three ways:
This of course does not allow sharing of the device between multiple concurrently running guests.
Pre-virtualization is a new approach that overcomes the drawbacks of para-virtualization without sacrificing the performance advantages it has over pure virtualization; it is in a sense the best of both worlds. Pre-virtualization is an automated way of para-virtualising an OS, while achieving the faithful architecture replication of pure virtualization.