summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_sema_service.c52
1 files changed, 51 insertions, 1 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index c8987b7..d20ad92 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -441,6 +441,16 @@ struct svc_channel {
u8 gr_ram_passes; /* slices walked so far */
bool gr_ram_logged; /* one discovery line per channel */
/*
+ * r496e: true when the ring was found by the RAM content scan (a
+ * kernel-RM sysmem channel - the X/GL 3D channel). Such a channel's
+ * pushes are 2D/3D method streams the emulation does not execute;
+ * the correct model is consume-and-apply-releases: no QMD capture,
+ * no launch forward, no no-capture hold. Also allows an all-zero
+ * NOP push (the driver's pushbuffer sanity test writes exactly one
+ * zero dword) to be consumed as the no-op it is.
+ */
+ bool gr_ram_ring;
+ /*
* r496b: the FB-scan USERD (see svc_userd_fb_scan). Latched when the
* registered/ring-derived candidates all fail; the scan validates the
* hit against the ring entries the put claims, so a foreign channel's
@@ -14575,8 +14585,33 @@ static void svc_gr_ring_autopin(struct nv_vgpu_device *vgpu,
SVC_APERTURE_SYS);
}
ch->gr_ram_logged = true;
+ ch->gr_ram_ring = true;
set_bit(ch->gr_index, &svc_gr_ring_done);
svc_ring_n++;
+ /*
+ * Persist the latch immediately: a later stalled
+ * path in this pass may `continue` past the
+ * end-of-pass write-back, and the next pass's
+ * snapshot must carry gr_ram_ring (the zero-NOP
+ * exception and the no-capture-hold skip key on
+ * it).
+ */
+ {
+ unsigned long flags2;
+ int i2;
+
+ spin_lock_irqsave(&svc.chan_lock, flags2);
+ for (i2 = 0; i2 < SVC_MAX_CHANNELS; i2++)
+ if (svc.chan[i2].valid &&
+ svc.chan[i2].vgpu == vgpu &&
+ svc.chan[i2].h_object ==
+ ch->h_object) {
+ svc.chan[i2].gr_ram_ring = true;
+ svc.chan[i2].gr_ram_logged = true;
+ break;
+ }
+ spin_unlock_irqrestore(&svc.chan_lock, flags2);
+ }
pr_info("sema-chan: GR ring h=0x%x rank=%u found by RAM content scan va=0x%llx -> pa=0x%llx (allocation window pinned; entry/push reads resolve through it)\n",
ch->h_object, ch->gr_index, ch->gpfifo_va,
hit_pa);
@@ -21163,7 +21198,20 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
injected = (svc_ipin_lookup(va, &ipa,
&iap) == 0);
- if (!svc_method_stream_plausible(pb, len)) {
+ /*
+ * r496e: an all-zero push on a
+ * content-scanned-ring channel is the
+ * driver's NOP sanity push (one zero
+ * dword - NVA06F_DMA_NOP), not a bad
+ * translation: accept it and let the
+ * decode find no ops.
+ */
+ bool zero_nop = ch->gr_ram_ring &&
+ len >= 4 &&
+ !memchr_inv(pb, 0, len);
+
+ if (!svc_method_stream_plausible(pb, len) &&
+ !zero_nop) {
svc.false_trans++;
if (injected) {
u8 *fb = kmalloc(len,
@@ -21982,6 +22030,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
jiffies;
}
if (gsp_sema_gr_nocap_hold_ms &&
+ !ch->gr_ram_ring &&
time_before(jiffies,
ch->gr_nocap_since +
msecs_to_jiffies(
@@ -22731,6 +22780,7 @@ static void svc_pump_channels(struct nv_vgpu_device *vgpu)
svc.chan[k].gr_ram_cursor = ch->gr_ram_cursor;
svc.chan[k].gr_ram_passes = ch->gr_ram_passes;
svc.chan[k].gr_ram_logged = ch->gr_ram_logged;
+ svc.chan[k].gr_ram_ring = ch->gr_ram_ring;
svc.chan[k].userd_scans = ch->userd_scans;
svc.chan[k].logged = ch->logged;
svc.chan[k].logged_expected = ch->logged_expected;