@@ -108,6 +108,45 @@ static int store_updates_sp(struct pt_regs *regs)
108108 * do_page_fault error handling helpers
109109 */
110110
111+ static int
112+ __bad_area_nosemaphore (struct pt_regs * regs , unsigned long address , int si_code )
113+ {
114+ /*
115+ * If we are in kernel mode, bail out with a SEGV, this will
116+ * be caught by the assembly which will restore the non-volatile
117+ * registers before calling bad_page_fault()
118+ */
119+ if (!user_mode (regs ))
120+ return SIGSEGV ;
121+
122+ _exception (SIGSEGV , regs , si_code , address );
123+
124+ return 0 ;
125+ }
126+
127+ static noinline int bad_area_nosemaphore (struct pt_regs * regs , unsigned long address )
128+ {
129+ return __bad_area_nosemaphore (regs , address , SEGV_MAPERR );
130+ }
131+
132+ static int __bad_area (struct pt_regs * regs , unsigned long address , int si_code )
133+ {
134+ struct mm_struct * mm = current -> mm ;
135+
136+ /*
137+ * Something tried to access memory that isn't in our memory map..
138+ * Fix it, but check if it's kernel or user first..
139+ */
140+ up_read (& mm -> mmap_sem );
141+
142+ return __bad_area_nosemaphore (regs , address , si_code );
143+ }
144+
145+ static noinline int bad_area (struct pt_regs * regs , unsigned long address )
146+ {
147+ return __bad_area (regs , address , SEGV_MAPERR );
148+ }
149+
111150#define MM_FAULT_RETURN 0
112151#define MM_FAULT_CONTINUE -1
113152#define MM_FAULT_ERR (sig ) (sig)
@@ -231,7 +270,6 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
231270 struct vm_area_struct * vma ;
232271 struct mm_struct * mm = current -> mm ;
233272 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE ;
234- int code = SEGV_MAPERR ;
235273 int is_exec = TRAP (regs ) == 0x400 ;
236274 int is_user = user_mode (regs );
237275 int is_write = page_fault_is_write (error_code );
@@ -317,7 +355,7 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
317355 */
318356 if (!down_read_trylock (& mm -> mmap_sem )) {
319357 if (!is_user && !search_exception_tables (regs -> nip ))
320- goto bad_area_nosemaphore ;
358+ return bad_area_nosemaphore ( regs , address ) ;
321359
322360retry :
323361 down_read (& mm -> mmap_sem );
@@ -332,11 +370,11 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
332370
333371 vma = find_vma (mm , address );
334372 if (!vma )
335- goto bad_area ;
373+ return bad_area ( regs , address ) ;
336374 if (vma -> vm_start <= address )
337375 goto good_area ;
338376 if (!(vma -> vm_flags & VM_GROWSDOWN ))
339- goto bad_area ;
377+ return bad_area ( regs , address ) ;
340378
341379 /*
342380 * N.B. The POWER/Open ABI allows programs to access up to
@@ -351,7 +389,7 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
351389 /* get user regs even if this fault is in kernel mode */
352390 struct pt_regs * uregs = current -> thread .regs ;
353391 if (uregs == NULL )
354- goto bad_area ;
392+ return bad_area ( regs , address ) ;
355393
356394 /*
357395 * A user-mode access to an address a long way below
@@ -366,14 +404,12 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
366404 * expand the stack rather than segfaulting.
367405 */
368406 if (address + 2048 < uregs -> gpr [1 ] && !store_update_sp )
369- goto bad_area ;
407+ return bad_area ( regs , address ) ;
370408 }
371409 if (expand_stack (vma , address ))
372- goto bad_area ;
410+ return bad_area ( regs , address ) ;
373411
374412good_area :
375- code = SEGV_ACCERR ;
376-
377413 if (is_exec ) {
378414 /*
379415 * Allow execution from readable areas if the MMU does not
@@ -388,16 +424,16 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
388424 if (!(vma -> vm_flags & VM_EXEC ) &&
389425 (cpu_has_feature (CPU_FTR_NOEXECUTE ) ||
390426 !(vma -> vm_flags & (VM_READ | VM_WRITE ))))
391- goto bad_area ;
427+ return bad_area ( regs , address ) ;
392428 /* a write */
393429 } else if (is_write ) {
394430 if (!(vma -> vm_flags & VM_WRITE ))
395- goto bad_area ;
431+ return bad_area ( regs , address ) ;
396432 flags |= FAULT_FLAG_WRITE ;
397433 /* a read */
398434 } else {
399435 if (!(vma -> vm_flags & (VM_READ | VM_EXEC | VM_WRITE )))
400- goto bad_area ;
436+ return bad_area ( regs , address ) ;
401437 }
402438#ifdef CONFIG_PPC_STD_MMU
403439 /*
@@ -462,11 +498,10 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
462498
463499 if (unlikely (fault & (VM_FAULT_RETRY |VM_FAULT_ERROR ))) {
464500 if (fault & VM_FAULT_SIGSEGV )
465- goto bad_area_nosemaphore ;
501+ return bad_area_nosemaphore ( regs , address ) ;
466502 rc = mm_fault_error (regs , address , fault );
467503 if (rc >= MM_FAULT_RETURN )
468504 return rc ;
469- rc = 0 ;
470505 }
471506
472507 /*
@@ -492,20 +527,7 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
492527 perf_sw_event (PERF_COUNT_SW_PAGE_FAULTS_MIN , 1 ,
493528 regs , address );
494529 }
495-
496- return rc ;
497-
498- bad_area :
499- up_read (& mm -> mmap_sem );
500-
501- bad_area_nosemaphore :
502- /* User mode accesses cause a SIGSEGV */
503- if (is_user ) {
504- _exception (SIGSEGV , regs , code , address );
505- return 0 ;
506- }
507-
508- return SIGSEGV ;
530+ return 0 ;
509531}
510532NOKPROBE_SYMBOL (__do_page_fault );
511533
0 commit comments