| /* |
| * AMD SEV test cases |
| * |
| * Copyright (c) 2021, Google Inc |
| * |
| * Authors: |
| * Hyunwook (Wooky) Baek <baekhw@google.com> |
| * Zixuan Wang <zixuanwang@google.com> |
| * |
| * SPDX-License-Identifier: LGPL-2.0-or-later |
| */ |
| |
| #include "libcflat.h" |
| #include "x86/processor.h" |
| #include "x86/amd_sev.h" |
| #include "msr.h" |
| |
| #define EXIT_SUCCESS 0 |
| #define EXIT_FAILURE 1 |
| |
| #define TESTDEV_IO_PORT 0xe0 |
| |
| static char st1[] = "abcdefghijklmnop"; |
| |
| static int test_sev_activation(void) |
| { |
| struct cpuid cpuid_out; |
| u64 msr_out; |
| |
| printf("SEV activation test is loaded.\n"); |
| |
| /* Tests if CPUID function to check SEV is implemented */ |
| cpuid_out = cpuid(CPUID_FN_LARGEST_EXT_FUNC_NUM); |
| printf("CPUID Fn8000_0000[EAX]: 0x%08x\n", cpuid_out.a); |
| if (cpuid_out.a < CPUID_FN_ENCRYPT_MEM_CAPAB) { |
| printf("CPUID does not support FN%08x\n", |
| CPUID_FN_ENCRYPT_MEM_CAPAB); |
| return EXIT_FAILURE; |
| } |
| |
| /* Tests if SEV is supported */ |
| cpuid_out = cpuid(CPUID_FN_ENCRYPT_MEM_CAPAB); |
| printf("CPUID Fn8000_001F[EAX]: 0x%08x\n", cpuid_out.a); |
| printf("CPUID Fn8000_001F[EBX]: 0x%08x\n", cpuid_out.b); |
| if (!(cpuid_out.a & SEV_SUPPORT_MASK)) { |
| printf("SEV is not supported.\n"); |
| return EXIT_FAILURE; |
| } |
| printf("SEV is supported\n"); |
| |
| /* Tests if SEV is enabled */ |
| msr_out = rdmsr(MSR_SEV_STATUS); |
| printf("MSR C001_0131[EAX]: 0x%08lx\n", msr_out & 0xffffffff); |
| if (!(msr_out & SEV_ENABLED_MASK)) { |
| printf("SEV is not enabled.\n"); |
| return EXIT_FAILURE; |
| } |
| printf("SEV is enabled\n"); |
| |
| return EXIT_SUCCESS; |
| } |
| |
| static void test_sev_es_activation(void) |
| { |
| if (rdmsr(MSR_SEV_STATUS) & SEV_ES_ENABLED_MASK) { |
| printf("SEV-ES is enabled.\n"); |
| } else { |
| printf("SEV-ES is not enabled.\n"); |
| } |
| } |
| |
| static void test_stringio(void) |
| { |
| int st1_len = sizeof(st1) - 1; |
| u16 got; |
| |
| asm volatile("cld \n\t" |
| "movw %0, %%dx \n\t" |
| "rep outsw \n\t" |
| : : "i"((short)TESTDEV_IO_PORT), |
| "S"(st1), "c"(st1_len / 2)); |
| |
| asm volatile("inw %1, %0\n\t" : "=a"(got) : "i"((short)TESTDEV_IO_PORT)); |
| |
| report((got & 0xff) == st1[sizeof(st1) - 3], "outsb nearly up"); |
| report((got & 0xff00) >> 8 == st1[sizeof(st1) - 2], "outsb up"); |
| } |
| |
| int main(void) |
| { |
| int rtn; |
| rtn = test_sev_activation(); |
| report(rtn == EXIT_SUCCESS, "SEV activation test."); |
| test_sev_es_activation(); |
| test_stringio(); |
| return report_summary(); |
| } |