Build from source
$ git clone https://git.qemu.org/git/qemu.git
$ cd qemu
$ mkdir -p build && cd build
$ ../configure --target-list=x86_64-softmmu
$ make -j$(nproc)
Add user to kvm
group and qemu
binaries to path
$ sudo usermod -aG kvm $USER
$ echo -e "export PATH=$PATH:$HOME/qemu/build/:$HOME/qemu/build/x86_64-softmmu/" | tee -a $HOME/.profile
NOTE
A re-login is necessary for the changes to be applied.
Create disk image
$ qemu-img create -f qcow2 vmdisk.qcow2 30G
Start installation
$ wget --trust-server-names --content-disposition https://download.fedoraproject.org/pub/fedora/linux/releases/35/Server/x86_64/iso/Fedora-Server-netinst-x86_64-35-1.2.iso
$ qemu-system-x86_64 -enable-kvm -m 8G -smp 8 -vga none -nographic -net nic,model=virtio -net user -drive file=vmdisk.qcow2 -cdrom Fedora-Server-netinst-x86_64-35-1.2.iso -serial mon:stdio
NOTE
Some distributions, like Fedora, will attempt to use a graphical installer. To avoid that, force usage of the serial console. Using -serial mon:stdio
, the guest is provided access to a virtual serial device which redirects everything to the host console. Edit the grub
entry that starts the installation and append console=ttyS0
to force the installer to continue in text mode. For more verbosity, add earlyprintk
and remove quiet
.
NOTE
Avoid using lvm
partitioning to avoid complexities with running custom kernels in the guest.
Start guest
$ qemu-system-x86_64 -enable-kvm -m 8G -smp 8 -vga none -nographic -net nic,model=virtio -net user -drive file=vmdisk.qcow2 -serial mon:stdio
NOTE
All this does is remove the -cdrom
option as installation media is no longer required.
Start guest
$ qemu-system-x86_64 -enable-kvm -m 8G -smp 8 -kernel linux/arch/x86/boot/bzImage -append "root=/dev/vda2 ro console=ttyS0" -vga none -nographic -net nic,model=virtio -net user -device virtio-blk-pci,drive=vmdisk -drive file=vmdisk.qcow2,if=none,id=vmdisk -serial mon:stdio
NOTE
An initrd
will not be used here. So make sure that all important modules are built into the vmlinux
binary i.e. CONFIG_...
is set to y
instead of m
. A good starting point is to capture lsmod
output within the guest, save that to lsmod.txt
on the host, and use that to create the custom kernel's .config
.
$ make LSMOD="lsmod.txt" localyesconfig
NOTE
For network and disk access, CONFIG_VIRTIO_NET
and CONFIG_VIRTIO_BLK
must be set to y
instead of m
.
NOTE
SeaBIOS expects the bzImage
as the payload for -kernel
.
$ make -j$(nproc) vmlinux bzImage