Skip to content

Commit 40e09b3

Browse files
committed
KVM: selftests: Add a basic SEV-ES smoke test
Extend sev_smoke_test to also run a minimal SEV-ES smoke test so that it's possible to test KVM's unique VMRUN=>#VMEXIT path for SEV-ES guests without needing a full blown SEV-ES capable VM, which requires a rather absurd amount of properly configured collateral. Punt on proper GHCB and ucall support, and instead use the GHCB MSR protocol to signal test completion. The most important thing at this point is to have _any_ kind of testing of KVM's __svm_sev_es_vcpu_run(). Cc: Tom Lendacky <thomas.lendacky@amd.com> Cc: Michael Roth <michael.roth@amd.com> Cc: Peter Gonda <pgonda@google.com> Cc: Carlos Bilbao <carlos.bilbao@amd.com> Tested-by: Carlos Bilbao <carlos.bilbao@amd.com> Link: https://lore.kernel.org/r/20240223004258.3104051-12-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent be250ff commit 40e09b3

File tree

4 files changed

+38
-2
lines changed

4 files changed

+38
-2
lines changed

tools/testing/selftests/kvm/include/x86_64/sev.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ enum sev_guest_state {
2525
#define SEV_POLICY_NO_DBG (1UL << 0)
2626
#define SEV_POLICY_ES (1UL << 2)
2727

28+
#define GHCB_MSR_TERM_REQ 0x100
29+
2830
void sev_vm_launch(struct kvm_vm *vm, uint32_t policy);
2931
void sev_vm_launch_measure(struct kvm_vm *vm, uint8_t *measurement);
3032
void sev_vm_launch_finish(struct kvm_vm *vm);

tools/testing/selftests/kvm/lib/x86_64/processor.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1072,7 +1072,7 @@ void kvm_get_cpu_address_width(unsigned int *pa_bits, unsigned int *va_bits)
10721072

10731073
void kvm_init_vm_address_properties(struct kvm_vm *vm)
10741074
{
1075-
if (vm->subtype == VM_SUBTYPE_SEV) {
1075+
if (vm->subtype == VM_SUBTYPE_SEV || vm->subtype == VM_SUBTYPE_SEV_ES) {
10761076
vm->arch.c_bit = BIT_ULL(this_cpu_property(X86_PROPERTY_SEV_C_BIT));
10771077
vm->gpa_tag_mask = vm->arch.c_bit;
10781078
}

tools/testing/selftests/kvm/lib/x86_64/sev.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ void sev_vm_launch(struct kvm_vm *vm, uint32_t policy)
5353
hash_for_each(vm->regions.slot_hash, ctr, region, slot_node)
5454
encrypt_region(vm, region);
5555

56+
if (policy & SEV_POLICY_ES)
57+
vm_sev_ioctl(vm, KVM_SEV_LAUNCH_UPDATE_VMSA, NULL);
58+
5659
vm->arch.is_pt_protected = true;
5760
}
5861

@@ -90,7 +93,8 @@ struct kvm_vm *vm_sev_create_with_one_vcpu(uint32_t policy, void *guest_code,
9093
struct vm_shape shape = {
9194
.type = VM_TYPE_DEFAULT,
9295
.mode = VM_MODE_DEFAULT,
93-
.subtype = VM_SUBTYPE_SEV,
96+
.subtype = policy & SEV_POLICY_ES ? VM_SUBTYPE_SEV_ES :
97+
VM_SUBTYPE_SEV,
9498
};
9599
struct kvm_vm *vm;
96100
struct kvm_vcpu *cpus[1];

tools/testing/selftests/kvm/x86_64/sev_smoke_test.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,21 @@
1212
#include "linux/psp-sev.h"
1313
#include "sev.h"
1414

15+
16+
static void guest_sev_es_code(void)
17+
{
18+
/* TODO: Check CPUID after GHCB-based hypercall support is added. */
19+
GUEST_ASSERT(rdmsr(MSR_AMD64_SEV) & MSR_AMD64_SEV_ENABLED);
20+
GUEST_ASSERT(rdmsr(MSR_AMD64_SEV) & MSR_AMD64_SEV_ES_ENABLED);
21+
22+
/*
23+
* TODO: Add GHCB and ucall support for SEV-ES guests. For now, simply
24+
* force "termination" to signal "done" via the GHCB MSR protocol.
25+
*/
26+
wrmsr(MSR_AMD64_SEV_ES_GHCB, GHCB_MSR_TERM_REQ);
27+
__asm__ __volatile__("rep; vmmcall");
28+
}
29+
1530
static void guest_sev_code(void)
1631
{
1732
GUEST_ASSERT(this_cpu_has(X86_FEATURE_SEV));
@@ -31,6 +46,16 @@ static void test_sev(void *guest_code, uint64_t policy)
3146
for (;;) {
3247
vcpu_run(vcpu);
3348

49+
if (policy & SEV_POLICY_ES) {
50+
TEST_ASSERT(vcpu->run->exit_reason == KVM_EXIT_SYSTEM_EVENT,
51+
"Wanted SYSTEM_EVENT, got %s",
52+
exit_reason_str(vcpu->run->exit_reason));
53+
TEST_ASSERT_EQ(vcpu->run->system_event.type, KVM_SYSTEM_EVENT_SEV_TERM);
54+
TEST_ASSERT_EQ(vcpu->run->system_event.ndata, 1);
55+
TEST_ASSERT_EQ(vcpu->run->system_event.data[0], GHCB_MSR_TERM_REQ);
56+
break;
57+
}
58+
3459
switch (get_ucall(vcpu, &uc)) {
3560
case UCALL_SYNC:
3661
continue;
@@ -54,5 +79,10 @@ int main(int argc, char *argv[])
5479
test_sev(guest_sev_code, SEV_POLICY_NO_DBG);
5580
test_sev(guest_sev_code, 0);
5681

82+
if (kvm_cpu_has(X86_FEATURE_SEV_ES)) {
83+
test_sev(guest_sev_es_code, SEV_POLICY_ES | SEV_POLICY_NO_DBG);
84+
test_sev(guest_sev_es_code, SEV_POLICY_ES);
85+
}
86+
5787
return 0;
5888
}

0 commit comments

Comments
 (0)