1/* 2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6/* 7 * Copyright (c) 1989, 1990 William F. Jolitz. 8 * Copyright (c) 1990 The Regents of the University of California. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * $FreeBSD: src/sys/amd64/amd64/exception.S,v 1.113 2003/10/15 02:04:52 peter Exp $ 40 */ 41 42#pragma ident "%Z%%M% %I% %E% SMI" 43 44#include <sys/asm_linkage.h> 45#include <sys/asm_misc.h> 46#include <sys/trap.h> 47#include <sys/psw.h> 48#include <sys/regset.h> 49#include <sys/privregs.h> 50#include <sys/dtrace.h> 51#include <sys/traptrace.h> 52#include <sys/machparam.h> 53 54/* 55 * only one routine in this file is interesting to lint 56 */ 57 58#if defined(__lint) 59 60void 61ndptrap_frstor(void) 62{} 63 64#else 65 66#include "assym.h" 67 68/* 69 * push $0 on stack for traps that do not 70 * generate an error code. This is so the rest 71 * of the kernel can expect a consistent stack 72 * from from any exception. 73 */ 74#define TRAP_NOERR(trapno) \ 75 push $0; \ 76 push $trapno 77 78/* 79 * error code already pushed by hw 80 * onto stack. 81 */ 82#define TRAP_ERR(trapno) \ 83 push $trapno 84 85 /* 86 * #DE 87 */ 88 ENTRY_NP(div0trap) 89 TRAP_NOERR(T_ZERODIV) /* $0 */ 90 jmp cmntrap 91 SET_SIZE(div0trap) 92 93#if defined(__amd64) 94 /* 95 * #DB 96 * 97 * If we get here as a result of single-stepping a sysenter 98 * instruction, we suddenly find ourselves taking a #db 99 * in kernel mode -before- we've swapgs'ed. So before we can 100 * take the trap, we do the swapgs here, and fix the return 101 * %rip in trap() so that we return immediately after the 102 * swapgs in the sysenter handler to avoid doing the swapgs again. 103 * 104 * Nobody said that the design of sysenter was particularly 105 * elegant, did they? 106 */ 107 ENTRY_NP(dbgtrap) 108 pushq %r11 109 leaq sys_sysenter(%rip), %r11 110 cmpq %r11, 8(%rsp) 111 jne 1f 112 swapgs 1131: popq %r11 114 TRAP_NOERR(T_SGLSTP) /* $1 */ 115 jmp cmntrap 116 SET_SIZE(dbgtrap) 117 118#elif defined(__i386) 119 /* 120 * #DB 121 */ 122 ENTRY_NP(dbgtrap) 123 TRAP_NOERR(T_SGLSTP) /* $1 */ 124 jmp cmntrap 125 SET_SIZE(dbgtrap) 126#endif 127 128#if defined(__amd64) 129 130/* 131 * Macro to set the gsbase or kgsbase to the address of the struct cpu 132 * for this processor. If we came from userland, set kgsbase else clear 133 * gs and set gsbase. We find the proper cpu struct by looping through 134 * the cpu structs for all processors till we find a match for the gdt 135 * of the trapping processor. The stack is expected to be pointing at 136 * The standard regs pushed by hardware on a trap (plus error code and trapno). 137 */ 138#define SET_CPU_GSBASE \ 139 subq $REGOFF_TRAPNO, %rsp; /* save regs */ \ 140 movq %rax, REGOFF_RAX(%rsp); \ 141 movq %rbx, REGOFF_RBX(%rsp); \ 142 movq %rcx, REGOFF_RCX(%rsp); \ 143 movq %rdx, REGOFF_RDX(%rsp); \ 144 movq %rbp, REGOFF_RBP(%rsp); \ 145 movq %rsp, %rbp; \ 146 subq $16, %rsp; /* space for gdt */ \ 147 sgdt 6(%rsp); \ 148 movq 8(%rsp), %rcx; /* %rcx has gdt to match */ \ 149 xorl %ebx, %ebx; /* loop index */ \ 150 leaq cpu(%rip), %rdx; /* cpu pointer array */ \ 1511: \ 152 movq (%rdx, %rbx, CLONGSIZE), %rax; /* get cpu[i] */ \ 153 cmpq $0x0, %rax; /* cpu[i] == NULL ? */ \ 154 je 2f; /* yes, continue */ \ 155 cmpq %rcx, CPU_GDT(%rax); /* gdt == cpu[i]->cpu_gdt ? */ \ 156 je 3f; /* yes, go set gsbase */ \ 1572: \ 158 incl %ebx; /* i++ */ \ 159 cmpl $NCPU, %ebx; /* i < NCPU ? */ \ 160 jb 1b; /* yes, loop */ \ 161/* XXX BIG trouble if we fall thru here. We didn't find a gdt match */ \ 1623: \ 163 movl $MSR_AMD_KGSBASE, %ecx; \ 164 cmpw $KCS_SEL, REGOFF_CS(%rbp); /* trap from kernel? */ \ 165 jne 4f; /* no, go set KGSBASE */ \ 166 movl $MSR_AMD_GSBASE, %ecx; /* yes, set GSBASE */ \ 167 mfence; /* OPTERON_ERRATUM_88 */ \ 1684: \ 169 movq %rax, %rdx; /* write base register */ \ 170 shrq $32, %rdx; \ 171 wrmsr; \ 172 movq REGOFF_RDX(%rbp), %rdx; /* restore regs */ \ 173 movq REGOFF_RCX(%rbp), %rcx; \ 174 movq REGOFF_RBX(%rbp), %rbx; \ 175 movq REGOFF_RAX(%rbp), %rax; \ 176 movq %rbp, %rsp; \ 177 movq REGOFF_RBP(%rsp), %rbp; \ 178 addq $REGOFF_TRAPNO, %rsp /* pop stack */ 179#endif /* __amd64 */ 180 181 182 183 184 .globl nmivect 185 .globl idt0_default_r 186 187#if defined(__amd64) 188 189 /* 190 * #NMI 191 */ 192 ENTRY_NP(nmiint) 193 TRAP_NOERR(T_NMIFLT) /* $2 */ 194 195 SET_CPU_GSBASE 196 197 /* 198 * Save all registers and setup segment registers 199 * with kernel selectors. 200 */ 201 INTR_PUSH 202 203 DISABLE_INTR_FLAGS /* and set the kernel flags */ 204 205 TRACE_PTR(%r12, %rax, %eax, %rdx, $TT_TRAP) 206 207 TRACE_REGS(%r12, %rsp, %rax, %rbx) 208 TRACE_STAMP(%r12) 209 210 movq %rsp, %rbp 211 212 movq %rbp, %rdi 213 call av_dispatch_nmivect 214 215 INTR_POP 216 iretq 217 SET_SIZE(nmiint) 218 219#elif defined(__i386) 220 221 /* 222 * #NMI 223 */ 224 ENTRY_NP(nmiint) 225 TRAP_NOERR(T_NMIFLT) /* $2 */ 226 227 /* 228 * Save all registers and setup segment registers 229 * with kernel selectors. 230 */ 231 INTR_PUSH 232 233 /* 234 * setup pointer to reg struct as 2nd argument. 235 */ 236 movl %esp, %ebp 237 pushl %ebp 238 239 DISABLE_INTR_FLAGS 240 241 movl nmivect, %esi /* get autovect structure */ 242loop1: 243 cmpl $0, %esi /* if pointer is null */ 244 je .intr_ret /* we're done */ 245 movl AV_VECTOR(%esi), %edx /* get the interrupt routine */ 246 pushl AV_INTARG1(%esi) /* get argument to interrupt routine */ 247 call *%edx /* call interrupt routine with arg */ 248 addl $4, %esp 249 movl AV_LINK(%esi), %esi /* get next routine on list */ 250 jmp loop1 /* keep looping until end of list */ 251 252.intr_ret: 253 addl $4, %esp /* 'pop' %ebp */ 254 INTR_POP_USER 255 iret 256 SET_SIZE(nmiint) 257 258#endif /* __i386 */ 259 260 /* 261 * #BP 262 */ 263 ENTRY_NP(brktrap) 264#if defined(__amd64) 265 cmpw $KCS_SEL, 8(%rsp) 266 je bp_jmpud 267#endif 268 269 TRAP_NOERR(T_BPTFLT) /* $3 */ 270 jmp dtrace_trap 271 272#if defined(__amd64) 273bp_jmpud: 274 /* 275 * This is a breakpoint in the kernel -- it is very likely that this 276 * is DTrace-induced. To unify DTrace handling, we spoof this as an 277 * invalid opcode (#UD) fault. Note that #BP is a trap, not a fault -- 278 * we must decrement the trapping %rip to make it appear as a fault. 279 * We then push a non-zero error code to indicate that this is coming 280 * from #BP. 281 */ 282 decq (%rsp) 283 push $1 /* error code -- non-zero for #BP */ 284 jmp ud_kernel 285#endif 286 287 SET_SIZE(brktrap) 288 289 /* 290 * #OF 291 */ 292 ENTRY_NP(ovflotrap) 293 TRAP_NOERR(T_OVFLW) /* $4 */ 294 jmp cmntrap 295 SET_SIZE(ovflotrap) 296 297 /* 298 * #BR 299 */ 300 ENTRY_NP(boundstrap) 301 TRAP_NOERR(T_BOUNDFLT) /* $5 */ 302 jmp cmntrap 303 SET_SIZE(boundstrap) 304 305#if defined(__amd64) 306 307 ENTRY_NP(invoptrap) 308 cmpw $KCS_SEL, 8(%rsp) 309 jne ud_user 310 311 push $0 /* error code -- zero for #UD */ 312ud_kernel: 313 push $0xdddd /* a dummy trap number */ 314 TRAP_PUSH 315 movq REGOFF_RIP(%rsp), %rdi 316 movq REGOFF_RSP(%rsp), %rsi 317 movq REGOFF_RAX(%rsp), %rdx 318 pushq (%rsi) 319 movq %rsp, %rsi 320 call dtrace_invop 321 ALTENTRY(dtrace_invop_callsite) 322 addq $8, %rsp 323 cmpl $DTRACE_INVOP_PUSHL_EBP, %eax 324 je ud_push 325 cmpl $DTRACE_INVOP_LEAVE, %eax 326 je ud_leave 327 cmpl $DTRACE_INVOP_NOP, %eax 328 je ud_nop 329 cmpl $DTRACE_INVOP_RET, %eax 330 je ud_ret 331 jmp ud_trap 332 333ud_push: 334 /* 335 * We must emulate a "pushq %rbp". To do this, we pull the stack 336 * down 8 bytes, and then store the base pointer. 337 */ 338 INTR_POP 339 subq $16, %rsp /* make room for %rbp */ 340 pushq %rax /* push temp */ 341 movq 24(%rsp), %rax /* load calling RIP */ 342 addq $1, %rax /* increment over trapping instr */ 343 movq %rax, 8(%rsp) /* store calling RIP */ 344 movq 32(%rsp), %rax /* load calling CS */ 345 movq %rax, 16(%rsp) /* store calling CS */ 346 movq 40(%rsp), %rax /* load calling RFLAGS */ 347 movq %rax, 24(%rsp) /* store calling RFLAGS */ 348 movq 48(%rsp), %rax /* load calling RSP */ 349 subq $8, %rax /* make room for %rbp */ 350 movq %rax, 32(%rsp) /* store calling RSP */ 351 movq 56(%rsp), %rax /* load calling SS */ 352 movq %rax, 40(%rsp) /* store calling SS */ 353 movq 32(%rsp), %rax /* reload calling RSP */ 354 movq %rbp, (%rax) /* store %rbp there */ 355 popq %rax /* pop off temp */ 356 iretq /* return from interrupt */ 357 358ud_leave: 359 /* 360 * We must emulate a "leave", which is the same as a "movq %rbp, %rsp" 361 * followed by a "popq %rbp". This is quite a bit simpler on amd64 362 * than it is on i386 -- we can exploit the fact that the %rsp is 363 * explicitly saved to effect the pop without having to reshuffle 364 * the other data pushed for the trap. 365 */ 366 INTR_POP 367 pushq %rax /* push temp */ 368 movq 8(%rsp), %rax /* load calling RIP */ 369 addq $1, %rax /* increment over trapping instr */ 370 movq %rax, 8(%rsp) /* store calling RIP */ 371 movq (%rbp), %rax /* get new %rbp */ 372 addq $8, %rbp /* adjust new %rsp */ 373 movq %rbp, 32(%rsp) /* store new %rsp */ 374 movq %rax, %rbp /* set new %rbp */ 375 popq %rax /* pop off temp */ 376 iretq /* return from interrupt */ 377 378ud_nop: 379 /* 380 * We must emulate a "nop". This is obviously not hard: we need only 381 * advance the %rip by one. 382 */ 383 INTR_POP 384 incq (%rsp) 385 iretq 386 387ud_ret: 388 INTR_POP 389 pushq %rax /* push temp */ 390 movq 32(%rsp), %rax /* load %rsp */ 391 movq (%rax), %rax /* load calling RIP */ 392 movq %rax, 8(%rsp) /* store calling RIP */ 393 addq $8, 32(%rsp) /* adjust new %rsp */ 394 popq %rax /* pop off temp */ 395 iretq /* return from interrupt */ 396 397ud_trap: 398 /* 399 * We're going to let the kernel handle this as a normal #UD. If, 400 * however, we came through #BP and are spoofing #UD (in this case, 401 * the stored error value will be non-zero), we need to de-spoof 402 * the trap by incrementing %rip and pushing T_BPTFLT. 403 */ 404 cmpq $0, REGOFF_ERR(%rsp) 405 je ud_ud 406 incq REGOFF_RIP(%rsp) 407 addq $REGOFF_RIP, %rsp 408 TRAP_NOERR(T_BPTFLT) /* $3 */ 409 jmp cmntrap 410 411ud_ud: 412 addq $REGOFF_RIP, %rsp 413ud_user: 414 TRAP_NOERR(T_ILLINST) 415 jmp cmntrap 416 SET_SIZE(invoptrap) 417 418#elif defined(__i386) 419 420 /* 421 * #UD 422 */ 423 ENTRY_NP(invoptrap) 424 /* 425 * If we are taking an invalid opcode trap while in the kernel, this 426 * is likely an FBT probe point. 427 */ 428 pushl %gs 429 cmpw $KGS_SEL, (%esp) 430 jne 8f 431 addl $4, %esp 432 pusha 433 pushl %eax /* push %eax -- may be return value */ 434 pushl %esp /* push stack pointer */ 435 addl $48, (%esp) /* adjust to incoming args */ 436 pushl 40(%esp) /* push calling EIP */ 437 call dtrace_invop 438 ALTENTRY(dtrace_invop_callsite) 439 addl $12, %esp 440 cmpl $DTRACE_INVOP_PUSHL_EBP, %eax 441 je 1f 442 cmpl $DTRACE_INVOP_POPL_EBP, %eax 443 je 2f 444 cmpl $DTRACE_INVOP_LEAVE, %eax 445 je 3f 446 cmpl $DTRACE_INVOP_NOP, %eax 447 je 4f 448 jmp 7f 449 4501: 451 /* 452 * We must emulate a "pushl %ebp". To do this, we pull the stack 453 * down 4 bytes, and then store the base pointer. 454 */ 455 popa 456 subl $4, %esp /* make room for %ebp */ 457 pushl %eax /* push temp */ 458 movl 8(%esp), %eax /* load calling EIP */ 459 incl %eax /* increment over LOCK prefix */ 460 movl %eax, 4(%esp) /* store calling EIP */ 461 movl 12(%esp), %eax /* load calling CS */ 462 movl %eax, 8(%esp) /* store calling CS */ 463 movl 16(%esp), %eax /* load calling EFLAGS */ 464 movl %eax, 12(%esp) /* store calling EFLAGS */ 465 movl %ebp, 16(%esp) /* push %ebp */ 466 popl %eax /* pop off temp */ 467 iret /* return from interrupt */ 468 4692: 470 /* 471 * We must emulate a "popl %ebp". To do this, we do the opposite of 472 * the above: we remove the %ebp from the stack, and squeeze up the 473 * saved state from the trap. 474 */ 475 popa 476 pushl %eax /* push temp */ 477 movl 16(%esp), %ebp /* pop %ebp */ 478 movl 12(%esp), %eax /* load calling EFLAGS */ 479 movl %eax, 16(%esp) /* store calling EFLAGS */ 480 movl 8(%esp), %eax /* load calling CS */ 481 movl %eax, 12(%esp) /* store calling CS */ 482 movl 4(%esp), %eax /* load calling EIP */ 483 incl %eax /* increment over LOCK prefix */ 484 movl %eax, 8(%esp) /* store calling EIP */ 485 popl %eax /* pop off temp */ 486 addl $4, %esp /* adjust stack pointer */ 487 iret /* return from interrupt */ 488 4893: 490 /* 491 * We must emulate a "leave", which is the same as a "movl %ebp, %esp" 492 * followed by a "popl %ebp". This looks similar to the above, but 493 * requires two temporaries: one for the new base pointer, and one 494 * for the staging register. 495 */ 496 popa 497 pushl %eax /* push temp */ 498 pushl %ebx /* push temp */ 499 movl %ebp, %ebx /* set temp to old %ebp */ 500 movl (%ebx), %ebp /* pop %ebp */ 501 movl 16(%esp), %eax /* load calling EFLAGS */ 502 movl %eax, (%ebx) /* store calling EFLAGS */ 503 movl 12(%esp), %eax /* load calling CS */ 504 movl %eax, -4(%ebx) /* store calling CS */ 505 movl 8(%esp), %eax /* load calling EIP */ 506 incl %eax /* increment over LOCK prefix */ 507 movl %eax, -8(%ebx) /* store calling EIP */ 508 movl %ebx, -4(%esp) /* temporarily store new %esp */ 509 popl %ebx /* pop off temp */ 510 popl %eax /* pop off temp */ 511 movl -12(%esp), %esp /* set stack pointer */ 512 subl $8, %esp /* adjust for three pushes, one pop */ 513 iret /* return from interrupt */ 514 5154: 516 /* 517 * We must emulate a "nop". This is obviously not hard: we need only 518 * advance the %eip by one. 519 */ 520 popa 521 incl (%esp) 522 iret 523 5247: 525 popa 526 pushl $0 527 pushl $T_ILLINST /* $6 */ 528 jmp cmntrap 5298: 530 addl $4, %esp 531 pushl $0 532 pushl $T_ILLINST /* $6 */ 533 jmp cmntrap 534 SET_SIZE(invoptrap) 535 536#endif /* __i386 */ 537 538#if defined(__amd64) 539 540 /* 541 * #NM 542 */ 543 ENTRY_NP(ndptrap) 544 /* 545 * We want to do this quickly as every lwp using fp will take this 546 * after a context switch -- we do the frequent path in ndptrap_frstor 547 * below; for all other cases, we let the trap code handle it 548 */ 549 pushq %rax 550 pushq %rbx 551 cmpw $KCS_SEL, 24(%rsp) /* did we come from kernel mode? */ 552 jne 1f 553 LOADCPU(%rbx) /* if yes, don't swapgs */ 554 jmp 2f 5551: 556 swapgs /* if from user, need swapgs */ 557 LOADCPU(%rbx) 558 swapgs 5592: 560 cmpl $0, fpu_exists(%rip) 561 je .handle_in_trap /* let trap handle no fp case */ 562 movq CPU_THREAD(%rbx), %rax /* %rax = curthread */ 563 movl $FPU_EN, %ebx 564 movq T_LWP(%rax), %rax /* %rax = lwp */ 565 testq %rax, %rax 566 jz .handle_in_trap /* should not happen? */ 567#if LWP_PCB_FPU != 0 568 addq $LWP_PCB_FPU, %rax /* &lwp->lwp_pcb.pcb_fpu */ 569#endif 570 testl %ebx, PCB_FPU_FLAGS(%rax) 571 jz .handle_in_trap /* must be the first fault */ 572 clts 573 andl $_BITNOT(FPU_VALID), PCB_FPU_FLAGS(%rax) 574#if FPU_CTX_FPU_REGS != 0 575 addq $FPU_CTX_FPU_REGS, %rax 576#endif 577 /* 578 * the label below is used in trap.c to detect FP faults in 579 * kernel due to user fault. 580 */ 581 ALTENTRY(ndptrap_frstor) 582 fxrstor (%rax) 583 popq %rbx 584 popq %rax 585 iretq 586 587.handle_in_trap: 588 popq %rbx 589 popq %rax 590 TRAP_NOERR(T_NOEXTFLT) /* $7 */ 591 jmp cmninttrap 592 SET_SIZE(ndptrap_frstor) 593 SET_SIZE(ndptrap) 594 595#elif defined(__i386) 596 597 ENTRY_NP(ndptrap) 598 /* 599 * We want to do this quickly as every lwp using fp will take this 600 * after a context switch -- we do the frequent path in fpnoextflt 601 * below; for all other cases, we let the trap code handle it 602 */ 603 pushl %eax 604 pushl %ebx 605 pushl %ds 606 pushl %gs 607 movl $KDS_SEL, %ebx 608 movw %bx, %ds 609 movl $KGS_SEL, %eax 610 movw %ax, %gs 611 LOADCPU(%ebx) 612 cmpl $0, fpu_exists 613 je .handle_in_trap /* let trap handle no fp case */ 614 movl CPU_THREAD(%ebx), %eax /* %eax = curthread */ 615 movl $FPU_EN, %ebx 616 movl T_LWP(%eax), %eax /* %eax = lwp */ 617 testl %eax, %eax 618 jz .handle_in_trap /* should not happen? */ 619#if LWP_PCB_FPU != 0 620 addl $LWP_PCB_FPU, %eax /* &lwp->lwp_pcb.pcb_fpu */ 621#endif 622 testl %ebx, PCB_FPU_FLAGS(%eax) 623 jz .handle_in_trap /* must be the first fault */ 624 clts 625 andl $_BITNOT(FPU_VALID), PCB_FPU_FLAGS(%eax) 626#if FPU_CTX_FPU_REGS != 0 627 addl $FPU_CTX_FPU_REGS, %eax 628#endif 629 /* 630 * the label below is used in trap.c to detect FP faults in kernel 631 * due to user fault. 632 */ 633 ALTENTRY(ndptrap_frstor) 634 .globl _patch_fxrstor_eax 635_patch_fxrstor_eax: 636 frstor (%eax) /* may be patched to fxrstor */ 637 nop /* (including this byte) */ 638 popl %gs 639 popl %ds 640 popl %ebx 641 popl %eax 642 iret 643 644.handle_in_trap: 645 popl %gs 646 popl %ds 647 popl %ebx 648 popl %eax 649 pushl $0 650 pushl $T_NOEXTFLT /* $7 */ 651 jmp cmninttrap 652 SET_SIZE(ndptrap_frstor) 653 SET_SIZE(ndptrap) 654 655#endif /* __i386 */ 656 657#if defined(__amd64) 658 659 /* 660 * #DF 661 */ 662 ENTRY_NP(syserrtrap) 663 pushq $T_DBLFLT 664 665 SET_CPU_GSBASE 666 667 /* 668 * We share this handler with kmdb (if kmdb is loaded). As such, we may 669 * have reached this point after encountering a #df in kmdb. If that 670 * happens, we'll still be on kmdb's IDT. We need to switch back to this 671 * CPU's IDT before proceeding. Furthermore, if we did arrive here from 672 * kmdb, kmdb is probably in a very sickly state, and shouldn't be 673 * entered from the panic flow. We'll suppress that entry by setting 674 * nopanicdebug. 675 */ 676 pushq %rax 677 subq $DESCTBR_SIZE, %rsp 678 sidt (%rsp) 679 movq %gs:CPU_IDT, %rax 680 cmpq %rax, DTR_BASE(%rsp) 681 je 1f 682 683 movq %rax, DTR_BASE(%rsp) 684 movw $_MUL(NIDT, GATE_DESC_SIZE), DTR_LIMIT(%rsp) 685 lidt (%rsp) 686 687 movl $1, nopanicdebug 688 6891: addq $DESCTBR_SIZE, %rsp 690 popq %rax 691 692 DFTRAP_PUSH 693 694 /* 695 * freeze trap trace. 696 */ 697#ifdef TRAPTRACE 698 leaq trap_trace_freeze(%rip), %r11 699 incl (%r11) 700#endif 701 702 ENABLE_INTR_FLAGS 703 704 movq %rsp, %rdi /* ®s */ 705 xorl %esi, %esi /* clear address */ 706 xorl %edx, %edx /* cpuid = 0 */ 707 call trap 708 709 SET_SIZE(syserrtrap) 710 711#elif defined(__i386) 712 713 /* 714 * #DF 715 */ 716 ENTRY_NP(syserrtrap) 717 cli /* disable interrupts */ 718 719 /* 720 * We share this handler with kmdb (if kmdb is loaded). As such, we may 721 * have reached this point after encountering a #df in kmdb. If that 722 * happens, we'll still be on kmdb's IDT. We need to switch back to this 723 * CPU's IDT before proceeding. Furthermore, if we did arrive here from 724 * kmdb, kmdb is probably in a very sickly state, and shouldn't be 725 * entered from the panic flow. We'll suppress that entry by setting 726 * nopanicdebug. 727 */ 728 subl $DESCTBR_SIZE, %esp 729 movl %gs:CPU_IDT, %eax 730 sidt (%esp) 731 cmpl DTR_BASE(%esp), %eax 732 je 1f 733 734 movl %eax, DTR_BASE(%esp) 735 movw $_MUL(NIDT, GATE_DESC_SIZE), DTR_LIMIT(%esp) 736 lidt (%esp) 737 738 movl $1, nopanicdebug 739 7401: addl $DESCTBR_SIZE, %esp 741 742 /* 743 * Check the CPL in the TSS to see what mode 744 * (user or kernel) we took the fault in. At this 745 * point we are running in the context of the double 746 * fault task (dftss) but the CPU's task points to 747 * the previous task (ktss) where the process context 748 * has been saved as the result of the task switch. 749 */ 750 movl %gs:CPU_TSS, %eax /* get the TSS */ 751 movl TSS_SS(%eax), %ebx /* save the fault SS */ 752 movl TSS_ESP(%eax), %edx /* save the fault ESP */ 753 testw $CPL_MASK, TSS_CS(%eax) /* user mode ? */ 754 jz make_frame 755 movw TSS_SS0(%eax), %ss /* get on the kernel stack */ 756 movl TSS_ESP0(%eax), %esp 757 758 /* 759 * Clear the NT flag to avoid a task switch when the process 760 * finally pops the EFL off the stack via an iret. Clear 761 * the TF flag since that is what the processor does for 762 * a normal exception. Clear the IE flag so that interrupts 763 * remain disabled. 764 */ 765 movl TSS_EFL(%eax), %ecx 766 andl $_BITNOT(PS_NT|PS_T|PS_IE), %ecx 767 pushl %ecx 768 popfl /* restore the EFL */ 769 movw TSS_LDT(%eax), %cx /* restore the LDT */ 770 lldt %cx 771 772 /* 773 * Restore process segment selectors. 774 */ 775 movw TSS_DS(%eax), %ds 776 movw TSS_ES(%eax), %es 777 movw TSS_FS(%eax), %fs 778 movw TSS_GS(%eax), %gs 779 780 /* 781 * Restore task segment selectors. 782 */ 783 movl $KDS_SEL, TSS_DS(%eax) 784 movl $KDS_SEL, TSS_ES(%eax) 785 movl $KDS_SEL, TSS_SS(%eax) 786 movl $KFS_SEL, TSS_FS(%eax) 787 movl $KGS_SEL, TSS_GS(%eax) 788 789 /* 790 * Clear the TS bit, the busy bits in both task 791 * descriptors, and switch tasks. 792 */ 793 clts 794 leal gdt0, %ecx 795 movl DFTSS_SEL+4(%ecx), %esi 796 andl $_BITNOT(0x200), %esi 797 movl %esi, DFTSS_SEL+4(%ecx) 798 movl KTSS_SEL+4(%ecx), %esi 799 andl $_BITNOT(0x200), %esi 800 movl %esi, KTSS_SEL+4(%ecx) 801 movw $KTSS_SEL, %cx 802 ltr %cx 803 804 /* 805 * Restore part of the process registers. 806 */ 807 movl TSS_EBP(%eax), %ebp 808 movl TSS_ECX(%eax), %ecx 809 movl TSS_ESI(%eax), %esi 810 movl TSS_EDI(%eax), %edi 811 812make_frame: 813 /* 814 * Make a trap frame. Leave the error code (0) on 815 * the stack since the first word on a trap stack is 816 * unused anyway. 817 */ 818 pushl %ebx / fault SS 819 pushl %edx / fault ESP 820 pushl TSS_EFL(%eax) / fault EFL 821 pushl TSS_CS(%eax) / fault CS 822 pushl TSS_EIP(%eax) / fault EIP 823 pushl $0 / error code 824 pushl $T_DBLFLT / trap number 8 825 movl TSS_EBX(%eax), %ebx / restore EBX 826 movl TSS_EDX(%eax), %edx / restore EDX 827 movl TSS_EAX(%eax), %eax / restore EAX 828 sti / enable interrupts 829 jmp cmntrap 830 SET_SIZE(syserrtrap) 831 832#endif /* __i386 */ 833 834 ENTRY_NP(overrun) 835 push $0 836 TRAP_NOERR(T_EXTOVRFLT) /* $9 i386 only - not generated */ 837 jmp cmninttrap 838 SET_SIZE(overrun) 839 840 /* 841 * #TS 842 */ 843 ENTRY_NP(invtsstrap) 844 TRAP_ERR(T_TSSFLT) /* $10 already have error code on stack */ 845 jmp cmntrap 846 SET_SIZE(invtsstrap) 847 848 /* 849 * #NP 850 */ 851 ENTRY_NP(segnptrap) 852 TRAP_ERR(T_SEGFLT) /* $11 already have error code on stack */ 853#if defined(__amd64) 854 SET_CPU_GSBASE 855#endif 856 jmp cmntrap 857 SET_SIZE(segnptrap) 858 859 /* 860 * #SS 861 */ 862 ENTRY_NP(stktrap) 863 TRAP_ERR(T_STKFLT) /* $12 already have error code on stack */ 864 jmp cmntrap 865 SET_SIZE(stktrap) 866 867 /* 868 * #GP 869 */ 870 ENTRY_NP(gptrap) 871 TRAP_ERR(T_GPFLT) /* $13 already have error code on stack */ 872#if defined(__amd64) 873 SET_CPU_GSBASE 874#endif 875 jmp cmntrap 876 SET_SIZE(gptrap) 877 878 /* 879 * #PF 880 */ 881 ENTRY_NP(pftrap) 882 TRAP_ERR(T_PGFLT) /* $14 already have error code on stack */ 883 jmp cmntrap 884 SET_SIZE(pftrap) 885 886#if !defined(__amd64) 887 888 /* 889 * #PF pentium bug workaround 890 */ 891 ENTRY_NP(pentium_pftrap) 892 pushl %eax 893 movl %cr2, %eax 894 andl $MMU_STD_PAGEMASK, %eax 895 896 cmpl %eax, %cs:idt0_default_r+2 /* fixme */ 897 898 je check_for_user_address 899user_mode: 900 popl %eax 901 pushl $T_PGFLT /* $14 */ 902 jmp cmntrap 903check_for_user_address: 904 /* 905 * Before we assume that we have an unmapped trap on our hands, 906 * check to see if this is a fault from user mode. If it is, 907 * we'll kick back into the page fault handler. 908 */ 909 movl 4(%esp), %eax /* error code */ 910 andl $PF_ERR_USER, %eax 911 jnz user_mode 912 913 /* 914 * We now know that this is the invalid opcode trap. 915 */ 916 popl %eax 917 addl $4, %esp /* pop error code */ 918 jmp invoptrap 919 SET_SIZE(pentium_pftrap) 920 921#endif /* !__amd64 */ 922 923 ENTRY_NP(resvtrap) 924 TRAP_NOERR(15) /* (reserved) */ 925 jmp cmntrap 926 SET_SIZE(resvtrap) 927 928 /* 929 * #MF 930 */ 931 ENTRY_NP(ndperr) 932 TRAP_NOERR(T_EXTERRFLT) /* $16 */ 933 jmp cmninttrap 934 SET_SIZE(ndperr) 935 936 /* 937 * #AC 938 */ 939 ENTRY_NP(achktrap) 940 TRAP_ERR(T_ALIGNMENT) /* $17 */ 941 jmp cmntrap 942 SET_SIZE(achktrap) 943 944 /* 945 * #MC 946 */ 947 .globl cmi_mca_trap /* see uts/i86pc/os/cmi.c */ 948 949#if defined(__amd64) 950 951 ENTRY_NP(mcetrap) 952 TRAP_NOERR(T_MCE) /* $18 */ 953 SET_CPU_GSBASE 954 INTR_PUSH 955 956 TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_TRAP) 957 TRACE_REGS(%rdi, %rsp, %rbx, %rcx) 958 TRACE_STAMP(%rdi) 959 960 DISABLE_INTR_FLAGS 961 movq %rsp, %rbp 962 963 movq %rsp, %rdi /* arg0 = struct regs *rp */ 964 call cmi_mca_trap /* cmi_mca_trap(rp); */ 965 966 jmp _sys_rtt 967 SET_SIZE(mcetrap) 968 969#else 970 971 ENTRY_NP(mcetrap) 972 TRAP_NOERR(T_MCE) /* $18 */ 973 INTR_PUSH 974 975 DISABLE_INTR_FLAGS 976 movl %esp, %ebp 977 978 movl %esp, %ecx 979 pushl %ecx /* arg0 = struct regs *rp */ 980 call cmi_mca_trap /* cmi_mca_trap(rp) */ 981 addl $4, %esp /* pop arg0 */ 982 983 jmp _sys_rtt 984 SET_SIZE(mcetrap) 985 986#endif 987 988 /* 989 * #XF 990 */ 991 ENTRY_NP(xmtrap) 992 TRAP_NOERR(T_SIMDFPE) /* $19 */ 993 jmp cmntrap 994 SET_SIZE(xmtrap) 995 996 ENTRY_NP(invaltrap) 997 TRAP_NOERR(30) /* very invalid */ 998 jmp cmntrap 999 SET_SIZE(invaltrap) 1000 1001 ENTRY_NP(invalint) 1002 TRAP_NOERR(31) /* even more so */ 1003 jmp cmnint 1004 SET_SIZE(invalint) 1005 1006 .globl fasttable 1007 1008#if defined(__amd64) 1009 1010 ENTRY_NP(fasttrap) 1011 cmpl $T_LASTFAST, %eax 1012 ja 1f 1013 orl %eax, %eax /* (zero extend top 32-bits) */ 1014 leaq fasttable(%rip), %r11 1015 leaq (%r11, %rax, CLONGSIZE), %r11 1016 jmp *(%r11) 10171: 1018 /* 1019 * Fast syscall number was illegal. Make it look 1020 * as if the INT failed. Modify %rip to point before the 1021 * INT, push the expected error code and fake a GP fault. 1022 * 1023 * XXX Why make the error code be offset into idt + 1? 1024 * Instead we should push a real (soft?) error code 1025 * on the stack and #gp handler could know about fasttraps? 1026 */ 1027 subq $2, (%rsp) /* XXX int insn 2-bytes */ 1028 pushq $_CONST(_MUL(T_FASTTRAP, GATE_DESC_SIZE) + 2) 1029 jmp gptrap 1030 SET_SIZE(fasttrap) 1031 1032#elif defined(__i386) 1033 1034 ENTRY_NP(fasttrap) 1035 cmpl $T_LASTFAST, %eax 1036 ja 1f 1037 jmp *%cs:fasttable(, %eax, CLONGSIZE) 10381: 1039 /* 1040 * Fast syscall number was illegal. Make it look 1041 * as if the INT failed. Modify %eip to point before the 1042 * INT, push the expected error code and fake a GP fault. 1043 * 1044 * XXX Why make the error code be offset into idt + 1? 1045 * Instead we should push a real (soft?) error code 1046 * on the stack and #gp handler could know about fasttraps? 1047 */ 1048 subl $2, (%esp) /* XXX int insn 2-bytes */ 1049 pushl $_CONST(_MUL(T_FASTTRAP, GATE_DESC_SIZE) + 2) 1050 jmp gptrap 1051 SET_SIZE(fasttrap) 1052 1053#endif /* __i386 */ 1054 1055 ENTRY_NP(dtrace_ret) 1056 TRAP_NOERR(T_DTRACE_RET) 1057 jmp dtrace_trap 1058 SET_SIZE(dtrace_ret) 1059 1060#if defined(__amd64) 1061 1062 /* 1063 * RFLAGS 24 bytes up the stack from %rsp. 1064 * XXX a constant would be nicer. 1065 */ 1066 ENTRY_NP(fast_null) 1067 orq $PS_C, 24(%rsp) /* set carry bit in user flags */ 1068 iretq 1069 SET_SIZE(fast_null) 1070 1071#elif defined(__i386) 1072 1073 ENTRY_NP(fast_null) 1074 orw $PS_C, 8(%esp) /* set carry bit in user flags */ 1075 iret 1076 SET_SIZE(fast_null) 1077 1078#endif /* __i386 */ 1079 1080 /* 1081 * Interrupts start at 32 1082 */ 1083#define MKIVCT(n) \ 1084 ENTRY_NP(ivct/**/n) \ 1085 push $0; \ 1086 push $n - 0x20; \ 1087 jmp cmnint; \ 1088 SET_SIZE(ivct/**/n) 1089 1090 MKIVCT(32) 1091 MKIVCT(33) 1092 MKIVCT(34) 1093 MKIVCT(35) 1094 MKIVCT(36) 1095 MKIVCT(37) 1096 MKIVCT(38) 1097 MKIVCT(39) 1098 MKIVCT(40) 1099 MKIVCT(41) 1100 MKIVCT(42) 1101 MKIVCT(43) 1102 MKIVCT(44) 1103 MKIVCT(45) 1104 MKIVCT(46) 1105 MKIVCT(47) 1106 MKIVCT(48) 1107 MKIVCT(49) 1108 MKIVCT(50) 1109 MKIVCT(51) 1110 MKIVCT(52) 1111 MKIVCT(53) 1112 MKIVCT(54) 1113 MKIVCT(55) 1114 MKIVCT(56) 1115 MKIVCT(57) 1116 MKIVCT(58) 1117 MKIVCT(59) 1118 MKIVCT(60) 1119 MKIVCT(61) 1120 MKIVCT(62) 1121 MKIVCT(63) 1122 MKIVCT(64) 1123 MKIVCT(65) 1124 MKIVCT(66) 1125 MKIVCT(67) 1126 MKIVCT(68) 1127 MKIVCT(69) 1128 MKIVCT(70) 1129 MKIVCT(71) 1130 MKIVCT(72) 1131 MKIVCT(73) 1132 MKIVCT(74) 1133 MKIVCT(75) 1134 MKIVCT(76) 1135 MKIVCT(77) 1136 MKIVCT(78) 1137 MKIVCT(79) 1138 MKIVCT(80) 1139 MKIVCT(81) 1140 MKIVCT(82) 1141 MKIVCT(83) 1142 MKIVCT(84) 1143 MKIVCT(85) 1144 MKIVCT(86) 1145 MKIVCT(87) 1146 MKIVCT(88) 1147 MKIVCT(89) 1148 MKIVCT(90) 1149 MKIVCT(91) 1150 MKIVCT(92) 1151 MKIVCT(93) 1152 MKIVCT(94) 1153 MKIVCT(95) 1154 MKIVCT(96) 1155 MKIVCT(97) 1156 MKIVCT(98) 1157 MKIVCT(99) 1158 MKIVCT(100) 1159 MKIVCT(101) 1160 MKIVCT(102) 1161 MKIVCT(103) 1162 MKIVCT(104) 1163 MKIVCT(105) 1164 MKIVCT(106) 1165 MKIVCT(107) 1166 MKIVCT(108) 1167 MKIVCT(109) 1168 MKIVCT(110) 1169 MKIVCT(111) 1170 MKIVCT(112) 1171 MKIVCT(113) 1172 MKIVCT(114) 1173 MKIVCT(115) 1174 MKIVCT(116) 1175 MKIVCT(117) 1176 MKIVCT(118) 1177 MKIVCT(119) 1178 MKIVCT(120) 1179 MKIVCT(121) 1180 MKIVCT(122) 1181 MKIVCT(123) 1182 MKIVCT(124) 1183 MKIVCT(125) 1184 MKIVCT(126) 1185 MKIVCT(127) 1186 MKIVCT(128) 1187 MKIVCT(129) 1188 MKIVCT(130) 1189 MKIVCT(131) 1190 MKIVCT(132) 1191 MKIVCT(133) 1192 MKIVCT(134) 1193 MKIVCT(135) 1194 MKIVCT(136) 1195 MKIVCT(137) 1196 MKIVCT(138) 1197 MKIVCT(139) 1198 MKIVCT(140) 1199 MKIVCT(141) 1200 MKIVCT(142) 1201 MKIVCT(143) 1202 MKIVCT(144) 1203 MKIVCT(145) 1204 MKIVCT(146) 1205 MKIVCT(147) 1206 MKIVCT(148) 1207 MKIVCT(149) 1208 MKIVCT(150) 1209 MKIVCT(151) 1210 MKIVCT(152) 1211 MKIVCT(153) 1212 MKIVCT(154) 1213 MKIVCT(155) 1214 MKIVCT(156) 1215 MKIVCT(157) 1216 MKIVCT(158) 1217 MKIVCT(159) 1218 MKIVCT(160) 1219 MKIVCT(161) 1220 MKIVCT(162) 1221 MKIVCT(163) 1222 MKIVCT(164) 1223 MKIVCT(165) 1224 MKIVCT(166) 1225 MKIVCT(167) 1226 MKIVCT(168) 1227 MKIVCT(169) 1228 MKIVCT(170) 1229 MKIVCT(171) 1230 MKIVCT(172) 1231 MKIVCT(173) 1232 MKIVCT(174) 1233 MKIVCT(175) 1234 MKIVCT(176) 1235 MKIVCT(177) 1236 MKIVCT(178) 1237 MKIVCT(179) 1238 MKIVCT(180) 1239 MKIVCT(181) 1240 MKIVCT(182) 1241 MKIVCT(183) 1242 MKIVCT(184) 1243 MKIVCT(185) 1244 MKIVCT(186) 1245 MKIVCT(187) 1246 MKIVCT(188) 1247 MKIVCT(189) 1248 MKIVCT(190) 1249 MKIVCT(191) 1250 MKIVCT(192) 1251 MKIVCT(193) 1252 MKIVCT(194) 1253 MKIVCT(195) 1254 MKIVCT(196) 1255 MKIVCT(197) 1256 MKIVCT(198) 1257 MKIVCT(199) 1258 MKIVCT(200) 1259 MKIVCT(201) 1260 MKIVCT(202) 1261 MKIVCT(203) 1262 MKIVCT(204) 1263 MKIVCT(205) 1264 MKIVCT(206) 1265 MKIVCT(207) 1266 MKIVCT(208) 1267 MKIVCT(209) 1268 MKIVCT(210) 1269 MKIVCT(211) 1270 MKIVCT(212) 1271 MKIVCT(213) 1272 MKIVCT(214) 1273 MKIVCT(215) 1274 MKIVCT(216) 1275 MKIVCT(217) 1276 MKIVCT(218) 1277 MKIVCT(219) 1278 MKIVCT(220) 1279 MKIVCT(221) 1280 MKIVCT(222) 1281 MKIVCT(223) 1282 MKIVCT(224) 1283 MKIVCT(225) 1284 MKIVCT(226) 1285 MKIVCT(227) 1286 MKIVCT(228) 1287 MKIVCT(229) 1288 MKIVCT(230) 1289 MKIVCT(231) 1290 MKIVCT(232) 1291 MKIVCT(233) 1292 MKIVCT(234) 1293 MKIVCT(235) 1294 MKIVCT(236) 1295 MKIVCT(237) 1296 MKIVCT(238) 1297 MKIVCT(239) 1298 MKIVCT(240) 1299 MKIVCT(241) 1300 MKIVCT(242) 1301 MKIVCT(243) 1302 MKIVCT(244) 1303 MKIVCT(245) 1304 MKIVCT(246) 1305 MKIVCT(247) 1306 MKIVCT(248) 1307 MKIVCT(249) 1308 MKIVCT(250) 1309 MKIVCT(251) 1310 MKIVCT(252) 1311 MKIVCT(253) 1312 MKIVCT(254) 1313 MKIVCT(255) 1314 1315#endif /* __lint */ 1316