[RFC 15/29] nvkm/vgpu: introduce FB memory allocation for vGPU

Zhi Wang
2024-09-22T12:50:48Z

Creating a vGPU requires allocating a mgmt heap from the FB memory. The
size of the mgmt heap that a vGPU requires is from the vGPU type.

Expose the FB memory allocation to NVIDIA vGPU VFIO module to allocate the
mgmt heap when creating a vGPU.

Signed-off-by: Zhi Wang <zhiw@nvidia.com>
---
.../nouveau/include/nvkm/vgpu_mgr/vgpu_mgr.h | 6 +++
drivers/gpu/drm/nouveau/nvkm/vgpu_mgr/vfio.c | 51 +++++++++++++++++++
include/drm/nvkm_vgpu_mgr_vfio.h | 8 +++
3 files changed, 65 insertions(+)

diff --git a/drivers/gpu/drm/nouveau/include/nvkm/vgpu_mgr/vgpu_mgr.h b/drivers/gpu/drm/nouveau/include/nvkm/vgpu_mgr/vgpu_mgr.h
index a351e8bfc772..b6e0321a53ad 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/vgpu_mgr/vgpu_mgr.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/vgpu_mgr/vgpu_mgr.h
@@ -6,6 +6,12 @@

#define NVIDIA_MAX_VGPUS 2

+struct nvkm_vgpu_mem {
+ struct nvidia_vgpu_mem base;
+ struct nvkm_memory *mem;
+ struct nvkm_vgpu_mgr *vgpu_mgr;
+};
+
struct nvkm_vgpu_mgr {
bool enabled;
struct nvkm_device *nvkm_dev;
diff --git a/drivers/gpu/drm/nouveau/nvkm/vgpu_mgr/vfio.c b/drivers/gpu/drm/nouveau/nvkm/vgpu_mgr/vfio.c
index 44d901a0474d..2aabb2c5f142 100644
--- a/drivers/gpu/drm/nouveau/nvkm/vgpu_mgr/vfio.c
+++ b/drivers/gpu/drm/nouveau/nvkm/vgpu_mgr/vfio.c
@@ -3,6 +3,7 @@
#include <core/device.h>
#include <engine/chid.h>
#include <engine/fifo.h>
+#include <subdev/bar.h>
#include <subdev/fb.h>
#include <subdev/gsp.h>

@@ -154,6 +155,54 @@ static int alloc_chids(void *handle, int count)
return ret;
}

+static void free_fbmem(struct nvidia_vgpu_mem *base)
+{
+ struct nvkm_vgpu_mem *mem =
+ container_of(base, struct nvkm_vgpu_mem, base);
+ struct nvkm_vgpu_mgr *vgpu_mgr = mem->vgpu_mgr;
+ struct nvkm_device *device = vgpu_mgr->nvkm_dev;
+
+ nvdev_debug(device, "free fb mem: addr %llx size %llx\n",
+ base->addr, base->size);
+
+ nvkm_memory_unref(&mem->mem);
+ kfree(mem);
+}
+
+static struct nvidia_vgpu_mem *alloc_fbmem(void *handle, u64 size,
+ bool vmmu_aligned)
+{
+ struct nvkm_device *device = handle;
+ struct nvkm_vgpu_mgr *vgpu_mgr = &device->vgpu_mgr;
+ struct nvidia_vgpu_mem *base;
+ struct nvkm_vgpu_mem *mem;
+ u32 shift = vmmu_aligned ? ilog2(vgpu_mgr->vmmu_segment_size) :
+ NVKM_RAM_MM_SHIFT;
+ int ret;
+
+ mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+ if (!mem)
+ return ERR_PTR(-ENOMEM);
+
+ base = &mem->base;
+
+ ret = nvkm_ram_get(device, NVKM_RAM_MM_NORMAL, 0x1, shift, size,
+ true, true, &mem->mem);
+ if (ret) {
+ kfree(mem);
+ return ERR_PTR(ret);
+ }
+
+ mem->vgpu_mgr = vgpu_mgr;
+ base->addr = mem->mem->func->addr(mem->mem);
+ base->size = mem->mem->func->size(mem->mem);
+
+ nvdev_debug(device, "alloc fb mem: addr %llx size %llx\n",
+ base->addr, base->size);
+
+ return base;
+}
+
struct nvkm_vgpu_mgr_vfio_ops nvkm_vgpu_mgr_vfio_ops = {
.vgpu_mgr_is_enabled = vgpu_mgr_is_enabled,
.get_handle = get_handle,
@@ -168,6 +217,8 @@ struct nvkm_vgpu_mgr_vfio_ops nvkm_vgpu_mgr_vfio_ops = {
.rm_ctrl_done = rm_ctrl_done,
.alloc_chids = alloc_chids,
.free_chids = free_chids,
+ .alloc_fbmem = alloc_fbmem,
+ .free_fbmem = free_fbmem,
};

/**
diff --git a/include/drm/nvkm_vgpu_mgr_vfio.h b/include/drm/nvkm_vgpu_mgr_vfio.h
index 001306fb0b5b..4841e9cf0d40 100644
--- a/include/drm/nvkm_vgpu_mgr_vfio.h
+++ b/include/drm/nvkm_vgpu_mgr_vfio.h
@@ -16,6 +16,11 @@ struct nvidia_vgpu_gsp_client {
void *gsp_device;
};

+struct nvidia_vgpu_mem {
+ u64 addr;
+ u64 size;
+};
+
struct nvkm_vgpu_mgr_vfio_ops {
bool (*vgpu_mgr_is_enabled)(void *handle);
void (*get_handle)(void *handle,
@@ -37,6 +42,9 @@ struct nvkm_vgpu_mgr_vfio_ops {
void *ctrl);
int (*alloc_chids)(void *handle, int count);
void (*free_chids)(void *handle, int offset, int count);
+ struct nvidia_vgpu_mem *(*alloc_fbmem)(void *handle, u64 size,
+ bool vmmu_aligned);
+ void (*free_fbmem)(struct nvidia_vgpu_mem *mem);
};

struct nvkm_vgpu_mgr_vfio_ops *nvkm_vgpu_mgr_get_vfio_ops(void *handle);
--
2.34.1