diff options
Diffstat (limited to 'arch/xtensa/mm/fault.c')
-rw-r--r-- | arch/xtensa/mm/fault.c | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c index b17885a0b508..5a74c53bc69c 100644 --- a/arch/xtensa/mm/fault.c +++ b/arch/xtensa/mm/fault.c | |||
@@ -44,6 +44,7 @@ void do_page_fault(struct pt_regs *regs) | |||
44 | 44 | ||
45 | int is_write, is_exec; | 45 | int is_write, is_exec; |
46 | int fault; | 46 | int fault; |
47 | unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE; | ||
47 | 48 | ||
48 | info.si_code = SEGV_MAPERR; | 49 | info.si_code = SEGV_MAPERR; |
49 | 50 | ||
@@ -71,6 +72,7 @@ void do_page_fault(struct pt_regs *regs) | |||
71 | address, exccause, regs->pc, is_write? "w":"", is_exec? "x":""); | 72 | address, exccause, regs->pc, is_write? "w":"", is_exec? "x":""); |
72 | #endif | 73 | #endif |
73 | 74 | ||
75 | retry: | ||
74 | down_read(&mm->mmap_sem); | 76 | down_read(&mm->mmap_sem); |
75 | vma = find_vma(mm, address); | 77 | vma = find_vma(mm, address); |
76 | 78 | ||
@@ -93,6 +95,7 @@ good_area: | |||
93 | if (is_write) { | 95 | if (is_write) { |
94 | if (!(vma->vm_flags & VM_WRITE)) | 96 | if (!(vma->vm_flags & VM_WRITE)) |
95 | goto bad_area; | 97 | goto bad_area; |
98 | flags |= FAULT_FLAG_WRITE; | ||
96 | } else if (is_exec) { | 99 | } else if (is_exec) { |
97 | if (!(vma->vm_flags & VM_EXEC)) | 100 | if (!(vma->vm_flags & VM_EXEC)) |
98 | goto bad_area; | 101 | goto bad_area; |
@@ -104,7 +107,11 @@ good_area: | |||
104 | * make sure we exit gracefully rather than endlessly redo | 107 | * make sure we exit gracefully rather than endlessly redo |
105 | * the fault. | 108 | * the fault. |
106 | */ | 109 | */ |
107 | fault = handle_mm_fault(mm, vma, address, is_write ? FAULT_FLAG_WRITE : 0); | 110 | fault = handle_mm_fault(mm, vma, address, flags); |
111 | |||
112 | if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) | ||
113 | return; | ||
114 | |||
108 | if (unlikely(fault & VM_FAULT_ERROR)) { | 115 | if (unlikely(fault & VM_FAULT_ERROR)) { |
109 | if (fault & VM_FAULT_OOM) | 116 | if (fault & VM_FAULT_OOM) |
110 | goto out_of_memory; | 117 | goto out_of_memory; |
@@ -112,10 +119,22 @@ good_area: | |||
112 | goto do_sigbus; | 119 | goto do_sigbus; |
113 | BUG(); | 120 | BUG(); |
114 | } | 121 | } |
115 | if (fault & VM_FAULT_MAJOR) | 122 | if (flags & FAULT_FLAG_ALLOW_RETRY) { |
116 | current->maj_flt++; | 123 | if (fault & VM_FAULT_MAJOR) |
117 | else | 124 | current->maj_flt++; |
118 | current->min_flt++; | 125 | else |
126 | current->min_flt++; | ||
127 | if (fault & VM_FAULT_RETRY) { | ||
128 | flags &= ~FAULT_FLAG_ALLOW_RETRY; | ||
129 | |||
130 | /* No need to up_read(&mm->mmap_sem) as we would | ||
131 | * have already released it in __lock_page_or_retry | ||
132 | * in mm/filemap.c. | ||
133 | */ | ||
134 | |||
135 | goto retry; | ||
136 | } | ||
137 | } | ||
119 | 138 | ||
120 | up_read(&mm->mmap_sem); | 139 | up_read(&mm->mmap_sem); |
121 | return; | 140 | return; |