Skip to content

Instantly share code, notes, and snippets.

@19h
Created July 11, 2026 12:55
Show Gist options
  • Select an option

  • Save 19h/14ae45b4ce1b72f8298bc404fb2c4028 to your computer and use it in GitHub Desktop.

Select an option

Save 19h/14ae45b4ce1b72f8298bc404fb2c4028 to your computer and use it in GitHub Desktop.
QEMU user-mode emulation: exact architecture and execution path

QEMU user-mode emulation: exact architecture and execution path

Revision anchor and scope

This analysis follows upstream QEMU 11.0.2, the most recent stable release listed by the QEMU project as of July 10, 2026. The release is anchored to tag object 0ab45d2af85f2fc9885b526ffbc8a15bbd1a2da8, pointing to commit e545d8bb9d63e9dd61542b88463183314cff9482. Function names and control paths below refer to that revision. Distribution builds may carry backports or downstream patches. (QEMU)

The principal subject is Linux user-mode emulation, implemented by binaries such as:

qemu-aarch64
qemu-arm
qemu-riscv64
qemu-x86_64
qemu-mips

This is different from qemu-system-*. Linux-user executes a target Linux process on a Linux host; system emulation constructs a virtual machine containing CPUs, devices, interrupt controllers, an MMU, firmware, and usually a guest kernel. BSD-user uses the same broad translation engine but has a separate loader and BSD ABI implementation. (QEMU Git Repositories)


Assumption register

ID Assumption Results depending on it Falsification probe
A1 The executable is qemu-ARCH, not qemu-system-ARCH. All statements about absence of a guest kernel, direct host-VM backing, syscall translation, and host threads. Inspect the process command line and binary name.
A2 The implementation is upstream QEMU 11.0.2. Exact function names, current execve() behavior, mapping implementation, and current limitations. Run qemu-ARCH --version; compare package source and downstream patch set against commit e545d8….
A3 Target and host expose Linux ABIs. TARGET_NR_* syscall translation, Linux signal frames, ELF auxiliary vectors, clone, futex, and /proc behavior. Examine the configured target; BSD-user source resides under bsd-user/, not linux-user/.
A4 QEMU was built with a normal native TCG backend. Translation to executable host instructions. Check build configuration for TCG Interpreter/TCI. A TCI build interprets TCG bytecode rather than emitting native host instructions.
A5 The selected QEMU target matches the ELF ISA, endianness, word size, and ABI. ELF loading, register conventions, syscall layouts, and pointer conversion. Compare e_machine, ELF class, byte order, target ABI flags, and QEMU binary/configuration.
A6 The selected virtual CPU model advertises only features QEMU implements. Instruction semantics, AT_HWCAP, AT_HWCAP2, target dynamic-linker dispatch, and IFUNC selection. Compare -cpu configuration, ELF feature requirements, target HWCAP values, and decoded instruction failures.
A7 The host kernel and page-size configuration can realize the requested target mappings closely enough. mmap, mprotect, file-tail mappings, subpage permissions, shared memory, and atomic behavior. Compare TARGET_PAGE_SIZE, host page size, host kernel facilities, and the exact failing mapping operation.

Unless explicitly qualified, the analysis below depends on A1–A7.


1. The irreducible model

QEMU Linux-user is a host-native process containing three principal mechanisms:

  1. A target-Linux process-image constructor.
  2. A target-ISA-to-host-ISA dynamic translator, TCG.
  3. A target-Linux-to-host-Linux ABI mediation layer.

The complete conceptual pipeline is:

target ELF executable
        │
        ▼
QEMU ELF loader constructs target process image
  - target virtual addresses
  - PT_LOAD mappings
  - target interpreter
  - target stack
  - argc/argv/envp
  - auxiliary vector
  - target vDSO / signal trampoline
        │
        ▼
target architectural state
  PC, SP, GPRs, FP/SIMD state, flags, TLS, CPU features
        │
        ▼
TCG translates target instructions into host instructions
        │
        ├──────── guest load/store ────────► host-mapped backing memory
        │
        ├──────── guest syscall ───────────► QEMU ABI translator ─► host kernel
        │
        ├──────── guest exception ─────────► target Linux signal
        │
        └──────── guest clone/fork ────────► host pthread/fork

QEMU preserves the observable target user/kernel contract to the extent implemented. It does not preserve the target kernel implementation that would ordinarily supply that contract. The filesystem, network stack, scheduler, host virtual-memory machinery, host process model, host credentials, and most other kernel services are the real host kernel’s services, reached through QEMU’s translation layer. (QEMU Git Repositories)

What is emulated, translated, or delegated

Facility Realization
Target scalar, FP, SIMD and control instructions Decoded by the target frontend; lowered through TCG or target helpers.
Target architectural registers Stored in a target-specific CPUArchState; cached in host registers within generated code when possible.
Target virtual address numbers Preserved as target integers and mapped into QEMU’s host address space.
Memory storage and host page tables Real host VM mappings owned by the QEMU process.
ELF process-image semantics Implemented by QEMU’s Linux-user ELF loader.
Target dynamic linker and target libc Ordinary target machine code executed through TCG.
Syscall instruction and target calling convention Recognized by the target CPU loop.
Syscall structures, flags, pointers and errors Translated by linux-user/syscall.c and associated target ABI code.
Actual file, socket, timer and process operations Normally performed by the host kernel.
Signals Hybrid: host delivery and faults are captured; QEMU constructs target signal state and target-format frames.
Guest threads Normally one host thread and one CPUState per guest thread.
Guest processes Normally one host process per target process; guest fork() uses host process creation.
Guest kernel, devices, interrupt controller, firmware and guest page tables Not present in Linux-user mode.
Target cycle timing Not modeled as target hardware timing.

2. Source-level control skeleton

The important source areas are:

linux-user/main.c                 host-process initialization
linux-user/linuxload.c            binary-format dispatch
linux-user/elfload.c              target ELF loading and initial stack
linux-user/mmap.c                 target VM operations
linux-user/uaccess.c              target-pointer validation and copying
linux-user/syscall.c              syscall dispatch and translation
linux-user/signal.c               host/target signal mediation
linux-user/<arch>/cpu_loop.c      target exception/syscall loop

target/<arch>/tcg/                target instruction decoder and TCG frontend

accel/tcg/cpu-exec.c              translated execution loop
accel/tcg/translator.c            generic target-translation loop
accel/tcg/translate-all.c         TranslationBlock creation and management
tcg/tcg.c                         IR processing, register allocation, code emission
tcg/<host>/                       host-specific TCG backend

A condensed source-level call graph is:

host kernel starts qemu-ARCH
└── main()                                      linux-user/main.c
    ├── parse options and target arguments
    ├── choose target CPU model
    ├── initialize TCG and CPU object
    ├── establish target address-space policy
    ├── create TaskState
    ├── loader_exec()                           linux-user/linuxload.c
    │   ├── prepare_binprm()
    │   └── load_elf_binary()                   linux-user/elfload.c
    │       ├── validate target ELF
    │       ├── load main ELF PT_LOAD mappings
    │       ├── load PT_INTERP, if present
    │       ├── allocate target stack
    │       ├── copy argv/env/string data
    │       ├── create auxiliary vector
    │       └── load target vDSO/signal trampoline
    ├── initialize brk, syscall and signal state
    ├── initialize target architectural registers
    └── cpu_loop()                              linux-user/<arch>/cpu_loop.c
        ├── cpu_exec()                          accel/tcg/cpu-exec.c
        │   ├── obtain target PC and execution flags
        │   ├── TranslationBlock lookup
        │   ├── on miss: tb_gen_code()
        │   │   ├── target decoder
        │   │   ├── TCG IR construction
        │   │   ├── optimization/liveness
        │   │   ├── host register allocation
        │   │   └── host-code emission
        │   └── tcg_qemu_tb_exec()
        ├── handle target syscall exception
        ├── handle target CPU exception
        ├── handle atomic fallback
        └── process pending target signals

The initial load path, target ELF dispatch, CPU-loop entry and TCG execution loop are directly visible in the corresponding QEMU source. (GitHub)


3. Host launch and initial target-process construction

3.1 The host first executes QEMU, not the target executable

There are two usual launch forms:

qemu-aarch64 ./program

or, through Linux binfmt_misc:

./program

In the second case, the host kernel recognizes the target ELF format and invokes the registered QEMU interpreter. QEMU contains handling for binfmt_misc conventions including AT_EXECFD and preservation of the original argv[0]. The process initially created by the host kernel is therefore a host-native QEMU process. The target executable has not been entered natively. (GitHub)

The process has:

  • a host-native QEMU text and data image;
  • QEMU runtime stacks;
  • a TCG code cache;
  • QEMU’s metadata and target CPU state;
  • host mappings that will back target virtual memory.

This distinction remains important throughout execution: the host kernel sees QEMU machine code executing, even when the logical computation belongs to the target program.

3.2 Target CPU creation

QEMU selects a target CPU model based on command-line configuration and, where applicable, target ELF properties. It initializes the target page-size policy, creates a target-specific CPUState/CPUArchState, resets it, and initializes TCG.

The selected CPU model determines, among other things:

  • which target instructions are legal;
  • feature-register results;
  • target HWCAP/HWCAP2 bits;
  • architectural behaviors used by the decoder;
  • which optimized routines the target dynamic linker may select.

Therefore, CPU-model choice is not merely a performance setting. It is part of the target ABI-visible machine description. (GitHub)

3.3 Establishing target address-space policy

Before loading the target image, QEMU establishes values including:

  • guest_base;
  • reserved_va;
  • target mmap search bases;
  • target ET_DYN load base;
  • mmap_min_addr;
  • target page-size configuration.

For a target with an address space substantially smaller than the host—for example, a 32-bit target on a 64-bit host—QEMU commonly reserves a contiguous host range covering the target address space. The reservation is initially inaccessible and subsequently replaced by real mappings. For large 64-bit target spaces, fully reserving every possible target address is often impractical, so target and QEMU host mappings can coexist in the host address space with explicit range validation. (GitHub)


4. Target ELF loading

4.1 QEMU performs the target-kernel ELF-loader role

loader_exec() prepares a linux_binprm-like structure, reads the executable header and dispatches to load_elf_binary() when the target file has valid ELF magic. This loader derives substantially from Linux ELF-loading logic, ported into QEMU user space and modified for target-width and target-endian data. (QEMU Git Repositories)

Validation includes, as applicable:

  • ELF magic and version;
  • ELF32 versus ELF64 class;
  • target endianness;
  • e_machine;
  • target ABI flags;
  • acceptable executable type, principally ET_EXEC or ET_DYN;
  • target-specific ELF properties and GNU properties.

This is target parsing. QEMU does not ask the host ELF loader to understand the foreign ELF’s target machine code.

4.2 Program-header processing

QEMU walks the target program headers and interprets at least the relevant portions of:

  • PT_LOAD;
  • PT_INTERP;
  • PT_PHDR;
  • PT_GNU_STACK;
  • PT_GNU_PROPERTY;
  • architecture-specific properties where implemented.

For each PT_LOAD, it computes target virtual-address ranges and file offsets, reserves the complete image when required, and maps the segment with logical permissions derived from ELF PF_R, PF_W, and PF_X. It handles partial file pages, zero-filled tails and BSS. It records the main image’s entry point, program-header location and initial brk extent. (QEMU Git Repositories)

For an ET_DYN object, QEMU chooses a target load bias. For an ET_EXEC, it attempts to realize the fixed target layout and detect conflicts. These decisions are made in target address space and then converted into host mappings.

4.3 Dynamic interpreter

When the main ELF contains:

PT_INTERP = /lib/ld-linux-aarch64.so.1

or the equivalent for another target, QEMU opens and maps that target interpreter. The -L/QEMU_LD_PREFIX configuration participates in locating an ABI-correct target interpreter rather than accidentally opening an incompatible host one. (QEMU Git Repositories)

After loading:

  • the main executable’s entry is placed in AT_ENTRY;
  • the interpreter base is placed in AT_BASE;
  • the initial target PC is the interpreter entry, not normally the main executable entry.

The interpreter then runs as ordinary target code under TCG. It performs relocations, symbol lookup, TLS setup and library loading by making translated guest syscalls. QEMU is not a replacement implementation of glibc’s or musl’s runtime linker.

4.4 Target stack and auxiliary vector

QEMU allocates a target stack mapping, including guard and executable-stack semantics associated with PT_GNU_STACK, then writes the target-format startup data:

target SP
   │
   ├── argc
   ├── argv[0 ... argc-1] pointers
   ├── NULL
   ├── envp[] pointers
   ├── NULL
   ├── auxiliary-vector type/value pairs
   └── strings, platform text, random bytes and associated data

All pointers use the target pointer width; scalar values and pointer words use the target byte order.

The auxiliary vector can include:

  • AT_PHDR;
  • AT_PHENT;
  • AT_PHNUM;
  • AT_PAGESZ;
  • AT_BASE;
  • AT_ENTRY;
  • AT_UID, AT_EUID, AT_GID, AT_EGID;
  • AT_HWCAP, AT_HWCAP2;
  • AT_CLKTCK;
  • AT_RANDOM;
  • AT_SECURE;
  • AT_EXECFN;
  • AT_PLATFORM;
  • AT_SYSINFO_EHDR.

QEMU creates 16 bytes for AT_RANDOM, derives target hardware-capability fields from the selected virtual CPU and can supply a target vDSO image or target signal-return trampoline. (QEMU Git Repositories)

The host vDSO cannot simply be exposed as executable target code: it contains host-ISA instructions. A QEMU-provided target vDSO, where available, contains target instructions and is itself translated by TCG.

4.5 Initial architectural registers

After image construction, target-specific code initializes the architectural state expected after Linux execve():

  • target PC;
  • target SP;
  • target argument registers where the ABI requires them;
  • status/control flags;
  • target TLS or architecture-specific process state;
  • selected CPU mode, always appropriate to target user execution rather than target kernel execution.

The target PC is then consumed by cpu_loop() and cpu_exec(). QEMU never performs a host-native jump to the target ELF’s bytes.


5. Target virtual memory inside the QEMU process

5.1 Address conversion

For ordinary untagged addresses, the fundamental mapping is:

[ H = B + G ]

where:

  • (G) is a target virtual address;
  • (B) is guest_base;
  • (H) is the host address at which the corresponding target bytes are mapped.

The inverse is:

[ G = H - B ]

QEMU’s actual helpers also:

  1. remove architecture-defined address tags where appropriate;
  2. validate target-range bounds;
  3. prevent integer wrapping;
  4. account for target pointer width;
  5. reject host addresses not belonging to the guest mapping.

Conceptually:

host_pointer = g2h_untagged(target_address);
target_address = h2g(host_pointer);

The current source explicitly defines g2h_untagged_vaddr() as target address plus guest_base and h2g() as the inverse transformation, subject to validity checks. (QEMU Git Repositories)

If guest_base == 0, numerical guest and host addresses can coincide for a mapping, but software must not assume this. Address tagging, range validation, reservations and host layout still matter.

5.2 This is not a guest MMU

In system emulation, QEMU may walk guest page tables or maintain software TLBs corresponding to a guest MMU.

Linux-user ordinarily does neither. The real translation from host virtual address to physical memory is performed by the host kernel’s page tables for the QEMU process. QEMU adds:

  • target-to-host address conversion;
  • a target page-flag database;
  • target mapping-layout policy;
  • target alignment checks;
  • fault classification;
  • TranslationBlock invalidation.

Thus, a translated guest load often becomes an ordinary host load from the mapped address rather than a full guest page-table walk. QEMU’s TCG documentation explicitly separates user-mode direct mapping from system-mode software-MMU operation. (QEMU Git Repositories)

5.3 Logical target page metadata

QEMU tracks target mapping state independently of the host kernel’s VMA list. Logical page flags include concepts such as:

PAGE_VALID
PAGE_READ
PAGE_WRITE
PAGE_EXEC
PAGE_WRITE_ORG
PAGE_ANON
PAGE_PASSTHROUGH
architecture-specific properties such as BTI or MTE state

The records are held in interval-tree-based page metadata and are updated by target mmap, mprotect, munmap, ELF loading, shared-memory operations and code-protection changes. (QEMU Git Repositories)

This metadata serves several purposes:

  • validating target pointers used by syscalls;
  • distinguishing target map errors from permission errors;
  • checking target instruction fetches;
  • locating free target ranges;
  • preserving original write permission while translated code is temporarily protected;
  • invalidating generated code after mapping changes;
  • handling target-specific permission properties.

5.4 Host protection synthesis

Target permissions cannot be copied mechanically to the host.

For example, current Linux-user code maps a target executable page as host-readable, not host-executable:

target PROT_EXEC  → host PROT_READ

The target instruction bytes are data consumed by QEMU’s translator. The host executes the separately generated TCG code cache, not the target page itself. (QEMU Git Repositories)

Consequently:

target code page:
    contains AArch64/RISC-V/MIPS/etc. bytes
    host mapping: readable, possibly writable
    host CPU: never directly executes those bytes

TCG code cache:
    contains x86-64/AArch64/etc. host bytes
    host mapping: executable under JIT W^X policy
    target program: cannot address it as target memory

5.5 Host and target page-size mismatch

Three cases exist:

  1. Host page size equals target page size.
  2. Host page size is smaller than target page size.
  3. Host page size is larger than target page size.

QEMU has distinct paths for these cases. For example, if a target page is larger than the host page and a file mapping ends partway through the target page, target Linux semantics may permit access through the complete target page while the host kernel would normally raise SIGBUS at the earlier host-page boundary. QEMU may combine file-backed and anonymous mappings to approximate the target behavior. The source notes that file extension after such a transformation cannot always retain exact target semantics. (QEMU Git Repositories)

When one host page contains multiple target pages, the host page must receive the union of permissions required by all contained target pages:

[ P_{\text{host page}}

\bigcup_{i=1}^{n}P_{\text{target page }i} ]

QEMU continues tracking finer target permissions in metadata, but host hardware protection is necessarily coarser. This creates edge cases for subpage protection, file sharing and fault behavior. Current mprotect code explicitly computes this permission union. (QEMU Git Repositories)

5.6 Target mmap family

Guest calls involving address-space topology cannot generally be passed through without mediation. QEMU implements target-aware versions of:

  • mmap and mmap2;
  • munmap;
  • mprotect;
  • mremap;
  • brk;
  • SysV shared-memory attachment;
  • selected madvise behavior.

These operations must preserve target address values, target alignment, reservation policy, page metadata and translated-code coherency.

When reserved_va is active, a target munmap usually replaces the region with a PROT_NONE anonymous reservation instead of returning it to arbitrary host use. That preserves the contiguous target-address reservation. (QEMU Git Repositories)


6. Representation of target CPU state

Each target architecture defines a CPUArchState containing the logical machine state, for example:

general-purpose registers
program counter
condition/status flags
floating-point registers and status
SIMD/vector registers
thread pointer
exclusive-monitor state
architecture-specific user-visible system state

A common CPUState surrounds this architecture-specific state with execution-control data:

exception index
interrupt and exit requests
current TranslationBlock
per-vCPU TB jump cache
single-step/debug state
thread association

The target frontend creates TCG “global” values corresponding to architectural fields, often backed by fixed offsets within CPUArchState. Within one TranslationBlock, the host register allocator may keep frequently used guest values in host registers. At required boundaries, values are synchronized so that helpers, exceptions, signals and the dispatcher observe a valid target state.

This leads to a two-level representation:

persistent architectural truth:
    CPUArchState in QEMU memory

temporary optimized representation:
    host registers and TCG temporaries while a TB executes

The TB key contains execution-state fields whose assumed values influence decoding. Examples include target PC, x86 code-segment base, execution flags, CPU mode and translation-control flags. A state transition that changes decoding assumptions therefore selects or creates a different TB. (QEMU Git Repositories)


7. TCG translation

7.1 TranslationBlock lookup

Before translating, cpu_exec() obtains target execution state and attempts to find a matching TranslationBlock.

Lookup is conceptually:

1. Compute TB key from:
     target PC
     code-page identity
     cs_base or equivalent
     architectural translation flags
     cflags / execution mode

2. Probe per-vCPU jump cache.

3. On cache miss, probe the shared TB hash table.

4. On miss, translate a new TB while holding the required mapping/
   translation locks.

5. Insert the resulting TB and update the per-vCPU cache.

The source validates both the first target code page and, when needed, the second page containing an instruction crossing a page boundary. (QEMU Git Repositories)

A TB is best defined operationally as:

The bounded, single-entry target instruction region emitted by one QEMU translation pass under a fixed set of execution assumptions.

It commonly corresponds closely to a compiler basic block and ends at a branch, exception-generating boundary, instruction-count bound, page-related constraint or another translator-selected stopping condition. -one-insn-per-tb forces the limiting case of one target instruction per TB. (QEMU Git Repositories)

7.2 Target decoding

Every target architecture provides a frontend, generally beneath:

target/<architecture>/tcg/

The generic translation loop establishes a DisasContext, calls target-specific initialization and repeatedly invokes the target’s instruction decoder. The decoder:

  1. fetches target instruction bytes;
  2. applies target endianness;
  3. recognizes the instruction and encoding;
  4. validates CPU-feature and privilege requirements;
  5. emits TCG operations or calls a target helper;
  6. updates the logical next PC;
  7. terminates translation at the appropriate boundary.

The generic translator exposes stages corresponding to:

init_disas_context
tb_start
insn_start
translate_insn
tb_stop

Per-instruction start metadata is generated so QEMU can reconstruct the exact target PC and other lazy state when host execution later faults inside the generated TB. (QEMU Git Repositories)

7.3 TCG intermediate representation

The decoder does not directly emit host instructions. It emits TCG operations over typed temporaries, including forms representing:

  • integer arithmetic and logic;
  • shifts, rotates and comparisons;
  • conditional selection;
  • branches;
  • target memory loads and stores;
  • host memory accesses to CPUArchState;
  • atomic operations;
  • memory barriers;
  • vector operations where supported;
  • calls to C helpers;
  • explicit TB exits.

TCG IR is a transient compiler representation. Normal native-TCG builds do not retain it as the primary execution form.

An instruction can be translated in three principal ways:

Target instruction
    ├── direct sequence of generic TCG operations
    ├── host-specific TCG operation with backend lowering
    └── call to a target/helper C function

Complex architectural operations, rare corner cases, FP behavior, privileged-state checks and instructions that can raise intricate exceptions frequently use helpers.

7.4 Optimization and code generation

After target translation, TCG performs implementation-dependent optimization and liveness analysis, allocates host registers, inserts spills and reloads, selects host instructions and emits machine code into the JIT buffer. It also emits slow paths, constant pools and relocation records and performs the host instruction-cache synchronization required by the host architecture. (QEMU Git Repositories)

Conceptually:

target bytes
    ↓ target decoder
TCG operations
    ↓ simplification / liveness
optimized TCG operation stream
    ↓ host register allocation
allocated host operations
    ↓ host backend
host machine-code bytes

The resulting host code takes a pointer to the target CPU environment and executes according to a calling convention established by QEMU’s TCG prologue.

Where the host’s executable-memory policy requires W^X separation, QEMU writes through a writable view or phase and executes through an executable view. tcg_qemu_tb_exec() receives the target CPU environment and the executable TB pointer. (QEMU Git Repositories)

7.5 Concurrent translation

Multiple target threads may reach the same untranslated address concurrently. QEMU can therefore produce duplicate candidate translations. Before publishing a new TB, it verifies page identity and hash-table state and can discard a duplicate in favor of the TB already installed by another thread. The host-PC range metadata is installed in an order that permits signal and exception lookup for emitted code. (QEMU Git Repositories)


8. Executing generated code

8.1 The dispatcher-to-TB transition

After lookup or generation, the execution engine invokes approximately:

tcg_qemu_tb_exec(cpu_env, tb_code_pointer)

The host CPU then executes generated native instructions directly. It is no longer interpreting target opcodes one at a time.

For a target arithmetic sequence such as:

add x0, x1, x2
lsl x3, x0, #4
eor x4, x3, x5

an x86-64 host might receive a compact sequence of host adds, shifts and XORs operating on allocated host registers. The exact allocation and instruction selection are backend decisions.

8.2 Guest versus host stacks

Two stacks coexist:

  1. Host execution stack Used by QEMU, generated host code and C helpers.

  2. Target architectural stack Addressed by the guest SP register and stored in guest-mapped memory.

A translated guest push, call-frame setup or stack store writes the target stack mapping. A helper invocation uses the host stack. Confusing these stacks leads to incorrect unwinding, instrumentation and signal models.

8.3 TranslationBlock exits

Generated code returns to the dispatcher or transfers to another TB for reasons including:

  • direct or indirect target control flow;
  • syscall instruction;
  • target exception;
  • interrupt or pending host signal;
  • debug breakpoint or single-step;
  • invalidated code;
  • self-modifying code;
  • explicit CPU exit request;
  • translation-cache constraints;
  • atomic fallback;
  • unmapped or protected memory access;
  • a helper requesting cpu_loop_exit.

The encoded TB return value identifies the relevant exit slot or reason, allowing cpu_exec() and the target-specific cpu_loop() to decide what happens next. (QEMU Git Repositories)

8.4 Direct TB chaining

Returning through the central dispatcher after every target branch is expensive. QEMU therefore supports direct chaining.

Initially:

TB A exit
   └── returns to dispatcher
        └── dispatcher finds TB B

After resolution, QEMU can patch the generated exit:

TB A host code ───── direct host branch ─────► TB B host code

For a conditional target branch, a TB can have separate patchable exit paths. Chaining is constrained by page identity, target state, invalidation safety and backend branch reachability. Indirect branches can use a runtime lookup helper and jump to a discovered TB pointer. (QEMU Git Repositories)

Every chained destination maintains enough reverse linkage that invalidating a target code page can unlink incoming branches. Direct chaining therefore optimizes dispatch without making stale generated code permanently reachable.


9. Guest loads and stores

9.1 Fast path

For an ordinary guest memory access, generated code implements the equivalent of:

[ H = \operatorname{g2h}(\operatorname{untag}(G)) ]

followed by a host load or store with the target operation’s:

  • width;
  • signedness;
  • endianness;
  • required alignment;
  • atomicity;
  • memory-order semantics.

Depending on host and target, guest-base addition and byte swapping can be folded into the generated instruction sequence. The target bytes remain in target byte order in memory. QEMU does not globally byte-swap files or memory pages.

For example, on a little-endian host emulating a big-endian target:

file and memory bytes: unchanged
target 32-bit load: reads four bytes and interprets them big-endian
TCG lowering: host load plus byte reversal, or equivalent sequence

Structured syscall arguments are separately converted field by field because host and target structure layout may also differ.

9.2 Slow paths and helpers

A memory operation may use a helper when it requires:

  • target-specific alignment checking;
  • uncommon size or atomicity;
  • cross-page handling;
  • target memory tagging;
  • software fallback;
  • precise exception generation;
  • instrumentation;
  • host facilities unavailable in direct form.

In user mode, the helper ultimately validates the target address and ordinarily reaches the same direct guest-to-host mapping rather than performing a guest page-table walk.

9.3 Fault classification

Suppose generated host code performs a load from the host address backing target address (G), and the host kernel raises SIGSEGV or SIGBUS.

QEMU’s host signal handler examines:

  • the faulting host PC;
  • whether that PC belongs to generated TCG code;
  • the host fault address;
  • the corresponding target address;
  • target page metadata;
  • whether the operation was a write;
  • whether the page was protected for self-modifying-code detection;
  • the target instruction metadata for that host PC.

It can then classify the event as:

  1. a target unmapped-address fault;
  2. a target permission fault;
  3. a target alignment or bus fault;
  4. a self-modifying-code write that should be consumed internally;
  5. an internal QEMU fault not attributable to guest execution.

For a real guest fault, QEMU restores the precise target state and asks the target architecture loop to synthesize the corresponding Linux signal, commonly SIGSEGV, SIGBUS, SIGILL or SIGFPE. A host fault occurring outside recognized generated-code/helper contexts is not silently reclassified as a guest fault. (QEMU Git Repositories)


10. Precise exceptions

Generated code may have optimized or delayed portions of target state. Therefore, a faulting host PC alone is insufficient unless QEMU knows which target instruction it represents.

During translation, QEMU records metadata mapping generated-code positions back to target instruction starts and relevant state. When a helper or host signal causes a nonlocal exit, QEMU:

  1. identifies the containing TB from the host PC;
  2. locates the target instruction metadata;
  3. reconstructs the target PC;
  4. restores lazy architectural state as required;
  5. exits generated code through QEMU’s exception machinery;
  6. delivers the target exception at the target instruction boundary.

QEMU uses controlled longjmp-style exits for these paths because returning normally through arbitrary helper and generated-code frames could commit state belonging to instructions after the fault point. (QEMU Git Repositories)

The intended invariant is:

[ \text{state delivered to target signal handler}

\text{target architectural state immediately before/at the faulting instruction} ]

subject to the architecture’s specified exception semantics and implementation correctness.


11. Self-modifying code and target JITs

Target programs may modify executable code, including:

  • dynamic language JITs;
  • runtime linkers;
  • instruction patchers;
  • trampolines;
  • packed or self-modifying binaries.

A stale TB would otherwise continue executing old semantics after the underlying target bytes changed.

11.1 Write-protect/invalidate mechanism

When QEMU translates bytes from a target code page that is logically writable, it can temporarily remove host write permission while remembering PAGE_WRITE_ORG.

A later guest write proceeds as follows:

translated guest store
        │
        ▼
host write to protected target-code page
        │
        ▼
host SIGSEGV
        │
        ▼
QEMU identifies PAGE_WRITE_ORG / translated-code protection
        │
        ├── invalidate every TB dependent on the page
        ├── unlink incoming direct TB chains
        ├── restore host write permission
        ├── force an execution exit if required for precise SMC
        └── return so the guest store can be retried

The protection fault is internal and is not delivered as target SIGSEGV. When code on the page is translated again, QEMU can reprotect the page. (QEMU Git Repositories)

11.2 Other invalidation sources

TBs are also invalidated by operations such as:

  • target munmap;
  • target mprotect;
  • replacement mmap;
  • code-writing debugger operations;
  • architecture-specific instruction-cache flush operations;
  • mappings whose backing identity changes;
  • global code-cache flush.

A target JIT therefore writes target instructions into target memory; QEMU later decodes those new target instructions and emits corresponding host instructions. The target JIT never generates host code merely because the host happens to have a different ISA.


12. System-call interception

12.1 The syscall instruction is a target CPU event

A target syscall instruction is decoded as part of the target ISA:

AArch64: svc
x86-64: syscall
x86-32: int 0x80 / sysenter paths
RISC-V: ecall
MIPS: syscall

It is not generally replaced inline with an unconstrained host syscall instruction. Instead, translated execution exits with an architecture-specific exception number. The target cpu_loop() extracts the syscall number and arguments according to that target’s ABI.

For AArch64, the broad source-level behavior is equivalent to:

number = target_x8;
args   = target_x0 ... target_x5;
result = do_syscall(env, number, args...);

if (result == QEMU_ERESTARTSYS) {
    target_pc -= 4;
} else {
    target_x0 = result;
}

x86 and other architectures use their own registers, instruction lengths and error-return conventions. (QEMU Git Repositories)

12.2 Generic dispatch

do_syscall() performs tracing, plugin/debug hooks and target syscall filtering before dispatching through do_syscall1() or related implementation paths. The switch uses target constants such as:

TARGET_NR_read
TARGET_NR_write
TARGET_NR_openat
TARGET_NR_mmap
TARGET_NR_clone
TARGET_NR_rt_sigaction

An unsupported target syscall normally yields target -ENOSYS, not an attempt to execute the same numerical syscall on the host. (GitLab)

12.3 Translation dimensions

A syscall boundary may require conversion of every one of the following:

Number and calling convention

Target syscall numbers often differ from host numbers. Target register placement and 64-bit argument splitting differ across ABIs.

Integer width and signedness

A 32-bit target’s:

long
unsigned long
time_t
off_t
size_t
pointer

may differ from the host types. QEMU uses target-specific abi_long, abi_ulong and explicit conversions.

Endianness

Target values in guest memory are byte-swapped as required. This includes structure fields, arrays, signal sets and futex comparison values.

Constants and flags

Numbers for:

  • O_*;
  • MAP_*;
  • PROT_*;
  • socket domains/options;
  • CLONE_*;
  • RLIMIT_*;
  • signal flags;
  • ioctl commands;

may differ. QEMU translates recognized bit masks and enumerations.

Structures

A host structure cannot ordinarily be copied directly into target memory. QEMU uses explicit target layouts for structures including:

  • stat and statx;
  • timespec and legacy time structures;
  • sigaction, siginfo_t, ucontext;
  • rlimit;
  • iovec;
  • socket address and ancillary structures;
  • directory entries;
  • rusage;
  • ioctl-specific records.

Pointers and buffers

A target pointer is validated and converted through the guest mapping. QEMU distinguishes read access from write access and can lock or copy buffers for the duration of a host operation.

Errors

Host errno values are mapped into target errno numbers. A host return of -1 plus errno is converted to the target kernel’s negative-error convention expected by the target libc and assembly ABI. (GitHub)

12.4 Example: target write

A target call conceptually equivalent to:

write(fd, guest_buf, count)

is implemented approximately as:

1. Validate [guest_buf, guest_buf + count) for target read access.
2. Convert the target address to a host pointer.
3. Resolve any FD-specific translator.
4. Call host write/safe_write.
5. Release the guest buffer lock.
6. Convert host error or byte count to target return form.
7. Store the result in the target return register.

The bytes are not endian-converted because a byte stream has no intrinsic integer endianness. A structured ioctl buffer or stat result, in contrast, requires field-level conversion. Current read, write, open and associated cases make these distinctions explicit. (GitLab)

12.5 Example: target read

For read, the guest buffer must be writable. The host kernel can often write directly into the host mapping that backs target memory:

target address G
       ↓ g2h
host pointer H
       ↓ host read(fd, H, count)
target bytes now visible at G

The direct pointer is safe only after QEMU has validated the target range and arranged signal-safe access behavior.

12.6 File descriptors

Guest FDs are normally backed by real host FDs and frequently retain the same integer value, while QEMU keeps metadata for special translation cases. Operations on regular files, sockets, pipes and event objects therefore ultimately involve host kernel objects.

This does not imply that every FD operation is transparent. QEMU may need:

  • command translation;
  • structure conversion;
  • event or signal integration;
  • target /proc special handling;
  • format translation for architecture-specific streams;
  • rejection of unsupported device ioctls.

12.7 VM-related syscalls are QEMU-owned

Calls such as mmap, mprotect, munmap, mremap and brk enter QEMU’s target address-space implementation. A raw host call would be insufficient because it could:

  • return a host address that is invalid as a target pointer;
  • overwrite QEMU runtime memory;
  • violate target alignment;
  • lose reserved_va;
  • leave stale TBs;
  • assign the wrong logical target permissions.

12.8 Legacy and multiplexed ABIs

The syscall layer also handles ABI patterns that may not exist on the host, including:

  • old 32-bit time layouts;
  • split 64-bit arguments;
  • mmap2 offsets expressed in target pages;
  • old socketcall or IPC multiplexers;
  • target-specific signal-set widths;
  • legacy stat variants;
  • architecture-specific syscall return conventions.

This is why “QEMU forwards syscalls” is materially incomplete. It implements an ABI compiler between two kernel interfaces.


13. Signal-safe blocking syscalls and restart

A naïve implementation has a race:

QEMU checks: no target signal pending
             │
             ├── host signal arrives here
             │
             ▼
QEMU enters a blocking host syscall

The target signal could remain pending while the host call blocks indefinitely.

QEMU addresses this through a carefully bounded “safe syscall” assembly region. Its host signal handler can determine whether the interrupted host PC lies:

  • before the real host syscall;
  • inside the host syscall;
  • after the point at which returning normally is safe.

When necessary, the handler redirects control so the syscall wrapper reports QEMU_ERESTARTSYS. The architecture-specific loop then rewinds the target PC to the target syscall instruction and processes the target signal. After the target handler returns, target SA_RESTART and target kernel-style rules determine whether execution retries the syscall or produces EINTR. (QEMU Git Repositories)

This is not simply host EINTR propagation. QEMU must preserve the restart semantics of the target instruction and target signal ABI.


14. Guest execve() is a special boundary

The initial target executable is loaded internally through:

loader_exec() → load_elf_binary()

A later guest execve() follows a different current-upstream path.

In QEMU 11.0.2:

  1. TARGET_NR_execve or TARGET_NR_execveat dispatches to do_execv().
  2. QEMU copies the target pathname, argv and environment into host-form arrays.
  3. It calls a safe host execve() or execveat() path.
  4. On success, the current QEMU host process is replaced.

Thus QEMU does not normally reset all its internal state and call its initial ELF loader for an arbitrary guest execve() in place. (GitLab)

Consequences:

  • If the new executable is foreign-architecture ELF and the host has a matching binfmt_misc registration, the host kernel invokes qemu-user again.
  • If it is host-native, the host kernel can replace QEMU with the native executable.
  • If it is foreign and no host binary-format handler recognizes it, the operation can fail with an executable-format error.
  • Host shebang processing applies to scripts presented to the host execve() path.
  • QEMU contains special handling for some self-executable paths and argument-preservation cases.

This behavior is version-sensitive and is one of the places where describing qemu-user as a wholly self-contained “guest process manager” becomes incorrect.


15. Signal virtualization

Signals can originate from three different domains.

Origin Example QEMU action
Host asynchronous signal Host SIGINT, timer signal, kill() Map host signal number/info to target representation and queue it.
Host synchronous fault caused by target execution Host SIGSEGV from generated guest load Recover target instruction state and synthesize target fault signal.
Pure target CPU exception Illegal target instruction, divide error, target breakpoint Architecture loop creates target signal without requiring an equivalent host fault.

QEMU initializes host-to-target and target-to-host signal-number tables and installs SA_SIGINFO host handlers for relevant signals, including fault signals. Host real-time signal ranges and target ranges need not coincide. (QEMU Git Repositories)

15.1 Host handler phase

The host signal handler can:

  • consume QEMU-internal execution-interrupt signals;
  • detect self-modifying-code protection faults;
  • recognize safe-syscall interruption;
  • identify a generated-code fault;
  • recover target PC/state;
  • translate host siginfo_t;
  • queue a target signal;
  • force exit from the current TB.

It does not call a target signal handler as host machine code.

15.2 Pending-target-signal phase

At a safe point in cpu_loop(), process_pending_signals() chooses a deliverable target signal according to target masks and priority rules. Synchronous target faults receive special handling so they cannot be indefinitely blocked in ways the target kernel would forbid.

QEMU consults the target’s emulated sigaction state:

  • default action;
  • ignore;
  • user handler;
  • mask;
  • alternate stack;
  • SA_SIGINFO;
  • restart and reset flags.

15.3 Target signal frame

For a user handler, architecture-specific code writes a target-format frame onto the target stack or target alternate signal stack. The frame contains the target ABI’s representation of:

  • siginfo_t;
  • ucontext_t;
  • general registers;
  • FP/SIMD state where required;
  • signal mask;
  • stack state;
  • return trampoline information.

QEMU then updates target registers so that normal TCG execution begins at the target handler’s address.

The handler itself is target code and is translated normally.

15.4 Signal return

The handler eventually invokes the target sigreturn or rt_sigreturn path, usually through a target vDSO or trampoline. QEMU:

  1. validates the frame in target memory;
  2. decodes target-endian, target-layout state;
  3. restores target registers;
  4. restores the signal mask and alternate-stack state;
  5. resumes at the saved target PC.

A sentinel return path prevents ordinary syscall-result write-back from overwriting registers just restored from the target frame. (QEMU Git Repositories)


16. Target exceptions without a target kernel

In a real target machine, an exception might transfer control to a privileged exception vector. Linux-user has no target kernel to receive it.

Instead:

target instruction exception
        │
        ▼
TCG helper or translated exit sets CPU exception index
        │
        ▼
target cpu_loop() switch
        │
        ├── map exception class and fault address
        └── queue target Linux signal

Examples include:

  • undefined or privileged instruction → commonly target SIGILL;
  • breakpoint → commonly target SIGTRAP;
  • integer or FP arithmetic exception → target SIGFPE;
  • target memory abort → target SIGSEGV or SIGBUS;
  • target alignment failure → architecture-dependent target signal.

The exact mapping is architecture-specific. AArch64’s user loop, for example, maps architectural exception classes and syndrome information directly into target Linux signals rather than entering an emulated EL1 exception vector. (QEMU Git Repositories)


17. Threads, clone(), fork() and process topology

17.1 One guest thread normally maps to one host thread

For a thread-like clone() using shared address space, QEMU:

  1. allocates a new target CPUState/CPUArchState;
  2. allocates a new TaskState;
  3. copies or initializes target register state according to clone semantics;
  4. configures target child SP, TLS and TID pointers;
  5. creates a host POSIX thread;
  6. enters the target CPU loop in that host thread.

The target memory is automatically shared because both host threads inhabit the same QEMU host process. The host kernel schedules them and permits actual parallel execution. QEMU’s documentation explicitly describes guest clone() as creating a real host thread with a separate virtual CPU. (QEMU Git Repositories)

Per-thread state therefore has the approximate structure:

host pthread
   ├── host runtime stack
   ├── thread-local pointer to CPUState
   ├── CPUArchState
   ├── TaskState
   ├── target signal state
   └── executes TCG-generated host code

The guest architectural SP points into guest memory and is not the pthread’s host SP.

17.2 Why QEMU does not blindly invoke raw host clone

Host C libraries maintain thread-local runtime state, cancellation data, stack guards and other invariants. Creating a thread with an arbitrary raw host clone invocation can violate those assumptions. QEMU classifies target clone flags and uses pthread-style creation for thread cases, host fork-like creation for process cases, and explicit emulation for selected target-only semantics.

Unsupported combinations are rejected rather than copied numerically into a host clone call.

17.3 Process-like clone and fork

A target fork-like operation uses host process creation. Host copy-on-write then supplies the ordinary memory-copy semantics.

QEMU surrounds the fork with preparation and repair of runtime state, including:

  • mapping locks;
  • translation locks;
  • mutex state;
  • per-process thread bookkeeping;
  • child CPU/task associations.

The child naturally contains only the calling host thread, matching the essential post-fork thread model. QEMU reinitializes locks whose inherited state would otherwise refer to vanished host threads. (QEMU Git Repositories)

Current source can emulate target vfork through safer fork-like behavior rather than allowing the target child to execute within the parent’s exact host runtime stack and QEMU state.

17.4 Namespace flags

Current QEMU documentation explicitly identifies Linux namespace-related clone flags as unsupported in user-mode emulation. The guest may still run inside namespaces already applied to the QEMU host process, but creating arbitrary new namespaces from target clone flags is not equivalent to running a real target kernel. (QEMU Git Repositories)

17.5 PIDs, TIDs and credentials

Because target processes and threads are backed by real host processes and threads:

  • target PIDs/TIDs are closely tied to host IDs;
  • target credentials derive from the QEMU process’s host credentials;
  • signal-delivery operations ultimately interact with host process objects;
  • scheduler priority and affinity operations are constrained by host policy;
  • the QEMU process’s namespaces and resource limits delimit guest effects.

QEMU translates representations and special cases, but it does not maintain an independent guest kernel PID namespace.


18. Futexes, atomics and memory ordering

18.1 Futexes

A target futex address normally maps to a real word in QEMU’s host address space. QEMU converts:

  • target pointer;
  • operation encoding;
  • timeout structure;
  • comparison value and byte order;
  • selected flags;

then invokes host futex facilities where possible.

This lets separate guest threads block and wake through the host kernel while sharing the same mapped target word.

18.2 TCG atomics

TCG represents atomic operations and memory barriers explicitly. When the host can realize the requested operation atomically, the backend emits an appropriate host atomic sequence.

When an operation cannot be implemented in the normal parallel path, QEMU can raise EXCP_ATOMIC and use cpu_exec_step_atomic():

acquire global exclusive execution lock
disable parallel-TB assumptions
translate or select a one-instruction TB
execute that instruction without chaining
release exclusive lock

This supplies atomicity with respect to other QEMU-managed guest CPUs/threads for that fallback path. (QEMU Git Repositories)

18.3 Memory-model limitation

The host and target memory models need not be identical. QEMU emits barriers and atomic sequences intended to preserve target ordering, but current documentation explicitly warns that differences can remain.

A particularly important boundary is shared memory concurrently accessed by a non-QEMU host process. A QEMU fallback implemented through its private exclusive lock is not atomic with respect to an external process that does not participate in that lock. QEMU’s mapping source calls out this external-sharing limitation for operations that require EXCP_ATOMIC. (QEMU Git Repositories)


19. Dynamic linking in exact operational terms

For a dynamically linked AArch64 program on an x86-64 host:

main ELF:        AArch64 instructions
PT_INTERP:       AArch64 dynamic linker
shared objects:  AArch64 instructions
QEMU runtime:    x86-64 instructions
TCG cache:       generated x86-64 instructions
host kernel:     x86-64 Linux kernel

The sequence is:

  1. QEMU maps the target main ELF.
  2. QEMU maps the target dynamic interpreter.
  3. QEMU sets target PC to the interpreter.
  4. TCG translates interpreter instructions.
  5. The target interpreter executes its own ELF/relocation algorithms.
  6. Its openat, read, mmap, mprotect and related calls enter QEMU’s syscall layer.
  7. QEMU obtains and maps target shared-object bytes.
  8. The interpreter applies target-format relocations by ordinary target memory writes.
  9. It resolves target TLS, PLT/GOT and IFUNC state.
  10. It transfers target control to constructors and then the target program entry.
  11. Every newly reached target code region is translated on demand.

The host ld.so loads QEMU itself. It does not relocate the target main executable or target shared objects.

A statically linked target binary merely omits the target dynamic-linker stage. Its compiled-in target libc and application code still execute through TCG.

qemu-user-static means that the QEMU executable is statically linked for deployment convenience; it does not imply that target code executes statically or natively.


20. Worked trace: AArch64 target on x86-64 host

Consider:

#include <unistd.h>

int main(void) {
    write(1, "X\n", 2);
    return 0;
}

compiled as an AArch64 Linux ELF and executed on x86-64 Linux.

Phase 1: host startup

The host kernel starts the x86-64 qemu-aarch64 binary directly or through binfmt_misc.

The host PC initially points into QEMU’s x86-64 startup code.

Phase 2: target ELF loading

QEMU:

  • validates EM_AARCH64;
  • maps the AArch64 PT_LOAD segments into its own host address space at addresses corresponding to target virtual addresses;
  • maps the target AArch64 interpreter if dynamically linked;
  • allocates an AArch64 target stack;
  • writes target-format argc/argv/envp/auxv;
  • initializes AArch64 SP, PC and process state.

Phase 3: first target instruction

Suppose the target PC is the dynamic linker’s entry and no matching TB exists.

QEMU:

  1. reads AArch64 bytes at target PC;
  2. decodes instructions;
  3. emits TCG operations;
  4. optimizes them;
  5. allocates x86-64 host registers;
  6. emits x86-64 machine code;
  7. stores the TB in the lookup structures;
  8. transfers host execution to that generated x86-64 code.

Phase 4: target memory operations

A target instruction loads from target address (G).

The generated code accesses approximately:

[ H = \text{guest_base} + G ]

using a host load, with alignment/endian handling required by AArch64 semantics.

Phase 5: target syscall

Eventually target libc executes approximately:

mov x0, #1          // fd
adr x1, message     // target pointer
mov x2, #2          // count
mov x8, #__NR_write
svc #0

The AArch64 translator emits an exception exit for svc.

The AArch64 CPU loop reads:

syscall number: x8
arguments:      x0 ... x5

and calls do_syscall().

Phase 6: host write

QEMU:

  1. validates the target buffer at x1;
  2. converts it into a host pointer;
  3. calls the host write path on FD 1;
  4. receives host return value 2;
  5. maps any host error if necessary;
  6. writes target x0 = 2.

The host kernel writes the two unchanged bytes 0x58 0x0a.

Phase 7: resume

Execution resumes after svc. QEMU may reuse an existing TB or translate the next one.

Phase 8: termination

Target libc eventually invokes exit_group. QEMU performs target process cleanup and terminates the corresponding host QEMU process and its guest-thread backing threads.

At no point did the x86-64 host CPU directly execute an AArch64 instruction byte.


21. Formal execution model

Let the target observable process state be:

[ S_g = (R, F, V, PC, M, A, \Sigma, \Theta) ]

where:

  • (R): scalar architectural registers;
  • (F): status, condition and control flags;
  • (V): FP/SIMD/vector state;
  • (PC): target program counter;
  • (M): target-addressed memory bytes;
  • (A): target VM metadata and permissions;
  • (\Sigma): signal actions, masks and pending state;
  • (\Theta): thread/process state.

Let (H) be the host environment, including kernel state, files, sockets, timing and scheduling.

For a translated TB (B), QEMU attempts to generate host code (J_B) such that, up to the first externally relevant boundary:

[ \pi_g(J_B(S_g,H))

\operatorname{ISA}_B(S_g) ]

Here, (\pi_g) projects the host/QEMU state back onto target-observable architectural state.

The qualification “up to the first boundary” matters because a TB may terminate at:

  • syscall;
  • signal;
  • exception;
  • asynchronous interrupt;
  • mapping change;
  • atomic fallback;
  • debugging event;
  • self-modifying write.

For a target syscall:

[ (n_g,a_g,M_g) \overset{\Phi}{\longrightarrow} (n_h,a_h,M_h) ]

[ (r_h,e_h,M_h')

K_h(n_h,a_h,M_h) ]

[ (r_h,e_h,M_h') \overset{\Psi}{\longrightarrow} (r_g,e_g,M_g') ]

where:

  • (\Phi) converts target number, arguments, pointers and structures;
  • (K_h) is the real host kernel operation or a QEMU-composed implementation;
  • (\Psi) converts results, errors and output structures back to the target ABI.

The intended equivalence domain is:

defined target ISA behavior
+
implemented target Linux userspace ABI
+
host services reachable through QEMU's translation

It is not equivalence of:

target kernel algorithms
target device behavior
target scheduling decisions
target cycle timing
all host-independent side effects
undefined guest behavior

This is an implementation contract and reasoning model, not a formal proof that every QEMU instruction and syscall implementation is bug-free.


22. Performance mechanics and complexity

Let:

  • (I) be the number of target instructions in a TB;
  • (M) be the number of mapped target intervals;
  • (T_p) be the number of TBs depending on an invalidated page;
  • (E_p) be the number of incoming chained edges to those TBs;
  • (N) be a copied syscall buffer length.
Operation Approximate complexity Principal cost
Per-vCPU TB-cache lookup (O(1)) Hash/index and key validation.
Shared TB-hash lookup Expected (O(1)) Concurrent hash lookup and code-page checks.
Decode and emit a TB Proportional to (I), plus optimization and allocation passes Decoder, IR construction, register allocation, host code emission.
Execute a cached arithmetic TB Proportional to emitted host instructions Often close to native host instruction throughput, excluding semantics overhead.
Target interval lookup Typically (O(\log M + k)) for overlapping intervals Interval-tree traversal.
Copy/convert byte buffer (O(N)) Validation and copying if direct access is not used.
Convert structure array (O(\text{elements} \times \text{fields})) Field layout and endian conversion.
Invalidate a code page (O(T_p + E_p)) conceptually TB removal and chain unlinking.
Host syscall Host-kernel dependent Kernel entry, I/O, blocking and conversion.
Signal delivery Target-signal scan plus frame construction Target context serialization.

These are implementation-level asymptotics rather than stable API guarantees.

22.1 Why cached code can be fast

After translation:

  • straight-line arithmetic is native host code;
  • target registers may remain in host registers;
  • guest memory often uses direct host loads/stores;
  • chained TBs bypass the dispatcher;
  • no guest page-table walk is needed in normal user-mode memory accesses.

22.2 Principal overhead sources

The material costs are:

  • first-use translation;
  • indirect-branch lookup;
  • TB dispatch when chaining is unavailable;
  • target/helper calls;
  • cross-endian operations;
  • FP or vector semantic helpers;
  • syscall conversion;
  • signal/fault transitions;
  • self-modifying-code invalidation;
  • target/host page-size adaptation;
  • instrumentation;
  • atomic fallback;
  • code-cache flushes.

Same-ISA qemu-user execution still normally passes through TCG. Upstream Linux-user does not become KVM-assisted simply because target and host ISAs match.


23. Exact limitations and divergence surfaces

23.1 Host kernel semantics remain visible

The target process ultimately receives behavior derived from the host kernel:

  • filesystem implementation;
  • networking behavior;
  • scheduler;
  • host kernel bugs and fixes;
  • host syscall availability;
  • credentials and namespaces;
  • resource limits;
  • timer resolution;
  • host security policy.

QEMU selectively translates or synthesizes observables, but it does not recreate an arbitrary historical target kernel.

23.2 Incomplete syscall and ioctl coverage

Unsupported target syscalls can return ENOSYS. Device-specific ioctls require explicit command and structure descriptions; unknown or incompatible ioctls may fail. QEMU’s own documentation notes that ioctl translation is command-specific. (QEMU Git Repositories)

23.3 ptrace and syscall tracing

A host strace observes QEMU’s host syscalls, not a clean target-syscall stream. QEMU provides target-aware tracing through QEMU_STRACE/-strace, but current documentation identifies it as incomplete. General target ptrace behavior is not equivalent to a native target kernel. (QEMU Git Repositories)

23.4 Page-size mismatch

Subpage protections, file tails, shared writable fragments, SIGBUS timing and files extended after mapping can diverge because the host hardware page is the minimum enforceable protection unit. Current source contains explicit workarounds and caveats for these cases. (QEMU Git Repositories)

23.5 Memory ordering and external shared memory

Target memory-order semantics may not be perfectly reproduced on a different host memory model. Exclusive-lock fallback only coordinates QEMU-managed execution, not arbitrary external processes.

23.6 Clone and namespace behavior

Namespace clone flags are unsupported, and some target clone combinations cannot be represented by host pthread/fork primitives. (QEMU Git Repositories)

23.7 Signals

Host and target signal numbering, real-time ranges, frame formats, restorer conventions and restart rules differ. QEMU translates these but cannot make host delivery timing identical to a specific target kernel.

23.8 ASLR and layout

QEMU constructs a plausible target layout, but allocation decisions are constrained by the QEMU host process’s existing mappings, host ASLR, guest_base, reservations and host page size. It is not necessarily bit-identical to a native target kernel’s layout.

23.9 Timing and performance counters

QEMU is not cycle accurate in Linux-user mode. Instruction counters, cycle counters, timer instructions, signal timing and scheduling interleavings need not match target hardware.

23.10 CPU and floating-point edge behavior

The selected CPU model and QEMU’s instruction/helper implementations determine:

  • optional instruction availability;
  • FP exception behavior;
  • NaN propagation;
  • vector corner cases;
  • user-visible system-register results.

Implementation defects or model differences can be observable.

23.11 Target /proc and machine identity

There is no independent guest procfs. QEMU selectively synthesizes or rewrites certain process views, while other data remains host-derived. Programs relying on exact native target /proc, kernel-release or hardware-topology behavior can detect differences.

23.12 Guest execve

Current guest execve() relies on the host executable-format path. Foreign-program recursion therefore depends on binfmt_misc or another host arrangement.

23.13 No kernel or device isolation by construction

A target file or network syscall can affect real host-visible objects under the QEMU process’s credentials and namespaces. Linux-user is not a virtual hardware boundary. Isolation, when present, comes from host mechanisms surrounding the QEMU process.


24. Instrumentation and binary-analysis leverage points

High impact

Target decoder and semantic normalization

The frontend has already resolved:

  • instruction length;
  • opcode class;
  • operand decoding;
  • feature validity;
  • target PC progression.

Instrumentation here observes target semantics before host register allocation obscures them.

TCG IR

TCG is the architecture-neutral point for:

  • instruction tracing;
  • memory-access instrumentation;
  • taint propagation;
  • coverage;
  • target semantic lifting;
  • dynamic data-flow analysis.

A single TCG-level mechanism can cover multiple target ISAs, subject to helper semantics and target-specific operations.

Host-PC ↔ target-PC metadata

The precise-exception mapping provides a basis for:

  • JIT-aware profilers;
  • target stack reconstruction;
  • crash attribution;
  • generated-code breakpoint translation;
  • host fault to target instruction correlation.

TB invalidation and chaining metadata

The page-to-TB and incoming-chain relationships expose:

  • self-modifying-code events;
  • target JIT compilation epochs;
  • code provenance;
  • executable-page mutation;
  • stale-code prevention boundaries.

Syscall ABI layer

do_syscall() and structure translators are natural points for:

  • target-aware syscall tracing;
  • policy enforcement in target ABI terms;
  • structured argument capture;
  • input/output taint sources;
  • reproducibility logging.

The syscall source already contains tracing and plugin-hook entry points. (GitLab)

Medium impact

Guest address-space metadata

The interval-tree and mapping hooks permit:

  • target-aware memory maps;
  • snapshot/diff logic;
  • executable-page tracking;
  • guest virtual-address normalization;
  • mapping lifetime reconstruction.

Synchronization with mmap_lock and TB invalidation is mandatory for coherent observation.

Target signal-frame construction

This is useful for:

  • architecture-correct crash dumps;
  • target unwind reconstruction;
  • signal-handler control-flow analysis;
  • precise asynchronous-event replay.

Atomic fallback paths

These identify target instructions whose semantics cannot be represented directly by the host’s ordinary parallel code path.

Low impact but operationally useful

JIT profiling outputs

QEMU supports mechanisms for associating generated regions with profiling tools. These describe host execution cost but need target-PC metadata to become meaningful for guest-level analysis. (QEMU Git Repositories)

One-instruction TB mode

-one-insn-per-tb simplifies instruction-boundary attribution but disables important chaining and batching advantages, substantially altering performance and timing. (QEMU Git Repositories)


25. Common incorrect models, red-teamed

Incorrect model Contradiction in the implementation
“qemu-user is a small virtual machine.” No target kernel, devices, firmware or guest scheduler are instantiated.
“It interprets each instruction.” Normal TCG builds emit and execute cached host machine code.
“It uses a software MMU for every load.” Linux-user ordinarily maps target memory directly into the host process and uses host page tables.
“A guest pointer is a host pointer.” It must be validated, untagged and transformed using guest_base; width and range differ.
“Executable target pages are host-executable.” Current mapping code converts target execute permission into host read permission; generated host code lives elsewhere.
“It forwards the target syscall number unchanged.” Target numbers, registers, flags, structures, pointers, endianness and errno are translated.
“The host dynamic linker loads target libraries.” The target dynamic linker is target code running under TCG.
“Signals pass directly to target handlers.” QEMU queues target signals and constructs target-format frames; handlers execute through TCG.
“Guest threads are green threads scheduled by QEMU.” Thread-like clone operations create real host threads, which the host kernel schedules.
“Every guest process is hidden inside one QEMU process.” Fork-like operations normally create host processes; current exec replaces the host QEMU process.
“Same-ISA qemu-user just executes natively.” Normal qemu-user still uses the TCG execution and ABI-control path.
“TCG IR is executed permanently.” IR is processed into host code and ordinarily discarded as the execution form.
“Host SIGSEGV always means target SIGSEGV.” It may be an internal SMC event, target map fault, safe-syscall event or QEMU defect.
“Guest execve() simply invokes the internal initial ELF loader again.” Current upstream translates arguments and enters host execve/execveat.
“All Linux syscalls are reproduced exactly.” Unsupported calls, ioctls, clone flags, page-size cases and host-kernel divergences remain.
“Target timing equals target hardware.” TB translation, host scheduling, helpers and host kernel behavior determine timing.

26. Compact invariant set

A technically accurate mental model can be reduced to the following invariants:

  1. The currently executing machine code is host code. It is either QEMU itself or TCG-generated code.

  2. The architectural state is target state. PC, registers, flags and exceptions follow the selected target model.

  3. Target memory is host memory with a target address interpretation. The host kernel’s mappings back it; QEMU maintains target metadata.

  4. Target code bytes are data to the host. They are decoded and translated, never directly entered as host instructions.

  5. The kernel boundary is an ABI translation boundary. A target syscall does not enter a target kernel.

  6. The target dynamic linker is part of the translated workload.

  7. Signals cross through QEMU-owned target state and frames.

  8. Guest threads and processes are normally backed by host threads and processes.

  9. Generated code is valid only while its target bytes, mapping identity and execution assumptions remain valid.

  10. Equivalence is functional and bounded, not kernel-, timing- or hardware-identical.


27. Quality gates

QG1 — Normativity: No normative or ethical conclusion is required.

QG2 — Assumptions: A1–A7 identify mode, revision, build, ABI, CPU model, target filesystem and host-VM dependencies, with direct falsification probes.

QG3 — Requirement coverage: Process loading, target memory, ELF, dynamic linking, CPU state, TCG translation, TB caching/chaining, faults, SMC, syscalls, signals, threads, atomics, execve, performance and limitations are covered end to end.

QG4 — Reproducibility: Address transformations, process flow, syscall transformations and complexity variables are explicitly defined.

QG5 — Edge consistency: Initial load versus later execve, target versus host stacks, logical versus host page permissions, and guest versus host signal faults are distinguished.

QG6 — Provenance: Claims are grounded in upstream QEMU 11.0.2 documentation and source.

QG7 — Bounded expansion: Analysis and instrumentation leverage points, security-boundary implications and major divergence surfaces are included.


Provenance

Primary implementation anchor:

QEMU version:       v11.0.2
Tag object:         0ab45d2af85f2fc9885b526ffbc8a15bbd1a2da8
Referenced commit:  e545d8bb9d63e9dd61542b88463183314cff9482
Release date listed: 2026-06-26

Principal upstream source paths examined:

docs/user/main.rst
docs/devel/tcg.rst

linux-user/main.c
linux-user/linuxload.c
linux-user/elfload.c
linux-user/mmap.c
linux-user/uaccess.c
linux-user/syscall.c
linux-user/signal.c
linux-user/aarch64/cpu_loop.c

include/user/guest-host.h

accel/tcg/cpu-exec.c
accel/tcg/translator.c
accel/tcg/translate-all.c
tcg/tcg.c

QEMU source files carry file-specific licenses. The Linux-user mapping and syscall implementations cited here are predominantly GPL version 2-or-later; include/user/guest-host.h carries LGPL-2.1-or-later licensing; portions of TCG, including tcg/tcg.c, use permissive licensing identified in their source headers. No QEMU source code was incorporated verbatim into this answer; pseudocode and equations are independent explanatory representations. (QEMU Git Repositories)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment