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