]> git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/idt.s
2b1a0af776a351885e257ff087c0409960653fe3
[apple/xnu.git] / osfmk / i386 / idt.s
1 /*
2 * Copyright (c) 2000-2005 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);\
102 Entry(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);\
115 Entry(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);\
156 Entry(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 ;\
169 L_ ## 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
179 Entry(master_idt)
180 Entry(hi_remap_data)
181 .text
182 Entry(hi_remap_text)
183
184 EXCEPTION(0x00,t_zero_div)
185 EXCEP_SPC(0x01,hi_debug)
186 INTERRUPT(0x02) /* NMI */
187 EXCEP_USR(0x03,t_int3)
188 EXCEP_USR(0x04,t_into)
189 EXCEP_USR(0x05,t_bounds)
190 EXCEPTION(0x06,t_invop)
191 EXCEPTION(0x07,t_nofpu)
192 #if MACH_KDB
193 EXCEP_TASK(0x08,db_task_dbl_fault)
194 #else
195 DF_FATAL_TASK(0x08,df_task_start)
196 #endif
197 EXCEPTION(0x09,a_fpu_over)
198 EXCEPTION(0x0a,a_inv_tss)
199 EXCEP_SPC(0x0b,hi_segnp)
200 #if MACH_KDB
201 EXCEP_TASK(0x0c,db_task_stk_fault)
202 #else
203 EXCEP_ERR(0x0c,t_stack_fault)
204 #endif
205 EXCEP_SPC(0x0d,hi_gen_prot)
206 EXCEP_SPC(0x0e,hi_page_fault)
207 EXCEPTION(0x0f,t_trap_0f)
208 EXCEPTION(0x10,t_fpu_err)
209 EXCEPTION(0x11,t_trap_11)
210 MC_FATAL_TASK(0x12,mc_task_start)
211 EXCEPTION(0x13,t_sse_err)
212 EXCEPTION(0x14,t_trap_14)
213 EXCEPTION(0x15,t_trap_15)
214 EXCEPTION(0x16,t_trap_16)
215 EXCEPTION(0x17,t_trap_17)
216 EXCEPTION(0x18,t_trap_18)
217 EXCEPTION(0x19,t_trap_19)
218 EXCEPTION(0x1a,t_trap_1a)
219 EXCEPTION(0x1b,t_trap_1b)
220 EXCEPTION(0x1c,t_trap_1c)
221 EXCEPTION(0x1d,t_trap_1d)
222 EXCEPTION(0x1e,t_trap_1e)
223 EXCEPTION(0x1f,t_trap_1f)
224
225 INTERRUPT(0x20)
226 INTERRUPT(0x21)
227 INTERRUPT(0x22)
228 INTERRUPT(0x23)
229 INTERRUPT(0x24)
230 INTERRUPT(0x25)
231 INTERRUPT(0x26)
232 INTERRUPT(0x27)
233 INTERRUPT(0x28)
234 INTERRUPT(0x29)
235 INTERRUPT(0x2a)
236 INTERRUPT(0x2b)
237 INTERRUPT(0x2c)
238 INTERRUPT(0x2d)
239 INTERRUPT(0x2e)
240 INTERRUPT(0x2f)
241
242 INTERRUPT(0x30)
243 INTERRUPT(0x31)
244 INTERRUPT(0x32)
245 INTERRUPT(0x33)
246 INTERRUPT(0x34)
247 INTERRUPT(0x35)
248 INTERRUPT(0x36)
249 INTERRUPT(0x37)
250 INTERRUPT(0x38)
251 INTERRUPT(0x39)
252 INTERRUPT(0x3a)
253 INTERRUPT(0x3b)
254 INTERRUPT(0x3c)
255 INTERRUPT(0x3d)
256 INTERRUPT(0x3e)
257 INTERRUPT(0x3f)
258
259 INTERRUPT(0x40)
260 INTERRUPT(0x41)
261 INTERRUPT(0x42)
262 INTERRUPT(0x43)
263 INTERRUPT(0x44)
264 INTERRUPT(0x45)
265 INTERRUPT(0x46)
266 INTERRUPT(0x47)
267 INTERRUPT(0x48)
268 INTERRUPT(0x49)
269 INTERRUPT(0x4a)
270 INTERRUPT(0x4b)
271 INTERRUPT(0x4c)
272 INTERRUPT(0x4d)
273 INTERRUPT(0x4e)
274 INTERRUPT(0x4f)
275
276 INTERRUPT(0x50)
277 INTERRUPT(0x51)
278 INTERRUPT(0x52)
279 INTERRUPT(0x53)
280 INTERRUPT(0x54)
281 INTERRUPT(0x55)
282 INTERRUPT(0x56)
283 INTERRUPT(0x57)
284 INTERRUPT(0x58)
285 INTERRUPT(0x59)
286 INTERRUPT(0x5a)
287 INTERRUPT(0x5b)
288 INTERRUPT(0x5c)
289 INTERRUPT(0x5d)
290 INTERRUPT(0x5e)
291 INTERRUPT(0x5f)
292
293 INTERRUPT(0x60)
294 INTERRUPT(0x61)
295 INTERRUPT(0x62)
296 INTERRUPT(0x63)
297 INTERRUPT(0x64)
298 INTERRUPT(0x65)
299 INTERRUPT(0x66)
300 INTERRUPT(0x67)
301 INTERRUPT(0x68)
302 INTERRUPT(0x69)
303 INTERRUPT(0x6a)
304 INTERRUPT(0x6b)
305 INTERRUPT(0x6c)
306 INTERRUPT(0x6d)
307 INTERRUPT(0x6e)
308 INTERRUPT(0x6f)
309
310 INTERRUPT(0x70)
311 INTERRUPT(0x71)
312 INTERRUPT(0x72)
313 INTERRUPT(0x73)
314 INTERRUPT(0x74)
315 INTERRUPT(0x75)
316 INTERRUPT(0x76)
317 INTERRUPT(0x77)
318 INTERRUPT(0x78)
319 INTERRUPT(0x79)
320 INTERRUPT(0x7a)
321 INTERRUPT(0x7b)
322 INTERRUPT(0x7c)
323 INTERRUPT(0x7d)
324 INTERRUPT(0x7e)
325 INTERRUPT(0x7f)
326
327 EXCEP_SPC_USR(0x80,hi_unix_scall)
328 EXCEP_SPC_USR(0x81,hi_mach_scall)
329 EXCEP_SPC_USR(0x82,hi_mdep_scall)
330 EXCEP_SPC_USR(0x83,hi_diag_scall)
331
332 INTERRUPT(0x84)
333 INTERRUPT(0x85)
334 INTERRUPT(0x86)
335 INTERRUPT(0x87)
336 INTERRUPT(0x88)
337 INTERRUPT(0x89)
338 INTERRUPT(0x8a)
339 INTERRUPT(0x8b)
340 INTERRUPT(0x8c)
341 INTERRUPT(0x8d)
342 INTERRUPT(0x8e)
343 INTERRUPT(0x8f)
344
345 INTERRUPT(0x90)
346 INTERRUPT(0x91)
347 INTERRUPT(0x92)
348 INTERRUPT(0x93)
349 INTERRUPT(0x94)
350 INTERRUPT(0x95)
351 INTERRUPT(0x96)
352 INTERRUPT(0x97)
353 INTERRUPT(0x98)
354 INTERRUPT(0x99)
355 INTERRUPT(0x9a)
356 INTERRUPT(0x9b)
357 INTERRUPT(0x9c)
358 INTERRUPT(0x9d)
359 INTERRUPT(0x9e)
360 INTERRUPT(0x9f)
361
362 INTERRUPT(0xa0)
363 INTERRUPT(0xa1)
364 INTERRUPT(0xa2)
365 INTERRUPT(0xa3)
366 INTERRUPT(0xa4)
367 INTERRUPT(0xa5)
368 INTERRUPT(0xa6)
369 INTERRUPT(0xa7)
370 INTERRUPT(0xa8)
371 INTERRUPT(0xa9)
372 INTERRUPT(0xaa)
373 INTERRUPT(0xab)
374 INTERRUPT(0xac)
375 INTERRUPT(0xad)
376 INTERRUPT(0xae)
377 INTERRUPT(0xaf)
378
379 INTERRUPT(0xb0)
380 INTERRUPT(0xb1)
381 INTERRUPT(0xb2)
382 INTERRUPT(0xb3)
383 INTERRUPT(0xb4)
384 INTERRUPT(0xb5)
385 INTERRUPT(0xb6)
386 INTERRUPT(0xb7)
387 INTERRUPT(0xb8)
388 INTERRUPT(0xb9)
389 INTERRUPT(0xba)
390 INTERRUPT(0xbb)
391 INTERRUPT(0xbc)
392 INTERRUPT(0xbd)
393 INTERRUPT(0xbe)
394 INTERRUPT(0xbf)
395
396 INTERRUPT(0xc0)
397 INTERRUPT(0xc1)
398 INTERRUPT(0xc2)
399 INTERRUPT(0xc3)
400 INTERRUPT(0xc4)
401 INTERRUPT(0xc5)
402 INTERRUPT(0xc6)
403 INTERRUPT(0xc7)
404 INTERRUPT(0xc8)
405 INTERRUPT(0xc9)
406 INTERRUPT(0xca)
407 INTERRUPT(0xcb)
408 INTERRUPT(0xcc)
409 INTERRUPT(0xcd)
410 INTERRUPT(0xce)
411 INTERRUPT(0xcf)
412
413 INTERRUPT(0xd0)
414 INTERRUPT(0xd1)
415 INTERRUPT(0xd2)
416 INTERRUPT(0xd3)
417 INTERRUPT(0xd4)
418 INTERRUPT(0xd5)
419 INTERRUPT(0xd6)
420 INTERRUPT(0xd7)
421 INTERRUPT(0xd8)
422 INTERRUPT(0xd9)
423 INTERRUPT(0xda)
424 INTERRUPT(0xdb)
425 INTERRUPT(0xdc)
426 INTERRUPT(0xdd)
427 INTERRUPT(0xde)
428 INTERRUPT(0xdf)
429
430 INTERRUPT(0xe0)
431 INTERRUPT(0xe1)
432 INTERRUPT(0xe2)
433 INTERRUPT(0xe3)
434 INTERRUPT(0xe4)
435 INTERRUPT(0xe5)
436 INTERRUPT(0xe6)
437 INTERRUPT(0xe7)
438 INTERRUPT(0xe8)
439 INTERRUPT(0xe9)
440 INTERRUPT(0xea)
441 INTERRUPT(0xeb)
442 INTERRUPT(0xec)
443 INTERRUPT(0xed)
444 INTERRUPT(0xee)
445 INTERRUPT(0xef)
446
447 INTERRUPT(0xf0)
448 INTERRUPT(0xf1)
449 INTERRUPT(0xf2)
450 INTERRUPT(0xf3)
451 INTERRUPT(0xf4)
452 INTERRUPT(0xf5)
453 INTERRUPT(0xf6)
454 INTERRUPT(0xf7)
455 INTERRUPT(0xf8)
456 INTERRUPT(0xf9)
457 INTERRUPT(0xfa)
458 INTERRUPT(0xfb)
459 INTERRUPT(0xfc)
460 INTERRUPT(0xfd)
461 INTERRUPT(0xfe)
462 EXCEPTION(0xff,t_preempt)
463
464
465 .data
466 Entry(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
501 Entry(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
519 1:
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 */
529 2:
530
531 Entry(hi_ret_to_kernel)
532
533 popl %eax /* ignore flavor of saved state */
534 EXT(ret_popl_gs):
535 popl %gs /* restore segment registers */
536 EXT(ret_popl_fs):
537 popl %fs
538 EXT(ret_popl_es):
539 popl %es
540 EXT(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
548 EXT(ret_iret):
549 iret /* return from interrupt */
550 fast_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 /*******************************************************************************************************/
560
561
562 Entry(hi_unix_scall)
563 pushl %eax /* save system call number */
564 pushl $0 /* clear trap number slot */
565 pusha /* save the general registers */
566 movl $ EXT(lo_unix_scall),%ebx
567 jmp enter_lohandler
568
569
570 Entry(hi_mach_scall)
571 pushl %eax /* save system call number */
572 pushl $0 /* clear trap number slot */
573 pusha /* save the general registers */
574 movl $ EXT(lo_mach_scall),%ebx
575 jmp enter_lohandler
576
577
578 Entry(hi_mdep_scall)
579 pushl %eax /* save system call number */
580 pushl $0 /* clear trap number slot */
581 pusha /* save the general registers */
582 movl $ EXT(lo_mdep_scall),%ebx
583 jmp enter_lohandler
584
585
586 Entry(hi_diag_scall)
587 pushl %eax // Save sselector
588 pushl $0 // Clear trap number slot
589 pusha // save the general registers
590 movl $EXT(lo_diag_scall),%ebx // Get the function down low to transfer to
591 jmp enter_lohandler // Leap to it...
592
593
594 /*
595 * sysenter entry point
596 * Requires user code to set up:
597 * edx: user instruction pointer (return address)
598 * ecx: user stack pointer
599 * on which is pushed stub ret addr and saved ebx
600 * Return to user-space is made using sysexit.
601 * Note: sysenter/sysexit cannot be used for calls returning a value in edx,
602 * or requiring ecx to be preserved.
603 */
604 Entry(hi_sysenter)
605 movl (%esp), %esp /* switch from intr stack to pcb */
606 /*
607 * Push values on to the PCB stack
608 * to cons up the saved state.
609 */
610 pushl $(USER_DS) /* ss */
611 pushl %ecx /* uesp */
612 pushf /* flags */
613 /*
614 * Clear, among others, the Nested Task (NT) flags bit;
615 * This is cleared by INT, but not by sysenter, which only
616 * clears RF, VM and IF.
617 */
618 pushl $0
619 popfl
620 pushl $(SYSENTER_CS) /* cs */
621 hi_sysenter_2:
622 pushl %edx /* eip */
623 pushl %eax /* err/eax - syscall code */
624 pushl $0 /* clear trap number slot */
625 pusha /* save the general registers */
626 orl $(EFL_IF),R_EFLAGS-R_EDI(%esp) /* (edi was last reg pushed) */
627 movl $ EXT(lo_sysenter),%ebx
628 enter_lohandler:
629 pushl %ds
630 pushl %es
631 pushl %fs
632 pushl %gs
633 enter_lohandler1:
634 pushl $(SS_32) /* 32-bit state flavor */
635 mov %ss,%eax
636 mov %eax,%ds
637 mov %eax,%fs
638 mov %eax,%es /* switch to kernel data seg */
639 mov $(CPU_DATA_GS),%eax
640 mov %eax,%gs
641 cld /* clear direction flag */
642 /*
643 * Switch to kernel's address space if necessary
644 */
645 movl HI_DATA(lo_kernel_cr3),%ecx
646 movl %cr3,%eax
647 cmpl %eax,%ecx
648 je 1f
649 movl %ecx,%cr3
650 movl %ecx,%gs:CPU_ACTIVE_CR3
651 1:
652 testb $3,R_CS(%esp)
653 jz 2f
654 movl %esp,%edx /* came from user mode */
655 subl %gs:CPU_HI_ISS,%edx
656 movl %gs:CPU_ACTIVE_THREAD,%ecx
657 addl ACT_PCB_ISS(%ecx),%edx /* rebase the high stack to a low address */
658 movl %edx,%esp
659 cmpl $0, ACT_PCB_IDS(%ecx) /* Is there a debug register state? */
660 je 2f
661 movl $0, %ecx /* If so, reset DR7 (the control) */
662 movl %ecx, %dr7
663 2:
664 movl R_TRAPNO(%esp),%ecx // Get the interrupt vector
665 addl $1,%gs:hwIntCnt(,%ecx,4) // Bump the count
666 jmp *%ebx
667
668
669 /*
670 * Page fault traps save cr2.
671 */
672 Entry(hi_page_fault)
673 pushl $(T_PAGE_FAULT) /* mark a page fault trap */
674 pusha /* save the general registers */
675 movl %cr2,%eax /* get the faulting address */
676 movl %eax,R_CR2-R_EDI(%esp) /* save in esp save slot */
677
678 movl $ EXT(lo_alltraps),%ebx
679 jmp enter_lohandler
680
681
682
683 /*
684 * Debug trap. Check for single-stepping across system call into
685 * kernel. If this is the case, taking the debug trap has turned
686 * off single-stepping - save the flags register with the trace
687 * bit set.
688 */
689 Entry(hi_debug)
690 testb $3,4(%esp)
691 jnz hi_debug_trap
692 /* trap came from kernel mode */
693 cmpl $(HI_TEXT(hi_mach_scall)),(%esp)
694 jne 6f
695 addl $12,%esp /* remove eip/cs/eflags from debug_trap */
696 jmp EXT(hi_mach_scall) /* continue system call entry */
697 6:
698 cmpl $(HI_TEXT(hi_mdep_scall)),(%esp)
699 jne 5f
700 addl $12,%esp /* remove eip/cs/eflags from debug_trap */
701 jmp EXT(hi_mdep_scall) /* continue system call entry */
702 5:
703 cmpl $(HI_TEXT(hi_unix_scall)),(%esp)
704 jne 4f
705 addl $12,%esp /* remove eip/cs/eflags from debug_trap */
706 jmp EXT(hi_unix_scall) /* continue system call entry */
707 4:
708 cmpl $(HI_TEXT(hi_sysenter)),(%esp)
709 jne hi_debug_trap
710 /*
711 * eip/cs/flags have been pushed on intr stack
712 * We have to switch to pcb stack and copy eflags.
713 * Note: setting the cs selector to SYSENTER_TF_CS
714 * will cause the return to user path to take the iret path so
715 * that eflags (containing the trap bit) is set atomically.
716 * In unix_syscall this is tested so that we'll rewind the pc
717 * to account for with sysenter or int entry.
718 */
719 addl $8,%esp /* remove eip/cs */
720 pushl %ecx /* save %ecx */
721 movl 8(%esp),%ecx /* top of intr stack -> pcb stack */
722 xchgl %ecx,%esp /* switch to pcb stack */
723 pushl $(USER_DS) /* ss */
724 pushl %ss:(%ecx) /* %ecx into uesp slot */
725 pushl %ss:4(%ecx) /* eflags */
726 movl %ss:(%ecx),%ecx /* restore %ecx */
727 pushl $(SYSENTER_TF_CS) /* cs - not SYSENTER_CS for iret path */
728 jmp hi_sysenter_2 /* continue sysenter entry */
729 hi_debug_trap:
730 pushl $0
731 pushl $(T_DEBUG) /* handle as user trap */
732 pusha /* save the general registers */
733 movl $ EXT(lo_alltraps),%ebx
734 jmp enter_lohandler
735
736
737
738 /*
739 * General protection or segment-not-present fault.
740 * Check for a GP/NP fault in the kernel_return
741 * sequence; if there, report it as a GP/NP fault on the user's instruction.
742 *
743 * esp-> 0: trap code (NP or GP)
744 * 4: segment number in error
745 * 8 eip
746 * 12 cs
747 * 16 eflags
748 * 20 old registers (trap is from kernel)
749 */
750 Entry(hi_gen_prot)
751 pushl $(T_GENERAL_PROTECTION) /* indicate fault type */
752 jmp trap_check_kernel_exit /* check for kernel exit sequence */
753
754 Entry(hi_segnp)
755 pushl $(T_SEGMENT_NOT_PRESENT)
756 /* indicate fault type */
757 trap_check_kernel_exit:
758 testb $3,12(%esp)
759 jnz hi_take_trap
760 /* trap was from kernel mode, so */
761 /* check for the kernel exit sequence */
762 cmpl $(HI_TEXT(ret_iret)),8(%esp) /* on IRET? */
763 je fault_iret
764 cmpl $(HI_TEXT(ret_popl_ds)),8(%esp) /* popping DS? */
765 je fault_popl_ds
766 cmpl $(HI_TEXT(ret_popl_es)),8(%esp) /* popping ES? */
767 je fault_popl_es
768 cmpl $(HI_TEXT(ret_popl_fs)),8(%esp) /* popping FS? */
769 je fault_popl_fs
770 cmpl $(HI_TEXT(ret_popl_gs)),8(%esp) /* popping GS? */
771 je fault_popl_gs
772 hi_take_trap:
773 pusha /* save the general registers */
774 movl $ EXT(lo_alltraps),%ebx
775 jmp enter_lohandler
776
777
778 /*
779 * GP/NP fault on IRET: CS or SS is in error.
780 * All registers contain the user's values.
781 *
782 * on SP is
783 * 0 trap number
784 * 4 errcode
785 * 8 eip
786 * 12 cs --> trapno
787 * 16 efl --> errcode
788 * 20 user eip
789 * 24 user cs
790 * 28 user eflags
791 * 32 user esp
792 * 36 user ss
793 */
794 fault_iret:
795 movl %eax,8(%esp) /* save eax (we don`t need saved eip) */
796 popl %eax /* get trap number */
797 movl %eax,12-4(%esp) /* put in user trap number */
798 popl %eax /* get error code */
799 movl %eax,16-8(%esp) /* put in user errcode */
800 popl %eax /* restore eax */
801 /* now treat as fault from user */
802 pusha /* save the general registers */
803 movl $ EXT(lo_alltraps),%ebx
804 jmp enter_lohandler
805
806 /*
807 * Fault restoring a segment register. The user's registers are still
808 * saved on the stack. The offending segment register has not been
809 * popped.
810 */
811 fault_popl_ds:
812 popl %eax /* get trap number */
813 popl %edx /* get error code */
814 addl $12,%esp /* pop stack to user regs */
815 jmp push_es /* (DS on top of stack) */
816 fault_popl_es:
817 popl %eax /* get trap number */
818 popl %edx /* get error code */
819 addl $12,%esp /* pop stack to user regs */
820 jmp push_fs /* (ES on top of stack) */
821 fault_popl_fs:
822 popl %eax /* get trap number */
823 popl %edx /* get error code */
824 addl $12,%esp /* pop stack to user regs */
825 jmp push_gs /* (FS on top of stack) */
826 fault_popl_gs:
827 popl %eax /* get trap number */
828 popl %edx /* get error code */
829 addl $12,%esp /* pop stack to user regs */
830 jmp push_none /* (GS on top of stack) */
831
832 push_es:
833 pushl %es /* restore es, */
834 push_fs:
835 pushl %fs /* restore fs, */
836 push_gs:
837 pushl %gs /* restore gs. */
838 push_none:
839 movl %eax,R_TRAPNO(%esp) /* set trap number */
840 movl %edx,R_ERR(%esp) /* set error code */
841 /* now treat as fault from user */
842 /* except that segment registers are */
843 /* already pushed */
844 movl $ EXT(lo_alltraps),%ebx
845 jmp enter_lohandler1
846
847
848 .text
849
850
851 Entry(lo_ret_to_user)
852 jmp *1f
853 1: .long HI_TEXT(hi_ret_to_user)
854
855 Entry(lo_ret_to_kernel)
856 jmp *1f
857 1: .long HI_TEXT(hi_ret_to_kernel)
858
859 Entry(hi_remap_etext)