diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-02 08:07:10 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-02 08:07:10 -0400 |
| commit | 22105e4ec738ac72d010d930222f6d8e62b4116c (patch) | |
| tree | 0ac34da3b20bc504d3c070e87e42e20ed6037e7e /kernel/gsp_phys_booter.h | |
| parent | fe95eadb2bc1cb9af49814528edecbc5e497d6cd (diff) | |
| download | open-iov-22105e4ec738ac72d010d930222f6d8e62b4116c.tar.gz open-iov-22105e4ec738ac72d010d930222f6d8e62b4116c.zip | |
gsp-phys: P6c C3 - relay forwarded-engine faults to the guest (default off)
New default-off gsp_phys_fault_relay: when a relayed copy times out, the
GSP-RM status queue is drained and the first OS_ERROR_LOG (0x1006) recorded
after the submission's doorbell is decoded (NOCAT corroboration), matched
against the ladder channel's runlist/chid, and delivered to the guest by
writing its channel notifier (info32=exceptType, info16=engine type,
status=0xffff) and posting the channel event. A late-release recheck skips
delivery if the engine actually completed, one delivery per hold, and the
existing software fallback always runs first, so no release or data is lost.
- pure decode helpers extracted from the status printers; prints unchanged
- status-queue walks serialized with a mutex; unmatched 0x1006 records are
no longer silently dropped
- fault epoch snapshot at the doorbell prevents stale records from matching
- fault counters and faults:/fault_relay: state lines
- default-off gsp_phys_fault_inject debug knob forces the next relayed
pair's source PTE to zero to produce a real engine fault
- pump notifier latch prevents clobbering a delivered fault
Live: injection run produced a real CE0 FAULT_PTE (0x1f @0x200000), decoded
with errString, chid/runlist matched, notifier delivered, software fallback
applied (applied+fallback==engaged), clean release; the guest RM reacted to
the delivered fault by tearing down its channels (faithful semantics).
Healthy control: faults all zero, relay requested=40 ok=40, smoke
matched=64/64, clean release. Caveat: the auxiliary event post failed
(no_event=1, no MSI-X) and the guest teardown means fault injection is not
smoke-compatible; the parameter stays off.
Diffstat (limited to 'kernel/gsp_phys_booter.h')
| -rw-r--r-- | kernel/gsp_phys_booter.h | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/kernel/gsp_phys_booter.h b/kernel/gsp_phys_booter.h index 408d380..30e30db 100644 --- a/kernel/gsp_phys_booter.h +++ b/kernel/gsp_phys_booter.h @@ -254,10 +254,23 @@ void gsp_phys_backend_guest_counters(u64 *ok, u64 *verify_ok, u64 *verify_fail, u64 *pool_exhausted, u64 *refused); /* Result of one guest CE copy (see the P6c note above). */ +struct gsp_phys_fault_info { + bool valid; + u32 function; + u32 except_type, runlist_id, chid, prev_xid; + u32 engine; + char err[256]; + u32 nocat_rec_type; + u64 nocat_error_code; + u32 nocat_subsystem; + char nocat_engine[64]; +}; + struct gsp_phys_backend_copy_result { u32 sem_value; /* last word observed at the polled semaphore */ u32 elapsed_ms; /* return-to-caller elapsed milliseconds */ int rc; /* duplicated function return code */ + struct gsp_phys_fault_info fault; /* decoded engine fault, if any */ }; int gsp_phys_backend_guest_ce_copy_ex(u64 src_hpa, u32 src_off, u64 dst_hpa, @@ -278,6 +291,38 @@ void gsp_phys_backend_relay_counters(u64 *requested, u64 *ok, u64 *verify_fail, u64 *pool_exhausted); /* + * P6c C3 fault observation/relay (gsp_phys_fault_relay=1; default off). + * + * gsp_phys_status_drain_fault() walks the unconsumed status-queue records with + * the same validated stage-3e ring walk as the debugfs drain, decodes the + * first OS_ERROR_LOG (function 0x1006) into *out, corroborates it with a + * just-seen NOCAT journal record (function 0x1020, matched on errorCode == + * exceptType) and consumes everything it walked. *epoch (if given) receives + * the fault epoch captured when that 0x1006 was consumed: the relay submit + * path snapshots the same counter immediately before the doorbell, and a + * fault is only relayed to the guest when its epoch is newer than the + * snapshot. Returns 0 with out->valid true on a found fault, -ENODATA when + * the walk completed without one, and -EINVAL/-EAGAIN/negative transport + * errors like the read-only drain. Serialized with the other status-queue + * walks by the internal walk mutex. + * + * gsp_phys_backend_ladder_channel_ids() reports the ladder channel's + * runlistId/chid derived from the work-submit token (the same decomposition + * the doorbell uses); false when no live ladder token exists. + * + * gsp_phys_backend_fault_counters() reads the observation counters: every + * 0x1006 consumed by any walk (seen), drained faults refused because their + * epoch was not newer than the submit snapshot (stale), faults returned + * fresh by gsp_phys_status_drain_fault() (drained), 0x1006 records consumed + * by a status wait for another function (wait_unmatched) and the current + * fault epoch. Plain reads, safe from the debugfs show path. + */ +int gsp_phys_status_drain_fault(struct gsp_phys_fault_info *out, u32 *epoch); +bool gsp_phys_backend_ladder_channel_ids(u32 *runlist_id, u32 *chid); +void gsp_phys_backend_fault_counters(u64 *seen, u64 *stale, u64 *drained, + u64 *wait_unmatched, u32 *epoch); + +/* * Command-queue TX: build a msgq record with the 570.144 element/rpc header * layout, splitting it into 1..16 4 KB elements when it does not fit one * (reference elemCount = ceil((48 + rpc.length) / 4096), each element copied |
