Skip to content

Hot Path vCPU Recognized Poll Loop Wait

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

Recognized Guest Poll-Loop Wait

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

Status: Conditionally applicable, high-risk research candidate; not implemented and not benchmarked.

Mechanism class: Guarded shortcut / guest-execution bypass.

Reviewed source: 322986f4c5502b3fa887a9605ac8cd88e9b2c579

Subsystem: vCPU/TCG and selected device completion events.

Summary

The existing PGRAPH fence shortcut removes pgraph.lock from one exact busy-polled register read. It does not remove the guest load/compare/branch loop around that read. A recognized poll-loop shortcut would detect one proven side-effect-free wait loop, sleep the vCPU until the producer changes the relevant condition or another wake reason occurs, then retry the original guest instructions.

This can remove thousands of guest instructions and MMIO reads, but it is much riskier than making one register access cheaper. Generic spin-loop recognition is not acceptable. The first implementation must target one profiled loop and one explicit device event.

Current flow

flowchart TD
    A[Guest enters fence/status polling loop] --> B[Translated load]
    B --> C[MMIO/device read]
    C --> D[Guest compare and branch]
    D -->|Condition false| B
    D -->|Condition true| E[Guest continues]

    F[Producer updates completion state] --> C
Loading

With the current fence-read fast path, the MMIO read may avoid a mutex, but the vCPU still executes each loop iteration.

Candidate flow

sequenceDiagram
    participant CPU as vCPU / recognized TB
    participant Dev as Device producer
    participant Wait as Event/sequence wait

    CPU->>CPU: Validate exact loop plan and side-effect-free state
    CPU->>Dev: Read condition and producer sequence
    CPU->>CPU: Condition still false?
    alt condition false
        CPU->>Wait: Register wait using observed sequence
        Dev->>Dev: Publish completion/state
        Dev->>Wait: Signal and advance sequence
        Wait-->>CPU: Wake on device, interrupt, timer, stop or deadline
        CPU->>CPU: Retry original guest loop
    else condition true
        CPU->>CPU: Execute original exit path
    end
Loading

The original loop must execute again after waking. The shortcut does not fabricate final flags, counters, instruction pointer state, or timeout results.

Admission must describe an exact loop

A plan must bind to a validated translated-code region and include at least:

  • guest PC range and code identity/hash;
  • the exact load address/register width;
  • comparison and branch condition;
  • proof that the loop body has no other memory/device side effects;
  • proof that it does not update a guest counter or timeout state;
  • the producer event/sequence that can make progress;
  • interrupt, timer, reset, stop, and snapshot wake conditions;
  • invalidation when guest code or mapping changes.

A loop that merely resembles a known pattern is not enough.

Lost-wakeup-safe handshake

The basic wait must follow a sequence protocol:

1. Read producer sequence.
2. Re-read the guest-visible condition.
3. If complete, run the original loop normally.
4. Register/sleep only if the sequence still matches.
5. Producer updates state, advances the sequence, and signals.
6. Wake and retry original guest code.

The wait must handle completion immediately before registration, during registration, and immediately after sleep begins. A plain “check then sleep” is incorrect.

Wake reasons

The vCPU must wake for more than the target device event:

  • target condition publication;
  • pending guest interrupt or NMI;
  • timer/deadline expiration;
  • VM stop/pause/shutdown/reset;
  • debugger/watchpoint activity;
  • snapshot/load transition;
  • TLB/TB invalidation or self-modifying code;
  • spurious wakeup;
  • safety watchdog for a producer that never completes.

After any wake, the original loop determines whether it exits.

Emulation boundary

The guest observes instruction effects, interrupt timing, timeout behavior, and device completion—not the host CPU cycles spent polling.

The equivalent contract is narrow:

For an admitted loop, replacing repeated iterations with a wait must produce the same observable loop exit, interrupt recognition, timeout behavior, and device ordering as executing those iterations normally.

If the shortcut intentionally removes a guest timeout or counter update, it is an approximation and must be classified separately.

Why it may help

Potential benefit:

recognized loop iterations avoided
× translated instruction and MMIO cost per iteration
− recognition, registration and wake cost

It can reduce vCPU CPU time even when guest completion latency does not change. That can still be valuable if the freed host core improves other threads or power use.

Seen in xemu

Current source explicitly says the Xbox D3D runtime busy-polls NV_PGRAPH_PATT_COLOR0. The existing narrow fast path confirms one important polling target and ordered producer publication.

No current source evidence identifies the exact guest instruction loops, their timeout behavior, or their side effects. A Release trace plus guest disassembly is required before creating a recognizer.

Code and ownership map

Area Role
hw/xbox/nv2a/pgraph/pgraph.c Current exact fence register fast read and producer ordering contract
x86 translator / TCG TB metadata Candidate loop identification and invalidation
vCPU execution/exit path Sleep, wake, interrupt/deadline handling and retry
PGRAPH/PFIFO producer Completion sequence publication and signal
snapshot/reset/debug paths Cancel waits and invalidate plans

Candidate implementation stages

Stage 1: evidence only

  • identify the exact hot guest PCs and loop forms;
  • count iterations and MMIO reads;
  • resolve whether the loop includes timeout/counter side effects;
  • map the producer event that changes the condition.

Stage 2: one hard-coded diagnostic recognizer

Use one title/build/loop signature with a non-persistent switch. The goal is to test the scheduling and wake contract, not create a general optimizer.

Stage 3: validated reusable plan

Only after the diagnostic succeeds should the design support code identity, mapping epochs, sequence publication, and invalidation as first-class data.

Negative controls

  1. Signal completion before, during, and after registration.
  2. Inject spurious wakeups.
  3. Leave the producer incomplete and require timer/interrupt progress.
  4. Add a guest counter increment inside the loop; recognition must fail.
  5. Add a read from a side-effecting register; recognition must fail.
  6. Add timeout arithmetic; recognition must fail unless modeled exactly.
  7. Modify the guest code after translation; the plan must invalidate.
  8. Remap the polled address.
  9. Restore a snapshot while the vCPU is asleep.
  10. Trigger an interrupt that the original loop would recognize.

Counters

poll_plan_candidates
poll_plan_admitted
poll_plan_rejected_by_reason
poll_wait_entries
poll_wait_wakes_device
poll_wait_wakes_interrupt
poll_wait_wakes_timer
poll_wait_spurious
poll_wait_timeouts
poll_iterations_avoided
mmio_reads_avoided
vcpu_cpu_ns
producer_completion_latency
false_recognition_failures

Risks

  • Lost wakeup and permanent hang.
  • Delayed or missed interrupt recognition.
  • Skipping guest timeout/counter behavior.
  • False recognition of a loop with side effects.
  • Self-modifying code or mapping changes leaving a stale plan.
  • Deadlock if the producer requires work from the sleeping vCPU or BQL owner.
  • Better host CPU usage but worse guest latency.
  • Title/build signatures becoming brittle maintenance hacks.

Qualification

  1. Capture optimized Release + matching DWARF evidence for the target loop.
  2. Publish guest disassembly and exact loop semantics.
  3. Build deterministic lost-wakeup, interrupt, timeout, side-effect, SMC, restore, and deadlock tests.
  4. Keep the normal guest loop as the maintained reference route.
  5. Run same-binary route A/B with effective-state and wake counters.
  6. Compare vCPU CPU, producer latency, guest progress, p95/p99, and correctness.
  7. Limit any initial product exposure to the exact proven pattern.
  8. Reject generic recognition until multiple independently proven loops share one safe contract.

Disposition

Conditionally applicable and potentially hard-hitting, but only after identifying a specific loop. The source supports the fence-poll motivation; it does not support a generic spin-loop bypass today.

Related pages

Full technical reference

Primary reference: This subject page is the design and research reference for Recognized Poll-Loop Wait. Pull requests are implementation/test history only.
Lifecycle: Performance - Unproven · Mechanism: Guest-execution bypass with event wake
Reviewed source: 322986f4c5502b3fa887a9605ac8cd88e9b2c579 · Acceptance class: intended exact or behavior-preserving for its admitted scope

1. Scope

Recognize one exact side-effect-free guest polling loop and sleep the vCPU until the producing emulated event, interrupt, timer, invalidation, or deadline requires retrying the original loop.

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
hw/xbox/nv2a/pgraph/* guest-polled PGRAPH register and producer event
target/i386/tcg/translate.c loop translation/code identity
accel/tcg/* vCPU wait, interrupt and TB invalidation boundaries

3. Current execution path

flowchart TD
    N0["Guest load MMIO/status"]
    N1["Compare"]
    N0 --> N1
    N2["Conditional branch back"]
    N1 --> N2
    N3["Repeat many iterations"]
    N2 --> N3
    N4["Eventually observe producer change"]
    N3 --> N4
Loading

4. Candidate execution path

flowchart TD
    N0["Validate exact loop plan"]
    N1["Check condition and producer sequence"]
    N0 --> N1
    N2["Register wait without lost wake"]
    N1 --> N2
    N3["Sleep vCPU"]
    N2 --> N3
    N4["Wake on event/interrupt/timer/invalidation"]
    N3 --> N4
    N5["Retry original guest loop"]
    N4 --> N5
Loading

5. Why it may help

Making each polled read cheaper still leaves the guest executing load/compare/branch. A proven wait loop can remove many iterations, but generic spin-loop recognition is unsafe because loops may contain timeout arithmetic, counters, side-effecting reads, or rely on interrupt timing.

6. Work removed

  • Repeated guest instructions
  • Repeated MMIO/status reads
  • TB dispatch/chaining for the loop
  • Host CPU busy time while producer is pending

7. Work that remains mandatory

  • Final original load/compare/exit semantics
  • Interrupt/timer recognition
  • Producer progress
  • Timeout behavior if present
  • Reference execution on any uncertainty

8. Implementation sketch

uint64_t seq = producer_sequence(plan->producer);
if (!poll_condition_satisfied(plan) &&
    validate_poll_loop_code(plan) &&
    register_waiter_if_sequence_unchanged(plan, seq)) {
    cpu_wait_until_event_or_exit(cpu, plan->deadline);
    return RETRY_ORIGINAL_GUEST_LOOP;
}
return EXECUTE_REFERENCE_LOOP;

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

  • Recognition binds exact guest PC/code bytes, MMIO read width/address, compare and branch, with no side effects.
  • Producer sequence handshake prevents lost wakeups.
  • Interrupts, timers, stop/reset, self-modifying code and remap invalidate/wake.
  • On wake, original code rechecks the condition.

10. State, ownership, invalidation, and fallback

The plan is attached to translated-code identity and one producer event. TB invalidation/self-modification removes it. Wait registration is synchronized with the producer sequence. Snapshot/reset cancels waiters and rebuilds state.

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 dramatically reduce vCPU CPU use in hot waits
  • Does not fabricate final guest register/flags
  • Narrow title/runtime loop can be thoroughly tested
  • Useful even if completion latency is unchanged

12. Costs and failure modes

  • Lost wakeups/deadlocks
  • False recognition changes guest work
  • Timeout/interrupt timing differences
  • Producer may require the waiting vCPU to run
  • Title/code-version specificity

13. Evidence counters

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

  • recognized_loop_entries
  • iterations_avoided
  • MMIO_reads_avoided
  • wait_duration
  • spurious_wakes
  • reference_fallbacks_by_reason
  • producer_latency
  • vCPU CPU time

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

  • Completion before/during/after registration
  • Spurious wake and never-completing producer
  • Interrupt/timer arrival
  • Loop with counter/side effect/timeout must reject
  • Self-modifying code
  • MMIO remap
  • Snapshot/reset
  • Producer dependency/deadlock analysis

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 one proven loop at a time with a complete wake/invalidation model, large avoided-iteration evidence, and unchanged guest completion behavior.

16. Rejection rule

Reject generic heuristics or any recognized loop whose producer, timeout, or side effects are not fully understood.

17. Related architecture and history

CPU-and-vCPU-Execution · Performance-Unproven · Hot-Path-PGRAPH-Fast-Fence-Polling · Timing-Clocks-and-Timers

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

Clone this wiki locally