mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
kvm: Force IOMMU remapping on memory slot read-only flag changes
Memory slot flags can be altered without changing other parameters of the slot. The read-only attribute is the only one the IOMMU cares about, so generate an un-map, re-map when this occurs. This also avoid unnecessarily re-mapping the slot when no IOMMU visible changes are made. Reviewed-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com> Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Gleb Natapov <gleb@redhat.com>
This commit is contained in:
parent
3f0c3d0bb2
commit
261874b0d5
@ -731,6 +731,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
|
||||
struct kvm_memory_slot *slot;
|
||||
struct kvm_memory_slot old, new;
|
||||
struct kvm_memslots *slots = NULL, *old_memslots;
|
||||
bool old_iommu_mapped;
|
||||
|
||||
r = check_memory_region_flags(mem);
|
||||
if (r)
|
||||
@ -772,6 +773,8 @@ int __kvm_set_memory_region(struct kvm *kvm,
|
||||
new.npages = npages;
|
||||
new.flags = mem->flags;
|
||||
|
||||
old_iommu_mapped = old.npages;
|
||||
|
||||
/*
|
||||
* Disallow changing a memory slot's size or changing anything about
|
||||
* zero sized slots that doesn't involve making them non-zero.
|
||||
@ -835,6 +838,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
|
||||
|
||||
/* slot was deleted or moved, clear iommu mapping */
|
||||
kvm_iommu_unmap_pages(kvm, &old);
|
||||
old_iommu_mapped = false;
|
||||
/* From this point no new shadow pages pointing to a deleted,
|
||||
* or moved, memslot will be created.
|
||||
*
|
||||
@ -863,11 +867,27 @@ int __kvm_set_memory_region(struct kvm *kvm,
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
/* map new memory slot into the iommu */
|
||||
/*
|
||||
* IOMMU mapping: New slots need to be mapped. Old slots need to be
|
||||
* un-mapped and re-mapped if their base changes or if flags that the
|
||||
* iommu cares about change (read-only). Base change unmapping is
|
||||
* handled above with slot deletion, so we only unmap incompatible
|
||||
* flags here. Anything else the iommu might care about for existing
|
||||
* slots (size changes, userspace addr changes) is disallowed above,
|
||||
* so any other attribute changes getting here can be skipped.
|
||||
*/
|
||||
if (npages) {
|
||||
r = kvm_iommu_map_pages(kvm, &new);
|
||||
if (r)
|
||||
goto out_slots;
|
||||
if (old_iommu_mapped &&
|
||||
((new.flags ^ old.flags) & KVM_MEM_READONLY)) {
|
||||
kvm_iommu_unmap_pages(kvm, &old);
|
||||
old_iommu_mapped = false;
|
||||
}
|
||||
|
||||
if (!old_iommu_mapped) {
|
||||
r = kvm_iommu_map_pages(kvm, &new);
|
||||
if (r)
|
||||
goto out_slots;
|
||||
}
|
||||
}
|
||||
|
||||
/* actual memory is freed via old in kvm_free_physmem_slot below */
|
||||
|
Loading…
Reference in New Issue
Block a user