[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <aHUe5HY4C2vungCd@google.com>
Date: Mon, 14 Jul 2025 08:14:44 -0700
From: Sean Christopherson <seanjc@...gle.com>
To: Zheyun Shen <szy0127@...u.edu.cn>
Cc: Srikanth Aithal <sraithal@....com>, linux-next@...r.kernel.org, kvm@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: Re: [BUG] NULL pointer dereference in sev_writeback_caches during KVM
SEV migration kselftest on AMD platform
On Mon, Jul 14, 2025, Zheyun Shen wrote:
> The problem is triggered by the following codes in tools/testing/selftests/kvm/x86/sev_migrate_tests.c:
> static void test_sev_migrate_from(bool es)
> {
> struct kvm_vm *src_vm;
> struct kvm_vm *dst_vms[NR_MIGRATE_TEST_VMS];
> int i, ret;
>
> src_vm = sev_vm_create(es);
> for (i = 0; i < NR_MIGRATE_TEST_VMS; ++i)
> dst_vms[i] = aux_vm_create(true);
>
> /* Initial migration from the src to the first dst. */
> sev_migrate_from(dst_vms[0], src_vm);
>
> for (i = 1; i < NR_MIGRATE_TEST_VMS; i++)
> sev_migrate_from(dst_vms[i], dst_vms[i - 1]);
>
> /* Migrate the guest back to the original VM. */
> ret = __sev_migrate_from(src_vm, dst_vms[NR_MIGRATE_TEST_VMS - 1]);
> TEST_ASSERT(ret == -1 && errno == EIO,
> "VM that was migrated from should be dead. ret %d, errno: %d", ret,
> errno);
>
> kvm_vm_free(src_vm);
> for (i = 0; i < NR_MIGRATE_TEST_VMS; ++i)
> kvm_vm_free(dst_vms[i]);
> }
>
> I add some logs in kvm and following shows the result:
> [ 51.618135] sev guest init kvm:ff177f272432e000
Argh, I forgot that sev_vm_move_enc_context_from() requires the destination to
*not* be an SEV guest. KVM needs to explicitly copy over the stack.
> [ 51.627235] kvm destory vm kvm:ff177f272432e000
> [ 51.628011] kvm destory vm mmu notifier unregister kvm:ff177f272432e000
> [ 51.642840] kvm destory vm arch destory vm kvm:ff177f272432e000
> [ 51.673612] vm destory x86
> [ 51.673957] svm vm destory
> [ 51.674401] kvm destory vm kvm:ff177f272432c000
> [ 51.675152] kvm destory vm mmu notifier unregister kvm:ff177f272432c000
> [ 51.675981] kvm destory vm arch destory vm kvm:ff177f272432c000
> [ 51.715937] vm destory x86
> [ 51.716289] svm vm destory
> [ 51.716754] kvm destory vm kvm:ff177f272432a000
> [ 51.717530] kvm destory vm mmu notifier unregister kvm:ff177f272432a000
> [ 51.718363] kvm destory vm arch destory vm kvm:ff177f272432a000
> [ 51.746672] vm destory x86
> [ 51.747018] svm vm destory
> [ 51.747454] kvm destory vm kvm:ff177f2724328000
> [ 51.748219] kvm destory vm mmu notifier unregister kvm:ff177f2724328000
> [ 51.749033] BUG: kernel NULL pointer dereference, address: 0000000000000000
> [ 51.749885] #PF: supervisor read access in kernel mode
> [ 51.750519] #PF: error_code(0x0000) - not-present page
>
> It seems that the cpumask structure is not transferred correctly from
> ff177f272432e000 to ff177f2724328000. But unfortunately I’m not familiar
> with SEV migration. I need to spend some time looking into how SEV migration
> works in order to solve this issue.
...
> >> I can reproduce this issue in my environment, and I will try to resolve it as
> >> soon as possible.
> >
> > Phew, that's good, because I can't repro this, and I don't see anything obviously
> > wrong.
/facepalm
-ENOCOFFEE. I was conflating CONFIG_VMAP_STACK with CONFIG_CPUMASK_OFFSTACK and
thus testing the wrong thing.
I think this is the fix, testing now...
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 95668e84ab86..1476e877b2dc 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -1936,6 +1936,7 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
dst->enc_context_owner = src->enc_context_owner;
dst->es_active = src->es_active;
dst->vmsa_features = src->vmsa_features;
+ memcpy(&dst->have_run_cpus, &src->have_run_cpus, sizeof(src->have_run_cpus));
src->asid = 0;
src->active = false;
@@ -1943,6 +1944,7 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
src->pages_locked = 0;
src->enc_context_owner = NULL;
src->es_active = false;
+ memset(&src->have_run_cpus, 0, sizeof(src->have_run_cpus));
list_cut_before(&dst->regions_list, &src->regions_list, &src->regions_list);
Powered by blists - more mailing lists