1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <fcntl.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <sys/ioctl.h> 7 8 #include "test_util.h" 9 #include "kvm_util.h" 10 #include "processor.h" 11 #include "svm_util.h" 12 #include "linux/psp-sev.h" 13 #include "sev.h" 14 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 30 static void guest_sev_code(void) 31 { 32 GUEST_ASSERT(this_cpu_has(X86_FEATURE_SEV)); 33 GUEST_ASSERT(rdmsr(MSR_AMD64_SEV) & MSR_AMD64_SEV_ENABLED); 34 35 GUEST_DONE(); 36 } 37 38 static void test_sev(void *guest_code, uint64_t policy) 39 { 40 struct kvm_vcpu *vcpu; 41 struct kvm_vm *vm; 42 struct ucall uc; 43 44 vm = vm_sev_create_with_one_vcpu(policy, guest_code, &vcpu); 45 46 for (;;) { 47 vcpu_run(vcpu); 48 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 59 switch (get_ucall(vcpu, &uc)) { 60 case UCALL_SYNC: 61 continue; 62 case UCALL_DONE: 63 return; 64 case UCALL_ABORT: 65 REPORT_GUEST_ASSERT(uc); 66 default: 67 TEST_FAIL("Unexpected exit: %s", 68 exit_reason_str(vcpu->run->exit_reason)); 69 } 70 } 71 72 kvm_vm_free(vm); 73 } 74 75 int main(int argc, char *argv[]) 76 { 77 TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SEV)); 78 79 test_sev(guest_sev_code, SEV_POLICY_NO_DBG); 80 test_sev(guest_sev_code, 0); 81 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 87 return 0; 88 } 89