virtio-iommu: Support migration
Add Migration support. We rely on recently added gtree and qlist migration. We only migrate the domain gtree. The endpoint gtree is re-constructed in a post-load operation. Signed-off-by: Eric Auger <eric.auger@redhat.com> Acked-by: Peter Xu <peterx@redhat.com> Reviewed-by: Juan Quintela <quintela@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Message-Id: <20200214132745.23392-8-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
a7c1da8adc
commit
bd0ab8702f
|
@ -643,16 +643,6 @@ static uint64_t virtio_iommu_get_features(VirtIODevice *vdev, uint64_t f,
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Migration is not yet supported: most of the state consists
|
|
||||||
* of balanced binary trees which are not yet ready for getting
|
|
||||||
* migrated
|
|
||||||
*/
|
|
||||||
static const VMStateDescription vmstate_virtio_iommu_device = {
|
|
||||||
.name = "virtio-iommu-device",
|
|
||||||
.unmigratable = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data)
|
static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data)
|
||||||
{
|
{
|
||||||
guint ua = GPOINTER_TO_UINT(a);
|
guint ua = GPOINTER_TO_UINT(a);
|
||||||
|
@ -736,9 +726,108 @@ static void virtio_iommu_instance_init(Object *obj)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VMSTATE_INTERVAL \
|
||||||
|
{ \
|
||||||
|
.name = "interval", \
|
||||||
|
.version_id = 1, \
|
||||||
|
.minimum_version_id = 1, \
|
||||||
|
.fields = (VMStateField[]) { \
|
||||||
|
VMSTATE_UINT64(low, VirtIOIOMMUInterval), \
|
||||||
|
VMSTATE_UINT64(high, VirtIOIOMMUInterval), \
|
||||||
|
VMSTATE_END_OF_LIST() \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VMSTATE_MAPPING \
|
||||||
|
{ \
|
||||||
|
.name = "mapping", \
|
||||||
|
.version_id = 1, \
|
||||||
|
.minimum_version_id = 1, \
|
||||||
|
.fields = (VMStateField[]) { \
|
||||||
|
VMSTATE_UINT64(phys_addr, VirtIOIOMMUMapping),\
|
||||||
|
VMSTATE_UINT32(flags, VirtIOIOMMUMapping), \
|
||||||
|
VMSTATE_END_OF_LIST() \
|
||||||
|
}, \
|
||||||
|
}
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_interval_mapping[2] = {
|
||||||
|
VMSTATE_MAPPING, /* value */
|
||||||
|
VMSTATE_INTERVAL /* key */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int domain_preload(void *opaque)
|
||||||
|
{
|
||||||
|
VirtIOIOMMUDomain *domain = opaque;
|
||||||
|
|
||||||
|
domain->mappings = g_tree_new_full((GCompareDataFunc)interval_cmp,
|
||||||
|
NULL, g_free, g_free);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_endpoint = {
|
||||||
|
.name = "endpoint",
|
||||||
|
.version_id = 1,
|
||||||
|
.minimum_version_id = 1,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
VMSTATE_UINT32(id, VirtIOIOMMUEndpoint),
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_domain = {
|
||||||
|
.name = "domain",
|
||||||
|
.version_id = 1,
|
||||||
|
.minimum_version_id = 1,
|
||||||
|
.pre_load = domain_preload,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
VMSTATE_UINT32(id, VirtIOIOMMUDomain),
|
||||||
|
VMSTATE_GTREE_V(mappings, VirtIOIOMMUDomain, 1,
|
||||||
|
vmstate_interval_mapping,
|
||||||
|
VirtIOIOMMUInterval, VirtIOIOMMUMapping),
|
||||||
|
VMSTATE_QLIST_V(endpoint_list, VirtIOIOMMUDomain, 1,
|
||||||
|
vmstate_endpoint, VirtIOIOMMUEndpoint, next),
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static gboolean reconstruct_endpoints(gpointer key, gpointer value,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
VirtIOIOMMU *s = (VirtIOIOMMU *)data;
|
||||||
|
VirtIOIOMMUDomain *d = (VirtIOIOMMUDomain *)value;
|
||||||
|
VirtIOIOMMUEndpoint *iter;
|
||||||
|
|
||||||
|
QLIST_FOREACH(iter, &d->endpoint_list, next) {
|
||||||
|
iter->domain = d;
|
||||||
|
g_tree_insert(s->endpoints, GUINT_TO_POINTER(iter->id), iter);
|
||||||
|
}
|
||||||
|
return false; /* continue the domain traversal */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int iommu_post_load(void *opaque, int version_id)
|
||||||
|
{
|
||||||
|
VirtIOIOMMU *s = opaque;
|
||||||
|
|
||||||
|
g_tree_foreach(s->domains, reconstruct_endpoints, s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_virtio_iommu_device = {
|
||||||
|
.name = "virtio-iommu-device",
|
||||||
|
.minimum_version_id = 1,
|
||||||
|
.version_id = 1,
|
||||||
|
.post_load = iommu_post_load,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
VMSTATE_GTREE_DIRECT_KEY_V(domains, VirtIOIOMMU, 1,
|
||||||
|
&vmstate_domain, VirtIOIOMMUDomain),
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static const VMStateDescription vmstate_virtio_iommu = {
|
static const VMStateDescription vmstate_virtio_iommu = {
|
||||||
.name = "virtio-iommu",
|
.name = "virtio-iommu",
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
|
.priority = MIG_PRI_IOMMU,
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_VIRTIO_DEVICE,
|
VMSTATE_VIRTIO_DEVICE,
|
||||||
|
|
Loading…
Reference in New Issue