This patch series adds a TCG backend for WebAssembly. Unlike eariler attempts [1], it is implemented using Emscripten's wasm64 target to support 64bit guests.
The first four commits are temporarily imported from a separated patch series which enables 64bit guests using wasm64 [2]. These commits are under review in that series and are included here only to allow subsequent patches to build. Please ignore them when reviewing this series. # 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. # 64bit guests support by wasm64 Support for 64bit guests is being reviewed in a separated patch series [2], which enables QEMU to use 64bit pointers by compiling with the --cpu=wasm64 flag. The Wasm TCG backend is based on this feature and also requires --cpu=wasm64. QEMU compiled with --cpu=wasm64 runs on wasm64-capable engines. To support engines which don't support wasm64 (e.g. Safari), the Wasm backend can use the compatibility flag "--enable-wasm64-32bit-address-limit" also introduced in [2]. This flag enables 64bit pointers in the C code while Emscripten lowers the output binary to wasm32 and limits the maximum memory size to 4GB. As a result, the Wasm backend can run on wasm32 engiens while supporting 64bit guests. Note: The flag was originally named --wasm64-32bit-address-limit but this patch series moved it from the configure script into meson_options.txt. To follow Meson's naming conventions, it was renamed to --enable-wasm64-32bit-address-limit. # Overview of build process To compile QEMU with Emscripten, the following dependencies are required. The emsdk-wasm-cross.docker environment includes all necessary components and can be used as the build environment: - Emscripten SDK (emsdk) v4.0.10 - Libraries cross-compiled with Emscripten (please see also emsdk-wasm-cross.docker for build steps) - GLib v2.84.0 - zlib v1.3.1 - libffi v3.5.2 - Pixman v0.44.2 The configure script supports --cpu=wasm64 flag to compile QEMU with 64bit pointer support. emconfigure ./configure --cpu=wasm64 \ --static --disable-tools \ --target-list=x86_64-softmmu emmake make -j$(nproc) If the output needs to run on wasm32 engines, use "--enable-wasm64-32bit-address-limit" flag. emconfigure ./configure --cpu=wasm64 --enable-wasm64-32bit-address-limit \ --static --disable-tools \ --target-list=x86_64-softmmu emmake make -j$(nproc) Either of the above commands generates the following files: - qemu-system-x86_64.js - qemu-system-x86_64.wasm 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', '-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 [3] (tcgdev64 branch) provides a complete setup, including an HTML file that implements a terminal UI. [1] https://patchew.org/QEMU/cover.1747744132.git.ktokunaga.m...@gmail.com/ [2] https://patchew.org/QEMU/cover.1754534225.git.ktokunaga.m...@gmail.com/ [3] https://github.com/ktock/qemu-wasm-sample/tree/tcgdev64 Kohei Tokunaga (35): meson: Add wasm64 support to the --cpu flag configure: Enable to propagate -sMEMORY64 flag to Emscripten dockerfiles: Add support for wasm64 to the wasm Dockerfile .gitlab-ci.d: Add build tests for wasm64 tcg: Fork TCI for wasm backend tcg/wasm: Do not use TCI disassembler in Wasm backend tcg/wasm: Set TCG_TARGET_REG_BITS to 64 meson: Enable to build wasm backend tcg/wasm: Set TCG_TARGET_INSN_UNIT_SIZE to 1 tcg/wasm: Add and/or/xor instructions tcg/wasm: Add add/sub/mul instructions tcg/wasm: Add shl/shr/sar instructions tcg/wasm: Add setcond/negsetcond/movcond instructions tcg/wasm: Add deposit/sextract/extract instrcutions tcg/wasm: Add load and store instructions tcg/wasm: Add mov/movi instructions tcg/wasm: Add ext instructions tcg/wasm: Add bswap instructions tcg/wasm: Add rem/div instructions tcg/wasm: Add andc/orc/eqv/nand/nor instructions tcg/wasm: Add neg/not/ctpop instructions tcg/wasm: Add rot/clz/ctz instructions tcg/wasm: Add br/brcond instructions tcg/wasm: Add exit_tb/goto_tb/goto_ptr instructions tcg/wasm: Add call instruction tcg/wasm: Add qemu_ld/qemu_st instructions tcg/wasm: Mark unimplemented instructions as C_NotImplemented tcg/wasm: Add initialization of fundamental registers tcg/wasm: Write wasm binary to TB tcg/wasm: Implement instantiation of Wasm binary tcg/wasm: Allow switching coroutine from a helper tcg/wasm: Enable instantiation of TBs executed many times tcg/wasm: Enable TLB lookup meson: Propagate optimization flag for linking on Emscripten .gitlab-ci.d: build wasm backend in CI .gitlab-ci.d/buildtest.yml | 26 +- .gitlab-ci.d/container-cross.yml | 20 +- .gitlab-ci.d/container-template.yml | 4 +- MAINTAINERS | 9 +- configure | 14 +- include/accel/tcg/getpc.h | 2 +- include/tcg/helper-info.h | 4 +- include/tcg/tcg.h | 2 +- meson.build | 14 +- meson_options.txt | 3 + scripts/meson-buildoptions.sh | 5 + 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/wasm.c | 1112 ++++++ tcg/wasm.h | 119 + tcg/wasm/tcg-target-con-set.h | 21 + tcg/wasm/tcg-target-con-str.h | 11 + tcg/wasm/tcg-target-has.h | 22 + tcg/wasm/tcg-target-mo.h | 17 + tcg/wasm/tcg-target-opc.h.inc | 15 + tcg/wasm/tcg-target-reg-bits.h | 15 + tcg/wasm/tcg-target.c.inc | 3167 +++++++++++++++++ tcg/wasm/tcg-target.h | 77 + ...2-cross.docker => emsdk-wasm-cross.docker} | 29 +- 35 files changed, 4822 insertions(+), 34 deletions(-) create mode 100644 tcg/wasm.c create mode 100644 tcg/wasm.h create mode 100644 tcg/wasm/tcg-target-con-set.h create mode 100644 tcg/wasm/tcg-target-con-str.h create mode 100644 tcg/wasm/tcg-target-has.h create mode 100644 tcg/wasm/tcg-target-mo.h create mode 100644 tcg/wasm/tcg-target-opc.h.inc create mode 100644 tcg/wasm/tcg-target-reg-bits.h create mode 100644 tcg/wasm/tcg-target.c.inc create mode 100644 tcg/wasm/tcg-target.h rename tests/docker/dockerfiles/{emsdk-wasm32-cross.docker => emsdk-wasm-cross.docker} (85%) -- 2.43.0