]>
Commit | Line | Data |
---|---|---|
24851580 | 1 | ///**@file |
2 | // Low leve x64 specific debug support functions. | |
3 | // | |
e5eed7d3 HT |
4 | // Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> |
5 | // Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR> | |
6 | // This program and the accompanying materials | |
24851580 | 7 | // are licensed and made available under the terms and conditions of the BSD License |
8 | // which accompanies this distribution. The full text of the license may be found at | |
9 | // http://opensource.org/licenses/bsd-license.php | |
10 | // | |
11 | // THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
12 | // WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
13 | // | |
c7a5da72 | 14 | //**/ |
24851580 | 15 | |
16 | ASM_GLOBAL ASM_PFX(OrigVector) | |
17 | ASM_GLOBAL ASM_PFX(InterruptEntryStub) | |
18 | ASM_GLOBAL ASM_PFX(StubSize) | |
19 | ASM_GLOBAL ASM_PFX(CommonIdtEntry) | |
20 | ASM_GLOBAL ASM_PFX(FxStorSupport) | |
c7a5da72 | 21 | |
22 | .data | |
24851580 | 23 | |
24 | ASM_PFX(StubSize): .long ASM_PFX(InterruptEntryStubEnd) - ASM_PFX(InterruptEntryStub) | |
25 | ASM_PFX(AppRsp): .long 0x11111111 # ? | |
26 | .long 0x11111111 # ? | |
27 | ASM_PFX(DebugRsp): .long 0x22222222 # ? | |
28 | .long 0x22222222 # ? | |
29 | ASM_PFX(ExtraPush): .long 0x33333333 # ? | |
30 | .long 0x33333333 # ? | |
31 | ASM_PFX(ExceptData): .long 0x44444444 # ? | |
32 | .long 0x44444444 # ? | |
33 | ASM_PFX(Rflags): .long 0x55555555 # ? | |
34 | .long 0x55555555 # ? | |
35 | ASM_PFX(OrigVector): .long 0x66666666 # ? | |
36 | .long 0x66666666 # ? | |
37 | ||
38 | // The declarations below define the memory region that will be used for the debug stack. | |
39 | // The context record will be built by pushing register values onto this stack. | |
40 | // It is imparitive that alignment be carefully managed, since the FXSTOR and | |
41 | // FXRSTOR instructions will GP fault if their memory operand is not 16 byte aligned. | |
42 | // | |
43 | // The stub will switch stacks from the application stack to the debuger stack | |
44 | // and pushes the exception number. | |
45 | // | |
46 | // Then we building the context record on the stack. Since the stack grows down, | |
47 | // we push the fields of the context record from the back to the front. There | |
48 | // are 336 bytes of stack used prior allocating the 512 bytes of stack to be | |
49 | // used as the memory buffer for the fxstor instruction. Therefore address of | |
50 | // the buffer used for the FXSTOR instruction is &Eax - 336 - 512, which | |
51 | // must be 16 byte aligned. | |
52 | // | |
53 | // We carefully locate the stack to make this happen. | |
54 | // | |
55 | // For reference, the context structure looks like this: | |
56 | // struct { | |
57 | // UINT64 ExceptionData; | |
58 | // FX_SAVE_STATE_X64 FxSaveState; // 512 bytes, must be 16 byte aligned | |
59 | // UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; | |
60 | // UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; | |
61 | // UINT64 RFlags; | |
62 | // UINT64 Ldtr, Tr; | |
63 | // UINT64 Gdtr[2], Idtr[2]; | |
64 | // UINT64 Rip; | |
65 | // UINT64 Gs, Fs, Es, Ds, Cs, Ss; | |
66 | // UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; | |
67 | // UINT64 R8, R9, R10, R11, R12, R13, R14, R15; | |
68 | // } SYSTEM_CONTEXT_X64; // 64 bit system context record | |
69 | ||
70 | .p2align 4 | |
71 | DebugStackEnd : .ascii "DbgStkEnd >>>>>>" # 16 byte long string - must be 16 bytes to preserve alignment | |
72 | .fill 0x1ffc, 4, 0x00000000 | |
73 | # 32K should be enough stack | |
74 | # This allocation is coocked to insure | |
75 | # that the the buffer for the FXSTORE instruction | |
76 | # will be 16 byte aligned also. | |
77 | # | |
78 | ASM_PFX(ExceptionNumber): .long 0x77777777 # first entry will be the vector number pushed by the stub | |
79 | .long 0x77777777 # ? | |
80 | ||
81 | DebugStackBegin : .ascii "<<<< DbgStkBegin" # initial debug ESP == DebugStackBegin, set in stub | |
c7a5da72 | 82 | |
24851580 | 83 | |
84 | .text | |
85 | ||
86 | //------------------------------------------------------------------------------ | |
87 | // BOOLEAN | |
88 | // FxStorSupport ( | |
89 | // void | |
90 | // ) | |
91 | // | |
92 | // Abstract: Returns TRUE if FxStor instructions are supported | |
93 | // | |
94 | ASM_GLOBAL ASM_PFX(FxStorSupport) | |
c7a5da72 | 95 | ASM_PFX(FxStorSupport): |
24851580 | 96 | // |
97 | // cpuid corrupts rbx which must be preserved per the C calling convention | |
98 | // | |
99 | pushq %rbx | |
100 | movq $1, %rax | |
101 | cpuid | |
102 | movl %edx, %eax | |
103 | andq $0x01000000, %rax | |
104 | shrq $24, %rax | |
105 | popq %rbx | |
106 | ret | |
107 | //------------------------------------------------------------------------------ | |
108 | // void | |
109 | // Vect2Desc ( | |
110 | // IA32_IDT_GATE_DESCRIPTOR * DestDesc, // rcx | |
111 | // void (*Vector) (void) // rdx | |
112 | // ) | |
113 | // | |
114 | // Abstract: Encodes an IDT descriptor with the given physical address | |
115 | // | |
116 | ASM_GLOBAL ASM_PFX(Vect2Desc) | |
117 | ASM_PFX(Vect2Desc): | |
118 | movq %rdx, %rax | |
119 | movw %ax, (%rcx) # write bits 15..0 of offset | |
120 | movw %cs, %dx | |
121 | movw %dx, 2(%rcx) # SYS_CODE_SEL from GDT | |
122 | movw $(0x0e00 | 0x8000), 4(%rcx) # type = 386 interrupt gate, present | |
123 | shrq $16, %rax | |
124 | movw %ax, 6(%rcx) # write bits 31..16 of offset | |
125 | shrq $16, %rax | |
126 | movl %eax, 8(%rcx) # write bits 63..32 of offset | |
127 | ||
128 | ret | |
129 | ||
130 | //------------------------------------------------------------------------------ | |
131 | // InterruptEntryStub | |
132 | // | |
133 | // Abstract: This code is not a function, but is a small piece of code that is | |
134 | // copied and fixed up once for each IDT entry that is hooked. | |
135 | // | |
136 | ASM_GLOBAL ASM_PFX(InterruptEntryStub) | |
137 | ASM_PFX(InterruptEntryStub): | |
138 | ||
139 | pushq $0 # push vector number - will be modified before installed | |
140 | jmp ASM_PFX(CommonIdtEntry) | |
c7a5da72 | 141 | |
24851580 | 142 | ASM_GLOBAL ASM_PFX(InterruptEntryStubEnd) |
143 | ASM_PFX(InterruptEntryStubEnd): | |
144 | ||
145 | //------------------------------------------------------------------------------ | |
146 | // CommonIdtEntry | |
147 | // | |
148 | // Abstract: This code is not a function, but is the common part for all IDT | |
149 | // vectors. | |
150 | // | |
151 | ASM_GLOBAL ASM_PFX(CommonIdtEntry) | |
152 | // | |
153 | // At this point, the stub has saved the current application stack esp into AppRsp | |
154 | // and switched stacks to the debug stack, where it pushed the vector number | |
155 | // | |
156 | // The application stack looks like this: | |
157 | // | |
158 | // ... | |
159 | // (last application stack entry) | |
160 | // [16 bytes alignment, do not care it] | |
161 | // SS from interrupted task | |
162 | // RSP from interrupted task | |
163 | // rflags from interrupted task | |
164 | // CS from interrupted task | |
165 | // RIP from interrupted task | |
166 | // Error code <-------------------- Only present for some exeption types | |
167 | // | |
168 | // Vector Number <----------------- pushed in our IDT Entry | |
169 | // | |
170 | ||
171 | ||
172 | // The stub switched us to the debug stack and pushed the interrupt number. | |
173 | // | |
174 | // Next, construct the context record. It will be build on the debug stack by | |
175 | // pushing the registers in the correct order so as to create the context structure | |
176 | // on the debug stack. The context record must be built from the end back to the | |
177 | // beginning because the stack grows down... | |
178 | // | |
179 | // For reference, the context record looks like this: | |
180 | // | |
181 | // typedef | |
182 | // struct { | |
183 | // UINT64 ExceptionData; | |
184 | // FX_SAVE_STATE_X64 FxSaveState; | |
185 | // UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; | |
186 | // UINT64 Cr0, Cr2, Cr3, Cr4, Cr8; | |
187 | // UINT64 RFlags; | |
188 | // UINT64 Ldtr, Tr; | |
189 | // UINT64 Gdtr[2], Idtr[2]; | |
190 | // UINT64 Rip; | |
191 | // UINT64 Gs, Fs, Es, Ds, Cs, Ss; | |
192 | // UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; | |
193 | // UINT64 R8, R9, R10, R11, R12, R13, R14, R15; | |
194 | // } SYSTEM_CONTEXT_X64; // 64 | |
195 | ASM_PFX(CommonIdtEntry): | |
196 | // NOTE: we save rsp here to prevent compiler put rip reference cause error AppRsp | |
197 | pushq %rax | |
198 | movq (8)(%rsp), %rax # save vector number | |
199 | movq %rax, ASM_PFX(ExceptionNumber)(%rip) # save vector number | |
200 | popq %rax | |
201 | addq $8, %rsp # pop vector number | |
202 | movq %rsp, ASM_PFX(AppRsp)(%rip) # save stack top | |
203 | movq DebugStackBegin(%rip), %rsp # switch to debugger stack | |
204 | subq $8, %rsp # leave space for vector number | |
205 | // UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; | |
206 | // UINT64 R8, R9, R10, R11, R12, R13, R14, R15; | |
207 | pushq %r15 | |
208 | pushq %r14 | |
209 | pushq %r13 | |
210 | pushq %r12 | |
211 | pushq %r11 | |
212 | pushq %r10 | |
213 | pushq %r9 | |
214 | pushq %r8 | |
215 | pushq %rax | |
216 | pushq %rcx | |
217 | pushq %rdx | |
218 | pushq %rbx | |
219 | pushq %rsp | |
220 | pushq %rbp | |
221 | pushq %rsi | |
222 | pushq %rdi | |
223 | // Save interrupt state rflags register... | |
224 | pushfq | |
225 | popq %rax | |
226 | movq %rax, ASM_PFX(Rflags)(%rip) | |
227 | // We need to determine if any extra data was pushed by the exception, and if so, save it | |
228 | // To do this, we check the exception number pushed by the stub, and cache the | |
229 | // result in a variable since we'll need this again. | |
230 | cmpl $0, ASM_PFX(ExceptionNumber)(%rip) | |
231 | jz ExtraPushOne | |
232 | cmpl $10, ASM_PFX(ExceptionNumber)(%rip) | |
233 | jz ExtraPushOne | |
234 | cmpl $11, ASM_PFX(ExceptionNumber)(%rip) | |
235 | jz ExtraPushOne | |
236 | cmpl $12, ASM_PFX(ExceptionNumber)(%rip) | |
237 | jz ExtraPushOne | |
238 | cmpl $13, ASM_PFX(ExceptionNumber)(%rip) | |
239 | jz ExtraPushOne | |
240 | cmpl $14, ASM_PFX(ExceptionNumber)(%rip) | |
241 | jz ExtraPushOne | |
242 | cmpl $17, ASM_PFX(ExceptionNumber)(%rip) | |
243 | jz ExtraPushOne | |
244 | movl $0, ASM_PFX(ExtraPush)(%rip) | |
245 | movl $0, ASM_PFX(ExceptData)(%rip) | |
246 | jmp ExtraPushDone | |
247 | ExtraPushOne: | |
248 | movl $1, ASM_PFX(ExtraPush)(%rip) | |
249 | ||
250 | // If there's some extra data, save it also, and modify the saved AppRsp to effectively | |
251 | // pop this value off the application's stack. | |
c7a5da72 | 252 | movq ASM_PFX(AppRsp)(%rip), %rax |
24851580 | 253 | movq (%rax), %rbx |
254 | movq %rbx, ASM_PFX(ExceptData)(%rip) | |
255 | addq $8, %rax | |
256 | movq %rax, ASM_PFX(AppRsp)(%rip) | |
257 | ||
258 | ExtraPushDone: | |
259 | ||
260 | // The "push" above pushed the debug stack rsp. Since what we're actually doing | |
261 | // is building the context record on the debug stack, we need to save the pushed | |
262 | // debug RSP, and replace it with the application's last stack entry... | |
263 | movq 24(%rsp), %rax | |
264 | movq %rax, ASM_PFX(DebugRsp)(%rip) | |
c7a5da72 | 265 | movq ASM_PFX(AppRsp)(%rip), %rax |
266 | movq 24(%rax), %rax | |
24851580 | 267 | # application stack has ss, rsp, rflags, cs, & rip, so |
c7a5da72 | 268 | # last actual application stack entry is saved at offset |
269 | # 24 bytes from stack top. | |
24851580 | 270 | movq %rax, 24(%rsp) |
271 | ||
272 | // continue building context record | |
273 | // UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero | |
274 | mov %ss, %rax | |
275 | pushq %rax | |
276 | # CS from application is one entry back in application stack | |
277 | movq ASM_PFX(AppRsp)(%rip), %rax | |
278 | movzxw 8(%rax), %rax | |
279 | pushq %rax | |
280 | ||
281 | mov %ds, %rax | |
282 | pushq %rax | |
283 | movw %es, %rax | |
284 | pushq %rax | |
285 | mov %fs, %rax | |
286 | pushq %rax | |
287 | mov %gs, %rax | |
288 | pushq %rax | |
289 | // UINT64 Rip; | |
290 | # Rip from application is on top of application stack | |
c7a5da72 | 291 | movq ASM_PFX(AppRsp)(%rip), %rax |
24851580 | 292 | pushq (%rax) |
293 | // UINT64 Gdtr[2], Idtr[2]; | |
294 | push $0 | |
295 | push $0 | |
296 | sidtq (%rsp) | |
297 | push $0 | |
298 | push $0 | |
299 | sgdtq (%rsp) | |
300 | ||
301 | // UINT64 Ldtr, Tr; | |
302 | xorq %rax, %rax | |
303 | str %ax | |
304 | pushq %rax | |
305 | sldt %ax | |
306 | pushq %rax | |
307 | ||
308 | // UINT64 RFlags; | |
309 | // Rflags from application is two entries back in application stack | |
c7a5da72 | 310 | movq ASM_PFX(AppRsp)(%rip), %rax |
24851580 | 311 | pushq 16(%rax) |
312 | // UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; | |
313 | // insure FXSAVE/FXRSTOR is enabled in CR4... | |
314 | // ... while we're at it, make sure DE is also enabled... | |
315 | movq %cr8, %rax | |
316 | pushq %rax | |
317 | movq %cr4, %rax | |
318 | orq $0x208, %rax | |
319 | movq %rax, %cr4 | |
320 | pushq %rax | |
321 | movq %cr3, %rax | |
322 | pushq %rax | |
323 | movq %cr2, %rax | |
324 | pushq %rax | |
325 | push $0 | |
326 | movq %cr0, %rax | |
327 | pushq %rax | |
328 | // UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; | |
329 | movq %dr7, %rax | |
330 | pushq %rax | |
331 | // clear Dr7 while executing debugger itself | |
332 | xorq %rax, %rax | |
333 | movq %rax, %dr7 | |
334 | ||
335 | movq %dr6, %rax | |
336 | pushq %rax | |
337 | // insure all status bits in dr6 are clear... | |
338 | xorq %rax, %rax | |
339 | movq %rax, %dr6 | |
340 | ||
341 | movq %dr3, %rax | |
342 | pushq %rax | |
343 | movq %dr2, %rax | |
344 | pushq %rax | |
345 | movq %dr1, %rax | |
346 | pushq %rax | |
347 | movq %dr0, %rax | |
348 | pushq %rax | |
349 | ||
350 | // FX_SAVE_STATE_X64 FxSaveState; | |
351 | subq $512, %rsp | |
352 | movq %rsp, %rdi | |
353 | # IMPORTANT!! The debug stack has been carefully constructed to | |
354 | # insure that rsp and rdi are 16 byte aligned when we get here. | |
355 | # They MUST be. If they are not, a GP fault will occur. | |
c7a5da72 | 356 | |
24851580 | 357 | # FXSTOR_RDI |
358 | fxsave (%rdi) | |
359 | ||
360 | // UINT64 ExceptionData; | |
361 | movq ASM_PFX(ExceptData)(%rip), %rax | |
362 | pushq %rax | |
363 | ||
364 | // call to C code which will in turn call registered handler | |
365 | // pass in the vector number | |
366 | movq %rsp, %rdx | |
c7a5da72 | 367 | movq ASM_PFX(ExceptionNumber)(%rip), %rcx |
24851580 | 368 | subq $40, %rsp |
369 | call ASM_PFX(InterruptDistrubutionHub) | |
370 | addq $40, %rsp | |
371 | // restore context... | |
372 | // UINT64 ExceptionData; | |
373 | addq $8, %rsp | |
374 | ||
375 | // FX_SAVE_STATE_X64 FxSaveState; | |
376 | movq %rsp, %rsi | |
c7a5da72 | 377 | |
24851580 | 378 | # FXRSTOR_RSI |
379 | fxrstor (%rsi) | |
380 | ||
381 | addq $512, %rsp | |
382 | ||
383 | // UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; | |
384 | popq %rax | |
385 | movq %rax, %dr0 | |
386 | popq %rax | |
387 | movq %rax, %dr1 | |
388 | popq %rax | |
389 | movq %rax, %dr2 | |
390 | popq %rax | |
391 | movq %rax, %dr3 | |
392 | ||
393 | // skip restore of dr6. We cleared dr6 during the context save. | |
394 | addq $8, %rsp | |
395 | popq %rax | |
396 | movq %rax, %dr7 | |
397 | ||
398 | // UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8; | |
399 | popq %rax | |
400 | movq %rax, %cr0 | |
401 | addq $8, %rsp | |
402 | popq %rax | |
403 | movq %rax, %cr2 | |
404 | popq %rax | |
405 | movq %rax, %cr3 | |
406 | popq %rax | |
407 | movq %rax, %cr4 | |
408 | popq %rax | |
409 | movq %rax, %cr8 | |
410 | // UINT64 RFlags; | |
c7a5da72 | 411 | movq ASM_PFX(AppRsp)(%rip), %rax |
24851580 | 412 | popq 16(%rax) |
413 | // UINT64 Ldtr, Tr; | |
414 | // UINT64 Gdtr[2], Idtr[2]; | |
415 | // Best not let anyone mess with these particular registers... | |
416 | addq $48, %rsp | |
417 | // UINT64 Rip; | |
418 | popq (%rax) | |
419 | ||
420 | // UINT64 Gs, Fs, Es, Ds, Cs, Ss; | |
421 | // NOTE - modified segment registers could hang the debugger... We | |
422 | // could attempt to insulate ourselves against this possibility, | |
423 | // but that poses risks as well. | |
424 | // | |
425 | ||
426 | popq %rax | |
427 | # mov %rax, %gs | |
428 | popq %rax | |
429 | # mov %rax, %fs | |
430 | popq %rax | |
431 | mov %rax, %es | |
432 | popq %rax | |
433 | mov %rax, %ds | |
c7a5da72 | 434 | movq ASM_PFX(AppRsp)(%rip), %rax |
24851580 | 435 | popq 8(%rax) |
436 | popq %rax | |
437 | mov %rax, %ss | |
438 | ## The next stuff to restore is the general purpose registers that were pushed | |
439 | ## using the "push" instruction. | |
440 | ## | |
441 | ## The value of RSP as stored in the context record is the application RSP | |
442 | ## including the 5 entries on the application stack caused by the exception | |
443 | ## itself. It may have been modified by the debug agent, so we need to | |
444 | ## determine if we need to relocate the application stack. | |
445 | ||
446 | movq 24(%rsp), %rbx # move the potentially modified AppRsp into rbx | |
c7a5da72 | 447 | movq ASM_PFX(AppRsp)(%rip), %rax |
448 | movq 24(%rax), %rax | |
24851580 | 449 | cmpq %rax, %rbx |
450 | je NoAppStackMove | |
451 | ||
c7a5da72 | 452 | movq ASM_PFX(AppRsp)(%rip), %rax |
24851580 | 453 | movq (%rax), %rcx # RIP |
454 | movq %rcx, (%rbx) | |
455 | ||
456 | movq 8(%rax), %rcx # CS | |
457 | movq %rcx, 8(%rbx) | |
458 | ||
459 | movq 16(%rax), %rcx # RFLAGS | |
460 | movq %rcx, 16(%rbx) | |
461 | ||
462 | movq 24(%rax), %rcx # RSP | |
463 | movq %rcx, 24(%rbx) | |
464 | ||
465 | movq 32(%rax), %rcx # SS | |
466 | movq %rcx, 32(%rbx) | |
467 | ||
468 | movq %rbx, %rax # modify the saved AppRsp to the new AppRsp | |
469 | movq %rax, ASM_PFX(AppRsp)(%rip) | |
470 | NoAppStackMove: | |
471 | movq ASM_PFX(DebugRsp)(%rip), %rax # restore the DebugRsp on the debug stack | |
472 | # so our "pop" will not cause a stack switch | |
473 | movq %rax, 24(%rsp) | |
474 | ||
475 | cmpl $0x068, ASM_PFX(ExceptionNumber)(%rip) | |
476 | jne NoChain | |
477 | ||
478 | Chain: | |
479 | ||
480 | // Restore rflags so when we chain, the flags will be exactly as if we were never here. | |
481 | // We gin up the stack to do an iretq so we can get ALL the flags. | |
c7a5da72 | 482 | movq ASM_PFX(AppRsp)(%rip), %rax |
24851580 | 483 | movq 40(%rax), %rbx |
484 | pushq %rbx | |
485 | mov %ss, %rax | |
486 | pushq %rax | |
487 | movq %rsp, %rax | |
488 | addq $16, %rax | |
489 | pushq %rax | |
c7a5da72 | 490 | movq ASM_PFX(AppRsp)(%rip), %rax |
24851580 | 491 | movq 16(%rax), %rbx |
492 | andq $0xfffffffffffffcff, %rbx # special handling for IF and TF | |
493 | pushq %rbx | |
494 | mov %cs, %rax | |
495 | pushq %rax | |
c7a5da72 | 496 | movq PhonyIretq(%rip), %rax |
24851580 | 497 | pushq %rax |
498 | iretq | |
499 | PhonyIretq: | |
500 | ||
501 | // UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; | |
502 | // UINT64 R8, R9, R10, R11, R12, R13, R14, R15; | |
503 | popq %rdi | |
504 | popq %rsi | |
505 | popq %rbp | |
506 | popq %rsp | |
507 | popq %rbx | |
508 | popq %rdx | |
509 | popq %rcx | |
510 | popq %rax | |
511 | popq %r8 | |
512 | popq %r9 | |
513 | popq %r10 | |
514 | popq %r11 | |
515 | popq %r12 | |
516 | popq %r13 | |
517 | popq %r14 | |
518 | popq %r15 | |
519 | ||
520 | // Switch back to application stack | |
c7a5da72 | 521 | movq ASM_PFX(AppRsp)(%rip), %rsp |
24851580 | 522 | // Jump to original handler |
523 | jmp ASM_PFX(OrigVector) | |
524 | NoChain: | |
525 | // UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax; | |
526 | // UINT64 R8, R9, R10, R11, R12, R13, R14, R15; | |
527 | popq %rdi | |
528 | popq %rsi | |
529 | popq %rbp | |
530 | popq %rsp | |
531 | popq %rbx | |
532 | popq %rdx | |
533 | popq %rcx | |
534 | popq %rax | |
535 | popq %r8 | |
536 | popq %r9 | |
537 | popq %r10 | |
538 | popq %r11 | |
539 | popq %r12 | |
540 | popq %r13 | |
541 | popq %r14 | |
542 | popq %r15 | |
543 | ||
544 | // Switch back to application stack | |
c7a5da72 | 545 | movq ASM_PFX(AppRsp)(%rip), %rsp |
24851580 | 546 | |
547 | // We're outa here... | |
548 | iret |