xref: /kvm-unit-tests/lib/x86/amd_sev.c (revision 350bf64a67f6b00edf466363c47c7d0ef1c3c52b)
1 /*
2  * AMD SEV support in kvm-unit-tests
3  *
4  * Copyright (c) 2021, Google Inc
5  *
6  * Authors:
7  *   Zixuan Wang <zixuanwang@google.com>
8  *
9  * SPDX-License-Identifier: LGPL-2.0-or-later
10  */
11 
12 #include "amd_sev.h"
13 #include "x86/processor.h"
14 
15 static unsigned short amd_sev_c_bit_pos;
16 
17 bool amd_sev_enabled(void)
18 {
19 	struct cpuid cpuid_out;
20 	static bool sev_enabled;
21 	static bool initialized = false;
22 
23 	/* Check CPUID and MSR for SEV status and store it for future function calls. */
24 	if (!initialized) {
25 		sev_enabled = false;
26 		initialized = true;
27 
28 		/* Test if we can query SEV features */
29 		cpuid_out = cpuid(CPUID_FN_LARGEST_EXT_FUNC_NUM);
30 		if (cpuid_out.a < CPUID_FN_ENCRYPT_MEM_CAPAB) {
31 			return sev_enabled;
32 		}
33 
34 		/* Test if SEV is supported */
35 		cpuid_out = cpuid(CPUID_FN_ENCRYPT_MEM_CAPAB);
36 		if (!(cpuid_out.a & SEV_SUPPORT_MASK)) {
37 			return sev_enabled;
38 		}
39 
40 		/* Test if SEV is enabled */
41 		if (rdmsr(MSR_SEV_STATUS) & SEV_ENABLED_MASK) {
42 			sev_enabled = true;
43 		}
44 	}
45 
46 	return sev_enabled;
47 }
48 
49 efi_status_t setup_amd_sev(void)
50 {
51 	struct cpuid cpuid_out;
52 
53 	if (!amd_sev_enabled()) {
54 		return EFI_UNSUPPORTED;
55 	}
56 
57 	/*
58 	 * Extract C-Bit position from ebx[5:0]
59 	 * AMD64 Architecture Programmer's Manual Volume 3
60 	 *   - Section " Function 8000_001Fh - Encrypted Memory Capabilities"
61 	 */
62 	cpuid_out = cpuid(CPUID_FN_ENCRYPT_MEM_CAPAB);
63 	amd_sev_c_bit_pos = (unsigned short)(cpuid_out.b & 0x3f);
64 
65 	return EFI_SUCCESS;
66 }
67 
68 unsigned long long get_amd_sev_c_bit_mask(void)
69 {
70 	if (amd_sev_enabled()) {
71 		return 1ull << amd_sev_c_bit_pos;
72 	} else {
73 		return 0;
74 	}
75 }
76