[RFC 27/29] vfio/vgpu_mgr: bootload the new vGPU

Zhi Wang
2024-09-22T12:51:01Z

All the resources that required by a new vGPU has been set up. It is time
to activate it.

Send the NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_BOOTLOAD_GSP_VGPU_PLUGIN_TASK
GSP RPC to activate the new vGPU.

Signed-off-by: Zhi Wang <zhiw@nvidia.com>
---
.../ctrl/ctrl2080/ctrl2080vgpumgrinternal.h | 90 ++++++++++++++++++
drivers/vfio/pci/nvidia-vgpu/nvkm.h | 3 +
drivers/vfio/pci/nvidia-vgpu/vgpu.c | 94 +++++++++++++++++++
3 files changed, 187 insertions(+)

diff --git a/drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080vgpumgrinternal.h b/drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080vgpumgrinternal.h
index f44cdc733229..58c6bff72f44 100644
--- a/drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080vgpumgrinternal.h
+++ b/drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080vgpumgrinternal.h
@@ -59,4 +59,94 @@ typedef struct NV2080_CTRL_VGPU_MGR_INTERNAL_PGPU_ADD_VGPU_TYPE_PARAMS {
NV_DECLARE_ALIGNED(NVA081_CTRL_VGPU_INFO vgpuInfo[NVA081_MAX_VGPU_TYPES_PER_PGPU], 8);
} NV2080_CTRL_VGPU_MGR_INTERNAL_PGPU_ADD_VGPU_TYPE_PARAMS;

+/*
+ * NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_BOOTLOAD_GSP_VGPU_PLUGIN_TASK
+ *
+ * This command is used to bootload GSP VGPU plugin task.
+ * Can be called only with SR-IOV and with VGPU_GSP_PLUGIN_OFFLOAD feature.
+ *
+ * dbdf - domain (31:16), bus (15:8), device (7:3), function (2:0)
+ * gfid - Gfid
+ * vgpuType - The Type ID for VGPU profile
+ * vmPid - Plugin process ID of vGPU guest instance
+ * swizzId - SwizzId
+ * numChannels - Number of channels
+ * numPluginChannels - Number of plugin channels
+ * bDisableSmcPartitionRestore - If set to true, SMC default execution partition
+ * save/restore will not be done in host-RM
+ * guestFbPhysAddrList - list of VMMU segment aligned physical address of guest FB memory
+ * guestFbLengthList - list of guest FB memory length in bytes
+ * pluginHeapMemoryPhysAddr - plugin heap memory offset
+ * pluginHeapMemoryLength - plugin heap memory length in bytes
+ * bDeviceProfilingEnabled - If set to true, profiling is allowed
+ */
+#define NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_BOOTLOAD_GSP_VGPU_PLUGIN_TASK (0x20804001) /* finn: Evaluated from "(FINN_NV20_SUBDEVICE_0_VGPU_MGR_INTERNAL_INTERFACE_ID << 8) | NV2080_CTRL_VGPU_MGR_INTERNAL_BOOTLOAD_GSP_VGPU_PLUGIN_TASK_PARAMS_MESSAGE_ID" */
+
+#define NV2080_CTRL_MAX_VMMU_SEGMENTS 384
+
+/* Must match NV2080_ENGINE_TYPE_LAST from cl2080.h */
+#define NV2080_GPU_MAX_ENGINES 0x3e
+
+#define NV2080_CTRL_VGPU_MGR_INTERNAL_BOOTLOAD_GSP_VGPU_PLUGIN_TASK_PARAMS_MESSAGE_ID (0x1U)
+
+typedef struct NV2080_CTRL_VGPU_MGR_INTERNAL_BOOTLOAD_GSP_VGPU_PLUGIN_TASK_PARAMS {
+ NvU32 dbdf;
+ NvU32 gfid;
+ NvU32 vgpuType;
+ NvU32 vmPid;
+ NvU32 swizzId;
+ NvU32 numChannels;
+ NvU32 numPluginChannels;
+ NvU32 chidOffset[NV2080_GPU_MAX_ENGINES];
+ NvBool bDisableDefaultSmcExecPartRestore;
+ NvU32 numGuestFbSegments;
+ NV_DECLARE_ALIGNED(NvU64 guestFbPhysAddrList[NV2080_CTRL_MAX_VMMU_SEGMENTS], 8);
+ NV_DECLARE_ALIGNED(NvU64 guestFbLengthList[NV2080_CTRL_MAX_VMMU_SEGMENTS], 8);
+ NV_DECLARE_ALIGNED(NvU64 pluginHeapMemoryPhysAddr, 8);
+ NV_DECLARE_ALIGNED(NvU64 pluginHeapMemoryLength, 8);
+ NV_DECLARE_ALIGNED(NvU64 ctrlBuffOffset, 8);
+ NV_DECLARE_ALIGNED(NvU64 initTaskLogBuffOffset, 8);
+ NV_DECLARE_ALIGNED(NvU64 initTaskLogBuffSize, 8);
+ NV_DECLARE_ALIGNED(NvU64 vgpuTaskLogBuffOffset, 8);
+ NV_DECLARE_ALIGNED(NvU64 vgpuTaskLogBuffSize, 8);
+ NvBool bDeviceProfilingEnabled;
+} NV2080_CTRL_VGPU_MGR_INTERNAL_BOOTLOAD_GSP_VGPU_PLUGIN_TASK_PARAMS;
+
+/*
+ * NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_SHUTDOWN_GSP_VGPU_PLUGIN_TASK
+ *
+ * This command is used to shutdown GSP VGPU plugin task.
+ * Can be called only with SR-IOV and with VGPU_GSP_PLUGIN_OFFLOAD feature.
+ *
+ * gfid - Gfid
+ */
+#define NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_SHUTDOWN_GSP_VGPU_PLUGIN_TASK (0x20804002) /* finn: Evaluated from "(FINN_NV20_SUBDEVICE_0_VGPU_MGR_INTERNAL_INTERFACE_ID << 8) | NV2080_CTRL_VGPU_MGR_INTERNAL_SHUTDOWN_GSP_VGPU_PLUGIN_TASK_PARAMS_MESSAGE_ID" */
+
+#define NV2080_CTRL_VGPU_MGR_INTERNAL_SHUTDOWN_GSP_VGPU_PLUGIN_TASK_PARAMS_MESSAGE_ID (0x2U)
+
+typedef struct NV2080_CTRL_VGPU_MGR_INTERNAL_SHUTDOWN_GSP_VGPU_PLUGIN_TASK_PARAMS {
+ NvU32 gfid;
+} NV2080_CTRL_VGPU_MGR_INTERNAL_SHUTDOWN_GSP_VGPU_PLUGIN_TASK_PARAMS;
+
+/*
+ * NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_VGPU_PLUGIN_CLEANUP
+ *
+ * This command is used to cleanup all the GSP VGPU plugin task allocated resources after its shutdown.
+ * Can be called only with SR-IOV and with VGPU_GSP_PLUGIN_OFFLOAD feature.
+ *
+ * gfid [IN]
+ * This parameter specifies the gfid of vGPU assigned to VM.
+ *
+ * Possible status values returned are:
+ * NV_OK
+ * NV_ERR_NOT_SUPPORTED
+ */
+#define NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_VGPU_PLUGIN_CLEANUP (0x20804008) /* finn: Evaluated from "(FINN_NV20_SUBDEVICE_0_VGPU_MGR_INTERNAL_INTERFACE_ID << 8) | NV2080_CTRL_VGPU_MGR_INTERNAL_VGPU_PLUGIN_CLEANUP_PARAMS_MESSAGE_ID" */
+
+#define NV2080_CTRL_VGPU_MGR_INTERNAL_VGPU_PLUGIN_CLEANUP_PARAMS_MESSAGE_ID (0x8U)
+
+typedef struct NV2080_CTRL_VGPU_MGR_INTERNAL_VGPU_PLUGIN_CLEANUP_PARAMS {
+ NvU32 gfid;
+} NV2080_CTRL_VGPU_MGR_INTERNAL_VGPU_PLUGIN_CLEANUP_PARAMS;
+
#endif
diff --git a/drivers/vfio/pci/nvidia-vgpu/nvkm.h b/drivers/vfio/pci/nvidia-vgpu/nvkm.h
index 8ad2241f7c5e..8e07422f99e5 100644
--- a/drivers/vfio/pci/nvidia-vgpu/nvkm.h
+++ b/drivers/vfio/pci/nvidia-vgpu/nvkm.h
@@ -88,4 +88,7 @@ static inline int nvidia_vgpu_mgr_get_handle(struct pci_dev *pdev,
#define nvidia_vgpu_mgr_bar1_unmap_mem(m, mem) \
m->handle.ops->bar1_unmap_mem(mem)

+#define nvidia_vgpu_mgr_get_engine_bitmap(m, b) \
+ m->handle.ops->get_engine_bitmap(m->handle.pf_drvdata, b)
+
#endif
diff --git a/drivers/vfio/pci/nvidia-vgpu/vgpu.c b/drivers/vfio/pci/nvidia-vgpu/vgpu.c
index 124a1a4593ae..e06d5155bb38 100644
--- a/drivers/vfio/pci/nvidia-vgpu/vgpu.c
+++ b/drivers/vfio/pci/nvidia-vgpu/vgpu.c
@@ -7,6 +7,7 @@

#include <nvrm/nvtypes.h>
#include <nvrm/common/sdk/nvidia/inc/ctrl/ctrla081.h>
+#include <nvrm/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080vgpumgrinternal.h>

#include "vgpu_mgr.h"

@@ -141,6 +142,91 @@ static int setup_mgmt_heap(struct nvidia_vgpu *vgpu)
return 0;
}

+static int shutdown_vgpu_plugin_task(struct nvidia_vgpu *vgpu)
+{
+ struct nvidia_vgpu_mgr *vgpu_mgr = vgpu->vgpu_mgr;
+ NV2080_CTRL_VGPU_MGR_INTERNAL_SHUTDOWN_GSP_VGPU_PLUGIN_TASK_PARAMS *ctrl;
+
+ ctrl = nvidia_vgpu_mgr_rm_ctrl_get(vgpu_mgr, &vgpu->gsp_client,
+ NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_SHUTDOWN_GSP_VGPU_PLUGIN_TASK,
+ sizeof(*ctrl));
+ if (IS_ERR(ctrl))
+ return PTR_ERR(ctrl);;
+
+ ctrl->gfid = vgpu->info.gfid;
+
+ return nvidia_vgpu_mgr_rm_ctrl_wr(vgpu_mgr, &vgpu->gsp_client,
+ ctrl);
+}
+
+static int cleanup_vgpu_plugin_task(struct nvidia_vgpu *vgpu)
+{
+ struct nvidia_vgpu_mgr *vgpu_mgr = vgpu->vgpu_mgr;
+ NV2080_CTRL_VGPU_MGR_INTERNAL_VGPU_PLUGIN_CLEANUP_PARAMS *ctrl;
+
+ ctrl = nvidia_vgpu_mgr_rm_ctrl_get(vgpu_mgr, &vgpu->gsp_client,
+ NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_VGPU_PLUGIN_CLEANUP,
+ sizeof(*ctrl));
+ if (IS_ERR(ctrl))
+ return PTR_ERR(ctrl);
+
+ ctrl->gfid = vgpu->info.gfid;
+
+ return nvidia_vgpu_mgr_rm_ctrl_wr(vgpu_mgr, &vgpu->gsp_client,
+ ctrl);
+}
+
+static int bootload_vgpu_plugin_task(struct nvidia_vgpu *vgpu)
+{
+ struct nvidia_vgpu_mgr *vgpu_mgr = vgpu->vgpu_mgr;
+ struct nvidia_vgpu_mgmt *mgmt = &vgpu->mgmt;
+ NV2080_CTRL_VGPU_MGR_INTERNAL_BOOTLOAD_GSP_VGPU_PLUGIN_TASK_PARAMS *ctrl;
+ DECLARE_BITMAP(engine_bitmap, NV2080_GPU_MAX_ENGINES);
+ int ret, i;
+
+ ctrl = nvidia_vgpu_mgr_rm_ctrl_get(vgpu_mgr, &vgpu->gsp_client,
+ NV2080_CTRL_CMD_VGPU_MGR_INTERNAL_BOOTLOAD_GSP_VGPU_PLUGIN_TASK,
+ sizeof(*ctrl));
+ if (IS_ERR(ctrl))
+ return PTR_ERR(ctrl);
+
+ ctrl->dbdf = vgpu->info.dbdf;
+ ctrl->gfid = vgpu->info.gfid;
+ ctrl->vmPid = 0;
+ ctrl->swizzId = 0;
+ ctrl->numChannels = vgpu->chid.num_chid;
+ ctrl->numPluginChannels = 0;
+
+ bitmap_clear(engine_bitmap, 0, NV2080_GPU_MAX_ENGINES);
+
+ /* FIXME: nvkm seems not correctly record engines. two engines are missing. */
+ nvidia_vgpu_mgr_get_engine_bitmap(vgpu_mgr, engine_bitmap);
+
+ for_each_set_bit(i, engine_bitmap, NV2080_GPU_MAX_ENGINES)
+ ctrl->chidOffset[i] = vgpu->chid.chid_offset;
+
+ ctrl->bDisableDefaultSmcExecPartRestore = false;
+ ctrl->numGuestFbSegments = 1;
+ ctrl->guestFbPhysAddrList[0] = vgpu->fbmem_heap->addr;
+ ctrl->guestFbLengthList[0] = vgpu->fbmem_heap->size;
+ ctrl->pluginHeapMemoryPhysAddr = mgmt->heap_mem->addr;
+ ctrl->pluginHeapMemoryLength = mgmt->heap_mem->size;
+ ctrl->ctrlBuffOffset = 0;
+ ctrl->initTaskLogBuffOffset = mgmt->heap_mem->addr +
+ init_task_log_buff_offset();
+ ctrl->initTaskLogBuffSize = init_task_log_buff_size();
+ ctrl->vgpuTaskLogBuffOffset = ctrl->initTaskLogBuffOffset +
+ ctrl->initTaskLogBuffSize;
+ ctrl->vgpuTaskLogBuffSize = vgpu_task_log_buff_size();
+ ctrl->bDeviceProfilingEnabled = false;
+
+ ret = nvidia_vgpu_mgr_rm_ctrl_wr(vgpu_mgr, &vgpu->gsp_client,
+ ctrl);
+ if (ret)
+ return ret;
+ return 0;
+}
+
/**
* nvidia_vgpu_mgr_destroy_vgpu - destroy a vGPU instance
* @vgpu: the vGPU instance going to be destroyed.
@@ -154,6 +240,8 @@ int nvidia_vgpu_mgr_destroy_vgpu(struct nvidia_vgpu *vgpu)
if (!atomic_cmpxchg(&vgpu->status, 1, 0))
return -ENODEV;

+ WARN_ON(shutdown_vgpu_plugin_task(vgpu));
+ WARN_ON(cleanup_vgpu_plugin_task(vgpu));
nvidia_vgpu_mgr_free_gsp_client(vgpu_mgr, &vgpu->gsp_client);
clean_mgmt_heap(vgpu);
clean_chids(vgpu);
@@ -207,10 +295,16 @@ int nvidia_vgpu_mgr_create_vgpu(struct nvidia_vgpu *vgpu, u8 *vgpu_type)
if (ret)
goto err_alloc_gsp_client;

+ ret = bootload_vgpu_plugin_task(vgpu);
+ if (ret)
+ goto err_bootload_vgpu_plugin_task;
+
atomic_set(&vgpu->status, 1);

return 0;

+err_bootload_vgpu_plugin_task:
+ nvidia_vgpu_mgr_free_gsp_client(vgpu_mgr, &vgpu->gsp_client);
err_alloc_gsp_client:
clean_mgmt_heap(vgpu);
err_setup_mgmt_heap:
--
2.34.1