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