summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_sema_service.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 0be279e..86cee81 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -9586,6 +9586,47 @@ static void svc_gr_data_fill(struct nv_vgpu_device *vgpu)
* 2 KB is scanned for plausible device VAs.
*/
n_cand = 0;
+ /*
+ * m121: kernel-argument pointers first. The launched kernel's device
+ * pointers live in the param page (qmd_word 32, c[0x0]) at byte
+ * offsets >= 0x150 (m120: mail_kernel out@0x160, msg@0x168; vadd
+ * a/b/c@0x160/0x168/0x170). m120 lost them: 13 candidates, the
+ * driver-internal pointers resolved first consumed the 100-page
+ * bounce cap, and c[0x0][0x168] stayed a guest VA (the first LDG
+ * MMU_NACKed). Collecting the argument area first guarantees those
+ * pages are resolved and their pointer words rewritten.
+ */
+ for (i = 0; i < svc_fwd_req.gr_n_pages; i++) {
+ const struct svc_gr_page *pp = &svc_fwd_req.gr_pages[i];
+ u64 hpa = 0;
+ const u8 *page;
+ u32 k;
+
+ if (pp->qmd_word != 32u || !pp->pa)
+ continue;
+ kind = (pp->ap == SVC_APERTURE_FB) ? SVC_APERTURE_FB :
+ SVC_APERTURE_SYS;
+ if (svc_fwd_operand_hpa(vgpu, kind, pp->pa, 0,
+ SEMA_PAGE_SIZE, &hpa, &off) || off)
+ continue;
+ page = (const u8 *)__va(hpa);
+ if (!page)
+ continue;
+ for (k = 0x150u / 8u; k < 256; k++) {
+ u64 v = get_unaligned_le64(page + k * 8);
+ u64 wv;
+
+ if (v < 0x10000000ULL || v >= (1ULL << 47) ||
+ (v & 3))
+ continue;
+ wv = v & ~(u64)(SEMA_PAGE_SIZE - 1);
+ for (w = 0; w < n_cand; w++)
+ if (wins[w] == wv)
+ break;
+ if (w == n_cand && n_cand < ARRAY_SIZE(wins))
+ wins[n_cand++] = wv;
+ }
+ }
for (i = 0; i < svc_fwd_req.gr_n_pages; i++) {
const struct svc_gr_page *pp = &svc_fwd_req.gr_pages[i];
u64 hpa = 0;