1
2
3
4
5
6
7#include <linux/signal.h>
8#include <linux/interrupt.h>
9#include <linux/sched/signal.h>
10#include <linux/errno.h>
11#include <linux/ptrace.h>
12#include <linux/uaccess.h>
13#include <linux/kdebug.h>
14#include <linux/perf_event.h>
15#include <linux/mm_types.h>
16#include <asm/mmu.h>
17
18
19
20
21
22
23
24
25noinline static int handle_kernel_vaddr_fault(unsigned long address)
26{
27
28
29
30
31 pgd_t *pgd, *pgd_k;
32 p4d_t *p4d, *p4d_k;
33 pud_t *pud, *pud_k;
34 pmd_t *pmd, *pmd_k;
35
36 pgd = pgd_offset(current->active_mm, address);
37 pgd_k = pgd_offset_k(address);
38
39 if (pgd_none (*pgd_k))
40 goto bad_area;
41 if (!pgd_present(*pgd))
42 set_pgd(pgd, *pgd_k);
43
44 p4d = p4d_offset(pgd, address);
45 p4d_k = p4d_offset(pgd_k, address);
46 if (p4d_none(*p4d_k))
47 goto bad_area;
48 if (!p4d_present(*p4d))
49 set_p4d(p4d, *p4d_k);
50
51 pud = pud_offset(p4d, address);
52 pud_k = pud_offset(p4d_k, address);
53 if (pud_none(*pud_k))
54 goto bad_area;
55 if (!pud_present(*pud))
56 set_pud(pud, *pud_k);
57
58 pmd = pmd_offset(pud, address);
59 pmd_k = pmd_offset(pud_k, address);
60 if (pmd_none(*pmd_k))
61 goto bad_area;
62 if (!pmd_present(*pmd))
63 set_pmd(pmd, *pmd_k);
64
65
66 return 0;
67
68bad_area:
69 return 1;
70}
71
72void do_page_fault(unsigned long address, struct pt_regs *regs)
73{
74 struct vm_area_struct *vma = NULL;
75 struct task_struct *tsk = current;
76 struct mm_struct *mm = tsk->mm;
77 int sig, si_code = SEGV_MAPERR;
78 unsigned int write = 0, exec = 0, mask;
79 vm_fault_t fault = VM_FAULT_SIGSEGV;
80 unsigned int flags;
81
82
83
84
85
86
87
88 if (address >= VMALLOC_START && !user_mode(regs)) {
89 if (unlikely(handle_kernel_vaddr_fault(address)))
90 goto no_context;
91 else
92 return;
93 }
94
95
96
97
98
99 if (faulthandler_disabled() || !mm)
100 goto no_context;
101
102 if (regs->ecr_cause & ECR_C_PROTV_STORE)
103 write = 1;
104 else if ((regs->ecr_vec == ECR_V_PROTV) &&
105 (regs->ecr_cause == ECR_C_PROTV_INST_FETCH))
106 exec = 1;
107
108 flags = FAULT_FLAG_DEFAULT;
109 if (user_mode(regs))
110 flags |= FAULT_FLAG_USER;
111 if (write)
112 flags |= FAULT_FLAG_WRITE;
113
114 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
115retry:
116 mmap_read_lock(mm);
117
118 vma = find_vma(mm, address);
119 if (!vma)
120 goto bad_area;
121 if (unlikely(address < vma->vm_start)) {
122 if (!(vma->vm_flags & VM_GROWSDOWN) || expand_stack(vma, address))
123 goto bad_area;
124 }
125
126
127
128
129 mask = VM_READ;
130 if (write)
131 mask = VM_WRITE;
132 if (exec)
133 mask = VM_EXEC;
134
135 if (!(vma->vm_flags & mask)) {
136 si_code = SEGV_ACCERR;
137 goto bad_area;
138 }
139
140 fault = handle_mm_fault(vma, address, flags, regs);
141
142
143 if (fault_signal_pending(fault, regs)) {
144 if (!user_mode(regs))
145 goto no_context;
146 return;
147 }
148
149
150
151
152 if (unlikely((fault & VM_FAULT_RETRY) &&
153 (flags & FAULT_FLAG_ALLOW_RETRY))) {
154 flags |= FAULT_FLAG_TRIED;
155 goto retry;
156 }
157
158bad_area:
159 mmap_read_unlock(mm);
160
161
162
163
164
165 if (likely(!(fault & VM_FAULT_ERROR)))
166
167 return;
168
169 if (!user_mode(regs))
170 goto no_context;
171
172 if (fault & VM_FAULT_OOM) {
173 pagefault_out_of_memory();
174 return;
175 }
176
177 if (fault & VM_FAULT_SIGBUS) {
178 sig = SIGBUS;
179 si_code = BUS_ADRERR;
180 }
181 else {
182 sig = SIGSEGV;
183 }
184
185 tsk->thread.fault_address = address;
186 force_sig_fault(sig, si_code, (void __user *)address);
187 return;
188
189no_context:
190 if (fixup_exception(regs))
191 return;
192
193 die("Oops", regs, address);
194}
195