Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
fault.c
Go to the documentation of this file.
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License. See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  *
7  * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
8  * Copyright 1999 SuSE GmbH (Philipp Rumpf, [email protected])
9  * Copyright 1999 Hewlett Packard Co.
10  *
11  */
12 
13 #include <linux/mm.h>
14 #include <linux/ptrace.h>
15 #include <linux/sched.h>
16 #include <linux/interrupt.h>
17 #include <linux/module.h>
18 
19 #include <asm/uaccess.h>
20 #include <asm/traps.h>
21 
22 #define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */
23  /* dumped to the console via printk) */
24 
25 
26 /* Various important other fields */
27 #define bit22set(x) (x & 0x00000200)
28 #define bits23_25set(x) (x & 0x000001c0)
29 #define isGraphicsFlushRead(x) ((x & 0xfc003fdf) == 0x04001a80)
30  /* extended opcode is 0x6a */
31 
32 #define BITSSET 0x1c0 /* for identifying LDCW */
33 
34 
36 
37 /*
38  * parisc_acctyp(unsigned int inst) --
39  * Given a PA-RISC memory access instruction, determine if the
40  * the instruction would perform a memory read or memory write
41  * operation.
42  *
43  * This function assumes that the given instruction is a memory access
44  * instruction (i.e. you should really only call it if you know that
45  * the instruction has generated some sort of a memory access fault).
46  *
47  * Returns:
48  * VM_READ if read operation
49  * VM_WRITE if write operation
50  * VM_EXEC if execute operation
51  */
52 static unsigned long
53 parisc_acctyp(unsigned long code, unsigned int inst)
54 {
55  if (code == 6 || code == 16)
56  return VM_EXEC;
57 
58  switch (inst & 0xf0000000) {
59  case 0x40000000: /* load */
60  case 0x50000000: /* new load */
61  return VM_READ;
62 
63  case 0x60000000: /* store */
64  case 0x70000000: /* new store */
65  return VM_WRITE;
66 
67  case 0x20000000: /* coproc */
68  case 0x30000000: /* coproc2 */
69  if (bit22set(inst))
70  return VM_WRITE;
71 
72  case 0x0: /* indexed/memory management */
73  if (bit22set(inst)) {
74  /*
75  * Check for the 'Graphics Flush Read' instruction.
76  * It resembles an FDC instruction, except for bits
77  * 20 and 21. Any combination other than zero will
78  * utilize the block mover functionality on some
79  * older PA-RISC platforms. The case where a block
80  * move is performed from VM to graphics IO space
81  * should be treated as a READ.
82  *
83  * The significance of bits 20,21 in the FDC
84  * instruction is:
85  *
86  * 00 Flush data cache (normal instruction behavior)
87  * 01 Graphics flush write (IO space -> VM)
88  * 10 Graphics flush read (VM -> IO space)
89  * 11 Graphics flush read/write (VM <-> IO space)
90  */
91  if (isGraphicsFlushRead(inst))
92  return VM_READ;
93  return VM_WRITE;
94  } else {
95  /*
96  * Check for LDCWX and LDCWS (semaphore instructions).
97  * If bits 23 through 25 are all 1's it is one of
98  * the above two instructions and is a write.
99  *
100  * Note: With the limited bits we are looking at,
101  * this will also catch PROBEW and PROBEWI. However,
102  * these should never get in here because they don't
103  * generate exceptions of the type:
104  * Data TLB miss fault/data page fault
105  * Data memory protection trap
106  */
107  if (bits23_25set(inst) == BITSSET)
108  return VM_WRITE;
109  }
110  return VM_READ; /* Default */
111  }
112  return VM_READ; /* Default */
113 }
114 
115 #undef bit22set
116 #undef bits23_25set
117 #undef isGraphicsFlushRead
118 #undef BITSSET
119 
120 
121 #if 0
122 /* This is the treewalk to find a vma which is the highest that has
123  * a start < addr. We're using find_vma_prev instead right now, but
124  * we might want to use this at some point in the future. Probably
125  * not, but I want it committed to CVS so I don't lose it :-)
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 
142 {
143  const struct exception_table_entry *fix;
144 
145  fix = search_exception_tables(regs->iaoq[0]);
146  if (fix) {
147  struct exception_data *d;
149  d->fault_ip = regs->iaoq[0];
150  d->fault_space = regs->isr;
151  d->fault_addr = regs->ior;
152 
153  regs->iaoq[0] = ((fix->fixup) & ~3);
154  /*
155  * NOTE: In some cases the faulting instruction
156  * may be in the delay slot of a branch. We
157  * don't want to take the branch, so we don't
158  * increment iaoq[1], instead we set it to be
159  * iaoq[0]+4, and clear the B bit in the PSW
160  */
161  regs->iaoq[1] = regs->iaoq[0] + 4;
162  regs->gr[0] &= ~PSW_B; /* IPSW in gr[0] */
163 
164  return 1;
165  }
166 
167  return 0;
168 }
169 
170 void do_page_fault(struct pt_regs *regs, unsigned long code,
171  unsigned long address)
172 {
173  struct vm_area_struct *vma, *prev_vma;
174  struct task_struct *tsk = current;
175  struct mm_struct *mm = tsk->mm;
176  unsigned long acc_type;
177  int fault;
178 
179  if (in_atomic() || !mm)
180  goto no_context;
181 
182  down_read(&mm->mmap_sem);
183  vma = find_vma_prev(mm, address, &prev_vma);
184  if (!vma || address < vma->vm_start)
185  goto check_expansion;
186 /*
187  * Ok, we have a good vm_area for this memory access. We still need to
188  * check the access permissions.
189  */
190 
191 good_area:
192 
193  acc_type = parisc_acctyp(code,regs->iir);
194 
195  if ((vma->vm_flags & acc_type) != acc_type)
196  goto bad_area;
197 
198  /*
199  * If for any reason at all we couldn't handle the fault, make
200  * sure we exit gracefully rather than endlessly redo the
201  * fault.
202  */
203 
204  fault = handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) ? FAULT_FLAG_WRITE : 0);
205  if (unlikely(fault & VM_FAULT_ERROR)) {
206  /*
207  * We hit a shared mapping outside of the file, or some
208  * other thing happened to us that made us unable to
209  * handle the page fault gracefully.
210  */
211  if (fault & VM_FAULT_OOM)
212  goto out_of_memory;
213  else if (fault & VM_FAULT_SIGBUS)
214  goto bad_area;
215  BUG();
216  }
217  if (fault & VM_FAULT_MAJOR)
218  current->maj_flt++;
219  else
220  current->min_flt++;
221  up_read(&mm->mmap_sem);
222  return;
223 
224 check_expansion:
225  vma = prev_vma;
226  if (vma && (expand_stack(vma, address) == 0))
227  goto good_area;
228 
229 /*
230  * Something tried to access memory that isn't in our memory map..
231  */
232 bad_area:
233  up_read(&mm->mmap_sem);
234 
235  if (user_mode(regs)) {
236  struct siginfo si;
237 
238 #ifdef PRINT_USER_FAULTS
239  printk(KERN_DEBUG "\n");
240  printk(KERN_DEBUG "do_page_fault() pid=%d command='%s' type=%lu address=0x%08lx\n",
241  task_pid_nr(tsk), tsk->comm, code, address);
242  if (vma) {
243  printk(KERN_DEBUG "vm_start = 0x%08lx, vm_end = 0x%08lx\n",
244  vma->vm_start, vma->vm_end);
245  }
246  show_regs(regs);
247 #endif
248  /* FIXME: actually we need to get the signo and code correct */
249  si.si_signo = SIGSEGV;
250  si.si_errno = 0;
251  si.si_code = SEGV_MAPERR;
252  si.si_addr = (void __user *) address;
254  return;
255  }
256 
257 no_context:
258 
259  if (!user_mode(regs) && fixup_exception(regs)) {
260  return;
261  }
262 
263  parisc_terminate("Bad Address (null pointer deref?)", regs, code, address);
264 
266  up_read(&mm->mmap_sem);
267  if (!user_mode(regs))
268  goto no_context;
270 }