This patch series is split from the original "Enable QEMU to run on browsers" series, focusing solely on introducing a TCG backend for WebAssembly. This implemention is based on the latest master which already includes the essential changes required to compile QEMU (in 32bit TCI mode) using Emscripten.
# New TCG Backend for Browsers A new TCG backend translates IR instructions into Wasm instructions and runs them using the browser's WebAssembly APIs (WebAssembly.Module and WebAssembly.instantiate). To minimize compilation overhead and avoid hitting the browser's limitation of the number of instances, this backend integrates a forked TCI. TBs run on TCI by default, with frequently executed TBs compiled into WebAssembly. # Workaround for Running 64bit Guests The current implementation uses Wasm's 32bit memory model. This series explores supporting TCG 64bit instructions while relying on SoftMMU for address translation. To enable 64bit guest support in Wasm today, it was necessary to partially revert recent changes that removed support for 64bit guests on 32bit hosts (e.g. commits a70af12addd9060fdf8f3dbd42b42e3072c3914f and bf455ec50b6fea15b4d2493059365bf94c706273) when compiling with Emscripten. The reverting is partial and addresses only pointer width differences between hosts and guests since the Wasm backend supports 64bit word operations. While this serves as a temporary workaround, a long-term solution could involve migrating to Wasm's 64bit memory model once it gains broader support, as it is currently not widely adopted (e.g. unsupported by Safari and libffi). # Overview of build process This section provides an overview of the build process for compiling QEMU using Emscripten. Full instructions are available in the sample repository[1]. To compile QEMU with Emscripten, the following dependencies are required. The emsdk-wasm32-cross.docker environment includes all necessary components and can be used as the build environment: - Emscripten SDK (emsdk) v3.1.50 - Libraries cross-compiled with Emscripten (refer to emsdk-wasm32-cross.docker for build steps) - GLib v2.84.0 - zlib v1.3.1 - libffi v3.4.7 - Pixman v0.44.2 QEMU can be compiled using Emscripten's emconfigure and emmake, which automatically set environment variables such as CC for targeting Emscripten. emconfigure configure --static --disable-tools --target-list=x86_64-softmmu emmake make -j$(nproc) This process generates the following files: - qemu-system-x86_64.js - qemu-system-x86_64.wasm - qemu-system-x86_64.worker.js Guest images can be packaged using Emscripten's file_packager.py tool. For example, if the images are stored in a directory named "pack", the following command packages them, allowing QEMU to access them through Emscripten's virtual filesystem: /path/to/file_packager.py qemu-system-x86_64.data --preload pack > load.js This process generates the following files: - qemu-system-x86_64.data - load.js Emscripten allows passing arguments to the QEMU command via the Module object in JavaScript: Module['arguments'] = [ '-nographic', '-m', '512M', '-accel', 'tcg,tb-size=500', '-L', 'pack/', '-drive', 'if=virtio,format=raw,file=pack/rootfs.bin', '-kernel', 'pack/bzImage', '-append', 'earlyprintk=ttyS0 console=ttyS0 root=/dev/vda loglevel=7', ]; The sample repository[1] provides a complete setup, including an HTML file that implements a terminal UI. [1] https://github.com/ktock/qemu-wasm-sample # Additional references - A talk at FOSDEM 2025: https://fosdem.org/2025/schedule/event/fosdem-2025-6290-running-qemu-inside-browser/ - Demo page on GitHub Pages: https://ktock.github.io/qemu-wasm-demo/ Kohei Tokunaga (33): tcg: Fork TCI for wasm32 backend tcg/wasm32: Do not use TCI disassembler in Wasm backend meson: Enable to build wasm backend tcg/wasm32: Set TCG_TARGET_INSN_UNIT_SIZE to 1 tcg/wasm32: Add and/or/xor instructions tcg/wasm32: Add add/sub/mul instructions tcg/wasm32: Add shl/shr/sar instructions tcg/wasm32: Add setcond/negsetcond/movcond instructions tcg/wasm32: Add deposit/sextract/extract instrcutions tcg/wasm32: Add load and store instructions tcg/wasm32: Add mov/movi instructions tcg/wasm32: Add ext instructions tcg/wasm32: Add bswap instructions tcg/wasm32: Add rem/div instructions tcg/wasm32: Add andc/orc/eqv/nand/nor instructions tcg/wasm32: Add neg/not/ctpop instructions tcg/wasm32: Add rot/clz/ctz instructions tcg/wasm32: Add addc/subb instructions tcg/wasm32: Add br/brcond instructions tcg/wasm32: Add exit_tb/goto_tb/goto_ptr instructions tcg/wasm32: Add call instruction tcg/wasm32: Add qemu_ld/qemu_st instructions include/exec: Allow using 64bit guest addresses on emscripten tcg/wasm32: Set TCG_TARGET_REG_BITS to 64 tcg/wasm32: Set mulu2/muls2 as unimplemented tcg/wasm32: Add initialization of fundamental registers tcg/wasm32: Write wasm binary to TB tcg/wasm32: Implement instantiation of Wasm binary tcg/wasm32: Allow Asyncify unwinding from TB tcg/wasm32: Enable instantiation of TBs executed many times tcg/wasm32: Enable TLB lookup meson: Propagate optimization flag for linking on Emscripten .gitlab-ci.d: build wasm backend in CI .gitlab-ci.d/buildtest.yml | 2 +- MAINTAINERS | 7 + accel/tcg/cputlb.c | 8 +- include/accel/tcg/getpc.h | 2 +- include/exec/helper-head.h.inc | 6 + include/exec/tlb-common.h | 14 +- include/exec/vaddr.h | 11 + include/qemu/atomic.h | 4 + include/tcg/helper-info.h | 4 +- include/tcg/tcg.h | 6 +- meson.build | 16 +- tcg/aarch64/tcg-target.c.inc | 11 + tcg/arm/tcg-target.c.inc | 11 + tcg/i386/tcg-target.c.inc | 11 + tcg/loongarch64/tcg-target.c.inc | 11 + tcg/meson.build | 5 + tcg/mips/tcg-target.c.inc | 11 + tcg/ppc/tcg-target.c.inc | 11 + tcg/region.c | 10 +- tcg/riscv/tcg-target.c.inc | 11 + tcg/s390x/tcg-target.c.inc | 11 + tcg/sparc64/tcg-target.c.inc | 11 + tcg/tcg.c | 23 +- tcg/tci/tcg-target.c.inc | 11 + tcg/wasm32.c | 1096 ++++++++ tcg/wasm32.h | 119 + tcg/wasm32/tcg-target-con-set.h | 21 + tcg/wasm32/tcg-target-con-str.h | 11 + tcg/wasm32/tcg-target-has.h | 22 + tcg/wasm32/tcg-target-mo.h | 17 + tcg/wasm32/tcg-target-opc.h.inc | 15 + tcg/wasm32/tcg-target-reg-bits.h | 12 + tcg/wasm32/tcg-target.c.inc | 3985 ++++++++++++++++++++++++++++++ tcg/wasm32/tcg-target.h | 76 + 34 files changed, 5569 insertions(+), 33 deletions(-) create mode 100644 tcg/wasm32.c create mode 100644 tcg/wasm32.h create mode 100644 tcg/wasm32/tcg-target-con-set.h create mode 100644 tcg/wasm32/tcg-target-con-str.h create mode 100644 tcg/wasm32/tcg-target-has.h create mode 100644 tcg/wasm32/tcg-target-mo.h create mode 100644 tcg/wasm32/tcg-target-opc.h.inc create mode 100644 tcg/wasm32/tcg-target-reg-bits.h create mode 100644 tcg/wasm32/tcg-target.c.inc create mode 100644 tcg/wasm32/tcg-target.h -- 2.43.0