vfio-user: handle DMA mappings

Define and register callbacks to manage the RAM regions used for
device DMA

Signed-off-by: Elena Ufimtseva <elena.ufimtseva@oracle.com>
Signed-off-by: John G Johnson <john.g.johnson@oracle.com>
Signed-off-by: Jagannathan Raman <jag.raman@oracle.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Message-id: faacbcd45c4d02c591f0dbfdc19041fbb3eae7eb.1655151679.git.jag.raman@oracle.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Jagannathan Raman 2022-06-13 16:26:31 -04:00 committed by Stefan Hajnoczi
parent 253007d147
commit 15ccf9bee7
3 changed files with 62 additions and 0 deletions

View file

@ -22,6 +22,7 @@
#include "hw/remote/iohub.h"
#include "hw/remote/iommu.h"
#include "hw/qdev-core.h"
#include "hw/remote/iommu.h"
static void remote_machine_init(MachineState *machine)
{
@ -51,6 +52,10 @@ static void remote_machine_init(MachineState *machine)
pci_host = PCI_HOST_BRIDGE(rem_host);
if (s->vfio_user) {
remote_iommu_setup(pci_host->bus);
}
remote_iohub_init(&s->iohub);
pci_bus_irqs(pci_host->bus, remote_iohub_set_irq, remote_iohub_map_irq,

View file

@ -7,3 +7,5 @@ mpqemu_recv_io_error(int cmd, int size, int nfds) "failed to receive %d size %d,
vfu_prop(const char *prop, const char *val) "vfu: setting %s as %s"
vfu_cfg_read(uint32_t offset, uint32_t val) "vfu: cfg: 0x%u -> 0x%x"
vfu_cfg_write(uint32_t offset, uint32_t val) "vfu: cfg: 0x%u <- 0x%x"
vfu_dma_register(uint64_t gpa, size_t len) "vfu: registering GPA 0x%"PRIx64", %zu bytes"
vfu_dma_unregister(uint64_t gpa) "vfu: unregistering GPA 0x%"PRIx64""

View file

@ -284,6 +284,54 @@ static ssize_t vfu_object_cfg_access(vfu_ctx_t *vfu_ctx, char * const buf,
return count;
}
static void dma_register(vfu_ctx_t *vfu_ctx, vfu_dma_info_t *info)
{
VfuObject *o = vfu_get_private(vfu_ctx);
AddressSpace *dma_as = NULL;
MemoryRegion *subregion = NULL;
g_autofree char *name = NULL;
struct iovec *iov = &info->iova;
if (!info->vaddr) {
return;
}
name = g_strdup_printf("mem-%s-%"PRIx64"", o->device,
(uint64_t)info->vaddr);
subregion = g_new0(MemoryRegion, 1);
memory_region_init_ram_ptr(subregion, NULL, name,
iov->iov_len, info->vaddr);
dma_as = pci_device_iommu_address_space(o->pci_dev);
memory_region_add_subregion(dma_as->root, (hwaddr)iov->iov_base, subregion);
trace_vfu_dma_register((uint64_t)iov->iov_base, iov->iov_len);
}
static void dma_unregister(vfu_ctx_t *vfu_ctx, vfu_dma_info_t *info)
{
VfuObject *o = vfu_get_private(vfu_ctx);
AddressSpace *dma_as = NULL;
MemoryRegion *mr = NULL;
ram_addr_t offset;
mr = memory_region_from_host(info->vaddr, &offset);
if (!mr) {
return;
}
dma_as = pci_device_iommu_address_space(o->pci_dev);
memory_region_del_subregion(dma_as->root, mr);
object_unparent((OBJECT(mr)));
trace_vfu_dma_unregister((uint64_t)info->iova.iov_base);
}
/*
* TYPE_VFU_OBJECT depends on the availability of the 'socket' and 'device'
* properties. It also depends on devices instantiated in QEMU. These
@ -387,6 +435,13 @@ static void vfu_object_init_ctx(VfuObject *o, Error **errp)
goto fail;
}
ret = vfu_setup_device_dma(o->vfu_ctx, &dma_register, &dma_unregister);
if (ret < 0) {
error_setg(errp, "vfu: Failed to setup DMA handlers for %s",
o->device);
goto fail;
}
ret = vfu_realize_ctx(o->vfu_ctx);
if (ret < 0) {
error_setg(errp, "vfu: Failed to realize device %s- %s",