1 /* This file contains a simple exception handler. Exceptions in user
2 * processes are converted to signals. Exceptions in a kernel task cause
6 #include "kernel/kernel.h"
11 #include "kernel/proc.h"
12 #include "kernel/proto.h"
14 extern int catch_pagefaults
= 0;
16 PRIVATE
void pagefault( struct proc
*pr
,
17 struct exception_frame
* frame
,
28 pagefaultcr2
= read_cr2();
31 printf("kernel: pagefault in pr %d, addr 0x%lx, his cr3 0x%lx, actual cr3 0x%lx\n",
32 pr
->p_endpoint
, pagefaultcr2
, pr
->p_seg
.p_cr3
, read_cr3());
36 assert(pr
->p_seg
.p_cr3
== read_cr3());
39 in_physcopy
= (frame
->eip
> (vir_bytes
) phys_copy
) &&
40 (frame
->eip
< (vir_bytes
) phys_copy_fault
);
42 if((is_nested
|| iskernelp(pr
)) &&
43 catch_pagefaults
&& in_physcopy
) {
45 printf("pf caught! addr 0x%lx\n", pagefaultcr2
);
48 frame
->eip
= (reg_t
) phys_copy_fault_in_kernel
;
51 pr
->p_reg
.pc
= (reg_t
) phys_copy_fault
;
52 pr
->p_reg
.retreg
= pagefaultcr2
;
59 panic("pagefault in kernel at pc 0x%lx address 0x%lx", frame
->eip
, pagefaultcr2
);
62 /* System processes that don't have their own page table can't
63 * have page faults. VM does have its own page table but also
64 * can't have page faults (because VM has to handle them).
66 if((pr
->p_endpoint
<= INIT_PROC_NR
&&
67 !(pr
->p_misc_flags
& MF_FULLVM
)) || pr
->p_endpoint
== VM_PROC_NR
) {
68 /* Page fault we can't / don't want to
71 printf("pagefault for process %d ('%s'), pc = 0x%x, addr = 0x%x, flags = 0x%x, is_nested %d\n",
72 pr
->p_endpoint
, pr
->p_name
, pr
->p_reg
.pc
,
73 pagefaultcr2
, frame
->errcode
, is_nested
);
75 printf("pc of pagefault: 0x%lx\n", frame
->eip
);
76 panic("page fault in system process: %d", pr
->p_endpoint
);
81 /* Don't schedule this process until pagefault is handled. */
82 assert(pr
->p_seg
.p_cr3
== read_cr3());
83 assert(!RTS_ISSET(pr
, RTS_PAGEFAULT
));
84 RTS_SET(pr
, RTS_PAGEFAULT
);
86 /* tell Vm about the pagefault */
87 m_pagefault
.m_source
= pr
->p_endpoint
;
88 m_pagefault
.m_type
= VM_PAGEFAULT
;
89 m_pagefault
.VPF_ADDR
= pagefaultcr2
;
90 m_pagefault
.VPF_FLAGS
= frame
->errcode
;
92 if ((err
= mini_send(pr
, VM_PROC_NR
,
93 &m_pagefault
, FROM_KERNEL
))) {
94 panic("WARNING: pagefault: mini_send returned %d\n", err
);
100 /*===========================================================================*
102 *===========================================================================*/
103 PUBLIC
void exception_handler(int is_nested
, struct exception_frame
* frame
)
105 /* An exception or unexpected interrupt has occurred. */
112 static struct ex_s ex_data
[] = {
113 { "Divide error", SIGFPE
, 86 },
114 { "Debug exception", SIGTRAP
, 86 },
115 { "Nonmaskable interrupt", SIGBUS
, 86 },
116 { "Breakpoint", SIGEMT
, 86 },
117 { "Overflow", SIGFPE
, 86 },
118 { "Bounds check", SIGFPE
, 186 },
119 { "Invalid opcode", SIGILL
, 186 },
120 { "Coprocessor not available", SIGFPE
, 186 },
121 { "Double fault", SIGBUS
, 286 },
122 { "Coprocessor segment overrun", SIGSEGV
, 286 },
123 { "Invalid TSS", SIGSEGV
, 286 },
124 { "Segment not present", SIGSEGV
, 286 },
125 { "Stack exception", SIGSEGV
, 286 }, /* STACK_FAULT already used */
126 { "General protection", SIGSEGV
, 286 },
127 { "Page fault", SIGSEGV
, 386 }, /* not close */
128 { NULL
, SIGILL
, 0 }, /* probably software trap */
129 { "Coprocessor error", SIGFPE
, 386 },
130 { "Alignment check", SIGBUS
, 386 },
131 { "Machine check", SIGBUS
, 386 },
132 { "SIMD exception", SIGFPE
, 386 },
134 register struct ex_s
*ep
;
135 struct proc
*saved_proc
;
137 /* Save proc_ptr, because it may be changed by debug statements. */
138 saved_proc
= proc_ptr
;
140 ep
= &ex_data
[frame
->vector
];
142 if (frame
->vector
== 2) { /* spurious NMI on some machines */
143 printf("got spurious NMI\n");
148 * handle special cases for nested problems as they might be tricky or filter
149 * them out quickly if the traps are not nested
153 * if a problem occured while copying a message from userspace because
154 * of a wrong pointer supplied by userland, handle it the only way we
157 if (((void*)frame
->eip
>= (void*)copy_msg_to_user
&&
158 (void*)frame
->eip
<= (void*)__copy_msg_to_user_end
) ||
159 ((void*)frame
->eip
>= (void*)copy_msg_from_user
&&
160 (void*)frame
->eip
<= (void*)__copy_msg_from_user_end
)) {
161 switch(frame
->vector
) {
162 /* these error are expected */
163 case PAGE_FAULT_VECTOR
:
164 case PROTECTION_VECTOR
:
165 frame
->eip
= (reg_t
) __user_copy_msg_pointer_failure
;
168 panic("Copy involving a user pointer failed unexpectedly!");
173 if(frame
->vector
== PAGE_FAULT_VECTOR
) {
174 pagefault(saved_proc
, frame
, is_nested
);
178 /* If an exception occurs while running a process, the is_nested variable
179 * will be zero. Exceptions in interrupt handlers or system traps will make
180 * is_nested non-zero.
182 if (is_nested
== 0 && ! iskernelp(saved_proc
)) {
187 "vec_nr= %d, trap_errno= 0x%lx, eip= 0x%lx, cs= 0x%x, eflags= 0x%lx\n",
188 frame
->vector
, (unsigned long)frame
->errcode
,
189 (unsigned long)frame
->eip
, frame
->cs
,
190 (unsigned long)frame
->eflags
);
191 printseg("cs: ", 1, saved_proc
, frame
->cs
);
192 printseg("ds: ", 0, saved_proc
, saved_proc
->p_reg
.ds
);
193 if(saved_proc
->p_reg
.ds
!= saved_proc
->p_reg
.ss
) {
194 printseg("ss: ", 0, saved_proc
, saved_proc
->p_reg
.ss
);
196 proc_stacktrace(saved_proc
);
200 cause_sig(proc_nr(saved_proc
), ep
->signum
);
204 /* Exception in system code. This is not supposed to happen. */
205 if (ep
->msg
== NULL
|| machine
.processor
< ep
->minprocessor
)
206 printf("\nIntel-reserved exception %d\n", frame
->vector
);
208 printf("\n%s\n", ep
->msg
);
209 printf("is_nested = %d ", is_nested
);
211 printf("vec_nr= %d, trap_errno= 0x%x, eip= 0x%x, "
212 "cs= 0x%x, eflags= 0x%x trap_esp 0x%08x\n",
213 frame
->vector
, frame
->errcode
, frame
->eip
,
214 frame
->cs
, frame
->eflags
, frame
);
215 printf("KERNEL registers :\n");
217 "\t%%eax 0x%08x %%ebx 0x%08x %%ecx 0x%08x %%edx 0x%08x\n"
218 "\t%%esp 0x%08x %%ebp 0x%08x %%esi 0x%08x %%edi 0x%08x\n",
219 ((u32_t
*)frame
)[-1],
220 ((u32_t
*)frame
)[-2],
221 ((u32_t
*)frame
)[-3],
222 ((u32_t
*)frame
)[-4],
223 ((u32_t
*)frame
)[-5],
224 ((u32_t
*)frame
)[-6],
225 ((u32_t
*)frame
)[-7],
228 printseg("ker cs: ", 1, NULL
, frame
->cs
);
229 printseg("ker ds: ", 0, NULL
, DS_SELECTOR
);
230 /* TODO should we enable this only when compiled for some debug mode? */
232 printf("scheduled was: process %d (%s), ", proc_nr(saved_proc
), saved_proc
->p_name
);
233 printf("pc = %u:0x%x\n", (unsigned) saved_proc
->p_reg
.cs
,
234 (unsigned) saved_proc
->p_reg
.pc
);
235 proc_stacktrace(saved_proc
);
237 panic("Unhandled kernel exception");
240 /* in an early stage of boot process we don't have processes yet */
241 panic("exception in kernel while booting");
245 /*===========================================================================*
247 *===========================================================================*/
248 PUBLIC
void proc_stacktrace(struct proc
*whichproc
)
250 reg_t v_bp
, v_pc
, v_hbp
;
253 v_bp
= whichproc
->p_reg
.fp
;
255 iskernel
= iskernelp(whichproc
);
257 printf("%-8.8s %6d 0x%lx ",
258 whichproc
->p_name
, whichproc
->p_endpoint
, whichproc
->p_reg
.pc
);
262 #define PRCOPY(pr, pv, v, n) \
263 (iskernel ? (memcpy((char *) v, (char *) pv, n), OK) : \
264 data_copy(pr->p_endpoint, pv, KERNEL, (vir_bytes) (v), n))
266 if(PRCOPY(whichproc
, v_bp
, &v_hbp
, sizeof(v_hbp
)) != OK
) {
267 printf("(v_bp 0x%lx ?)", v_bp
);
270 if(PRCOPY(whichproc
, v_bp
+ sizeof(v_pc
), &v_pc
, sizeof(v_pc
)) != OK
) {
271 printf("(v_pc 0x%lx ?)", v_bp
+ sizeof(v_pc
));
274 printf("0x%lx ", (unsigned long) v_pc
);
275 if(v_hbp
!= 0 && v_hbp
<= v_bp
) {
276 printf("(hbp %lx ?)", v_hbp
);