mirror of https://github.com/xemu-project/xemu.git
memory: Add Error** argument to memory_get_xlat_addr()
Let the callers do the reporting. This will be useful in vfio_iommu_map_dirty_notify(). Cc: Michael S. Tsirkin <mst@redhat.com> Cc: Paolo Bonzini <pbonzini@redhat.com> Cc: David Hildenbrand <david@redhat.com> Reviewed-by: Peter Xu <peterx@redhat.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Avihai Horon <avihaih@nvidia.com> Signed-off-by: Cédric Le Goater <clg@redhat.com>
This commit is contained in:
parent
94d1208840
commit
ebb481c03c
|
@ -253,12 +253,13 @@ static bool vfio_listener_skipped_section(MemoryRegionSection *section)
|
||||||
|
|
||||||
/* Called with rcu_read_lock held. */
|
/* Called with rcu_read_lock held. */
|
||||||
static bool vfio_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr,
|
static bool vfio_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr,
|
||||||
ram_addr_t *ram_addr, bool *read_only)
|
ram_addr_t *ram_addr, bool *read_only,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
bool ret, mr_has_discard_manager;
|
bool ret, mr_has_discard_manager;
|
||||||
|
|
||||||
ret = memory_get_xlat_addr(iotlb, vaddr, ram_addr, read_only,
|
ret = memory_get_xlat_addr(iotlb, vaddr, ram_addr, read_only,
|
||||||
&mr_has_discard_manager);
|
&mr_has_discard_manager, errp);
|
||||||
if (ret && mr_has_discard_manager) {
|
if (ret && mr_has_discard_manager) {
|
||||||
/*
|
/*
|
||||||
* Malicious VMs might trigger discarding of IOMMU-mapped memory. The
|
* Malicious VMs might trigger discarding of IOMMU-mapped memory. The
|
||||||
|
@ -288,6 +289,7 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
|
||||||
hwaddr iova = iotlb->iova + giommu->iommu_offset;
|
hwaddr iova = iotlb->iova + giommu->iommu_offset;
|
||||||
void *vaddr;
|
void *vaddr;
|
||||||
int ret;
|
int ret;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
trace_vfio_iommu_map_notify(iotlb->perm == IOMMU_NONE ? "UNMAP" : "MAP",
|
trace_vfio_iommu_map_notify(iotlb->perm == IOMMU_NONE ? "UNMAP" : "MAP",
|
||||||
iova, iova + iotlb->addr_mask);
|
iova, iova + iotlb->addr_mask);
|
||||||
|
@ -304,7 +306,8 @@ static void vfio_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
|
||||||
if ((iotlb->perm & IOMMU_RW) != IOMMU_NONE) {
|
if ((iotlb->perm & IOMMU_RW) != IOMMU_NONE) {
|
||||||
bool read_only;
|
bool read_only;
|
||||||
|
|
||||||
if (!vfio_get_xlat_addr(iotlb, &vaddr, NULL, &read_only)) {
|
if (!vfio_get_xlat_addr(iotlb, &vaddr, NULL, &read_only, &local_err)) {
|
||||||
|
error_report_err(local_err);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -1213,6 +1216,7 @@ static void vfio_iommu_map_dirty_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
|
||||||
VFIOContainerBase *bcontainer = giommu->bcontainer;
|
VFIOContainerBase *bcontainer = giommu->bcontainer;
|
||||||
hwaddr iova = iotlb->iova + giommu->iommu_offset;
|
hwaddr iova = iotlb->iova + giommu->iommu_offset;
|
||||||
ram_addr_t translated_addr;
|
ram_addr_t translated_addr;
|
||||||
|
Error *local_err = NULL;
|
||||||
int ret = -EINVAL;
|
int ret = -EINVAL;
|
||||||
|
|
||||||
trace_vfio_iommu_map_dirty_notify(iova, iova + iotlb->addr_mask);
|
trace_vfio_iommu_map_dirty_notify(iova, iova + iotlb->addr_mask);
|
||||||
|
@ -1224,7 +1228,8 @@ static void vfio_iommu_map_dirty_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
|
||||||
}
|
}
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
if (!vfio_get_xlat_addr(iotlb, NULL, &translated_addr, NULL)) {
|
if (!vfio_get_xlat_addr(iotlb, NULL, &translated_addr, NULL, &local_err)) {
|
||||||
|
error_report_err(local_err);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -208,6 +208,7 @@ static void vhost_vdpa_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
|
||||||
void *vaddr;
|
void *vaddr;
|
||||||
int ret;
|
int ret;
|
||||||
Int128 llend;
|
Int128 llend;
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
if (iotlb->target_as != &address_space_memory) {
|
if (iotlb->target_as != &address_space_memory) {
|
||||||
error_report("Wrong target AS \"%s\", only system memory is allowed",
|
error_report("Wrong target AS \"%s\", only system memory is allowed",
|
||||||
|
@ -227,7 +228,9 @@ static void vhost_vdpa_iommu_map_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
|
||||||
if ((iotlb->perm & IOMMU_RW) != IOMMU_NONE) {
|
if ((iotlb->perm & IOMMU_RW) != IOMMU_NONE) {
|
||||||
bool read_only;
|
bool read_only;
|
||||||
|
|
||||||
if (!memory_get_xlat_addr(iotlb, &vaddr, NULL, &read_only, NULL)) {
|
if (!memory_get_xlat_addr(iotlb, &vaddr, NULL, &read_only, NULL,
|
||||||
|
&local_err)) {
|
||||||
|
error_report_err(local_err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ret = vhost_vdpa_dma_map(s, VHOST_VDPA_GUEST_PA_ASID, iova,
|
ret = vhost_vdpa_dma_map(s, VHOST_VDPA_GUEST_PA_ASID, iova,
|
||||||
|
|
|
@ -774,9 +774,22 @@ void ram_discard_manager_register_listener(RamDiscardManager *rdm,
|
||||||
void ram_discard_manager_unregister_listener(RamDiscardManager *rdm,
|
void ram_discard_manager_unregister_listener(RamDiscardManager *rdm,
|
||||||
RamDiscardListener *rdl);
|
RamDiscardListener *rdl);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* memory_get_xlat_addr: Extract addresses from a TLB entry
|
||||||
|
*
|
||||||
|
* @iotlb: pointer to an #IOMMUTLBEntry
|
||||||
|
* @vaddr: virtual address
|
||||||
|
* @ram_addr: RAM address
|
||||||
|
* @read_only: indicates if writes are allowed
|
||||||
|
* @mr_has_discard_manager: indicates memory is controlled by a
|
||||||
|
* RamDiscardManager
|
||||||
|
* @errp: pointer to Error*, to store an error if it happens.
|
||||||
|
*
|
||||||
|
* Return: true on success, else false setting @errp with error.
|
||||||
|
*/
|
||||||
bool memory_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr,
|
bool memory_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr,
|
||||||
ram_addr_t *ram_addr, bool *read_only,
|
ram_addr_t *ram_addr, bool *read_only,
|
||||||
bool *mr_has_discard_manager);
|
bool *mr_has_discard_manager, Error **errp);
|
||||||
|
|
||||||
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
|
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
|
||||||
typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
|
typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
|
||||||
|
|
|
@ -2179,7 +2179,7 @@ void ram_discard_manager_unregister_listener(RamDiscardManager *rdm,
|
||||||
/* Called with rcu_read_lock held. */
|
/* Called with rcu_read_lock held. */
|
||||||
bool memory_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr,
|
bool memory_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr,
|
||||||
ram_addr_t *ram_addr, bool *read_only,
|
ram_addr_t *ram_addr, bool *read_only,
|
||||||
bool *mr_has_discard_manager)
|
bool *mr_has_discard_manager, Error **errp)
|
||||||
{
|
{
|
||||||
MemoryRegion *mr;
|
MemoryRegion *mr;
|
||||||
hwaddr xlat;
|
hwaddr xlat;
|
||||||
|
@ -2197,7 +2197,7 @@ bool memory_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr,
|
||||||
mr = address_space_translate(&address_space_memory, iotlb->translated_addr,
|
mr = address_space_translate(&address_space_memory, iotlb->translated_addr,
|
||||||
&xlat, &len, writable, MEMTXATTRS_UNSPECIFIED);
|
&xlat, &len, writable, MEMTXATTRS_UNSPECIFIED);
|
||||||
if (!memory_region_is_ram(mr)) {
|
if (!memory_region_is_ram(mr)) {
|
||||||
error_report("iommu map to non memory area %" HWADDR_PRIx "", xlat);
|
error_setg(errp, "iommu map to non memory area %" HWADDR_PRIx "", xlat);
|
||||||
return false;
|
return false;
|
||||||
} else if (memory_region_has_ram_discard_manager(mr)) {
|
} else if (memory_region_has_ram_discard_manager(mr)) {
|
||||||
RamDiscardManager *rdm = memory_region_get_ram_discard_manager(mr);
|
RamDiscardManager *rdm = memory_region_get_ram_discard_manager(mr);
|
||||||
|
@ -2216,8 +2216,8 @@ bool memory_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr,
|
||||||
* were already restored before IOMMUs are restored.
|
* were already restored before IOMMUs are restored.
|
||||||
*/
|
*/
|
||||||
if (!ram_discard_manager_is_populated(rdm, &tmp)) {
|
if (!ram_discard_manager_is_populated(rdm, &tmp)) {
|
||||||
error_report("iommu map to discarded memory (e.g., unplugged via"
|
error_setg(errp, "iommu map to discarded memory (e.g., unplugged"
|
||||||
" virtio-mem): %" HWADDR_PRIx "",
|
" via virtio-mem): %" HWADDR_PRIx "",
|
||||||
iotlb->translated_addr);
|
iotlb->translated_addr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2228,7 +2228,7 @@ bool memory_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr,
|
||||||
* check that it did not truncate too much.
|
* check that it did not truncate too much.
|
||||||
*/
|
*/
|
||||||
if (len & iotlb->addr_mask) {
|
if (len & iotlb->addr_mask) {
|
||||||
error_report("iommu has granularity incompatible with target AS");
|
error_setg(errp, "iommu has granularity incompatible with target AS");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue