Wasmjit is a new runtime for WebAssembly whose main goal is to run
unmodified POSIX-conforming programs, compiled with
Emscripten, within the
Linux kernel. Targeting the kernel has also made it suitable for
running in constrained environments like microcontrollers or within
other applications. As long as your environment provides an
implementation of a C90 compiler, you should be able to run
Wasmjit. It doesn’t even require libc (though it currently requires
The main interface to Wasmjit is a command line program, aptly named
wasmjit. This program has been tested on Linux, OpenBSD, and
macOS. Additionally when this program is run on Linux, it will use the
kernel module to execute the WebAssembly program.
I announced the initial alpha version about a month ago and there seemed to be a decent amount of excitement about the project, especially from within the WebAssembly community. Since then Wasmjit has made an appearance in a few places online:
- Meet Wasmjit, your future embeddable WebAssembly runtime
- WebAssembly’s post-MVP future: A cartoon skill tree
- Wasmjit führt Webassembly-Module in Ring 0 aus
- A presentation that included Wasmjit
This is a much bigger response to the project than I expected. From my perspective, Wasmjit is very low-level and isn’t a tool that would exactly be used by a general programming audience. In any case, I’ve been grateful for all the coverage and all the people that have reached out, asked questions, and offered to help.
Why Run WebAssembly in Ring-0?
Ignoring WebAssembly for the moment, there are a few main reasons why one would generally want to run their program in “ring 0,” otherwise known as “kernel space.”
The first main reason is about context switching efficiency. If you are running an IO bound program, like a production web server, you are likely spending a non-trivial amount of time switching between user space and kernel-space on every system call. The cost of a system call is high, especially after Meltdown. It takes roughly 10x more time to issue a system call than a normal function call. Since Wasmjit runs programs in kernel space, all system calls become normal function calls. Therefore running a system-call heavy program in Wasmjit could save you an significant amount of resources, either money or electricity, whichever is more valuable in your specific use case.
Another instance of context switching happens when the kernel switches between two user processes. This usually involves flushing the TLB and swapping the page tables. Since processes run in kernel-space in Wasmjit, it saves a swap when switching between a normal process and a Wasmjit process. Zero swaps happen when switching between two Wasmjit processes. On workloads with heavy process-concurrency, this can save a save a significant amount of resources as well.
The second main reason why being able to run programs in kernel space might be useful is hardware-related. Not all CPUs feature MMUs (the hardware usually responsible for isolating the memory of user processes). Examples include microcontrollers and cheaper CPUs. It’s cumbersome and potentially unsafe to run normal programs with Linux on these devices since they lack a way to properly isolate user processes. The “software isolation” provided by Wasmjit allows these devices to run user processes without the increased risk of kernel panic, obviating the need for a design based on a more expensive CPU.
The Road Ahead
Wasmjit works today. It can already run many WebAssembly programs generated by Emscripten without any modification on the most popular x86_64 POSIX systems. There is still a lot more work to do, however.
The current goal is to implement as many Linux system calls in Wasmjit as is necessary to run nginx.wasm. This is about 113 system calls and is a labor of love. At that point Wasmjit will host this blog ;) The near term goals after that are to implement an efficient WebAssembly interpreter and an arm64 JIT. Additionally I want to standardize the system call interface that Emscripten targets and that Wasmjit implements.
This blog will document the experience of building Wasmjit, mostly from a technical aspect but occasionally will cover some non-technical topics as well. I have a post on implementing Spectre v1 and v2 mitagations coming up.
If Wasmjit is interesting to you and you’d like to help, please get in touch. Any help at this point would be greatly appreciated and could make a big impact.