Skip to content

System Architecture

Mainkill1 edited this page Sep 27, 2026 · 3 revisions

System Architecture

xemu models the original Xbox as a collection of QEMU devices connected through the machine's memory, PCI, interrupt, DMA, and timing infrastructure. The important architectural boundary is between guest-visible hardware state and host-side implementations used to realize that state.

Machine composition

The Xbox machine is assembled primarily from hw/xbox/xbox.c. The machine class selects a Pentium III x86 CPU and permits one guest CPU. The rest of the platform is constructed around PC-compatible infrastructure plus Xbox-specific chipset, storage, input, audio, and NV2A devices.

Area Guest-facing role Representative source area
CPU Single x86 Pentium III-compatible processor hw/xbox/xbox.c, target/i386, accel/tcg
Main memory Guest system RAM and address-space mappings QEMU memory subsystem, Xbox machine setup
PCI / LPC Device discovery, configuration, legacy platform services hw/xbox, QEMU PCI/LPC infrastructure
PIT / RTC PC-compatible timer and real-time-clock devices used by the Xbox platform Xbox machine initialization + common device models
NV2A Graphics processor, VRAM-visible behavior, command submission, timers, display and reports hw/xbox/nv2a
Storage IDE/ATA-style Xbox disk and optical-device behavior Xbox machine and storage device models
Audio MCPX APU and related audio path hw/xbox/mcpx / Xbox audio code
Input / USB Xbox controllers and USB-facing behavior Xbox/USB device models

The machine intentionally tolerates some failed memory transactions because real software can probe absent or partially implemented PCI/ISA regions. A failed probe is therefore not automatically equivalent to a fatal emulator error.

End-to-end execution

flowchart TD
    A[Guest application / Xbox kernel] --> B[x86 guest CPU state]
    B --> C[TCG vCPU execution]
    C --> D{Operation type}

    D -->|Normal guest instruction| C
    D -->|RAM access| E[Guest memory regions]
    D -->|MMIO / port I/O| F[Emulated device]

    F --> G{Device family}
    G --> H[Chipset / storage / USB / audio]
    G --> I[NV2A]

    I --> J[PFIFO]
    J --> K[PGRAPH]
    K --> L{Renderer backend}
    L --> M[OpenGL]
    L --> N[Vulkan]

    O[QEMU clocks / timers] --> F
    O --> I
    F --> P[Interrupt state]
    I --> P
    P --> B
Loading

A guest instruction that only changes CPU registers can remain inside translated host code. An I/O instruction, an MMIO access, an interrupt, an exception, a translated-code invalidation, or another asynchronous condition can force control back into emulator code so the corresponding device or scheduler work can run.

Major execution domains

xemu is easier to reason about when the program is divided into execution domains rather than files.

vCPU execution

The Xbox has one guest CPU. xemu creates one guest CPU object and the MTTCG path runs it on a dedicated vCPU thread. The thread repeatedly enters the TCG execution engine, executes translated blocks, then handles exits such as interrupts, exceptions, debug events, or waits.

See CPU & vCPU Execution.

Main/event-loop work

QEMU infrastructure handles event-loop work, timers, host I/O notifications, UI integration, and coordination that is not owned by the vCPU thread. A timer callback is not a guest instruction: it is host-side emulation work scheduled against a particular QEMU clock domain.

See Clocks & Timers.

NV2A command processing

The guest writes command data and GPU state through memory/MMIO. PFIFO consumes pushbuffer/channel work and feeds methods toward PGRAPH. PGRAPH maintains the backend-independent NV2A graphics state. The selected renderer translates that state into OpenGL or Vulkan operations.

See NV2A Graphics Architecture.

Renderer ownership

The guest does not directly submit OpenGL or Vulkan calls. PGRAPH exposes a renderer interface and backend code owns the host graphics API objects. This is why a state change can have very different host-side cost between OpenGL and Vulkan while representing the same guest-visible NV2A operation.

See OpenGL Renderer, Vulkan Renderer, and OpenGL vs Vulkan.

Guest time versus host time

Several kinds of time coexist:

  • Host time drives the process and operating-system waits.
  • Virtual time advances according to the emulated machine's execution policy.
  • Device clocks derive guest-visible counters or deadlines from emulated hardware state.
  • Presentation/frame cadence is an observation of GPU/display progress and is not interchangeable with guest CPU time.

The NV2A PTIMER is a good example: its visible counter derives from QEMU virtual time and NV2A clock configuration, then an alarm can schedule a host callback that eventually asserts a guest-visible interrupt. Changing host waiting precision does not directly change the emulated PTIMER frequency.

Memory and DMA boundaries

Devices interact with guest memory through QEMU memory regions, DMA mappings, and device-specific ownership rules. For graphics this is especially important because data may exist in several forms at once:

Guest RAM / VRAM
    ↓
backend mirror or staging resource
    ↓
host GPU resource
    ↓
possible GPU-written result
    ↓
readback / coherency operation
    ↓
guest-visible RAM / VRAM

The direction of the newest authoritative copy matters. A backend optimization is correct only if it preserves that ownership. This is why vertex uploads, surfaces, report/query results, and snapshot restore all need explicit lifetime reasoning rather than simply copying fewer bytes.

Interrupt flow

At a high level, device state becomes CPU-visible through interrupt controllers and CPU interrupt delivery:

sequenceDiagram
    participant D as Emulated device
    participant I as Interrupt routing
    participant C as vCPU / x86 CPU
    participant T as TCG dispatcher

    D->>I: Assert or clear interrupt condition
    I->>C: Update CPU-visible interrupt state
    T->>T: Observe exit/request boundary
    T->>C: Deliver interrupt at legal guest boundary
    C->>T: Continue guest execution
Loading

TCG cannot blindly run translated guest instructions forever. It has explicit exit paths so asynchronous device state can become visible at the correct architectural boundary.

Snapshot and lifecycle boundaries

Save/restore is a cross-subsystem operation. Guest RAM and device state can be replaced while host resources such as GL/Vulkan objects cannot simply be serialized as guest state. Each subsystem therefore needs a lifecycle contract:

Phase Requirement
Save preparation Flush or expose guest-visible state that currently exists only in host-side resources
Save Serialize guest/device state, not opaque host GPU handles
Restore Reconstruct derived host-side state from restored guest/device state
Shutdown Stop producers, retire or cancel asynchronous work, then destroy owned resources

Renderer pre_savevm_* and pre_shutdown_* hooks exist because renderer-owned state participates in those global lifecycle transitions.

Hardware model versus host realization

The machine is best understood as a chain of observable contracts, not a schematic simulator.

flowchart LR
    A[Guest software] --> B[CPU / PCI / MMIO / I/O contract]
    B --> C[Emulated device state]
    C --> D{Implementation boundary}
    D --> E[Pure device logic]
    D --> F[Generic QEMU device]
    D --> G[Host service]
    D --> H[Compatibility shortcut]
    E --> I[Guest-visible result]
    F --> I
    G --> I
    H --> I
Loading

Important current examples:

Area Current implementation boundary Why it matters
Pentium III CPU Architectural x86 through TCG, not cycle-accurate P6 pipeline/cache simulation Host CPU time cannot be converted directly into Xbox CPU cycles
LPC/PCI/SMBus Logical buses and callbacks, not motherboard wire edges Port/MMIO timing is emulator timing, not bus propagation time
PIT/RTC/OHCI/IDE Reused QEMU PC-compatible devices where suitable Guest semantics are inherited from mature generic device models
PC speaker QEMU pcspk is linked to PIT and realized even though a retail console does not normally expose a populated speaker Source presence is not proof of a physical user-facing device
SMC Software-facing register/event model, not PIC firmware execution Fan/LED/security/timing details can be absent while normal kernel behavior works
Video encoder Current SMBus models are mainly register arrays Analog encoder cost/behavior is not represented by those callbacks
APU Dedicated worker + host SDL queue pacing Host audio backpressure can appear as emulator timing
NV2A Register/DMA/PFIFO/PGRAPH semantics translated to GL/Vulkan Host render passes/pipelines are implementation artifacts, not NV2A objects
Memory controller Current PCI function is explicitly a pci-testdev stub Undocumented register probing can expose missing hardware

For motherboard-level examples and source FIXME boundaries, see Hardware Fidelity & Emulation Boundaries.

Performance boundaries

The main performance regions do not all represent the same kind of work:

Region Typical cost source
vCPU / TCG Translation-block dispatch, guest instruction execution, exits, memory helpers
Timers Timer-list operations, wakeups, callback frequency, guest IRQ work
PFIFO/PGRAPH Method decoding, guest GPU state changes, locking, command preparation
Shader translation Guest shader/combiner state → GLSL → compiled host shader representation
OpenGL Driver validation, implicit synchronization, shader/program/state updates
Vulkan Explicit command recording, pipeline creation, descriptors, barriers, submissions, fences
Memory coherency RAM/VRAM mirrors, surface readback, vertex/texture upload, report publication

A profile should first identify which boundary owns the time before changing code. See Performance Methodology.

Key source entry points

File / area Why start there
hw/xbox/xbox.c Machine construction and CPU/platform setup
accel/tcg/cpu-exec.c Central translated guest execution loop
accel/tcg/tcg-accel-ops-mttcg.c vCPU thread creation and MTTCG run loop
util/qemu-timer.c QEMU clock and timer-list implementation
hw/xbox/nv2a/nv2a.c NV2A device integration and lifecycle
hw/xbox/nv2a/pfifo.c Pushbuffer/channel command processing
hw/xbox/nv2a/pgraph/pgraph.c Shared NV2A graphics state/method behavior
hw/xbox/nv2a/pgraph/pgraph.h Shared renderer interface and PGRAPH ownership
hw/xbox/nv2a/pgraph/gl/* OpenGL renderer implementation
hw/xbox/nv2a/pgraph/vk/* Vulkan renderer implementation

Related pages

Clone this wiki locally