On Mon, Nov 22, 2021, Paolo Bonzini wrote: > list_replace_init cannot be used if the source is an empty list, > because "new->next->prev = new" will overwrite "old->next": > > new old > prev = new, next = new prev = old, next = old > new->next = old->next prev = new, next = old prev = old, next = old > new->next->prev = new prev = new, next = old prev = old, next = new > new->prev = old->prev prev = old, next = old prev = old, next = old > new->next->prev = new prev = old, next = old prev = new, next = new > > The desired outcome instead would be to leave both old and new the same > as they were (two empty circular lists). Use list_cut_before, which > already has the necessary check and is documented to discard the > previous contents of the list that will hold the result. > > Fixes: b56639318bb2 ("KVM: SEV: Add support for SEV intra host migration") > Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> > --- > arch/x86/kvm/svm/sev.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c > index 21ac0a5de4e0..75955beb3770 100644 > --- a/arch/x86/kvm/svm/sev.c > +++ b/arch/x86/kvm/svm/sev.c > @@ -1613,8 +1613,7 @@ static void sev_migrate_from(struct kvm_sev_info *dst, > src->handle = 0; > src->pages_locked = 0; > > - INIT_LIST_HEAD(&dst->regions_list); > - list_replace_init(&src->regions_list, &dst->regions_list); > + list_cut_before(&dst->regions_list, &src->regions_list, &src->regions_list); Yeesh, that is tricky. A list_move_all() helper in list.h to do list_cut_before(dst, src, src); would be nice. Reviewed-by: Sean Christopherson <seanjc@xxxxxxxxxx> > } > > static int sev_es_migrate_from(struct kvm *dst, struct kvm *src) > -- > 2.27.0 > >