summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Gabrylchuk <oleksandr.gabrylchuk@opensynergy.com>2022-02-24 12:06:48 +0100
committerMarge Bot <emma+marge@anholt.net>2022-03-01 17:25:56 +0000
commit02fab4cf9e3a7fd824dc2fc99e5b1abea02ec8ce (patch)
tree2b83c4a8af0501cbd5092a2166c43163be413ba8
parentfd3451babd6cded6794561d74c8919576ba1f97d (diff)
venus: Implement guest vram blob type.
Add support of GUEST_VRAM type of blob. These are dedicated heap memory allocations required for vk support on hypervisors that don't support runtime injections of host memory into guest physical address space. The flow of usage: 1) Host VM reserves dedicated heap memory 2) Device get info about memory reservations and report it to guest using mmio registers 3) Guest virtio-gpu driver on starts checks mmio registers for physical address and length of reserved region. Then it reserves it in guest. 4) On each call of vkAllocateMemory() guest driver gets chunk of required memory and send it to host using sg list. It uses one sg entry for 1 blob call. Heap is managed on guest using drm memory manager (drm_mm). Signed-off-by: Oleksandr.Gabrylchuk <Oleksandr.Gabrylchuk@opensynergy.com> Signed-off-by: Andrii Pauk <Andrii.Pauk@opensynergy.com> Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org> Reviewed-by: Chia-I Wu <olvaffe@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14536>
-rw-r--r--src/virtio/vulkan/vn_device_memory.c98
-rw-r--r--src/virtio/vulkan/vn_renderer.h1
-rw-r--r--src/virtio/vulkan/vn_renderer_virtgpu.c40
3 files changed, 126 insertions, 13 deletions
diff --git a/src/virtio/vulkan/vn_device_memory.c b/src/virtio/vulkan/vn_device_memory.c
index 2d9c9b92c33..62125cfb2ce 100644
--- a/src/virtio/vulkan/vn_device_memory.c
+++ b/src/virtio/vulkan/vn_device_memory.c
@@ -189,9 +189,16 @@ vn_device_memory_pool_suballocate(struct vn_device *dev,
}
static bool
-vn_device_memory_should_suballocate(const VkMemoryAllocateInfo *alloc_info,
+vn_device_memory_should_suballocate(const struct vn_device *dev,
+ const VkMemoryAllocateInfo *alloc_info,
const VkMemoryPropertyFlags flags)
{
+ const struct vn_instance *instance = dev->physical_device->instance;
+ const struct vn_renderer_info *renderer = &instance->renderer->info;
+
+ if (renderer->has_guest_vram)
+ return false;
+
/* We should not support suballocations because apps can do better. But
* each BO takes up a KVM memslot currently and some CTS tests exhausts
* them. This might not be needed on newer (host) kernels where there are
@@ -285,15 +292,71 @@ vn_device_memory_import_dma_buf(struct vn_device *dev,
}
static VkResult
-vn_device_memory_alloc(struct vn_device *dev,
- struct vn_device_memory *mem,
- const VkMemoryAllocateInfo *alloc_info,
- VkExternalMemoryHandleTypeFlags external_handles)
+vn_device_memory_alloc_guest_vram(
+ struct vn_device *dev,
+ struct vn_device_memory *mem,
+ const VkMemoryAllocateInfo *alloc_info,
+ VkExternalMemoryHandleTypeFlags external_handles)
{
VkDevice dev_handle = vn_device_to_handle(dev);
VkDeviceMemory mem_handle = vn_device_memory_to_handle(mem);
- VkResult result = vn_call_vkAllocateMemory(dev->instance, dev_handle,
- alloc_info, NULL, &mem_handle);
+ VkResult result = VK_SUCCESS;
+
+ result = vn_renderer_bo_create_from_device_memory(
+ dev->renderer, mem->size, 0, mem->flags, external_handles,
+ &mem->base_bo);
+ if (result != VK_SUCCESS) {
+ return result;
+ }
+
+ const VkImportMemoryResourceInfoMESA import_memory_resource_info = {
+ .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_RESOURCE_INFO_MESA,
+ .pNext = alloc_info->pNext,
+ .resourceId = mem->base_bo->res_id,
+ };
+
+ const VkMemoryAllocateInfo memory_allocate_info = {
+ .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ .pNext = &import_memory_resource_info,
+ .allocationSize = alloc_info->allocationSize,
+ .memoryTypeIndex = alloc_info->memoryTypeIndex,
+ };
+
+ vn_instance_roundtrip(dev->instance);
+
+ result = vn_call_vkAllocateMemory(
+ dev->instance, dev_handle, &memory_allocate_info, NULL, &mem_handle);
+ if (result != VK_SUCCESS) {
+ vn_renderer_bo_unref(dev->renderer, mem->base_bo);
+ return result;
+ }
+
+ result =
+ vn_instance_submit_roundtrip(dev->instance, &mem->bo_roundtrip_seqno);
+ if (result != VK_SUCCESS) {
+ vn_renderer_bo_unref(dev->renderer, mem->base_bo);
+ vn_async_vkFreeMemory(dev->instance, dev_handle, mem_handle, NULL);
+ return result;
+ }
+
+ mem->bo_roundtrip_seqno_valid = true;
+
+ return VK_SUCCESS;
+}
+
+static VkResult
+vn_device_memory_alloc_generic(
+ struct vn_device *dev,
+ struct vn_device_memory *mem,
+ const VkMemoryAllocateInfo *alloc_info,
+ VkExternalMemoryHandleTypeFlags external_handles)
+{
+ VkDevice dev_handle = vn_device_to_handle(dev);
+ VkDeviceMemory mem_handle = vn_device_memory_to_handle(mem);
+ VkResult result = VK_SUCCESS;
+
+ result = vn_call_vkAllocateMemory(dev->instance, dev_handle, alloc_info,
+ NULL, &mem_handle);
if (result != VK_SUCCESS || !external_handles)
return result;
@@ -318,6 +381,24 @@ vn_device_memory_alloc(struct vn_device *dev,
return VK_SUCCESS;
}
+static VkResult
+vn_device_memory_alloc(struct vn_device *dev,
+ struct vn_device_memory *mem,
+ const VkMemoryAllocateInfo *alloc_info,
+ VkExternalMemoryHandleTypeFlags external_handles)
+{
+ const struct vn_instance *instance = dev->physical_device->instance;
+ const struct vn_renderer_info *renderer_info = &instance->renderer->info;
+
+ if (renderer_info->has_guest_vram) {
+ return vn_device_memory_alloc_guest_vram(dev, mem, alloc_info,
+ external_handles);
+ }
+
+ return vn_device_memory_alloc_generic(dev, mem, alloc_info,
+ external_handles);
+}
+
VkResult
vn_AllocateMemory(VkDevice device,
const VkMemoryAllocateInfo *pAllocateInfo,
@@ -382,7 +463,8 @@ vn_AllocateMemory(VkDevice device,
} else if (export_info) {
result = vn_device_memory_alloc(dev, mem, pAllocateInfo,
export_info->handleTypes);
- } else if (vn_device_memory_should_suballocate(pAllocateInfo, mem_flags)) {
+ } else if (vn_device_memory_should_suballocate(dev, pAllocateInfo,
+ mem_flags)) {
result = vn_device_memory_pool_suballocate(
dev, mem, pAllocateInfo->memoryTypeIndex);
} else {
diff --git a/src/virtio/vulkan/vn_renderer.h b/src/virtio/vulkan/vn_renderer.h
index e34f14cbef0..5bf4d1217a8 100644
--- a/src/virtio/vulkan/vn_renderer.h
+++ b/src/virtio/vulkan/vn_renderer.h
@@ -56,6 +56,7 @@ struct vn_renderer_info {
bool has_cache_management;
bool has_external_sync;
bool has_implicit_fencing;
+ bool has_guest_vram;
uint32_t max_sync_queue_count;
diff --git a/src/virtio/vulkan/vn_renderer_virtgpu.c b/src/virtio/vulkan/vn_renderer_virtgpu.c
index bf1d5f3b1e8..25ccec4b8af 100644
--- a/src/virtio/vulkan/vn_renderer_virtgpu.c
+++ b/src/virtio/vulkan/vn_renderer_virtgpu.c
@@ -41,6 +41,15 @@ struct drm_virtgpu_context_init {
#define VIRTGPU_PARAM_MAX_SYNC_QUEUE_COUNT 100
#endif /* VIRTGPU_PARAM_MAX_SYNC_QUEUE_COUNT */
+#ifndef VIRTGPU_PARAM_GUEST_VRAM
+/* All guest allocations happen via virtgpu dedicated heap. */
+#define VIRTGPU_PARAM_GUEST_VRAM 9
+#endif
+
+#ifndef VIRTGPU_BLOB_MEM_GUEST_VRAM
+#define VIRTGPU_BLOB_MEM_GUEST_VRAM 0x0004
+#endif
+
/* XXX comment these out to really use kernel uapi */
#define SIMULATE_BO_SIZE_FIX 1
//#define SIMULATE_CONTEXT_INIT 1
@@ -104,6 +113,7 @@ struct virtgpu {
} capset;
uint32_t shmem_blob_mem;
+ uint32_t bo_blob_mem;
/* note that we use gem_handle instead of res_id to index because
* res_id is monotonically increasing by default (see
@@ -1175,8 +1185,8 @@ virtgpu_bo_create_from_dma_buf(struct vn_renderer *renderer,
uint32_t blob_flags;
size_t mmap_size;
if (info.blob_mem) {
- /* must be VIRTGPU_BLOB_MEM_HOST3D */
- if (info.blob_mem != VIRTGPU_BLOB_MEM_HOST3D)
+ /* must be VIRTGPU_BLOB_MEM_HOST3D or VIRTGPU_BLOB_MEM_GUEST_VRAM */
+ if (info.blob_mem != gpu->bo_blob_mem)
goto fail;
/* blob_flags is not passed to the kernel and is only for internal use
@@ -1254,7 +1264,7 @@ virtgpu_bo_create_from_device_memory(
uint32_t res_id;
uint32_t gem_handle = virtgpu_ioctl_resource_create_blob(
- gpu, VIRTGPU_BLOB_MEM_HOST3D, blob_flags, size, mem_id, &res_id);
+ gpu, gpu->bo_blob_mem, blob_flags, size, mem_id, &res_id);
if (!gem_handle)
return VK_ERROR_OUT_OF_DEVICE_MEMORY;
@@ -1398,6 +1408,9 @@ virtgpu_init_renderer_info(struct virtgpu *gpu)
info->vk_mesa_venus_protocol_spec_version =
capset->vk_mesa_venus_protocol_spec_version;
info->supports_blob_id_0 = capset->supports_blob_id_0;
+
+ if (gpu->bo_blob_mem == VIRTGPU_BLOB_MEM_GUEST_VRAM)
+ info->has_guest_vram = true;
}
static void
@@ -1487,8 +1500,8 @@ virtgpu_init_params(struct virtgpu *gpu)
{
const uint64_t required_params[] = {
VIRTGPU_PARAM_3D_FEATURES, VIRTGPU_PARAM_CAPSET_QUERY_FIX,
- VIRTGPU_PARAM_RESOURCE_BLOB, VIRTGPU_PARAM_HOST_VISIBLE,
- VIRTGPU_PARAM_CROSS_DEVICE, VIRTGPU_PARAM_CONTEXT_INIT,
+ VIRTGPU_PARAM_RESOURCE_BLOB, VIRTGPU_PARAM_CROSS_DEVICE,
+ VIRTGPU_PARAM_CONTEXT_INIT,
};
uint64_t val;
for (uint32_t i = 0; i < ARRAY_SIZE(required_params); i++) {
@@ -1502,6 +1515,23 @@ virtgpu_init_params(struct virtgpu *gpu)
}
}
+ val = virtgpu_ioctl_getparam(gpu, VIRTGPU_PARAM_HOST_VISIBLE);
+ if (val) {
+ gpu->bo_blob_mem = VIRTGPU_BLOB_MEM_HOST3D;
+ } else {
+ val = virtgpu_ioctl_getparam(gpu, VIRTGPU_PARAM_GUEST_VRAM);
+ if (val) {
+ gpu->bo_blob_mem = VIRTGPU_BLOB_MEM_GUEST_VRAM;
+ }
+ }
+
+ if (!val) {
+ vn_log(gpu->instance,
+ "one of required kernel params (%d or %d) is missing",
+ (int)VIRTGPU_PARAM_HOST_VISIBLE, (int)VIRTGPU_PARAM_GUEST_VRAM);
+ return VK_ERROR_INITIALIZATION_FAILED;
+ }
+
val = virtgpu_ioctl_getparam(gpu, VIRTGPU_PARAM_MAX_SYNC_QUEUE_COUNT);
if (!val) {
if (VN_DEBUG(INIT))