mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
ARC: mm: do_page_fault refactor #7: fold the various error handling
- single up_read() call vs. 4 - so much easier on eyes Technically it seems like @bad_area label moved up, but even in old regime, it was a special case of delivering SIGSEGV unconditionally which we now do as well, although with checks. Also note that @fault needs to be initialized since we can land in @bad_area (which reads it) without setting it up with return value of handle_mm_fault() - failing to do so did bite us although as a side effect of different patch: see [1] [1]: http://lists.infradead.org/pipermail/linux-snps-arc/2019-May/005803.html Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
This commit is contained in:
parent
98cb57ad70
commit
5e91bf5ce9
@ -63,9 +63,9 @@ void do_page_fault(unsigned long address, struct pt_regs *regs)
|
||||
struct vm_area_struct *vma = NULL;
|
||||
struct task_struct *tsk = current;
|
||||
struct mm_struct *mm = tsk->mm;
|
||||
int si_code = SEGV_MAPERR;
|
||||
int sig, si_code = SEGV_MAPERR;
|
||||
unsigned int write = 0, exec = 0, mask;
|
||||
vm_fault_t fault; /* handle_mm_fault() output */
|
||||
vm_fault_t fault = VM_FAULT_SIGSEGV; /* handle_mm_fault() output */
|
||||
unsigned int flags; /* handle_mm_fault() input */
|
||||
|
||||
/*
|
||||
@ -174,47 +174,27 @@ retry:
|
||||
return;
|
||||
}
|
||||
|
||||
if (fault & VM_FAULT_OOM)
|
||||
goto out_of_memory;
|
||||
else if (fault & VM_FAULT_SIGSEGV)
|
||||
goto bad_area;
|
||||
else if (fault & VM_FAULT_SIGBUS)
|
||||
goto do_sigbus;
|
||||
|
||||
/* no man's land */
|
||||
BUG();
|
||||
|
||||
/*
|
||||
* Something tried to access memory that isn't in our memory map..
|
||||
* Fix it, but check if it's kernel or user first..
|
||||
*/
|
||||
bad_area:
|
||||
up_read(&mm->mmap_sem);
|
||||
|
||||
if (!user_mode(regs))
|
||||
goto no_context;
|
||||
|
||||
tsk->thread.fault_address = address;
|
||||
force_sig_fault(SIGSEGV, si_code, (void __user *)address, tsk);
|
||||
return;
|
||||
if (fault & VM_FAULT_OOM) {
|
||||
pagefault_out_of_memory();
|
||||
return;
|
||||
}
|
||||
|
||||
out_of_memory:
|
||||
up_read(&mm->mmap_sem);
|
||||
|
||||
if (!user_mode(regs))
|
||||
goto no_context;
|
||||
|
||||
pagefault_out_of_memory();
|
||||
return;
|
||||
|
||||
do_sigbus:
|
||||
up_read(&mm->mmap_sem);
|
||||
|
||||
if (!user_mode(regs))
|
||||
goto no_context;
|
||||
if (fault & VM_FAULT_SIGBUS) {
|
||||
sig = SIGBUS;
|
||||
si_code = BUS_ADRERR;
|
||||
}
|
||||
else {
|
||||
sig = SIGSEGV;
|
||||
}
|
||||
|
||||
tsk->thread.fault_address = address;
|
||||
force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address, tsk);
|
||||
force_sig_fault(sig, si_code, (void __user *)address, tsk);
|
||||
return;
|
||||
|
||||
no_context:
|
||||
|
Loading…
Reference in New Issue
Block a user