Building QEMU with virtio-gpu and rutabaga_gfx
Building QEMU with virtio-gpu
and rutabaga_gfx
Date: on 2023-11-22 | Updated: on 2024-01-04
virtio-gpu-rutabaga
device is available in QEMU 8.2 release candidates and later versions.
1. Install Debian host system dependencies
You might have to install more if you haven't built QEMU before on the host.
apt install -y {libpulse,libdrm,libglm,libstb,libegl,libgles,libvulkan,vulkan-validationlayers}-dev
In Debian trixie, vulkan-validation-layers-dev
has been renamed to vulkan-utility-libraries-dev
.
2. Build qemu
git clone https://gitlab.com/qemu-project/qemu.git
Checkout master
or a 8.2 tagged release.
2.1 (maybe optional) Build libvirglrenderer
Depending on the system version you have you might need a newer libvirglrender
export PREFIX="$(pwd)"/prefix
git clone https://gitlab.freedesktop.org/virgl/virglrenderer.git
cd virglrenderer
meson setup -Dprefix=$PREFIX -Dlibdir=lib build
cd build
ninja install
2.2 Build rutabaga
/gfxstream
dependencies
You will need to build gfxstream
and rutabaga_gfx
dependencies for QEMU.
Instead of polluting the host root FS, you can put everything under a local prefix folder:
cd qemu
mkdir -p build/deps/prefix
cd build/deps
Here we will build every dependency and install them in prefix/
# Development prefix tree
export PREFIX="$(pwd)"/prefix
export CMAKE_INSTALL_PREFIX="${PREFIX}"
export PKG_CONFIG_PATH="${PREFIX}/lib/pkgconfig":"${PREFIX}/lib/x86_64-linux-gnu/pkgconfig"
The following rutabaga_gfx
build instructions were taken from https://crosvm.dev/book/appendix/rutabaga_gfx.html
2.2.1 - Build aemu
HEAD
revision:
qemu/deps/aemu % git log -1
caf5a07 (HEAD -> main, origin/master, origin/main, origin/HEAD) Simplify formatter interface to use std::string
# from <https://crosvm.dev/book/appendix/rutabaga_gfx.html#build-aemu-base>
git clone https://android.googlesource.com/platform/hardware/google/aemu
cd aemu/
cmake -DAEMU_COMMON_GEN_PKGCONFIG=ON \
-DAEMU_COMMON_BUILD_CONFIG=gfxstream \
-DENABLE_VKCEREAL_TESTS=OFF \
--install-prefix "${PREFIX}" \
-B build
cmake --build build -j
cmake --install build --prefix "${CMAKE_INSTALL_PREFIX}"
2.2.2 Build gfxstream
HEAD
revision:
qemu/deps/gfxstream % git log -1
3e45436a (HEAD -> main, origin/master, origin/main, origin/HEAD) Merge "Fix crash on exit" into main
# from <https://crosvm.dev/book/appendix/rutabaga_gfx.html#build-gfxstream>
git clone https://android.googlesource.com/platform/hardware/google/gfxstream
cd gfxstream/
meson setup -Ddefault_library=static --prefix "${PREFIX}" build/
meson install -C build
2.2.3 Build rutabaga
FFI
git clone https://github.com/google/crosvm
You will also need rust/cargo.
Install the stable channel 1.68.2-{x86_64,aarch64}-unknown-linux-gnu
toolchain with rustup
if you don't have it already:
rustup toolchain list | grep -q 1.68.2-x86_64-unknown-linux-gnu || rustup toolchain install 1.68.2-x86_64-unknown-linux-gnu
crosvm
HEAD
revision:
crosvm % git log -1
cd04b6198 (HEAD -> main, origin/main, origin/HEAD) Upgrade gdbstub and gdbstub_arch.
# crosvm HEAD revision: 1eca601ea
export RUSTFLAGS='-Clink-arg=-L='"${PREFIX}"/lib/x86_64-linux-gnu/
cd crosvm/rutabaga_gfx/ffi
make
make prefix="${PREFIX}" install
Important: if the Makefile
did not find gfxstream with pkg-config
, the library is built without the gfxstream feature. Make sure this step has worked.
2.2.4 Build qemu
binary
After all that, go back to qemu/build
and build QEMU:
cd qemu/build
export CFLAGS="-I${PREFIX}/include -L${PREFIX}/lib" # needed for rutabaga_gfx_ffi.h
../configure --enable-system --enable-tools --enable-vhost-user --enable-slirp --enable-kvm --enable-debug --target-list=x86_64-softmmu --enable-rutabaga-gfx
make -j$(nproc)
3. Run the guest.
I used this QEMU invocation:
#!/bin/zsh
export WAYLAND_SOCK=/run/user/1000/wayland-0
#export WAYLAND_SOCK=/tmp/wayland.sock
GUEST_DATA_IMG=...
./build/qemu-system-x86_64 \
-m 4G \
-machine pc,accel=kvm,memory-backend=mem,usb=off \
-device virtio-scsi-pci,id=scsi0 \
-device virtio-net-pci,netdev=net0 \
-D qemu.log \
-netdev user,id=net0,hostfwd=tcp::8022-:22 \
-object memory-backend-file,id=mem,size=4G,mem-path=/dev/shm,share=on \
-audio driver=pa,model=hda,server=/run/user/1000/pulse/native \
-device virtio-vga-rutabaga,gfxstream-vulkan=on,cross-domain=on,wayland-socket-path=${WAYLAND_SOCK},hostmem=8G \
"$GUEST_DATA_IMG"
If you use Wayland, choose WAYLAND_SOCK=/run/user/1000/wayland-0
or similar. If you use weston
inside Xorg run weston -S /tmp/wayland.sock
and use WAYLAND_SOCK=/tmp/wayland.sock
.
3.1 Running graphic apps in guest through sommelier
You will need to build sommelier
inside the guest.
Clone the repository:
git clone https://chromium.googlesource.com/chromiumos/platform2
cd platform2/vm_tools/sommelier/
I used the HEAD
revision: Mon Aug 14 02:58:30 2023 +0000 40e9663246e784fb4d3abc0385ac2fe717ecf460 Revert "vm_tools/9s: Replace crosvm_base::vsock with vsock crate"
On Debian, you will need the following build dependencies:
apt install -y cmake \
libdrm{2,-dev} \
libgbm{1,-dev} \
libpixman-1-{0,dev} \
libwayland-bin \
'libwayland-client*' \
libwayland-dev \
libxcb-composite0{,-dev} \
libxcb1-dev \
libxkbcommon{0,-dev} \
meson \
pkg-config \
python3 \
python3-jinja2
Then perform the build:
meson setup build -Dwith_tests=false
meson compile -C build
meson install -C build
# run a weston-terminal
sommelier --virtgpu-channel weston-terminal
# run glmark2 benchmarks
apt install -y glmark2-wayland
sommelier --virtgpu-channel glmark2-wayland
This should open weston-terminal
and glmark2-wayland
on your host's wayland compositor.