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 16static 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 30static 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 38static 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 75int 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