mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-24 12:09:58 +00:00
virtio-iommu: Set supported page size mask
The virtio-iommu device can deal with arbitrary page sizes for virtual endpoints, but for endpoints assigned with VFIO it must follow the page granule used by the host IOMMU driver. Implement the interface to set the vIOMMU page size mask, called by VFIO for each endpoint. We assume that all host IOMMU drivers use the same page granule (the host page granule). Override the page_size_mask field in the virtio config space. Signed-off-by: Bharat Bhushan <bbhushan2@marvell.com> Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org> Message-Id: <20201030180510.747225-10-jean-philippe@linaro.org> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
b917749842
commit
5c3cfe33f4
@ -109,6 +109,7 @@ virtio_iommu_fill_resv_property(uint32_t devid, uint8_t subtype, uint64_t start,
|
||||
virtio_iommu_notify_map(const char *name, uint64_t virt_start, uint64_t virt_end, uint64_t phys_start, uint32_t flags) "mr=%s virt_start=0x%"PRIx64" virt_end=0x%"PRIx64" phys_start=0x%"PRIx64" flags=%d"
|
||||
virtio_iommu_notify_unmap(const char *name, uint64_t virt_start, uint64_t virt_end) "mr=%s virt_start=0x%"PRIx64" virt_end=0x%"PRIx64
|
||||
virtio_iommu_remap(const char *name, uint64_t virt_start, uint64_t virt_end, uint64_t phys_start) "mr=%s virt_start=0x%"PRIx64" virt_end=0x%"PRIx64" phys_start=0x%"PRIx64
|
||||
virtio_iommu_set_page_size_mask(const char *name, uint64_t old, uint64_t new) "mr=%s old_mask=0x%"PRIx64" new_mask=0x%"PRIx64
|
||||
virtio_iommu_notify_flag_add(const char *name) "add notifier to mr %s"
|
||||
virtio_iommu_notify_flag_del(const char *name) "del notifier from mr %s"
|
||||
|
||||
|
@ -899,6 +899,55 @@ static int virtio_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu_mr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The default mask (TARGET_PAGE_MASK) is the smallest supported guest granule,
|
||||
* for example 0xfffffffffffff000. When an assigned device has page size
|
||||
* restrictions due to the hardware IOMMU configuration, apply this restriction
|
||||
* to the mask.
|
||||
*/
|
||||
static int virtio_iommu_set_page_size_mask(IOMMUMemoryRegion *mr,
|
||||
uint64_t new_mask,
|
||||
Error **errp)
|
||||
{
|
||||
IOMMUDevice *sdev = container_of(mr, IOMMUDevice, iommu_mr);
|
||||
VirtIOIOMMU *s = sdev->viommu;
|
||||
uint64_t cur_mask = s->config.page_size_mask;
|
||||
|
||||
trace_virtio_iommu_set_page_size_mask(mr->parent_obj.name, cur_mask,
|
||||
new_mask);
|
||||
|
||||
if ((cur_mask & new_mask) == 0) {
|
||||
error_setg(errp, "virtio-iommu page mask 0x%"PRIx64
|
||||
" is incompatible with mask 0x%"PRIx64, cur_mask, new_mask);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* After the machine is finalized, we can't change the mask anymore. If by
|
||||
* chance the hotplugged device supports the same granule, we can still
|
||||
* accept it. Having a different masks is possible but the guest will use
|
||||
* sub-optimal block sizes, so warn about it.
|
||||
*/
|
||||
if (qdev_hotplug) {
|
||||
int new_granule = ctz64(new_mask);
|
||||
int cur_granule = ctz64(cur_mask);
|
||||
|
||||
if (new_granule != cur_granule) {
|
||||
error_setg(errp, "virtio-iommu page mask 0x%"PRIx64
|
||||
" is incompatible with mask 0x%"PRIx64, cur_mask,
|
||||
new_mask);
|
||||
return -1;
|
||||
} else if (new_mask != cur_mask) {
|
||||
warn_report("virtio-iommu page mask 0x%"PRIx64
|
||||
" does not match 0x%"PRIx64, cur_mask, new_mask);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->config.page_size_mask &= new_mask;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void virtio_iommu_device_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
||||
@ -1130,6 +1179,7 @@ static void virtio_iommu_memory_region_class_init(ObjectClass *klass,
|
||||
imrc->translate = virtio_iommu_translate;
|
||||
imrc->replay = virtio_iommu_replay;
|
||||
imrc->notify_flag_changed = virtio_iommu_notify_flag_changed;
|
||||
imrc->iommu_set_page_size_mask = virtio_iommu_set_page_size_mask;
|
||||
}
|
||||
|
||||
static const TypeInfo virtio_iommu_info = {
|
||||
|
Loading…
Reference in New Issue
Block a user