3 #include <inc/assert.h>
7 #include <kern/console.h>
8 #include <kern/monitor.h>
10 #include <kern/syscall.h>
12 static struct Taskstate ts
;
14 /* Interrupt descriptor table. (Must be built at run time because
15 * shifted function addresses can't be represented in relocation records.)
17 struct Gatedesc idt
[256] = { { 0 } };
18 struct Pseudodesc idt_pd
= {
19 sizeof(idt
) - 1, (uint32_t) idt
23 static const char *trapname(int trapno
)
25 static const char * const excnames
[] = {
28 "Non-Maskable Interrupt",
31 "BOUND Range Exceeded",
33 "Device Not Available",
35 "Coprocessor Segment Overrun",
37 "Segment Not Present",
42 "x87 FPU Floating-Point Error",
45 "SIMD Floating-Point Exception"
48 if (trapno
< sizeof(excnames
)/sizeof(excnames
[0]))
49 return excnames
[trapno
];
50 if (trapno
== T_SYSCALL
)
52 return "(unknown trap)";
59 extern struct Segdesc gdt
[];
61 extern void divzero_entry();
62 extern void debug_entry();
63 extern void nmi_entry();
64 extern void brkpt_entry();
65 extern void oflow_entry();
66 extern void bound_entry();
67 extern void illop_entry();
68 extern void device_entry();
69 extern void dblflt_entry();
70 extern void tss_entry();
71 extern void segnp_entry();
72 extern void stack_entry();
73 extern void gpflt_entry();
74 extern void pgflt_entry();
75 extern void fperr_entry();
76 extern void align_entry();
77 extern void mchk_entry();
78 extern void simderr_entry();
80 // LAB 3: Your code here.
81 SETGATE(idt
[T_DIVIDE
], 1, GD_KT
, divzero_entry
, 0);
82 SETGATE(idt
[T_DEBUG
], 1, GD_KT
, debug_entry
, 0);
83 SETGATE(idt
[T_NMI
], 0, GD_KT
, nmi_entry
, 0);
84 SETGATE(idt
[T_BRKPT
], 1, GD_KT
, brkpt_entry
, 3);
85 SETGATE(idt
[T_OFLOW
], 1, GD_KT
, oflow_entry
, 0);
86 SETGATE(idt
[T_BOUND
], 1, GD_KT
, bound_entry
, 0);
87 SETGATE(idt
[T_ILLOP
], 1, GD_KT
, illop_entry
, 0);
88 SETGATE(idt
[T_DEVICE
], 1, GD_KT
, device_entry
, 0);
89 SETGATE(idt
[T_DBLFLT
], 1, GD_KT
, dblflt_entry
, 0);
90 SETGATE(idt
[T_TSS
], 1, GD_KT
, tss_entry
, 0);
91 SETGATE(idt
[T_SEGNP
], 1, GD_KT
, segnp_entry
, 0);
92 SETGATE(idt
[T_STACK
], 1, GD_KT
, stack_entry
, 0);
93 SETGATE(idt
[T_GPFLT
], 1, GD_KT
, gpflt_entry
, 0);
94 SETGATE(idt
[T_PGFLT
], 1, GD_KT
, pgflt_entry
, 0);
95 SETGATE(idt
[T_FPERR
], 1, GD_KT
, fperr_entry
, 0);
96 SETGATE(idt
[T_ALIGN
], 1, GD_KT
, align_entry
, 0);
97 SETGATE(idt
[T_MCHK
], 1, GD_KT
, mchk_entry
, 0);
98 SETGATE(idt
[T_SIMDERR
], 1, GD_KT
, simderr_entry
, 0);
100 // Setup a TSS so that we get the right stack
101 // when we trap to the kernel.
102 ts
.ts_esp0
= KSTACKTOP
;
105 // Initialize the TSS field of the gdt.
106 gdt
[GD_TSS
>> 3] = SEG16(STS_T32A
, (uint32_t) (&ts
),
107 sizeof(struct Taskstate
), 0);
108 gdt
[GD_TSS
>> 3].sd_s
= 0;
114 asm volatile("lidt idt_pd");
118 print_trapframe(struct Trapframe
*tf
)
120 cprintf("TRAP frame at %p\n", tf
);
121 print_regs(&tf
->tf_regs
);
122 cprintf(" es 0x----%04x\n", tf
->tf_es
);
123 cprintf(" ds 0x----%04x\n", tf
->tf_ds
);
124 cprintf(" trap 0x%08x %s\n", tf
->tf_trapno
, trapname(tf
->tf_trapno
));
125 cprintf(" err 0x%08x\n", tf
->tf_err
);
126 cprintf(" eip 0x%08x\n", tf
->tf_eip
);
127 cprintf(" cs 0x----%04x\n", tf
->tf_cs
);
128 cprintf(" flag 0x%08x\n", tf
->tf_eflags
);
129 cprintf(" esp 0x%08x\n", tf
->tf_esp
);
130 cprintf(" ss 0x----%04x\n", tf
->tf_ss
);
134 print_regs(struct PushRegs
*regs
)
136 cprintf(" edi 0x%08x\n", regs
->reg_edi
);
137 cprintf(" esi 0x%08x\n", regs
->reg_esi
);
138 cprintf(" ebp 0x%08x\n", regs
->reg_ebp
);
139 cprintf(" oesp 0x%08x\n", regs
->reg_oesp
);
140 cprintf(" ebx 0x%08x\n", regs
->reg_ebx
);
141 cprintf(" edx 0x%08x\n", regs
->reg_edx
);
142 cprintf(" ecx 0x%08x\n", regs
->reg_ecx
);
143 cprintf(" eax 0x%08x\n", regs
->reg_eax
);
147 trap_dispatch(struct Trapframe
*tf
)
149 // Handle processor exceptions.
150 // LAB 3: Your code here.
151 switch (tf
->tf_trapno
) {
154 panic("enter breakpoint");
157 page_fault_handler(tf
);
163 // Unexpected trap: The user process or the kernel has a bug.
165 if (tf
->tf_cs
== GD_KT
)
166 panic("unhandled trap in kernel");
174 trap(struct Trapframe
*tf
)
176 cprintf("Incoming TRAP frame at %p\n", tf
);
178 if ((tf
->tf_cs
& 3) == 3) {
179 // Trapped from user mode.
180 // Copy trap frame (which is currently on the stack)
181 // into 'curenv->env_tf', so that running the environment
182 // will restart at the trap point.
184 curenv
->env_tf
= *tf
;
185 // The trapframe on the stack should be ignored from here on.
186 tf
= &curenv
->env_tf
;
189 // Dispatch based on what type of trap occurred
192 // Return to the current environment, which should be runnable.
193 assert(curenv
&& curenv
->env_status
== ENV_RUNNABLE
);
199 page_fault_handler(struct Trapframe
*tf
)
203 // Read processor's CR2 register to find the faulting address
206 // Handle kernel-mode page faults.
208 // LAB 3: Your code here.
210 // We've already handled kernel-mode exceptions, so if we get here,
211 // the page fault happened in user mode.
213 // Call the environment's page fault upcall, if one exists. Set up a
214 // page fault stack frame on the user exception stack (below
215 // UXSTACKTOP), then branch to curenv->env_pgfault_upcall.
217 // The page fault upcall might cause another page fault, in which case
218 // we branch to the page fault upcall recursively, pushing another
219 // page fault stack frame on top of the user exception stack.
221 // The trap handler needs one word of scratch space at the top of the
222 // trap-time stack in order to return. In the non-recursive case, we
223 // don't have to worry about this because the top of the regular user
224 // stack is free. In the recursive case, this means we have to leave
225 // an extra word between the current top of the exception stack and
226 // the new stack frame because the exception stack _is_ the trap-time
229 // If there's no page fault upcall, the environment didn't allocate a
230 // page for its exception stack, or the exception stack overflows,
231 // then destroy the environment that caused the fault.
234 // user_mem_assert() and env_run() are useful here.
235 // To change what the user environment runs, modify 'curenv->env_tf'
236 // (the 'tf' variable points at 'curenv->env_tf').
238 // LAB 4: Your code here.
240 // Destroy the environment that caused the fault.
241 cprintf("[%08x] user fault va %08x ip %08x\n",
242 curenv
->env_id
, fault_va
, tf
->tf_eip
);