mirror of https://github.com/xemu-project/xemu.git
virtio-iommu: Support bypass domain
The driver can create a bypass domain by passing the VIRTIO_IOMMU_ATTACH_F_BYPASS flag on the ATTACH request. Bypass domains perform slightly better than domains with identity mappings since they skip translation. Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Message-Id: <20220214124356.872985-4-jean-philippe@linaro.org> Acked-by: Cornelia Huck <cohuck@redhat.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Tested-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
448179e33e
commit
d9c96f2425
|
@ -43,6 +43,7 @@
|
|||
|
||||
typedef struct VirtIOIOMMUDomain {
|
||||
uint32_t id;
|
||||
bool bypass;
|
||||
GTree *mappings;
|
||||
QLIST_HEAD(, VirtIOIOMMUEndpoint) endpoint_list;
|
||||
} VirtIOIOMMUDomain;
|
||||
|
@ -258,12 +259,16 @@ static void virtio_iommu_put_endpoint(gpointer data)
|
|||
}
|
||||
|
||||
static VirtIOIOMMUDomain *virtio_iommu_get_domain(VirtIOIOMMU *s,
|
||||
uint32_t domain_id)
|
||||
uint32_t domain_id,
|
||||
bool bypass)
|
||||
{
|
||||
VirtIOIOMMUDomain *domain;
|
||||
|
||||
domain = g_tree_lookup(s->domains, GUINT_TO_POINTER(domain_id));
|
||||
if (domain) {
|
||||
if (domain->bypass != bypass) {
|
||||
return NULL;
|
||||
}
|
||||
return domain;
|
||||
}
|
||||
domain = g_malloc0(sizeof(*domain));
|
||||
|
@ -271,6 +276,7 @@ static VirtIOIOMMUDomain *virtio_iommu_get_domain(VirtIOIOMMU *s,
|
|||
domain->mappings = g_tree_new_full((GCompareDataFunc)interval_cmp,
|
||||
NULL, (GDestroyNotify)g_free,
|
||||
(GDestroyNotify)g_free);
|
||||
domain->bypass = bypass;
|
||||
g_tree_insert(s->domains, GUINT_TO_POINTER(domain_id), domain);
|
||||
QLIST_INIT(&domain->endpoint_list);
|
||||
trace_virtio_iommu_get_domain(domain_id);
|
||||
|
@ -334,11 +340,16 @@ static int virtio_iommu_attach(VirtIOIOMMU *s,
|
|||
{
|
||||
uint32_t domain_id = le32_to_cpu(req->domain);
|
||||
uint32_t ep_id = le32_to_cpu(req->endpoint);
|
||||
uint32_t flags = le32_to_cpu(req->flags);
|
||||
VirtIOIOMMUDomain *domain;
|
||||
VirtIOIOMMUEndpoint *ep;
|
||||
|
||||
trace_virtio_iommu_attach(domain_id, ep_id);
|
||||
|
||||
if (flags & ~VIRTIO_IOMMU_ATTACH_F_BYPASS) {
|
||||
return VIRTIO_IOMMU_S_INVAL;
|
||||
}
|
||||
|
||||
ep = virtio_iommu_get_endpoint(s, ep_id);
|
||||
if (!ep) {
|
||||
return VIRTIO_IOMMU_S_NOENT;
|
||||
|
@ -356,7 +367,12 @@ static int virtio_iommu_attach(VirtIOIOMMU *s,
|
|||
}
|
||||
}
|
||||
|
||||
domain = virtio_iommu_get_domain(s, domain_id);
|
||||
domain = virtio_iommu_get_domain(s, domain_id,
|
||||
flags & VIRTIO_IOMMU_ATTACH_F_BYPASS);
|
||||
if (!domain) {
|
||||
/* Incompatible bypass flag */
|
||||
return VIRTIO_IOMMU_S_INVAL;
|
||||
}
|
||||
QLIST_INSERT_HEAD(&domain->endpoint_list, ep, next);
|
||||
|
||||
ep->domain = domain;
|
||||
|
@ -419,6 +435,10 @@ static int virtio_iommu_map(VirtIOIOMMU *s,
|
|||
return VIRTIO_IOMMU_S_NOENT;
|
||||
}
|
||||
|
||||
if (domain->bypass) {
|
||||
return VIRTIO_IOMMU_S_INVAL;
|
||||
}
|
||||
|
||||
interval = g_malloc0(sizeof(*interval));
|
||||
|
||||
interval->low = virt_start;
|
||||
|
@ -464,6 +484,11 @@ static int virtio_iommu_unmap(VirtIOIOMMU *s,
|
|||
if (!domain) {
|
||||
return VIRTIO_IOMMU_S_NOENT;
|
||||
}
|
||||
|
||||
if (domain->bypass) {
|
||||
return VIRTIO_IOMMU_S_INVAL;
|
||||
}
|
||||
|
||||
interval.low = virt_start;
|
||||
interval.high = virt_end;
|
||||
|
||||
|
@ -780,6 +805,9 @@ static IOMMUTLBEntry virtio_iommu_translate(IOMMUMemoryRegion *mr, hwaddr addr,
|
|||
entry.perm = flag;
|
||||
}
|
||||
goto unlock;
|
||||
} else if (ep->domain->bypass) {
|
||||
entry.perm = flag;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
found = g_tree_lookup_extended(ep->domain->mappings, (gpointer)(&interval),
|
||||
|
@ -1139,8 +1167,8 @@ static const VMStateDescription vmstate_endpoint = {
|
|||
|
||||
static const VMStateDescription vmstate_domain = {
|
||||
.name = "domain",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.pre_load = domain_preload,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(id, VirtIOIOMMUDomain),
|
||||
|
@ -1149,6 +1177,7 @@ static const VMStateDescription vmstate_domain = {
|
|||
VirtIOIOMMUInterval, VirtIOIOMMUMapping),
|
||||
VMSTATE_QLIST_V(endpoint_list, VirtIOIOMMUDomain, 1,
|
||||
vmstate_endpoint, VirtIOIOMMUEndpoint, next),
|
||||
VMSTATE_BOOL_V(bypass, VirtIOIOMMUDomain, 2),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
@ -1186,7 +1215,7 @@ static const VMStateDescription vmstate_virtio_iommu_device = {
|
|||
.version_id = 2,
|
||||
.post_load = iommu_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_GTREE_DIRECT_KEY_V(domains, VirtIOIOMMU, 1,
|
||||
VMSTATE_GTREE_DIRECT_KEY_V(domains, VirtIOIOMMU, 2,
|
||||
&vmstate_domain, VirtIOIOMMUDomain),
|
||||
VMSTATE_UINT8_V(config.bypass, VirtIOIOMMU, 2),
|
||||
VMSTATE_END_OF_LIST()
|
||||
|
|
Loading…
Reference in New Issue