]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/MpInitLib/X64/AmdSev.nasm
8bb1161fa0f77fe4681eaa872e7e8dd844ebf80a
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / X64 / AmdSev.nasm
1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2021, AMD Inc. All rights reserved.<BR>
3 ; SPDX-License-Identifier: BSD-2-Clause-Patent
4 ;
5 ; Module Name:
6 ;
7 ; AmdSev.nasm
8 ;
9 ; Abstract:
10 ;
11 ; This provides helper used by the MpFunc.nasm. If AMD SEV-ES is active
12 ; then helpers perform the additional setups (such as GHCB).
13 ;
14 ;-------------------------------------------------------------------------------
15
16 %define SIZE_4KB 0x1000
17
18 RegisterGhcbGpa:
19 ;
20 ; Register GHCB GPA when SEV-SNP is enabled
21 ;
22 lea edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevSnpIsEnabled)]
23 cmp byte [edi], 1 ; SevSnpIsEnabled
24 jne RegisterGhcbGpaDone
25
26 ; Save the rdi and rsi to used for later comparison
27 push rdi
28 push rsi
29 mov edi, eax
30 mov esi, edx
31 or eax, 18 ; Ghcb registration request
32 wrmsr
33 rep vmmcall
34 rdmsr
35 mov r12, rax
36 and r12, 0fffh
37 cmp r12, 19 ; Ghcb registration response
38 jne GhcbGpaRegisterFailure
39
40 ; Verify that GPA is not changed
41 and eax, 0fffff000h
42 cmp edi, eax
43 jne GhcbGpaRegisterFailure
44 cmp esi, edx
45 jne GhcbGpaRegisterFailure
46 pop rsi
47 pop rdi
48 jmp RegisterGhcbGpaDone
49
50 ;
51 ; Request the guest termination
52 ;
53 GhcbGpaRegisterFailure:
54 xor edx, edx
55 mov eax, 256 ; GHCB terminate
56 wrmsr
57 rep vmmcall
58
59 ; We should not return from the above terminate request, but if we do
60 ; then enter into the hlt loop.
61 DoHltLoop:
62 cli
63 hlt
64 jmp DoHltLoop
65
66 RegisterGhcbGpaDone:
67 OneTimeCallRet RegisterGhcbGpa
68
69 ;
70 ; The function checks whether SEV-ES is enabled, if enabled
71 ; then setup the GHCB page.
72 ;
73 SevEsSetupGhcb:
74 lea edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevEsIsEnabled)]
75 cmp byte [edi], 1 ; SevEsIsEnabled
76 jne SevEsSetupGhcbExit
77
78 ;
79 ; program GHCB
80 ; Each page after the GHCB is a per-CPU page, so the calculation programs
81 ; a GHCB to be every 8KB.
82 ;
83 mov eax, SIZE_4KB
84 shl eax, 1 ; EAX = SIZE_4K * 2
85 mov ecx, ebx
86 mul ecx ; EAX = SIZE_4K * 2 * CpuNumber
87 mov edi, esi
88 add edi, MP_CPU_EXCHANGE_INFO_FIELD (GhcbBase)
89 add rax, qword [edi]
90 mov rdx, rax
91 shr rdx, 32
92 mov rcx, 0xc0010130
93
94 OneTimeCall RegisterGhcbGpa
95
96 wrmsr
97
98 SevEsSetupGhcbExit:
99 OneTimeCallRet SevEsSetupGhcb
100
101 ;
102 ; The function checks whether SEV-ES is enabled, if enabled, use
103 ; the GHCB
104 ;
105 SevEsGetApicId:
106 lea edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevEsIsEnabled)]
107 cmp byte [edi], 1 ; SevEsIsEnabled
108 jne SevEsGetApicIdExit
109
110 ;
111 ; Since we don't have a stack yet, we can't take a #VC
112 ; exception. Use the GHCB protocol to perform the CPUID
113 ; calls.
114 ;
115 mov rcx, 0xc0010130
116 rdmsr
117 shl rdx, 32
118 or rax, rdx
119 mov rdi, rax ; RDI now holds the original GHCB GPA
120
121 ;
122 ; For SEV-SNP, the recommended handling for getting the x2APIC ID
123 ; would be to use the SNP CPUID table to fetch CPUID.00H:EAX and
124 ; CPUID:0BH:EBX[15:0] instead of the GHCB MSR protocol vmgexits
125 ; below.
126 ;
127 ; To avoid the unecessary ugliness to accomplish that here, the BSP
128 ; has performed these checks in advance (where #VC handler handles
129 ; the CPUID table lookups automatically) and cached them in a flag
130 ; so those checks can be skipped here.
131 ;
132 mov eax, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevSnpIsEnabled)]
133 cmp al, 1
134 jne CheckExtTopoAvail
135
136 ;
137 ; Even with SEV-SNP, the actual x2APIC ID in CPUID.0BH:EDX
138 ; fetched from the hypervisor the same way SEV-ES does it.
139 ;
140 mov eax, [esi + MP_CPU_EXCHANGE_INFO_FIELD (ExtTopoAvail)]
141 cmp al, 1
142 je GetApicIdSevEs
143 ; The 8-bit APIC ID fallback is also the same as with SEV-ES
144 jmp NoX2ApicSevEs
145
146 CheckExtTopoAvail:
147 mov rdx, 0 ; CPUID function 0
148 mov rax, 0 ; RAX register requested
149 or rax, 4
150 wrmsr
151 rep vmmcall
152 rdmsr
153 cmp edx, 0bh
154 jb NoX2ApicSevEs ; CPUID level below CPUID_EXTENDED_TOPOLOGY
155
156 mov rdx, 0bh ; CPUID function 0x0b
157 mov rax, 040000000h ; RBX register requested
158 or rax, 4
159 wrmsr
160 rep vmmcall
161 rdmsr
162 test edx, 0ffffh
163 jz NoX2ApicSevEs ; CPUID.0BH:EBX[15:0] is zero
164
165 GetApicIdSevEs:
166 mov rdx, 0bh ; CPUID function 0x0b
167 mov rax, 0c0000000h ; RDX register requested
168 or rax, 4
169 wrmsr
170 rep vmmcall
171 rdmsr
172
173 ; Processor is x2APIC capable; 32-bit x2APIC ID is now in EDX
174 jmp RestoreGhcb
175
176 NoX2ApicSevEs:
177 ; Processor is not x2APIC capable, so get 8-bit APIC ID
178 mov rdx, 1 ; CPUID function 1
179 mov rax, 040000000h ; RBX register requested
180 or rax, 4
181 wrmsr
182 rep vmmcall
183 rdmsr
184 shr edx, 24
185
186 RestoreGhcb:
187 mov rbx, rdx ; Save x2APIC/APIC ID
188
189 mov rdx, rdi ; RDI holds the saved GHCB GPA
190 shr rdx, 32
191 mov eax, edi
192 wrmsr
193
194 mov rdx, rbx
195
196 ; x2APIC ID or APIC ID is in EDX
197 jmp GetProcessorNumber
198
199 SevEsGetApicIdExit:
200 OneTimeCallRet SevEsGetApicId