QEMU is an indispensable tool for the virtual machine inclined. It's a command line utility for running virtual machines.
Main documentation: https://www.qemu.org/docs/master/system/
Example Flags
Run a 64 bit Intel / AMD system
qemu-system-x86_64 ...
KVM
Without KVM your VM will be VERY VERY VERY slow. You'll want to enable this.
-enable-kvm
Make sure your use account has access to /dev/kvm
, use chown
to make the
group kvm
, and add your user to that group. You'll need log out and log back
in for changes to take effect. Or run bash --login
.
$ groupadd kvm
$ sudo usermod -aG kvm $USER
$ ll /dev/kvm
crw-rw-rw- 1 root root 10, 232 Jul 22 12:10 /dev/kvm
$ chown root:kvm /dev/kvm
$ ll /dev/kvm
crw-rw-rw- 1 root kvm 10, 232 Jul 22 12:10 /dev/kvm
Multiple CPUs
-smp cpus=4
More detailed
-smp sockets=1,cpus=4,cores=2 -cpu host
Memory
-m 8192M
Networking - NAT
-netdev user,id=mynet0 \
-device virtio-net-pci,netdev=mynet0
You can also do what's known as "bridged" networking. It can be a bit of a mess though. It's covered in the main QEMU documentation at the top.
TODO Cover bridged networking
USB
You may want to give a VM control over a USB device, such as a USB NIC.
Creating a ehci device and attaching the usb device to it is important!
Use lsusb -v
to find the idProduct (productid) and idVendor (vendorid)
-usb \
-device usb-ehci,id=ehci \
-device usb-host,bus=ehci.0,vendorid=0x0424,productid=0xEC00
Share small files
-virtfs local,path=$PWD/share,mount_tag=host0,security_model=mapped-file,id=host0
Fast Random Number Generator
-device virtio-rng-pci
Port Forwarding
-net \
user,hostfwd=tcp::2222-:22,hostfwd=tcp::4444-:2222
Guest Image
For a raw .img
or .iso
-drive \
file="image.iso",if=virtio,aio=threads,format=raw
For a .qcow2
-drive \
file="image.qcow2",if=virtio,aio=threads,format=qcow2
Kernel
Boot directly to a Linux kernel binary (skips some BIOS stuff)
-kernel \
"linux-source-tree/arch/x86/boot/bzImage"
Kernel cmdline
The root*
options here correspond to the
Host Filesystem Passthrough section.
-append \
"console=ttyS0 rootfstype=9p root=fsdev-root ro rootflags=trans=virtio,version=9p2000.u init=/usr/lib/systemd/systemd"
Disable GUI
-nographic
CPU Emulation
Specify host
to have QEMU not emulate another CPU, just use the host CPU.
-cpu host
Specify BIOS
You'll need this if you want to use UEFI
-bios \
"path/to/OVMF.fd"
BIOS Debugging Connection
-chardev \
pipe,path=qemudebugpipe,id=seabios \
-device \
isa-debugcon,iobase=0x402,chardev=seabios
Reference: https://www.seabios.org/Debugging#Debugging_with_gdb_on_QEMU
Host Filesystem Passthrough
Use a directory on the host as a filesystem for the guest.
This requires that the guest kernel has been configured with:
CONFIG_9P_FS=y
CONFIG_9P_FS_POSIX_ACL=y
CONFIG_9P_FS_SECURITY=y
CONFIG_NET_9P=y
CONFIG_NET_9P_VIRTIO=y
9P fs is buggy as all hell In particular, fsync seems to be broken.
-fsdev \
local,id=fsdev-root,path="${CHROOT}",security_model=passthrough,readonly \
-device \
virtio-9p-pci,fsdev=fsdev-root,mount_tag=/dev/root
Make sure you're using the corresponding kernel cmdline options.
Creating A Bootable UEFI Guest Image
Create qcow2
image
$ qemu-img create -f qcow2 image.qcow2 20G
Source of NBD commands: https://gist.github.com/shamil/62935d9b456a6f9877b5
Enable network block devices
$ sudo modprobe nbd max_part=8
Map the image file to the /dev/nbd0
network block device
$ sudo qemu-nbd --connect=/dev/nbd0 image.qcow2
Create GPT partition table (UEFI)
$ sudo parted /dev/nbd0 << 'EOF'
mklabel gpt
mkpart primary fat32 1MiB 261MiB
set 1 esp on
mkpart primary linux-swap 261MiB 10491MiB
mkpart primary ext4 10491MiB 100%
EOF
Format partitions
$ sudo mkfs.fat /dev/nbd0p1
$ sudo mkswap /dev/nbd0p2
$ sudo mkfs.ext4 /dev/nbd0p3
Unmount and disconnect
$ sudo umount -R /mnt/somepoint/
$ sudo qemu-nbd --disconnect /dev/nbd0
parted commands from: https://wiki.archlinux.org/index.php/Parted#UEFI/GPT_examples
CPU Hotplug
-smp 1,maxcpus=2 -qmp unix:/tmp/q,server,nowait
In another shell
$ sudo qemu/scripts/qmp/qmp-shell -p -v /tmp/q
Welcome to the QMP low-level shell!
Connected to QEMU 4.1.0
(QEMU) device_add id=cpu-2 driver=host-x86_64-cpu socket-id=1 core-id=0 thread-id=0 die-id=0
Back in your Linux guest you'll see
[ 51.190460] CPU1 has been hot-added
in the dmesg logs.
To initialize the CPU within the guest
# echo 1 > /sys/devices/system/cpu/cpu1/online
Reference: https://wiki.qemu.org/Features/CPUHotplug
Precompiled UEFI Firmware
https://cdn.download.clearlinux.org/image/OVMF.fd
UEFI_BIOS="-bios OVMF.fd"
if [ -f OVMF_VARS.fd -a -f OVMF_CODE.fd ]; then
UEFI_BIOS=" -drive file=OVMF_CODE.fd,if=pflash,format=raw,unit=0,readonly=on "
UEFI_BIOS+=" -drive file=OVMF_VARS.fd,if=pflash,format=raw,unit=1 "
fi