1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/mm.h>
14#include <linux/ptrace.h>
15#include <linux/sched.h>
16#include <linux/sched/debug.h>
17#include <linux/interrupt.h>
18#include <linux/extable.h>
19#include <linux/uaccess.h>
20#include <linux/hugetlb.h>
21#include <linux/perf_event.h>
22
23#include <asm/traps.h>
24
25
26#define bit22set(x) (x & 0x00000200)
27#define bits23_25set(x) (x & 0x000001c0)
28#define isGraphicsFlushRead(x) ((x & 0xfc003fdf) == 0x04001a80)
29
30
31#define BITSSET 0x1c0
32
33
34int show_unhandled_signals = 1;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51static unsigned long
52parisc_acctyp(unsigned long code, unsigned int inst)
53{
54 if (code == 6 || code == 16)
55 return VM_EXEC;
56
57 switch (inst & 0xf0000000) {
58 case 0x40000000:
59 case 0x50000000:
60 return VM_READ;
61
62 case 0x60000000:
63 case 0x70000000:
64 return VM_WRITE;
65
66 case 0x20000000:
67 case 0x30000000:
68 if (bit22set(inst))
69 return VM_WRITE;
70 fallthrough;
71
72 case 0x0:
73 if (bit22set(inst)) {
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 if (isGraphicsFlushRead(inst))
92 return VM_READ;
93 return VM_WRITE;
94 } else {
95
96
97
98
99
100
101
102
103
104
105
106
107 if (bits23_25set(inst) == BITSSET)
108 return VM_WRITE;
109 }
110 return VM_READ;
111 }
112 return VM_READ;
113}
114
115#undef bit22set
116#undef bits23_25set
117#undef isGraphicsFlushRead
118#undef BITSSET
119
120
121#if 0
122
123
124
125
126
127 while (tree != vm_avl_empty) {
128 if (tree->vm_start > addr) {
129 tree = tree->vm_avl_left;
130 } else {
131 prev = tree;
132 if (prev->vm_next == NULL)
133 break;
134 if (prev->vm_next->vm_start > addr)
135 break;
136 tree = tree->vm_avl_right;
137 }
138 }
139#endif
140
141int fixup_exception(struct pt_regs *regs)
142{
143 const struct exception_table_entry *fix;
144
145 fix = search_exception_tables(regs->iaoq[0]);
146 if (fix) {
147
148
149
150
151
152
153
154 if (fix->fixup & 1) {
155 regs->gr[8] = -EFAULT;
156
157
158 if (parisc_acctyp(0, regs->iir) == VM_READ) {
159 int treg = regs->iir & 0x1f;
160 BUG_ON(treg == 0);
161 regs->gr[treg] = 0;
162 }
163 }
164
165 regs->iaoq[0] = (unsigned long)&fix->fixup + fix->fixup;
166 regs->iaoq[0] &= ~3;
167
168
169
170
171
172
173
174 regs->iaoq[1] = regs->iaoq[0] + 4;
175 regs->gr[0] &= ~PSW_B;
176
177 return 1;
178 }
179
180 return 0;
181}
182
183
184
185
186
187
188
189
190
191
192static const char * const trap_description[] = {
193 [1] "High-priority machine check (HPMC)",
194 [2] "Power failure interrupt",
195 [3] "Recovery counter trap",
196 [5] "Low-priority machine check",
197 [6] "Instruction TLB miss fault",
198 [7] "Instruction access rights / protection trap",
199 [8] "Illegal instruction trap",
200 [9] "Break instruction trap",
201 [10] "Privileged operation trap",
202 [11] "Privileged register trap",
203 [12] "Overflow trap",
204 [13] "Conditional trap",
205 [14] "FP Assist Exception trap",
206 [15] "Data TLB miss fault",
207 [16] "Non-access ITLB miss fault",
208 [17] "Non-access DTLB miss fault",
209 [18] "Data memory protection/unaligned access trap",
210 [19] "Data memory break trap",
211 [20] "TLB dirty bit trap",
212 [21] "Page reference trap",
213 [22] "Assist emulation trap",
214 [25] "Taken branch trap",
215 [26] "Data memory access rights trap",
216 [27] "Data memory protection ID trap",
217 [28] "Unaligned data reference trap",
218};
219
220const char *trap_name(unsigned long code)
221{
222 const char *t = NULL;
223
224 if (code < ARRAY_SIZE(trap_description))
225 t = trap_description[code];
226
227 return t ? t : "Unknown trap";
228}
229
230
231
232
233
234static inline void
235show_signal_msg(struct pt_regs *regs, unsigned long code,
236 unsigned long address, struct task_struct *tsk,
237 struct vm_area_struct *vma)
238{
239 if (!unhandled_signal(tsk, SIGSEGV))
240 return;
241
242 if (!printk_ratelimit())
243 return;
244
245 pr_warn("\n");
246 pr_warn("do_page_fault() command='%s' type=%lu address=0x%08lx",
247 tsk->comm, code, address);
248 print_vma_addr(KERN_CONT " in ", regs->iaoq[0]);
249
250 pr_cont("\ntrap #%lu: %s%c", code, trap_name(code),
251 vma ? ',':'\n');
252
253 if (vma)
254 pr_cont(" vm_start = 0x%08lx, vm_end = 0x%08lx\n",
255 vma->vm_start, vma->vm_end);
256
257 show_regs(regs);
258}
259
260void do_page_fault(struct pt_regs *regs, unsigned long code,
261 unsigned long address)
262{
263 struct vm_area_struct *vma, *prev_vma;
264 struct task_struct *tsk;
265 struct mm_struct *mm;
266 unsigned long acc_type;
267 vm_fault_t fault = 0;
268 unsigned int flags;
269
270 if (faulthandler_disabled())
271 goto no_context;
272
273 tsk = current;
274 mm = tsk->mm;
275 if (!mm)
276 goto no_context;
277
278 flags = FAULT_FLAG_DEFAULT;
279 if (user_mode(regs))
280 flags |= FAULT_FLAG_USER;
281
282 acc_type = parisc_acctyp(code, regs->iir);
283 if (acc_type & VM_WRITE)
284 flags |= FAULT_FLAG_WRITE;
285 perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
286retry:
287 mmap_read_lock(mm);
288 vma = find_vma_prev(mm, address, &prev_vma);
289 if (!vma || address < vma->vm_start)
290 goto check_expansion;
291
292
293
294
295
296good_area:
297
298 if ((vma->vm_flags & acc_type) != acc_type)
299 goto bad_area;
300
301
302
303
304
305
306
307 fault = handle_mm_fault(vma, address, flags, regs);
308
309 if (fault_signal_pending(fault, regs))
310 return;
311
312 if (unlikely(fault & VM_FAULT_ERROR)) {
313
314
315
316
317
318 if (fault & VM_FAULT_OOM)
319 goto out_of_memory;
320 else if (fault & VM_FAULT_SIGSEGV)
321 goto bad_area;
322 else if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
323 VM_FAULT_HWPOISON_LARGE))
324 goto bad_area;
325 BUG();
326 }
327 if (flags & FAULT_FLAG_ALLOW_RETRY) {
328 if (fault & VM_FAULT_RETRY) {
329
330
331
332
333
334 flags |= FAULT_FLAG_TRIED;
335 goto retry;
336 }
337 }
338 mmap_read_unlock(mm);
339 return;
340
341check_expansion:
342 vma = prev_vma;
343 if (vma && (expand_stack(vma, address) == 0))
344 goto good_area;
345
346
347
348
349bad_area:
350 mmap_read_unlock(mm);
351
352 if (user_mode(regs)) {
353 int signo, si_code;
354
355 switch (code) {
356 case 15:
357
358 if (!vma ||
359 address < vma->vm_start || address >= vma->vm_end) {
360 signo = SIGSEGV;
361 si_code = SEGV_MAPERR;
362 break;
363 }
364
365
366 if ((vma->vm_flags & acc_type) != acc_type) {
367 signo = SIGSEGV;
368 si_code = SEGV_ACCERR;
369 break;
370 }
371
372
373 fallthrough;
374 case 17:
375 case 18:
376 signo = SIGBUS;
377 si_code = (code == 18) ? BUS_ADRALN : BUS_ADRERR;
378 break;
379 case 16:
380 case 26:
381 default:
382 signo = SIGSEGV;
383 si_code = (code == 26) ? SEGV_ACCERR : SEGV_MAPERR;
384 break;
385 }
386#ifdef CONFIG_MEMORY_FAILURE
387 if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) {
388 unsigned int lsb = 0;
389 printk(KERN_ERR
390 "MCE: Killing %s:%d due to hardware memory corruption fault at %08lx\n",
391 tsk->comm, tsk->pid, address);
392
393
394
395
396
397 if (fault & VM_FAULT_HWPOISON_LARGE)
398 lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
399 else if (fault & VM_FAULT_HWPOISON)
400 lsb = PAGE_SHIFT;
401
402 force_sig_mceerr(BUS_MCEERR_AR, (void __user *) address,
403 lsb);
404 return;
405 }
406#endif
407 show_signal_msg(regs, code, address, tsk, vma);
408
409 force_sig_fault(signo, si_code, (void __user *) address);
410 return;
411 }
412
413no_context:
414
415 if (!user_mode(regs) && fixup_exception(regs)) {
416 return;
417 }
418
419 parisc_terminate("Bad Address (null pointer deref?)", regs, code, address);
420
421 out_of_memory:
422 mmap_read_unlock(mm);
423 if (!user_mode(regs))
424 goto no_context;
425 pagefault_out_of_memory();
426}
427