c1f23d63 |
1 | ;******************************************************************************\r |
2 | ;*\r |
3 | ;* Copyright (c) 2006, Intel Corporation \r |
4 | ;* All rights reserved. This program and the accompanying materials \r |
5 | ;* are licensed and made available under the terms and conditions of the BSD License \r |
6 | ;* which accompanies this distribution. The full text of the license may be found at \r |
7 | ;* http://opensource.org/licenses/bsd-license.php \r |
8 | ;* \r |
9 | ;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r |
10 | ;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r |
11 | ;*\r |
12 | ;******************************************************************************\r |
13 | \r |
14 | EXCPT64_DIVIDE_ERROR EQU 0\r |
15 | EXCPT64_DEBUG EQU 1\r |
16 | EXCPT64_NMI EQU 2\r |
17 | EXCPT64_BREAKPOINT EQU 3\r |
18 | EXCPT64_OVERFLOW EQU 4\r |
19 | EXCPT64_BOUND EQU 5\r |
20 | EXCPT64_INVALID_OPCODE EQU 6\r |
21 | EXCPT64_DOUBLE_FAULT EQU 8\r |
22 | EXCPT64_INVALID_TSS EQU 10\r |
23 | EXCPT64_SEG_NOT_PRESENT EQU 11\r |
24 | EXCPT64_STACK_FAULT EQU 12\r |
25 | EXCPT64_GP_FAULT EQU 13\r |
26 | EXCPT64_PAGE_FAULT EQU 14\r |
27 | EXCPT64_FP_ERROR EQU 16\r |
28 | EXCPT64_ALIGNMENT_CHECK EQU 17\r |
29 | EXCPT64_MACHINE_CHECK EQU 18\r |
30 | EXCPT64_SIMD EQU 19\r |
31 | \r |
32 | FXSTOR_FLAG EQU 01000000h ; bit cpuid 24 of feature flags\r |
33 | \r |
34 | ;; The FXSTOR and FXRSTOR commands are used for saving and restoring the x87,\r |
35 | ;; MMX, SSE, SSE2, etc registers. The initialization of the debugsupport driver\r |
36 | ;; MUST check the CPUID feature flags to see that these instructions are available\r |
37 | ;; and fail to init if they are not.\r |
38 | \r |
39 | ;; fxstor [rdi]\r |
40 | FXSTOR_RDI MACRO\r |
41 | db 0fh, 0aeh, 00000111y ; mod = 00, reg/op = 000, r/m = 111 = [rdi]\r |
42 | ENDM\r |
43 | \r |
44 | ;; fxrstor [rsi]\r |
45 | FXRSTOR_RSI MACRO\r |
46 | db 0fh, 0aeh, 00001110y ; mod = 00, reg/op = 001, r/m = 110 = [rsi]\r |
47 | ENDM\r |
48 | \r |
49 | data SEGMENT\r |
50 | \r |
51 | public OrigVector, InterruptEntryStub, StubSize, CommonIdtEntry, FxStorSupport\r |
52 | \r |
53 | StubSize dd InterruptEntryStubEnd - InterruptEntryStub\r |
54 | AppRsp dq 1111111111111111h ; ?\r |
55 | DebugRsp dq 2222222222222222h ; ?\r |
56 | ExtraPush dq 3333333333333333h ; ?\r |
57 | ExceptData dq 4444444444444444h ; ?\r |
58 | Rflags dq 5555555555555555h ; ?\r |
59 | OrigVector dq 6666666666666666h ; ?\r |
60 | \r |
61 | ;; The declarations below define the memory region that will be used for the debug stack.\r |
62 | ;; The context record will be built by pushing register values onto this stack.\r |
63 | ;; It is imparitive that alignment be carefully managed, since the FXSTOR and\r |
64 | ;; FXRSTOR instructions will GP fault if their memory operand is not 16 byte aligned.\r |
65 | ;;\r |
66 | ;; The stub will switch stacks from the application stack to the debuger stack\r |
67 | ;; and pushes the exception number.\r |
68 | ;;\r |
69 | ;; Then we building the context record on the stack. Since the stack grows down,\r |
70 | ;; we push the fields of the context record from the back to the front. There\r |
71 | ;; are 336 bytes of stack used prior allocating the 512 bytes of stack to be\r |
72 | ;; used as the memory buffer for the fxstor instruction. Therefore address of\r |
73 | ;; the buffer used for the FXSTOR instruction is &Eax - 336 - 512, which\r |
74 | ;; must be 16 byte aligned.\r |
75 | ;;\r |
76 | ;; We carefully locate the stack to make this happen.\r |
77 | ;;\r |
78 | ;; For reference, the context structure looks like this:\r |
79 | ;; struct {\r |
80 | ;; UINT64 ExceptionData;\r |
81 | ;; FX_SAVE_STATE_X64 FxSaveState; // 512 bytes, must be 16 byte aligned\r |
82 | ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r |
83 | ;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r |
84 | ;; UINT64 RFlags;\r |
85 | ;; UINT64 Ldtr, Tr;\r |
86 | ;; UINT64 Gdtr[2], Idtr[2];\r |
87 | ;; UINT64 Rip;\r |
88 | ;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r |
89 | ;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r |
90 | ;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r |
91 | ;; } SYSTEM_CONTEXT_X64; // 64 bit system context record\r |
92 | \r |
93 | align 16\r |
94 | DebugStackEnd db "DbgStkEnd >>>>>>" ;; 16 byte long string - must be 16 bytes to preserve alignment\r |
95 | dd 1ffch dup (000000000h) ;; 32K should be enough stack\r |
96 | ;; This allocation is coocked to insure \r |
97 | ;; that the the buffer for the FXSTORE instruction\r |
98 | ;; will be 16 byte aligned also.\r |
99 | ;;\r |
100 | ExceptionNumber dq ? ;; first entry will be the vector number pushed by the stub\r |
101 | \r |
102 | DebugStackBegin db "<<<< DbgStkBegin" ;; initial debug ESP == DebugStackBegin, set in stub\r |
103 | \r |
104 | data ENDS\r |
105 | \r |
106 | text SEGMENT\r |
107 | \r |
108 | externdef InterruptDistrubutionHub:near\r |
109 | \r |
110 | ;------------------------------------------------------------------------------\r |
111 | ; VOID\r |
112 | ; EfiWbinvd (\r |
113 | ; VOID\r |
114 | ; )\r |
115 | ;\r |
116 | ; Abstract: Writeback and invalidate cache\r |
117 | ;\r |
118 | EfiWbinvd PROC PUBLIC\r |
119 | wbinvd\r |
120 | ret\r |
121 | EfiWbinvd ENDP\r |
122 | \r |
123 | ;------------------------------------------------------------------------------\r |
124 | ; BOOLEAN\r |
125 | ; FxStorSupport (\r |
126 | ; void\r |
127 | ; )\r |
128 | ;\r |
129 | ; Abstract: Returns TRUE if FxStor instructions are supported\r |
130 | ;\r |
131 | FxStorSupport PROC PUBLIC\r |
132 | \r |
133 | ;\r |
134 | ; cpuid corrupts rbx which must be preserved per the C calling convention\r |
135 | ;\r |
136 | push rbx\r |
137 | mov rax, 1\r |
138 | cpuid\r |
139 | mov eax, edx\r |
140 | and rax, FXSTOR_FLAG\r |
141 | shr rax, 24\r |
142 | pop rbx\r |
143 | ret\r |
144 | FxStorSupport ENDP\r |
145 | \r |
146 | \r |
147 | ;------------------------------------------------------------------------------\r |
148 | ; DESCRIPTOR *\r |
149 | ; GetIdtr (\r |
150 | ; void\r |
151 | ; )\r |
152 | ;\r |
153 | ; Abstract: Returns physical address of IDTR\r |
154 | ;\r |
155 | GetIdtr PROC PUBLIC\r |
156 | push rbp\r |
157 | mov rbp, rsp\r |
158 | \r |
159 | sidt QWORD PTR [rbp - 0ah]\r |
160 | mov rax, QWORD PTR [rbp - 8h]\r |
161 | \r |
162 | mov rsp, rbp\r |
163 | pop rbp\r |
164 | ret\r |
165 | GetIdtr ENDP\r |
166 | \r |
167 | \r |
168 | ;------------------------------------------------------------------------------\r |
169 | ; BOOLEAN\r |
170 | ; WriteInterruptFlag (\r |
171 | ; BOOLEAN NewState // rcx\r |
172 | ; )\r |
173 | ;\r |
174 | ; Abstract: Programs interrupt flag to the requested state and returns previous\r |
175 | ; state.\r |
176 | ;\r |
177 | WriteInterruptFlag PROC PUBLIC\r |
178 | \r |
179 | pushfq\r |
180 | pop rax\r |
181 | and rax, 200h\r |
182 | shr rax, 9\r |
183 | cmp rcx, 0\r |
184 | jnz EnableIF\r |
185 | cli\r |
186 | ret\r |
187 | EnableIF:\r |
188 | sti\r |
189 | ret\r |
190 | \r |
191 | WriteInterruptFlag ENDP\r |
192 | \r |
193 | \r |
194 | \r |
195 | ;------------------------------------------------------------------------------\r |
196 | ; void\r |
197 | ; Vect2Desc (\r |
198 | ; DESCRIPTOR * DestDesc, // rcx\r |
199 | ; void (*Vector) (void) // rdx\r |
200 | ; )\r |
201 | ;\r |
202 | ; Abstract: Encodes an IDT descriptor with the given physical address\r |
203 | ;\r |
204 | Vect2Desc PROC PUBLIC\r |
205 | \r |
206 | mov rax, rdx\r |
207 | mov word ptr [rcx], ax ; write bits 15..0 of offset\r |
208 | mov dx, cs\r |
209 | mov word ptr [rcx+2], dx ; SYS_CODE_SEL from GDT\r |
210 | mov word ptr [rcx+4], 0e00h OR 8000h ; type = 386 interrupt gate, present\r |
211 | shr rax, 16\r |
212 | mov word ptr [rcx+6], ax ; write bits 31..16 of offset\r |
213 | shr rax, 16\r |
214 | mov dword ptr [rcx+8], eax ; write bits 63..32 of offset\r |
215 | \r |
216 | ret\r |
217 | \r |
218 | Vect2Desc ENDP\r |
219 | \r |
220 | \r |
221 | \r |
222 | ;------------------------------------------------------------------------------\r |
223 | ; InterruptEntryStub\r |
224 | ;\r |
225 | ; Abstract: This code is not a function, but is a small piece of code that is\r |
226 | ; copied and fixed up once for each IDT entry that is hooked.\r |
227 | ;\r |
228 | InterruptEntryStub::\r |
229 | push 0 ; push vector number - will be modified before installed\r |
230 | db 0e9h ; jump rel32\r |
231 | dd 0 ; fixed up to relative address of CommonIdtEntry\r |
232 | InterruptEntryStubEnd:\r |
233 | \r |
234 | \r |
235 | \r |
236 | ;------------------------------------------------------------------------------\r |
237 | ; CommonIdtEntry\r |
238 | ;\r |
239 | ; Abstract: This code is not a function, but is the common part for all IDT\r |
240 | ; vectors.\r |
241 | ;\r |
242 | CommonIdtEntry::\r |
243 | ;;\r |
244 | ;; At this point, the stub has saved the current application stack esp into AppRsp\r |
245 | ;; and switched stacks to the debug stack, where it pushed the vector number\r |
246 | ;;\r |
247 | ;; The application stack looks like this:\r |
248 | ;;\r |
249 | ;; ...\r |
250 | ;; (last application stack entry)\r |
251 | ;; [16 bytes alignment, do not care it]\r |
252 | ;; SS from interrupted task\r |
253 | ;; RSP from interrupted task\r |
254 | ;; rflags from interrupted task\r |
255 | ;; CS from interrupted task\r |
256 | ;; RIP from interrupted task\r |
257 | ;; Error code <-------------------- Only present for some exeption types\r |
258 | ;;\r |
259 | ;; Vector Number <----------------- pushed in our IDT Entry\r |
260 | ;;\r |
261 | \r |
262 | \r |
263 | ;; The stub switched us to the debug stack and pushed the interrupt number.\r |
264 | ;;\r |
265 | ;; Next, construct the context record. It will be build on the debug stack by\r |
266 | ;; pushing the registers in the correct order so as to create the context structure\r |
267 | ;; on the debug stack. The context record must be built from the end back to the\r |
268 | ;; beginning because the stack grows down...\r |
269 | ;\r |
270 | ;; For reference, the context record looks like this:\r |
271 | ;;\r |
272 | ;; typedef\r |
273 | ;; struct {\r |
274 | ;; UINT64 ExceptionData;\r |
275 | ;; FX_SAVE_STATE_X64 FxSaveState;\r |
276 | ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r |
277 | ;; UINT64 Cr0, Cr2, Cr3, Cr4, Cr8;\r |
278 | ;; UINT64 RFlags;\r |
279 | ;; UINT64 Ldtr, Tr;\r |
280 | ;; UINT64 Gdtr[2], Idtr[2];\r |
281 | ;; UINT64 Rip;\r |
282 | ;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r |
283 | ;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r |
284 | ;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r |
285 | ;; } SYSTEM_CONTEXT_X64; // 64 bit system context record\r |
286 | \r |
287 | ;; NOTE: we save rsp here to prevent compiler put rip reference cause error AppRsp\r |
288 | push rax\r |
289 | mov rax, qword ptr [rsp][8] ; save vector number\r |
290 | mov ExceptionNumber, rax ; save vector number\r |
291 | pop rax\r |
292 | add rsp, 8 ; pop vector number\r |
293 | mov AppRsp, rsp ; save stack top\r |
294 | mov rsp, offset DebugStackBegin ; switch to debugger stack\r |
295 | sub rsp, 8 ; leave space for vector number\r |
296 | \r |
297 | ;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r |
298 | ;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r |
299 | push r15\r |
300 | push r14\r |
301 | push r13\r |
302 | push r12\r |
303 | push r11\r |
304 | push r10\r |
305 | push r9\r |
306 | push r8\r |
307 | push rax\r |
308 | push rcx\r |
309 | push rdx\r |
310 | push rbx\r |
311 | push rsp\r |
312 | push rbp\r |
313 | push rsi\r |
314 | push rdi\r |
315 | \r |
316 | ;; Save interrupt state rflags register...\r |
317 | pushfq\r |
318 | pop rax\r |
319 | mov qword ptr Rflags, rax\r |
320 | \r |
321 | ;; We need to determine if any extra data was pushed by the exception, and if so, save it\r |
322 | ;; To do this, we check the exception number pushed by the stub, and cache the\r |
323 | ;; result in a variable since we'll need this again.\r |
324 | cmp ExceptionNumber, EXCPT64_DOUBLE_FAULT\r |
325 | jz ExtraPushOne\r |
326 | cmp ExceptionNumber, EXCPT64_INVALID_TSS\r |
327 | jz ExtraPushOne\r |
328 | cmp ExceptionNumber, EXCPT64_SEG_NOT_PRESENT\r |
329 | jz ExtraPushOne\r |
330 | cmp ExceptionNumber, EXCPT64_STACK_FAULT\r |
331 | jz ExtraPushOne\r |
332 | cmp ExceptionNumber, EXCPT64_GP_FAULT\r |
333 | jz ExtraPushOne\r |
334 | cmp ExceptionNumber, EXCPT64_PAGE_FAULT\r |
335 | jz ExtraPushOne\r |
336 | cmp ExceptionNumber, EXCPT64_ALIGNMENT_CHECK\r |
337 | jz ExtraPushOne\r |
338 | mov ExtraPush, 0\r |
339 | mov ExceptData, 0\r |
340 | jmp ExtraPushDone\r |
341 | ExtraPushOne:\r |
342 | mov ExtraPush, 1\r |
343 | \r |
344 | ;; If there's some extra data, save it also, and modify the saved AppRsp to effectively\r |
345 | ;; pop this value off the application's stack.\r |
346 | mov rax, AppRsp\r |
347 | mov rbx, [rax]\r |
348 | mov ExceptData, rbx\r |
349 | add rax, 8\r |
350 | mov AppRsp, rax\r |
351 | \r |
352 | ExtraPushDone:\r |
353 | \r |
354 | ;; The "push" above pushed the debug stack rsp. Since what we're actually doing\r |
355 | ;; is building the context record on the debug stack, we need to save the pushed\r |
356 | ;; debug RSP, and replace it with the application's last stack entry...\r |
357 | mov rax, [rsp + 24]\r |
358 | mov DebugRsp, rax\r |
359 | mov rax, AppRsp\r |
360 | add rax, 40\r |
361 | ; application stack has ss, rsp, rflags, cs, & rip, so\r |
362 | ; last actual application stack entry is\r |
363 | ; 40 bytes into the application stack.\r |
364 | mov [rsp + 24], rax\r |
365 | \r |
366 | ;; continue building context record\r |
367 | ;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero\r |
368 | mov rax, ss\r |
369 | push rax\r |
370 | \r |
371 | ; CS from application is one entry back in application stack\r |
372 | mov rax, AppRsp\r |
373 | movzx rax, word ptr [rax + 8]\r |
374 | push rax\r |
375 | \r |
376 | mov rax, ds\r |
377 | push rax\r |
378 | mov rax, es\r |
379 | push rax\r |
380 | mov rax, fs\r |
381 | push rax\r |
382 | mov rax, gs\r |
383 | push rax\r |
384 | \r |
385 | ;; UINT64 Rip;\r |
386 | ; Rip from application is on top of application stack\r |
387 | mov rax, AppRsp\r |
388 | push qword ptr [rax]\r |
389 | \r |
390 | ;; UINT64 Gdtr[2], Idtr[2];\r |
391 | push 0\r |
392 | push 0\r |
393 | sidt fword ptr [rsp]\r |
394 | push 0\r |
395 | push 0\r |
396 | sgdt fword ptr [rsp]\r |
397 | \r |
398 | ;; UINT64 Ldtr, Tr;\r |
399 | xor rax, rax\r |
400 | str ax\r |
401 | push rax\r |
402 | sldt ax\r |
403 | push rax\r |
404 | \r |
405 | ;; UINT64 RFlags;\r |
406 | ;; Rflags from application is two entries back in application stack\r |
407 | mov rax, AppRsp\r |
408 | push qword ptr [rax + 16]\r |
409 | \r |
410 | ;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r |
411 | ;; insure FXSAVE/FXRSTOR is enabled in CR4...\r |
412 | ;; ... while we're at it, make sure DE is also enabled...\r |
413 | mov rax, cr8\r |
414 | push rax\r |
415 | mov rax, cr4\r |
416 | or rax, 208h\r |
417 | mov cr4, rax\r |
418 | push rax\r |
419 | mov rax, cr3\r |
420 | push rax\r |
421 | mov rax, cr2\r |
422 | push rax\r |
423 | push 0\r |
424 | mov rax, cr0\r |
425 | push rax\r |
426 | \r |
427 | ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r |
428 | mov rax, dr7\r |
429 | push rax\r |
430 | ;; clear Dr7 while executing debugger itself\r |
431 | xor rax, rax\r |
432 | mov dr7, rax\r |
433 | \r |
434 | mov rax, dr6\r |
435 | push rax\r |
436 | ;; insure all status bits in dr6 are clear...\r |
437 | xor rax, rax\r |
438 | mov dr6, rax\r |
439 | \r |
440 | mov rax, dr3\r |
441 | push rax\r |
442 | mov rax, dr2\r |
443 | push rax\r |
444 | mov rax, dr1\r |
445 | push rax\r |
446 | mov rax, dr0\r |
447 | push rax\r |
448 | \r |
449 | ;; FX_SAVE_STATE_X64 FxSaveState;\r |
450 | sub rsp, 512\r |
451 | mov rdi, rsp\r |
452 | ; IMPORTANT!! The debug stack has been carefully constructed to\r |
453 | ; insure that rsp and rdi are 16 byte aligned when we get here.\r |
454 | ; They MUST be. If they are not, a GP fault will occur.\r |
455 | FXSTOR_RDI\r |
456 | \r |
457 | ;; UINT64 ExceptionData;\r |
458 | mov rax, ExceptData\r |
459 | push rax\r |
460 | \r |
461 | ; call to C code which will in turn call registered handler\r |
462 | ; pass in the vector number\r |
463 | mov rdx, rsp\r |
464 | mov rcx, ExceptionNumber\r |
465 | sub rsp, 40\r |
466 | call InterruptDistrubutionHub\r |
467 | add rsp, 40\r |
468 | \r |
469 | ; restore context...\r |
470 | ;; UINT64 ExceptionData;\r |
471 | add rsp, 8\r |
472 | \r |
473 | ;; FX_SAVE_STATE_X64 FxSaveState;\r |
474 | mov rsi, rsp\r |
475 | FXRSTOR_RSI\r |
476 | add rsp, 512\r |
477 | \r |
478 | ;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r |
479 | pop rax\r |
480 | mov dr0, rax\r |
481 | pop rax\r |
482 | mov dr1, rax\r |
483 | pop rax\r |
484 | mov dr2, rax\r |
485 | pop rax\r |
486 | mov dr3, rax\r |
487 | ;; skip restore of dr6. We cleared dr6 during the context save.\r |
488 | add rsp, 8\r |
489 | pop rax\r |
490 | mov dr7, rax\r |
491 | \r |
492 | ;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;\r |
493 | pop rax\r |
494 | mov cr0, rax\r |
495 | add rsp, 8\r |
496 | pop rax\r |
497 | mov cr2, rax\r |
498 | pop rax\r |
499 | mov cr3, rax\r |
500 | pop rax\r |
501 | mov cr4, rax\r |
502 | pop rax\r |
503 | mov cr8, rax\r |
504 | \r |
505 | ;; UINT64 RFlags;\r |
506 | mov rax, AppRsp\r |
507 | pop qword ptr [rax + 16]\r |
508 | \r |
509 | ;; UINT64 Ldtr, Tr;\r |
510 | ;; UINT64 Gdtr[2], Idtr[2];\r |
511 | ;; Best not let anyone mess with these particular registers...\r |
512 | add rsp, 48\r |
513 | \r |
514 | ;; UINT64 Rip;\r |
515 | pop qword ptr [rax]\r |
516 | \r |
517 | ;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;\r |
518 | ;; NOTE - modified segment registers could hang the debugger... We\r |
519 | ;; could attempt to insulate ourselves against this possibility,\r |
520 | ;; but that poses risks as well.\r |
521 | ;;\r |
522 | \r |
523 | pop rax\r |
524 | ; mov gs, rax\r |
525 | pop rax\r |
526 | ; mov fs, rax\r |
527 | pop rax\r |
528 | mov es, rax\r |
529 | pop rax\r |
530 | mov ds, rax\r |
531 | mov rax, AppRsp\r |
532 | pop qword ptr [rax + 8]\r |
533 | pop rax\r |
534 | mov ss, rax\r |
535 | \r |
536 | ;; The next stuff to restore is the general purpose registers that were pushed\r |
537 | ;; using the "push" instruction.\r |
538 | ;;\r |
539 | ;; The value of RSP as stored in the context record is the application RSP\r |
540 | ;; including the 5 entries on the application stack caused by the exception\r |
541 | ;; itself. It may have been modified by the debug agent, so we need to\r |
542 | ;; determine if we need to relocate the application stack.\r |
543 | \r |
544 | mov rbx, [rsp + 24] ; move the potentially modified AppRsp into rbx\r |
545 | mov rax, AppRsp\r |
546 | add rax, 40\r |
547 | cmp rbx, rax\r |
548 | je NoAppStackMove\r |
549 | \r |
550 | mov rax, AppRsp\r |
551 | mov rcx, [rax] ; RIP\r |
552 | mov [rbx], rcx\r |
553 | \r |
554 | mov rcx, [rax + 8] ; CS\r |
555 | mov [rbx + 8], rcx\r |
556 | \r |
557 | mov rcx, [rax + 16] ; RFLAGS\r |
558 | mov [rbx + 16], rcx\r |
559 | \r |
560 | mov rcx, [rax + 24] ; RSP\r |
561 | mov [rbx + 24], rcx\r |
562 | \r |
563 | mov rcx, [rax + 32] ; SS\r |
564 | mov [rbx + 32], rcx\r |
565 | \r |
566 | mov rax, rbx ; modify the saved AppRsp to the new AppRsp\r |
567 | mov AppRsp, rax\r |
568 | NoAppStackMove:\r |
569 | mov rax, DebugRsp ; restore the DebugRsp on the debug stack\r |
570 | ; so our "pop" will not cause a stack switch\r |
571 | mov [rsp + 24], rax\r |
572 | \r |
573 | cmp ExceptionNumber, 068h\r |
574 | jne NoChain\r |
575 | \r |
576 | Chain:\r |
577 | \r |
578 | ;; Restore rflags so when we chain, the flags will be exactly as if we were never here.\r |
579 | ;; We gin up the stack to do an iretq so we can get ALL the flags.\r |
580 | mov rax, AppRsp\r |
581 | mov rbx, [rax + 40]\r |
582 | push rbx\r |
583 | mov rax, ss\r |
584 | push rax\r |
585 | mov rax, rsp\r |
586 | add rax, 16\r |
587 | push rax\r |
588 | mov rax, AppRsp\r |
589 | mov rbx, [rax + 16]\r |
590 | and rbx, NOT 300h ; special handling for IF and TF\r |
591 | push rbx\r |
592 | mov rax, cs\r |
593 | push rax\r |
594 | mov rax, offset PhonyIretq\r |
595 | push rax\r |
596 | iretq\r |
597 | PhonyIretq:\r |
598 | \r |
599 | ;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r |
600 | ;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r |
601 | pop rdi\r |
602 | pop rsi\r |
603 | pop rbp\r |
604 | pop rsp\r |
605 | pop rbx\r |
606 | pop rdx\r |
607 | pop rcx\r |
608 | pop rax\r |
609 | pop r8\r |
610 | pop r9\r |
611 | pop r10\r |
612 | pop r11\r |
613 | pop r12\r |
614 | pop r13\r |
615 | pop r14\r |
616 | pop r15\r |
617 | \r |
618 | ;; Switch back to application stack\r |
619 | mov rsp, AppRsp\r |
620 | \r |
621 | ;; Jump to original handler\r |
622 | jmp OrigVector\r |
623 | \r |
624 | NoChain:\r |
625 | ;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;\r |
626 | ;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;\r |
627 | pop rdi\r |
628 | pop rsi\r |
629 | pop rbp\r |
630 | pop rsp\r |
631 | pop rbx\r |
632 | pop rdx\r |
633 | pop rcx\r |
634 | pop rax\r |
635 | pop r8\r |
636 | pop r9\r |
637 | pop r10\r |
638 | pop r11\r |
639 | pop r12\r |
640 | pop r13\r |
641 | pop r14\r |
642 | pop r15\r |
643 | \r |
644 | ;; Switch back to application stack\r |
645 | mov rsp, AppRsp\r |
646 | \r |
647 | ;; We're outa here...\r |
648 | iretq\r |
649 | text ENDS\r |
650 | \r |
651 | END\r |
652 | \r |
653 | \r |
654 | \r |