Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 340372
b: refs/heads/master
c: 3d7b6a6
h: refs/heads/master
v: v3
  • Loading branch information
Kautuk Consul authored and David Howells committed Dec 12, 2012
1 parent f84825c commit 47c2eb2
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 83c2dc15ce824450e7044b9f90cd529c25747ae0
refs/heads/master: 3d7b6a674e266999a90ff1e21c6c839e30200c51
33 changes: 25 additions & 8 deletions trunk/arch/mn10300/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
struct mm_struct *mm;
unsigned long page;
siginfo_t info;
int write, fault;
int fault;
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;

#ifdef CONFIG_GDBSTUB
/* handle GDB stub causing a fault */
Expand Down Expand Up @@ -170,6 +171,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
if (in_atomic() || !mm)
goto no_context;

retry:
down_read(&mm->mmap_sem);

vma = find_vma(mm, address);
Expand Down Expand Up @@ -220,7 +222,6 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
*/
good_area:
info.si_code = SEGV_ACCERR;
write = 0;
switch (fault_code & (MMUFCR_xFC_PGINVAL|MMUFCR_xFC_TYPE)) {
default: /* 3: write, present */
case MMUFCR_xFC_TYPE_WRITE:
Expand All @@ -232,7 +233,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
case MMUFCR_xFC_PGINVAL | MMUFCR_xFC_TYPE_WRITE:
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
write++;
flags |= FAULT_FLAG_WRITE;
break;

/* read from protected page */
Expand All @@ -251,18 +252,34 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
* make sure we exit gracefully rather than endlessly redo
* the fault.
*/
fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
fault = handle_mm_fault(mm, vma, address, flags);

if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
return;

if (unlikely(fault & VM_FAULT_ERROR)) {
if (fault & VM_FAULT_OOM)
goto out_of_memory;
else if (fault & VM_FAULT_SIGBUS)
goto do_sigbus;
BUG();
}
if (fault & VM_FAULT_MAJOR)
current->maj_flt++;
else
current->min_flt++;
if (flags & FAULT_FLAG_ALLOW_RETRY) {
if (fault & VM_FAULT_MAJOR)
current->maj_flt++;
else
current->min_flt++;
if (fault & VM_FAULT_RETRY) {
flags &= ~FAULT_FLAG_ALLOW_RETRY;

/* No need to up_read(&mm->mmap_sem) as we would
* have already released it in __lock_page_or_retry
* in mm/filemap.c.
*/

goto retry;
}
}

up_read(&mm->mmap_sem);
return;
Expand Down

0 comments on commit 47c2eb2

Please sign in to comment.