diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/gsp_rm_emulation.c | 20 | ||||
| -rw-r--r-- | kernel/gsp_sema_service.c | 17 |
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; } |
