
This is one of those posts that s more for my own reference than likely to be helpful for others. If you re unlucky it ll have some useful tips for you. If I m lucky then I ll get a bunch of folk pointing out some optimisations.
First, what I m trying to achieve. I want a virtual machine environment where I can manually do tests on random kernels, and also various TPM related experiments. So I don t want something as fixed as a
libvirt setup. I d like the following:
- It to be fairly lightweight, so I can run it on a laptop while usefully doing other things
- I need a TPM 2.0 device to appear to the guest OS, but it doesn t need to be a real TPM
- Block device discard should work, so I can back it with a
qcow2
image and use fstrim to keep the actual on disk size small, without constraining my potential for file system expansion should I need it
- I ve no need for graphics, in fact a serial console would be better as it eases copy & paste, especially when I screw up kernel changes
That turns out to be possible, but it took a bunch of trial and error to get there. So I m writing it down. I generally do this on a Fedora based host system (FC40 at present, but this all worked with FC38 + FC39 too), and I run Debian 12 (bookworm) as the guest. At present I m using
qemu 8.2.2 and
swtpm 0.9.0, both from the FC40 packages.
One other issue I spent too long tracking down is that the version of grub 2.06 in bookworm does not manage to pass the
TPMEventLog
through to the guest kernel properly. The events get measured and the PCRs updated just fine, but
/sys/kernel/security/tpm0/binary_bios_measurements
doesn t even get created. Using either grub 2.06 from FC40, or the 2.12 backport in
bookworm-backports
, makes this work just fine.
Anyway, for reference, the following is the script I use to start the swtpm, and then qemu. The
debugcon
line can be dropped if you re not interested in OVMF debug logging. This needs the guest OS to be configured up for a serial console, but avoids the overhead of graphics emulation.
As I said at the start, I m open to any hints about other options I should be passing; as long as I get acceptable performance in the guest I care more about reducing host load than optimising for the guest.
#!/bin/sh
BASEDIR=/home/noodles/debian-qemu
if [ ! -S $ BASEDIR /swtpm/swtpm-sock ]; then
echo Starting swtpm:
swtpm socket --tpmstate dir=$ BASEDIR /swtpm \
--tpm2 \
--ctrl type=unixio,path=$ BASEDIR /swtpm/swtpm-sock &
fi
echo Starting QEMU:
qemu-system-x86_64 -enable-kvm -m 2048 \
-machine type=q35 \
-smbios type=1,serial=N00DL35,uuid=fd225315-f72a-4d66-9b16-55363c6c938b \
-drive if=pflash,format=qcow2,readonly=on,file=/usr/share/edk2/ovmf/OVMF_CODE_4M.qcow2 \
-drive if=pflash,format=raw,file=$ BASEDIR /OVMF_VARS.fd \
-global isa-debugcon.iobase=0x402 -debugcon file:$ BASEDIR /debian.ovmf.log \
-device virtio-blk-pci,drive=drive0,id=virblk0 \
-drive file=$ BASEDIR /debian-12-efi.qcow2,if=none,id=drive0,discard=on \
-net nic,model=virtio -net user \
-chardev socket,id=chrtpm,path=$ BASEDIR /swtpm/swtpm-sock \
-tpmdev emulator,id=tpm0,chardev=chrtpm \
-device tpm-tis,tpmdev=tpm0 \
-display none \
-nographic \
-boot menu=on