1/* 2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 29 * @OSF_COPYRIGHT@ 30 */ 31/* 32 * Mach Operating System 33 * Copyright (c) 1991,1990 Carnegie Mellon University 34 * All Rights Reserved. 35 * 36 * Permission to use, copy, modify and distribute this software and its 37 * documentation is hereby granted, provided that both the copyright 38 * notice and this permission notice appear in all copies of the 39 * software, derivative works or modified versions, and any portions 40 * thereof, and that both notices appear in supporting documentation. 41 * 42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 44 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 45 * 46 * Carnegie Mellon requests users of this software to return to 47 * 48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 49 * School of Computer Science 50 * Carnegie Mellon University 51 * Pittsburgh PA 15213-3890 52 * 53 * any improvements or extensions that they make and grant Carnegie Mellon 54 * the rights to redistribute these changes. 55 */ 56/* 57 */ 58#include <i386/asm.h> 59#include <assym.s> 60#include <mach_kdb.h> 61#include <i386/eflags.h> 62#include <i386/trap.h> 63 64#define HI_DATA(lo_addr) ( (EXT(lo_addr) - EXT(hi_remap_data)) + HIGH_IDT_BASE ) 65#define HI_TEXT(lo_text) ( (EXT(lo_text) - EXT(hi_remap_text)) + HIGH_MEM_BASE ) 66 67/* 68 * Interrupt descriptor table and code vectors for it. 69 */ 70#define IDT_BASE_ENTRY(vec,seg,type) \ 71 .data ;\ 72 .long EXT(vec) - EXT(hi_remap_text) + HIGH_MEM_BASE ; \ 73 .word seg ;\ 74 .byte 0 ;\ 75 .byte type ;\ 76 .text 77 78#define IDT_BASE_ENTRY_INT(vec,seg,type) \ 79 .data ;\ 80 .long vec - EXT(hi_remap_text) + HIGH_MEM_BASE ; \ 81 .word seg ;\ 82 .byte 0 ;\ 83 .byte type ;\ 84 .text 85 86#define IDT_BASE_ENTRY_TG(vec,seg,type) \ 87 .data ;\ 88 .long 0 ; \ 89 .word seg ;\ 90 .byte 0 ;\ 91 .byte type ;\ 92 .text 93 94#define IDT_ENTRY(vec,type) IDT_BASE_ENTRY(vec,KERNEL_CS,type) 95#define IDT_ENTRY_INT(vec,type) IDT_BASE_ENTRY_INT(vec,KERNEL_CS,type) 96 97/* 98 * No error code. Clear error code and push trap number. 99 */ 100#define EXCEPTION(n,name) \ 101 IDT_ENTRY(name,K_INTR_GATE);\ 102Entry(name) ;\ 103 pushl $0 ;\ 104 pushl $(n) ;\ 105 pusha ;\ 106 movl $ EXT(lo_alltraps),%ebx ;\ 107 jmp enter_lohandler 108 109 110/* 111 * Interrupt from user. Clear error code and push trap number. 112 */ 113#define EXCEP_USR(n,name) \ 114 IDT_ENTRY(name,U_INTR_GATE);\ 115Entry(name) ;\ 116 pushl $0 ;\ 117 pushl $(n) ;\ 118 pusha ;\ 119 movl $ EXT(lo_alltraps),%ebx ;\ 120 jmp enter_lohandler 121 122 123/* 124 * Special interrupt code. 125 */ 126#define EXCEP_SPC(n,name) \ 127 IDT_ENTRY(name,K_INTR_GATE) 128 129/* 130 * Special interrupt code from user. 131 */ 132#define EXCEP_SPC_USR(n,name) \ 133 IDT_ENTRY(name,U_INTR_GATE) 134 135 136/* 137 * Extra-special interrupt code. Note that no offset may be 138 * specified in a task gate descriptor, so name is ignored. 139 */ 140#define EXCEP_TASK(n,name) \ 141 IDT_BASE_ENTRY_TG(0,DEBUG_TSS,K_TASK_GATE) 142 143/* Double-fault fatal handler */ 144#define DF_FATAL_TASK(n,name) \ 145 IDT_BASE_ENTRY_TG(0,DF_TSS,K_TASK_GATE) 146 147/* machine-check handler */ 148#define MC_FATAL_TASK(n,name) \ 149 IDT_BASE_ENTRY_TG(0,MC_TSS,K_TASK_GATE) 150 151/* 152 * Error code has been pushed. Push trap number. 153 */ 154#define EXCEP_ERR(n,name) \ 155 IDT_ENTRY(name,K_INTR_GATE);\ 156Entry(name) ;\ 157 pushl $(n) ;\ 158 pusha ;\ 159 movl $ EXT(lo_alltraps),%ebx ;\ 160 jmp enter_lohandler 161 162 163/* 164 * Interrupt. 165 */ 166#define INTERRUPT(n) \ 167 IDT_ENTRY_INT(L_ ## n,K_INTR_GATE) ;\ 168 .align FALIGN ;\ 169L_ ## n: ;\ 170 pushl $0 ;\ 171 pushl $(n) ;\ 172 pusha ;\ 173 movl $ EXT(lo_allintrs),%ebx ;\ 174 jmp enter_lohandler 175 176 177 .data 178 .align 12 179Entry(master_idt) 180Entry(hi_remap_data) 181 .text 182Entry(hi_remap_text) 183 184EXCEPTION(0x00,t_zero_div) 185EXCEP_SPC(0x01,hi_debug) 186INTERRUPT(0x02) /* NMI */ 187EXCEP_USR(0x03,t_int3) 188EXCEP_USR(0x04,t_into) 189EXCEP_USR(0x05,t_bounds) 190EXCEPTION(0x06,t_invop) 191EXCEPTION(0x07,t_nofpu) 192#if MACH_KDB 193EXCEP_TASK(0x08,db_task_dbl_fault) 194#else 195DF_FATAL_TASK(0x08,df_task_start) 196#endif 197EXCEPTION(0x09,a_fpu_over) 198EXCEPTION(0x0a,a_inv_tss) 199EXCEP_SPC(0x0b,hi_segnp) 200#if MACH_KDB 201EXCEP_TASK(0x0c,db_task_stk_fault) 202#else 203EXCEP_ERR(0x0c,t_stack_fault) 204#endif 205EXCEP_SPC(0x0d,hi_gen_prot) 206EXCEP_SPC(0x0e,hi_page_fault) 207EXCEPTION(0x0f,t_trap_0f) 208EXCEPTION(0x10,t_fpu_err) 209EXCEPTION(0x11,t_trap_11) 210MC_FATAL_TASK(0x12,mc_task_start) 211EXCEPTION(0x13,t_sse_err) 212EXCEPTION(0x14,t_trap_14) 213EXCEPTION(0x15,t_trap_15) 214EXCEPTION(0x16,t_trap_16) 215EXCEPTION(0x17,t_trap_17) 216EXCEPTION(0x18,t_trap_18) 217EXCEPTION(0x19,t_trap_19) 218EXCEPTION(0x1a,t_trap_1a) 219EXCEPTION(0x1b,t_trap_1b) 220EXCEPTION(0x1c,t_trap_1c) 221EXCEPTION(0x1d,t_trap_1d) 222EXCEPTION(0x1e,t_trap_1e) 223EXCEPTION(0x1f,t_trap_1f) 224 225INTERRUPT(0x20) 226INTERRUPT(0x21) 227INTERRUPT(0x22) 228INTERRUPT(0x23) 229INTERRUPT(0x24) 230INTERRUPT(0x25) 231INTERRUPT(0x26) 232INTERRUPT(0x27) 233INTERRUPT(0x28) 234INTERRUPT(0x29) 235INTERRUPT(0x2a) 236INTERRUPT(0x2b) 237INTERRUPT(0x2c) 238INTERRUPT(0x2d) 239INTERRUPT(0x2e) 240INTERRUPT(0x2f) 241 242INTERRUPT(0x30) 243INTERRUPT(0x31) 244INTERRUPT(0x32) 245INTERRUPT(0x33) 246INTERRUPT(0x34) 247INTERRUPT(0x35) 248INTERRUPT(0x36) 249INTERRUPT(0x37) 250INTERRUPT(0x38) 251INTERRUPT(0x39) 252INTERRUPT(0x3a) 253INTERRUPT(0x3b) 254INTERRUPT(0x3c) 255INTERRUPT(0x3d) 256INTERRUPT(0x3e) 257INTERRUPT(0x3f) 258 259INTERRUPT(0x40) 260INTERRUPT(0x41) 261INTERRUPT(0x42) 262INTERRUPT(0x43) 263INTERRUPT(0x44) 264INTERRUPT(0x45) 265INTERRUPT(0x46) 266INTERRUPT(0x47) 267INTERRUPT(0x48) 268INTERRUPT(0x49) 269INTERRUPT(0x4a) 270INTERRUPT(0x4b) 271INTERRUPT(0x4c) 272INTERRUPT(0x4d) 273INTERRUPT(0x4e) 274INTERRUPT(0x4f) 275 276INTERRUPT(0x50) 277INTERRUPT(0x51) 278INTERRUPT(0x52) 279INTERRUPT(0x53) 280INTERRUPT(0x54) 281INTERRUPT(0x55) 282INTERRUPT(0x56) 283INTERRUPT(0x57) 284INTERRUPT(0x58) 285INTERRUPT(0x59) 286INTERRUPT(0x5a) 287INTERRUPT(0x5b) 288INTERRUPT(0x5c) 289INTERRUPT(0x5d) 290INTERRUPT(0x5e) 291INTERRUPT(0x5f) 292 293INTERRUPT(0x60) 294INTERRUPT(0x61) 295INTERRUPT(0x62) 296INTERRUPT(0x63) 297INTERRUPT(0x64) 298INTERRUPT(0x65) 299INTERRUPT(0x66) 300INTERRUPT(0x67) 301INTERRUPT(0x68) 302INTERRUPT(0x69) 303INTERRUPT(0x6a) 304INTERRUPT(0x6b) 305INTERRUPT(0x6c) 306INTERRUPT(0x6d) 307INTERRUPT(0x6e) 308INTERRUPT(0x6f) 309 310INTERRUPT(0x70) 311INTERRUPT(0x71) 312INTERRUPT(0x72) 313INTERRUPT(0x73) 314INTERRUPT(0x74) 315INTERRUPT(0x75) 316INTERRUPT(0x76) 317INTERRUPT(0x77) 318INTERRUPT(0x78) 319INTERRUPT(0x79) 320INTERRUPT(0x7a) 321INTERRUPT(0x7b) 322INTERRUPT(0x7c) 323INTERRUPT(0x7d) 324INTERRUPT(0x7e) 325EXCEP_USR(0x7f, t_dtrace_ret) 326 327EXCEP_SPC_USR(0x80,hi_unix_scall) 328EXCEP_SPC_USR(0x81,hi_mach_scall) 329EXCEP_SPC_USR(0x82,hi_mdep_scall) 330EXCEP_SPC_USR(0x83,hi_diag_scall) 331 332INTERRUPT(0x84) 333INTERRUPT(0x85) 334INTERRUPT(0x86) 335INTERRUPT(0x87) 336INTERRUPT(0x88) 337INTERRUPT(0x89) 338INTERRUPT(0x8a) 339INTERRUPT(0x8b) 340INTERRUPT(0x8c) 341INTERRUPT(0x8d) 342INTERRUPT(0x8e) 343INTERRUPT(0x8f) 344 345INTERRUPT(0x90) 346INTERRUPT(0x91) 347INTERRUPT(0x92) 348INTERRUPT(0x93) 349INTERRUPT(0x94) 350INTERRUPT(0x95) 351INTERRUPT(0x96) 352INTERRUPT(0x97) 353INTERRUPT(0x98) 354INTERRUPT(0x99) 355INTERRUPT(0x9a) 356INTERRUPT(0x9b) 357INTERRUPT(0x9c) 358INTERRUPT(0x9d) 359INTERRUPT(0x9e) 360INTERRUPT(0x9f) 361 362INTERRUPT(0xa0) 363INTERRUPT(0xa1) 364INTERRUPT(0xa2) 365INTERRUPT(0xa3) 366INTERRUPT(0xa4) 367INTERRUPT(0xa5) 368INTERRUPT(0xa6) 369INTERRUPT(0xa7) 370INTERRUPT(0xa8) 371INTERRUPT(0xa9) 372INTERRUPT(0xaa) 373INTERRUPT(0xab) 374INTERRUPT(0xac) 375INTERRUPT(0xad) 376INTERRUPT(0xae) 377INTERRUPT(0xaf) 378 379INTERRUPT(0xb0) 380INTERRUPT(0xb1) 381INTERRUPT(0xb2) 382INTERRUPT(0xb3) 383INTERRUPT(0xb4) 384INTERRUPT(0xb5) 385INTERRUPT(0xb6) 386INTERRUPT(0xb7) 387INTERRUPT(0xb8) 388INTERRUPT(0xb9) 389INTERRUPT(0xba) 390INTERRUPT(0xbb) 391INTERRUPT(0xbc) 392INTERRUPT(0xbd) 393INTERRUPT(0xbe) 394INTERRUPT(0xbf) 395 396INTERRUPT(0xc0) 397INTERRUPT(0xc1) 398INTERRUPT(0xc2) 399INTERRUPT(0xc3) 400INTERRUPT(0xc4) 401INTERRUPT(0xc5) 402INTERRUPT(0xc6) 403INTERRUPT(0xc7) 404INTERRUPT(0xc8) 405INTERRUPT(0xc9) 406INTERRUPT(0xca) 407INTERRUPT(0xcb) 408INTERRUPT(0xcc) 409INTERRUPT(0xcd) 410INTERRUPT(0xce) 411INTERRUPT(0xcf) 412 413INTERRUPT(0xd0) 414INTERRUPT(0xd1) 415INTERRUPT(0xd2) 416INTERRUPT(0xd3) 417INTERRUPT(0xd4) 418INTERRUPT(0xd5) 419INTERRUPT(0xd6) 420INTERRUPT(0xd7) 421INTERRUPT(0xd8) 422INTERRUPT(0xd9) 423INTERRUPT(0xda) 424INTERRUPT(0xdb) 425INTERRUPT(0xdc) 426INTERRUPT(0xdd) 427INTERRUPT(0xde) 428INTERRUPT(0xdf) 429 430INTERRUPT(0xe0) 431INTERRUPT(0xe1) 432INTERRUPT(0xe2) 433INTERRUPT(0xe3) 434INTERRUPT(0xe4) 435INTERRUPT(0xe5) 436INTERRUPT(0xe6) 437INTERRUPT(0xe7) 438INTERRUPT(0xe8) 439INTERRUPT(0xe9) 440INTERRUPT(0xea) 441INTERRUPT(0xeb) 442INTERRUPT(0xec) 443INTERRUPT(0xed) 444INTERRUPT(0xee) 445INTERRUPT(0xef) 446 447INTERRUPT(0xf0) 448INTERRUPT(0xf1) 449INTERRUPT(0xf2) 450INTERRUPT(0xf3) 451INTERRUPT(0xf4) 452INTERRUPT(0xf5) 453INTERRUPT(0xf6) 454INTERRUPT(0xf7) 455INTERRUPT(0xf8) 456INTERRUPT(0xf9) 457INTERRUPT(0xfa) 458INTERRUPT(0xfb) 459INTERRUPT(0xfc) 460INTERRUPT(0xfd) 461INTERRUPT(0xfe) 462EXCEPTION(0xff,t_preempt) 463 464 465 .data 466Entry(lo_kernel_cr3) 467 .long 0 468 .long 0 469 470 .text 471 472 473/******************************************************************************************************* 474 * 475 * Trap/interrupt entry points. 476 * 477 * All traps must create the following save area on the PCB "stack": 478 * 479 * gs 480 * fs 481 * es 482 * ds 483 * edi 484 * esi 485 * ebp 486 * cr2 if page fault - otherwise unused 487 * ebx 488 * edx 489 * ecx 490 * eax 491 * trap number 492 * error code 493 * eip 494 * cs 495 * eflags 496 * user esp - if from user 497 * user ss - if from user 498 */ 499 500 501Entry(hi_ret_to_user) 502 movl %esp,%ebx 503 movl %gs:CPU_ACTIVE_THREAD,%ecx 504 subl ACT_PCB_ISS(%ecx),%ebx 505 movl $(WINDOWS_CLEAN),ACT_COPYIO_STATE(%ecx) 506 507 movl ACT_PCB_IDS(%ecx),%eax /* get debug state struct */ 508 cmpl $0,%eax /* is there a debug state */ 509 je 1f /* branch if not */ 510 movl DS_DR0(%eax), %ecx /* Load the 32 bit debug registers */ 511 movl %ecx, %db0 512 movl DS_DR1(%eax), %ecx 513 movl %ecx, %db1 514 movl DS_DR2(%eax), %ecx 515 movl %ecx, %db2 516 movl DS_DR3(%eax), %ecx 517 movl %ecx, %db3 518 movl DS_DR7(%eax), %eax 5191: 520 addl %gs:CPU_HI_ISS,%ebx /* rebase PCB save area to high addr */ 521 movl %gs:CPU_TASK_CR3,%ecx 522 movl %ecx,%gs:CPU_ACTIVE_CR3 523 movl %ebx,%esp /* switch to hi based PCB stack */ 524 movl %ecx,%cr3 /* switch to user's address space */ 525 526 cmpl $0,%eax /* is dr7 set to something? */ 527 je 2f /* branch if not */ 528 movl %eax,%db7 /* Set dr7 */ 5292: 530 531Entry(hi_ret_to_kernel) 532 533 popl %eax /* ignore flavor of saved state */ 534EXT(ret_popl_gs): 535 popl %gs /* restore segment registers */ 536EXT(ret_popl_fs): 537 popl %fs 538EXT(ret_popl_es): 539 popl %es 540EXT(ret_popl_ds): 541 popl %ds 542 543 popa /* restore general registers */ 544 addl $8,%esp /* discard trap number and error code */ 545 546 cmpl $(SYSENTER_CS),4(%esp) /* test for fast entry/exit */ 547 je fast_exit 548EXT(ret_iret): 549 iret /* return from interrupt */ 550fast_exit: 551 popl %edx /* user return eip */ 552 popl %ecx /* pop and toss cs */ 553 andl $(~EFL_IF),(%esp) /* clear intrs enabled, see sti below */ 554 popf /* flags - carry denotes failure */ 555 popl %ecx /* user return esp */ 556 sti /* interrupts enabled after sysexit */ 557 sysexit 558 559 560Entry(hi_unix_scall) 561 pushl %eax /* save system call number */ 562 pushl $0 /* clear trap number slot */ 563 pusha /* save the general registers */ 564 movl $ EXT(lo_unix_scall),%ebx 565 jmp enter_lohandler 566 567 568Entry(hi_mach_scall) 569 pushl %eax /* save system call number */ 570 pushl $0 /* clear trap number slot */ 571 pusha /* save the general registers */ 572 movl $ EXT(lo_mach_scall),%ebx 573 jmp enter_lohandler 574 575 576Entry(hi_mdep_scall) 577 pushl %eax /* save system call number */ 578 pushl $0 /* clear trap number slot */ 579 pusha /* save the general registers */ 580 movl $ EXT(lo_mdep_scall),%ebx 581 jmp enter_lohandler 582 583 584Entry(hi_diag_scall) 585 pushl %eax // Save sselector 586 pushl $0 // Clear trap number slot 587 pusha // save the general registers 588 movl $EXT(lo_diag_scall),%ebx // Get the function down low to transfer to 589 jmp enter_lohandler // Leap to it... 590 591 592/* 593 * sysenter entry point 594 * Requires user code to set up: 595 * edx: user instruction pointer (return address) 596 * ecx: user stack pointer 597 * on which is pushed stub ret addr and saved ebx 598 * Return to user-space is made using sysexit. 599 * Note: sysenter/sysexit cannot be used for calls returning a value in edx, 600 * or requiring ecx to be preserved. 601 */ 602Entry(hi_sysenter) 603 movl (%esp), %esp /* switch from intr stack to pcb */ 604 /* 605 * Push values on to the PCB stack 606 * to cons up the saved state. 607 */ 608 pushl $(USER_DS) /* ss */ 609 pushl %ecx /* uesp */ 610 pushf /* flags */ 611 /* 612 * Clear, among others, the Nested Task (NT) flags bit; 613 * This is cleared by INT, but not by SYSENTER. 614 */ 615 pushl $0 616 popfl 617 pushl $(SYSENTER_CS) /* cs */ 618hi_sysenter_2: 619 pushl %edx /* eip */ 620 pushl %eax /* err/eax - syscall code */ 621 pushl $0 /* clear trap number slot */ 622 pusha /* save the general registers */ 623 orl $(EFL_IF),R_EFLAGS-R_EDI(%esp) /* (edi was last reg pushed) */ 624 movl $ EXT(lo_sysenter),%ebx 625enter_lohandler: 626 pushl %ds 627 pushl %es 628 pushl %fs 629 pushl %gs 630 pushl $(SS_32) /* 32-bit state flavor */ 631enter_lohandler1: 632 mov %ss,%eax 633 mov %eax,%ds 634 mov %eax,%fs 635 mov %eax,%es /* switch to kernel data seg */ 636 mov $(CPU_DATA_GS),%eax 637 mov %eax,%gs 638 cld /* clear direction flag */ 639 /* 640 * Switch to kernel's address space if necessary 641 */ 642 movl HI_DATA(lo_kernel_cr3),%ecx 643 movl %cr3,%eax 644 cmpl %eax,%ecx 645 je 1f 646 movl %ecx,%cr3 647 movl %ecx,%gs:CPU_ACTIVE_CR3 6481: 649 testb $3,R_CS(%esp) 650 jz 2f 651 movl %esp,%edx /* came from user mode */ 652 subl %gs:CPU_HI_ISS,%edx 653 movl %gs:CPU_ACTIVE_THREAD,%ecx 654 addl ACT_PCB_ISS(%ecx),%edx /* rebase the high stack to a low address */ 655 movl %edx,%esp 656 cmpl $0, ACT_PCB_IDS(%ecx) /* Is there a debug register state? */ 657 je 2f 658 movl $0, %ecx /* If so, reset DR7 (the control) */ 659 movl %ecx, %dr7 6602: 661 movl R_TRAPNO(%esp),%ecx // Get the interrupt vector 662 addl $1,%gs:hwIntCnt(,%ecx,4) // Bump the count 663 jmp *%ebx 664 665 666/* 667 * Page fault traps save cr2. 668 */ 669Entry(hi_page_fault) 670 pushl $(T_PAGE_FAULT) /* mark a page fault trap */ 671 pusha /* save the general registers */ 672 movl %cr2,%eax /* get the faulting address */ 673 movl %eax,R_CR2-R_EDI(%esp) /* save in esp save slot */ 674 675 movl $ EXT(lo_alltraps),%ebx 676 jmp enter_lohandler 677 678 679 680/* 681 * Debug trap. Check for single-stepping across system call into 682 * kernel. If this is the case, taking the debug trap has turned 683 * off single-stepping - save the flags register with the trace 684 * bit set. 685 */ 686Entry(hi_debug) 687 testb $3,4(%esp) 688 jnz hi_debug_trap 689 /* trap came from kernel mode */ 690 cmpl $(HI_TEXT(hi_mach_scall)),(%esp) 691 jne 6f 692 addl $12,%esp /* remove eip/cs/eflags from debug_trap */ 693 jmp EXT(hi_mach_scall) /* continue system call entry */ 6946: 695 cmpl $(HI_TEXT(hi_mdep_scall)),(%esp) 696 jne 5f 697 addl $12,%esp /* remove eip/cs/eflags from debug_trap */ 698 jmp EXT(hi_mdep_scall) /* continue system call entry */ 6995: 700 cmpl $(HI_TEXT(hi_unix_scall)),(%esp) 701 jne 4f 702 addl $12,%esp /* remove eip/cs/eflags from debug_trap */ 703 jmp EXT(hi_unix_scall) /* continue system call entry */ 7044: 705 cmpl $(HI_TEXT(hi_sysenter)),(%esp) 706 jne hi_debug_trap 707 /* 708 * eip/cs/flags have been pushed on intr stack 709 * We have to switch to pcb stack and copy eflags. 710 * Note: setting the cs selector to SYSENTER_TF_CS 711 * will cause the return to user path to take the iret path so 712 * that eflags (containing the trap bit) is set atomically. 713 * In unix_syscall this is tested so that we'll rewind the pc 714 * to account for with sysenter or int entry. 715 */ 716 addl $8,%esp /* remove eip/cs */ 717 pushl %ecx /* save %ecx */ 718 movl 8(%esp),%ecx /* top of intr stack -> pcb stack */ 719 xchgl %ecx,%esp /* switch to pcb stack */ 720 pushl $(USER_DS) /* ss */ 721 pushl %ss:(%ecx) /* %ecx into uesp slot */ 722 pushl %ss:4(%ecx) /* eflags */ 723 movl %ss:(%ecx),%ecx /* restore %ecx */ 724 pushl $(SYSENTER_TF_CS) /* cs - not SYSENTER_CS for iret path */ 725 jmp hi_sysenter_2 /* continue sysenter entry */ 726hi_debug_trap: 727 pushl $0 728 pushl $(T_DEBUG) /* handle as user trap */ 729 pusha /* save the general registers */ 730 movl $ EXT(lo_alltraps),%ebx 731 jmp enter_lohandler 732 733 734 735/* 736 * General protection or segment-not-present fault. 737 * Check for a GP/NP fault in the kernel_return 738 * sequence; if there, report it as a GP/NP fault on the user's instruction. 739 * 740 * esp-> 0: trap code (NP or GP) 741 * 4: segment number in error 742 * 8 eip 743 * 12 cs 744 * 16 eflags 745 * 20 old registers (trap is from kernel) 746 */ 747Entry(hi_gen_prot) 748 pushl $(T_GENERAL_PROTECTION) /* indicate fault type */ 749 jmp trap_check_kernel_exit /* check for kernel exit sequence */ 750 751Entry(hi_segnp) 752 pushl $(T_SEGMENT_NOT_PRESENT) 753 /* indicate fault type */ 754trap_check_kernel_exit: 755 testb $3,12(%esp) 756 jnz hi_take_trap 757 /* trap was from kernel mode, so */ 758 /* check for the kernel exit sequence */ 759 cmpl $(HI_TEXT(ret_iret)),8(%esp) /* on IRET? */ 760 je fault_iret 761 cmpl $(HI_TEXT(ret_popl_ds)),8(%esp) /* popping DS? */ 762 je fault_popl_ds 763 cmpl $(HI_TEXT(ret_popl_es)),8(%esp) /* popping ES? */ 764 je fault_popl_es 765 cmpl $(HI_TEXT(ret_popl_fs)),8(%esp) /* popping FS? */ 766 je fault_popl_fs 767 cmpl $(HI_TEXT(ret_popl_gs)),8(%esp) /* popping GS? */ 768 je fault_popl_gs 769hi_take_trap: 770 pusha /* save the general registers */ 771 movl $ EXT(lo_alltraps),%ebx 772 jmp enter_lohandler 773 774 775/* 776 * GP/NP fault on IRET: CS or SS is in error. 777 * All registers contain the user's values. 778 * 779 * on SP is 780 * 0 trap number 781 * 4 errcode 782 * 8 eip 783 * 12 cs --> trapno 784 * 16 efl --> errcode 785 * 20 user eip 786 * 24 user cs 787 * 28 user eflags 788 * 32 user esp 789 * 36 user ss 790 */ 791fault_iret: 792 movl %eax,8(%esp) /* save eax (we don`t need saved eip) */ 793 popl %eax /* get trap number */ 794 movl %eax,12-4(%esp) /* put in user trap number */ 795 popl %eax /* get error code */ 796 movl %eax,16-8(%esp) /* put in user errcode */ 797 popl %eax /* restore eax */ 798 /* now treat as fault from user */ 799 pusha /* save the general registers */ 800 movl $ EXT(lo_alltraps),%ebx 801 jmp enter_lohandler 802 803/* 804 * Fault restoring a segment register. The user's registers are still 805 * saved on the stack. The offending segment register has not been 806 * popped. 807 */ 808fault_popl_ds: 809 popl %eax /* get trap number */ 810 popl %edx /* get error code */ 811 addl $12,%esp /* pop stack to user regs */ 812 jmp push_es /* (DS on top of stack) */ 813fault_popl_es: 814 popl %eax /* get trap number */ 815 popl %edx /* get error code */ 816 addl $12,%esp /* pop stack to user regs */ 817 jmp push_fs /* (ES on top of stack) */ 818fault_popl_fs: 819 popl %eax /* get trap number */ 820 popl %edx /* get error code */ 821 addl $12,%esp /* pop stack to user regs */ 822 jmp push_gs /* (FS on top of stack) */ 823fault_popl_gs: 824 popl %eax /* get trap number */ 825 popl %edx /* get error code */ 826 addl $12,%esp /* pop stack to user regs */ 827 jmp push_none /* (GS on top of stack) */ 828 829push_es: 830 pushl %es /* restore es, */ 831push_fs: 832 pushl %fs /* restore fs, */ 833push_gs: 834 pushl %gs /* restore gs. */ 835push_none: 836 pushl $(SS_32) /* 32-bit state flavor */ 837 movl %eax,R_TRAPNO(%esp) /* set trap number */ 838 movl %edx,R_ERR(%esp) /* set error code */ 839 /* now treat as fault from user */ 840 /* except that segment registers are */ 841 /* already pushed */ 842 movl $ EXT(lo_alltraps),%ebx 843 jmp enter_lohandler1 844 845 846 .text 847 848 849Entry(lo_ret_to_user) 850 jmp *1f 8511: .long HI_TEXT(hi_ret_to_user) 852 853Entry(lo_ret_to_kernel) 854 jmp *1f 8551: .long HI_TEXT(hi_ret_to_kernel) 856 857Entry(hi_remap_etext) 858