[RFC 28/29] vfio/vgpu_mgr: introduce vGPU host RPC channel

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

A newly created vGPU requires some runtime configuration to be uploaded
before moving on.

Introduce the vGPU host RPCs manipulation APIs to send vGPU RPCs.
Send vGPU RPCs to upload the runtime configuration of a vGPU.

Cc: Neo Jia <cjia@nvidia.com>
Cc: Surath Mitra <smitra@nvidia.com>
Signed-off-by: Zhi Wang <zhiw@nvidia.com>
---
drivers/vfio/pci/nvidia-vgpu/Makefile | 2 +-
drivers/vfio/pci/nvidia-vgpu/debug.h | 18 ++
.../nvidia/inc/ctrl/ctrl0000/ctrl0000system.h | 30 +++
.../nvrm/common/sdk/nvidia/inc/dev_vgpu_gsp.h | 213 +++++++++++++++
.../common/sdk/nvidia/inc/nv_vgpu_types.h | 51 ++++
.../common/sdk/vmioplugin/inc/vmioplugin.h | 26 ++
drivers/vfio/pci/nvidia-vgpu/rpc.c | 242 ++++++++++++++++++
drivers/vfio/pci/nvidia-vgpu/vgpu.c | 11 +
drivers/vfio/pci/nvidia-vgpu/vgpu_mgr.c | 31 +++
drivers/vfio/pci/nvidia-vgpu/vgpu_mgr.h | 21 ++
10 files changed, 644 insertions(+), 1 deletion(-)
create mode 100644 drivers/vfio/pci/nvidia-vgpu/debug.h
create mode 100644 drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/nvidia/inc/ctrl/ctrl0000/ctrl0000system.h
create mode 100644 drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/nvidia/inc/dev_vgpu_gsp.h
create mode 100644 drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/nvidia/inc/nv_vgpu_types.h
create mode 100644 drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/vmioplugin/inc/vmioplugin.h
create mode 100644 drivers/vfio/pci/nvidia-vgpu/rpc.c

diff --git a/drivers/vfio/pci/nvidia-vgpu/Makefile b/drivers/vfio/pci/nvidia-vgpu/Makefile
index bd65fa548ea1..fade9d49df97 100644
--- a/drivers/vfio/pci/nvidia-vgpu/Makefile
+++ b/drivers/vfio/pci/nvidia-vgpu/Makefile
@@ -2,4 +2,4 @@
ccflags-y += -I$(srctree)/$(src)/include

obj-$(CONFIG_NVIDIA_VGPU_MGR) += nvidia-vgpu-mgr.o
-nvidia-vgpu-mgr-y := vgpu_mgr.o vgpu.o vgpu_types.o
+nvidia-vgpu-mgr-y := vgpu_mgr.o vgpu.o vgpu_types.o rpc.o
diff --git a/drivers/vfio/pci/nvidia-vgpu/debug.h b/drivers/vfio/pci/nvidia-vgpu/debug.h
new file mode 100644
index 000000000000..bc1c4273f089
--- /dev/null
+++ b/drivers/vfio/pci/nvidia-vgpu/debug.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright © 2024 NVIDIA Corporation
+ */
+
+#ifndef __NVIDIA_VGPU_DEBUG_H__
+#define __NVIDIA_VGPU_DEBUG_H__
+
+#define nv_vgpu_dbg(v, f, a...) \
+ pci_dbg(v->pdev, "nvidia-vgpu %d: "f, v->info.id, ##a)
+
+#define nv_vgpu_info(v, f, a...) \
+ pci_info(v->pdev, "nvidia-vgpu %d: "f, v->info.id, ##a)
+
+#define nv_vgpu_err(v, f, a...) \
+ pci_err(v->pdev, "nvidia-vgpu %d: "f, v->info.id, ##a)
+
+#endif
diff --git a/drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/nvidia/inc/ctrl/ctrl0000/ctrl0000system.h b/drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/nvidia/inc/ctrl/ctrl0000/ctrl0000system.h
new file mode 100644
index 000000000000..871c498fb666
--- /dev/null
+++ b/drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/nvidia/inc/ctrl/ctrl0000/ctrl0000system.h
@@ -0,0 +1,30 @@
+#ifndef __src_common_sdk_nvidia_inc_ctrl_ctrl0000_ctrl0000system_h__
+#define __src_common_sdk_nvidia_inc_ctrl_ctrl0000_ctrl0000system_h__
+
+/* Excerpt of RM headers from https://github.com/NVIDIA/open-gpu-kernel-modules/tree/535.113.01 */
+
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2005-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#define NV0000_CTRL_CMD_SYSTEM_GET_VGX_SYSTEM_INFO_BUFFER_SIZE 256U
+#endif
diff --git a/drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/nvidia/inc/dev_vgpu_gsp.h b/drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/nvidia/inc/dev_vgpu_gsp.h
new file mode 100644
index 000000000000..8f3ea48ef10d
--- /dev/null
+++ b/drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/nvidia/inc/dev_vgpu_gsp.h
@@ -0,0 +1,213 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright © 2024 NVIDIA Corporation
+ */
+#ifndef __src_common_sdk_nvidia_inc_vgpu_dev_nv_vgpu_gsp_h__
+#define __src_common_sdk_nvidia_inc_vgpu_dev_nv_vgpu_gsp_h__
+
+#include "nv_vgpu_types.h"
+
+#define GSP_PLUGIN_BOOTLOADED 0x4E654A6F
+
+/******************************************************************************/
+/* GSP Control buffer shared between CPU Plugin and GSP Plugin - START */
+/******************************************************************************/
+
+/* GSP Plugin heap memory layout
+ +--------------------------------+ offset = 0
+ | CONTROL BUFFER |
+ +--------------------------------+
+ | RESPONSE BUFFER |
+ +--------------------------------+
+ | MESSAGE BUFFER |
+ +--------------------------------+
+ | MIGRATION BUFFER |
+ +--------------------------------+
+ | GSP PLUGIN ERROR BUFFER |
+ +--------------------------------+
+ | INIT TASK LOG BUFFER |
+ +--------------------------------+
+ | VGPU TASK LOG BUFFER |
+ +--------------------------------+
+ | MEMORY AVAILABLE FOR |
+ | GSP PLUGIN INTERNAL HEAP USAGE |
+ +--------------------------------+
+ */
+#define VGPU_CPU_GSP_CTRL_BUFF_VERSION 0x1
+#define VGPU_CPU_GSP_CTRL_BUFF_REGION_SIZE 4096
+#define VGPU_CPU_GSP_RESPONSE_BUFF_REGION_SIZE 4096
+#define VGPU_CPU_GSP_MESSAGE_BUFF_REGION_SIZE 4096
+#define VGPU_CPU_GSP_MIGRATION_BUFF_REGION_SIZE (2 * 1024 * 1024)
+#define VGPU_CPU_GSP_ERROR_BUFF_REGION_SIZE 4096
+#define VGPU_CPU_GSP_INIT_TASK_LOG_BUFF_REGION_SIZE (128 * 1024)
+#define VGPU_CPU_GSP_VGPU_TASK_LOG_BUFF_REGION_SIZE (256 * 1024)
+#define VGPU_CPU_GSP_COMMUNICATION_BUFF_TOTAL_SIZE (VGPU_CPU_GSP_CTRL_BUFF_REGION_SIZE + \
+ VGPU_CPU_GSP_RESPONSE_BUFF_REGION_SIZE + \
+ VGPU_CPU_GSP_MESSAGE_BUFF_REGION_SIZE + \
+ VGPU_CPU_GSP_MIGRATION_BUFF_REGION_SIZE + \
+ VGPU_CPU_GSP_ERROR_BUFF_REGION_SIZE + \
+ VGPU_CPU_GSP_INIT_TASK_LOG_BUFF_REGION_SIZE + \
+ VGPU_CPU_GSP_VGPU_TASK_LOG_BUFF_REGION_SIZE)
+
+//
+// Control buffer: CPU Plugin -> GSP Plugin
+// CPU Plugin - Write only
+// GSP Plugin - Read only
+//
+typedef union {
+ NvU8 buf[VGPU_CPU_GSP_CTRL_BUFF_REGION_SIZE];
+ struct {
+ volatile NvU32 version; // Version of format
+ volatile NvU32 message_type; // Task to be performed by GSP Plugin
+ volatile NvU32 message_seq_num; // Incrementing sequence number to identify the RPC packet
+ volatile NvU64 response_buff_offset; // Buffer used to send data from GSP Plugin -> CPU Plugin
+ volatile NvU64 message_buff_offset; // Buffer used to send RPC data between CPU and GSP Plugin
+ volatile NvU64 migration_buff_offset; // Buffer used to send migration data between CPU and GSP Plugin
+ volatile NvU64 error_buff_offset; // Buffer used to send error data from GSP Plugin -> CPU Plugin
+ volatile NvU32 migration_buf_cpu_access_offset;// CPU plugin GET/PUT offset of migration buffer
+ volatile NvBool is_migration_in_progress; // Is migration active or cancelled
+ volatile NvU32 error_buff_cpu_get_idx; // GET pointer into ERROR Buffer for CPU Plugin
+ volatile NvU32 attached_vgpu_count;
+ volatile struct {
+ NvU32 vgpu_type_id;
+ NvU32 host_gpu_pci_id;
+ NvU32 pci_dev_id;
+ NvU8 vgpu_uuid[VM_UUID_SIZE];
+ } host_info[VMIOPD_MAX_INSTANCES];
+ };
+} VGPU_CPU_GSP_CTRL_BUFF_REGION;
+
+//
+// Specify actions intended on getting
+// notification from CPU Plugin -> GSP plugin
+//
+typedef enum {
+ NV_VGPU_CPU_RPC_MSG_VERSION_NEGOTIATION = 1,
+ NV_VGPU_CPU_RPC_MSG_SETUP_CONFIG_PARAMS_AND_INIT,
+ NV_VGPU_CPU_RPC_MSG_RESET,
+ NV_VGPU_CPU_RPC_MSG_MIGRATION_STOP_WORK,
+ NV_VGPU_CPU_RPC_MSG_MIGRATION_CANCEL_STOP,
+ NV_VGPU_CPU_RPC_MSG_MIGRATION_SAVE_STATE,
+ NV_VGPU_CPU_RPC_MSG_MIGRATION_CANCEL_SAVE,
+ NV_VGPU_CPU_RPC_MSG_MIGRATION_RESTORE_STATE,
+ NV_VGPU_CPU_RPC_MSG_MIGRATION_RESTORE_DEFERRED_STATE,
+ NV_VGPU_CPU_RPC_MSG_MIGRATION_RESUME_WORK,
+ NV_VGPU_CPU_RPC_MSG_CONSOLE_VNC_STATE,
+ NV_VGPU_CPU_RPC_MSG_VF_BAR0_REG_ACCESS,
+ NV_VGPU_CPU_RPC_MSG_UPDATE_BME_STATE,
+ NV_VGPU_CPU_RPC_MSG_GET_GUEST_INFO,
+ NV_VGPU_CPU_RPC_MSG_MAX,
+} MESSAGE;
+
+//
+// Params structure for NV_VGPU_CPU_RPC_MSG_VERSION_NEGOTIATION
+//
+typedef struct {
+ volatile NvU32 version_cpu; /* Sent by CPU Plugin */
+ volatile NvU32 version_negotiated; /* Updated by GSP Plugin */
+} NV_VGPU_CPU_RPC_DATA_VERSION_NEGOTIATION;
+
+//
+// Host CPU arch
+//
+typedef enum {
+ NV_VGPU_HOST_CPU_ARCH_AARCH64 = 1,
+ NV_VGPU_HOST_CPU_ARCH_X86_64,
+} NV_VGPU_HOST_CPU_ARCH;
+
+//
+// Params structure for NV_VGPU_CPU_RPC_MSG_COPY_CONFIG_PARAMS
+//
+typedef struct {
+ volatile NvU8 vgpu_uuid[VM_UUID_SIZE];
+ volatile NvU32 dbdf;
+ volatile NvU32 driver_vm_vf_dbdf;
+ volatile NvU32 vgpu_device_instance_id;
+ volatile NvU32 vgpu_type;
+ volatile NvU32 vm_pid;
+ volatile NvU32 swizz_id;
+ volatile NvU32 num_channels;
+ volatile NvU32 num_plugin_channels;
+ volatile NvU32 vmm_cap;
+ volatile NvU32 migration_feature;
+ volatile NvU32 hypervisor_type;
+ volatile NvU32 host_cpu_arch;
+ volatile NvU64 host_page_size;
+ volatile NvBool rev1[2];
+ volatile NvBool enable_uvm;
+ volatile NvBool linux_interrupt_optimization;
+ volatile NvBool vmm_migration_supported;
+ volatile NvBool rev2;
+ volatile NvBool enable_console_vnc;
+ volatile NvBool use_non_stall_linux_events;
+ volatile NvU32 rev3;
+} NV_VGPU_CPU_RPC_DATA_COPY_CONFIG_PARAMS;
+
+// Params structure for NV_VGPU_CPU_RPC_MSG_UPDATE_BME_STATE
+typedef struct {
+ volatile NvBool enable;
+ volatile NvBool allowed;
+} NV_VGPU_CPU_RPC_DATA_UPDATE_BME_STATE;
+//
+// Message Buffer:
+// CPU Plugin - Read/Write
+// GSP Plugin - Read/Write
+//
+typedef union {
+ NvU8 buf[VGPU_CPU_GSP_MESSAGE_BUFF_REGION_SIZE];
+ NV_VGPU_CPU_RPC_DATA_VERSION_NEGOTIATION version_data;
+ NV_VGPU_CPU_RPC_DATA_COPY_CONFIG_PARAMS config_data;
+ NV_VGPU_CPU_RPC_DATA_UPDATE_BME_STATE bme_state;
+} VGPU_CPU_GSP_MSG_BUFF_REGION;
+
+typedef struct {
+ volatile NvU64 sequence_update_start;
+ volatile NvU64 sequence_update_end;
+ volatile NvU32 effective_fb_page_size;
+ volatile NvU32 rect_width;
+ volatile NvU32 rect_height;
+ volatile NvU32 surface_width;
+ volatile NvU32 surface_height;
+ volatile NvU32 surface_size;
+ volatile NvU32 surface_offset;
+ volatile NvU32 surface_format;
+ volatile NvU32 surface_kind;
+ volatile NvU32 surface_pitch;
+ volatile NvU32 surface_type;
+ volatile NvU8 surface_block_height;
+ volatile vmiop_bool_t is_blanking_enabled;
+ volatile vmiop_bool_t is_flip_pending;
+ volatile vmiop_bool_t is_free_pending;
+ volatile vmiop_bool_t is_memory_blocklinear;
+} VGPU_CPU_GSP_DISPLAYLESS_SURFACE;
+
+//
+// GSP Plugin Response Buffer:
+// CPU Plugin - Read only
+// GSP Plugin - Write only
+//
+typedef union {
+ NvU8 buf[VGPU_CPU_GSP_RESPONSE_BUFF_REGION_SIZE];
+ struct {
+ // Updated by GSP Plugin once task is complete
+ volatile NvU32 message_seq_num_processed;
+ // Updated by GSP on completion of RPC
+ volatile NvU32 result_code;
+ volatile NvU32 guest_rpc_version;
+ // GSP plugin GET/PUT offset pointer of migration buffer
+ volatile NvU32 migration_buf_gsp_access_offset;
+ // Current state of migration
+ volatile NvU32 migration_state_save_complete;
+ // Console VNC surface information
+ volatile VGPU_CPU_GSP_DISPLAYLESS_SURFACE surface[VMIOPD_MAX_HEADS];
+ // PUT pointer into ERROR Buffer for GSP Plugin
+ volatile NvU32 error_buff_gsp_put_idx;
+ // Updated grid license state as received from guest
+ volatile NvU32 grid_license_state;
+ };
+} VGPU_CPU_GSP_RESPONSE_BUFF_REGION;
+
+/******************************************************************************/
+/* GSP Control buffer shared between CPU Plugin and GSP Plugin - END */
+/******************************************************************************/
+#endif
diff --git a/drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/nvidia/inc/nv_vgpu_types.h b/drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/nvidia/inc/nv_vgpu_types.h
new file mode 100644
index 000000000000..903a5840366c
--- /dev/null
+++ b/drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/nvidia/inc/nv_vgpu_types.h
@@ -0,0 +1,51 @@
+#ifndef __src_common_sdk_nvidia_inc_nv_vgpu_types_h__
+#define __src_common_sdk_nvidia_inc_nv_vgpu_types_h__
+
+/* Excerpt of RM headers from https://github.com/NVIDIA/open-gpu-kernel-modules/tree/535.113.01 */
+
+/*
+ * SPDX-FileCopyrightText: Copyright (c) 2016-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#define VM_UUID_SIZE 16
+#define INVALID_VGPU_DEV_INST 0xFFFFFFFFU
+#define MAX_VGPU_DEVICES_PER_VM 16U
+
+/* This enum represents the current state of guest dependent fields */
+typedef enum GUEST_VM_INFO_STATE {
+ GUEST_VM_INFO_STATE_UNINITIALIZED = 0,
+ GUEST_VM_INFO_STATE_INITIALIZED = 1,
+} GUEST_VM_INFO_STATE;
+
+/* This enum represents types of VM identifiers */
+typedef enum VM_ID_TYPE {
+ VM_ID_DOMAIN_ID = 0,
+ VM_ID_UUID = 1,
+} VM_ID_TYPE;
+
+/* This structure represents VM identifier */
+typedef union VM_ID {
+ NvU8 vmUuid[VM_UUID_SIZE];
+ NV_DECLARE_ALIGNED(NvU64 vmId, 8);
+} VM_ID;
+
+#endif
diff --git a/drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/vmioplugin/inc/vmioplugin.h b/drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/vmioplugin/inc/vmioplugin.h
new file mode 100644
index 000000000000..58a473309e42
--- /dev/null
+++ b/drivers/vfio/pci/nvidia-vgpu/include/nvrm/common/sdk/vmioplugin/inc/vmioplugin.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright © 2024 NVIDIA Corporation
+ */
+#ifndef __src_common_sdk_vmioplugin_inc_vmioplugin_h__
+#define __src_common_sdk_vmioplugin_inc_vmioplugin_h__
+
+#define VMIOPD_MAX_INSTANCES 16
+#define VMIOPD_MAX_HEADS 4
+
+/**
+ * Boolean type.
+ */
+
+enum vmiop_bool_e {
+ vmiop_false = 0, /*!< Boolean false */
+ vmiop_true = 1 /*!< Boolean true */
+};
+
+/**
+ * Boolean type.
+ */
+
+typedef enum vmiop_bool_e vmiop_bool_t;
+
+#endif
diff --git a/drivers/vfio/pci/nvidia-vgpu/rpc.c b/drivers/vfio/pci/nvidia-vgpu/rpc.c
new file mode 100644
index 000000000000..c316941f4b97
--- /dev/null
+++ b/drivers/vfio/pci/nvidia-vgpu/rpc.c
@@ -0,0 +1,242 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright © 2024 NVIDIA Corporation
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+
+#include <nvrm/nvtypes.h>
+#include <nvrm/common/sdk/nvidia/inc/ctrl/ctrl0000/ctrl0000system.h>
+#include <nvrm/common/sdk/vmioplugin/inc/vmioplugin.h>
+#include <nvrm/common/sdk/nvidia/inc/dev_vgpu_gsp.h>
+#include <nvrm/common/sdk/nvidia/inc/ctrl/ctrla081.h>
+
+#include "debug.h"
+#include "vgpu_mgr.h"
+
+static void trigger_doorbell(struct nvidia_vgpu *vgpu)
+{
+ struct nvidia_vgpu_mgr *vgpu_mgr = vgpu->vgpu_mgr;
+
+ u32 v = vgpu->info.gfid * 32 + 17;
+
+ writel(v, vgpu_mgr->bar0_vaddr + 0x00B80000 + 0x2200);
+ readl(vgpu_mgr->bar0_vaddr + 0x00B80000 + 0x2200);
+}
+
+static void send_rpc_request(struct nvidia_vgpu *vgpu, u32 msg_type,
+ void *data, u64 size)
+{
+ struct nvidia_vgpu_rpc *rpc = &vgpu->rpc;
+ VGPU_CPU_GSP_CTRL_BUFF_REGION *ctrl_buf = rpc->ctrl_buf;
+
+ if (data && size)
+ memcpy_toio(rpc->msg_buf, data, size);
+
+ ctrl_buf->message_type = msg_type;
+
+ rpc->msg_seq_num++;
+ ctrl_buf->message_seq_num = rpc->msg_seq_num;
+
+ trigger_doorbell(vgpu);
+}
+
+static int wait_for_response(struct nvidia_vgpu *vgpu)
+{
+ struct nvidia_vgpu_rpc *rpc = &vgpu->rpc;
+ VGPU_CPU_GSP_RESPONSE_BUFF_REGION *resp_buf = rpc->resp_buf;
+
+ u64 timeout = 120 * 1000000; /* 120s */
+
+ do {
+ if (resp_buf->message_seq_num_processed == rpc->msg_seq_num)
+ break;
+
+ usleep_range(1, 2);
+ } while (--timeout);
+
+ return timeout ? 0 : -ETIMEDOUT;
+}
+
+static int recv_rpc_response(struct nvidia_vgpu *vgpu, void *data,
+ u64 size, u32 *result)
+{
+ struct nvidia_vgpu_rpc *rpc = &vgpu->rpc;
+ VGPU_CPU_GSP_RESPONSE_BUFF_REGION *resp_buf = rpc->resp_buf;
+ int ret;
+
+ ret = wait_for_response(vgpu);
+ if (result)
+ *result = resp_buf->result_code;
+
+ if (ret)
+ return ret;
+
+ if (data && size)
+ memcpy_fromio(data, rpc->msg_buf, size);
+
+ return 0;
+}
+
+int nvidia_vgpu_rpc_call(struct nvidia_vgpu *vgpu, u32 msg_type,
+ void *data, u64 size)
+{
+ struct nvidia_vgpu_rpc *rpc = &vgpu->rpc;
+ u32 result;
+ int ret;
+
+ if (WARN_ON(msg_type >= NV_VGPU_CPU_RPC_MSG_MAX) ||
+ (size > VGPU_CPU_GSP_MESSAGE_BUFF_REGION_SIZE) ||
+ ((size != 0) && (data == NULL)))
+ return -EINVAL;
+
+ mutex_lock(&rpc->lock);
+
+ send_rpc_request(vgpu, msg_type, data, size);
+ ret = recv_rpc_response(vgpu, data, size, &result);
+
+ mutex_unlock(&rpc->lock);
+ if (ret || result) {
+ nv_vgpu_err(vgpu, "fail to recv RPC: result %u\n",
+ result);
+ return -EINVAL;
+ }
+ return ret;
+}
+
+void nvidia_vgpu_clean_rpc(struct nvidia_vgpu *vgpu)
+{
+}
+
+static void init_rpc_buf_pointers(struct nvidia_vgpu *vgpu)
+{
+ struct nvidia_vgpu_mgmt *mgmt = &vgpu->mgmt;
+ struct nvidia_vgpu_rpc *rpc = &vgpu->rpc;
+
+ rpc->ctrl_buf = mgmt->ctrl_vaddr;
+ rpc->resp_buf = rpc->ctrl_buf + VGPU_CPU_GSP_CTRL_BUFF_REGION_SIZE;
+ rpc->msg_buf = rpc->resp_buf + VGPU_CPU_GSP_RESPONSE_BUFF_REGION_SIZE;
+ rpc->migration_buf = rpc->msg_buf + VGPU_CPU_GSP_MESSAGE_BUFF_REGION_SIZE;
+ rpc->error_buf = rpc->migration_buf + VGPU_CPU_GSP_MIGRATION_BUFF_REGION_SIZE;
+}
+
+static void init_ctrl_buf_offsets(struct nvidia_vgpu *vgpu)
+{
+ struct nvidia_vgpu_rpc *rpc = &vgpu->rpc;
+ VGPU_CPU_GSP_CTRL_BUFF_REGION *ctrl_buf;
+ u64 offset = 0;
+
+ ctrl_buf = rpc->ctrl_buf;
+
+ ctrl_buf->version = VGPU_CPU_GSP_CTRL_BUFF_VERSION;
+
+ offset = VGPU_CPU_GSP_CTRL_BUFF_REGION_SIZE;
+ ctrl_buf->response_buff_offset = offset;
+
+ offset += VGPU_CPU_GSP_RESPONSE_BUFF_REGION_SIZE;
+ ctrl_buf->message_buff_offset = offset;
+
+ offset += VGPU_CPU_GSP_MESSAGE_BUFF_REGION_SIZE;
+ ctrl_buf->migration_buff_offset = offset;
+
+ offset += VGPU_CPU_GSP_MIGRATION_BUFF_REGION_SIZE;
+ ctrl_buf->error_buff_offset = offset;
+}
+
+static int wait_vgpu_plugin_task_bootloaded(struct nvidia_vgpu *vgpu)
+{
+ struct nvidia_vgpu_rpc *rpc = &vgpu->rpc;
+ VGPU_CPU_GSP_CTRL_BUFF_REGION *ctrl_buf = rpc->ctrl_buf;
+
+ u64 timeout = 10 * 1000000; /* 10 s */
+
+ do {
+ if (ctrl_buf->message_seq_num == GSP_PLUGIN_BOOTLOADED)
+ break;
+
+ usleep_range(1, 2);
+ } while (--timeout);
+
+ return timeout ? 0 : -ETIMEDOUT;
+}
+
+static int negotiate_rpc_version(struct nvidia_vgpu *vgpu)
+{
+ return nvidia_vgpu_rpc_call(vgpu, NV_VGPU_CPU_RPC_MSG_VERSION_NEGOTIATION,
+ NULL, 0);
+}
+
+unsigned char config_params[] = {
+ 0x24, 0xef, 0x8f, 0xf7, 0x3e, 0xd5, 0x11, 0xef, 0xae, 0x36, 0x97, 0x58,
+ 0xb1, 0xcb, 0x0c, 0x87, 0x04, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0xd0, 0xc1, 0x65, 0x03, 0x00, 0x00, 0xa1, 0x0e, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0x40, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+};
+
+static int send_config_params_and_init(struct nvidia_vgpu *vgpu)
+{
+ struct nvidia_vgpu_mgr *vgpu_mgr = vgpu->vgpu_mgr;
+ NV_VGPU_CPU_RPC_DATA_COPY_CONFIG_PARAMS params = {0};
+ NVA081_CTRL_VGPU_INFO *info = (NVA081_CTRL_VGPU_INFO *)
+ vgpu->vgpu_type;
+
+ memcpy(&params, config_params, sizeof(config_params));
+
+ params.dbdf = vgpu->info.dbdf;
+ params.vgpu_device_instance_id =
+ nvidia_vgpu_mgr_get_gsp_client_handle(vgpu_mgr, &vgpu->gsp_client);
+ params.vgpu_type = info->vgpuType;
+ params.vm_pid = 0;
+ params.swizz_id = 0;
+ params.num_channels = vgpu->chid.num_chid;
+ params.num_plugin_channels = vgpu->chid.num_plugin_channels;
+
+ return nvidia_vgpu_rpc_call(vgpu, NV_VGPU_CPU_RPC_MSG_SETUP_CONFIG_PARAMS_AND_INIT,
+ &params, sizeof(params));
+}
+
+/**
+ * nvidia_vgpu_setup_rpc - setup the vGPU host RPC channel and send runtime
+ * configuration.
+ * @vgpu: the vGPU instance.
+ * @vgpu_type: the vGPU type of the vGPU instance.
+ *
+ * Returns: 0 on success, others on failure.
+ */
+int nvidia_vgpu_setup_rpc(struct nvidia_vgpu *vgpu)
+{
+ struct nvidia_vgpu_rpc *rpc = &vgpu->rpc;
+ int ret;
+
+ mutex_init(&rpc->lock);
+
+ init_rpc_buf_pointers(vgpu);
+ init_ctrl_buf_offsets(vgpu);
+
+ ret = wait_vgpu_plugin_task_bootloaded(vgpu);
+ if (ret) {
+ nv_vgpu_err(vgpu, "waiting bootload timeout!\n");
+ return ret;
+ }
+
+ ret = negotiate_rpc_version(vgpu);
+ if (ret) {
+ nv_vgpu_err(vgpu, "fail to negotiate rpc version!\n");
+ return ret;
+ }
+
+ ret = send_config_params_and_init(vgpu);
+ if (ret) {
+ nv_vgpu_err(vgpu, "fail to init vgpu plugin task!\n");
+ return ret;
+ }
+
+ nv_vgpu_dbg(vgpu, "vGPU RPC initialization is done.\n");
+
+ return 0;
+}
diff --git a/drivers/vfio/pci/nvidia-vgpu/vgpu.c b/drivers/vfio/pci/nvidia-vgpu/vgpu.c
index e06d5155bb38..93d27db30a41 100644
--- a/drivers/vfio/pci/nvidia-vgpu/vgpu.c
+++ b/drivers/vfio/pci/nvidia-vgpu/vgpu.c
@@ -8,6 +8,9 @@
#include <nvrm/nvtypes.h>
#include <nvrm/common/sdk/nvidia/inc/ctrl/ctrla081.h>
#include <nvrm/common/sdk/nvidia/inc/ctrl/ctrl2080/ctrl2080vgpumgrinternal.h>
+#include <nvrm/common/sdk/nvidia/inc/ctrl/ctrl0000/ctrl0000system.h>
+#include <nvrm/common/sdk/vmioplugin/inc/vmioplugin.h>
+#include <nvrm/common/sdk/nvidia/inc/dev_vgpu_gsp.h>

#include "vgpu_mgr.h"

@@ -240,6 +243,7 @@ int nvidia_vgpu_mgr_destroy_vgpu(struct nvidia_vgpu *vgpu)
if (!atomic_cmpxchg(&vgpu->status, 1, 0))
return -ENODEV;

+ nvidia_vgpu_clean_rpc(vgpu);
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);
@@ -299,10 +303,17 @@ int nvidia_vgpu_mgr_create_vgpu(struct nvidia_vgpu *vgpu, u8 *vgpu_type)
if (ret)
goto err_bootload_vgpu_plugin_task;

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

return 0;

+err_setup_rpc:
+ shutdown_vgpu_plugin_task(vgpu);
+ cleanup_vgpu_plugin_task(vgpu);
err_bootload_vgpu_plugin_task:
nvidia_vgpu_mgr_free_gsp_client(vgpu_mgr, &vgpu->gsp_client);
err_alloc_gsp_client:
diff --git a/drivers/vfio/pci/nvidia-vgpu/vgpu_mgr.c b/drivers/vfio/pci/nvidia-vgpu/vgpu_mgr.c
index dcb314b14f91..e84cf4a845d4 100644
--- a/drivers/vfio/pci/nvidia-vgpu/vgpu_mgr.c
+++ b/drivers/vfio/pci/nvidia-vgpu/vgpu_mgr.c
@@ -7,11 +7,35 @@

DEFINE_MUTEX(vgpu_mgr_attach_lock);

+static void unmap_pf_mmio(struct nvidia_vgpu_mgr *vgpu_mgr)
+{
+ iounmap(vgpu_mgr->bar0_vaddr);
+}
+
+static int map_pf_mmio(struct nvidia_vgpu_mgr *vgpu_mgr)
+{
+ struct pci_dev *pdev = vgpu_mgr->pdev;
+ resource_size_t start, size;
+ void *vaddr;
+
+ start = pci_resource_start(pdev, 0);
+ size = pci_resource_len(pdev, 0);
+
+ vaddr = ioremap(start, size);
+ if (!vaddr)
+ return -ENOMEM;
+
+ vgpu_mgr->bar0_vaddr = vaddr;
+
+ return 0;
+}
+
static void vgpu_mgr_release(struct kref *kref)
{
struct nvidia_vgpu_mgr *vgpu_mgr =
container_of(kref, struct nvidia_vgpu_mgr, refcount);

+ unmap_pf_mmio(vgpu_mgr);
nvidia_vgpu_mgr_free_gsp_client(vgpu_mgr, &vgpu_mgr->gsp_client);
nvidia_vgpu_mgr_detach_handle(&vgpu_mgr->handle);
kvfree(vgpu_mgr);
@@ -83,6 +107,8 @@ struct nvidia_vgpu_mgr *nvidia_vgpu_mgr_get(struct pci_dev *dev)
kref_init(&vgpu_mgr->refcount);
mutex_init(&vgpu_mgr->vgpu_id_lock);

+ vgpu_mgr->pdev = dev->physfn;
+
ret = nvidia_vgpu_mgr_alloc_gsp_client(vgpu_mgr,
&vgpu_mgr->gsp_client);
if (ret)
@@ -92,9 +118,14 @@ struct nvidia_vgpu_mgr *nvidia_vgpu_mgr_get(struct pci_dev *dev)
if (ret)
goto fail_init_vgpu_types;

+ ret = map_pf_mmio(vgpu_mgr);
+ if (ret)
+ goto fail_map_pf_mmio;
+
mutex_unlock(&vgpu_mgr_attach_lock);
return vgpu_mgr;

+fail_map_pf_mmio:
fail_init_vgpu_types:
nvidia_vgpu_mgr_free_gsp_client(vgpu_mgr, &vgpu_mgr->gsp_client);
fail_alloc_gsp_client:
diff --git a/drivers/vfio/pci/nvidia-vgpu/vgpu_mgr.h b/drivers/vfio/pci/nvidia-vgpu/vgpu_mgr.h
index 6f05b285484c..af922d8e539c 100644
--- a/drivers/vfio/pci/nvidia-vgpu/vgpu_mgr.h
+++ b/drivers/vfio/pci/nvidia-vgpu/vgpu_mgr.h
@@ -28,6 +28,16 @@ struct nvidia_vgpu_mgmt {
void __iomem *vgpu_task_log_vaddr;
};

+struct nvidia_vgpu_rpc {
+ struct mutex lock;
+ u32 msg_seq_num;
+ void __iomem *ctrl_buf;
+ void __iomem *resp_buf;
+ void __iomem *msg_buf;
+ void __iomem *migration_buf;
+ void __iomem *error_buf;
+};
+
struct nvidia_vgpu {
struct mutex lock;
atomic_t status;
@@ -41,6 +51,7 @@ struct nvidia_vgpu {
struct nvidia_vgpu_mem *fbmem_heap;
struct nvidia_vgpu_chid chid;
struct nvidia_vgpu_mgmt mgmt;
+ struct nvidia_vgpu_rpc rpc;
};

struct nvidia_vgpu_mgr {
@@ -55,6 +66,9 @@ struct nvidia_vgpu_mgr {
u32 num_vgpu_types;

struct nvidia_vgpu_gsp_client gsp_client;
+
+ struct pci_dev *pdev;
+ void __iomem *bar0_vaddr;
};

struct nvidia_vgpu_mgr *nvidia_vgpu_mgr_get(struct pci_dev *dev);
@@ -65,4 +79,11 @@ int nvidia_vgpu_mgr_create_vgpu(struct nvidia_vgpu *vgpu, u8 *vgpu_type);

int nvidia_vgpu_mgr_init_vgpu_types(struct nvidia_vgpu_mgr *vgpu_mgr);

+int nvidia_vgpu_rpc_call(struct nvidia_vgpu *vgpu, u32 msg_type,
+ void *data, u64 size);
+void nvidia_vgpu_clean_rpc(struct nvidia_vgpu *vgpu);
+int nvidia_vgpu_setup_rpc(struct nvidia_vgpu *vgpu);
+
+int nvidia_vgpu_mgr_reset_vgpu(struct nvidia_vgpu *vgpu);
+
#endif
--
2.34.1