]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.S
cd101475a7c11adde5b1d9ffa25341eeb73709f8
[mirror_edk2.git] / UefiCpuPkg / Library / CpuExceptionHandlerLib / X64 / ExceptionHandlerAsm.S
1 #------------------------------------------------------------------------------ ;
2 # Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
3 # This program and the accompanying materials
4 # are licensed and made available under the terms and conditions of the BSD License
5 # which accompanies this distribution. The full text of the license may be found at
6 # http://opensource.org/licenses/bsd-license.php.
7 #
8 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10 #
11 # Module Name:
12 #
13 # ExceptionHandlerAsm.S
14 #
15 # Abstract:
16 #
17 # x64 CPU Exception Handler
18 #
19 # Notes:
20 #
21 #------------------------------------------------------------------------------
22
23
24 #EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions
25
26 ASM_GLOBAL ASM_PFX(CommonExceptionHandler)
27 ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
28
29
30 .text
31
32 #
33 # point to the external interrupt vector table
34 #
35 Exception0Handle:
36 pushq $0
37 jmp ASM_PFX(CommonInterruptEntry)
38 Exception1Handle:
39 pushq $1
40 jmp ASM_PFX(CommonInterruptEntry)
41 Exception2Handle:
42 pushq $2
43 jmp ASM_PFX(CommonInterruptEntry)
44 Exception3Handle:
45 pushq $3
46 jmp ASM_PFX(CommonInterruptEntry)
47 Exception4Handle:
48 pushq $4
49 jmp ASM_PFX(CommonInterruptEntry)
50 Exception5Handle:
51 pushq $5
52 jmp ASM_PFX(CommonInterruptEntry)
53 Exception6Handle:
54 pushq $6
55 jmp ASM_PFX(CommonInterruptEntry)
56 Exception7Handle:
57 pushq $7
58 jmp ASM_PFX(CommonInterruptEntry)
59 Exception8Handle:
60 pushq $8
61 jmp ASM_PFX(CommonInterruptEntry)
62 Exception9Handle:
63 pushq $9
64 jmp ASM_PFX(CommonInterruptEntry)
65 Exception10Handle:
66 pushq $10
67 jmp ASM_PFX(CommonInterruptEntry)
68 Exception11Handle:
69 pushq $11
70 jmp ASM_PFX(CommonInterruptEntry)
71 Exception12Handle:
72 pushq $12
73 jmp ASM_PFX(CommonInterruptEntry)
74 Exception13Handle:
75 pushq $13
76 jmp ASM_PFX(CommonInterruptEntry)
77 Exception14Handle:
78 pushq $14
79 jmp ASM_PFX(CommonInterruptEntry)
80 Exception15Handle:
81 pushq $15
82 jmp ASM_PFX(CommonInterruptEntry)
83 Exception16Handle:
84 pushq $16
85 jmp ASM_PFX(CommonInterruptEntry)
86 Exception17Handle:
87 pushq $17
88 jmp ASM_PFX(CommonInterruptEntry)
89 Exception18Handle:
90 pushq $18
91 jmp ASM_PFX(CommonInterruptEntry)
92 Exception19Handle:
93 pushq $19
94 jmp ASM_PFX(CommonInterruptEntry)
95 Exception20Handle:
96 pushq $20
97 jmp ASM_PFX(CommonInterruptEntry)
98 Exception21Handle:
99 pushq $21
100 jmp ASM_PFX(CommonInterruptEntry)
101 Exception22Handle:
102 pushq $22
103 jmp ASM_PFX(CommonInterruptEntry)
104 Exception23Handle:
105 pushq $23
106 jmp ASM_PFX(CommonInterruptEntry)
107 Exception24Handle:
108 pushq $24
109 jmp ASM_PFX(CommonInterruptEntry)
110 Exception25Handle:
111 pushq $25
112 jmp ASM_PFX(CommonInterruptEntry)
113 Exception26Handle:
114 pushq $26
115 jmp ASM_PFX(CommonInterruptEntry)
116 Exception27Handle:
117 pushq $27
118 jmp ASM_PFX(CommonInterruptEntry)
119 Exception28Handle:
120 pushq $28
121 jmp ASM_PFX(CommonInterruptEntry)
122 Exception29Handle:
123 pushq $29
124 jmp ASM_PFX(CommonInterruptEntry)
125 Exception30Handle:
126 pushq $30
127 jmp ASM_PFX(CommonInterruptEntry)
128 Exception31Handle:
129 pushq $31
130 jmp ASM_PFX(CommonInterruptEntry)
131
132
133 #---------------------------------------;
134 # CommonInterruptEntry ;
135 #---------------------------------------;
136 # The follow algorithm is used for the common interrupt routine.
137
138 ASM_GLOBAL ASM_PFX(CommonInterruptEntry)
139 ASM_PFX(CommonInterruptEntry):
140 cli
141 #
142 # All interrupt handlers are invoked through interrupt gates, so
143 # IF flag automatically cleared at the entry point
144 #
145 #
146 # Calculate vector number
147 #
148 xchgq (%rsp), %rcx # get the return address of call, actually, it is the address of vector number.
149 cmp $32, %ecx # Intel reserved vector for exceptions?
150 jae NoErrorCode
151 pushq %rax
152 leaq ASM_PFX(mErrorCodeFlag)(%rip), %rax
153 bt %ecx, (%rax)
154 popq %rax
155 jc CommonInterruptEntry_al_0000
156
157 NoErrorCode:
158
159 #
160 # Push a dummy error code on the stack
161 # to maintain coherent stack map
162 #
163 pushq (%rsp)
164 movq $0, 8(%rsp)
165 CommonInterruptEntry_al_0000:
166 pushq %rbp
167 movq %rsp, %rbp
168
169 #
170 # Stack:
171 # +---------------------+ <-- 16-byte aligned ensured by processor
172 # + Old SS +
173 # +---------------------+
174 # + Old RSP +
175 # +---------------------+
176 # + RFlags +
177 # +---------------------+
178 # + CS +
179 # +---------------------+
180 # + RIP +
181 # +---------------------+
182 # + Error Code +
183 # +---------------------+
184 # + RCX / Vector Number +
185 # +---------------------+
186 # + RBP +
187 # +---------------------+ <-- RBP, 16-byte aligned
188 #
189
190
191 #
192 # Since here the stack pointer is 16-byte aligned, so
193 # EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
194 # is 16-byte aligned
195 #
196
197 #; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
198 #; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
199 pushq %r15
200 pushq %r14
201 pushq %r13
202 pushq %r12
203 pushq %r11
204 pushq %r10
205 pushq %r9
206 pushq %r8
207 pushq %rax
208 pushq 8(%rbp) # RCX
209 pushq %rdx
210 pushq %rbx
211 pushq 48(%rbp) # RSP
212 pushq (%rbp) # RBP
213 pushq %rsi
214 pushq %rdi
215
216 #; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
217 movzwq 56(%rbp), %rax
218 pushq %rax # for ss
219 movzwq 32(%rbp), %rax
220 pushq %rax # for cs
221 movl %ds, %eax
222 pushq %rax
223 movl %es, %eax
224 pushq %rax
225 movl %fs, %eax
226 pushq %rax
227 movl %gs, %eax
228 pushq %rax
229
230 movq %rcx, 8(%rbp) # save vector number
231
232 #; UINT64 Rip;
233 pushq 24(%rbp)
234
235 #; UINT64 Gdtr[2], Idtr[2];
236 xorq %rax, %rax
237 pushq %rax
238 pushq %rax
239 sidt (%rsp)
240 xchgq 2(%rsp), %rax
241 xchgq (%rsp), %rax
242 xchgq 8(%rsp), %rax
243
244 xorq %rax, %rax
245 pushq %rax
246 pushq %rax
247 sgdt (%rsp)
248 xchgq 2(%rsp), %rax
249 xchgq (%rsp), %rax
250 xchgq 8(%rsp), %rax
251
252 #; UINT64 Ldtr, Tr;
253 xorq %rax, %rax
254 str %ax
255 pushq %rax
256 sldt %ax
257 pushq %rax
258
259 #; UINT64 RFlags;
260 pushq 40(%rbp)
261
262 #; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
263 movq %cr8, %rax
264 pushq %rax
265 movq %cr4, %rax
266 orq $0x208, %rax
267 movq %rax, %cr4
268 pushq %rax
269 mov %cr3, %rax
270 pushq %rax
271 mov %cr2, %rax
272 pushq %rax
273 xorq %rax, %rax
274 pushq %rax
275 mov %cr0, %rax
276 pushq %rax
277
278 #; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
279 movq %dr7, %rax
280 pushq %rax
281 movq %dr6, %rax
282 pushq %rax
283 movq %dr3, %rax
284 pushq %rax
285 movq %dr2, %rax
286 pushq %rax
287 movq %dr1, %rax
288 pushq %rax
289 movq %dr0, %rax
290 pushq %rax
291
292 #; FX_SAVE_STATE_X64 FxSaveState;
293 subq $512, %rsp
294 movq %rsp, %rdi
295 .byte 0x0f, 0x0ae, 0x07 #fxsave [rdi]
296
297 #; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
298 cld
299
300 #; UINT32 ExceptionData;
301 pushq 16(%rbp)
302
303 #; Prepare parameter and call
304 mov 8(%rbp), %rcx
305 mov %rsp, %rdx
306 #
307 # Per X64 calling convention, allocate maximum parameter stack space
308 # and make sure RSP is 16-byte aligned
309 #
310 subq $40, %rsp
311 call ASM_PFX(CommonExceptionHandler)
312 addq $40, %rsp
313
314 cli
315 #; UINT64 ExceptionData;
316 addq $8, %rsp
317
318 #; FX_SAVE_STATE_X64 FxSaveState;
319
320 movq %rsp, %rsi
321 .byte 0x0f, 0x0ae, 0x0E # fxrstor [rsi]
322 addq $512, %rsp
323
324 #; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
325 #; Skip restoration of DRx registers to support in-circuit emualators
326 #; or debuggers set breakpoint in interrupt/exception context
327 addq $48, %rsp
328
329 #; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
330 popq %rax
331 movq %rax, %cr0
332 addq $8, %rsp # not for Cr1
333 popq %rax
334 movq %rax, %cr2
335 popq %rax
336 movq %rax, %cr3
337 popq %rax
338 movq %rax, %cr4
339 popq %rax
340 movq %rax, %cr8
341
342 #; UINT64 RFlags;
343 popq 40(%rbp)
344
345 #; UINT64 Ldtr, Tr;
346 #; UINT64 Gdtr[2], Idtr[2];
347 #; Best not let anyone mess with these particular registers...
348 addq $48, %rsp
349
350 #; UINT64 Rip;
351 popq 24(%rbp)
352
353 #; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
354 popq %rax
355 # mov %rax, %gs ; not for gs
356 popq %rax
357 # mov %rax, %fs ; not for fs
358 # (X64 will not use fs and gs, so we do not restore it)
359 popq %rax
360 movl %eax, %es
361 popq %rax
362 movl %eax, %ds
363 popq 32(%rbp) # for cs
364 popq 56(%rbp) # for ss
365
366 #; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
367 #; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
368 popq %rdi
369 popq %rsi
370 addq $8, %rsp # not for rbp
371 popq 48(%rbp) # for rsp
372 popq %rbx
373 popq %rdx
374 popq %rcx
375 popq %rax
376 popq %r8
377 popq %r9
378 popq %r10
379 popq %r11
380 popq %r12
381 popq %r13
382 popq %r14
383 popq %r15
384
385 movq %rbp, %rsp
386 popq %rbp
387 addq $16, %rsp
388 iretq
389
390
391 #-------------------------------------------------------------------------------------
392 # AsmGetAddressMap (&AddressMap);
393 #-------------------------------------------------------------------------------------
394 # comments here for definition of address map
395 ASM_GLOBAL ASM_PFX(GetTemplateAddressMap)
396 ASM_PFX(GetTemplateAddressMap):
397
398 movabsq $Exception0Handle, %rax
399 movq %rax, (%rcx)
400 movq $(Exception1Handle - Exception0Handle), 0x08(%rcx)
401
402 ret
403
404 #END
405
406