The constraints introduced by shared code buffers make supporting calls with the previous layout impossible. The main additional constraint imposed by call-ret that if a host location is ever pushed onto the call-ret stack, then it must forever be a valid jump target. While this is reasonable in the: unlinked, direct linked, unlinked, direct linked case; it's almost impossible to achieve in the: unlinked, indirect linked, unlinked, direct linked case while ensuring all backpatching cases are valid with the current approach. To solve this introduce an additional layer of indirection, jump thunks, these are emitted at the end of a multiblock and are used to handle the two cases of calling the initial linker, and calling an indirect linked block. Initially at the ExitFunction location a branch/call to a unique jump thunk will be emitted, which will have the code layout: 00: b 0x8 04: br TMP1 08: ldr TMP1, <Shared exit linker> 0c: blr TMP1 10: HostCode 18: GuestRIP 20: CallerOffset If a direct link can be performed, then the initial branch/call to the jump thunk can be linked/unlinked to point to the jump thunk in a single 32-bit atomic operation. For an indirect link, the HostCode member is updated with a 64 bit atomic operation, and then a 32 bit atomic operation is used to replace the branch at 00 with a load of HostCode. Indirect unlinks are done by placing back the b 0x8 at 00. Safety: (1) Sequential link (e.g. one waiting to lock, one locked and linking): Linking is idempotent, would just rewrite the same data atomically. (2) Simultaneous link or simultaneous delink: Impossible due to LookupCache locking. (3) Simultaneous link and execute: (3.1) Direct link: Either the direct link is observed at the thunk callsite, or it is not observed and the linker is entered - this is then just (1). (3.2) Indirect link: Either the branch at 00 in the thunk is observed to be replaced with an ldr, in which case the modified HostCode must be observed due to the cache flush. Alternatively the branch replacement isn't observed and it's just (1). (4) Simultaneous unlink and execute: (4.1) Direct link: Either the jump to the jump thunk is seen, which must be in its base unlinked state with the branch at 00 as that would be inserted by any previous indirect unlink. In such a case the linker would just be entered, giving (5). Alternatively the modified jump isn't seen and it calls the original host code (which is fine). (4.2) Indirect link: If an ldr is seen at 00, then the rest of that sequence will function fine as HostCode is left untouched. If a branch is seen at 00, then it will just call the linker giving (5). (5) Sequential unlink then link: Unlinking restores the callsite and jump thunk to their original contents (aside from a modified HostCode). Linking then works as usual.
FEX: Emulate x86 Programs on ARM64
FEX allows you to run x86 applications on ARM64 Linux devices, similar to qemu-user and box64. It offers broad compatibility with both 32-bit and 64-bit binaries, and it can be used alongside Wine/Proton to play Windows games.
It supports forwarding API calls to host system libraries like OpenGL or Vulkan to reduce emulation overhead. An experimental code cache helps minimize in-game stuttering as much as possible. Furthermore, a per-app configuration system allows tweaking performance per game, e.g. by skipping costly memory model emulation. We also provide a user-friendly FEXConfig GUI to explore and change these settings.
Prerequisites
FEX requires ARMv8.0+ hardware. It has been tested with the following Linux distributions, though others are likely to work as well:
- Arch Linux
- Fedora Linux
- openSUSE
- Ubuntu 22.04/24.04/24.10
An x86-64 RootFS is required and can be downloaded using our FEXRootFSFetcher tool for many distributions.
For other distributions you will need to generate your own RootFS (our wiki page might help).
Quick Start
For Ubuntu 22.04, 24.04 and 24.10
Execute the following command in the terminal to install FEX through a PPA.
curl --silent https://raw.githubusercontent.com/FEX-Emu/FEX/main/Scripts/InstallFEX.py | python3
This command will walk you through installing FEX through a PPA, and downloading a RootFS for use with FEX.
For other Distributions
Follow the guide on the official FEX-Emu Wiki here.
Navigating the Source
See the Source Outline for more information.