8 static void kill (struct intr_frame *);
9 static void page_fault (struct intr_frame *);
11 /* Registers handlers for interrupts that can be caused by user
14 In a real Unix-like OS, most of these interrupts would be
15 passed along to the user process in the form of signals, but
16 we don't implement signals. Instead, we'll make them simply
17 kill the user process.
19 Page faults are an exception. Here they are treated the same
20 way as other exceptions, but this will need to change to
21 implement virtual memory.
23 Refer to [IA32-v3] section 5.14 for a description of each of
28 /* These exceptions can be raised explicitly by a user program,
29 e.g. via the INT, INT3, INTO, and BOUND instructions. Thus,
30 we set DPL==3, meaning that user programs are allowed to
31 invoke them via these instructions. */
32 intr_register (3, 3, INTR_ON, kill, "#BP Breakpoint Exception");
33 intr_register (4, 3, INTR_ON, kill, "#OF Overflow Exception");
34 intr_register (5, 3, INTR_ON, kill, "#BR BOUND Range Exceeded Exception");
36 /* These exceptions have DPL==0, preventing user processes from
37 invoking them via the INT instruction. They can still be
38 caused indirectly, e.g. #DE can be caused by dividing by
40 intr_register (0, 0, INTR_ON, kill, "#DE Divide Error");
41 intr_register (1, 0, INTR_ON, kill, "#DB Debug Exception");
42 intr_register (6, 0, INTR_ON, kill, "#UD Invalid Opcode Exception");
43 intr_register (7, 0, INTR_ON, kill, "#NM Device Not Available Exception");
44 intr_register (11, 0, INTR_ON, kill, "#NP Segment Not Present");
45 intr_register (12, 0, INTR_ON, kill, "#SS Stack Fault Exception");
46 intr_register (13, 0, INTR_ON, kill, "#GP General Protection Exception");
47 intr_register (16, 0, INTR_ON, kill, "#MF x87 FPU Floating-Point Error");
48 intr_register (19, 0, INTR_ON, kill, "#XF SIMD Floating-Point Exception");
50 /* Most exceptions can be handled with interrupts turned on.
51 We need to disable interrupts for page faults because the
52 fault address is stored in CR2 and needs to be preserved. */
53 intr_register (14, 0, INTR_OFF, page_fault, "#PF Page-Fault Exception");
56 /* Handler for an exception (probably) caused by a user process. */
58 kill (struct intr_frame *f)
60 /* This interrupt is one (probably) caused by a user process.
61 For example, the process might have tried to access unmapped
62 virtual memory (a page fault). For now, we simply kill the
63 user process. Later, we'll want to handle page faults in
64 the kernel. Real Unix-like operating systems pass most
65 exceptions back to the process via signals, but we don't
68 /* The interrupt frame's code segment value tells us where the
69 exception originated. */
73 /* User's code segment, so it's a user exception, as we
74 expected. Kill the user process. */
75 printk ("%s: dying due to interrupt %#04x (%s).\n",
76 thread_name (thread_current ()),
77 f->vec_no, intr_name (f->vec_no));
82 /* Kernel's code segment, which indicates a kernel bug.
83 Kernel code shouldn't throw exceptions. (Page faults
84 may cause kernel exceptions--but they shouldn't arrive
85 here.) Panic the kernel to make the point. */
87 PANIC ("Kernel bug - unexpected interrupt in kernel");
90 /* Some other code segment? Shouldn't happen. Panic the
92 printk ("Interrupt %#04x (%s) in unknown segment %04x\n",
93 f->vec_no, intr_name (f->vec_no), f->cs);
98 /* Page fault error code bits that describe the cause of the exception. */
99 #define PF_P 0x1 /* 0: not-present page. 1: access rights violation. */
100 #define PF_W 0x2 /* 0: read, 1: write. */
101 #define PF_U 0x4 /* 0: kernel, 1: user process. */
103 /* Page fault handler. This is a skeleton that must be filled in
104 to implement virtual memory.
106 At entry, the address that faulted is in CR2 (Control Register
107 2) and information about the fault, formatted as described in
108 the PF_* macros above, is in F's error_code member. The
109 example code here shows how to parse that information. You
110 can find more information about both of these in the
111 description of "Interrupt 14--Page Fault Exception (#PF)" in
112 [IA32-v3] section 5.14, which is pages 5-46 to 5-49. */
114 page_fault (struct intr_frame *f)
116 bool not_present, write, user;
119 /* Determine cause. */
120 not_present = (f->error_code & PF_P) == 0;
121 write = (f->error_code & PF_W) != 0;
122 user = (f->error_code & PF_U) != 0;
124 /* Obtain faulting address.
126 (The faulting address is not necesarily the address of the
127 instruction that caused the fault--that's in F's eip
128 member. Rather, it's the linear address that was accessed
129 to cause the fault, which is probably an address of data,
131 asm ("movl %%cr2, %0" : "=r" (fault_addr));
133 /* To implement virtual memory, delete the rest of the function
134 body, and replace it with code that brings in the page to
135 which fault_addr refers. */
136 printk ("Page fault on address %08"PRIx32": %s %s page in %s context.\n",
138 not_present ? "not present" : "rights violation",
139 write ? "writing" : "reading",
140 user ? "user" : "kernel");