#include "qemu/error-report.h"
#include "qemu/units.h"
#include "monitor/monitor.h"
+#include "system/ramblock.h"
#include "vfio-helpers.h"
/*
region->mmaps[index].mmap = NULL;
}
+static bool vfio_region_create_dma_buf(VFIORegion *region, Error **errp)
+{
+ g_autofree struct vfio_device_feature *feature = NULL;
+ VFIODevice *vbasedev = region->vbasedev;
+ struct vfio_device_feature_dma_buf *dma_buf;
+ size_t total_size;
+ int i, ret;
+
+ total_size = sizeof(*feature) + sizeof(*dma_buf) +
+ sizeof(struct vfio_region_dma_range) * region->nr_mmaps;
+ feature = g_malloc0(total_size);
+ *feature = (struct vfio_device_feature) {
+ .argsz = total_size,
+ .flags = VFIO_DEVICE_FEATURE_GET | VFIO_DEVICE_FEATURE_DMA_BUF,
+ };
+
+ dma_buf = (void *)feature->data;
+ *dma_buf = (struct vfio_device_feature_dma_buf) {
+ .region_index = region->nr,
+ .open_flags = O_RDWR,
+ .nr_ranges = region->nr_mmaps,
+ };
+
+ for (i = 0; i < region->nr_mmaps; i++) {
+ dma_buf->dma_ranges[i].offset = region->mmaps[i].offset;
+ dma_buf->dma_ranges[i].length = region->mmaps[i].size;
+ }
+
+ ret = vfio_device_get_feature(vbasedev, feature);
+ if (ret < 0) {
+ if (ret == -ENOTTY) {
+ warn_report_once("VFIO dma-buf not supported in kernel: "
+ "PCI BAR IOMMU mappings may fail");
+ return true;
+ }
+ /* P2P DMA or exposing device memory use cases are not supported. */
+ error_setg_errno(errp, -ret, "%s: failed to create dma-buf: "
+ "PCI BAR IOMMU mappings may fail",
+ memory_region_name(region->mem));
+ return false;
+ }
+
+ /* Assign the dmabuf fd to associated RAMBlock */
+ for (i = 0; i < region->nr_mmaps; i++) {
+ MemoryRegion *mr = ®ion->mmaps[i].mem;
+ RAMBlock *ram_block = mr->ram_block;
+
+ ram_block->fd = ret;
+ ram_block->fd_offset = region->mmaps[i].offset;
+ trace_vfio_region_dmabuf(region->vbasedev->name, ret, region->nr,
+ memory_region_name(region->mem),
+ region->mmaps[i].offset,
+ region->mmaps[i].size);
+ }
+ return true;
+}
+
int vfio_region_mmap(VFIORegion *region)
{
int i, ret, prot = 0;
+ Error *local_err = NULL;
char *name;
int fd;
- if (!region->mem) {
+ if (!region->mem || !region->nr_mmaps) {
return 0;
}
region->mmaps[i].size - 1);
}
+ if (!vfio_region_create_dma_buf(region, &local_err)) {
+ error_report_err(local_err);
+ }
+
return 0;
no_mmap:
vfio_region_write(const char *name, int index, uint64_t addr, uint64_t data, unsigned size) " (%s:region%d+0x%"PRIx64", 0x%"PRIx64 ", %d)"
vfio_region_read(char *name, int index, uint64_t addr, unsigned size, uint64_t data) " (%s:region%d+0x%"PRIx64", %d) = 0x%"PRIx64
vfio_region_setup(const char *dev, int index, const char *name, unsigned long flags, unsigned long offset, unsigned long size) "Device %s, region %d \"%s\", flags: 0x%lx, offset: 0x%lx, size: 0x%lx"
+vfio_region_dmabuf(const char *dev, int fd, int index, const char *name, unsigned long offset, unsigned long size) "Device %s, dmabuf fd %d region %d \"%s\", offset: 0x%lx, size: 0x%lx"
vfio_region_mmap_fault(const char *name, int index, unsigned long offset, unsigned long size, int fault) "Region %s mmaps[%d], [0x%lx - 0x%lx], fault: %d"
vfio_region_mmap(const char *name, unsigned long offset, unsigned long end) "Region %s [0x%lx - 0x%lx]"
vfio_region_exit(const char *name, int index) "Device %s, region %d"