summaryrefslogtreecommitdiff
path: root/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.asm
blob: 2cc78db374882c91edf0c1a0a6502b4b71b7109b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
;------------------------------------------------------------------------------ ;
; Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
; This program and the accompanying materials
; are licensed and made available under the terms and conditions of the BSD License
; which accompanies this distribution.  The full text of the license may be found at
; http://opensource.org/licenses/bsd-license.php.
;
; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
;
; Module Name:
;
;   ExceptionHandlerAsm.Asm
;
; Abstract:
;
;   x64 CPU Exception Handler
;
; Notes:
;
;------------------------------------------------------------------------------

;
; CommonExceptionHandler()
;
externdef CommonExceptionHandler:near

EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions

data SEGMENT

CommonEntryAddr                dq      CommonInterruptEntry;

.code

Exception0Handle:
    push    0
    jmp     qword ptr [CommonEntryAddr]
Exception1Handle:
    push    1
    jmp     qword ptr [CommonEntryAddr]
Exception2Handle:
    push    2
    jmp     qword ptr [CommonEntryAddr]
Exception3Handle:
    push    3
    jmp     qword ptr [CommonEntryAddr]
Exception4Handle:
    push    4
    jmp     qword ptr [CommonEntryAddr]
Exception5Handle:
    push    5
    jmp     qword ptr [CommonEntryAddr]
Exception6Handle:
    push    6
    jmp     qword ptr [CommonEntryAddr]
Exception7Handle:
    push    7
    jmp     qword ptr [CommonEntryAddr]
Exception8Handle:
    push    8
    jmp     qword ptr [CommonEntryAddr]
Exception9Handle:
    push    9
    jmp     qword ptr [CommonEntryAddr]
Exception10Handle:
    push    10
    jmp     qword ptr [CommonEntryAddr]
Exception11Handle:
    push    11
    jmp     qword ptr [CommonEntryAddr]
Exception12Handle:
    push    12
    jmp     qword ptr [CommonEntryAddr]
Exception13Handle:
    push    13
    jmp     qword ptr [CommonEntryAddr]
Exception14Handle:
    push    14
    jmp     qword ptr [CommonEntryAddr]
Exception15Handle:
    push    15
    jmp     qword ptr [CommonEntryAddr]
Exception16Handle:
    push    16
    jmp     qword ptr [CommonEntryAddr]
Exception17Handle:
    push    17
    jmp     qword ptr [CommonEntryAddr]
Exception18Handle:
    push    18
    jmp     qword ptr [CommonEntryAddr]
Exception19Handle:
    push    19
    jmp     qword ptr [CommonEntryAddr]
Exception20Handle:
    push    20
    jmp     qword ptr [CommonEntryAddr]
Exception21Handle:
    push    21
    jmp     qword ptr [CommonEntryAddr]
Exception22Handle:
    push    22
    jmp     qword ptr [CommonEntryAddr]
Exception23Handle:
    push    23
    jmp     qword ptr [CommonEntryAddr]
Exception24Handle:
    push    24
    jmp     qword ptr [CommonEntryAddr]
Exception25Handle:
    push    25
    jmp     qword ptr [CommonEntryAddr]
Exception26Handle:
    push    26
    jmp     qword ptr [CommonEntryAddr]
Exception27Handle:
    push    27
    jmp     qword ptr [CommonEntryAddr]
Exception28Handle:
    push    28
    jmp     qword ptr [CommonEntryAddr]
Exception29Handle:
    push    29
    jmp     qword ptr [CommonEntryAddr]
Exception30Handle:
    push    30
    jmp     qword ptr [CommonEntryAddr]
Exception31Handle:
    push    31
    jmp     qword ptr [CommonEntryAddr]

;CommonInterruptEntrypoint:
;---------------------------------------;
; _CommonEntry                  ;
;----------------------------------------------------------------------------;
; The follow algorithm is used for the common interrupt routine.
; Entry from each interrupt with a push eax and eax=interrupt number

;---------------------------------------;
; CommonInterruptEntry                  ;
;---------------------------------------;
; The follow algorithm is used for the common interrupt routine.

CommonInterruptEntry PROC PUBLIC  
    cli
    ;
    ; All interrupt handlers are invoked through interrupt gates, so
    ; IF flag automatically cleared at the entry point
    ;
    ;
    ; Calculate vector number
    ;
    xchg    rcx, [rsp] ; get the return address of call, actually, it is the address of vector number.
    cmp     ecx, 32         ; Intel reserved vector for exceptions?
    jae     NoErrorCode
    bt      mErrorCodeFlag, ecx
    jc      @F

NoErrorCode:

    ;
    ; Push a dummy error code on the stack
    ; to maintain coherent stack map
    ;
    push    [rsp]
    mov     qword ptr [rsp + 8], 0
@@:       
    push    rbp
    mov     rbp, rsp

    ;
    ; Stack:
    ; +---------------------+ <-- 16-byte aligned ensured by processor
    ; +    Old SS           +
    ; +---------------------+
    ; +    Old RSP          +
    ; +---------------------+
    ; +    RFlags           +
    ; +---------------------+
    ; +    CS               +
    ; +---------------------+
    ; +    RIP              +
    ; +---------------------+
    ; +    Error Code       +
    ; +---------------------+
    ; + RCX / Vector Number +
    ; +---------------------+
    ; +    RBP              +
    ; +---------------------+ <-- RBP, 16-byte aligned
    ;


    ;
    ; Since here the stack pointer is 16-byte aligned, so
    ; EFI_FX_SAVE_STATE_X64 of EFI_SYSTEM_CONTEXT_x64
    ; is 16-byte aligned
    ;

;; UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
;; UINT64  R8, R9, R10, R11, R12, R13, R14, R15;
    push r15
    push r14
    push r13
    push r12
    push r11
    push r10
    push r9
    push r8
    push rax
    push qword ptr [rbp + 8]   ; RCX
    push rdx
    push rbx
    push qword ptr [rbp + 48]  ; RSP
    push qword ptr [rbp]       ; RBP
    push rsi
    push rdi

;; UINT64  Gs, Fs, Es, Ds, Cs, Ss;  insure high 16 bits of each is zero
    movzx   rax, word ptr [rbp + 56]
    push    rax                      ; for ss
    movzx   rax, word ptr [rbp + 32]
    push    rax                      ; for cs
    mov     rax, ds
    push    rax
    mov     rax, es
    push    rax
    mov     rax, fs
    push    rax
    mov     rax, gs
    push    rax

    mov     [rbp + 8], rcx               ; save vector number

;; UINT64  Rip;
    push    qword ptr [rbp + 24]

;; UINT64  Gdtr[2], Idtr[2];
    xor     rax, rax
    push    rax
    push    rax
    sidt    [rsp]
    xchg    rax, [rsp + 2]
    xchg    rax, [rsp]
    xchg    rax, [rsp + 8]

    xor     rax, rax
    push    rax
    push    rax
    sgdt    [rsp]
    xchg    rax, [rsp + 2]
    xchg    rax, [rsp]
    xchg    rax, [rsp + 8]

;; UINT64  Ldtr, Tr;
    xor     rax, rax
    str     ax
    push    rax
    sldt    ax
    push    rax

;; UINT64  RFlags;
    push    qword ptr [rbp + 40]

;; UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
    mov     rax, cr8
    push    rax
    mov     rax, cr4
    or      rax, 208h
    mov     cr4, rax
    push    rax
    mov     rax, cr3
    push    rax
    mov     rax, cr2
    push    rax
    xor     rax, rax
    push    rax
    mov     rax, cr0
    push    rax

;; UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
    mov     rax, dr7
    push    rax
    mov     rax, dr6
    push    rax
    mov     rax, dr3
    push    rax
    mov     rax, dr2
    push    rax
    mov     rax, dr1
    push    rax
    mov     rax, dr0
    push    rax

;; FX_SAVE_STATE_X64 FxSaveState;
    sub rsp, 512
    mov rdi, rsp
    db 0fh, 0aeh, 07h ;fxsave [rdi]

;; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
    cld

;; UINT32  ExceptionData;
    push    qword ptr [rbp + 16]

;; Prepare parameter and call
    mov     rcx, [rbp + 8]
    mov     rdx, rsp
    ;
    ; Per X64 calling convention, allocate maximum parameter stack space
    ; and make sure RSP is 16-byte aligned
    ;
    sub     rsp, 4 * 8 + 8
    mov     rax, CommonExceptionHandler
    call    rax
    add     rsp, 4 * 8 + 8

    cli
;; UINT64  ExceptionData;
    add     rsp, 8

;; FX_SAVE_STATE_X64 FxSaveState;

    mov rsi, rsp
    db 0fh, 0aeh, 0Eh ; fxrstor [rsi]
    add rsp, 512

;; UINT64  Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
;; Skip restoration of DRx registers to support in-circuit emualators
;; or debuggers set breakpoint in interrupt/exception context
    add     rsp, 8 * 6

;; UINT64  Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
    pop     rax
    mov     cr0, rax
    add     rsp, 8   ; not for Cr1
    pop     rax
    mov     cr2, rax
    pop     rax
    mov     cr3, rax
    pop     rax
    mov     cr4, rax
    pop     rax
    mov     cr8, rax

;; UINT64  RFlags;
    pop     qword ptr [rbp + 40]

;; UINT64  Ldtr, Tr;
;; UINT64  Gdtr[2], Idtr[2];
;; Best not let anyone mess with these particular registers...
    add     rsp, 48

;; UINT64  Rip;
    pop     qword ptr [rbp + 24]

;; UINT64  Gs, Fs, Es, Ds, Cs, Ss;
    pop     rax
    ; mov     gs, rax ; not for gs
    pop     rax
    ; mov     fs, rax ; not for fs
    ; (X64 will not use fs and gs, so we do not restore it)
    pop     rax
    mov     es, rax
    pop     rax
    mov     ds, rax
    pop     qword ptr [rbp + 32]  ; for cs
    pop     qword ptr [rbp + 56]  ; for ss

;; UINT64  Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
;; UINT64  R8, R9, R10, R11, R12, R13, R14, R15;
    pop     rdi
    pop     rsi
    add     rsp, 8               ; not for rbp
    pop     qword ptr [rbp + 48] ; for rsp
    pop     rbx
    pop     rdx
    pop     rcx
    pop     rax
    pop     r8
    pop     r9
    pop     r10
    pop     r11
    pop     r12
    pop     r13
    pop     r14
    pop     r15

    mov     rsp, rbp
    pop     rbp
    add     rsp, 16
    iretq

CommonInterruptEntry ENDP

;-------------------------------------------------------------------------------------
;  GetTemplateAddressMap (&AddressMap);
;-------------------------------------------------------------------------------------
; comments here for definition of address map
GetTemplateAddressMap   PROC
        mov         rax, offset Exception0Handle
        mov         qword ptr [rcx], rax
        mov         qword ptr [rcx+8h], Exception1Handle - Exception0Handle
        ret
GetTemplateAddressMap   ENDP

END