]> git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/idt.s
xnu-1699.24.23.tar.gz
[apple/xnu.git] / osfmk / i386 / idt.s
1 /*
2 * Copyright (c) 2000-2010 Apple 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 #include <i386/rtclock_asm.h>
64 #define _ARCH_I386_ASM_HELP_H_ /* Prevent inclusion of user header */
65 #include <mach/i386/syscall_sw.h>
66 #include <i386/postcode.h>
67 #include <i386/proc_reg.h>
68 #include <mach/exception_types.h>
69
70 /*
71 * Low-memory handlers.
72 */
73 #define LO_ALLINTRS EXT(lo_allintrs32)
74 #define LO_ALLTRAPS EXT(lo_alltraps32)
75 #define LO_SYSENTER EXT(lo_sysenter32)
76 #define LO_UNIX_SCALL EXT(lo_unix_scall32)
77 #define LO_MACH_SCALL EXT(lo_mach_scall32)
78 #define LO_MDEP_SCALL EXT(lo_mdep_scall32)
79 #define LO_DIAG_SCALL EXT(lo_diag_scall32)
80
81
82 #define HI_DATA(lo_addr) ( (EXT(lo_addr) - EXT(hi_remap_data)) + HIGH_IDT_BASE )
83 #define HI_TEXT(lo_text) ( (EXT(lo_text) - EXT(hi_remap_text)) + HIGH_MEM_BASE )
84
85 /*
86 * Interrupt descriptor table and code vectors for it.
87 */
88 #define IDT_BASE_ENTRY(vec,seg,type) \
89 .data ;\
90 .long EXT(vec) - EXT(hi_remap_text) + HIGH_MEM_BASE ; \
91 .word seg ;\
92 .byte 0 ;\
93 .byte type ;\
94 .text
95
96 #define IDT_BASE_ENTRY_INT(vec,seg,type) \
97 .data ;\
98 .long vec - EXT(hi_remap_text) + HIGH_MEM_BASE ; \
99 .word seg ;\
100 .byte 0 ;\
101 .byte type ;\
102 .text
103
104 #define IDT_BASE_ENTRY_TG(vec,seg,type) \
105 .data ;\
106 .long 0 ; \
107 .word seg ;\
108 .byte 0 ;\
109 .byte type ;\
110 .text
111
112 #define IDT_ENTRY(vec,type) IDT_BASE_ENTRY(vec,KERNEL32_CS,type)
113 #define IDT_ENTRY_INT(vec,type) IDT_BASE_ENTRY_INT(vec,KERNEL32_CS,type)
114
115 /*
116 * No error code. Clear error code and push trap number.
117 */
118 #define EXCEPTION(n,name) \
119 IDT_ENTRY(name,K_INTR_GATE);\
120 Entry(name) ;\
121 pushl $0 ;\
122 pushl $(n) ;\
123 pusha ;\
124 movl $(LO_ALLTRAPS),%ebx ;\
125 jmp enter_lohandler
126
127
128 /*
129 * Interrupt from user. Clear error code and push trap number.
130 */
131 #define EXCEP_USR(n,name) \
132 IDT_ENTRY(name,U_INTR_GATE);\
133 Entry(name) ;\
134 pushl $0 ;\
135 pushl $(n) ;\
136 pusha ;\
137 movl $(LO_ALLTRAPS),%ebx ;\
138 jmp enter_lohandler
139
140
141 /*
142 * Special interrupt code.
143 */
144 #define EXCEP_SPC(n,name) \
145 IDT_ENTRY(name,K_INTR_GATE)
146
147 /*
148 * Special interrupt code from user.
149 */
150 #define EXCEP_SPC_USR(n,name) \
151 IDT_ENTRY(name,U_INTR_GATE)
152
153
154 /*
155 * Extra-special interrupt code. Note that no offset may be
156 * specified in a task gate descriptor, so name is ignored.
157 */
158 #define EXCEP_TASK(n,name) \
159 IDT_BASE_ENTRY_TG(0,DEBUG_TSS,K_TASK_GATE)
160
161 /* Double-fault fatal handler */
162 #define DF_FATAL_TASK(n,name) \
163 IDT_BASE_ENTRY_TG(0,DF_TSS,K_TASK_GATE)
164
165 /* machine-check handler */
166 #define MC_FATAL_TASK(n,name) \
167 IDT_BASE_ENTRY_TG(0,MC_TSS,K_TASK_GATE)
168
169 /*
170 * Error code has been pushed. Push trap number.
171 */
172 #define EXCEP_ERR(n,name) \
173 IDT_ENTRY(name,K_INTR_GATE) ;\
174 Entry(name) ;\
175 pushl $(n) ;\
176 pusha ;\
177 movl $(LO_ALLTRAPS),%ebx ;\
178 jmp enter_lohandler
179
180
181 /*
182 * Interrupt.
183 */
184 #define INTERRUPT(n) \
185 IDT_ENTRY_INT(L_ ## n,K_INTR_GATE) ;\
186 .align FALIGN ;\
187 L_ ## n: ;\
188 pushl $0 ;\
189 pushl $(n) ;\
190 pusha ;\
191 movl $(LO_ALLINTRS),%ebx ;\
192 jmp enter_lohandler
193
194
195 .data
196 .align 12
197 Entry(master_idt)
198 Entry(hi_remap_data)
199 .text
200 .align 12
201 Entry(hi_remap_text)
202
203 EXCEPTION(0x00,t_zero_div)
204 EXCEP_SPC(0x01,hi_debug)
205 INTERRUPT(0x02) /* NMI */
206 EXCEP_USR(0x03,t_int3)
207 EXCEP_USR(0x04,t_into)
208 EXCEP_USR(0x05,t_bounds)
209 EXCEPTION(0x06,t_invop)
210 EXCEPTION(0x07,t_nofpu)
211 #if MACH_KDB
212 EXCEP_TASK(0x08,db_task_dbl_fault)
213 #else
214 DF_FATAL_TASK(0x08,df_task_start)
215 #endif
216 EXCEPTION(0x09,a_fpu_over)
217 EXCEPTION(0x0a,a_inv_tss)
218 EXCEP_SPC(0x0b,hi_segnp)
219 #if MACH_KDB
220 EXCEP_TASK(0x0c,db_task_stk_fault)
221 #else
222 EXCEP_ERR(0x0c,t_stack_fault)
223 #endif
224 EXCEP_SPC(0x0d,hi_gen_prot)
225 EXCEP_SPC(0x0e,hi_page_fault)
226 EXCEPTION(0x0f,t_trap_0f)
227 EXCEPTION(0x10,t_fpu_err)
228 EXCEPTION(0x11,t_trap_11)
229 MC_FATAL_TASK(0x12,mc_task_start)
230 EXCEPTION(0x13,t_sse_err)
231 EXCEPTION(0x14,t_trap_14)
232 EXCEPTION(0x15,t_trap_15)
233 EXCEPTION(0x16,t_trap_16)
234 EXCEPTION(0x17,t_trap_17)
235 EXCEPTION(0x18,t_trap_18)
236 EXCEPTION(0x19,t_trap_19)
237 EXCEPTION(0x1a,t_trap_1a)
238 EXCEPTION(0x1b,t_trap_1b)
239 EXCEPTION(0x1c,t_trap_1c)
240 EXCEPTION(0x1d,t_trap_1d)
241 EXCEPTION(0x1e,t_trap_1e)
242 EXCEPTION(0x1f,t_trap_1f)
243
244 INTERRUPT(0x20)
245 INTERRUPT(0x21)
246 INTERRUPT(0x22)
247 INTERRUPT(0x23)
248 INTERRUPT(0x24)
249 INTERRUPT(0x25)
250 INTERRUPT(0x26)
251 INTERRUPT(0x27)
252 INTERRUPT(0x28)
253 INTERRUPT(0x29)
254 INTERRUPT(0x2a)
255 INTERRUPT(0x2b)
256 INTERRUPT(0x2c)
257 INTERRUPT(0x2d)
258 INTERRUPT(0x2e)
259 INTERRUPT(0x2f)
260
261 INTERRUPT(0x30)
262 INTERRUPT(0x31)
263 INTERRUPT(0x32)
264 INTERRUPT(0x33)
265 INTERRUPT(0x34)
266 INTERRUPT(0x35)
267 INTERRUPT(0x36)
268 INTERRUPT(0x37)
269 INTERRUPT(0x38)
270 INTERRUPT(0x39)
271 INTERRUPT(0x3a)
272 INTERRUPT(0x3b)
273 INTERRUPT(0x3c)
274 INTERRUPT(0x3d)
275 INTERRUPT(0x3e)
276 INTERRUPT(0x3f)
277
278 INTERRUPT(0x40)
279 INTERRUPT(0x41)
280 INTERRUPT(0x42)
281 INTERRUPT(0x43)
282 INTERRUPT(0x44)
283 INTERRUPT(0x45)
284 INTERRUPT(0x46)
285 INTERRUPT(0x47)
286 INTERRUPT(0x48)
287 INTERRUPT(0x49)
288 INTERRUPT(0x4a)
289 INTERRUPT(0x4b)
290 INTERRUPT(0x4c)
291 INTERRUPT(0x4d)
292 INTERRUPT(0x4e)
293 INTERRUPT(0x4f)
294
295 INTERRUPT(0x50)
296 INTERRUPT(0x51)
297 INTERRUPT(0x52)
298 INTERRUPT(0x53)
299 INTERRUPT(0x54)
300 INTERRUPT(0x55)
301 INTERRUPT(0x56)
302 INTERRUPT(0x57)
303 INTERRUPT(0x58)
304 INTERRUPT(0x59)
305 INTERRUPT(0x5a)
306 INTERRUPT(0x5b)
307 INTERRUPT(0x5c)
308 INTERRUPT(0x5d)
309 INTERRUPT(0x5e)
310 INTERRUPT(0x5f)
311
312 INTERRUPT(0x60)
313 INTERRUPT(0x61)
314 INTERRUPT(0x62)
315 INTERRUPT(0x63)
316 INTERRUPT(0x64)
317 INTERRUPT(0x65)
318 INTERRUPT(0x66)
319 INTERRUPT(0x67)
320 INTERRUPT(0x68)
321 INTERRUPT(0x69)
322 INTERRUPT(0x6a)
323 INTERRUPT(0x6b)
324 INTERRUPT(0x6c)
325 INTERRUPT(0x6d)
326 INTERRUPT(0x6e)
327 INTERRUPT(0x6f)
328
329 INTERRUPT(0x70)
330 INTERRUPT(0x71)
331 INTERRUPT(0x72)
332 INTERRUPT(0x73)
333 INTERRUPT(0x74)
334 INTERRUPT(0x75)
335 INTERRUPT(0x76)
336 INTERRUPT(0x77)
337 INTERRUPT(0x78)
338 INTERRUPT(0x79)
339 INTERRUPT(0x7a)
340 INTERRUPT(0x7b)
341 INTERRUPT(0x7c)
342 INTERRUPT(0x7d)
343 INTERRUPT(0x7e)
344 EXCEP_USR(0x7f, t_dtrace_ret)
345
346 EXCEP_SPC_USR(0x80,hi_unix_scall)
347 EXCEP_SPC_USR(0x81,hi_mach_scall)
348 EXCEP_SPC_USR(0x82,hi_mdep_scall)
349 EXCEP_SPC_USR(0x83,hi_diag_scall)
350
351 INTERRUPT(0x84)
352 INTERRUPT(0x85)
353 INTERRUPT(0x86)
354 INTERRUPT(0x87)
355 INTERRUPT(0x88)
356 INTERRUPT(0x89)
357 INTERRUPT(0x8a)
358 INTERRUPT(0x8b)
359 INTERRUPT(0x8c)
360 INTERRUPT(0x8d)
361 INTERRUPT(0x8e)
362 INTERRUPT(0x8f)
363
364 INTERRUPT(0x90)
365 INTERRUPT(0x91)
366 INTERRUPT(0x92)
367 INTERRUPT(0x93)
368 INTERRUPT(0x94)
369 INTERRUPT(0x95)
370 INTERRUPT(0x96)
371 INTERRUPT(0x97)
372 INTERRUPT(0x98)
373 INTERRUPT(0x99)
374 INTERRUPT(0x9a)
375 INTERRUPT(0x9b)
376 INTERRUPT(0x9c)
377 INTERRUPT(0x9d)
378 INTERRUPT(0x9e)
379 INTERRUPT(0x9f)
380
381 INTERRUPT(0xa0)
382 INTERRUPT(0xa1)
383 INTERRUPT(0xa2)
384 INTERRUPT(0xa3)
385 INTERRUPT(0xa4)
386 INTERRUPT(0xa5)
387 INTERRUPT(0xa6)
388 INTERRUPT(0xa7)
389 INTERRUPT(0xa8)
390 INTERRUPT(0xa9)
391 INTERRUPT(0xaa)
392 INTERRUPT(0xab)
393 INTERRUPT(0xac)
394 INTERRUPT(0xad)
395 INTERRUPT(0xae)
396 INTERRUPT(0xaf)
397
398 INTERRUPT(0xb0)
399 INTERRUPT(0xb1)
400 INTERRUPT(0xb2)
401 INTERRUPT(0xb3)
402 INTERRUPT(0xb4)
403 INTERRUPT(0xb5)
404 INTERRUPT(0xb6)
405 INTERRUPT(0xb7)
406 INTERRUPT(0xb8)
407 INTERRUPT(0xb9)
408 INTERRUPT(0xba)
409 INTERRUPT(0xbb)
410 INTERRUPT(0xbc)
411 INTERRUPT(0xbd)
412 INTERRUPT(0xbe)
413 INTERRUPT(0xbf)
414
415 INTERRUPT(0xc0)
416 INTERRUPT(0xc1)
417 INTERRUPT(0xc2)
418 INTERRUPT(0xc3)
419 INTERRUPT(0xc4)
420 INTERRUPT(0xc5)
421 INTERRUPT(0xc6)
422 INTERRUPT(0xc7)
423 INTERRUPT(0xc8)
424 INTERRUPT(0xc9)
425 INTERRUPT(0xca)
426 INTERRUPT(0xcb)
427 INTERRUPT(0xcc)
428 INTERRUPT(0xcd)
429 INTERRUPT(0xce)
430 INTERRUPT(0xcf)
431
432 INTERRUPT(0xd0)
433 INTERRUPT(0xd1)
434 INTERRUPT(0xd2)
435 INTERRUPT(0xd3)
436 INTERRUPT(0xd4)
437 INTERRUPT(0xd5)
438 INTERRUPT(0xd6)
439 INTERRUPT(0xd7)
440 INTERRUPT(0xd8)
441 INTERRUPT(0xd9)
442 INTERRUPT(0xda)
443 INTERRUPT(0xdb)
444 INTERRUPT(0xdc)
445 INTERRUPT(0xdd)
446 INTERRUPT(0xde)
447 INTERRUPT(0xdf)
448
449 INTERRUPT(0xe0)
450 INTERRUPT(0xe1)
451 INTERRUPT(0xe2)
452 INTERRUPT(0xe3)
453 INTERRUPT(0xe4)
454 INTERRUPT(0xe5)
455 INTERRUPT(0xe6)
456 INTERRUPT(0xe7)
457 INTERRUPT(0xe8)
458 INTERRUPT(0xe9)
459 INTERRUPT(0xea)
460 INTERRUPT(0xeb)
461 INTERRUPT(0xec)
462 INTERRUPT(0xed)
463 INTERRUPT(0xee)
464 INTERRUPT(0xef)
465
466 INTERRUPT(0xf0)
467 INTERRUPT(0xf1)
468 INTERRUPT(0xf2)
469 INTERRUPT(0xf3)
470 INTERRUPT(0xf4)
471 INTERRUPT(0xf5)
472 INTERRUPT(0xf6)
473 INTERRUPT(0xf7)
474 INTERRUPT(0xf8)
475 INTERRUPT(0xf9)
476 INTERRUPT(0xfa)
477 INTERRUPT(0xfb)
478 INTERRUPT(0xfc)
479 INTERRUPT(0xfd)
480 INTERRUPT(0xfe)
481 EXCEPTION(0xff,t_preempt)
482
483
484 .data
485 Entry(lo_kernel_cr3)
486 .long 0
487 .long 0
488
489 .text
490
491
492 /*
493 * Trap/interrupt entry points.
494 *
495 * All traps must create the following save area on the PCB "stack":
496 *
497 * gs
498 * fs
499 * es
500 * ds
501 * edi
502 * esi
503 * ebp
504 * cr2 if page fault - otherwise unused
505 * ebx
506 * edx
507 * ecx
508 * eax
509 * trap number
510 * error code
511 * eip
512 * cs
513 * eflags
514 * user esp - if from user
515 * user ss - if from user
516 */
517
518 ret_to_kernel:
519 jmp *1f
520 1: .long HI_TEXT(hi_ret_to_kernel)
521
522 ret_to_user:
523 jmp *1f
524 1: .long HI_TEXT(hi_ret_to_user)
525
526 Entry(hi_ret_to_user)
527 movl %esp,%ebx
528 movl %gs:CPU_ACTIVE_THREAD,%ecx
529 subl TH_PCB_ISS(%ecx),%ebx
530 movl $(WINDOWS_CLEAN),TH_COPYIO_STATE(%ecx)
531
532 movl TH_PCB_IDS(%ecx),%eax /* get debug state struct */
533 cmpl $0,%eax /* is there a debug state */
534 je 1f /* branch if not */
535 movl DS_DR0(%eax), %ecx /* Load the 32 bit debug registers */
536 movl %ecx, %db0
537 movl DS_DR1(%eax), %ecx
538 movl %ecx, %db1
539 movl DS_DR2(%eax), %ecx
540 movl %ecx, %db2
541 movl DS_DR3(%eax), %ecx
542 movl %ecx, %db3
543 movl DS_DR7(%eax), %eax
544 1:
545 addl %gs:CPU_HI_ISS,%ebx /* rebase PCB save area to high addr */
546 movl %gs:CPU_TASK_CR3,%ecx
547 movl %ecx,%gs:CPU_ACTIVE_CR3
548 movl %ebx,%esp /* switch to hi based PCB stack */
549 movl %ecx,%cr3 /* switch to user's address space */
550
551 cmpl $0,%eax /* is dr7 set to something? */
552 je 2f /* branch if not */
553 movl %eax,%db7 /* Set dr7 */
554 2:
555
556 Entry(hi_ret_to_kernel)
557
558 popl %eax /* ignore flavor of saved state */
559 EXT(ret_popl_gs):
560 popl %gs /* restore segment registers */
561 EXT(ret_popl_fs):
562 popl %fs
563 EXT(ret_popl_es):
564 popl %es
565 EXT(ret_popl_ds):
566 popl %ds
567
568 popa /* restore general registers */
569 addl $8,%esp /* discard trap number and error code */
570
571 cmpl $(SYSENTER_CS),4(%esp) /* test for fast entry/exit */
572 je fast_exit
573 EXT(ret_iret):
574 iret /* return from interrupt */
575 fast_exit:
576 popl %edx /* user return eip */
577 popl %ecx /* pop and toss cs */
578 andl $(~EFL_IF),(%esp) /* clear intrs enabled, see sti below */
579 popf /* flags - carry denotes failure */
580 popl %ecx /* user return esp */
581 sti /* interrupts enabled after sysexit */
582 sysexit
583
584
585 Entry(hi_unix_scall)
586 pushl %eax /* save system call number */
587 pushl $0 /* clear trap number slot */
588 pusha /* save the general registers */
589 movl $(LO_UNIX_SCALL),%ebx
590 jmp enter_lohandler
591
592
593 Entry(hi_mach_scall)
594 pushl %eax /* save system call number */
595 pushl $0 /* clear trap number slot */
596 pusha /* save the general registers */
597 movl $(LO_MACH_SCALL),%ebx
598 jmp enter_lohandler
599
600
601 Entry(hi_mdep_scall)
602 pushl %eax /* save system call number */
603 pushl $0 /* clear trap number slot */
604 pusha /* save the general registers */
605 movl $(LO_MDEP_SCALL),%ebx
606 jmp enter_lohandler
607
608
609 Entry(hi_diag_scall)
610 pushl %eax // Save sselector
611 pushl $0 // Clear trap number slot
612 pusha // save the general registers
613 movl $(LO_DIAG_SCALL),%ebx // Get the function down low to transfer to
614 jmp enter_lohandler // Leap to it...
615
616
617 /*
618 * sysenter entry point
619 * Requires user code to set up:
620 * edx: user instruction pointer (return address)
621 * ecx: user stack pointer
622 * on which is pushed stub ret addr and saved ebx
623 * Return to user-space is made using sysexit.
624 * Note: sysenter/sysexit cannot be used for calls returning a value in edx,
625 * or requiring ecx to be preserved.
626 */
627 Entry(hi_sysenter)
628 movl (%esp), %esp /* switch from intr stack to pcb */
629 /*
630 * Push values on to the PCB stack
631 * to cons up the saved state.
632 */
633 pushl $(USER_DS) /* ss */
634 pushl %ecx /* uesp */
635 pushf /* flags */
636 /*
637 * Clear, among others, the Nested Task (NT) flags bit;
638 * This is cleared by INT, but not by SYSENTER.
639 */
640 pushl $0
641 popfl
642 pushl $(SYSENTER_CS) /* cs */
643 hi_sysenter_2:
644 pushl %edx /* eip */
645 pushl %eax /* err/eax - syscall code */
646 pushl $0 /* clear trap number slot */
647 pusha /* save the general registers */
648 orl $(EFL_IF),R32_EFLAGS-R32_EDI(%esp) /* (edi was last reg pushed) */
649 movl $(LO_SYSENTER),%ebx
650 enter_lohandler:
651 pushl %ds
652 pushl %es
653 pushl %fs
654 pushl %gs
655 pushl $(SS_32) /* 32-bit state flavor */
656 enter_lohandler1:
657 mov %ss,%eax
658 mov %eax,%ds
659 mov %eax,%fs
660 mov %eax,%es /* switch to kernel data seg */
661 mov $(CPU_DATA_GS),%eax
662 mov %eax,%gs
663 cld /* clear direction flag */
664 /*
665 * Switch to kernel's address space if necessary
666 */
667 movl HI_DATA(lo_kernel_cr3),%ecx
668 movl %cr3,%eax
669 cmpl %eax,%ecx
670 je 1f
671 movl %ecx,%cr3
672 movl %ecx,%gs:CPU_ACTIVE_CR3
673 1:
674 testb $3,R32_CS(%esp)
675 jz 2f
676 movl %esp,%edx /* came from user mode */
677 xor %ebp, %ebp
678 subl %gs:CPU_HI_ISS,%edx
679 movl %gs:CPU_ACTIVE_THREAD,%ecx
680 addl TH_PCB_ISS(%ecx),%edx /* rebase the high stack to a low address */
681 movl %edx,%esp
682 cmpl $0, TH_PCB_IDS(%ecx) /* Is there a debug register state? */
683 je 2f
684 movl $0, %ecx /* If so, reset DR7 (the control) */
685 movl %ecx, %dr7
686 2:
687 movl R32_TRAPNO(%esp),%ecx // Get the interrupt vector
688 addl $1,%gs:hwIntCnt(,%ecx,4) // Bump the count
689 jmp *%ebx
690
691
692 /*
693 * Page fault traps save cr2.
694 */
695 Entry(hi_page_fault)
696 pushl $(T_PAGE_FAULT) /* mark a page fault trap */
697 pusha /* save the general registers */
698 movl %cr2,%eax /* get the faulting address */
699 movl %eax,R32_CR2-R32_EDI(%esp)/* save in esp save slot */
700
701 movl $(LO_ALLTRAPS),%ebx
702 jmp enter_lohandler
703
704
705
706 /*
707 * Debug trap. Check for single-stepping across system call into
708 * kernel. If this is the case, taking the debug trap has turned
709 * off single-stepping - save the flags register with the trace
710 * bit set.
711 */
712 Entry(hi_debug)
713 testb $3,4(%esp)
714 jnz hi_debug_trap
715 /* trap came from kernel mode */
716 cmpl $(HI_TEXT(hi_mach_scall)),(%esp)
717 jne 6f
718 addl $12,%esp /* remove eip/cs/eflags from debug_trap */
719 jmp EXT(hi_mach_scall) /* continue system call entry */
720 6:
721 cmpl $(HI_TEXT(hi_mdep_scall)),(%esp)
722 jne 5f
723 addl $12,%esp /* remove eip/cs/eflags from debug_trap */
724 jmp EXT(hi_mdep_scall) /* continue system call entry */
725 5:
726 cmpl $(HI_TEXT(hi_unix_scall)),(%esp)
727 jne 4f
728 addl $12,%esp /* remove eip/cs/eflags from debug_trap */
729 jmp EXT(hi_unix_scall) /* continue system call entry */
730 4:
731 cmpl $(HI_TEXT(hi_sysenter)),(%esp)
732 jne hi_debug_trap
733 /*
734 * eip/cs/flags have been pushed on intr stack
735 * We have to switch to pcb stack and copy eflags.
736 * Note: setting the cs selector to SYSENTER_TF_CS
737 * will cause the return to user path to take the iret path so
738 * that eflags (containing the trap bit) is set atomically.
739 * In unix_syscall this is tested so that we'll rewind the pc
740 * to account for with sysenter or int entry.
741 */
742 addl $8,%esp /* remove eip/cs */
743 pushl %ecx /* save %ecx */
744 movl 8(%esp),%ecx /* top of intr stack -> pcb stack */
745 xchgl %ecx,%esp /* switch to pcb stack */
746 pushl $(USER_DS) /* ss */
747 pushl %ss:(%ecx) /* %ecx into uesp slot */
748 pushl %ss:4(%ecx) /* eflags */
749 movl %ss:(%ecx),%ecx /* restore %ecx */
750 pushl $(SYSENTER_TF_CS) /* cs - not SYSENTER_CS for iret path */
751 jmp hi_sysenter_2 /* continue sysenter entry */
752 hi_debug_trap:
753 pushl $0
754 pushl $(T_DEBUG) /* handle as user trap */
755 pusha /* save the general registers */
756 movl $(LO_ALLTRAPS),%ebx
757 jmp enter_lohandler
758
759
760
761 /*
762 * General protection or segment-not-present fault.
763 * Check for a GP/NP fault in the kernel_return
764 * sequence; if there, report it as a GP/NP fault on the user's instruction.
765 *
766 * esp-> 0: trap code (NP or GP)
767 * 4: segment number in error
768 * 8 eip
769 * 12 cs
770 * 16 eflags
771 * 20 old registers (trap is from kernel)
772 */
773 Entry(hi_gen_prot)
774 pushl $(T_GENERAL_PROTECTION) /* indicate fault type */
775 jmp trap_check_kernel_exit /* check for kernel exit sequence */
776
777 Entry(hi_segnp)
778 pushl $(T_SEGMENT_NOT_PRESENT)
779 /* indicate fault type */
780 trap_check_kernel_exit:
781 testb $3,12(%esp)
782 jnz hi_take_trap
783 /* trap was from kernel mode, so */
784 /* check for the kernel exit sequence */
785 cmpl $(HI_TEXT(ret_iret)),8(%esp) /* on IRET? */
786 je fault_iret
787 cmpl $(HI_TEXT(ret_popl_ds)),8(%esp) /* popping DS? */
788 je fault_popl_ds
789 cmpl $(HI_TEXT(ret_popl_es)),8(%esp) /* popping ES? */
790 je fault_popl_es
791 cmpl $(HI_TEXT(ret_popl_fs)),8(%esp) /* popping FS? */
792 je fault_popl_fs
793 cmpl $(HI_TEXT(ret_popl_gs)),8(%esp) /* popping GS? */
794 je fault_popl_gs
795 hi_take_trap:
796 pusha /* save the general registers */
797 movl $(LO_ALLTRAPS),%ebx
798 jmp enter_lohandler
799
800
801 /*
802 * GP/NP fault on IRET: CS or SS is in error.
803 * All registers contain the user's values.
804 *
805 * on SP is
806 * 0 trap number
807 * 4 errcode
808 * 8 eip
809 * 12 cs --> trapno
810 * 16 efl --> errcode
811 * 20 user eip
812 * 24 user cs
813 * 28 user eflags
814 * 32 user esp
815 * 36 user ss
816 */
817 fault_iret:
818 movl %eax,8(%esp) /* save eax (we don`t need saved eip) */
819 popl %eax /* get trap number */
820 movl %eax,12-4(%esp) /* put in user trap number */
821 popl %eax /* get error code */
822 movl %eax,16-8(%esp) /* put in user errcode */
823 popl %eax /* restore eax */
824 /* now treat as fault from user */
825 pusha /* save the general registers */
826 movl $(LO_ALLTRAPS),%ebx
827 jmp enter_lohandler
828
829 /*
830 * Fault restoring a segment register. The user's registers are still
831 * saved on the stack. The offending segment register has not been
832 * popped.
833 */
834 fault_popl_ds:
835 popl %eax /* get trap number */
836 popl %edx /* get error code */
837 addl $12,%esp /* pop stack to user regs */
838 jmp push_es /* (DS on top of stack) */
839 fault_popl_es:
840 popl %eax /* get trap number */
841 popl %edx /* get error code */
842 addl $12,%esp /* pop stack to user regs */
843 jmp push_fs /* (ES on top of stack) */
844 fault_popl_fs:
845 popl %eax /* get trap number */
846 popl %edx /* get error code */
847 addl $12,%esp /* pop stack to user regs */
848 jmp push_gs /* (FS on top of stack) */
849 fault_popl_gs:
850 popl %eax /* get trap number */
851 popl %edx /* get error code */
852 addl $12,%esp /* pop stack to user regs */
853 jmp push_none /* (GS on top of stack) */
854
855 push_es:
856 pushl %es /* restore es, */
857 push_fs:
858 pushl %fs /* restore fs, */
859 push_gs:
860 pushl %gs /* restore gs. */
861 push_none:
862 pushl $(SS_32) /* 32-bit state flavor */
863 movl %eax,R32_TRAPNO(%esp) /* set trap number */
864 movl %edx,R32_ERR(%esp) /* set error code */
865 /* now treat as fault from user */
866 /* except that segment registers are */
867 /* already pushed */
868 movl $(LO_ALLTRAPS),%ebx
869 jmp enter_lohandler1
870
871
872 .text
873
874
875 Entry(hi_remap_etext)
876
877
878 /*
879 * All 32 bit task 'exceptions' enter lo_alltraps:
880 * esp -> x86_saved_state_t
881 *
882 * The rest of the state is set up as:
883 * cr3 -> kernel directory
884 * esp -> low based stack
885 * gs -> CPU_DATA_GS
886 * cs -> KERNEL32_CS
887 * ss/ds/es -> KERNEL_DS
888 *
889 * interrupts disabled
890 * direction flag cleared
891 */
892 Entry(lo_alltraps32)
893 movl R32_CS(%esp),%eax /* assume 32-bit state */
894 cmpl $(SS_64),SS_FLAVOR(%esp)/* 64-bit? */
895 jne 1f
896 movl R64_CS(%esp),%eax /* 64-bit user mode */
897 1:
898 testb $3,%al
899 jz trap_from_kernel
900 /* user mode trap */
901 TIME_TRAP_UENTRY
902
903 movl %gs:CPU_ACTIVE_THREAD,%ecx
904 movl TH_TASK(%ecx),%ebx
905
906 /* Check for active vtimers in the current task */
907 TASK_VTIMER_CHECK(%ebx, %ecx)
908
909 movl %gs:CPU_KERNEL_STACK,%ebx
910 xchgl %ebx,%esp /* switch to kernel stack */
911
912 CCALL1(user_trap, %ebx) /* call user trap routine */
913 /* user_trap() unmasks interrupts */
914 cli /* hold off intrs - critical section */
915 xorl %ecx,%ecx /* don't check if we're in the PFZ */
916
917 /*
918 * Return from trap or system call, checking for ASTs.
919 * On lowbase PCB stack with intrs disabled
920 */
921 Entry(return_from_trap32)
922 movl %gs:CPU_ACTIVE_THREAD, %esp
923 movl TH_PCB_ISS(%esp), %esp /* switch back to PCB stack */
924 movl %gs:CPU_PENDING_AST, %eax
925 testl %eax, %eax
926 je EXT(return_to_user) /* branch if no AST */
927 LEXT(return_from_trap_with_ast)
928 movl %gs:CPU_KERNEL_STACK, %ebx
929 xchgl %ebx, %esp /* switch to kernel stack */
930
931 testl %ecx, %ecx /* see if we need to check for an EIP in the PFZ */
932 je 2f /* no, go handle the AST */
933 cmpl $(SS_64), SS_FLAVOR(%ebx) /* are we a 64-bit task? */
934 je 1f
935 /* no... 32-bit user mode */
936 movl R32_EIP(%ebx), %eax
937 pushl %ebx /* save PCB stack */
938 xorl %ebp, %ebp /* clear frame pointer */
939 CCALL1(commpage_is_in_pfz32, %eax)
940 popl %ebx /* retrieve pointer to PCB stack */
941 testl %eax, %eax
942 je 2f /* not in the PFZ... go service AST */
943 movl %eax, R32_EBX(%ebx) /* let the PFZ know we've pended an AST */
944 xchgl %ebx, %esp /* switch back to PCB stack */
945 jmp EXT(return_to_user)
946 1: /* 64-bit user mode */
947 movl R64_RIP(%ebx), %ecx
948 movl R64_RIP+4(%ebx), %eax
949 pushl %ebx /* save PCB stack */
950 xorl %ebp, %ebp /* clear frame pointer */
951 CCALL2(commpage_is_in_pfz64, %ecx, %eax)
952 popl %ebx /* retrieve pointer to PCB stack */
953 testl %eax, %eax
954 je 2f /* not in the PFZ... go service AST */
955 movl %eax, R64_RBX(%ebx) /* let the PFZ know we've pended an AST */
956 xchgl %ebx, %esp /* switch back to PCB stack */
957 jmp EXT(return_to_user)
958 2:
959 sti /* interrupts always enabled on return to user mode */
960 xorl %ebp, %ebp /* Clear framepointer */
961 CCALL1(i386_astintr, $0) /* take the AST */
962 cli
963 xorl %ecx, %ecx /* don't check if we're in the PFZ */
964 jmp EXT(return_from_trap32) /* and check again (rare) */
965
966
967 /*
968 * Trap from kernel mode. No need to switch stacks.
969 * Interrupts must be off here - we will set them to state at time of trap
970 * as soon as it's safe for us to do so and not recurse doing preemption
971 */
972 trap_from_kernel:
973 movl %esp, %eax /* saved state addr */
974 pushl R32_EIP(%esp) /* Simulate a CALL from fault point */
975 pushl %ebp /* Extend framepointer chain */
976 movl %esp, %ebp
977 CCALL1WITHSP(kernel_trap, %eax) /* Call kernel trap handler */
978 popl %ebp
979 addl $4, %esp
980 cli
981
982 movl %gs:CPU_PENDING_AST,%eax /* get pending asts */
983 testl $ AST_URGENT,%eax /* any urgent preemption? */
984 je ret_to_kernel /* no, nothing to do */
985 cmpl $ T_PREEMPT,R32_TRAPNO(%esp)
986 je ret_to_kernel /* T_PREEMPT handled in kernel_trap() */
987 testl $ EFL_IF,R32_EFLAGS(%esp) /* interrupts disabled? */
988 je ret_to_kernel
989 cmpl $0,%gs:CPU_PREEMPTION_LEVEL /* preemption disabled? */
990 jne ret_to_kernel
991 movl %gs:CPU_KERNEL_STACK,%eax
992 movl %esp,%ecx
993 xorl %eax,%ecx
994 and EXT(kernel_stack_mask),%ecx
995 testl %ecx,%ecx /* are we on the kernel stack? */
996 jne ret_to_kernel /* no, skip it */
997
998 CCALL1(i386_astintr, $1) /* take the AST */
999
1000 jmp ret_to_kernel
1001
1002
1003 /*
1004 * All interrupts on all tasks enter here with:
1005 * esp-> -> x86_saved_state_t
1006 *
1007 * cr3 -> kernel directory
1008 * esp -> low based stack
1009 * gs -> CPU_DATA_GS
1010 * cs -> KERNEL32_CS
1011 * ss/ds/es -> KERNEL_DS
1012 *
1013 * interrupts disabled
1014 * direction flag cleared
1015 */
1016 Entry(lo_allintrs32)
1017 /*
1018 * test whether already on interrupt stack
1019 */
1020 movl %gs:CPU_INT_STACK_TOP,%ecx
1021 cmpl %esp,%ecx
1022 jb 1f
1023 leal -INTSTACK_SIZE(%ecx),%edx
1024 cmpl %esp,%edx
1025 jb int_from_intstack
1026 1:
1027 xchgl %ecx,%esp /* switch to interrupt stack */
1028
1029 movl %cr0,%eax /* get cr0 */
1030 orl $(CR0_TS),%eax /* or in TS bit */
1031 movl %eax,%cr0 /* set cr0 */
1032
1033 subl $8, %esp /* for 16-byte stack alignment */
1034 pushl %ecx /* save pointer to old stack */
1035 movl %ecx,%gs:CPU_INT_STATE /* save intr state */
1036
1037 TIME_INT_ENTRY /* do timing */
1038
1039 movl %gs:CPU_ACTIVE_THREAD,%ecx
1040 movl TH_TASK(%ecx),%ebx
1041
1042 /* Check for active vtimers in the current task */
1043 TASK_VTIMER_CHECK(%ebx, %ecx)
1044
1045 incl %gs:CPU_PREEMPTION_LEVEL
1046 incl %gs:CPU_INTERRUPT_LEVEL
1047
1048 movl %gs:CPU_INT_STATE, %eax
1049 CCALL1(interrupt, %eax) /* call generic interrupt routine */
1050
1051 cli /* just in case we returned with intrs enabled */
1052 xorl %eax,%eax
1053 movl %eax,%gs:CPU_INT_STATE /* clear intr state pointer */
1054
1055 decl %gs:CPU_INTERRUPT_LEVEL
1056 decl %gs:CPU_PREEMPTION_LEVEL
1057
1058 TIME_INT_EXIT /* do timing */
1059
1060 movl %gs:CPU_ACTIVE_THREAD,%eax
1061 movl TH_PCB_FPS(%eax),%eax /* get pcb's ifps */
1062 testl %eax, %eax /* Is there a context */
1063 je 1f /* Branch if not */
1064 cmpl $0, FP_VALID(%eax) /* Check fp_valid */
1065 jne 1f /* Branch if valid */
1066 clts /* Clear TS */
1067 jmp 2f
1068 1:
1069 movl %cr0,%eax /* get cr0 */
1070 orl $(CR0_TS),%eax /* or in TS bit */
1071 movl %eax,%cr0 /* set cr0 */
1072 2:
1073 popl %esp /* switch back to old stack */
1074
1075 /* Load interrupted code segment into %eax */
1076 movl R32_CS(%esp),%eax /* assume 32-bit state */
1077 cmpl $(SS_64),SS_FLAVOR(%esp)/* 64-bit? */
1078 jne 3f
1079 movl R64_CS(%esp),%eax /* 64-bit user mode */
1080 3:
1081 testb $3,%al /* user mode, */
1082 jnz ast_from_interrupt_user /* go handle potential ASTs */
1083 /*
1084 * we only want to handle preemption requests if
1085 * the interrupt fell in the kernel context
1086 * and preemption isn't disabled
1087 */
1088 movl %gs:CPU_PENDING_AST,%eax
1089 testl $ AST_URGENT,%eax /* any urgent requests? */
1090 je ret_to_kernel /* no, nothing to do */
1091
1092 cmpl $0,%gs:CPU_PREEMPTION_LEVEL /* preemption disabled? */
1093 jne ret_to_kernel /* yes, skip it */
1094
1095 movl %gs:CPU_KERNEL_STACK,%eax
1096 movl %esp,%ecx
1097 xorl %eax,%ecx
1098 and EXT(kernel_stack_mask),%ecx
1099 testl %ecx,%ecx /* are we on the kernel stack? */
1100 jne ret_to_kernel /* no, skip it */
1101
1102 /*
1103 * Take an AST from kernel space. We don't need (and don't want)
1104 * to do as much as the case where the interrupt came from user
1105 * space.
1106 */
1107 CCALL1(i386_astintr, $1)
1108
1109 jmp ret_to_kernel
1110
1111
1112 /*
1113 * nested int - simple path, can't preempt etc on way out
1114 */
1115 int_from_intstack:
1116 incl %gs:CPU_PREEMPTION_LEVEL
1117 incl %gs:CPU_INTERRUPT_LEVEL
1118
1119 movl %esp, %edx /* x86_saved_state */
1120 CCALL1(interrupt, %edx)
1121
1122 decl %gs:CPU_INTERRUPT_LEVEL
1123 decl %gs:CPU_PREEMPTION_LEVEL
1124
1125 jmp ret_to_kernel
1126
1127 /*
1128 * Take an AST from an interrupted user
1129 */
1130 ast_from_interrupt_user:
1131 movl %gs:CPU_PENDING_AST,%eax
1132 testl %eax,%eax /* pending ASTs? */
1133 je ret_to_user /* no, nothing to do */
1134
1135 TIME_TRAP_UENTRY
1136
1137 movl $1, %ecx /* check if we're in the PFZ */
1138 jmp EXT(return_from_trap_with_ast) /* return */
1139
1140
1141 /*
1142 * 32bit Tasks
1143 * System call entries via INTR_GATE or sysenter:
1144 *
1145 * esp -> x86_saved_state32_t
1146 * cr3 -> kernel directory
1147 * esp -> low based stack
1148 * gs -> CPU_DATA_GS
1149 * cs -> KERNEL32_CS
1150 * ss/ds/es -> KERNEL_DS
1151 *
1152 * interrupts disabled
1153 * direction flag cleared
1154 */
1155
1156 Entry(lo_sysenter32)
1157 /*
1158 * We can be here either for a mach syscall or a unix syscall,
1159 * as indicated by the sign of the code:
1160 */
1161 movl R32_EAX(%esp),%eax
1162 testl %eax,%eax
1163 js EXT(lo_mach_scall32) /* < 0 => mach */
1164 /* > 0 => unix */
1165
1166 Entry(lo_unix_scall32)
1167 TIME_TRAP_UENTRY
1168
1169 movl %gs:CPU_KERNEL_STACK,%edi
1170 xchgl %edi,%esp /* switch to kernel stack */
1171 movl %gs:CPU_ACTIVE_THREAD,%ecx /* get current thread */
1172 movl TH_TASK(%ecx),%ebx /* point to current task */
1173 incl TH_SYSCALLS_UNIX(%ecx) /* increment call count */
1174
1175 /* Check for active vtimers in the current task */
1176 TASK_VTIMER_CHECK(%ebx, %ecx)
1177
1178 sti
1179
1180 CCALL1(unix_syscall, %edi)
1181 /*
1182 * always returns through thread_exception_return
1183 */
1184
1185
1186 Entry(lo_mach_scall32)
1187 TIME_TRAP_UENTRY
1188
1189 movl %gs:CPU_KERNEL_STACK,%edi
1190 xchgl %edi,%esp /* switch to kernel stack */
1191 movl %gs:CPU_ACTIVE_THREAD,%ecx /* get current thread */
1192 movl TH_TASK(%ecx),%ebx /* point to current task */
1193 incl TH_SYSCALLS_MACH(%ecx) /* increment call count */
1194
1195 /* Check for active vtimers in the current task */
1196 TASK_VTIMER_CHECK(%ebx, %ecx)
1197
1198 sti
1199
1200 CCALL1(mach_call_munger, %edi)
1201 /*
1202 * always returns through thread_exception_return
1203 */
1204
1205
1206 Entry(lo_mdep_scall32)
1207 TIME_TRAP_UENTRY
1208
1209 movl %gs:CPU_KERNEL_STACK,%edi
1210 xchgl %edi,%esp /* switch to kernel stack */
1211 movl %gs:CPU_ACTIVE_THREAD,%ecx /* get current thread */
1212 movl TH_TASK(%ecx),%ebx /* point to current task */
1213
1214 /* Check for active vtimers in the current task */
1215 TASK_VTIMER_CHECK(%ebx, %ecx)
1216
1217 sti
1218
1219 CCALL1(machdep_syscall, %edi)
1220 /*
1221 * always returns through thread_exception_return
1222 */
1223
1224
1225 Entry(lo_diag_scall32)
1226 TIME_TRAP_UENTRY
1227
1228 movl %gs:CPU_KERNEL_STACK,%edi
1229 xchgl %edi,%esp /* switch to kernel stack */
1230 movl %gs:CPU_ACTIVE_THREAD,%ecx /* get current thread */
1231 movl TH_TASK(%ecx),%ebx /* point to current task */
1232
1233 /* Check for active vtimers in the current task */
1234 TASK_VTIMER_CHECK(%ebx, %ecx)
1235
1236 pushl %edi /* push pbc stack for later */
1237
1238 CCALL1(diagCall, %edi) // Call diagnostics
1239
1240 cli // Disable interruptions just in case
1241 popl %esp // Get back the original stack
1242 cmpl $0,%eax // What kind of return is this?
1243 jne EXT(return_to_user) // Normal return, do not check asts...
1244
1245 CCALL5(i386_exception, $EXC_SYSCALL, $0x6000, $0, $1, $0)
1246 // pass what would be the diag syscall
1247 // error return - cause an exception
1248 /* no return */
1249
1250
1251 LEXT(return_to_user)
1252 TIME_TRAP_UEXIT
1253 jmp ret_to_user
1254
1255
1256 /*
1257 * Double-fault exception handler task. The last gasp...
1258 */
1259 Entry(df_task_start)
1260 CCALL1(panic_double_fault32, $(T_DOUBLE_FAULT))
1261 hlt
1262
1263
1264 /*
1265 * machine-check handler task. The last gasp...
1266 */
1267 Entry(mc_task_start)
1268 CCALL1(panic_machine_check32, $(T_MACHINE_CHECK))
1269 hlt
1270
1271 #if MACH_KDB
1272 #include <i386/lapic.h>
1273 #define CX(addr,reg) addr(,reg,4)
1274 #if 0
1275 /*
1276 * Note that the per-fault entry points are not currently
1277 * functional. The only way to make them work would be to
1278 * set up separate TSS's for each fault type, which doesn't
1279 * currently seem worthwhile. (The offset part of a task
1280 * gate is always ignored.) So all faults that task switch
1281 * currently resume at db_task_start.
1282 */
1283 /*
1284 * Double fault (Murphy's point) - error code (0) on stack
1285 */
1286 Entry(db_task_dbl_fault)
1287 popl %eax
1288 movl $(T_DOUBLE_FAULT),%ebx
1289 jmp db_task_start
1290 /*
1291 * Segment not present - error code on stack
1292 */
1293 Entry(db_task_seg_np)
1294 popl %eax
1295 movl $(T_SEGMENT_NOT_PRESENT),%ebx
1296 jmp db_task_start
1297 /*
1298 * Stack fault - error code on (current) stack
1299 */
1300 Entry(db_task_stk_fault)
1301 popl %eax
1302 movl $(T_STACK_FAULT),%ebx
1303 jmp db_task_start
1304 /*
1305 * General protection fault - error code on stack
1306 */
1307 Entry(db_task_gen_prot)
1308 popl %eax
1309 movl $(T_GENERAL_PROTECTION),%ebx
1310 jmp db_task_start
1311 #endif /* 0 */
1312 /*
1313 * The entry point where execution resumes after last-ditch debugger task
1314 * switch.
1315 */
1316 Entry(db_task_start)
1317 movl %esp,%edx
1318 subl $(ISS32_SIZE),%edx
1319 movl %edx,%esp /* allocate x86_saved_state on stack */
1320 movl %eax,R32_ERR(%esp)
1321 movl %ebx,R32_TRAPNO(%esp)
1322 pushl %edx
1323 CPU_NUMBER(%edx)
1324 movl CX(EXT(master_dbtss),%edx),%edx
1325 movl TSS_LINK(%edx),%eax
1326 pushl %eax /* pass along selector of previous TSS */
1327 call EXT(db_tss_to_frame)
1328 popl %eax /* get rid of TSS selector */
1329 call EXT(db_trap_from_asm)
1330 addl $0x4,%esp
1331 /*
1332 * And now...?
1333 */
1334 iret /* ha, ha, ha... */
1335 #endif /* MACH_KDB */