1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * AMD Memory Encryption Support
5 * Copyright (C) 2017 Advanced Micro Devices, Inc.
7 * Author: Tom Lendacky <thomas.lendacky@amd.com>
10 #include <linux/linkage.h>
12 #include <asm/processor-flags.h>
14 #include <asm/asm-offsets.h>
18 SYM_FUNC_START(get_sev_encryption_bit)
21 #ifdef CONFIG_AMD_MEM_ENCRYPT
26 movl $0x80000000, %eax /* CPUID to check the highest leaf */
28 cmpl $0x8000001f, %eax /* See if 0x8000001f is available */
32 * Check for the SEV feature:
33 * CPUID Fn8000_001F[EAX] - Bit 1
34 * CPUID Fn8000_001F[EBX] - Bits 5:0
35 * Pagetable bit position used to indicate encryption
37 movl $0x8000001f, %eax
39 bt $1, %eax /* Check if SEV is available */
42 movl $MSR_AMD64_SEV, %ecx /* Read the SEV MSR */
44 bt $MSR_AMD64_SEV_ENABLED_BIT, %eax /* Check if SEV is active */
48 andl $0x3f, %eax /* Return the encryption bit location */
59 #endif /* CONFIG_AMD_MEM_ENCRYPT */
62 SYM_FUNC_END(get_sev_encryption_bit)
65 * sev_es_req_cpuid - Request a CPUID value from the Hypervisor using
66 * the GHCB MSR protocol
68 * @%eax: Register to request (0=EAX, 1=EBX, 2=ECX, 3=EDX)
69 * @%edx: CPUID Function
71 * Returns 0 in %eax on success, non-zero on failure
72 * %edx returns CPUID value on success
74 SYM_CODE_START_LOCAL(sev_es_req_cpuid)
77 movl $MSR_AMD64_SEV_ES_GHCB, %ecx
79 rep; vmmcall # VMGEXIT
84 andl $0x3ffff000, %ecx # Bits [12-29] MBZ
87 /* Check return code */
92 /* All good - return success */
99 SYM_CODE_END(sev_es_req_cpuid)
101 SYM_CODE_START(startup32_vc_handler)
107 /* Keep CPUID function in %ebx */
110 /* Check if error-code == SVM_EXIT_CPUID */
114 movl $0, %eax # Request CPUID[fn].EAX
115 movl %ebx, %edx # CPUID fn
116 call sev_es_req_cpuid # Call helper
117 testl %eax, %eax # Check return code
119 movl %edx, 12(%esp) # Store result
121 movl $1, %eax # Request CPUID[fn].EBX
122 movl %ebx, %edx # CPUID fn
123 call sev_es_req_cpuid # Call helper
124 testl %eax, %eax # Check return code
126 movl %edx, 8(%esp) # Store result
128 movl $2, %eax # Request CPUID[fn].ECX
129 movl %ebx, %edx # CPUID fn
130 call sev_es_req_cpuid # Call helper
131 testl %eax, %eax # Check return code
133 movl %edx, 4(%esp) # Store result
135 movl $3, %eax # Request CPUID[fn].EDX
136 movl %ebx, %edx # CPUID fn
137 call sev_es_req_cpuid # Call helper
138 testl %eax, %eax # Check return code
140 movl %edx, 0(%esp) # Store result
143 * Sanity check CPUID results from the Hypervisor. See comment in
144 * do_vc_no_ghcb() for more details on why this is necessary.
147 /* Fail if SEV leaf not available in CPUID[0x80000000].EAX */
148 cmpl $0x80000000, %ebx
150 cmpl $0x8000001f, 12(%esp)
155 /* Fail if SEV bit not set in CPUID[0x8000001f].EAX[1] */
156 cmpl $0x8000001f, %ebx
167 /* Remove error code */
170 /* Jump over CPUID instruction */
175 /* Send terminate request to Hypervisor */
178 movl $MSR_AMD64_SEV_ES_GHCB, %ecx
182 /* If request fails, go to hlt loop */
185 SYM_CODE_END(startup32_vc_handler)
189 #include "../../kernel/sev_verify_cbit.S"
193 #ifdef CONFIG_AMD_MEM_ENCRYPT
195 SYM_DATA(sme_me_mask, .quad 0)
196 SYM_DATA(sev_status, .quad 0)
197 SYM_DATA(sev_check_data, .quad 0)