]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/idt.s
xnu-1228.9.59.tar.gz
[apple/xnu.git] / osfmk / i386 / idt.s
CommitLineData
1c79356b 1/*
2d21ac55 2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
2d21ac55
A
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.
8f6c56a5 14 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
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>
0c530ab8
A
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 )
1c79356b
A
66
67/*
68 * Interrupt descriptor table and code vectors for it.
69 */
70#define IDT_BASE_ENTRY(vec,seg,type) \
71 .data ;\
2d21ac55 72 .long EXT(vec) - EXT(hi_remap_text) + HIGH_MEM_BASE ; \
0c530ab8
A
73 .word seg ;\
74 .byte 0 ;\
75 .byte type ;\
76 .text
77
78#define IDT_BASE_ENTRY_INT(vec,seg,type) \
79 .data ;\
2d21ac55 80 .long vec - EXT(hi_remap_text) + HIGH_MEM_BASE ; \
0c530ab8
A
81 .word seg ;\
82 .byte 0 ;\
83 .byte type ;\
84 .text
85
86#define IDT_BASE_ENTRY_TG(vec,seg,type) \
87 .data ;\
2d21ac55 88 .long 0 ; \
1c79356b
A
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)
0c530ab8 95#define IDT_ENTRY_INT(vec,type) IDT_BASE_ENTRY_INT(vec,KERNEL_CS,type)
1c79356b
A
96
97/*
98 * No error code. Clear error code and push trap number.
99 */
100#define EXCEPTION(n,name) \
0c530ab8 101 IDT_ENTRY(name,K_INTR_GATE);\
1c79356b
A
102Entry(name) ;\
103 pushl $0 ;\
104 pushl $(n) ;\
0c530ab8
A
105 pusha ;\
106 movl $ EXT(lo_alltraps),%ebx ;\
107 jmp enter_lohandler
1c79356b 108
0c530ab8 109
1c79356b
A
110/*
111 * Interrupt from user. Clear error code and push trap number.
112 */
113#define EXCEP_USR(n,name) \
0c530ab8 114 IDT_ENTRY(name,U_INTR_GATE);\
1c79356b
A
115Entry(name) ;\
116 pushl $0 ;\
117 pushl $(n) ;\
0c530ab8
A
118 pusha ;\
119 movl $ EXT(lo_alltraps),%ebx ;\
120 jmp enter_lohandler
121
1c79356b
A
122
123/*
124 * Special interrupt code.
125 */
126#define EXCEP_SPC(n,name) \
0c530ab8
A
127 IDT_ENTRY(name,K_INTR_GATE)
128
1c79356b
A
129/*
130 * Special interrupt code from user.
131 */
132#define EXCEP_SPC_USR(n,name) \
0c530ab8
A
133 IDT_ENTRY(name,U_INTR_GATE)
134
1c79356b
A
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) \
0c530ab8
A
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)
1c79356b
A
150
151/*
152 * Error code has been pushed. Push trap number.
153 */
154#define EXCEP_ERR(n,name) \
0c530ab8 155 IDT_ENTRY(name,K_INTR_GATE);\
1c79356b
A
156Entry(name) ;\
157 pushl $(n) ;\
0c530ab8
A
158 pusha ;\
159 movl $ EXT(lo_alltraps),%ebx ;\
160 jmp enter_lohandler
1c79356b 161
0c530ab8 162
1c79356b
A
163/*
164 * Interrupt.
165 */
166#define INTERRUPT(n) \
0c530ab8
A
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
1c79356b
A
176
177 .data
0c530ab8
A
178 .align 12
179Entry(master_idt)
180Entry(hi_remap_data)
1c79356b 181 .text
0c530ab8 182Entry(hi_remap_text)
1c79356b
A
183
184EXCEPTION(0x00,t_zero_div)
0c530ab8 185EXCEP_SPC(0x01,hi_debug)
1c79356b
A
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
0c530ab8 195DF_FATAL_TASK(0x08,df_task_start)
1c79356b
A
196#endif
197EXCEPTION(0x09,a_fpu_over)
198EXCEPTION(0x0a,a_inv_tss)
0c530ab8 199EXCEP_SPC(0x0b,hi_segnp)
1c79356b
A
200#if MACH_KDB
201EXCEP_TASK(0x0c,db_task_stk_fault)
202#else
203EXCEP_ERR(0x0c,t_stack_fault)
204#endif
0c530ab8
A
205EXCEP_SPC(0x0d,hi_gen_prot)
206EXCEP_SPC(0x0e,hi_page_fault)
1c79356b
A
207EXCEPTION(0x0f,t_trap_0f)
208EXCEPTION(0x10,t_fpu_err)
209EXCEPTION(0x11,t_trap_11)
0c530ab8
A
210MC_FATAL_TASK(0x12,mc_task_start)
211EXCEPTION(0x13,t_sse_err)
1c79356b
A
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)
2d21ac55 325EXCEP_USR(0x7f, t_dtrace_ret)
1c79356b 326
0c530ab8
A
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
1c79356b
A
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
0c530ab8
A
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:
2d21ac55
A
551 popl %edx /* user return eip */
552 popl %ecx /* pop and toss cs */
0c530ab8 553 andl $(~EFL_IF),(%esp) /* clear intrs enabled, see sti below */
2d21ac55
A
554 popf /* flags - carry denotes failure */
555 popl %ecx /* user return esp */
0c530ab8 556 sti /* interrupts enabled after sysexit */
2d21ac55 557 sysexit
0c530ab8
A
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;
2d21ac55 613 * This is cleared by INT, but not by SYSENTER.
0c530ab8 614 */
2d21ac55 615 pushl $0
0c530ab8
A
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
0c530ab8 630 pushl $(SS_32) /* 32-bit state flavor */
2d21ac55 631enter_lohandler1:
0c530ab8
A
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
2d21ac55 663 jmp *%ebx
0c530ab8
A
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:
2d21ac55 836 pushl $(SS_32) /* 32-bit state flavor */
0c530ab8
A
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)