xref: /kvm-unit-tests/lib/x86/amd_sev.c (revision 30203ea534d3a70f570e1c2fc8ab79ed28ddb555)
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 
68350bf64aSZixuan Wang unsigned long long get_amd_sev_c_bit_mask(void)
69350bf64aSZixuan Wang {
70350bf64aSZixuan Wang 	if (amd_sev_enabled()) {
71350bf64aSZixuan Wang 		return 1ull << amd_sev_c_bit_pos;
72350bf64aSZixuan Wang 	} else {
73350bf64aSZixuan Wang 		return 0;
74350bf64aSZixuan Wang 	}
75350bf64aSZixuan Wang }
76*30203ea5SZixuan Wang 
77*30203ea5SZixuan Wang unsigned long long get_amd_sev_addr_upperbound(void)
78*30203ea5SZixuan Wang {
79*30203ea5SZixuan Wang 	if (amd_sev_enabled()) {
80*30203ea5SZixuan Wang 		return amd_sev_c_bit_pos - 1;
81*30203ea5SZixuan Wang 	} else {
82*30203ea5SZixuan Wang 		/* Default memory upper bound */
83*30203ea5SZixuan Wang 		return PT_ADDR_UPPER_BOUND_DEFAULT;
84*30203ea5SZixuan Wang 	}
85*30203ea5SZixuan Wang }
86