Skip to content

Hot Path vCPU REP MOVS RAM Chunks

github-actions[bot] edited this page Sep 14, 2026 · 3 revisions

REP MOVS RAM-Chunk Shortcut

Lifecycle: Performance - Unproven · Type: Memory shortcut
State: Source-backed; runtime value is not established.

Status: Source-validated shortcut candidate; not implemented or benchmarked.

Mechanism class: Runtime-admitted bulk-memory bypass of repeated guest load/store iterations.

Reviewed source: 322986f4c5502b3fa887a9605ac8cd88e9b2c579

Primary files: target/i386/tcg/emit.c.inc, target/i386/tcg/translate.c, TCG SoftMMU/TLB and dirty/invalidation code.

Summary

Current xemu already keeps REP MOVS inside translated execution; it does not necessarily return to the main dispatcher for every copied element. The emitter routes MOVS through:

gen_repz(s, ot, gen_movs);

The remaining expansion is inside the loop: each element still requires guest source/destination address work, a generic guest load and store, index updates, and count/loop handling.

The proposed shortcut admits a bounded ordinary-RAM span once and replaces many per-element operations with one native bulk copy, followed by an exact guest-progress commit.

This is a genuine shortcut because the general SoftMMU iteration remains available for MMIO, faults, overlaps, code pages, watchpoints, reverse direction, short counts, and every unproven case.

Current route

flowchart TD
    A[Guest REP MOVS] --> B[Translated repeat loop]
    B --> C[Calculate guest source and destination]
    C --> D[Guest load through normal memory path]
    D --> E[Guest store through normal memory path]
    E --> F[Update ESI/EDI and ECX]
    F --> G{Count remains and no required exit?}
    G -->|Yes| B
    G -->|No| H[Continue/exit guest execution]
Loading

This route is general and preserves per-element faults, side effects, memory-type routing, dirty tracking, code invalidation, watchpoints, direction, and interruption points.

Initial shortcut scope

The first experiment should admit only:

instruction: REP MOVSB
address size: one explicitly tested mode
DF: clear / forward
count: above a minimum threshold
source and destination: ordinary RAM
source and destination spans: within currently admitted page/window
overlap: rejected
watchpoints/breakpoints: absent
MMIO/ROM/aliases: rejected
write permission: proven
code-page/self-modifying-code responsibility: understood or rejected
chunk length: bounded for interrupts and device progress

Do not begin with reverse direction, element widths above one byte, overlap, cross-page spans, or raw writes to translated code pages.

Candidate route

flowchart TD
    A[Guest REP MOVSB] --> B{Candidate mode and count threshold?}
    B -->|No| R[Reference translated iteration]
    B -->|Yes| C[Resolve source and destination access]
    C --> D{Both ordinary RAM and safe bounded spans?}
    D -->|No| R
    D -->|Yes| E{Forward and non-overlapping?}
    E -->|No| R
    E -->|Yes| F[Choose min of count, source span, destination span and chunk cap]
    F --> G[Execute native bounded copy]
    G --> H[Perform required dirty/code-invalidation publication]
    H --> I[Commit exactly completed ESI, EDI and ECX progress]
    I --> J{Count remains and no exit/interrupt pending?}
    J -->|Yes| C
    J -->|No| K[Retry/continue architectural guest path]
Loading

Illustrative helper shape:

/* Interfaces are illustrative, not current xemu APIs. */
size_t chunk = admit_rep_movsb_ram_chunk(env, src, dst, count);
if (chunk != 0) {
    execute_native_copy(src_host, dst_host, chunk);
    publish_guest_write_effects(dst, chunk);
    commit_rep_movs_progress(env, chunk);
    return;
}
execute_reference_iteration(env);

The candidate should retry the architectural loop after every bounded chunk. This preserves a clear place to observe exit requests, interrupts, changed mappings, and remaining count.

Why it may help

The possible avoided work is:

  • repeated software-TLB probes for source and destination;
  • repeated slow-path labels/branches;
  • per-element guest address calculation;
  • per-element ESI/EDI/ECX updates;
  • per-element loop branches;
  • repeated load/store helper transitions when an access misses the fast path.

A rough opportunity model is:

eligible bytes copied
× current memory-access/check cost per byte
- admission and chunk-publication cost

Small copies may lose. Measure count distributions and admitted bytes before selecting a threshold.

Why memcpy() is not a complete design

Guest MOVS is architectural execution, not a generic library copy.

Overlap

Sequential MOVS behavior can differ from memcpy() and memmove() when ranges overlap. The first shortcut rejects overlap rather than selecting a library function by intuition.

Fault progress

A fault can occur after some elements have completed. Guest indices/count must represent exactly completed work. Restricting a chunk to already admitted page/window spans avoids claiming progress across an unvalidated second page.

Destination side effects

Raw host writes may need to publish:

  • dirty-memory state;
  • translated-code invalidation for self-modifying guest code;
  • display/device client dirtiness;
  • watchpoint/debug events;
  • snapshot/migration dirtiness;
  • write-protection/fault behavior.

If those responsibilities cannot be satisfied cheaply and exactly, the candidate must reject the range.

Interruptibility and fairness

Large guest REP operations can be interruptible between iterations. A single unbounded host copy can delay interrupts or device progress. Use a conservative chunk cap and recheck exit/interrupt state between chunks.

Address-admission contract

A valid source plan must prove:

  • current guest virtual-to-physical translation;
  • readable permission;
  • ordinary RAM backing;
  • contiguous host bytes for the admitted length;
  • no watchpoint or side-effecting memory region;
  • mapping/TLB epoch remains valid for the operation.

A valid destination plan must additionally prove:

  • writable permission;
  • complete dirty/code invalidation handling;
  • no ROM/MMIO/alias behavior requiring callbacks;
  • no unsupported overlap with the source.

Do not reuse an admitted host pointer across unrelated guest instructions without a mapping-generation design. The first experiment resolves each chunk at runtime.

Code and ownership map

Area Role
target/i386/tcg/emit.c.inc::gen_MOVS() Instruction translation entry
gen_repz / gen_movs path Current translated per-element loop
TCG SoftMMU/TLB access generation Current source/destination memory checks
RAM MemoryRegion/address-space mapping Host pointer and span admission
dirty-memory and TB invalidation Required destination publication
CPU exit/interrupt state Chunk interruption/fairness
ESI/EDI/ECX architectural state Exact progress commit

Evidence counters

Counter Unit Meaning
rep_movs_exec instructions Dynamic use
rep_movs_requested_bytes bytes Total guest request size
rep_movs_candidate_attempts chunks Admission tried
rep_movs_admitted_chunks chunks Native route entered
rep_movs_admitted_bytes bytes Useful work bypassed
rep_movs_reference_bytes bytes General route retained
rep_movs_reject_* chunks Count, direction, overlap, page, MMIO, watchpoint, code, permission, mapping
tlb_checks_avoided estimated/actual operations Local work removal
chunk_exit_checks checks Interruptibility overhead
fault_progress_mismatches cases Correctness failure

Report the distribution of chunk sizes. A high hit count consisting only of 4-byte chunks can be slower than the reference.

Required correctness tests

Counts and boundaries

  • zero count;
  • one byte;
  • below/at/above admission threshold;
  • source ending at page boundary;
  • destination ending at page boundary;
  • unmapped or protected second page;
  • maximum bounded chunk and multi-chunk completion.

Memory classes

  • ordinary RAM;
  • ROM/read-only destination;
  • MMIO source or destination;
  • RAM alias/remap;
  • watchpoint;
  • translated code page/self-modifying destination;
  • snapshot/dirty tracking active.

Semantics

  • forward non-overlap positive case;
  • forward overlap in both relative directions — must reject initially;
  • DF set — must reject initially;
  • different address-size/count register modes;
  • source/destination wraparound;
  • interrupt/exit request between chunks;
  • mapping invalidation between chunks;
  • fault after partial reference progress.

Negative control

Deliberately allow one unsafe cross-page or overlap case in a test build. The oracle must detect wrong data, wrong fault point, or wrong architectural progress.

Expected profile signature

large REP MOVSB operations are dynamically common
admitted bytes are substantial
per-byte TLB/address/bookkeeping operations fall
host copy execution becomes visible
vCPU time per fixed copy workload improves
retail guest progress improves or CPU falls
fault, dirty and architectural progress remain exact

A synthetic memory test alone is insufficient. Identify titles or boot/runtime operations that actually execute eligible copies.

Failure modes

  • Claiming the current implementation dispatches once per byte when it already loops in translated code.
  • Replacing overlapping MOVS with memcpy().
  • Crossing a possible fault boundary and over-advancing guest state.
  • Bypassing write dirtying or self-modifying-code invalidation.
  • Treating MMIO/ROM/aliases as RAM.
  • Holding stale host pointers across mapping changes.
  • Copying so much at once that interrupts/device progress are delayed.
  • Setting a threshold without measuring copy-size distribution.
  • Using total copied bytes without proving shortcut admission.

Qualification plan

  1. Count REP forms, direction, count distribution, memory class, and hot guest PCs.
  2. Build a source/destination span-admission diagnostic without changing execution.
  3. Implement only forward non-overlapping REP MOVSB within admitted RAM spans.
  4. Bound chunks to one proven window and a conservative interrupt cap.
  5. Preserve the reference loop for every rejection.
  6. Build exact data, register/count, fault-point, dirty-state, and invalidation tests.
  7. Inspect optimized generated code and memory slow-path counts.
  8. Measure synthetic fixed-byte work and representative titles separately.
  9. Expand widths/directions/pages only as independent follow-up experiments.

Related pages

Full technical reference

Primary reference: This subject page is the design and research reference for REP MOVS RAM Chunks. Pull requests are implementation/test history only.
Lifecycle: Performance - Unproven · Mechanism: Bounded guest-memory loop shortcut
Reviewed source: 322986f4c5502b3fa887a9605ac8cd88e9b2c579 · Acceptance class: intended exact or behavior-preserving for its admitted scope

1. Scope

For a narrow admitted forward non-overlapping RAM case, copy a bounded chunk natively instead of executing generic guest address/load/store/bookkeeping for every element.

This entry remains Unproven: the source path and opportunity are concrete, but no accepted xemu runtime result has established that the candidate improves representative workloads. The page defines what must be bypassed, what remains mandatory, and how the hypothesis can be rejected.

2. Source seams

File / function Role
target/i386/tcg/translate.c REP MOVS translation and in-TB loop
tcg/* guest memory access, dirty tracking and code invalidation

3. Current execution path

flowchart TD
    N0["Per element: compute source/destination"]
    N1["Guest load"]
    N0 --> N1
    N2["Guest store"]
    N1 --> N2
    N3["Advance ESI/EDI"]
    N2 --> N3
    N4["Decrement ECX"]
    N3 --> N4
    N5["Check loop/exit"]
    N4 --> N5
    N6["Repeat"]
    N5 --> N6
Loading

4. Candidate execution path

flowchart TD
    N0["Admit bounded ordinary-RAM spans"]
    N1["Select safe chunk"]
    N0 --> N1
    N2["Native copy/rep movsb"]
    N1 --> N2
    N3["Publish dirty/code invalidation"]
    N2 --> N3
    N4["Commit exact guest progress"]
    N3 --> N4
    N5["Check interrupt/remaining count"]
    N4 --> N5
    N6["Fallback otherwise"]
    N5 --> N6
Loading

5. Why it may help

Current implementation already loops inside translated code, so the opportunity is not 'avoid dispatcher per byte.' It is remove repeated generic memory preparation and register bookkeeping for a common safe span. Fault and partial-progress semantics make an unrestricted memcpy replacement invalid.

6. Work removed

  • Repeated software memory-access setup per element
  • Repeated index/count bookkeeping
  • Some loop branches

7. Work that remains mandatory

  • Dirty tracking and translated-code invalidation
  • Interruptibility
  • Fault/partial progress
  • Overlap/direction semantics
  • MMIO/watchpoint fallback

8. Implementation sketch

; After narrow admission has produced host pointers and a safe count
mov     rsi, host_src
mov     rdi, host_dst
mov     rcx, admitted_count
rep movsb
; Then commit guest ESI/EDI/ECX for exactly rcx completed bytes.

The sketch defines the intended boundary; it is not a complete patch and does not replace source review, ownership design, or focused tests.

9. Correctness contract

  • Initial route is REP MOVSB, forward, non-overlapping, ordinary RAM.
  • Chunk stays inside validated mappings and a bounded interrupt interval.
  • Guest registers reflect exact completed progress on exit/fault.
  • Destination dirty/code invalidation is correct before later execution.

10. State, ownership, invalidation, and fallback

Admission is per chunk; host pointers do not survive remap/TLB changes. Chunk size bounds interrupt latency. Writes to code pages trigger required invalidation. Any overlap, backward direction, watchpoint, MMIO, permission/fault ambiguity uses reference iteration.

The maintained reference path remains the fallback whenever admission, capability, lifetime, or validation is uncertain. A fast result with an unproven dependency is not acceptable as an exact optimization.

11. Advantages

  • Can remove large amounts of generated memory-loop overhead
  • Native string engines are highly optimized
  • Clear size/eligibility counters
  • Narrow exact subset possible

12. Costs and failure modes

  • Fault/partial progress complexity
  • Overlap semantics
  • Dirty/code invalidation
  • Interrupt latency
  • Small copies may lose to setup
  • Backend/host variation

13. Evidence counters

Counters must be cheap, subsystem-owned, and snapshotted outside the hot loop. Record at least:

  • REP_MOVS_invocations
  • requested_bytes
  • admitted_bytes
  • chunk_size_distribution
  • reference_rejections_by_reason
  • memory_checks_avoided
  • faults/interrupts
  • CPU time per fixed copy

A local reduction is not enough. Evidence must connect route reachability and removed work to fixed guest progress, CPU/GPU time where applicable, and p95/p99 behavior.

14. Qualification matrix

  • Zero/tiny/large counts
  • Page boundary and unmapped second page
  • Forward/backward
  • Overlap patterns
  • Code-page destination
  • MMIO/watchpoint rejection
  • Interrupt during long copy
  • Partial progress/fault
  • Random differential memory/register state

Correctness runs may use validation layers, detailed comparisons, and fault injection. Performance acceptance must use optimized Release builds with matching symbols and minimal instrumentation.

15. Acceptance rule

Promote only a narrow subset after exact progress/fault/invalidation tests and representative workloads show common large admitted chunks.

16. Rejection rule

Reject broad memcpy/memmove substitution, unbounded chunks, or any path that cannot reproduce guest progress and memory side effects.

17. Related architecture and history

CPU-and-vCPU-Execution · Performance-Unproven · Hot-Path-TCG-Direct-RAM-Read-Windows · Memory-and-DMA

PR pages may be linked as supporting evidence, but they are not substitutes for this reference.

Clone this wiki locally