mirror of https://github.com/xemu-project/xemu.git
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:
parent
253007d147
commit
15ccf9bee7
|
@ -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,
|
||||
|
|
|
@ -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""
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue