Difference between revisions of "The Execution Frontier"

From Open-IOV
Jump to navigation Jump to search
m (Fix repository links: point to the cgit tree URLs (git.vgpu.io/open-iov.git/tree/...))
m (Status refresh 2026-10-20: guest CUDA kernels execute on the physical GPU (vector-add/matmul/transformer green); boot-poisoning defect fixed)
Line 3: Line 3:
= The Execution Frontier =
= The Execution Frontier =


<blockquote>'''What this page is.''' The current leading edge of guest-facing execution: the chain that must fire for a stock guest CUDA kernel to run on the physical GPU, what has been proven about it, where it stops, how we know, and the open lines of investigation and theories. It is evidence-led: every statement carries a live observation, a decompilation finding, or a clearly labelled theory. Condensed from [https://git.vgpu.io/open-iov.git/tree/docs/04-implementation/03-execution-frontier.md <code>../docs/04-implementation/03-execution-frontier.md</code>]; the docs tree wins on disagreement.</blockquote>
<blockquote>'''What this page is.''' The state of guest-facing execution: the chain that must fire for a stock guest CUDA kernel to run on the physical GPU, what has been proven about it, how we know, and where the leading edge is now. The chain fires end to end: verified guest CUDA clients execute on the physical GPU and wake up correctly; the leading edge is now breadth and hardening. It is evidence-led: every statement carries a live observation, a decompilation finding, or a clearly labelled theory. Condensed from [https://git.vgpu.io/open-iov.git/tree/docs/04-implementation/03-execution-frontier.md <code>../docs/04-implementation/03-execution-frontier.md</code>]; the docs tree wins on disagreement.</blockquote>


Status: 2026-10-12 (source page dated 2026-10-06), tree <code>master @ 2f066727</code>. Tags: <code>[live]</code> observed; <code>[wip]</code> partial; <code>[wall]</code> current blocker; theories are labelled as such.
Status: 2026-10-20, tree <code>master @ 16291c72</code>. Tags: <code>[live]</code> observed; <code>[wip]</code> partial; <code>[wall]</code> current blocker; theories are labelled as such.


== 1. The chain that should fire ==
== 1. The chain that should fire ==
Line 52: Line 52:
| 6
| 6
| '''Inline-QMD install''' (descriptor materialised)
| '''Inline-QMD install''' (descriptor materialised)
| <code>[wall]</code> not observed
| <code>[live]</code> observed
|-
|-
| 7
| 7
| '''Engine reads the QMD'''
| '''Engine reads the QMD'''
| <code>[wall]</code> not observed
| <code>[live]</code> observed
|-
|-
| 8
| 8
Line 64: Line 64:
| 9
| 9
| GR dispatches the grid to the SMs
| GR dispatches the grid to the SMs
| never observed on this stack
| <code>[live]</code> observed (the guest's results verify)
|-
|-
| 10
| 10
| Engine authors release + channel semaphore
| Engine authors release + channel semaphore
| absent for forwarded launches
| <code>[live]</code> engine-authored releases relay to the guest
|-
|-
| 11
| 11
| Host relays completion; guest wakes
| Host relays completion; guest wakes
| the guest waits and times out
| <code>[live]</code> the guest's synchronisation waits resolve
|}
|}


'''One-line summary:''' the guest, the emulation, the forwarding path and the front-end are live; the '''launch-descriptor install path''' (stages 6–7) is the leading edge, and with it stages 9–11.
'''One-line summary:''' the whole chain is live; the leading edge is now breadth and hardening — the large-buffer staged-transfer class, reproducibility across boots, and per-guest execution isolation.


== 2. Where the leading edge is ==
== 2. Where the leading edge is ==


A stock guest program now reaches its kernel launch and submits it through the forwarding path. On the wire the ring entry is consumed and the front-end methods run — but the launch descriptor is never materialised, the engine never reads a QMD, no engine-authored completion appears, and the guest blocks in its synchronisation wait.
A stock, unmodified guest CUDA program executes its kernels on the physical GPU and verifies its results. On fresh boots the vector-add client (<code>victory_mail</code>) prints <code>VADD n=32768 bad=0</code> + <code>STATUS OK</code>, the matrix-multiply client (<code>victory_matmul</code>) prints <code>MATMUL n=256 bad=0</code> + <code>STATUS OK</code>, and a transformer kernel prints <code>dh=256 seq=64 bad=0</code>, <code>FFN4 layers=4 bad=0</code> + <code>STATUS OK</code>. The executing engine is the physical GPU under the module's own real GSP-RM session; the host CUDA bridge is not part of this path. Engine-authored completions relay to the guest and its synchronisation waits resolve.


This is '''not''' a context-validity wall (ruled out at dispatch) and '''not''' a window-mapping wall for the descriptor destination (that install is accepted). The wall is the '''form of the launch method stream''': what the front-end requires in order to install the inline descriptor, and what the engine requires in order to read and dispatch it.
The leading edge has moved from the launch chain itself — it fires — to breadth and hardening around it:
 
* '''The large-buffer staged-transfer class.''' Multi-megabyte staged transfers between guest memory and device memory are under repair: some large multi-chunk clients still mis-verify.
* '''Reproducibility across boots.''' A boot-poisoning defect was root-caused and fixed: under the driver's status-queue mode the emulation read the wrong queue cursor, so under load the reply ring could desynchronise and the first CUDA client would fail (the user-visible <code>STATUS FAIL</code>-then-freeze report). Re-measurement across fresh boots is in progress.
* '''Per-guest execution isolation.''' Multiple mediated devices with different emulated VRAM sizes and multiple guests already coexist at the device level; per-guest execution isolation for multiple simultaneous CUDA guests is in progress.
 
No breadth beyond these is claimed: OpenGL/Vulkan, Windows guests, migration and performance numbers remain planned.


== 3. How we know (observables and their limits) ==
== 3. How we know (observables and their limits) ==
Line 91: Line 97:
! What it does not prove
! What it does not prove
|-
|-
| Ring entry consumed; ring cursor advances
| Client verification output (<code>bad=0</code> + <code>STATUS OK</code>)
| the front-end is alive and fetching
| the guest executed its kernel and verified its results
| nothing about the engine
| by itself, which engine produced the results
|-
|-
| Method execution on the ladder channel
| Engine-authored release relayed to the guest
| the front-end can execute the method vocabulary
| the engine executed the launch and the relay works
| '''not''' engine execution — these signals can be front-end-authored
| nothing about other launches
|-
|-
| Descriptor buffer prewritten with a detectable sentinel
| The guest's synchronisation wait resolving
| whether the descriptor was materialised after submission
| completion reached the guest through the relay
| a read does not modify memory; the sentinel detects installs, not reads
| nothing about other launches
|-
|-
| Install sentinel unchanged after submit
| Ring entry consumed; ring cursor advances
| the inline-install method did not run
| the front-end is alive and fetching
| it does not say why
| '''not''' engine execution — front-end signals are necessary but not sufficient
|-
|-
| Engine-authored release word absent; poll times out
| Reproduction across fresh boots
| the engine did not complete the launch
| the path is not a lucky boot
| it does not say whether the engine started
| no "every boot" claim yet while re-measurement is in progress
|-
|-
| No GR fault recorded
| No GR fault recorded
| the engine did not raise this error
| the engine did not raise this error
| silence is not health: a skipped launch is silent by construction
| silence is not health: a skipped launch is silent by construction
|-
| Channel instance context flag set
| the channel is context-valid at dispatch
| nothing about the descriptor path
|}
|}


'''Consequence:''' progress on this frontier must be measured by an '''engine-authored''' signal (the release word advancing) — not by front-end signals, which we have already learned to distinguish.
'''Consequence:''' acceptance is verified guest results plus the engine-authored release; a green run counts as progress only when it reproduces across fresh boots.


== 4. What is exonerated (do not relitigate) ==
== 4. What is exonerated (do not relitigate) ==
Line 129: Line 131:
* The shared context-buffer one-shot rule — traced to a shared per-GPU buffer already initialised in the same cycle; not the dispatch delta.
* The shared context-buffer one-shot rule — traced to a shared per-GPU buffer already initialised in the same cycle; not the dispatch delta.
* Parenting/TSG for the fetch — both variants fetch identically.
* Parenting/TSG for the fetch — both variants fetch identically.
* The copy-engine path — CE-class work, releases and fault relay are live (default off); the GR path is a separate problem.
* The copy-engine path — CE-class work, releases and fault relay are live (default off); the GR path is separate.
* The descriptor-gate line of investigation (the old T1–T4 theories) — the inline-descriptor install, the engine read, the dispatch, the engine-authored release and the guest wake-up are all observed; closed by observation.
* The old boot-poisoning defect — root-caused to the status-queue consumption cursor and fixed.


== 5. The clear issues (ranked) ==
== 5. The clear issues (ranked) ==


'''Issue A — the forwarded stream carries a verbatim guest prelude that cannot complete.''' The forwarded stream includes a verbatim copy of the guest's prelude whose inline-data writes target addresses not present in the engine's view of the channel's page tables, and the referenced data is not relocated. The shorter, proven stream shape fires its tail (channel semaphore) but still does not schedule the descriptor.
'''Issue A — the large-buffer staged-transfer class.''' Multi-megabyte staged transfers between guest memory and device memory are under repair: some large multi-chunk clients still mis-verify.


'''Issue B — the descriptor-virtualization control method is absent.''' The method that arms the inline-descriptor install path is not present in the forwarded stream. Fixing it should materialise the descriptor — falsifiable in one cycle by watching the sentinel and the engine-read signal.
'''Issue B — reproducibility across boots (re-measurement).''' The boot-poisoning defect (wrong status-queue consumption cursor under the driver's status-queue mode; the reply ring could desynchronise under load, the first client would fail) was root-caused and fixed. Re-measurement across fresh boots is in progress; no "every boot" claim is made until it completes.


'''Issue C — diagnostic hygiene.''' The sentinel placed at word 0 overlaps real descriptor fields; it must be moved to an unused word so diagnostics do not perturb what they measure.
'''Issue C — per-guest execution isolation.''' Multiple mediated devices with different emulated VRAM sizes and multiple guests coexist at the device level; per-guest execution isolation for simultaneous CUDA guests is in progress.


== 6. Lines of investigation (live) ==
== 6. Lines of investigation (live) ==


# '''Restore the proven launch shape''' as the baseline and '''re-add the virtualization control method''' — one variable at a time, with the install sentinel and the engine-read signal as the readout.
# '''Repair the large-buffer staged-transfer class''' — the three green clients stay the regression battery and must remain green throughout.
# '''Relocate or drop the verbatim prelude''' so inline-data writes target addresses present in the engine's view, or replace it with the host-side staging the proven shape already uses.
# '''Complete the fresh-boot re-measurement''' — demonstrate the fixed boot path across fresh boots before claiming boot-to-boot reproducibility.
# '''Move the sentinel''' and re-run to confirm the readout is clean.
# '''Per-guest execution isolation''' — build from the device-level coexistence to isolation for simultaneous CUDA guests.
# '''Diff against a known-good reference''' — our own ladder dispatching a descriptor built from the same source material, or a captured working launch of the stock stack on the same GPU — converting the remaining work from inference to differential.
# '''Hold the acceptance battery''' — vector-add, matrix-multiply and the transformer kernel; each entry is accepted only on its own verification output (<code>bad=0</code> + <code>STATUS OK</code>).
# '''Offline probing''' of any rule the front-end or engine is believed to require, using the firmware debugger before spending a supervised cycle ([[risc-v-gsp-rm-debugger|<code>Riscv-GSP-RM-Debugger.md</code>]]).
 
== 7. Theories (labelled; not yet proven) ==


* '''T1 — the virtualization control is the gate.''' The front-end will not materialise an inline descriptor until the control method enables the install path.
== 7. Theories, resolved ==
* '''T2 — materialise-then-read.''' The engine only schedules a descriptor that exists in its own view; an install targeting unmapped destinations aborts silently rather than faulting.
* '''T3 — the verbatim prelude poisons the launch.''' Its refused writes leave the launch path unable to schedule the descriptor.
* '''T4 — relocation is the missing transform.''' The guest's descriptor is valid for the guest's view of memory; the forwarding path must relocate referenced data into the channel's view before install.


Each theory has a one-cycle falsifier: the install sentinel, the engine-read signal, and the engine-authored release, in that order.
The descriptor-gate theories (T1–T4) are resolved and are not kept as open: the inline-descriptor install, the engine's QMD read, the grid dispatch, the engine-authored release and the guest wake-up are all directly observed, so the launch chain they questioned is proven end to end. The remaining work is engineering (large-buffer transfers, boot-to-boot reproducibility, per-guest isolation), each with an acceptance signal named before the work.


== 8. Claim discipline ==
== 8. Claim discipline ==


* '''Engine-authored release is the only proof of execution.''' Front-end signals are necessary but not sufficient.
* '''Engine-authored release is the acceptance signal for execution''' — now observed end to end; the guest's own verification (<code>bad=0</code> + <code>STATUS OK</code>) is the guest-side acceptance signal.
* '''Front-end signals are necessary but not sufficient.''' Ring cursor and front-end method execution can be front-end-authored; they never substitute for the engine-authored release.
* '''Silence is not health.''' No fault recorded does not mean no fault occurred.
* '''Silence is not health.''' No fault recorded does not mean no fault occurred.
* '''Emulator verdicts are instruction/memory-level.''' They bound behaviour, never timing or device environment.
* '''Emulator verdicts are instruction/memory-level.''' They bound behaviour, never timing or device environment.
* '''A green run counts only when it reproduces across fresh boots.'''
* '''A wall is closed only by an acceptance signal''', named before the experiment.
* '''A wall is closed only by an acceptance signal''', named before the experiment.



Revision as of 09:19, 20 October 2026

An absence of critical technical documentation has historically slowed growth and adoption of developer ecosystems for GPU virtualization.

This CC-BY-4.0 licensed content can either be used with attribution, or used as inspiration for new documentation, created by GPU vendors for public commercial distribution as developer documentation.

Where possible, this documentation will clearly label dates and versions of observed-but-not-guaranteed behaviour vs. vendor-documented stable interfaces/behaviour with guarantees of forward or backward compatibility.

The Execution Frontier

What this page is. The state of guest-facing execution: the chain that must fire for a stock guest CUDA kernel to run on the physical GPU, what has been proven about it, how we know, and where the leading edge is now. The chain fires end to end: verified guest CUDA clients execute on the physical GPU and wake up correctly; the leading edge is now breadth and hardening. It is evidence-led: every statement carries a live observation, a decompilation finding, or a clearly labelled theory. Condensed from ../docs/04-implementation/03-execution-frontier.md; the docs tree wins on disagreement.

Status: 2026-10-20, tree master @ 16291c72. Tags: [live] observed; [wip] partial; [wall] current blocker; theories are labelled as such.

1. The chain that should fire

A guest CUDA launch becomes a method stream in a push buffer, referenced by a GPFIFO ring entry, announced by a doorbell. The host emulation decodes it and forwards an equivalent method stream to a real channel owned by the module's resource-manager session. The hardware front-end fetches and executes the methods, the launch descriptor (QMD) is materialised and read by the GR engine, the grid is dispatched to the SMs, and completion is published as semaphores the guest waits on.

guest: builds launch + method stream
       GPFIFO entry + doorbell
   -> host: doorbell trap, decode, rebuild forward stream,
            prewrite QMD, ring/USERD, doorbell
   -> front-end: fetch GPFIFO entry (ring cursor advances)
   -> front-end: execute methods (object bind, cache ops, report sem)
   -> front-end: install inline QMD into the descriptor buffer
   -> GR engine: read QMD through the channel's page tables
   -> context switch loads the channel context (FECS/ucode)
   -> GR: dispatch grid to the SMs
   -> engine authors release semaphore + channel semaphore
   -> host polls release, relays to guest; CUDA wakes
# Stage State
1 Guest builds launch + method stream [live] observed (stock driver, unmodified)
2 GPFIFO entry + doorbell [live] observed
3 Host decode + forward stream + QMD prewrite + ring/USERD [live] observed
4 Front-end fetches the ring entry [live] observed (ring cursor advances)
5 Front-end executes methods [live] observed (object bind, cache ops, report semaphore)
6 Inline-QMD install (descriptor materialised) [live] observed
7 Engine reads the QMD [live] observed
8 Context switch loads the channel context [live] context validity at dispatch is ruled in
9 GR dispatches the grid to the SMs [live] observed (the guest's results verify)
10 Engine authors release + channel semaphore [live] engine-authored releases relay to the guest
11 Host relays completion; guest wakes [live] the guest's synchronisation waits resolve

One-line summary: the whole chain is live; the leading edge is now breadth and hardening — the large-buffer staged-transfer class, reproducibility across boots, and per-guest execution isolation.

2. Where the leading edge is

A stock, unmodified guest CUDA program executes its kernels on the physical GPU and verifies its results. On fresh boots the vector-add client (victory_mail) prints VADD n=32768 bad=0 + STATUS OK, the matrix-multiply client (victory_matmul) prints MATMUL n=256 bad=0 + STATUS OK, and a transformer kernel prints dh=256 seq=64 bad=0, FFN4 layers=4 bad=0 + STATUS OK. The executing engine is the physical GPU under the module's own real GSP-RM session; the host CUDA bridge is not part of this path. Engine-authored completions relay to the guest and its synchronisation waits resolve.

The leading edge has moved from the launch chain itself — it fires — to breadth and hardening around it:

  • The large-buffer staged-transfer class. Multi-megabyte staged transfers between guest memory and device memory are under repair: some large multi-chunk clients still mis-verify.
  • Reproducibility across boots. A boot-poisoning defect was root-caused and fixed: under the driver's status-queue mode the emulation read the wrong queue cursor, so under load the reply ring could desynchronise and the first CUDA client would fail (the user-visible STATUS FAIL-then-freeze report). Re-measurement across fresh boots is in progress.
  • Per-guest execution isolation. Multiple mediated devices with different emulated VRAM sizes and multiple guests already coexist at the device level; per-guest execution isolation for multiple simultaneous CUDA guests is in progress.

No breadth beyond these is claimed: OpenGL/Vulkan, Windows guests, migration and performance numbers remain planned.

3. How we know (observables and their limits)

Observable What it proves What it does not prove
Client verification output (bad=0 + STATUS OK) the guest executed its kernel and verified its results by itself, which engine produced the results
Engine-authored release relayed to the guest the engine executed the launch and the relay works nothing about other launches
The guest's synchronisation wait resolving completion reached the guest through the relay nothing about other launches
Ring entry consumed; ring cursor advances the front-end is alive and fetching not engine execution — front-end signals are necessary but not sufficient
Reproduction across fresh boots the path is not a lucky boot no "every boot" claim yet while re-measurement is in progress
No GR fault recorded the engine did not raise this error silence is not health: a skipped launch is silent by construction

Consequence: acceptance is verified guest results plus the engine-authored release; a green run counts as progress only when it reproduces across fresh boots.

4. What is exonerated (do not relitigate)

  • Context validity at dispatch — the channel's context is valid when the launch is submitted (instance flag set).
  • The descriptor destination window mapping — installed in the engine's table view at submit.
  • Front-end fetch and control-block alignment — the entry is consumed with the host control block at offset 0.
  • The shared context-buffer one-shot rule — traced to a shared per-GPU buffer already initialised in the same cycle; not the dispatch delta.
  • Parenting/TSG for the fetch — both variants fetch identically.
  • The copy-engine path — CE-class work, releases and fault relay are live (default off); the GR path is separate.
  • The descriptor-gate line of investigation (the old T1–T4 theories) — the inline-descriptor install, the engine read, the dispatch, the engine-authored release and the guest wake-up are all observed; closed by observation.
  • The old boot-poisoning defect — root-caused to the status-queue consumption cursor and fixed.

5. The clear issues (ranked)

Issue A — the large-buffer staged-transfer class. Multi-megabyte staged transfers between guest memory and device memory are under repair: some large multi-chunk clients still mis-verify.

Issue B — reproducibility across boots (re-measurement). The boot-poisoning defect (wrong status-queue consumption cursor under the driver's status-queue mode; the reply ring could desynchronise under load, the first client would fail) was root-caused and fixed. Re-measurement across fresh boots is in progress; no "every boot" claim is made until it completes.

Issue C — per-guest execution isolation. Multiple mediated devices with different emulated VRAM sizes and multiple guests coexist at the device level; per-guest execution isolation for simultaneous CUDA guests is in progress.

6. Lines of investigation (live)

  1. Repair the large-buffer staged-transfer class — the three green clients stay the regression battery and must remain green throughout.
  2. Complete the fresh-boot re-measurement — demonstrate the fixed boot path across fresh boots before claiming boot-to-boot reproducibility.
  3. Per-guest execution isolation — build from the device-level coexistence to isolation for simultaneous CUDA guests.
  4. Hold the acceptance battery — vector-add, matrix-multiply and the transformer kernel; each entry is accepted only on its own verification output (bad=0 + STATUS OK).

7. Theories, resolved

The descriptor-gate theories (T1–T4) are resolved and are not kept as open: the inline-descriptor install, the engine's QMD read, the grid dispatch, the engine-authored release and the guest wake-up are all directly observed, so the launch chain they questioned is proven end to end. The remaining work is engineering (large-buffer transfers, boot-to-boot reproducibility, per-guest isolation), each with an acceptance signal named before the work.

8. Claim discipline

  • Engine-authored release is the acceptance signal for execution — now observed end to end; the guest's own verification (bad=0 + STATUS OK) is the guest-side acceptance signal.
  • Front-end signals are necessary but not sufficient. Ring cursor and front-end method execution can be front-end-authored; they never substitute for the engine-authored release.
  • Silence is not health. No fault recorded does not mean no fault occurred.
  • Emulator verdicts are instruction/memory-level. They bound behaviour, never timing or device environment.
  • A green run counts only when it reproduces across fresh boots.
  • A wall is closed only by an acceptance signal, named before the experiment.

9. Related pages