summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/gsp_sema_service.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 7681ef6..0a4e723 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -3104,16 +3104,25 @@ static int svc_rescue_push_page(struct nv_vgpu_device *vgpu,
u32 want_payload = ch->expected_sem_payload;
u64 cand[SVC_MBUF_MAX];
u32 ncand = 0, i;
+ u32 pin_len;
if (!ch->engine_type || ch->ce_index >= 32 || !want_payload)
return -ENOENT;
- if ((entry_va & 0xfffff) || entry_va < SEMA_VA_LO ||
- entry_va >= SEMA_VA_HI)
+ if (entry_va < SEMA_VA_LO || entry_va >= SEMA_VA_HI)
return -EINVAL;
if (time_before(jiffies, ch->rescue_last + 5 * HZ))
return -EAGAIN;
ch->rescue_last = jiffies;
+ /*
+ * Slot-aligned entries pin the whole 1 MB slot at once (all of its
+ * pushes share the mapping); an entry in the middle of a slot only
+ * needs the pages its own push occupies - candidate 2 below is the
+ * PA of the entry VA's page in both cases.
+ */
+ pin_len = (entry_va & 0xfffff) ?
+ ALIGN(entry_len + SEMA_PAGE_SIZE, SEMA_PAGE_SIZE) : 0x100000;
+
buf = kmalloc(SVC_SCAN_CHUNK, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -3181,7 +3190,7 @@ static int svc_rescue_push_page(struct nv_vgpu_device *vgpu,
u8 probe[64];
u32 j;
- for (j = 0; j < 0x100000; j += SEMA_PAGE_SIZE) {
+ for (j = 0; j < pin_len; j += SEMA_PAGE_SIZE) {
svc_pin_store(entry_va + j, cand[i] + j,
SVC_APERTURE_SYS);
svc_lat_store(entry_va + j, cand[i] + j,
@@ -3190,7 +3199,7 @@ static int svc_rescue_push_page(struct nv_vgpu_device *vgpu,
if (!svc_read_va_trusted(vgpu, entry_va, probe,
sizeof(probe)) &&
svc_method_stream_plausible(probe, sizeof(probe))) {
- for (j = 0; j < 0x100000; j += SEMA_PAGE_SIZE)
+ for (j = 0; j < pin_len; j += SEMA_PAGE_SIZE)
svc_mark_hot(cand[i] + j);
pr_info("sema-svc: content rescue ch=0x%x rank=%u slot=%u entry_va=0x%llx len=%u -> pa=0x%llx (cand %u/%u)\n",
ch->h_object, ch->ce_index, slot, entry_va,