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.c92
1 files changed, 60 insertions, 32 deletions
diff --git a/kernel/gsp_phys_booter.c b/kernel/gsp_phys_booter.c
index 8757a8e..c3620e5 100644
--- a/kernel/gsp_phys_booter.c
+++ b/kernel/gsp_phys_booter.c
@@ -315,7 +315,7 @@ bool gsp_phys_boot_requested(void)
/* libos init argument ids: the name bytes packed big-endian into the u64. */
#define GSP_PHYS_LIBOS_ID_LOGINIT 0x4c4f47494e4954ULL /* "LOGINIT" */
-#define GSP_PHYS_LIBOS_ID_LOGRM 0x4c4f474dULL /* "LOGRM" */
+#define GSP_PHYS_LIBOS_ID_LOGRM 0x4c4f47524dULL /* "LOGRM" */
#define GSP_PHYS_LIBOS_ID_RMARGS 0x524d41524753ULL /* "RMARGS" */
#define GSP_PHYS_LIBOS_KIND_CONTIGUOUS 1
#define GSP_PHYS_LIBOS_LOC_SYSMEM 1
@@ -415,10 +415,12 @@ struct gsp_phys_rpc_unloading_guest_driver {
/*
* rpc_get_gsp_static_info_v14_00 (g_rpc-structures.h:408): the request-side
- * struct is one NvU32 `data`. The server answers with a zeroed-prefixed
- * GspStaticConfigInfo payload (rpcGetGspStaticInfo_v14_00,
- * rpc.c:8875-8913: rpc.length = 32 + sizeof(GspStaticConfigInfo), reply
- * copied into the `data` union member).
+ * struct is one NvU32 `data`, but the reference sender sizes the request
+ * message to the full reply payload (rpcGetGspStaticInfo_v14_00,
+ * rpc.c:8875-8913: rpcWriteCommonHeader(..., sizeof(GspStaticConfigInfo))),
+ * and the server fills a reply of that declared size. We therefore submit a
+ * zeroed GSP_PHYS_SCI_MIN_SIZE-byte payload (reply budget) rather than the
+ * bare 4-byte struct.
*/
struct gsp_phys_rpc_get_gsp_static_info {
__le32 data;
@@ -3140,12 +3142,14 @@ static u64 gsp_phys_cl_pdb_properties(struct pci_dev *pdev)
static void gsp_phys_preinit_fill_system_info(
struct gsp_phys_gsp_system_info *info, struct pci_dev *pdev,
- u64 sys_timer_offset_ns)
+ void __iomem *bar0, u64 sys_timer_offset_ns)
{
struct pci_dev *bridge;
struct pci_dev *fhb;
u64 bars[3] = { 0, 0, 0 };
u32 cap = 0;
+ u32 cfg_id = 0, cfg_rev = 0, cfg_sub = 0;
+ u32 mirror_id, mirror_rev, mirror_sub;
unsigned int i, nbars = 0;
memset(info, 0, sizeof(*info));
@@ -3176,9 +3180,32 @@ static void gsp_phys_preinit_fill_system_info(
cpu_to_le32(GSP_PHYS_PCI_CONFIG_MIRROR_BASE);
info->pci_config_mirror_size =
cpu_to_le32(GSP_PHYS_PCI_CONFIG_MIRROR_SIZE);
- info->pci_device_id = cpu_to_le32(pdev->device);
- info->pci_sub_device_id = cpu_to_le32(pdev->subsystem_device);
- info->pci_revision_id = cpu_to_le32(pdev->revision);
+ /*
+ * The reference sends the raw config-space dwords it reads back from
+ * NV_XVE_ID / NV_XVE_SUBSYSTEM / NV_XVE_REV_ID (rpc.c:9486-9488),
+ * i.e. device<<16|vendor etc. - not the unpacked 16-bit fields.
+ */
+ if (!pci_read_config_dword(pdev, 0x00, &cfg_id) &&
+ !pci_read_config_dword(pdev, 0x08, &cfg_rev) &&
+ !pci_read_config_dword(pdev, 0x2c, &cfg_sub)) {
+ info->pci_device_id = cpu_to_le32(cfg_id);
+ info->pci_sub_device_id = cpu_to_le32(cfg_sub);
+ info->pci_revision_id = cpu_to_le32(cfg_rev & 0xffu);
+ } else {
+ info->pci_device_id = cpu_to_le32(
+ ((u32)pdev->device << 16) | pdev->vendor);
+ info->pci_sub_device_id = cpu_to_le32(
+ ((u32)pdev->subsystem_device << 16) |
+ pdev->subsystem_vendor);
+ info->pci_revision_id = cpu_to_le32(pdev->revision & 0xffu);
+ }
+
+ mirror_id = ioread32(bar0 + GSP_PHYS_PCI_CONFIG_MIRROR_BASE);
+ mirror_rev = ioread32(bar0 + GSP_PHYS_PCI_CONFIG_MIRROR_BASE + 0x08);
+ mirror_sub = ioread32(bar0 + GSP_PHYS_PCI_CONFIG_MIRROR_BASE + 0x2c);
+ pr_info("gsp-phys-boot: NV_PCFG mirror @0x%x: id=0x%08x rev=0x%08x sub=0x%08x (config @0x00/0x08/0x2c: 0x%08x/0x%08x/0x%08x)\n",
+ GSP_PHYS_PCI_CONFIG_MIRROR_BASE, mirror_id, mirror_rev,
+ mirror_sub, cfg_id, cfg_rev, cfg_sub);
info->oor_arch = 0; /* OOR_ARCH_X86_64 */
if (!pcie_capability_read_dword(pdev, PCI_EXP_DEVCAP, &cap) &&
@@ -3317,8 +3344,8 @@ static int gsp_phys_preinit_rpcs(void __iomem *bar0, struct pci_dev *pdev)
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
- gsp_phys_preinit_fill_system_info(info, pdev, sys_timer_offset_ns);
- pr_info("gsp-phys-boot: pre-boot GSP_SET_SYSTEM_INFO (fn%u) prepared: gpuPhys=0x%llx fb=0x%llx inst=0x%llx io=0x%llx dbf=0x%llx mirror=0x%x/0x%x ids=%04x:%04x:%02x maxUserVa=0x%llx pageSize=0x%llx flr=%u behindBridge=%u l1ss=0x%x lnkCap=0x%x primary=%u sysTimerOffsetNs=0x%llx\n",
+ gsp_phys_preinit_fill_system_info(info, pdev, bar0, sys_timer_offset_ns);
+ pr_info("gsp-phys-boot: pre-boot GSP_SET_SYSTEM_INFO (fn%u) prepared: gpuPhys=0x%llx fb=0x%llx inst=0x%llx io=0x%llx dbf=0x%llx mirror=0x%x/0x%x ids=%08x:%08x:%08x maxUserVa=0x%llx pageSize=0x%llx flr=%u behindBridge=%u l1ss=0x%x lnkCap=0x%x primary=%u sysTimerOffsetNs=0x%llx\n",
GSP_PHYS_RPC_FUNC_GSP_SET_SYSTEM_INFO,
le64_to_cpu(info->gpu_phys_addr),
le64_to_cpu(info->gpu_phys_fb_addr),
@@ -3329,7 +3356,8 @@ static int gsp_phys_preinit_rpcs(void __iomem *bar0, struct pci_dev *pdev)
le32_to_cpu(info->pci_config_mirror_size),
le32_to_cpu(info->pci_device_id),
le32_to_cpu(info->pci_sub_device_id),
- info->pci_revision_id, le64_to_cpu(info->max_user_va),
+ le32_to_cpu(info->pci_revision_id),
+ le64_to_cpu(info->max_user_va),
le64_to_cpu(info->host_page_size), info->b_flr_supported,
info->b_gpu_behind_bridge,
le32_to_cpu(info->chipset_l1ss_enable),
@@ -3593,31 +3621,35 @@ static void gsp_phys_sci_decode(const u8 *p, u32 len)
}
/*
- * One GET_GSP_STATIC_INFO attempt: submit the 4-byte request, wait up to
- * ~10 s for the matching reply and decode it. Matching is by rpc.function
- * only, as the reference client does (kernel_gsp.c:1735); the reply's
- * rpc.sequence and transport seqNum are logged.
+ * One GET_GSP_STATIC_INFO attempt: submit a GSP_PHYS_SCI_MIN_SIZE-byte
+ * zeroed request (the declared reply budget, as the reference sender does),
+ * wait up to ~10 s for the matching reply and decode it. Matching is by
+ * rpc.function only, as the reference client does (kernel_gsp.c:1735); the
+ * reply's rpc.sequence and transport seqNum are logged.
*/
static int gsp_phys_rm_probe_fn65(void __iomem *bar0, bool after_fn1)
{
- struct gsp_phys_rpc_get_gsp_static_info req;
+ void *req;
struct gsp_phys_status_queue sq;
struct gsp_phys_rx_record rec;
u32 tx_seq;
int ret;
- memset(&req, 0, sizeof(req));
+ req = kvzalloc(GSP_PHYS_SCI_MIN_SIZE, GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
tx_seq = boot_stage.tx_seq_num;
ret = gsp_phys_queue_tx_submit(bar0,
GSP_PHYS_RPC_FUNC_GET_GSP_STATIC_INFO,
- &req, sizeof(req));
+ req, GSP_PHYS_SCI_MIN_SIZE);
+ kvfree(req);
if (ret) {
pr_err("gsp-phys-boot: rm-probe: GET_GSP_STATIC_INFO (65) submit failed: %d\n",
ret);
return ret;
}
- pr_info("gsp-phys-boot: rm-probe: GET_GSP_STATIC_INFO (65) request submitted (payload %zu B, rpc.sequence=0, txSeqNum=%u%s); waiting up to %u ms for the reply\n",
- sizeof(req), tx_seq,
+ pr_info("gsp-phys-boot: rm-probe: GET_GSP_STATIC_INFO (65) request submitted (payload %u B, rpc.sequence=0, txSeqNum=%u%s); waiting up to %u ms for the reply\n",
+ GSP_PHYS_SCI_MIN_SIZE, tx_seq,
after_fn1 ? ", after SET_GUEST_SYSTEM_INFO" : "",
GSP_PHYS_RM_PROBE_TIMEOUT_MS);
@@ -3718,8 +3750,8 @@ static int gsp_phys_rm_probe_fn1(void __iomem *bar0)
}
/*
- * One debugfs write: GET_GSP_STATIC_INFO; when it gets no reply, send
- * SET_GUEST_SYSTEM_INFO once and retry GET_GSP_STATIC_INFO once. Serialised
+ * One debugfs write: SET_GUEST_SYSTEM_INFO then GET_GSP_STATIC_INFO, the
+ * reference order (kernel_gsp.c:3780-3788), and decode the reply. Serialised
* with the unload trigger by gsp_phys_rm_lock, and bounded by the per-wait
* timeouts. Never touches WPR2 and never sends before GSP-RM init-done (the
* caller gates on boot_stage.rm_init_done). At most one probe cycle per
@@ -3741,15 +3773,11 @@ static int gsp_phys_rm_probe(void __iomem *bar0)
return -EINVAL;
}
boot_stage.rm_probe_attempts++;
- ret = gsp_phys_rm_probe_fn65(bar0, false);
- if (ret) {
- pr_info("gsp-phys-boot: rm-probe: no static-info reply; sending SET_GUEST_SYSTEM_INFO (1) once, then retrying GET_GSP_STATIC_INFO (65) once\n");
- fn1_ret = gsp_phys_rm_probe_fn1(bar0);
- if (fn1_ret)
- pr_err("gsp-phys-boot: rm-probe: SET_GUEST_SYSTEM_INFO (1) attempt returned %d; retrying GET_GSP_STATIC_INFO (65) anyway\n",
- fn1_ret);
- ret = gsp_phys_rm_probe_fn65(bar0, true);
- }
+ fn1_ret = gsp_phys_rm_probe_fn1(bar0);
+ if (fn1_ret)
+ pr_err("gsp-phys-boot: rm-probe: SET_GUEST_SYSTEM_INFO (1) attempt returned %d; issuing GET_GSP_STATIC_INFO (65) anyway\n",
+ fn1_ret);
+ ret = gsp_phys_rm_probe_fn65(bar0, true);
boot_stage.rm_probe_done = true;
boot_stage.rm_probe_last_ret = ret;
mutex_unlock(&gsp_phys_rm_lock);