diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-29 16:32:03 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-09-29 16:32:03 -0400 |
| commit | 5b80f3d5e1b9a597a7e7e0d761a5fa8b5804dbc1 (patch) | |
| tree | d9dde0e9f59099edda901b4117b8e076eddc1260 | |
| parent | 09a729ac2a8c6f1865d5ef3bfd2b4df55d43764a (diff) | |
| download | open-iov-5b80f3d5e1b9a597a7e7e0d761a5fa8b5804dbc1.tar.gz open-iov-5b80f3d5e1b9a597a7e7e0d761a5fa8b5804dbc1.zip | |
sema-svc: bounded diagnostics for GR counter writes; scanner guarantees counter-page delta
- rel-apply/publish now log the first 32/48 outcomes (written, skipped with
current value, no slot, read failure) so the live counter page can be
matched against host writes.
- guest pin scanner logs the counter page's pagemap state each loop and adds
it to the delta set explicitly, so the page is pinned the moment it is
mapped even if the window scan misses it.
| -rw-r--r-- | kernel/gsp_sema_service.c | 42 | ||||
| -rw-r--r-- | tools/guest-diag/guest_pin_stream.py | 24 |
2 files changed, 57 insertions, 9 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c index 21f0de0..e336277 100644 --- a/kernel/gsp_sema_service.c +++ b/kernel/gsp_sema_service.c @@ -351,6 +351,8 @@ struct sema_svc { u64 releases_jumped; /* applied with gap > 1 */ u64 releases_faked; /* skipped-entry fallback */ u64 counter_rel_applied; /* releases to registered counters */ + u64 counter_rel_dbg; /* rel-apply diagnostic budget */ + u64 counter_pub_dbg; /* counter-publish diagnostic budget */ u64 counter_pub_calls; /* publishes that found a registered counter */ u64 gr_rel_applied; /* release writes into the GR counter page */ u64 gr_rel_log; @@ -2107,6 +2109,7 @@ static void svc_counter_release_apply(struct nv_vgpu_device *vgpu, u32 h, u64 pa = 0; u32 cur = 0; int i; + u32 dbg = 0; if (!h || !payload) return; @@ -2119,21 +2122,43 @@ static void svc_counter_release_apply(struct nv_vgpu_device *vgpu, u32 h, } } spin_unlock_irqrestore(&svc.chan_lock, flags); - if (!pa) + if (!pa) { + if (svc.counter_rel_dbg < 32) { + svc.counter_rel_dbg++; + pr_info("sema-chan: rel-apply h=0x%x pay=%u -> no slot registered\n", + h, payload); + } return; + } - if (svc_read_ap(vgpu, pa, SVC_APERTURE_SYS, &cur, sizeof(cur))) + if (svc_read_ap(vgpu, pa, SVC_APERTURE_SYS, &cur, sizeof(cur))) { + if (svc.counter_rel_dbg < 32) { + svc.counter_rel_dbg++; + pr_info("sema-chan: rel-apply h=0x%x pa=0x%llx pay=%u -> read failed\n", + h, pa, payload); + } return; - if (payload <= cur || payload - cur > 0x100000) + } + if (payload <= cur || payload - cur > 0x100000) { + if (svc.counter_rel_dbg < 32) { + svc.counter_rel_dbg++; + pr_info("sema-chan: rel-apply h=0x%x pa=0x%llx pay=%u cur=%u -> skip\n", + h, pa, payload, cur); + } return; + } if (svc_write_ap(vgpu, pa, SVC_APERTURE_SYS, &payload, sizeof(payload))) return; svc.releases_applied++; svc.counter_rel_applied++; svc.post_hint_until = jiffies + 10 * HZ; - pr_info_ratelimited("sema-chan: counter release h=0x%x pa=0x%llx val=%u (was %u)\n", - h, pa, payload, cur); + if (svc.counter_rel_dbg < 32) { + svc.counter_rel_dbg++; + pr_info("sema-chan: rel-apply h=0x%x pa=0x%llx pay=%u cur=%u -> written\n", + h, pa, payload, cur); + } + (void)dbg; } /* @@ -3966,8 +3991,11 @@ static void svc_counter_publish(struct nv_vgpu_device *vgpu, &val, sizeof(val))) return; ch->counter_last = val; - pr_info_ratelimited("sema-chan: counter publish h=0x%x pa=0x%llx val=%u\n", - ch->h_object, ch->counter_pa, val); + if (svc.counter_pub_dbg < 48) { + svc.counter_pub_dbg++; + pr_info("sema-chan: counter publish h=0x%x pa=0x%llx val=%u (was %u)\n", + ch->h_object, ch->counter_pa, val, cur); + } } /* diff --git a/tools/guest-diag/guest_pin_stream.py b/tools/guest-diag/guest_pin_stream.py index 8d0b34d..717a05d 100644 --- a/tools/guest-diag/guest_pin_stream.py +++ b/tools/guest-diag/guest_pin_stream.py @@ -141,6 +141,26 @@ def main(): time.sleep(INTERVAL) continue dt = time.time() - t0 + # Diagnostic: the GR completion-counter page is the one page the + # client's context-init wait polls; log its pagemap entry every loop + # so a scan blind spot is visible in the guest log. + cpm = None + try: + fdp = os.open('/proc/%d/pagemap' % pid, os.O_RDONLY) + os.lseek(fdp, (0x20400fec0 // 4096) * 8, 0) + cpm = int.from_bytes(os.read(fdp, 8), 'little') + os.close(fdp) + except OSError: + cpm = None + diag = ('cpm=%s' % ('present' if (cpm or 0) >> 63 & 1 else 'absent') + if cpm is not None else 'cpm=ERR') + # Guaranteed fast path for the GR completion-counter page: if the + # window scan misses it (observed once), add it explicitly so the host + # can register the slots before the client's first wait. + if cpm is not None and (cpm >> 63) & 1: + cpa = (cpm & ((1 << 55) - 1)) << 12 + if cpa and (not PAMAX or cpa < PAMAX): + cur[0x20400f000] = cpa new = [(va, pa) for va, pa in cur.items() if seen.get(va) != pa] seen = cur lines = [] @@ -152,9 +172,9 @@ def main(): last_log = now try: with open('/tmp/guest_pin_stream.log', 'a') as f: - f.write('%s pid=%s present=%d new=%d sem=%d scan=%.3fs\n' + f.write('%s pid=%s present=%d new=%d sem=%d scan=%.3fs %s\n' % (time.strftime('%T'), pid, len(cur), len(new), - len(seen_sems), dt)) + len(seen_sems), dt, diag)) except OSError: pass if not new and not lines: |
