summaryrefslogtreecommitdiffstats
path: root/kernel/gsp_phys_booter.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/gsp_phys_booter.c')
-rw-r--r--kernel/gsp_phys_booter.c39
1 files changed, 35 insertions, 4 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 07fb7f9..49e8be9 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -12767,7 +12767,17 @@ EXPORT_SYMBOL_GPL(gsp_phys_backend_guest_ce_copy);
#define GSP_PHYS_RMCALL_GR_QMD_INLINE_WORDS 66u
#define GSP_PHYS_RMCALL_GR_QMD_REL_PAYLOAD GSP_PHYS_RMCALL_SEM_PAYLOAD
#define GSP_PHYS_RMCALL_GR_SEM_PAYLOAD 0xc0ffee02u
-/* Method block bound: SET_OBJECT(2) + inline run(67) + REPORT_SEM(8). */
+/*
+ * PCAS launcher (bisect): the driver's non-IQ2M path schedules a QMD with
+ * SEND_PCAS_A = (QMD VA >> 8) followed by SEND_SIGNALING_PCAS_B with
+ * INVALIDATE|SCHEDULE (turing_launch.c:1671-1694, CU_PCAS_TYPE_COPY). Emitted
+ * after the inline window once the caller has prewritten the QMD words to the
+ * destination, so the launch can run without the PBDMA inline copy.
+ */
+#define GSP_PHYS_RMCALL_GR_SEND_PCAS_A 0x2b4u
+#define GSP_PHYS_RMCALL_GR_SEND_SIGNALING_PCAS_B 0x2bcu
+#define GSP_PHYS_RMCALL_GR_PCAS_INVALIDATE_SCHEDULE 0x3u
+/* Method block bound: inline run(67) + PCAS(4) + REPORT_SEM(8). */
#define GSP_PHYS_RMCALL_GR_METHOD_WORDS 96u
static u64 gsp_phys_gr_submitted;
@@ -12813,6 +12823,11 @@ static u32 gsp_phys_rmcall_build_gr_launch(u32 *pb, const u32 *qmd,
*p++ = (u32)((qmd_va >> 8) & 0xffffffffu);
memcpy(p, qmd, GSP_PHYS_GR_QMD_WORDS * 4);
p += GSP_PHYS_GR_QMD_WORDS;
+ p = gsp_phys_rmcall_push_gr(p, GSP_PHYS_RMCALL_GR_SEND_PCAS_A,
+ (u32)(qmd_va >> 8));
+ p = gsp_phys_rmcall_push_gr(p,
+ GSP_PHYS_RMCALL_GR_SEND_SIGNALING_PCAS_B,
+ GSP_PHYS_RMCALL_GR_PCAS_INVALIDATE_SCHEDULE);
p = gsp_phys_rmcall_push_gr(p, GSP_PHYS_RMCALL_GR_SET_REPORT_SEMAPHORE_A,
(u32)(sem_va >> 32));
p = gsp_phys_rmcall_push_gr(p, GSP_PHYS_RMCALL_GR_SET_REPORT_SEMAPHORE_B,
@@ -13070,6 +13085,7 @@ int gsp_phys_backend_guest_gr_submit(const struct gsp_phys_gr_submit *req,
u64 qmd_rel_hpa = 0, ch_rel_hpa = 0;
u64 ch_sem_va = GSP_PHYS_RMCALL_VA_SEM + 4;
u64 qmd_dst = GSP_PHYS_RMCALL_VA_SRC;
+ u8 *qmd_dst_mem = NULL;
u32 qmd_rel_off = 0, ch_rel_off = 0;
u32 poll = 0, w0 = 0, w1 = 0, grpoll_n = 0;
int ret = 0;
@@ -13407,21 +13423,24 @@ gr_page_unmapped:
*/
if (req->qmd_hpa) {
u64 qmd_page = req->qmd_va & ~(u64)(GSP_PHYS_PAGE_SIZE - 1);
+ u32 qmd_off = (u32)(req->qmd_va & (GSP_PHYS_PAGE_SIZE - 1));
if (qmd_page &&
!gsp_phys_rmcall_gr_map_va_locked(bar0, qmd_page,
req->qmd_hpa, epoch)) {
qmd_dst = qmd_page;
+ qmd_dst_mem = (u8 *)__va(req->qmd_hpa) + qmd_off;
} else {
u64 sh_va = 0;
if (n_shadow < GSP_PHYS_RMCALL_GR_SHADOW_PAGES &&
!gsp_phys_rmcall_gr_map_shadow_locked(
n_shadow, req->qmd_hpa, &sh_va)) {
+ qmd_dst_mem = (u8 *)gsp_phys_chunk_page_va(
+ &boot_stage.rmcall_gr_shadow,
+ n_shadow) + qmd_off;
n_shadow++;
- qmd_dst = sh_va +
- (req->qmd_va &
- (GSP_PHYS_PAGE_SIZE - 1));
+ qmd_dst = sh_va + qmd_off;
}
}
pr_info("vgsp-gr: inline-QMD dest va=0x%llx hpa=0x%llx -> 0x%llx (shadow=%u)\n",
@@ -13457,6 +13476,18 @@ gr_page_unmapped:
WRITE_ONCE(*(u32 *)(sem_va + 4), 0);
wmb();
+ /*
+ * IQ2M bisect: prewrite the exact QMD words into the destination
+ * memory so the explicit PCAS in the method block can schedule the
+ * launch even when the PBDMA inline copy never lands.
+ */
+ if (qmd_dst_mem) {
+ memcpy(qmd_dst_mem, qmd, GSP_PHYS_GR_QMD_WORDS * 4);
+ wmb();
+ pr_info("vgsp-gr: QMD prewritten to dest 0x%llx (%u words)\n",
+ qmd_dst, GSP_PHYS_GR_QMD_WORDS);
+ }
+
words = gsp_phys_rmcall_build_gr_launch(methods, qmd,
qmd_dst,
ch_sem_va, want_ch);