Operating System Emulation on Raspberry Pi 5
The Raspberry Pi 5 is a remarkably useful small host for historical operating-system work, but “run another OS” describes several very different techniques. Its 64-bit ARM (AArch64) Cortex-A76 processor can virtualize an ARM64 guest efficiently when the kernel and firmware expose KVM. It can also use QEMU to emulate a PC or another machine whose processor has a different instruction set, such as x86, but that second job is software CPU emulation and is much slower. A good project starts by naming the guest architecture, the intended software, and whether the purpose is learning, preservation, testing, or a daily service. It does not start by assuming that any ISO can be made fast on any board.
What the Pi 5 can actually host
Raspberry Pi 5 is an ARM64 host with four 2.4 GHz Cortex-A76 cores, VideoCore VII graphics, USB 3 storage options, and a PCIe connection that can be used with appropriate NVMe hardware. Raspberry Pi OS 64-bit is a sensible baseline because it uses the host’s native architecture and has current kernel and package support. Memory capacity, cooling, storage latency, and the particular guest matter at least as much as clock speed. A Pi configured with too little free RAM or a worn microSD card is not made dependable by choosing an emulator with more switches.
KVM is Linux’s in-kernel virtualization interface. In the same-ISA case, the guest’s ordinary CPU instructions run on the host CPU while QEMU provides virtual devices, RAM layout, firmware hand-off, display, and I/O. Thus an ARM64 Linux guest on an ARM64 Pi 5 can be a practical lightweight VM. KVM is not an accelerator for an x86 guest on an ARM host: ARM hardware cannot directly execute x86 instructions. QEMU then uses its Tiny Code Generator (TCG) to translate guest instructions into ARM instructions at run time. That cross-ISA path is emulation, and performance, especially for CPU-heavy or graphics-heavy software, is limited.
| Goal | Typical tool and mode | Pi 5 expectation |
|---|---|---|
| ARM64 Linux appliance or test machine | qemu-system-aarch64 with KVM, if /dev/kvm is available | Usually the best VM use case; modest server and desktop guests are realistic. |
| Vintage x86 PC, DOS, early x86 Linux/BSD | qemu-system-i386 or qemu-system-x86_64 with TCG | Excellent for patient experimentation; expect far less than native PC speed. |
| One foreign-architecture command-line program | QEMU user-mode, such as qemu-x86_64 | Useful for builds or inspection; it is not a complete virtual PC. |
| DOS software and selected Windows 3.x/9x-era software | DOSBox-X | Convenient compatibility environment, not a general modern PC VM. |
| Some x86 Linux applications on ARM64 Linux | Box64 plus compatible libraries; Wine where applicable | Translation/compatibility, not an x86 operating-system emulator. |
Full-system emulation is different from user mode
QEMU system emulation creates a whole virtual machine. A command such as qemu-system-i386 models an x86 machine with a CPU, chipset-like devices, disk controller, NIC, display adapter, and firmware; it can boot a guest installer ISO. QEMU has separate system executables for supported machine families, commonly including qemu-system-aarch64, qemu-system-arm, qemu-system-i386, qemu-system-x86_64, qemu-system-mips, qemu-system-ppc, and qemu-system-riscv64. Installed target names vary by distribution, so inspect them rather than guessing:
uname -m
find /usr/bin -maxdepth 1 -type f -name 'qemu-system-*' -printf '%f\n' | sort
qemu-system-aarch64 --version
test -r /dev/kvm && test -w /dev/kvm \
&& echo 'KVM device is readable and writable' \
|| echo 'No usable KVM access for this user'
QEMU user-mode emulation instead runs a foreign executable as a Linux process. It translates that program’s CPU instructions and passes compatible Linux system calls to the host kernel; it needs an appropriate foreign userland, dynamic loader, and libraries. It does not emulate firmware, bootloaders, a disk controller, or a complete foreign kernel. It is valuable with a container/chroot or cross-build workflow, but it cannot boot DOS or test an x86 kernel. Do not confuse a successful qemu-aarch64 or qemu-x86_64 command with proof that a full guest will run.
Establish the host safely
Begin with a fully updated supported 64-bit Raspberry Pi OS installation, reliable storage, the official 27 W USB-C power supply or an equivalently specified supply, and active cooling. Sustained translation or compilation can heat the Pi enough to reduce clocks; fit the official Active Cooler or a well-designed case fan and leave ventilation clear. Use an SSD over USB 3 or a correctly installed NVMe HAT for active VM images when possible. A quality microSD card is fine for learning, but intensive guest writes, snapshots, and sudden power loss are harsh on it.
These commands inspect the machine and package catalogue without changing boot firmware or deleting data:
uname -m
cat /etc/os-release
vcgencmd measure_temp
vcgencmd get_throttled
df -hT
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINTS
apt-cache search '^qemu-system'
apt-cache policy qemu-system-arm qemu-utils libvirt-daemon-system
vcgencmd get_throttled is Raspberry Pi-specific; consult Raspberry Pi’s documentation for the bit meanings rather than treating a nonzero result as a harmless curiosity. Before installing packages, identify the boot disk in lsblk, reserve free host space, and back up important files. On Raspberry Pi OS releases that offer them, packages commonly include qemu-system-arm, qemu-system-misc, qemu-utils, and optional libvirt components. Use apt-cache show to confirm what a package supplies, then install only the targets needed. Repository split and package names can change.
sudo apt update
sudo apt install qemu-system-arm qemu-utils
The two commands above are a deliberately small starting point for ARM system emulation and image tools, not a universal recipe for x86, RISC-V, or libvirt. Review the package transaction before accepting it. Never run raw device-writing commands from a VM tutorial against a disk you have not identified; creating a guest disk image is safer and sufficient for nearly every first experiment.
Firmware, boot paths, and storage images
A guest needs firmware suited to its emulated machine. Traditional x86 guests normally expect a BIOS-compatible firmware; many modern x86 guests expect UEFI, commonly OVMF. ARM virtual machines commonly use UEFI builds derived from EDK2/AAVMF, although some board models boot a kernel directly or follow board-specific firmware conventions. A Pi board’s own EEPROM boot firmware is not interchangeable with guest UEFI firmware. Select the firmware described by the QEMU machine and guest documentation, and keep a copy and version note with the VM. Secure Boot only helps when the guest’s signed boot chain and enrolled keys are deliberately configured; it is not a generic compatibility toggle.
A raw image is a straightforward virtual disk file. A qcow2 image supports sparse allocation, backing files, and QEMU snapshot features, at the cost of more bookkeeping. Create project directories on the SSD, not in a random system directory, and inspect images before changing them:
mkdir -p "$HOME/vm-lab/images"
qemu-img create -f qcow2 "$HOME/vm-lab/images/arm-lab.qcow2" 20G
qemu-img info "$HOME/vm-lab/images/arm-lab.qcow2"
du -h "$HOME/vm-lab/images/arm-lab.qcow2"
df -h "$HOME/vm-lab/images"
The 20G figure is virtual capacity, not a claim about current host consumption. A sparse image can grow until the host filesystem is full. Do not delete, rename, or move a base image while an overlay/backing chain refers to it. Use qemu-img info --backing-chain to inspect relationships. For a dependable backup, shut the guest down, preserve its disk image, firmware-variable file if used, and launch/libvirt definition together, then test a restore. A snapshot is a rollback convenience that still depends on its parent image; it is not an independent backup.
A practical ARM64 KVM guest
First confirm KVM availability. On a normal bare-metal Pi 5 with a suitable kernel, /dev/kvm may be present; in a container, restricted account, or nested virtual Pi it may not be. The following inspection does not attempt to load modules or alter boot settings:
ls -l /dev/kvm
id
lsmod | grep -E '(^kvm|kvm_)' || true
qemu-system-aarch64 -accel help
If access is unavailable, use TCG for a small ARM guest or fix the platform support through Raspberry Pi OS and kernel documentation. Do not add an account to broad privileged groups blindly. When KVM is usable, an ARM64 guest can use -accel kvm and a matching virtual CPU model. QEMU’s virt machine is a generic virtual ARM platform, not an emulation of the Pi 5 board; software needing Raspberry Pi GPIO, VideoCore, HATs, or board firmware should run on the host or real hardware rather than expecting a generic VM to provide them.
Use a current ARM64 installer image whose checksum and signature you have verified from its publisher. Start with two virtual CPUs, modest RAM, a virtio disk and virtio network where the guest supports them, and a serial console for a server. An illustrative shape is qemu-system-aarch64 -machine virt,accel=kvm -cpu host -m 2048 -smp 2, but it deliberately omits the distribution-specific UEFI path, installer ISO, disk, and networking arguments. Copying an incomplete command is less safe than reading qemu-system-aarch64 -machine help, -device help, and the guest distribution’s ARM virtualization notes. Graphical ARM guests also need a deliberately selected display device and input setup; a serial install is easier to diagnose on a headless Pi.
x86, DOS, and the limits of translation
For an x86 operating system, select an x86 QEMU system target and accept TCG. An early text-mode Linux, 386BSD-era-style research exercise, or small DOS installation is historically appropriate. Give it an emulated disk, compatible IDE-like storage and legacy NIC/display only when the guest lacks virtio drivers. Favor 32-bit x86 for old software that actually requires it; emulating an x86-64 PC merely to install a large contemporary desktop increases CPU, RAM, disk, and graphics demands. QEMU’s TCG can be impressively functional, but booting and compiling are commonly slow, and software rendering is not a substitute for a modern discrete PC GPU.
DOSBox-X is often the friendlier answer for a DOS application, game, or an exploratory Windows 3.x and selected Windows 9x-style environment. It provides an emulated DOS-oriented PC environment with configuration aimed at that era. It is not a general-purpose PC hypervisor, is not an x86 Windows 10/11 solution, and should not be described as one. Its emulated hardware, drivers, installer expectations, and compatibility goals differ from QEMU. Choose DOSBox-X when the target fits its documented vintage scope; choose QEMU system emulation when you need to study a boot sequence, disk controller, firmware choice, or a complete machine model.
Box64 translates many x86-64 Linux user-space programs for ARM64 Linux, and Wine implements Windows API compatibility for Windows applications. A Box64/Wine combination may make a particular program practical, but it is neither a full x86 PC nor a bootable Windows guest. Driver-dependent software, kernel components, anti-cheat, proprietary launchers, and graphics stacks can fail. Test a legally obtained program in an isolated user account or lab first. It is especially important never to promise usable modern x86 Windows performance on a Pi 5: cross-ISA CPU work, GPU/API translation, memory pressure, and unsupported drivers make that an unrealistic design target.
Headless operation, graphics, and networks
A headless guest saves host graphics resources and is ideal for an ARM Linux server, early Unix-like system, or installer with a serial console. Use a local terminal multiplexer, QEMU’s serial monitor, or a carefully access-controlled SSH path. A graphical guest is appropriate when the period software truly needs it, but start at modest resolution and color depth. QEMU emulated VGA/SVGA output is not GPU passthrough, and cross-ISA 3D acceleration on this platform is a poor baseline. Keep the Pi’s desktop responsive by leaving memory and CPU headroom instead of assigning every core and nearly all RAM to one VM.
Networking should begin with the narrowest useful exposure. QEMU user-mode networking/NAT lets a guest make outbound connections without placing an obsolete guest directly on the household LAN. An isolated network, or no NIC at all, is best for DOS and unpatched legacy systems. Bridging makes a guest a peer on the LAN and should be a conscious choice, not a cure for a connectivity problem. Do not forward guest SMB, web, remote-desktop, or vintage services from a router to the Internet. Exchange files through a small, scanned, read-only staging directory or a temporary virtual ISO; treat files originating in a legacy guest as untrusted.
libvirt is optional, not guaranteed
libvirt can manage QEMU domains, storage pools, virtual networks, snapshots, and remote administration, while virt-manager is a graphical client. It can make several ARM guests repeatable, but availability and polish on Raspberry Pi OS depend on the release, repository, architecture packages, system services, polkit rules, and whether KVM is accessible. A package being searchable does not guarantee that every GUI workflow or firmware integration is supported. Check first with apt-cache policy libvirt-daemon-system libvirt-clients virt-manager and, after an intentional installation, virsh -c qemu:///session list --all. Prefer a direct QEMU command for one learning machine; adopt libvirt when its management benefits outweigh its extra layer.
Experiments worth doing
- DOS laboratory: install FreeDOS or another lawfully obtained DOS release in DOSBox-X, mount a dedicated transfer directory read-only at first, and compare conventional-memory settings for a small utility.
- Early x86 system: boot a lawfully obtained early Linux or BSD installer under
qemu-system-i386; document the selected CPU, RAM, disk controller, BIOS, and elapsed install time. Keep it offline unless an isolated lab specifically needs networking. - Native-ISA comparison: install a small ARM64 Linux guest on QEMU’s
virtmachine with KVM, then repeat a CPU-bound command under TCG. This demonstrates virtualization versus emulation without pretending it is a Pi-board emulator. - Other architectures: boot a historically appropriate RISC-V, MIPS, PowerPC, or ARM image in the corresponding QEMU system target, using serial console output. Begin with vendor or project test images and documentation, not an arbitrary desktop ISO.
- Recovery drill: make a powered-off copy of one qcow2 guest and its configuration, intentionally test it in a separate directory, and confirm that your backup is bootable.
Install operating systems, firmware, BIOS images, and application media only from sources you are licensed or otherwise legally entitled to use. Copyright, firmware extraction, and license-transfer rules vary by product and jurisdiction. Freely licensed systems such as Raspberry Pi OS, Debian, Fedora, FreeBSD where supported, and FreeDOS are excellent test media; verify their published checksums. Preserve a note of source URL, version, checksum, disk format, firmware, QEMU version, and network mode with each experiment.
Authoritative references
- Raspberry Pi 5 documentation — power, cooling, storage, and board capabilities.
- QEMU documentation — system targets, TCG, KVM acceleration, networking, and image tools.
- Linux kernel KVM documentation — the kernel virtualization interface and architecture-specific support.
- libvirt documentation — QEMU domain, storage, and network administration.
- DOSBox-X wiki and Box86/Box64 project resources — intended compatibility scope and configuration.
dispelled