8 #include <linux/signal.h>
9 #include <linux/sched.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>
19 #include <linux/module.h>
21 #include <linux/perf_event.h>
24 #include <asm/mmu_context.h>
25 #include <asm/uaccess.h>
26 #include <asm/ptrace.h>
27 #include <asm/highmem.h>
41 const int field =
sizeof(
unsigned long) * 2;
44 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
45 (write ? FAULT_FLAG_WRITE : 0);
76 # define VMALLOC_FAULT_TARGET no_context
78 # define VMALLOC_FAULT_TARGET vmalloc_fault
84 if (
unlikely(address >= MODULE_START && address < MODULE_END))
93 goto bad_area_nosemaphore;
102 if (!(vma->
vm_flags & VM_GROWSDOWN))
120 pr_notice(
"Cpu%d[%s:%d:%0*lx:%ld:%0*lx] XI violation\n",
123 field, address, write,
130 pr_notice(
"Cpu%d[%s:%d:%0*lx:%ld:%0*lx] RI violation\n",
133 field, address, write,
139 if (!(vma->
vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
151 if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(
current))
155 if (
unlikely(fault & VM_FAULT_ERROR)) {
156 if (fault & VM_FAULT_OOM)
158 else if (fault & VM_FAULT_SIGBUS)
162 if (flags & FAULT_FLAG_ALLOW_RETRY) {
163 if (fault & VM_FAULT_MAJOR) {
172 if (fault & VM_FAULT_RETRY) {
173 flags &= ~FAULT_FLAG_ALLOW_RETRY;
174 flags |= FAULT_FLAG_TRIED;
196 bad_area_nosemaphore:
202 printk(
"do_page_fault() #2: sending SIGSEGV to %s for "
203 "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n",
205 write ?
"write access to" :
"read access from",
207 field, (
unsigned long) regs->
cp0_epc,
208 field, (
unsigned long) regs->
regs[31]);
213 info.si_addr = (
void __user *) address;
232 "virtual address %0*lx, epc == %0*lx, ra == %0*lx\n",
234 field, regs->
regs[31]);
258 printk(
"do_page_fault() #3: sending SIGBUS to %s for "
259 "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n",
261 write ?
"write access to" :
"read access from",
263 field, (
unsigned long) regs->
cp0_epc,
264 field, (
unsigned long) regs->
regs[31]);
270 info.si_addr = (
void __user *) address;