diff mbox series

KVM: selftests: Add SEV-ES shutdown test

Message ID 20240709182936.146487-1-pgonda@google.com (mailing list archive)
State Accepted
Commit 2f6fcfa1f4264c1f035ddd092ebd046499f7cbea
Headers show
Series KVM: selftests: Add SEV-ES shutdown test | expand

Commit Message

Peter Gonda July 9, 2024, 6:29 p.m. UTC
Regression test for ae20eef5 ("KVM: SVM: Update SEV-ES shutdown intercepts
with more metadata"). Test confirms userspace is correctly indicated of
a guest shutdown not previous behavior of an EINVAL from KVM_RUN.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Sean Christopherson <seanjc@google.com>
Cc: Alper Gun <alpergun@google.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Michael Roth <michael.roth@amd.com>
Cc: kvm@vger.kernel.org
Cc: linux-kselftest@vger.kernel.org
Signed-off-by: Peter Gonda <pgonda@google.com>

---
 .../selftests/kvm/x86_64/sev_smoke_test.c     | 26 +++++++++++++++++++
 1 file changed, 26 insertions(+)

Comments

Pratik R. Sampat July 11, 2024, 4:19 p.m. UTC | #1
Hi Peter,

On 7/9/2024 1:29 PM, Peter Gonda wrote:
> Regression test for ae20eef5 ("KVM: SVM: Update SEV-ES shutdown intercepts
> with more metadata"). Test confirms userspace is correctly indicated of
> a guest shutdown not previous behavior of an EINVAL from KVM_RUN.
> 
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Sean Christopherson <seanjc@google.com>
> Cc: Alper Gun <alpergun@google.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Michael Roth <michael.roth@amd.com>
> Cc: kvm@vger.kernel.org
> Cc: linux-kselftest@vger.kernel.org
> Signed-off-by: Peter Gonda <pgonda@google.com>

Tested-by: Pratik R. Sampat <pratikrajesh.sampat@amd.com>

> 
> ---
>  .../selftests/kvm/x86_64/sev_smoke_test.c     | 26 +++++++++++++++++++
>  1 file changed, 26 insertions(+)
> 
> diff --git a/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c b/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c
> index 7c70c0da4fb74..04f24d5f09877 100644
> --- a/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c
> @@ -160,6 +160,30 @@ static void test_sev(void *guest_code, uint64_t policy)
>  	kvm_vm_free(vm);
>  }
>  
> +static void guest_shutdown_code(void)
> +{
> +	__asm__ __volatile__("ud2");
> +}
> +
> +static void test_sev_es_shutdown(void)
> +{
> +	struct kvm_vcpu *vcpu;
> +	struct kvm_vm *vm;
> +
> +	uint32_t type = KVM_X86_SEV_ES_VM;
> +
> +	vm = vm_sev_create_with_one_vcpu(type, guest_shutdown_code, &vcpu);
> +
> +	vm_sev_launch(vm, SEV_POLICY_ES, NULL);
> +
> +	vcpu_run(vcpu);
> +	TEST_ASSERT(vcpu->run->exit_reason == KVM_EXIT_SHUTDOWN,
> +		    "Wanted SHUTDOWN, got %s",
> +		    exit_reason_str(vcpu->run->exit_reason));
> +
> +	kvm_vm_free(vm);
> +}
> +

I guess this case also applies to SNP. So maybe once this patch is
queued up I could spin another patch in my SNP kselftest patch series
that parameterizes this function to test SNP as well.

Thanks!
Pratik

>  int main(int argc, char *argv[])
>  {
>  	TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SEV));
> @@ -171,6 +195,8 @@ int main(int argc, char *argv[])
>  		test_sev(guest_sev_es_code, SEV_POLICY_ES | SEV_POLICY_NO_DBG);
>  		test_sev(guest_sev_es_code, SEV_POLICY_ES);
>  
> +		test_sev_es_shutdown();
> +
>  		if (kvm_has_cap(KVM_CAP_XCRS) &&
>  		    (xgetbv(0) & XFEATURE_MASK_X87_AVX) == XFEATURE_MASK_X87_AVX) {
>  			test_sync_vmsa(0);
Peter Gonda July 11, 2024, 4:37 p.m. UTC | #2
>
> I guess this case also applies to SNP. So maybe once this patch is
> queued up I could spin another patch in my SNP kselftest patch series
> that parameterizes this function to test SNP as well.
>

Thanks! That sounds great. I plan on sending a few tests for the
sev-es termination codes. I can base that on top of your SNP series.
Sean Christopherson Aug. 30, 2024, 2:36 a.m. UTC | #3
On Tue, Jul 09, 2024, Peter Gonda wrote:
> Regression test for ae20eef5 ("KVM: SVM: Update SEV-ES shutdown intercepts
> with more metadata"). Test confirms userspace is correctly indicated of
> a guest shutdown not previous behavior of an EINVAL from KVM_RUN.
> 
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Sean Christopherson <seanjc@google.com>
> Cc: Alper Gun <alpergun@google.com>
> Cc: Tom Lendacky <thomas.lendacky@amd.com>
> Cc: Michael Roth <michael.roth@amd.com>
> Cc: kvm@vger.kernel.org
> Cc: linux-kselftest@vger.kernel.org
> Signed-off-by: Peter Gonda <pgonda@google.com>
> 
> ---
>  .../selftests/kvm/x86_64/sev_smoke_test.c     | 26 +++++++++++++++++++
>  1 file changed, 26 insertions(+)
> 
> diff --git a/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c b/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c
> index 7c70c0da4fb74..04f24d5f09877 100644
> --- a/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c
> +++ b/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c
> @@ -160,6 +160,30 @@ static void test_sev(void *guest_code, uint64_t policy)
>  	kvm_vm_free(vm);
>  }
>  
> +static void guest_shutdown_code(void)
> +{
> +	__asm__ __volatile__("ud2");

Heh, this passes by dumb luck, not because the #UD itself causes a SHUTDOWN.  It
_looks_ like the #UD causes a shutdown, because KVM will always see the original
guest RIP, but the shutdown actually occurs somewhere in the ucall_assert() in
route_exception().

Now that x86 selftests install an IDT and exception handlers by default, it's
actually quite hard to induce shutdown.  Ok, not "hard", but it requires more
work than simply generating a #UD.

I'll add this as fixup when applying:

diff --git a/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c b/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c
index 04f24d5f0987..2e9197eb1652 100644
--- a/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c
+++ b/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c
@@ -162,6 +162,12 @@ static void test_sev(void *guest_code, uint64_t policy)
 
 static void guest_shutdown_code(void)
 {
+       struct desc_ptr idt;
+
+       /* Clobber the IDT so that #UD is guaranteed to trigger SHUTDOWN. */
+       memset(&idt, 0, sizeof(idt));
+       __asm__ __volatile__("lidt %0" :: "m"(idt));
+
        __asm__ __volatile__("ud2");
 }
Sean Christopherson Aug. 31, 2024, 12:20 a.m. UTC | #4
On Tue, 09 Jul 2024 11:29:36 -0700, Peter Gonda wrote:
> Regression test for ae20eef5 ("KVM: SVM: Update SEV-ES shutdown intercepts
> with more metadata"). Test confirms userspace is correctly indicated of
> a guest shutdown not previous behavior of an EINVAL from KVM_RUN.

Applied to kvm-x86 selftests, with the IDT clobbering.  Thanks!

[1/1] KVM: selftests: Add SEV-ES shutdown test
      https://github.com/kvm-x86/linux/commit/2f6fcfa1f426

--
https://github.com/kvm-x86/linux/tree/next
diff mbox series

Patch

diff --git a/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c b/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c
index 7c70c0da4fb74..04f24d5f09877 100644
--- a/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c
+++ b/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c
@@ -160,6 +160,30 @@  static void test_sev(void *guest_code, uint64_t policy)
 	kvm_vm_free(vm);
 }
 
+static void guest_shutdown_code(void)
+{
+	__asm__ __volatile__("ud2");
+}
+
+static void test_sev_es_shutdown(void)
+{
+	struct kvm_vcpu *vcpu;
+	struct kvm_vm *vm;
+
+	uint32_t type = KVM_X86_SEV_ES_VM;
+
+	vm = vm_sev_create_with_one_vcpu(type, guest_shutdown_code, &vcpu);
+
+	vm_sev_launch(vm, SEV_POLICY_ES, NULL);
+
+	vcpu_run(vcpu);
+	TEST_ASSERT(vcpu->run->exit_reason == KVM_EXIT_SHUTDOWN,
+		    "Wanted SHUTDOWN, got %s",
+		    exit_reason_str(vcpu->run->exit_reason));
+
+	kvm_vm_free(vm);
+}
+
 int main(int argc, char *argv[])
 {
 	TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SEV));
@@ -171,6 +195,8 @@  int main(int argc, char *argv[])
 		test_sev(guest_sev_es_code, SEV_POLICY_ES | SEV_POLICY_NO_DBG);
 		test_sev(guest_sev_es_code, SEV_POLICY_ES);
 
+		test_sev_es_shutdown();
+
 		if (kvm_has_cap(KVM_CAP_XCRS) &&
 		    (xgetbv(0) & XFEATURE_MASK_X87_AVX) == XFEATURE_MASK_X87_AVX) {
 			test_sync_vmsa(0);