In this walk-through, we'll use an Ubuntu cloudimg along with the gpio sample server to emulate a very simple GPIO device.
vfio-user
client support is not yet merged into qemu
. Instead, download and build jlevon's master.vfio-user branch of qemu; for example:
git clone -b master.vfio-user git@github.com:jlevon/qemu.git cd qemu ./configure --prefix=/usr --enable-kvm --enable-vnc --target-list=x86_64-softmmu --enable-debug --enable-vfio-user-client make -j
Set up the necessary metadata files:
sudo apt install cloud-image-utils $ cat metadata.yaml instance-id: iid-local01 local-hostname: cloudimg $ cat user-data.yaml #cloud-config ssh_import_id: - gh:jlevon cloud-localds seed.img user-data.yaml metadata.yaml
don't forget to replace jlevon
with your github user name.
Start the gpio
server process:
rm -f /tmp/vfio-user.sock ./build/samples/gpio-pci-idio-16 -v /tmp/vfio-user.sock &
Make sure your system has hugepages available:
$ cat /proc/sys/vm/nr_hugepages 1024
Now you should be able to start qemu:
$ imgpath=/path/to/bionic-server-cloudimg-amd64.img $ sudo ~/src/build/qemu-system-x86_64 \ -machine accel=kvm,type=q35 -cpu host -m 2G \ -mem-prealloc -object memory-backend-file,id=ram-node0,prealloc=yes,mem-path=/dev/hugepages/gpio,share=yes,size=2G \ -numa node,memdev=ram-node0 \ -nographic \ -device virtio-net-pci,netdev=net0 \ -netdev user,id=net0,hostfwd=tcp::2222-:22 \ -drive if=virtio,format=qcow2,file=$imgpath \ -drive if=virtio,format=raw,file=seed.img \ -device vfio-user-pci,socket=/tmp/vfio-user.sock
Log in to your VM and load the kernel driver:
$ ssh -p 2222 ubuntu@localhost ... $ sudo apt install linux-modules-extra-$(uname -r) $ sudo modprobe gpio-pci-idio-16
Now we should be able to observe the emulated GPIO device's pins:
$ sudo su - # cat /sys/class/gpio/gpiochip480/base > /sys/class/gpio/export # for ((i=0;i<12;i++)); do cat /sys/class/gpio/OUT0/value; done
and the server should output something like:
gpio: region2: read 0 from (0:1) gpio: region2: read 0 from (0:1) gpio: region2: read 0 from (0:1) gpio: region2: read 0x1 from (0:1) gpio: region2: read 0x1 from (0:1) gpio: region2: read 0x1 from (0:1) gpio: region2: read 0x2 from (0:1) gpio: region2: read 0x2 from (0:1) gpio: region2: read 0x2 from (0:1) gpio: region2: read 0x3 from (0:1) gpio: region2: read 0x3 from (0:1) gpio: region2: read 0x3 from (0:1)