CpuAsm.S revision 01a1c0fc9e60dfd6b26bd6d9aa9c3a6242bbb608
1#------------------------------------------------------------------------------ 2#* 3#* Copyright (c) 2006 - 2009, 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#* CpuAsm.S 13#* 14#* Abstract: 15#* 16#------------------------------------------------------------------------------ 17 18 19#.MMX 20#.XMM 21 22#EXTRN ASM_PFX(mErrorCodeFlag):DWORD # Error code flags for exceptions 23 24 25# 26# point to the external interrupt vector table 27# 28ExternalVectorTablePtr: 29 .byte 0, 0, 0, 0 30 31ASM_GLOBAL ASM_PFX(InitializeExternalVectorTablePtr) 32ASM_PFX(InitializeExternalVectorTablePtr): 33 movl 4(%esp), %eax 34 movl %eax, ExternalVectorTablePtr 35 ret 36 37#------------------------------------------------------------------------------ 38# VOID 39# SetCodeSelector ( 40# UINT16 Selector 41# ); 42#------------------------------------------------------------------------------ 43ASM_GLOBAL ASM_PFX(SetCodeSelector) 44ASM_PFX(SetCodeSelector): 45 movl 4(%esp), %ecx 46 subl $0x10, %esp 47 leal setCodeSelectorLongJump, %eax 48 movl %eax, (%esp) 49 movw %cx, 4(%esp) 50 .byte 0xFF, 0x2C, 0x24 # jmp *(%esp) note:(FWORD jmp) 51setCodeSelectorLongJump: 52 addl $0x10, %esp 53 ret 54 55#------------------------------------------------------------------------------ 56# VOID 57# SetDataSelectors ( 58# UINT16 Selector 59# ); 60#------------------------------------------------------------------------------ 61ASM_GLOBAL ASM_PFX(SetDataSelectors) 62ASM_PFX(SetDataSelectors): 63 movl 4(%esp), %ecx 64 movw %cx, %ss 65 movw %cx, %ds 66 movw %cx, %es 67 movw %cx, %fs 68 movw %cx, %gs 69 ret 70 71#---------------------------------------; 72# CommonInterruptEntry ; 73#---------------------------------------; 74# The follow algorithm is used for the common interrupt routine. 75 76ASM_GLOBAL ASM_PFX(CommonInterruptEntry) 77ASM_PFX(CommonInterruptEntry): 78 cli 79 # 80 # All interrupt handlers are invoked through interrupt gates, so 81 # IF flag automatically cleared at the entry point 82 # 83 84 # 85 # Calculate vector number 86 # 87 # Get the return address of call, actually, it is the 88 # address of vector number. 89 # 90 xchgl (%esp), %ecx 91 movw (%ecx), %cx 92 andl $0x0FFFF, %ecx 93 cmpl $32, %ecx # Intel reserved vector for exceptions? 94 jae NoErrorCode 95 bt %ecx, ASM_PFX(mErrorCodeFlag) 96 jc HasErrorCode 97 98NoErrorCode: 99 100 # 101 # Stack: 102 # +---------------------+ 103 # + EFlags + 104 # +---------------------+ 105 # + CS + 106 # +---------------------+ 107 # + EIP + 108 # +---------------------+ 109 # + ECX + 110 # +---------------------+ <-- ESP 111 # 112 # Registers: 113 # ECX - Vector Number 114 # 115 116 # 117 # Put Vector Number on stack 118 # 119 pushl %ecx 120 121 # 122 # Put 0 (dummy) error code on stack, and restore ECX 123 # 124 xorl %ecx, %ecx # ECX = 0 125 xchgl 4(%esp), %ecx 126 127 jmp ErrorCodeAndVectorOnStack 128 129HasErrorCode: 130 131 # 132 # Stack: 133 # +---------------------+ 134 # + EFlags + 135 # +---------------------+ 136 # + CS + 137 # +---------------------+ 138 # + EIP + 139 # +---------------------+ 140 # + Error Code + 141 # +---------------------+ 142 # + ECX + 143 # +---------------------+ <-- ESP 144 # 145 # Registers: 146 # ECX - Vector Number 147 # 148 149 # 150 # Put Vector Number on stack and restore ECX 151 # 152 xchgl (%esp), %ecx 153 154 # 155 # Fall through to join main routine code 156 # at ErrorCodeAndVectorOnStack 157 # 158CommonInterruptEntry_al_0000: 159 jmp CommonInterruptEntry_al_0000 160 161ErrorCodeAndVectorOnStack: 162 pushl %ebp 163 movl %esp, %ebp 164 165 # 166 # Stack: 167 # +---------------------+ 168 # + EFlags + 169 # +---------------------+ 170 # + CS + 171 # +---------------------+ 172 # + EIP + 173 # +---------------------+ 174 # + Error Code + 175 # +---------------------+ 176 # + Vector Number + 177 # +---------------------+ 178 # + EBP + 179 # +---------------------+ <-- EBP 180 # 181 182 # 183 # Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32 184 # is 16-byte aligned 185 # 186 andl $0x0fffffff0, %esp 187 subl $12, %esp 188 189#; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; 190 pushl %eax 191 pushl %ecx 192 pushl %edx 193 pushl %ebx 194 leal 24(%ebp), %ecx 195 pushl %ecx # ESP 196 pushl (%ebp) # EBP 197 pushl %esi 198 pushl %edi 199 200#; UINT32 Gs, Fs, Es, Ds, Cs, Ss; 201 movl %ss, %eax 202 pushl %eax 203 movzwl 16(%ebp), %eax 204 pushl %eax 205 movl %ds, %eax 206 pushl %eax 207 movl %es, %eax 208 pushl %eax 209 movl %fs, %eax 210 pushl %eax 211 movl %gs, %eax 212 pushl %eax 213 214#; UINT32 Eip; 215 movl 12(%ebp), %eax 216 pushl %eax 217 218#; UINT32 Gdtr[2], Idtr[2]; 219 subl $8, %esp 220 sidt (%esp) 221 movl 2(%esp), %eax 222 xchgl (%esp), %eax 223 andl $0x0FFFF, %eax 224 movl %eax, 4(%esp) 225 226 subl $8, %esp 227 sgdt (%esp) 228 movl 2(%esp), %eax 229 xchgl (%esp), %eax 230 andl $0x0FFFF, %eax 231 movl %eax, 4(%esp) 232 233#; UINT32 Ldtr, Tr; 234 xorl %eax, %eax 235 str %ax 236 pushl %eax 237 sldt %ax 238 pushl %eax 239 240#; UINT32 EFlags; 241 movl 20(%ebp), %eax 242 pushl %eax 243 244#; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4; 245 movl %cr4, %eax 246 orl $0x208, %eax 247 movl %eax, %cr4 248 pushl %eax 249 movl %cr3, %eax 250 pushl %eax 251 movl %cr2, %eax 252 pushl %eax 253 xorl %eax, %eax 254 pushl %eax 255 movl %cr0, %eax 256 pushl %eax 257 258#; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; 259 movl %dr7, %eax 260 pushl %eax 261#; clear Dr7 while executing debugger itself 262 xorl %eax, %eax 263 movl %eax, %dr7 264 265 movl %dr6, %eax 266 pushl %eax 267#; insure all status bits in dr6 are clear... 268 xorl %eax, %eax 269 movl %eax, %dr6 270 271 movl %dr3, %eax 272 pushl %eax 273 movl %dr2, %eax 274 pushl %eax 275 movl %dr1, %eax 276 pushl %eax 277 movl %dr0, %eax 278 pushl %eax 279 280#; FX_SAVE_STATE_IA32 FxSaveState; 281 subl $512, %esp 282 movl %esp, %edi 283 .byte 0x0f, 0x0ae, 0x07 #fxsave [edi] 284 285#; UINT32 ExceptionData; 286 pushl 8(%ebp) 287 288#; call into exception handler 289 movl ExternalVectorTablePtr, %eax # get the interrupt vectors base 290 orl %eax, %eax # NULL? 291 jz nullExternalExceptionHandler 292 293 mov 4(%ebp), %ecx 294 movl (%eax,%ecx,4), %eax 295 orl %eax, %eax # NULL? 296 jz nullExternalExceptionHandler 297 298#; Prepare parameter and call 299 movl %esp, %edx 300 pushl %edx 301 movl 4(%ebp), %edx 302 pushl %edx 303 304 # 305 # Call External Exception Handler 306 # 307 call *%eax 308 addl $8, %esp 309 310nullExternalExceptionHandler: 311 312 cli 313#; UINT32 ExceptionData; 314 addl $4, %esp 315 316#; FX_SAVE_STATE_IA32 FxSaveState; 317 movl %esp, %esi 318 .byte 0x0f, 0x0ae, 0x0e # fxrstor [esi] 319 addl $512, %esp 320 321#; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; 322 popl %eax 323 movl %eax, %dr0 324 popl %eax 325 movl %eax, %dr1 326 popl %eax 327 movl %eax, %dr2 328 popl %eax 329 movl %eax, %dr3 330#; skip restore of dr6. We cleared dr6 during the context save. 331 addl $4, %esp 332 popl %eax 333 movl %eax, %dr7 334 335#; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4; 336 popl %eax 337 movl %eax, %cr0 338 addl $4, %esp # not for Cr1 339 popl %eax 340 movl %eax, %cr2 341 popl %eax 342 movl %eax, %cr3 343 popl %eax 344 movl %eax, %cr4 345 346#; UINT32 EFlags; 347 popl 20(%ebp) 348 349#; UINT32 Ldtr, Tr; 350#; UINT32 Gdtr[2], Idtr[2]; 351#; Best not let anyone mess with these particular registers... 352 addl $24, %esp 353 354#; UINT32 Eip; 355 popl 12(%ebp) 356 357#; UINT32 Gs, Fs, Es, Ds, Cs, Ss; 358#; NOTE - modified segment registers could hang the debugger... We 359#; could attempt to insulate ourselves against this possibility, 360#; but that poses risks as well. 361#; 362 popl %gs 363 popl %fs 364 popl %es 365 popl %ds 366 popl 16(%ebp) 367 popl %ss 368 369#; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; 370 popl %edi 371 popl %esi 372 addl $4, %esp # not for ebp 373 addl $4, %esp # not for esp 374 popl %ebx 375 popl %edx 376 popl %ecx 377 popl %eax 378 379 movl %ebp, %esp 380 popl %ebp 381 addl $8, %esp 382 iretl 383 384 385#END 386 387