~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/kvm/x86_64/sev_smoke_test.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 #include <math.h>
  8 
  9 #include "test_util.h"
 10 #include "kvm_util.h"
 11 #include "processor.h"
 12 #include "svm_util.h"
 13 #include "linux/psp-sev.h"
 14 #include "sev.h"
 15 
 16 
 17 #define XFEATURE_MASK_X87_AVX (XFEATURE_MASK_FP | XFEATURE_MASK_SSE | XFEATURE_MASK_YMM)
 18 
 19 static void guest_sev_es_code(void)
 20 {
 21         /* TODO: Check CPUID after GHCB-based hypercall support is added. */
 22         GUEST_ASSERT(rdmsr(MSR_AMD64_SEV) & MSR_AMD64_SEV_ENABLED);
 23         GUEST_ASSERT(rdmsr(MSR_AMD64_SEV) & MSR_AMD64_SEV_ES_ENABLED);
 24 
 25         /*
 26          * TODO: Add GHCB and ucall support for SEV-ES guests.  For now, simply
 27          * force "termination" to signal "done" via the GHCB MSR protocol.
 28          */
 29         wrmsr(MSR_AMD64_SEV_ES_GHCB, GHCB_MSR_TERM_REQ);
 30         __asm__ __volatile__("rep; vmmcall");
 31 }
 32 
 33 static void guest_sev_code(void)
 34 {
 35         GUEST_ASSERT(this_cpu_has(X86_FEATURE_SEV));
 36         GUEST_ASSERT(rdmsr(MSR_AMD64_SEV) & MSR_AMD64_SEV_ENABLED);
 37 
 38         GUEST_DONE();
 39 }
 40 
 41 /* Stash state passed via VMSA before any compiled code runs.  */
 42 extern void guest_code_xsave(void);
 43 asm("guest_code_xsave:\n"
 44     "mov $-1, %eax\n"
 45     "mov $-1, %edx\n"
 46     "xsave (%rdi)\n"
 47     "jmp guest_sev_es_code");
 48 
 49 static void compare_xsave(u8 *from_host, u8 *from_guest)
 50 {
 51         int i;
 52         bool bad = false;
 53         for (i = 0; i < 4095; i++) {
 54                 if (from_host[i] != from_guest[i]) {
 55                         printf("mismatch at %02hhx | %02hhx %02hhx\n", i, from_host[i], from_guest[i]);
 56                         bad = true;
 57                 }
 58         }
 59 
 60         if (bad)
 61                 abort();
 62 }
 63 
 64 static void test_sync_vmsa(uint32_t policy)
 65 {
 66         struct kvm_vcpu *vcpu;
 67         struct kvm_vm *vm;
 68         vm_vaddr_t gva;
 69         void *hva;
 70 
 71         double x87val = M_PI;
 72         struct kvm_xsave __attribute__((aligned(64))) xsave = { 0 };
 73         struct kvm_sregs sregs;
 74         struct kvm_xcrs xcrs = {
 75                 .nr_xcrs = 1,
 76                 .xcrs[0].xcr = 0,
 77                 .xcrs[0].value = XFEATURE_MASK_X87_AVX,
 78         };
 79 
 80         vm = vm_sev_create_with_one_vcpu(KVM_X86_SEV_ES_VM, guest_code_xsave, &vcpu);
 81         gva = vm_vaddr_alloc_shared(vm, PAGE_SIZE, KVM_UTIL_MIN_VADDR,
 82                                     MEM_REGION_TEST_DATA);
 83         hva = addr_gva2hva(vm, gva);
 84 
 85         vcpu_args_set(vcpu, 1, gva);
 86 
 87         vcpu_sregs_get(vcpu, &sregs);
 88         sregs.cr4 |= X86_CR4_OSFXSR | X86_CR4_OSXSAVE;
 89         vcpu_sregs_set(vcpu, &sregs);
 90 
 91         vcpu_xcrs_set(vcpu, &xcrs);
 92         asm("fninit\n"
 93             "vpcmpeqb %%ymm4, %%ymm4, %%ymm4\n"
 94             "fldl %3\n"
 95             "xsave (%2)\n"
 96             "fstp %%st\n"
 97             : "=m"(xsave)
 98             : "A"(XFEATURE_MASK_X87_AVX), "r"(&xsave), "m" (x87val)
 99             : "ymm4", "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)");
100         vcpu_xsave_set(vcpu, &xsave);
101 
102         vm_sev_launch(vm, SEV_POLICY_ES | policy, NULL);
103 
104         /* This page is shared, so make it decrypted.  */
105         memset(hva, 0, 4096);
106 
107         vcpu_run(vcpu);
108 
109         TEST_ASSERT(vcpu->run->exit_reason == KVM_EXIT_SYSTEM_EVENT,
110                     "Wanted SYSTEM_EVENT, got %s",
111                     exit_reason_str(vcpu->run->exit_reason));
112         TEST_ASSERT_EQ(vcpu->run->system_event.type, KVM_SYSTEM_EVENT_SEV_TERM);
113         TEST_ASSERT_EQ(vcpu->run->system_event.ndata, 1);
114         TEST_ASSERT_EQ(vcpu->run->system_event.data[0], GHCB_MSR_TERM_REQ);
115 
116         compare_xsave((u8 *)&xsave, (u8 *)hva);
117 
118         kvm_vm_free(vm);
119 }
120 
121 static void test_sev(void *guest_code, uint64_t policy)
122 {
123         struct kvm_vcpu *vcpu;
124         struct kvm_vm *vm;
125         struct ucall uc;
126 
127         uint32_t type = policy & SEV_POLICY_ES ? KVM_X86_SEV_ES_VM : KVM_X86_SEV_VM;
128 
129         vm = vm_sev_create_with_one_vcpu(type, guest_code, &vcpu);
130 
131         /* TODO: Validate the measurement is as expected. */
132         vm_sev_launch(vm, policy, NULL);
133 
134         for (;;) {
135                 vcpu_run(vcpu);
136 
137                 if (policy & SEV_POLICY_ES) {
138                         TEST_ASSERT(vcpu->run->exit_reason == KVM_EXIT_SYSTEM_EVENT,
139                                     "Wanted SYSTEM_EVENT, got %s",
140                                     exit_reason_str(vcpu->run->exit_reason));
141                         TEST_ASSERT_EQ(vcpu->run->system_event.type, KVM_SYSTEM_EVENT_SEV_TERM);
142                         TEST_ASSERT_EQ(vcpu->run->system_event.ndata, 1);
143                         TEST_ASSERT_EQ(vcpu->run->system_event.data[0], GHCB_MSR_TERM_REQ);
144                         break;
145                 }
146 
147                 switch (get_ucall(vcpu, &uc)) {
148                 case UCALL_SYNC:
149                         continue;
150                 case UCALL_DONE:
151                         return;
152                 case UCALL_ABORT:
153                         REPORT_GUEST_ASSERT(uc);
154                 default:
155                         TEST_FAIL("Unexpected exit: %s",
156                                   exit_reason_str(vcpu->run->exit_reason));
157                 }
158         }
159 
160         kvm_vm_free(vm);
161 }
162 
163 int main(int argc, char *argv[])
164 {
165         TEST_REQUIRE(kvm_cpu_has(X86_FEATURE_SEV));
166 
167         test_sev(guest_sev_code, SEV_POLICY_NO_DBG);
168         test_sev(guest_sev_code, 0);
169 
170         if (kvm_cpu_has(X86_FEATURE_SEV_ES)) {
171                 test_sev(guest_sev_es_code, SEV_POLICY_ES | SEV_POLICY_NO_DBG);
172                 test_sev(guest_sev_es_code, SEV_POLICY_ES);
173 
174                 if (kvm_has_cap(KVM_CAP_XCRS) &&
175                     (xgetbv(0) & XFEATURE_MASK_X87_AVX) == XFEATURE_MASK_X87_AVX) {
176                         test_sync_vmsa(0);
177                         test_sync_vmsa(SEV_POLICY_NO_DBG);
178                 }
179         }
180 
181         return 0;
182 }
183 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php