Developer Stjepan Poljak has documented how to boot a Linux kernel on 64-bit x86 systems from his Rust-based virtualization project, using Xen’s PVH boot protocol. This approach simplifies part of the operating system startup process, allowing him to advance his KVM-based virtual machine implementation without first reproducing the entire boot sequence of a conventional BIOS.

The key facts about PVH boot on x86 in 20 seconds

  • Stjepan Poljak has extended his Rust virtualization project, which already booted Linux on ARM64, to support x86.
  • The approach uses PVH, a Xen protocol that simplifies kernel entry in a virtual machine.
  • KVM allows specific registers and virtual CPU segments to be configured directly.
  • The kernel needs information about its entry point, the memory map and boot parameters.
  • The x86-64 initialization code is available on GitHub.

The work highlights one of the challenges involved in developing a hypervisor or virtual machine monitor (VMM) from scratch: booting a kernel is not simply a matter of loading a file into memory and jumping to an address. The environment must provide the CPU state expected by Linux, describe the available memory and supply the parameters the operating system needs during its earliest instructions.

In notes published on September 25, 2026, Poljak explains that he had previously tried to use Linux’s traditional boot protocol through the boot_params structure. Finding that approach too complex for obtaining initial results, he turned to PVH, an alternative that reduces some of the work required from the virtualization software.

Why PVH simplifies Linux boot

On a conventional x86 machine, the processor begins execution at the reset vector, located at physical address 0xFFFFFFF0. From there, firmware takes control and participates in preparing the boot environment. In a classic BIOS boot process, the firmware can load the first sector of a bootable device, check its signature and transfer execution to the initial code, which continues preparing the system.

That code typically starts in 16-bit real mode. To reach 32-bit protected mode, it must prepare, among other things, a Global Descriptor Table (GDT), disable interrupts during the transition and set the appropriate bit in the CR0 control register. A far jump then loads the appropriate code selector.

If the operating system is going to run in 64-bit mode, additional preparation is required for the processor state and paging. In a custom virtualization project, reproducing all these stages can become a substantial task before the kernel even starts executing.

PVH provides a different route. Originating in Xen, the protocol allows virtualization software to give Linux a defined initial environment without fully imitating the traditional firmware and bootloader sequence. In the procedure described by Poljak, the kernel initially enters a 32-bit protected-mode state and performs the transition to 64-bit mode itself.

This is useful for a KVM-based VMM. Rather than building the entire boot infrastructure of a physical machine from scratch, the developer can prepare part of the virtual CPU state directly and provide the kernel with the information required by the PVH interface.

That does not eliminate initialization work. Instead, it shifts the responsibility toward explicitly configuring registers, segments, memory and the structures required by the protocol.

What information does the kernel need to boot through PVH?

The first step is to determine whether the Linux kernel’s ELF image supports the protocol. Poljak explains that this involves inspecting Xen ELF notes and locating XEN_ELFNOTE_PHYS32_ENTRY, note type 18. Its descriptor contains the physical 32-bit entry point at which the guest must begin execution.

Kernels that support PVH relocation may also include XEN_ELFNOTE_PHYS32_RELOC, note type 19. This note describes alignment and physical-address constraints that must be respected when loading relocatable PVH kernels.

Once the entry point has been identified, the VMM must prepare memory and the structures Linux will receive. Poljak’s procedure includes:

  • Loading the kernel’s ELF segments into memory.
  • Copying the kernel command line to an accessible address.
  • Building a memory map using HvmMemEntry entries.
  • Creating and populating the HvmStartInfo structure.
  • Placing the memory entries and startup structure in guest memory.
  • Loading the initramfs, when used, together with its command line and an HvmModuleEntry entry describing its location.

The memory map tells the kernel which memory regions are available. HvmStartInfo contains information required for PVH startup, while HvmModuleEntry identifies the initial module supplied to the operating system. Here, the term module refers to the Xen modules defined by the protocol, not Linux kernel modules loaded later. For Linux, the relevant example is the initramfs.

These structures form part of the interface between the hypervisor and the kernel. If an address, size or initialization field does not match what Linux expects, the boot process can stop before the operating system initializes its usual subsystems.

KVM allows the virtual CPU state to be configured directly

Another important part of the implementation is preparing the processor’s registers and segments. Poljak states that RIP, the register identifying the next instruction to execute, must point to the entry obtained from ELF note type 18. The RBX register must contain the physical address of HvmStartInfo, as required by the PVH protocol described in his notes.

The segment registers must also be prepared to represent a valid protected-mode state. In a conventional boot process, the descriptors would reside in a GDT stored in guest memory, and the processor would obtain each segment’s attributes by loading its selector.

With KVM, the developer can set much of this state directly through the virtual CPU interfaces. The published code uses the kvm_segment structure and the KVM_SET_SREGS operation to configure the segments without reproducing the entire process of loading a GDT inside the virtual machine.

The example includes a code segment with selector 1 << 3, a data segment with selector 2 << 3, and a task register (TR) configured with a limit of 0x67, following the requirements that the author attributes to Xen’s PVH protocol. It also specifies attributes such as privilege level, address size, granularity and access permissions.

The initialization covers other registers as well. Poljak states that the PE bit in CR0 must be enabled, that CR4 is initialized to zero in his implementation, and that specific RFLAGS bits, including VM, IF and TF, must be cleared for the initial state described. These values are part of his specific VMM initialization and should not be treated as a universal boot recipe for every x86 configuration.

The technical reference for the startup structures is available in Linux’s Xen-related headers, while the kernel’s own source code documents the register setup performed during PVH entry. Together, these sources help connect the virtual machine’s initialization to the environment Linux expects to receive.

Another step forward for the Rust-based hypervisor

Poljak’s project could already boot Linux on ARM64 and now includes an initial boot path for 64-bit x86. The implementation is published in the kvm-rust repository, in the architecture-specific x86 initialization file. The author notes that substantial functionality remains to be implemented on the x86 side of the VMM.

The article does not describe a finished hypervisor or a complete implementation of Linux’s traditional boot process. Its contribution is to demonstrate how PVH can be used to reach the kernel’s entry point and establish a working foundation for further virtualization development.

For developers working on hypervisors, emulation or operating systems, this approach reduces the initial scope of the problem. Instead of implementing every stage of a physical machine’s boot process first, they can rely on a defined interface to prepare the virtual CPU and the memory structures Linux needs.

The code also provides a practical example of how Rust, KVM interfaces and the Xen protocol interact during system initialization.

Frequently asked questions

What is PVH in Linux?

PVH is a boot protocol originating in Xen that defines how to provide the kernel with an initial CPU state and the information it needs to begin executing inside a virtual machine.

Why use PVH in a KVM project?

It simplifies part of the boot process compared with reproducing the entire traditional BIOS and bootloader path. The VMM still needs to prepare the registers, memory map and startup structures.

What are Xen ELF notes used for?

The XEN_ELFNOTE_PHYS32_ENTRY note, type 18, identifies the kernel’s physical 32-bit entry point. Note type 19 can describe alignment and physical-address constraints for relocatable PVH kernels.

Where is the implementation code available?

The x86-64 initialization code is available in the project’s kvm-rust GitHub repository: https://github.com/StjepanPoljak/kvm-rust/blob/main/src/arch/x86_64/init.rs

Scroll to Top