2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
32 * Mach Operating System
33 * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
34 * All Rights Reserved.
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.
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.
46 * Carnegie Mellon requests users of this software to return to
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
53 * any improvements or extensions that they make and grant Carnegie Mellon
54 * the rights to redistribute these changes.
59 * Hardware trap/fault handler.
63 #include <mach_kgdb.h>
65 #include <mach_ldebug.h>
68 #include <i386/eflags.h>
69 #include <i386/trap.h>
70 #include <i386/pmap.h>
73 #include <mach/exception.h>
74 #include <mach/kern_return.h>
75 #include <mach/vm_param.h>
76 #include <mach/i386/thread_status.h>
78 #include <vm/vm_kern.h>
79 #include <vm/vm_fault.h>
81 #include <kern/kern_types.h>
82 #include <kern/processor.h>
83 #include <kern/thread.h>
84 #include <kern/task.h>
85 #include <kern/sched.h>
86 #include <kern/sched_prim.h>
87 #include <kern/exception.h>
89 #include <kern/misc_protos.h>
92 #include <kgdb/kgdb_defs.h>
93 #endif /* MACH_KGDB */
95 #include <i386/intel_read_fault.h>
98 #include <kgdb/kgdb_defs.h>
99 #endif /* MACH_KGDB */
102 #include <ddb/db_watch.h>
103 #include <ddb/db_run.h>
104 #include <ddb/db_break.h>
105 #include <ddb/db_trap.h>
106 #endif /* MACH_KDB */
110 #include <i386/io_emulate.h>
113 * Forward declarations
115 extern void user_page_fault_continue(
118 extern boolean_t
v86_assist(
120 struct i386_saved_state
*regs
);
122 extern boolean_t
check_io_fault(
123 struct i386_saved_state
*regs
);
125 extern int inst_fetch(
130 thread_syscall_return(
133 register thread_t thr_act
= current_thread();
134 register struct i386_saved_state
*regs
= USER_REGS(thr_act
);
136 thread_exception_return();
142 boolean_t debug_all_traps_with_kdb
= FALSE
;
143 extern struct db_watchpoint
*db_watchpoint_list
;
144 extern boolean_t db_watchpoints_inserted
;
145 extern boolean_t db_breakpoints_inserted
;
148 thread_kdb_return(void)
150 register thread_t thread
= current_thread();
151 register struct i386_saved_state
*regs
= USER_REGS(thread
);
153 if (kdb_trap(regs
->trapno
, regs
->err
, regs
)) {
155 assert(thread
->mutex_count
== 0);
156 #endif /* MACH_LDEBUG */
157 thread_exception_return();
161 boolean_t let_ddb_vm_fault
= FALSE
;
163 #endif /* MACH_KDB */
166 user_page_fault_continue(
169 register thread_t thread
= current_thread();
170 register struct i386_saved_state
*regs
= USER_REGS(thread
);
172 if ((kr
== KERN_SUCCESS
) || (kr
== KERN_ABORTED
)) {
174 if (!db_breakpoints_inserted
) {
175 db_set_breakpoints();
177 if (db_watchpoint_list
&&
178 db_watchpoints_inserted
&&
179 (regs
->err
& T_PF_WRITE
) &&
180 db_find_watchpoint(thread
->map
,
181 (vm_offset_t
)regs
->cr2
,
183 kdb_trap(T_WATCHPOINT
, 0, regs
);
184 #endif /* MACH_KDB */
185 thread_exception_return();
190 if (debug_all_traps_with_kdb
&&
191 kdb_trap(regs
->trapno
, regs
->err
, regs
)) {
193 assert(thread
->mutex_count
== 0);
194 #endif /* MACH_LDEBUG */
195 thread_exception_return();
198 #endif /* MACH_KDB */
200 i386_exception(EXC_BAD_ACCESS
, kr
, regs
->cr2
);
205 * Fault recovery in copyin/copyout routines.
209 uint32_t recover_addr
;
212 extern struct recovery recover_table
[];
213 extern struct recovery recover_table_end
[];
216 * Recovery from Successful fault in copyout does not
217 * return directly - it retries the pte check, since
218 * the 386 ignores write protection in kernel mode.
220 extern struct recovery retry_table
[];
221 extern struct recovery retry_table_end
[];
223 const char * trap_type
[] = {TRAP_NAMES
};
224 int TRAP_TYPES
= sizeof(trap_type
)/sizeof(trap_type
[0]);
228 * Trap from kernel mode. Only page-fault errors are recoverable,
229 * and then only in special circumstances. All other errors are
230 * fatal. Return value indicates if trap was handled.
234 register struct i386_saved_state
*regs
)
237 unsigned int subcode
;
238 int interruptible
= THREAD_UNINT
;
241 kern_return_t result
= KERN_FAILURE
;
242 register thread_t thread
;
246 thread
= current_thread();
250 ast_taken(AST_PREEMPTION
, FALSE
);
261 case T_FLOATING_POINT_ERROR
:
267 * If the current map is a submap of the kernel map,
268 * and the address is within that map, fault on that
269 * map. If the same check is done in vm_fault
270 * (vm_map_lookup), we may deadlock on the kernel map
274 mp_disable_preemption();
276 && kdb_active
[cpu_number()]
277 && !let_ddb_vm_fault
) {
279 * Force kdb to handle this one.
281 mp_enable_preemption();
284 mp_enable_preemption();
285 #endif /* MACH_KDB */
286 subcode
= regs
->cr2
; /* get faulting address */
288 if (subcode
> LINEAR_KERNEL_ADDRESS
) {
290 } else if (thread
== THREAD_NULL
)
297 * Check for watchpoint on kernel static data.
298 * vm_fault would fail in this case
300 if (map
== kernel_map
&&
301 db_watchpoint_list
&&
302 db_watchpoints_inserted
&&
303 (code
& T_PF_WRITE
) &&
304 (vm_offset_t
)subcode
< vm_last_phys
&&
305 ((*(pte
= pmap_pte(kernel_pmap
, (vm_offset_t
)subcode
))) &
306 INTEL_PTE_WRITE
) == 0) {
307 *pte
= *pte
| INTEL_PTE_VALID
| INTEL_PTE_WRITE
; /* XXX need invltlb here? */
308 result
= KERN_SUCCESS
;
310 #endif /* MACH_KDB */
313 * Since the 386 ignores write protection in
314 * kernel mode, always try for write permission
315 * first. If that fails and the fault was a
316 * read fault, retry with read permission.
318 if (map
== kernel_map
) {
319 register struct recovery
*rp
;
321 interruptible
= THREAD_UNINT
;
322 for (rp
= recover_table
; rp
< recover_table_end
; rp
++) {
323 if (regs
->eip
== rp
->fault_addr
) {
324 interruptible
= THREAD_ABORTSAFE
;
329 result
= vm_fault(map
,
330 trunc_page((vm_offset_t
)subcode
),
331 VM_PROT_READ
|VM_PROT_WRITE
,
333 (map
== kernel_map
) ? interruptible
: THREAD_ABORTSAFE
, NULL
, 0);
336 if (result
== KERN_SUCCESS
) {
337 /* Look for watchpoints */
338 if (db_watchpoint_list
&&
339 db_watchpoints_inserted
&&
340 (code
& T_PF_WRITE
) &&
341 db_find_watchpoint(map
,
342 (vm_offset_t
)subcode
, regs
))
343 kdb_trap(T_WATCHPOINT
, 0, regs
);
346 #endif /* MACH_KDB */
347 if ((code
& T_PF_WRITE
) == 0 &&
348 result
== KERN_PROTECTION_FAILURE
)
351 * Must expand vm_fault by hand,
352 * so that we can ask for read-only access
353 * but enter a (kernel)writable mapping.
355 result
= intel_read_fault(map
,
356 trunc_page((vm_offset_t
)subcode
));
359 if (result
== KERN_SUCCESS
) {
361 * Certain faults require that we back up
364 register struct recovery
*rp
;
366 for (rp
= retry_table
; rp
< retry_table_end
; rp
++) {
367 if (regs
->eip
== rp
->fault_addr
) {
368 regs
->eip
= rp
->recover_addr
;
377 case T_GENERAL_PROTECTION
:
380 * If there is a failure recovery address
381 * for this fault, go there.
384 register struct recovery
*rp
;
386 for (rp
= recover_table
;
387 rp
< recover_table_end
;
389 if (regs
->eip
== rp
->fault_addr
) {
390 regs
->eip
= rp
->recover_addr
;
397 * Check thread recovery address also -
398 * v86 assist uses it.
400 if (thread
->recover
) {
401 regs
->eip
= thread
->recover
;
407 * Unanticipated page-fault errors in kernel
410 /* fall through... */
414 * Exception 15 is reserved but some chips may generate it
415 * spuriously. Seen at startup on AMD Athlon-64.
418 kprintf("kernel_trap() ignoring spurious trap 15\n");
423 * ...and return failure, so that locore can call into
427 kdp_i386_trap(type
, regs
, result
, regs
->cr2
);
435 * Called if both kernel_trap() and kdb_trap() fail.
439 register struct i386_saved_state
*regs
)
447 printf("trap type %d, code = %x, pc = %x\n",
448 type
, code
, regs
->eip
);
454 * Trap from user mode.
458 register struct i386_saved_state
*regs
)
462 unsigned int subcode
;
466 kern_return_t result
;
467 thread_t thread
= current_thread();
468 boolean_t kernel_act
= FALSE
;
470 if (regs
->efl
& EFL_VM
) {
472 * If hardware assist can handle exception,
473 * continue execution.
475 if (v86_assist(thread
, regs
))
487 exc
= EXC_ARITHMETIC
;
492 exc
= EXC_BREAKPOINT
;
497 exc
= EXC_BREAKPOINT
;
502 exc
= EXC_ARITHMETIC
;
503 code
= EXC_I386_INTO
;
506 case T_OUT_OF_BOUNDS
:
508 code
= EXC_I386_BOUND
;
511 case T_INVALID_OPCODE
:
512 exc
= EXC_BAD_INSTRUCTION
;
513 code
= EXC_I386_INVOP
;
525 case 10: /* invalid TSS == iret with NT flag set */
526 exc
= EXC_BAD_INSTRUCTION
;
527 code
= EXC_I386_INVTSSFLT
;
528 subcode
= regs
->err
& 0xffff;
531 case T_SEGMENT_NOT_PRESENT
:
532 exc
= EXC_BAD_INSTRUCTION
;
533 code
= EXC_I386_SEGNPFLT
;
534 subcode
= regs
->err
& 0xffff;
538 exc
= EXC_BAD_INSTRUCTION
;
539 code
= EXC_I386_STKFLT
;
540 subcode
= regs
->err
& 0xffff;
543 case T_GENERAL_PROTECTION
:
544 if (!(regs
->efl
& EFL_VM
)) {
545 if (check_io_fault(regs
))
548 exc
= EXC_BAD_INSTRUCTION
;
549 code
= EXC_I386_GPFLT
;
550 subcode
= regs
->err
& 0xffff;
555 prot
= VM_PROT_READ
|VM_PROT_WRITE
;
556 if (kernel_act
== FALSE
) {
557 if (!(regs
->err
& T_PF_WRITE
))
559 (void) user_page_fault_continue(vm_fault(thread
->map
,
560 trunc_page((vm_offset_t
)subcode
),
563 THREAD_ABORTSAFE
, NULL
, 0));
567 if (subcode
> LINEAR_KERNEL_ADDRESS
) {
570 result
= vm_fault(thread
->map
,
571 trunc_page((vm_offset_t
)subcode
),
574 (map
== kernel_map
) ? THREAD_UNINT
: THREAD_ABORTSAFE
, NULL
, 0);
575 if ((result
!= KERN_SUCCESS
) && (result
!= KERN_ABORTED
)) {
577 * Must expand vm_fault by hand,
578 * so that we can ask for read-only access
579 * but enter a (kernel) writable mapping.
581 result
= intel_read_fault(thread
->map
,
582 trunc_page((vm_offset_t
)subcode
));
584 user_page_fault_continue(result
);
589 case T_FLOATING_POINT_ERROR
:
595 Debugger("Unanticipated user trap");
597 #endif /* MACH_KGDB */
599 if (kdb_trap(type
, regs
->err
, regs
))
601 #endif /* MACH_KDB */
602 printf("user trap type %d, code = %x, pc = %x\n",
603 type
, regs
->err
, regs
->eip
);
609 if (debug_all_traps_with_kdb
&&
610 kdb_trap(type
, regs
->err
, regs
))
612 #endif /* MACH_KDB */
614 i386_exception(exc
, code
, subcode
);
619 * V86 mode assist for interrupt handling.
621 boolean_t v86_assist_on
= TRUE
;
622 boolean_t v86_unsafe_ok
= FALSE
;
623 boolean_t v86_do_sti_cli
= TRUE
;
624 boolean_t v86_do_sti_immediate
= FALSE
;
626 #define V86_IRET_PENDING 0x4000
634 register struct i386_saved_state
*regs
)
636 register struct v86_assist_state
*v86
= &thread
->machine
.pcb
->ims
.v86s
;
639 * Build an 8086 address. Use only when off is known to be 16 bits.
641 #define Addr8086(seg,off) ((((seg) & 0xffff) << 4) + (off))
643 #define EFL_V86_SAFE ( EFL_OF | EFL_DF | EFL_TF \
644 | EFL_SF | EFL_ZF | EFL_AF \
654 unsigned short flags
;
657 struct iret_32 iret_32
;
658 struct iret_16 iret_16
;
670 * If delayed STI pending, enable interrupts.
671 * Turn off tracing if on only to delay STI.
673 if (v86
->flags
& V86_IF_PENDING
) {
674 v86
->flags
&= ~V86_IF_PENDING
;
675 v86
->flags
|= EFL_IF
;
676 if ((v86
->flags
& EFL_TF
) == 0)
677 regs
->efl
&= ~EFL_TF
;
680 if (regs
->trapno
== T_DEBUG
) {
682 if (v86
->flags
& EFL_TF
) {
684 * Trace flag was also set - it has priority
686 return FALSE
; /* handle as single-step */
689 * Fall through to check for interrupts.
692 else if (regs
->trapno
== T_GENERAL_PROTECTION
) {
694 * General protection error - must be an 8086 instruction
698 boolean_t addr_32
= FALSE
;
699 boolean_t data_32
= FALSE
;
703 * Set up error handler for bad instruction/data
706 __asm__("movl $(addr_error), %0" : : "m" (thread
->recover
));
710 unsigned char opcode
;
714 return FALSE
; /* GP fault: IP out of range */
717 opcode
= *(unsigned char *)Addr8086(regs
->cs
,eip
);
720 case 0xf0: /* lock */
721 case 0xf2: /* repne */
722 case 0xf3: /* repe */
732 case 0x66: /* data size */
736 case 0x67: /* address size */
740 case 0xe4: /* inb imm */
741 case 0xe5: /* inw imm */
742 case 0xe6: /* outb imm */
743 case 0xe7: /* outw imm */
744 io_port
= *(unsigned char *)Addr8086(regs
->cs
, eip
);
748 case 0xec: /* inb dx */
749 case 0xed: /* inw dx */
750 case 0xee: /* outb dx */
751 case 0xef: /* outw dx */
752 case 0x6c: /* insb */
753 case 0x6d: /* insw */
754 case 0x6e: /* outsb */
755 case 0x6f: /* outsw */
756 io_port
= regs
->edx
& 0xffff;
760 opcode
|= 0x6600; /* word IO */
762 switch (emulate_io(regs
, opcode
, io_port
)) {
764 /* instruction executed */
767 /* port mapped, retry instruction */
771 /* port not mapped */
778 if (!v86_do_sti_cli
) {
783 v86
->flags
&= ~EFL_IF
;
784 /* disable simulated interrupts */
789 if (!v86_do_sti_cli
) {
794 if ((v86
->flags
& EFL_IF
) == 0) {
795 if (v86_do_sti_immediate
) {
796 v86
->flags
|= EFL_IF
;
798 v86
->flags
|= V86_IF_PENDING
;
801 /* single step to set IF next inst. */
806 case 0x9c: /* pushf */
813 if ((v86
->flags
& EFL_IF
) == 0)
816 if ((v86
->flags
& EFL_TF
) == 0)
818 else flags
|= EFL_TF
;
823 else if (sp
> 0xffff)
825 size
= (data_32
) ? 4 : 2;
829 if (copyout((char *)&flags
,
830 (user_addr_t
)Addr8086(regs
->ss
,sp
),
836 regs
->uesp
= (regs
->uesp
& 0xffff0000) | sp
;
840 case 0x9d: /* popf */
848 else if (sp
> 0xffff)
852 if (sp
> 0xffff - sizeof(int))
854 nflags
= *(int *)Addr8086(regs
->ss
,sp
);
858 if (sp
> 0xffff - sizeof(short))
860 nflags
= *(unsigned short *)
861 Addr8086(regs
->ss
,sp
);
867 regs
->uesp
= (regs
->uesp
& 0xffff0000) | sp
;
869 if (v86
->flags
& V86_IRET_PENDING
) {
870 v86
->flags
= nflags
& (EFL_TF
| EFL_IF
);
871 v86
->flags
|= V86_IRET_PENDING
;
873 v86
->flags
= nflags
& (EFL_TF
| EFL_IF
);
875 regs
->efl
= (regs
->efl
& ~EFL_V86_SAFE
)
876 | (nflags
& EFL_V86_SAFE
);
879 case 0xcf: /* iret */
883 union iret_struct iret_struct
;
885 v86
->flags
&= ~V86_IRET_PENDING
;
889 else if (sp
> 0xffff)
893 if (sp
> 0xffff - sizeof(struct iret_32
))
895 iret_struct
.iret_32
=
896 *(struct iret_32
*) Addr8086(regs
->ss
,sp
);
897 sp
+= sizeof(struct iret_32
);
900 if (sp
> 0xffff - sizeof(struct iret_16
))
902 iret_struct
.iret_16
=
903 *(struct iret_16
*) Addr8086(regs
->ss
,sp
);
904 sp
+= sizeof(struct iret_16
);
909 regs
->uesp
= (regs
->uesp
& 0xffff0000) | sp
;
912 eip
= iret_struct
.iret_32
.eip
;
913 regs
->cs
= iret_struct
.iret_32
.cs
& 0xffff;
914 nflags
= iret_struct
.iret_32
.eflags
;
917 eip
= iret_struct
.iret_16
.ip
;
918 regs
->cs
= iret_struct
.iret_16
.cs
;
919 nflags
= iret_struct
.iret_16
.flags
;
922 v86
->flags
= nflags
& (EFL_TF
| EFL_IF
);
923 regs
->efl
= (regs
->efl
& ~EFL_V86_SAFE
)
924 | (nflags
& EFL_V86_SAFE
);
929 * Instruction not emulated here.
934 break; /* exit from 'while TRUE' */
936 regs
->eip
= (regs
->eip
& 0xffff0000) | eip
;
940 * Not a trap we handle.
946 if ((v86
->flags
& EFL_IF
) && ((v86
->flags
& V86_IRET_PENDING
)==0)) {
948 struct v86_interrupt_table
*int_table
;
953 int_table
= (struct v86_interrupt_table
*) v86
->int_table
;
954 int_count
= v86
->int_count
;
957 for (i
= 0; i
< int_count
; int_table
++, i
++) {
958 if (!int_table
->mask
&& int_table
->count
> 0) {
960 vec
= int_table
->vec
;
966 * Take this interrupt
969 struct iret_16 iret_16
;
970 struct int_vec int_vec
;
972 sp
= regs
->uesp
& 0xffff;
973 if (sp
< sizeof(struct iret_16
))
975 sp
-= sizeof(struct iret_16
);
976 iret_16
.ip
= regs
->eip
;
977 iret_16
.cs
= regs
->cs
;
978 iret_16
.flags
= regs
->efl
& 0xFFFF;
979 if ((v86
->flags
& EFL_TF
) == 0)
980 iret_16
.flags
&= ~EFL_TF
;
981 else iret_16
.flags
|= EFL_TF
;
983 (void) memcpy((char *) &int_vec
,
984 (char *) (sizeof(struct int_vec
) * vec
),
985 sizeof (struct int_vec
));
986 if (copyout((char *)&iret_16
,
987 (user_addr_t
)Addr8086(regs
->ss
,sp
),
988 sizeof(struct iret_16
)))
990 regs
->uesp
= (regs
->uesp
& 0xFFFF0000) | (sp
& 0xffff);
991 regs
->eip
= int_vec
.ip
;
992 regs
->cs
= int_vec
.cs
;
993 regs
->efl
&= ~EFL_TF
;
994 v86
->flags
&= ~(EFL_IF
| EFL_TF
);
995 v86
->flags
|= V86_IRET_PENDING
;
1003 * On address error, report a page fault.
1004 * XXX report GP fault - we don`t save
1005 * the faulting address.
1008 __asm__("addr_error:;");
1009 thread
->recover
= 0;
1013 * On stack address error, return stack fault (12).
1016 thread
->recover
= 0;
1017 regs
->trapno
= T_STACK_FAULT
;
1022 * Handle AST traps for i386.
1023 * Check for delayed floating-point exception from
1027 extern void log_thread_action (thread_t
, char *);
1030 i386_astintr(int preemption
)
1032 ast_t
*my_ast
, mask
= AST_ALL
;
1035 s
= splsched(); /* block interrupts to check reasons */
1036 mp_disable_preemption();
1037 my_ast
= ast_pending();
1038 if (*my_ast
& AST_I386_FP
) {
1040 * AST was for delayed floating-point exception -
1041 * FP interrupt occurred while in kernel.
1042 * Turn off this AST reason and handle the FPU error.
1045 ast_off(AST_I386_FP
);
1046 mp_enable_preemption();
1053 * Not an FPU trap. Handle the AST.
1054 * Interrupts are still blocked.
1059 mask
= AST_PREEMPTION
;
1060 mp_enable_preemption();
1062 mp_enable_preemption();
1065 mp_enable_preemption();
1074 * Handle exceptions for i386.
1076 * If we are an AT bus machine, we must turn off the AST for a
1077 * delayed floating-point exception.
1079 * If we are providing floating-point emulation, we may have
1080 * to retrieve the real register values from the floating point
1090 exception_data_type_t codes
[EXCEPTION_CODE_MAX
];
1093 * Turn off delayed FPU error handling.
1096 mp_disable_preemption();
1097 ast_off(AST_I386_FP
);
1098 mp_enable_preemption();
1101 codes
[0] = code
; /* new exception interface */
1103 exception_triage(exc
, codes
, 2);
1109 struct i386_saved_state
*regs
)
1111 int eip
, opcode
, io_port
;
1112 boolean_t data_16
= FALSE
;
1115 * Get the instruction.
1120 opcode
= inst_fetch(eip
, regs
->cs
);
1123 case 0x66: /* data-size prefix */
1127 case 0xf3: /* rep prefix */
1136 case 0xE4: /* inb imm */
1137 case 0xE5: /* inl imm */
1138 case 0xE6: /* outb imm */
1139 case 0xE7: /* outl imm */
1140 /* port is immediate byte */
1141 io_port
= inst_fetch(eip
, regs
->cs
);
1145 case 0xEC: /* inb dx */
1146 case 0xED: /* inl dx */
1147 case 0xEE: /* outb dx */
1148 case 0xEF: /* outl dx */
1149 case 0x6C: /* insb */
1150 case 0x6D: /* insl */
1151 case 0x6E: /* outsb */
1152 case 0x6F: /* outsl */
1153 /* port is in DX register */
1154 io_port
= regs
->edx
& 0xFFFF;
1164 opcode
|= 0x6600; /* word IO */
1166 switch (emulate_io(regs
, opcode
, io_port
)) {
1168 /* instruction executed */
1173 /* port mapped, retry instruction */
1177 /* port not mapped */
1184 kernel_preempt_check (void)
1188 mp_disable_preemption();
1189 myast
= ast_pending();
1190 if ((*myast
& AST_URGENT
) &&
1191 get_interrupt_level() == 1
1193 mp_enable_preemption_no_check();
1194 __asm__
volatile (" int $0xff");
1196 mp_enable_preemption_no_check();
1202 extern void db_i386_state(struct i386_saved_state
*regs
);
1204 #include <ddb/db_output.h>
1208 struct i386_saved_state
*regs
)
1210 db_printf("eip %8x\n", regs
->eip
);
1211 db_printf("trap %8x\n", regs
->trapno
);
1212 db_printf("err %8x\n", regs
->err
);
1213 db_printf("efl %8x\n", regs
->efl
);
1214 db_printf("ebp %8x\n", regs
->ebp
);
1215 db_printf("esp %8x\n", regs
->esp
);
1216 db_printf("uesp %8x\n", regs
->uesp
);
1217 db_printf("cs %8x\n", regs
->cs
& 0xff);
1218 db_printf("ds %8x\n", regs
->ds
& 0xff);
1219 db_printf("es %8x\n", regs
->es
& 0xff);
1220 db_printf("fs %8x\n", regs
->fs
& 0xff);
1221 db_printf("gs %8x\n", regs
->gs
& 0xff);
1222 db_printf("ss %8x\n", regs
->ss
& 0xff);
1223 db_printf("eax %8x\n", regs
->eax
);
1224 db_printf("ebx %8x\n", regs
->ebx
);
1225 db_printf("ecx %8x\n", regs
->ecx
);
1226 db_printf("edx %8x\n", regs
->edx
);
1227 db_printf("esi %8x\n", regs
->esi
);
1228 db_printf("edi %8x\n", regs
->edi
);
1231 #endif /* MACH_KDB */