JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

Type 1 vs Type 2 and Trap-and-Emulate

Guide one sold you the dream of one machine pretending to be many. Now we open the hood: where the hypervisor actually sits (bare-metal versus hosted), the single beautiful trick — trap-and-emulate — that makes the illusion work, and the reason x86 spent twenty years being maddeningly hard to virtualize.

Where does the hypervisor sit? Type 1 vs Type 2

In guide one you met the hypervisor — the thin layer of software that hands each virtual machine its own fake hardware and keeps the guests from noticing each other. The very first question to ask about any real hypervisor is a question of seating: where in the software stack does it actually live? There are two answers, and the whole industry is organized around them. A type 1 hypervisor runs directly on the bare metal — it is the lowest layer of software on the machine, sitting right on the silicon where an ordinary OS would normally sit, with the guest operating systems stacked on top of it. A type 2 hypervisor runs as an ordinary program inside a normal host OS — your everyday Windows, macOS, or Linux boots first, and the hypervisor is just one more application running on it, with the guests nested one level deeper still.

Picture the difference as two ways to run a guest house. A type 1 hypervisor is a purpose-built apartment block: the ground floor is nothing but the building's own management — no tenant lives there, it exists only to allocate rooms — and every resident is a guest above it. A type 2 hypervisor is more like renting out the spare bedrooms of a house you already live in: the host OS is the family that occupies the place day to day, and the guests are squeezed into rooms the host lends them. The block is leaner and gives every guest more even, predictable service; the shared house is easier to set up because someone already lives there and you just install one more app.

The core trick: trap-and-emulate

Now the deep question. A guest OS thinks it owns the machine. It will try to do exactly the things a kernel does — disable interrupts, reload the page-table register, talk to a disk controller, switch into and out of privileged mode. But it must NOT really be allowed to, because that would let it stomp on the hypervisor and on the other guests. So how do you let a guest believe it is in charge while quietly stripping it of real power? The answer is one of the most elegant ideas in all of systems software, and it reuses a wall you already know intimately: dual-mode operation, the hardware split between user mode and kernel mode.

Here is the move, and it has a name: trap-and-emulate. Run the whole guest — including the guest's own kernel — down in user mode, the deprivileged level. Keep the real hypervisor as the only thing running in kernel mode. Now ordinary guest instructions (add two numbers, copy memory the guest already owns) just run straight on the real CPU at full native speed; nothing special happens, so there is almost no overhead. But the instant the guest kernel tries a privileged instruction — something only kernel mode is allowed to do — the hardware refuses, because the guest is really in user mode. That refusal is not a crash; it is a trap: the CPU jumps to the hypervisor, exactly the same mechanism a trap uses to enter a normal kernel. The hypervisor catches the trap, looks at what the guest was trying to do, performs that action on the guest's fake hardware (it emulates it), and hands control back. The guest never knows it was intercepted.

  guest kernel (running in USER mode)
        |  executes a privileged instruction
        v
  [ CPU sees user mode -> refuses -> TRAP ]
        |
        v
  hypervisor (KERNEL mode)
     1. catch the trap
     2. decode what guest meant to do
     3. emulate it on the guest's virtual hardware
     4. return -> resume guest right after the instruction
Trap-and-emulate: a privileged instruction in the deprivileged guest faults into the hypervisor, which mimics the effect and resumes the guest.

Why is this such a good design? Because the common case — the overwhelming majority of instructions — costs nothing at all; only the rare privileged ones pay the price of a trap. This is the same instinct as making a system call expensive but ordinary arithmetic free. Gerald Popek and Robert Goldberg made it precise back in 1974: a machine is cleanly virtualizable by trap-and-emulate only if every sensitive instruction (one that touches or reveals privileged machine state) is also a privileged instruction (one that traps when run in user mode). If that condition holds, the trap net catches everything dangerous. Hold onto that sentence — it is exactly the condition x86 broke.

Why x86 was historically hard

Trap-and-emulate is beautiful, but it only works if the hardware cooperates — and for decades the most popular hardware on Earth did not. The classic x86 instruction set, designed long before anyone cared about virtualization, contained a notorious set of about seventeen instructions that were sensitive but not privileged: they read or quietly changed privileged machine state, yet when run in user mode they did NOT trap. They just silently did the wrong thing. The textbook villain is the POPF instruction. In real kernel mode it can change the interrupt-enable flag; run the very same POPF in user mode and, instead of trapping so the hypervisor could step in, the CPU just ignored that part and carried on. The trap net had a hole in it, and dangerous instructions slipped straight through.

By Popek and Goldberg's rule, that single defect meant x86 was not cleanly virtualizable by trap-and-emulate at all. You could not simply deprivilege a guest and trust the traps to catch everything, because the worst instructions would not trap. For years this was taken as a flat impossibility — and then in 1998 a company called VMware found a way around it in pure software. Their trick was binary translation: instead of letting the guest's kernel code run directly and hoping it traps, the hypervisor scans the guest's instruction stream just ahead of execution and rewrites it on the fly. Every harmless instruction is left alone and runs at native speed; every one of those treacherous sensitive-but-not-privileged instructions is swapped out for a safe sequence that calls into the hypervisor instead. In effect, software manufactures the traps the hardware forgot to provide.

A subtle but important honesty: binary translation is not slow because translation is constant — most code is translated once and cached, then reused. The cost shows up elsewhere. Translated code is larger, the translator itself burns CPU and memory, and certain workloads (lots of system calls, lots of page-table changes) trigger far more hypervisor round-trips than native. So early software-only x86 VMs were impressively correct but carried a real, measurable tax. That lingering tax is exactly what the hardware fix in the next section was built to erase.

Three ways to virtualize: full, para, hardware-assisted

Step back and you can see the whole landscape as three answers to the same problem. Full virtualization is what binary translation gives you: the guest OS is left completely unmodified — it genuinely thinks it is on real hardware — and the hypervisor does whatever software gymnastics are needed to keep the illusion airtight. The headline benefit is that you can run an off-the-shelf, untouched OS, even one whose source you have never seen. The cost is the overhead we just described.

Paravirtualization takes the opposite bargain. Instead of fooling the guest, you let it in on the secret. With paravirtualization the guest OS is modified so that, wherever it would have executed an awkward privileged instruction, it instead politely makes an explicit call — a hypercall — straight to the hypervisor, the way a normal program makes a system call to the kernel. No traps to catch, no instruction stream to rewrite, no troublesome instructions to worry about, because the guest simply does not run them. The result is fast and clean. The price is honesty about a hard limit: you can only paravirtualize an OS whose source you can change. Xen made this famous; it is also why paravirtualized drivers (a cooperative fast path for disk and network) remain everywhere even on systems that are otherwise fully virtualized.

Hardware-assisted virtualization is the answer the chipmakers finally gave, and it has quietly made the other two debates almost moot. Around 2005-2006 Intel (VT-x) and AMD (AMD-V) added a brand-new, even-more-privileged operating layer to the CPU — often called root mode versus the guest's non-root mode. With hardware-assisted virtualization the guest kernel can finally run in its own genuine kernel mode (so unmodified OSes work, like full virtualization), yet the CPU automatically traps cleanly out to the hypervisor on exactly the events that matter — a so-called VM exit — closing the seventeen-instruction hole in the silicon itself. No binary translation, no guest modification. It is, in a sense, trap-and-emulate finally done right, with the hardware enforcing Popek and Goldberg's rule for you. Be honest about the catch, though: a VM exit and the matching VM entry are not free, so the new game became minimizing how often you have to take one.

Tying it together, and the honest caveats

  1. A program inside the guest makes a request that needs the guest kernel — say it calls read(fd, buf, n) to read a file.
  2. The guest kernel runs ordinary code at native speed, then reaches an instruction that touches privileged state (program the disk controller, change a control register).
  3. Control leaves the guest: on old x86 a binary-translated stub calls the hypervisor; on modern hardware the CPU takes a clean VM exit into root mode.
  4. The hypervisor emulates the intended effect against this guest's virtual hardware, isolated from every other guest and from itself.
  5. Control returns and the guest resumes exactly where it left off, none the wiser that it never owned the machine.

Notice what this guide has and has not covered. We have made the CPU virtualizable: the guest can run its own kernel and the hypervisor stays in control. But a real machine is more than a CPU. The guest also expects to manage memory — and the page tables it builds are themselves dangerous privileged state, so they need their own trap-and-emulate story (shadow page tables, then hardware nested page tables). It expects disks and network cards that do not physically exist. Those — virtualizing memory and I/O, and how a virtual machine can even be picked up and moved to another physical host while running — are the whole subject of the next guide. This one gave you the engine; the next one bolts on the wheels.