xref: /kvm-unit-tests/lib/x86/amd_sev.c (revision bf812590dcb67210ff8074f6c6dcc39df5da0852)
1350bf64aSZixuan Wang /*
2350bf64aSZixuan Wang  * AMD SEV support in kvm-unit-tests
3350bf64aSZixuan Wang  *
4350bf64aSZixuan Wang  * Copyright (c) 2021, Google Inc
5350bf64aSZixuan Wang  *
6350bf64aSZixuan Wang  * Authors:
7350bf64aSZixuan Wang  *   Zixuan Wang <zixuanwang@google.com>
8350bf64aSZixuan Wang  *
9350bf64aSZixuan Wang  * SPDX-License-Identifier: LGPL-2.0-or-later
10350bf64aSZixuan Wang  */
11350bf64aSZixuan Wang 
12350bf64aSZixuan Wang #include "amd_sev.h"
13350bf64aSZixuan Wang #include "x86/processor.h"
14350bf64aSZixuan Wang 
15350bf64aSZixuan Wang static unsigned short amd_sev_c_bit_pos;
16350bf64aSZixuan Wang 
17350bf64aSZixuan Wang bool amd_sev_enabled(void)
18350bf64aSZixuan Wang {
19350bf64aSZixuan Wang 	struct cpuid cpuid_out;
20350bf64aSZixuan Wang 	static bool sev_enabled;
21350bf64aSZixuan Wang 	static bool initialized = false;
22350bf64aSZixuan Wang 
23350bf64aSZixuan Wang 	/* Check CPUID and MSR for SEV status and store it for future function calls. */
24350bf64aSZixuan Wang 	if (!initialized) {
25350bf64aSZixuan Wang 		sev_enabled = false;
26350bf64aSZixuan Wang 		initialized = true;
27350bf64aSZixuan Wang 
28350bf64aSZixuan Wang 		/* Test if we can query SEV features */
29350bf64aSZixuan Wang 		cpuid_out = cpuid(CPUID_FN_LARGEST_EXT_FUNC_NUM);
30350bf64aSZixuan Wang 		if (cpuid_out.a < CPUID_FN_ENCRYPT_MEM_CAPAB) {
31350bf64aSZixuan Wang 			return sev_enabled;
32350bf64aSZixuan Wang 		}
33350bf64aSZixuan Wang 
34350bf64aSZixuan Wang 		/* Test if SEV is supported */
35350bf64aSZixuan Wang 		cpuid_out = cpuid(CPUID_FN_ENCRYPT_MEM_CAPAB);
36350bf64aSZixuan Wang 		if (!(cpuid_out.a & SEV_SUPPORT_MASK)) {
37350bf64aSZixuan Wang 			return sev_enabled;
38350bf64aSZixuan Wang 		}
39350bf64aSZixuan Wang 
40350bf64aSZixuan Wang 		/* Test if SEV is enabled */
41350bf64aSZixuan Wang 		if (rdmsr(MSR_SEV_STATUS) & SEV_ENABLED_MASK) {
42350bf64aSZixuan Wang 			sev_enabled = true;
43350bf64aSZixuan Wang 		}
44350bf64aSZixuan Wang 	}
45350bf64aSZixuan Wang 
46350bf64aSZixuan Wang 	return sev_enabled;
47350bf64aSZixuan Wang }
48350bf64aSZixuan Wang 
49350bf64aSZixuan Wang efi_status_t setup_amd_sev(void)
50350bf64aSZixuan Wang {
51350bf64aSZixuan Wang 	struct cpuid cpuid_out;
52350bf64aSZixuan Wang 
53350bf64aSZixuan Wang 	if (!amd_sev_enabled()) {
54350bf64aSZixuan Wang 		return EFI_UNSUPPORTED;
55350bf64aSZixuan Wang 	}
56350bf64aSZixuan Wang 
57350bf64aSZixuan Wang 	/*
58350bf64aSZixuan Wang 	 * Extract C-Bit position from ebx[5:0]
59350bf64aSZixuan Wang 	 * AMD64 Architecture Programmer's Manual Volume 3
60350bf64aSZixuan Wang 	 *   - Section " Function 8000_001Fh - Encrypted Memory Capabilities"
61350bf64aSZixuan Wang 	 */
62350bf64aSZixuan Wang 	cpuid_out = cpuid(CPUID_FN_ENCRYPT_MEM_CAPAB);
63350bf64aSZixuan Wang 	amd_sev_c_bit_pos = (unsigned short)(cpuid_out.b & 0x3f);
64350bf64aSZixuan Wang 
65350bf64aSZixuan Wang 	return EFI_SUCCESS;
66350bf64aSZixuan Wang }
67350bf64aSZixuan Wang 
68*bf812590SZixuan Wang bool amd_sev_es_enabled(void)
69*bf812590SZixuan Wang {
70*bf812590SZixuan Wang 	static bool sev_es_enabled;
71*bf812590SZixuan Wang 	static bool initialized = false;
72*bf812590SZixuan Wang 
73*bf812590SZixuan Wang 	if (!initialized) {
74*bf812590SZixuan Wang 		sev_es_enabled = false;
75*bf812590SZixuan Wang 		initialized = true;
76*bf812590SZixuan Wang 
77*bf812590SZixuan Wang 		if (!amd_sev_enabled()) {
78*bf812590SZixuan Wang 			return sev_es_enabled;
79*bf812590SZixuan Wang 		}
80*bf812590SZixuan Wang 
81*bf812590SZixuan Wang 		/* Test if SEV-ES is enabled */
82*bf812590SZixuan Wang 		if (rdmsr(MSR_SEV_STATUS) & SEV_ES_ENABLED_MASK) {
83*bf812590SZixuan Wang 			sev_es_enabled = true;
84*bf812590SZixuan Wang 		}
85*bf812590SZixuan Wang 	}
86*bf812590SZixuan Wang 
87*bf812590SZixuan Wang 	return sev_es_enabled;
88*bf812590SZixuan Wang }
89*bf812590SZixuan Wang 
90350bf64aSZixuan Wang unsigned long long get_amd_sev_c_bit_mask(void)
91350bf64aSZixuan Wang {
92350bf64aSZixuan Wang 	if (amd_sev_enabled()) {
93350bf64aSZixuan Wang 		return 1ull << amd_sev_c_bit_pos;
94350bf64aSZixuan Wang 	} else {
95350bf64aSZixuan Wang 		return 0;
96350bf64aSZixuan Wang 	}
97350bf64aSZixuan Wang }
9830203ea5SZixuan Wang 
9930203ea5SZixuan Wang unsigned long long get_amd_sev_addr_upperbound(void)
10030203ea5SZixuan Wang {
10130203ea5SZixuan Wang 	if (amd_sev_enabled()) {
10230203ea5SZixuan Wang 		return amd_sev_c_bit_pos - 1;
10330203ea5SZixuan Wang 	} else {
10430203ea5SZixuan Wang 		/* Default memory upper bound */
10530203ea5SZixuan Wang 		return PT_ADDR_UPPER_BOUND_DEFAULT;
10630203ea5SZixuan Wang 	}
10730203ea5SZixuan Wang }
108