summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/gsp_rm_emulation.c20
-rw-r--r--kernel/gsp_sema_service.c17
2 files changed, 35 insertions, 2 deletions
diff --git a/kernel/gsp_rm_emulation.c b/kernel/gsp_rm_emulation.c
index 9ba17c8..4420810 100644
--- a/kernel/gsp_rm_emulation.c
+++ b/kernel/gsp_rm_emulation.c
@@ -3793,6 +3793,8 @@ static void gsp_rm_register_channel(struct gsp_emu_context *ctx, u32 h_client,
* USERD zero (the service must never write a guessed block).
*/
if (userd_wire_base == 0) {
+ u64 wire_pa = desc.userd_pa;
+ u32 wire_as = desc.userd_as;
u32 h_userd = 0;
desc.userd_pa = 0;
@@ -3813,6 +3815,24 @@ static void gsp_rm_register_channel(struct gsp_emu_context *ctx, u32 h_client,
h_userd,
uo);
}
+ /*
+ * CONT.438b: the X/GLX kernel channel needs its
+ * wire-derived block until the client memory-object
+ * table can name the real USERD. c24 (V30) cleared
+ * it and X failed "Failed to initialize DMA"/
+ * "Failed to allocate push buffer"; c23 (V28) used
+ * base 0 + userdOffset and X started. Keep the old
+ * value as a fallback, but only when it is a real
+ * 4K-backed offset (the resolver still wins when it
+ * has a verified memory object).
+ */
+ if (!desc.userd_pa && wire_pa) {
+ desc.userd_pa = wire_pa;
+ desc.userd_as = wire_as;
+ pr_info_ratelimited("vgsp-rm: chan USERD hObject=0x%x hUserd=0x%x unresolved; fallback to wire base+offset=0x%llx as=%u (no guessed table PA)\n",
+ h_object, h_userd,
+ wire_pa, wire_as);
+ }
}
}
memcpy(&desc.notifier_pa, params + GSPRM_CHAN_NOTIFIER_MEM, 8);
diff --git a/kernel/gsp_sema_service.c b/kernel/gsp_sema_service.c
index 146291c..6bf2b38 100644
--- a/kernel/gsp_sema_service.c
+++ b/kernel/gsp_sema_service.c
@@ -27233,6 +27233,7 @@ ce_fb_scan:
* write target for GP_GET.
*/
u64 foreign_userd_pages[SVC_MAX_CHANNELS];
+ u32 foreign_userd_as[SVC_MAX_CHANNELS];
unsigned long chflags;
u32 foreign_userd_n = 0;
u32 oi;
@@ -27249,8 +27250,11 @@ ce_fb_scan:
if (other->h_object == ch->h_object &&
other->vgpu == ch->vgpu)
continue;
- foreign_userd_pages[foreign_userd_n++] =
+ foreign_userd_pages[foreign_userd_n] =
other->userd_pa & ~0xfffULL;
+ foreign_userd_as[foreign_userd_n] =
+ other->userd_as;
+ foreign_userd_n++;
}
spin_unlock_irqrestore(&svc.chan_lock, chflags);
@@ -27296,7 +27300,16 @@ ce_fb_scan:
*/
page = off & ~0xfffULL;
for (oi = 0; oi < foreign_userd_n; oi++) {
- if (foreign_userd_pages[oi] == page) {
+ /*
+ * CONT.438b: the same numeric PA can
+ * exist in sysmem and vidmem (c23:
+ * X's 0x8f0000 sysmem block vs the
+ * RC watchdog's 0x8f0000 FB block).
+ * Only a same-aperture owner makes
+ * the candidate foreign.
+ */
+ if (foreign_userd_pages[oi] == page &&
+ foreign_userd_as[oi] == ch->userd_as) {
foreign = true;
break;
}