1350bf64aSZixuan Wang /*
2350bf64aSZixuan Wang * AMD SEV test cases
3350bf64aSZixuan Wang *
4350bf64aSZixuan Wang * Copyright (c) 2021, Google Inc
5350bf64aSZixuan Wang *
6350bf64aSZixuan Wang * Authors:
7350bf64aSZixuan Wang * Hyunwook (Wooky) Baek <baekhw@google.com>
8350bf64aSZixuan Wang * Zixuan Wang <zixuanwang@google.com>
9350bf64aSZixuan Wang *
10350bf64aSZixuan Wang * SPDX-License-Identifier: LGPL-2.0-or-later
11350bf64aSZixuan Wang */
12350bf64aSZixuan Wang
13350bf64aSZixuan Wang #include "libcflat.h"
14350bf64aSZixuan Wang #include "x86/processor.h"
15350bf64aSZixuan Wang #include "x86/amd_sev.h"
168e38cb32SPaolo Bonzini #include "msr.h"
17350bf64aSZixuan Wang
18350bf64aSZixuan Wang #define EXIT_SUCCESS 0
19350bf64aSZixuan Wang #define EXIT_FAILURE 1
20350bf64aSZixuan Wang
21*ef9094a5SMarc Orr #define TESTDEV_IO_PORT 0xe0
22*ef9094a5SMarc Orr
23*ef9094a5SMarc Orr static char st1[] = "abcdefghijklmnop";
24*ef9094a5SMarc Orr
test_sev_activation(void)25350bf64aSZixuan Wang static int test_sev_activation(void)
26350bf64aSZixuan Wang {
27350bf64aSZixuan Wang struct cpuid cpuid_out;
28350bf64aSZixuan Wang u64 msr_out;
29350bf64aSZixuan Wang
30350bf64aSZixuan Wang printf("SEV activation test is loaded.\n");
31350bf64aSZixuan Wang
32350bf64aSZixuan Wang /* Tests if CPUID function to check SEV is implemented */
33350bf64aSZixuan Wang cpuid_out = cpuid(CPUID_FN_LARGEST_EXT_FUNC_NUM);
34350bf64aSZixuan Wang printf("CPUID Fn8000_0000[EAX]: 0x%08x\n", cpuid_out.a);
35350bf64aSZixuan Wang if (cpuid_out.a < CPUID_FN_ENCRYPT_MEM_CAPAB) {
36350bf64aSZixuan Wang printf("CPUID does not support FN%08x\n",
37350bf64aSZixuan Wang CPUID_FN_ENCRYPT_MEM_CAPAB);
38350bf64aSZixuan Wang return EXIT_FAILURE;
39350bf64aSZixuan Wang }
40350bf64aSZixuan Wang
41350bf64aSZixuan Wang /* Tests if SEV is supported */
42350bf64aSZixuan Wang cpuid_out = cpuid(CPUID_FN_ENCRYPT_MEM_CAPAB);
43350bf64aSZixuan Wang printf("CPUID Fn8000_001F[EAX]: 0x%08x\n", cpuid_out.a);
44350bf64aSZixuan Wang printf("CPUID Fn8000_001F[EBX]: 0x%08x\n", cpuid_out.b);
45350bf64aSZixuan Wang if (!(cpuid_out.a & SEV_SUPPORT_MASK)) {
46350bf64aSZixuan Wang printf("SEV is not supported.\n");
47350bf64aSZixuan Wang return EXIT_FAILURE;
48350bf64aSZixuan Wang }
49350bf64aSZixuan Wang printf("SEV is supported\n");
50350bf64aSZixuan Wang
51350bf64aSZixuan Wang /* Tests if SEV is enabled */
52350bf64aSZixuan Wang msr_out = rdmsr(MSR_SEV_STATUS);
53350bf64aSZixuan Wang printf("MSR C001_0131[EAX]: 0x%08lx\n", msr_out & 0xffffffff);
54350bf64aSZixuan Wang if (!(msr_out & SEV_ENABLED_MASK)) {
55350bf64aSZixuan Wang printf("SEV is not enabled.\n");
56350bf64aSZixuan Wang return EXIT_FAILURE;
57350bf64aSZixuan Wang }
58350bf64aSZixuan Wang printf("SEV is enabled\n");
59350bf64aSZixuan Wang
60350bf64aSZixuan Wang return EXIT_SUCCESS;
61350bf64aSZixuan Wang }
62350bf64aSZixuan Wang
test_sev_es_activation(void)638e38cb32SPaolo Bonzini static void test_sev_es_activation(void)
648e38cb32SPaolo Bonzini {
658e38cb32SPaolo Bonzini if (rdmsr(MSR_SEV_STATUS) & SEV_ES_ENABLED_MASK) {
668e38cb32SPaolo Bonzini printf("SEV-ES is enabled.\n");
678e38cb32SPaolo Bonzini } else {
688e38cb32SPaolo Bonzini printf("SEV-ES is not enabled.\n");
698e38cb32SPaolo Bonzini }
708e38cb32SPaolo Bonzini }
718e38cb32SPaolo Bonzini
test_stringio(void)72*ef9094a5SMarc Orr static void test_stringio(void)
73*ef9094a5SMarc Orr {
74*ef9094a5SMarc Orr int st1_len = sizeof(st1) - 1;
75*ef9094a5SMarc Orr u16 got;
76*ef9094a5SMarc Orr
77*ef9094a5SMarc Orr asm volatile("cld \n\t"
78*ef9094a5SMarc Orr "movw %0, %%dx \n\t"
79*ef9094a5SMarc Orr "rep outsw \n\t"
80*ef9094a5SMarc Orr : : "i"((short)TESTDEV_IO_PORT),
81*ef9094a5SMarc Orr "S"(st1), "c"(st1_len / 2));
82*ef9094a5SMarc Orr
83*ef9094a5SMarc Orr asm volatile("inw %1, %0\n\t" : "=a"(got) : "i"((short)TESTDEV_IO_PORT));
84*ef9094a5SMarc Orr
85*ef9094a5SMarc Orr report((got & 0xff) == st1[sizeof(st1) - 3], "outsb nearly up");
86*ef9094a5SMarc Orr report((got & 0xff00) >> 8 == st1[sizeof(st1) - 2], "outsb up");
87*ef9094a5SMarc Orr }
88*ef9094a5SMarc Orr
main(void)89350bf64aSZixuan Wang int main(void)
90350bf64aSZixuan Wang {
91350bf64aSZixuan Wang int rtn;
92350bf64aSZixuan Wang rtn = test_sev_activation();
93350bf64aSZixuan Wang report(rtn == EXIT_SUCCESS, "SEV activation test.");
948e38cb32SPaolo Bonzini test_sev_es_activation();
95*ef9094a5SMarc Orr test_stringio();
96350bf64aSZixuan Wang return report_summary();
97350bf64aSZixuan Wang }
98