1#------------------------------------------------------------------------------ 2# 3# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR> 4# This program and the accompanying materials 5# are licensed and made available under the terms and conditions of the BSD License 6# which accompanies this distribution. The full text of the license may be found at 7# http://opensource.org/licenses/bsd-license.php. 8# 9# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 10# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 11# 12# Module Name: 13# 14# AsmFuncs.S 15# 16# Abstract: 17# 18# Debug interrupt handle functions. 19# 20#------------------------------------------------------------------------------ 21 22#include "DebugException.h" 23 24ASM_GLOBAL ASM_PFX(InterruptProcess) 25ASM_GLOBAL ASM_PFX(Exception0Handle) 26ASM_GLOBAL ASM_PFX(ExceptionStubHeaderSize) 27ASM_GLOBAL ASM_PFX(TimerInterruptHandle) 28ASM_GLOBAL ASM_PFX(CommonEntry) 29 30.macro AGENT_HANDLER_SIGNATURE 31 .byte 0x41, 0x47, 0x54, 0x48 # AGENT_HANDLER_SIGNATURE SIGNATURE_32('A','G','T','H') 32.endm 33 34.data 35 36ASM_PFX(ExceptionStubHeaderSize): .long ASM_PFX(Exception1Handle) - ASM_PFX(Exception0Handle) 37 38.text 39 40AGENT_HANDLER_SIGNATURE 41ASM_PFX(Exception0Handle): 42 cli 43 pushl %eax 44 mov $0, %eax 45 jmp ASM_PFX(CommonEntry) 46AGENT_HANDLER_SIGNATURE 47ASM_PFX(Exception1Handle): 48 cli 49 pushl %eax 50 mov $1, %eax 51 jmp ASM_PFX(CommonEntry) 52AGENT_HANDLER_SIGNATURE 53ASM_PFX(Exception2Handle): 54 cli 55 pushl %eax 56 mov $2, %eax 57 jmp ASM_PFX(CommonEntry) 58AGENT_HANDLER_SIGNATURE 59ASM_PFX(Exception3Handle): 60 cli 61 pushl %eax 62 mov $3, %eax 63 jmp ASM_PFX(CommonEntry) 64AGENT_HANDLER_SIGNATURE 65ASM_PFX(Exception4Handle): 66 cli 67 pushl %eax 68 mov $4, %eax 69 jmp ASM_PFX(CommonEntry) 70AGENT_HANDLER_SIGNATURE 71ASM_PFX(Exception5Handle): 72 cli 73 pushl %eax 74 mov $5, %eax 75 jmp ASM_PFX(CommonEntry) 76AGENT_HANDLER_SIGNATURE 77ASM_PFX(Exception6Handle): 78 cli 79 pushl %eax 80 mov $6, %eax 81 jmp ASM_PFX(CommonEntry) 82AGENT_HANDLER_SIGNATURE 83ASM_PFX(Exception7Handle): 84 cli 85 pushl %eax 86 mov $7, %eax 87 jmp ASM_PFX(CommonEntry) 88AGENT_HANDLER_SIGNATURE 89ASM_PFX(Exception8Handle): 90 cli 91 pushl %eax 92 mov $8, %eax 93 jmp ASM_PFX(CommonEntry) 94AGENT_HANDLER_SIGNATURE 95ASM_PFX(Exception9Handle): 96 cli 97 pushl %eax 98 mov $9, %eax 99 jmp ASM_PFX(CommonEntry) 100AGENT_HANDLER_SIGNATURE 101ASM_PFX(Exception10Handle): 102 cli 103 pushl %eax 104 mov $10, %eax 105 jmp ASM_PFX(CommonEntry) 106AGENT_HANDLER_SIGNATURE 107ASM_PFX(Exception11Handle): 108 cli 109 pushl %eax 110 mov $11, %eax 111 jmp ASM_PFX(CommonEntry) 112AGENT_HANDLER_SIGNATURE 113ASM_PFX(Exception12Handle): 114 cli 115 pushl %eax 116 mov $12, %eax 117 jmp ASM_PFX(CommonEntry) 118AGENT_HANDLER_SIGNATURE 119ASM_PFX(Exception13Handle): 120 cli 121 pushl %eax 122 mov $13, %eax 123 jmp ASM_PFX(CommonEntry) 124AGENT_HANDLER_SIGNATURE 125ASM_PFX(Exception14Handle): 126 cli 127 pushl %eax 128 mov $14, %eax 129 jmp ASM_PFX(CommonEntry) 130AGENT_HANDLER_SIGNATURE 131ASM_PFX(Exception15Handle): 132 cli 133 pushl %eax 134 mov $15, %eax 135 jmp ASM_PFX(CommonEntry) 136AGENT_HANDLER_SIGNATURE 137ASM_PFX(Exception16Handle): 138 cli 139 pushl %eax 140 mov $16, %eax 141 jmp ASM_PFX(CommonEntry) 142AGENT_HANDLER_SIGNATURE 143ASM_PFX(Exception17Handle): 144 cli 145 pushl %eax 146 mov $17, %eax 147 jmp ASM_PFX(CommonEntry) 148AGENT_HANDLER_SIGNATURE 149ASM_PFX(Exception18Handle): 150 cli 151 pushl %eax 152 mov $18, %eax 153 jmp ASM_PFX(CommonEntry) 154AGENT_HANDLER_SIGNATURE 155ASM_PFX(Exception19Handle): 156 cli 157 pushl %eax 158 mov $19, %eax 159 jmp ASM_PFX(CommonEntry) 160AGENT_HANDLER_SIGNATURE 161ASM_PFX(TimerInterruptHandle): 162 cli 163 pushl %eax 164 mov $32, %eax 165 jmp ASM_PFX(CommonEntry) 166 167 168ASM_PFX(CommonEntry): 169 170#---------------------------------------; 171# _CommonEntry ; 172#----------------------------------------------------------------------------; 173# The follow algorithm is used for the common interrupt routine. 174# Entry from each interrupt with a push eax and eax=interrupt number 175# 176# +---------------------+ 177# + EFlags + 178# +---------------------+ 179# + CS + 180# +---------------------+ 181# + EIP + 182# +---------------------+ 183# + Error Code + 184# +---------------------+ 185# + EAX / Vector Number + 186# +---------------------+ 187# + EBP + 188# +---------------------+ <-- EBP 189# 190 191# We need to determine if any extra data was pushed by the exception 192 cmpl $DEBUG_EXCEPT_DOUBLE_FAULT, %eax 193 je NoExtrPush 194 cmpl $DEBUG_EXCEPT_INVALID_TSS, %eax 195 je NoExtrPush 196 cmpl $DEBUG_EXCEPT_SEG_NOT_PRESENT, %eax 197 je NoExtrPush 198 cmpl $DEBUG_EXCEPT_STACK_FAULT, %eax 199 je NoExtrPush 200 cmpl $DEBUG_EXCEPT_GP_FAULT, %eax 201 je NoExtrPush 202 cmpl $DEBUG_EXCEPT_PAGE_FAULT, %eax 203 je NoExtrPush 204 cmpl $DEBUG_EXCEPT_ALIGNMENT_CHECK, %eax 205 je NoExtrPush 206 207 pushl (%esp) 208 movl $0, 4(%esp) 209 210NoExtrPush: 211 212 pushl %ebp 213 movl %esp,%ebp 214 215 # 216 # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32 217 # is 16-byte aligned 218 # 219 andl $0xfffffff0,%esp 220 subl $12,%esp 221 222## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; 223 pushl 0x4(%ebp) 224 pushl %ebx 225 pushl %ecx 226 pushl %edx 227 mov %eax, %ebx # save vector in ebx 228 leal 24(%ebp),%ecx 229 pushl %ecx # save original ESP 230 pushl (%ebp) 231 pushl %esi 232 pushl %edi 233 234## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4; 235## insure FXSAVE/FXRSTOR is enabled in CR4... 236## ... while we're at it, make sure DE is also enabled... 237 mov $1, %eax 238 pushl %ebx # temporarily save value of ebx on stack 239 cpuid # use CPUID to determine if FXSAVE/FXRESTOR 240 # and DE are supported 241 popl %ebx # retore value of ebx that was overwritten 242 # by CPUID 243 movl %cr4, %eax 244 pushl %eax # push cr4 firstly 245 testl $BIT24, %edx # Test for FXSAVE/FXRESTOR support 246 jz L1 247 orl $BIT9, %eax # Set CR4.OSFXSR 248L1: 249 testl $BIT2, %edx # Test for Debugging Extensions support 250 jz L2 251 orl $BIT3, %eax # Set CR4.DE 252L2: 253 movl %eax, %cr4 254 movl %cr3, %eax 255 pushl %eax 256 movl %cr2, %eax 257 pushl %eax 258 xorl %eax,%eax 259 pushl %eax 260 movl %cr0, %eax 261 pushl %eax 262 263## UINT32 Gs, Fs, Es, Ds, Cs, Ss; 264 movl %ss,%eax 265 pushl %eax 266 movzwl 16(%ebp), %eax 267 pushl %eax 268 movl %ds,%eax 269 pushl %eax 270 movl %es,%eax 271 pushl %eax 272 movl %fs,%eax 273 pushl %eax 274 movl %gs,%eax 275 pushl %eax 276 277## UINT32 Eip; 278 pushl 12(%ebp) 279 280## UINT32 Gdtr[2], Idtr[2]; 281 subl $8,%esp 282 sidt (%esp) 283 subl $8,%esp 284 sgdt (%esp) 285 286## UINT32 Ldtr, Tr; 287 xorl %eax,%eax 288 strl %eax 289 pushl %eax 290 sldtl %eax 291 pushl %eax 292 293## UINT32 EFlags; 294 pushl 20(%ebp) 295 296## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; 297 movl %dr7, %eax 298 pushl %eax 299## clear Dr7 while executing debugger itself 300 xorl %eax,%eax 301 movl %eax, %dr7 302 303 movl %dr6, %eax 304 pushl %eax 305## insure all status bits in dr6 are clear... 306 xorl %eax,%eax 307 movl %eax, %dr6 308 309 movl %dr3, %eax 310 pushl %eax 311 movl %dr2, %eax 312 pushl %eax 313 movl %dr1, %eax 314 pushl %eax 315 movl %dr0, %eax 316 pushl %eax 317 318## FX_SAVE_STATE_IA32 FxSaveState; 319 subl $512,%esp 320 movl %esp,%edi 321 testl $BIT24, %edx # Test for FXSAVE/FXRESTOR support. 322 # edx still contains result from CPUID above 323 jz L3 324 .byte 0x0f, 0xae, 0x07 # fxsave [edi] 325L3: 326 327## save the exception data 328 pushl 8(%esp) 329 330## Clear Direction Flag 331 cld 332 333## Prepare parameter and call C function 334 pushl %esp 335 pushl %ebx 336 call ASM_PFX(InterruptProcess) 337 addl $8,%esp 338 339## skip the exception data 340 addl $4,%esp 341 342## FX_SAVE_STATE_IA32 FxSaveState; 343 movl %esp,%esi 344 movl $1, %eax 345 cpuid # use CPUID to determine if FXSAVE/FXRESTOR 346 # are supported 347 testl $BIT24, %edx # Test for FXSAVE/FXRESTOR support 348 jz L4 349 .byte 0x0f, 0xae, 0x0e # fxrstor [esi] 350L4: 351 addl $512,%esp 352 353## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; 354 popl %eax 355 movl %eax, %dr0 356 popl %eax 357 movl %eax, %dr1 358 popl %eax 359 movl %eax, %dr2 360 popl %eax 361 movl %eax, %dr3 362## skip restore of dr6. We cleared dr6 during the context save. 363 addl $4,%esp 364 popl %eax 365 movl %eax, %dr7 366 367## UINT32 EFlags; 368 popl 20(%ebp) 369 370## UINT32 Ldtr, Tr; 371## UINT32 Gdtr[2], Idtr[2]; 372## Best not let anyone mess with these particular registers... 373 addl $24,%esp 374 375## UINT32 Eip; 376 pop 12(%ebp) 377 378## UINT32 Gs, Fs, Es, Ds, Cs, Ss; 379## NOTE - modified segment registers could hang the debugger... We 380## could attempt to insulate ourselves against this possibility, 381## but that poses risks as well. 382## 383 popl %gs 384 popl %fs 385 popl %es 386 popl %ds 387 popl 16(%ebp) 388 popl %ss 389 390## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4; 391 popl %eax 392 movl %eax, %cr0 393 addl $4,%esp # not for Cr1 394 popl %eax 395 movl %eax, %cr2 396 popl %eax 397 movl %eax, %cr3 398 popl %eax 399 movl %eax, %cr4 400 401## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; 402 popl %edi 403 popl %esi 404 addl $4,%esp # not for ebp 405 addl $4,%esp # not for esp 406 popl %edx 407 popl %ecx 408 popl %ebx 409 popl %eax 410 411 movl %ebp,%esp 412 popl %ebp 413 addl $8,%esp # skip eax 414 iretl 415 416