nvk/nvkmd: Add memory and virtual address interfaces

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30033>
This commit is contained in:
Faith Ekstrand
2024-07-02 11:23:24 -05:00
committed by Marge Bot
parent 4323d2ac54
commit 0b93c42ba1
2 changed files with 284 additions and 0 deletions
+41
View File
@@ -15,3 +15,44 @@ nvkmd_try_create_pdev_for_drm(struct _drmDevice *drm_device,
return nvkmd_nouveau_try_create_pdev(drm_device, log_obj,
debug_flags, pdev_out);
}
VkResult
nvkmd_dev_alloc_mapped_mem(struct nvkmd_dev *dev,
struct vk_object_base *log_obj,
uint64_t size_B, uint64_t align_B,
enum nvkmd_mem_flags flags,
enum nvkmd_mem_map_flags map_flags,
struct nvkmd_mem **mem_out)
{
struct nvkmd_mem *mem;
VkResult result;
result = nvkmd_dev_alloc_mem(dev, log_obj, size_B, align_B,
flags | NVKMD_MEM_CAN_MAP, &mem);
if (result != VK_SUCCESS)
return result;
assert(!(map_flags & NVKMD_MEM_MAP_FIXED));
result = mem->ops->map(mem, log_obj, map_flags, NULL);
if (result != VK_SUCCESS) {
mem->ops->free(mem);
return result;
}
*mem_out = mem;
return VK_SUCCESS;
}
void
nvkmd_mem_unref(struct nvkmd_mem *mem)
{
assert(p_atomic_read(&mem->refcnt) > 0);
if (!p_atomic_dec_zero(&mem->refcnt))
return;
if (mem->map != NULL)
mem->ops->unmap(mem);
mem->ops->free(mem);
}
+243
View File
@@ -6,6 +6,8 @@
#define NVKMD_H 1
#include "nv_device_info.h"
#include "util/u_atomic.h"
#include "vulkan/vulkan_core.h"
#include "nouveau_device.h"
@@ -27,11 +29,38 @@ struct vk_object_base;
* Enums
*/
enum nvkmd_mem_flags {
/** VRAM on discrete GPUs or GART on integrated */
NVKMD_MEM_LOCAL = 1 << 0,
NVKMD_MEM_GART = 1 << 1,
NVKMD_MEM_CAN_MAP = 1 << 2,
NVKMD_MEM_NO_SHARE = 1 << 3,
};
enum nvkmd_mem_map_flags {
NVKMD_MEM_MAP_RD = 1 << 0,
NVKMD_MEM_MAP_WR = 1 << 1,
NVKMD_MEM_MAP_RDWR = NVKMD_MEM_MAP_RD | NVKMD_MEM_MAP_WR,
NVKMD_MEM_MAP_FIXED = 1 << 2,
};
enum nvkmd_va_flags {
/** This VA should be configured for sparse (soft faults) */
NVKMD_VA_SPARSE = 1 << 0,
/** This VA should come from the capture/replay pool */
NVKMD_VA_REPLAY = 1 << 1,
/** Attempt to place this VA at the requested address and fail otherwise */
NVKMD_VA_ALLOC_FIXED = 1 << 2,
};
/*
* Structs
*/
struct nvkmd_info {
bool has_dma_buf;
bool has_get_vram_used;
bool has_alloc_tiled;
bool has_map_fixed;
@@ -70,12 +99,89 @@ struct nvkmd_dev_ops {
uint64_t (*get_gpu_timestamp)(struct nvkmd_dev *dev);
int (*get_drm_fd)(struct nvkmd_dev *dev);
VkResult (*alloc_mem)(struct nvkmd_dev *dev,
struct vk_object_base *log_obj,
uint64_t size_B, uint64_t align_B,
enum nvkmd_mem_flags flags,
struct nvkmd_mem **mem_out);
VkResult (*alloc_tiled_mem)(struct nvkmd_dev *dev,
struct vk_object_base *log_obj,
uint64_t size_B, uint64_t align_B,
uint8_t pte_kind, uint16_t tile_mode,
enum nvkmd_mem_flags flags,
struct nvkmd_mem **mem_out);
VkResult (*import_dma_buf)(struct nvkmd_dev *dev,
struct vk_object_base *log_obj,
int fd, struct nvkmd_mem **mem_out);
VkResult (*alloc_va)(struct nvkmd_dev *dev,
struct vk_object_base *log_obj,
enum nvkmd_va_flags flags, uint8_t pte_kind,
uint64_t size_B, uint64_t align_B,
uint64_t fixed_addr, struct nvkmd_va **va_out);
};
struct nvkmd_dev {
const struct nvkmd_dev_ops *ops;
};
struct nvkmd_mem_ops {
void (*free)(struct nvkmd_mem *mem);
VkResult (*map)(struct nvkmd_mem *mem,
struct vk_object_base *log_obj,
enum nvkmd_mem_map_flags flags,
void *fixed_addr);
void (*unmap)(struct nvkmd_mem *mem);
VkResult (*overmap)(struct nvkmd_mem *mem,
struct vk_object_base *log_obj);
VkResult (*export_dma_buf)(struct nvkmd_mem *mem,
struct vk_object_base *log_obj,
int *fd_out);
};
struct nvkmd_mem {
const struct nvkmd_mem_ops *ops;
uint32_t refcnt;
enum nvkmd_mem_flags flags;
uint64_t size_B;
const struct nvkmd_va *va;
void *map;
};
struct nvkmd_va_ops {
void (*free)(struct nvkmd_va *va);
VkResult (*bind_mem)(struct nvkmd_va *va,
struct vk_object_base *log_obj,
uint64_t va_offset_B,
struct nvkmd_mem *mem,
uint64_t mem_offset_B,
uint64_t range_B);
VkResult (*unbind)(struct nvkmd_va *va,
struct vk_object_base *log_obj,
uint64_t va_offset_B,
uint64_t range_B);
};
struct nvkmd_va {
const struct nvkmd_va_ops *ops;
enum nvkmd_va_flags flags;
uint8_t pte_kind;
uint64_t addr;
uint64_t size_B;
};
/*
* Macros
*
@@ -155,4 +261,141 @@ nvkmd_dev_get_drm_fd(struct nvkmd_dev *dev)
return dev->ops->get_drm_fd(dev);
}
static inline VkResult MUST_CHECK
nvkmd_dev_alloc_mem(struct nvkmd_dev *dev,
struct vk_object_base *log_obj,
uint64_t size_B, uint64_t align_B,
enum nvkmd_mem_flags flags,
struct nvkmd_mem **mem_out)
{
return dev->ops->alloc_mem(dev, log_obj, size_B, align_B, flags, mem_out);
}
static inline VkResult MUST_CHECK
nvkmd_dev_alloc_tiled_mem(struct nvkmd_dev *dev,
struct vk_object_base *log_obj,
uint64_t size_B, uint64_t align_B,
uint8_t pte_kind, uint16_t tile_mode,
enum nvkmd_mem_flags flags,
struct nvkmd_mem **mem_out)
{
return dev->ops->alloc_tiled_mem(dev, log_obj, size_B, align_B,
pte_kind, tile_mode, flags, mem_out);
}
/* Implies NVKMD_MEM_CAN_MAP */
VkResult MUST_CHECK
nvkmd_dev_alloc_mapped_mem(struct nvkmd_dev *dev,
struct vk_object_base *log_obj,
uint64_t size_B, uint64_t align_B,
enum nvkmd_mem_flags flags,
enum nvkmd_mem_map_flags map_flags,
struct nvkmd_mem **mem_out);
static inline VkResult MUST_CHECK
nvkmd_dev_import_dma_buf(struct nvkmd_dev *dev,
struct vk_object_base *log_obj,
int fd, struct nvkmd_mem **mem_out)
{
return dev->ops->import_dma_buf(dev, log_obj, fd, mem_out);
}
static inline VkResult MUST_CHECK
nvkmd_dev_alloc_va(struct nvkmd_dev *dev,
struct vk_object_base *log_obj,
enum nvkmd_va_flags flags, uint8_t pte_kind,
uint64_t size_B, uint64_t align_B,
uint64_t fixed_addr, struct nvkmd_va **va_out)
{
return dev->ops->alloc_va(dev, log_obj, flags, pte_kind, size_B, align_B,
fixed_addr, va_out);
}
static inline struct nvkmd_mem *
nvkmd_mem_ref(struct nvkmd_mem *mem)
{
p_atomic_inc(&mem->refcnt);
return mem;
}
void nvkmd_mem_unref(struct nvkmd_mem *mem);
static inline VkResult MUST_CHECK
nvkmd_mem_map(struct nvkmd_mem *mem, struct vk_object_base *log_obj,
enum nvkmd_mem_map_flags flags, void *fixed_addr,
void **map_out)
{
assert(mem->map == NULL);
VkResult result = mem->ops->map(mem, log_obj, flags, fixed_addr);
if (result != VK_SUCCESS)
return result;
*map_out = mem->map;
return VK_SUCCESS;
}
static inline void
nvkmd_mem_unmap(struct nvkmd_mem *mem)
{
assert(mem->map != NULL);
mem->ops->unmap(mem);
assert(mem->map == NULL);
}
static inline VkResult MUST_CHECK
nvkmd_mem_overmap(struct nvkmd_mem *mem, struct vk_object_base *log_obj)
{
assert(mem->map != NULL);
VkResult result = mem->ops->overmap(mem, log_obj);
assert(mem->map == NULL);
return result;
}
static inline VkResult MUST_CHECK
nvkmd_mem_export_dma_buf(struct nvkmd_mem *mem,
struct vk_object_base *log_obj,
int *fd_out)
{
assert(!(mem->flags & NVKMD_MEM_NO_SHARE));
return mem->ops->export_dma_buf(mem, log_obj, fd_out);
}
static inline void
nvkmd_va_free(struct nvkmd_va *va)
{
va->ops->free(va);
}
static inline VkResult MUST_CHECK
nvkmd_va_bind_mem(struct nvkmd_va *va,
struct vk_object_base *log_obj,
uint64_t va_offset_B,
struct nvkmd_mem *mem,
uint64_t mem_offset_B,
uint64_t range_B)
{
assert(va_offset_B <= va->size_B);
assert(va_offset_B + range_B <= va->size_B);
assert(mem_offset_B <= mem->size_B);
assert(mem_offset_B + range_B <= mem->size_B);
return va->ops->bind_mem(va, log_obj, va_offset_B,
mem, mem_offset_B, range_B);
}
static inline VkResult MUST_CHECK
nvkmd_va_unbind(struct nvkmd_va *va,
struct vk_object_base *log_obj,
uint64_t va_offset_B,
uint64_t range_B)
{
assert(va_offset_B <= va->size_B);
assert(va_offset_B + range_B <= va->size_B);
return va->ops->unbind(va, log_obj, va_offset_B, range_B);
}
#endif /* NVKMD_H */