Move user exception support into userprog.
[pintos-anon] / src / userprog / exception.c
1 #include "exception.h"
2 #include "lib.h"
3 #include "gdt.h"
4 #include "interrupt.h"
5 #include "thread.h"
6
7 static void kill (struct intr_frame *);
8
9 /* Registers handlers for interrupts that can be caused by user
10    programs.
11
12    In a real Unix-like OS, most of these interrupts would be
13    passed along to the user process in the form of signals, but
14    we don't implement signals.  Instead, we'll make them simply
15    kill the user process.
16
17    Page faults are an exception.  Here they are treated the same
18    way as other exceptions, but this will need to change to
19    implement virtual memory.
20
21    Refer to [IA32-v3] section 5.14 for a description of each of
22    these exceptions. */
23 void
24 exception_init (void) 
25 {
26   /* These exceptions can be raised explicitly by a user program,
27      e.g. via the INT, INT3, INTO, and BOUND instructions.  Thus,
28      we set DPL==3, meaning that user programs are allowed to
29      invoke them via these instructions. */
30   intr_register (3, 3, INTR_ON, kill, "#BP Breakpoint Exception");
31   intr_register (4, 3, INTR_ON, kill, "#OF Overflow Exception");
32   intr_register (5, 3, INTR_ON, kill, "#BR BOUND Range Exceeded Exception");
33
34   /* These exceptions have DPL==0, preventing user processes from
35      invoking them via the INT instruction.  They can still be
36      caused indirectly, e.g. #DE can be caused by dividing by
37      0.  */
38   intr_register (0, 0, INTR_ON, kill, "#DE Divide Error");
39   intr_register (1, 0, INTR_ON, kill, "#DB Debug Exception");
40   intr_register (6, 0, INTR_ON, kill, "#UD Invalid Opcode Exception");
41   intr_register (7, 0, INTR_ON, kill, "#NM Device Not Available Exception");
42   intr_register (11, 0, INTR_ON, kill, "#NP Segment Not Present");
43   intr_register (12, 0, INTR_ON, kill, "#SS Stack Fault Exception");
44   intr_register (13, 0, INTR_ON, kill, "#GP General Protection Exception");
45   intr_register (16, 0, INTR_ON, kill, "#MF x87 FPU Floating-Point Error");
46   intr_register (19, 0, INTR_ON, kill, "#XF SIMD Floating-Point Exception");
47
48   /* Most exceptions can be handled with interrupts turned on.
49      We need to disable interrupts for page faults because the
50      fault address is stored in CR2 and needs to be preserved. */
51   intr_register (14, 0, INTR_OFF, kill, "#PF Page-Fault Exception");
52 }
53
54 /* Handler for an exception (probably) caused by a user process. */
55 static void
56 kill (struct intr_frame *f) 
57 {
58   /* This interrupt is one (probably) caused by a user process.
59      For example, the process might have tried to access unmapped
60      virtual memory (a page fault).  For now, we simply kill the
61      user process.  Later, we'll want to handle page faults in
62      the kernel.  Real Unix-like operating systems pass most
63      exceptions back to the process via signals, but we don't
64      implement them. */
65      
66   /* The interrupt frame's code segment value tells us where the
67      exception originated. */
68   switch (f->cs)
69     {
70     case SEL_UCSEG:
71       /* User's code segment, so it's a user exception, as we
72          expected. */
73       printk ("%s: dying due to interrupt %#04x (%s).\n",
74               thread_name (thread_current ()),
75               f->vec_no, intr_name (f->vec_no));
76       intr_dump_frame (f);
77       thread_exit (); 
78
79     case SEL_KCSEG:
80       /* Kernel's code segment, which indicates a kernel bug.
81          Kernel code shouldn't throw exceptions.  (Page faults
82          may cause kernel exceptions--but they shouldn't arrive
83          here.) */
84       intr_dump_frame (f);
85       PANIC ("Kernel bug - unexpected interrupt in kernel"); 
86
87     default:
88       /* Some other code segment?  Shouldn't happen. */
89       printk ("Interrupt %#04x (%s) in unknown segment %04x\n",
90              f->vec_no, intr_name (f->vec_no), f->cs);
91       thread_exit ();
92     }
93 }
94