summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_sema_service.c
diff options
context:
space:
mode:
authorArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-16 22:12:29 -0400
committerArthur Hanson Rasmusson <arthur@vgpu.io>2026-10-16 22:12:29 -0400
commitf87e0c521452686e32ea113d382addee06447ee9 (patch)
tree6a8e05f34e51348cef07437bab2a250b0c28e0db /kernel/gsp_sema_service.c
parent419615dc4e1fa5e9c2b4e0d15a0df94ca163a09b (diff)
downloadopen-iov-f87e0c521452686e32ea113d382addee06447ee9.tar.gz
open-iov-f87e0c521452686e32ea113d382addee06447ee9.zip
vgsp: m169b bounded device-dst guard (3s per destination page, then release with the walk translation; r173: the unbounded guard deadlocked mail's first H2D - device pins only appear via the launch/fill paths, which the held copy blocked)
Diffstat (limited to 'kernel/gsp_sema_service.c')
-rw-r--r--kernel/gsp_sema_service.c57
1 files changed, 56 insertions, 1 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 343684b..93bcd20 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -731,6 +731,8 @@ struct sema_svc {
u64 copy_watch_log; /* sema_copy_watch log budget */
u64 copy_dst_hold; /* m169: device-dst copies held for
* want of a pin (stale-table guard) */
+ u64 copy_dst_relaxed; /* m169b: guards released without
+ * a pin after the bounded wait */
u64 copy_pat_log; /* sema_copy_pat log budget */
u64 copy_dst_log; /* sema_copy_dst log budget */
u32 op_tr_src; /* provenance of last svc_op_translate */
@@ -2863,6 +2865,7 @@ static inline bool svc_pool_pa_identity(u64 va, u64 pa)
}
static void svc_pool_boot_store(u64 va, u64 pa, int ap); /* m168 */
+static bool svc_dst_guard_hold(u64 va); /* m169b */
static int svc_pool_pa_lookup(u64 va, u64 *pa, int *ap)
{
@@ -4573,7 +4576,8 @@ static int svc_copy(struct nv_vgpu_device *vgpu, u64 dst, u64 src, size_t total,
*/
if (dst_virt && dst_aperture == CE_APERTURE_VID &&
dst_prov >= 3 && dst_orig >= SVC_VAS_FLOOR &&
- gsp_sema_copy_dst_pin_guard) {
+ gsp_sema_copy_dst_pin_guard &&
+ svc_dst_guard_hold(dst_orig)) {
svc.copy_dst_hold++;
if (svc.copy_dst_hold <= 16)
pr_info("sema-svc: device-dst copy held: dst=0x%llx prov=%u (no pin yet; stale-table guard)\n",
@@ -9637,6 +9641,57 @@ bool gsp_sema_pool_hold_fresh = 1;
bool gsp_sema_copy_dst_pin_guard = 1;
/*
+ * m169b: the guard above must never deadlock the boot's first client. The
+ * first device-destination H2D of a client runs before any launch, and the
+ * pins for device VAs are (re)discovered by the launch/fill paths - so at
+ * that instant NO pin can exist. r173: mail's H2D was held forever
+ * (opdef_held ~6000 passes, six expiry cycles, the entry re-held on every
+ * re-decode because the retry keeps resolving prov>=3). Bound the wait per
+ * destination page: after this many ms the guard releases and the copy runs
+ * with the walk translation (the historical behavior; the walk of a
+ * just-built client table is fresh), logged loudly.
+ */
+unsigned gsp_sema_copy_dst_guard_ms = 3000;
+#define SVC_DST_GUARD_SLOTS 16
+struct svc_dst_guard {
+ u64 va_page;
+ unsigned long first;
+};
+static struct svc_dst_guard svc_dst_guard[SVC_DST_GUARD_SLOTS];
+static u32 svc_dst_guard_next;
+
+/* true = the guard may hold this destination; false = release it. */
+static bool svc_dst_guard_hold(u64 va)
+{
+ u64 page = va & ~(u64)(SEMA_PAGE_SIZE - 1);
+ unsigned long now = jiffies;
+ u32 i, slot = SVC_DST_GUARD_SLOTS;
+
+ for (i = 0; i < SVC_DST_GUARD_SLOTS; i++) {
+ if (svc_dst_guard[i].va_page == page) {
+ if (time_before(now, svc_dst_guard[i].first +
+ msecs_to_jiffies(
+ gsp_sema_copy_dst_guard_ms)))
+ return true;
+ if (svc_dst_guard[i].first) {
+ svc_dst_guard[i].first = 0;
+ svc.copy_dst_relaxed++;
+ pr_info("sema-svc: device-dst guard released without a pin va=0x%llx (using the walk translation)\n",
+ page);
+ }
+ return false;
+ }
+ if (!svc_dst_guard[i].va_page)
+ slot = i;
+ }
+ if (slot == SVC_DST_GUARD_SLOTS)
+ slot = svc_dst_guard_next++ % SVC_DST_GUARD_SLOTS;
+ svc_dst_guard[slot].va_page = page;
+ svc_dst_guard[slot].first = now;
+ return true;
+}
+
+/*
* CE release fallback: when a push carrying a tracking-semaphore release
* cannot be read (and the content rescue failed), advance the channel's
* tracking semaphore to the expected payload directly. The push's data