This source file includes following definitions.
- do_page_fault
1
2
3
4
5
6
7 #include <linux/config.h>
8 #include <linux/signal.h>
9 #include <linux/sched.h>
10 #include <linux/head.h>
11 #include <linux/kernel.h>
12 #include <linux/errno.h>
13 #include <linux/string.h>
14 #include <linux/types.h>
15 #include <linux/ptrace.h>
16 #include <linux/mman.h>
17 #include <linux/mm.h>
18
19 #include <asm/system.h>
20 #include <asm/segment.h>
21 #include <asm/pgtable.h>
22
23 extern void die_if_kernel(char *,struct pt_regs *,long);
24
25
26
27
28
29
30
31
32
33
34
35 asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
36 {
37 struct vm_area_struct * vma;
38 unsigned long address;
39 unsigned long page;
40
41
42 __asm__("movl %%cr2,%0":"=r" (address));
43 vma = find_vma(current, address);
44 if (!vma)
45 goto bad_area;
46 if (vma->vm_start <= address)
47 goto good_area;
48 if (!(vma->vm_flags & VM_GROWSDOWN))
49 goto bad_area;
50 if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur)
51 goto bad_area;
52 vma->vm_offset -= vma->vm_start - (address & PAGE_MASK);
53 vma->vm_start = (address & PAGE_MASK);
54
55
56
57
58 good_area:
59
60
61
62 if (error_code & 2) {
63 if (!(vma->vm_flags & VM_WRITE))
64 goto bad_area;
65 } else {
66
67 if (error_code & 1)
68 goto bad_area;
69 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
70 goto bad_area;
71 }
72
73
74
75 if (regs->eflags & VM_MASK) {
76 unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT;
77 if (bit < 32)
78 current->tss.screen_bitmap |= 1 << bit;
79 }
80 if (error_code & 1) {
81 #ifdef CONFIG_TEST_VERIFY_AREA
82 if (regs->cs == KERNEL_CS)
83 printk("WP fault at %08x\n", regs->eip);
84 #endif
85 do_wp_page(vma, address, error_code & 2);
86 return;
87 }
88 do_no_page(vma, address, error_code & 2);
89 return;
90
91
92
93
94
95 bad_area:
96 if (error_code & 4) {
97 current->tss.cr2 = address;
98 current->tss.error_code = error_code;
99 current->tss.trap_no = 14;
100 send_sig(SIGSEGV, current, 1);
101 return;
102 }
103
104
105
106
107
108
109 if (wp_works_ok < 0 && address == TASK_SIZE && (error_code & 1)) {
110 wp_works_ok = 1;
111 pg0[0] = pte_val(mk_pte(0, PAGE_SHARED));
112 invalidate();
113 printk("This processor honours the WP bit even when in supervisor mode. Good.\n");
114 return;
115 }
116 if ((unsigned long) (address-TASK_SIZE) < PAGE_SIZE) {
117 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
118 pg0[0] = pte_val(mk_pte(0, PAGE_SHARED));
119 } else
120 printk(KERN_ALERT "Unable to handle kernel paging request");
121 printk(" at virtual address %08lx\n",address);
122 __asm__("movl %%cr3,%0" : "=r" (page));
123 printk(KERN_ALERT "current->tss.cr3 = %08lx, %%cr3 = %08lx\n",
124 current->tss.cr3, page);
125 page = ((unsigned long *) page)[address >> 22];
126 printk(KERN_ALERT "*pde = %08lx\n", page);
127 if (page & 1) {
128 page &= PAGE_MASK;
129 address &= 0x003ff000;
130 page = ((unsigned long *) page)[address >> PAGE_SHIFT];
131 printk(KERN_ALERT "*pte = %08lx\n", page);
132 }
133 die_if_kernel("Oops", regs, error_code);
134 do_exit(SIGKILL);
135 }