Skip to content

Commit cf47f50

Browse files
Sean Christophersonbonzini
authored andcommitted
KVM: Move setting of memslot into helper routine
Split out the core functionality of setting a memslot into a separate helper in preparation for moving memslot deletion into its own routine. Tested-by: Christoffer Dall <christoffer.dall@arm.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Peter Xu <peterx@redhat.com> Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 71a4c30 commit cf47f50

File tree

1 file changed

+63
-43
lines changed

1 file changed

+63
-43
lines changed

virt/kvm/kvm_main.c

Lines changed: 63 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,66 @@ static struct kvm_memslots *install_new_memslots(struct kvm *kvm,
983983
return old_memslots;
984984
}
985985

986+
static int kvm_set_memslot(struct kvm *kvm,
987+
const struct kvm_userspace_memory_region *mem,
988+
const struct kvm_memory_slot *old,
989+
struct kvm_memory_slot *new, int as_id,
990+
enum kvm_mr_change change)
991+
{
992+
struct kvm_memory_slot *slot;
993+
struct kvm_memslots *slots;
994+
int r;
995+
996+
slots = kvzalloc(sizeof(struct kvm_memslots), GFP_KERNEL_ACCOUNT);
997+
if (!slots)
998+
return -ENOMEM;
999+
memcpy(slots, __kvm_memslots(kvm, as_id), sizeof(struct kvm_memslots));
1000+
1001+
if (change == KVM_MR_DELETE || change == KVM_MR_MOVE) {
1002+
/*
1003+
* Note, the INVALID flag needs to be in the appropriate entry
1004+
* in the freshly allocated memslots, not in @old or @new.
1005+
*/
1006+
slot = id_to_memslot(slots, old->id);
1007+
slot->flags |= KVM_MEMSLOT_INVALID;
1008+
1009+
/*
1010+
* We can re-use the old memslots, the only difference from the
1011+
* newly installed memslots is the invalid flag, which will get
1012+
* dropped by update_memslots anyway. We'll also revert to the
1013+
* old memslots if preparing the new memory region fails.
1014+
*/
1015+
slots = install_new_memslots(kvm, as_id, slots);
1016+
1017+
/* From this point no new shadow pages pointing to a deleted,
1018+
* or moved, memslot will be created.
1019+
*
1020+
* validation of sp->gfn happens in:
1021+
* - gfn_to_hva (kvm_read_guest, gfn_to_pfn)
1022+
* - kvm_is_visible_gfn (mmu_check_root)
1023+
*/
1024+
kvm_arch_flush_shadow_memslot(kvm, slot);
1025+
}
1026+
1027+
r = kvm_arch_prepare_memory_region(kvm, new, mem, change);
1028+
if (r)
1029+
goto out_slots;
1030+
1031+
update_memslots(slots, new, change);
1032+
slots = install_new_memslots(kvm, as_id, slots);
1033+
1034+
kvm_arch_commit_memory_region(kvm, mem, old, new, change);
1035+
1036+
kvfree(slots);
1037+
return 0;
1038+
1039+
out_slots:
1040+
if (change == KVM_MR_DELETE || change == KVM_MR_MOVE)
1041+
slots = install_new_memslots(kvm, as_id, slots);
1042+
kvfree(slots);
1043+
return r;
1044+
}
1045+
9861046
/*
9871047
* Allocate some memory and give it an address in the guest physical address
9881048
* space.
@@ -999,7 +1059,6 @@ int __kvm_set_memory_region(struct kvm *kvm,
9991059
unsigned long npages;
10001060
struct kvm_memory_slot *slot;
10011061
struct kvm_memory_slot old, new;
1002-
struct kvm_memslots *slots;
10031062
int as_id, id;
10041063
enum kvm_mr_change change;
10051064

@@ -1086,58 +1145,19 @@ int __kvm_set_memory_region(struct kvm *kvm,
10861145
return r;
10871146
}
10881147

1089-
slots = kvzalloc(sizeof(struct kvm_memslots), GFP_KERNEL_ACCOUNT);
1090-
if (!slots) {
1091-
r = -ENOMEM;
1092-
goto out_bitmap;
1093-
}
1094-
memcpy(slots, __kvm_memslots(kvm, as_id), sizeof(struct kvm_memslots));
1095-
1096-
if ((change == KVM_MR_DELETE) || (change == KVM_MR_MOVE)) {
1097-
slot = id_to_memslot(slots, id);
1098-
slot->flags |= KVM_MEMSLOT_INVALID;
1099-
1100-
/*
1101-
* We can re-use the old memslots, the only difference from the
1102-
* newly installed memslots is the invalid flag, which will get
1103-
* dropped by update_memslots anyway. We'll also revert to the
1104-
* old memslots if preparing the new memory region fails.
1105-
*/
1106-
slots = install_new_memslots(kvm, as_id, slots);
1107-
1108-
/* From this point no new shadow pages pointing to a deleted,
1109-
* or moved, memslot will be created.
1110-
*
1111-
* validation of sp->gfn happens in:
1112-
* - gfn_to_hva (kvm_read_guest, gfn_to_pfn)
1113-
* - kvm_is_visible_gfn (mmu_check_root)
1114-
*/
1115-
kvm_arch_flush_shadow_memslot(kvm, slot);
1116-
}
1117-
1118-
r = kvm_arch_prepare_memory_region(kvm, &new, mem, change);
1119-
if (r)
1120-
goto out_slots;
1121-
11221148
/* actual memory is freed via old in kvm_free_memslot below */
11231149
if (change == KVM_MR_DELETE) {
11241150
new.dirty_bitmap = NULL;
11251151
memset(&new.arch, 0, sizeof(new.arch));
11261152
}
11271153

1128-
update_memslots(slots, &new, change);
1129-
slots = install_new_memslots(kvm, as_id, slots);
1130-
1131-
kvm_arch_commit_memory_region(kvm, mem, &old, &new, change);
1154+
r = kvm_set_memslot(kvm, mem, &old, &new, as_id, change);
1155+
if (r)
1156+
goto out_bitmap;
11321157

11331158
kvm_free_memslot(kvm, &old, &new);
1134-
kvfree(slots);
11351159
return 0;
11361160

1137-
out_slots:
1138-
if (change == KVM_MR_DELETE || change == KVM_MR_MOVE)
1139-
slots = install_new_memslots(kvm, as_id, slots);
1140-
kvfree(slots);
11411161
out_bitmap:
11421162
if (new.dirty_bitmap && !old.dirty_bitmap)
11431163
kvm_destroy_dirty_bitmap(&new);

0 commit comments

Comments
 (0)