hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/arch/openrisc/mm/fault.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * OpenRISC fault.c
34 *
....@@ -8,17 +9,13 @@
89 * Modifications for the OpenRISC architecture:
910 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
1011 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
11
- *
12
- * This program is free software; you can redistribute it and/or
13
- * modify it under the terms of the GNU General Public License
14
- * as published by the Free Software Foundation; either version
15
- * 2 of the License, or (at your option) any later version.
1612 */
1713
1814 #include <linux/mm.h>
1915 #include <linux/interrupt.h>
2016 #include <linux/extable.h>
2117 #include <linux/sched/signal.h>
18
+#include <linux/perf_event.h>
2219
2320 #include <linux/uaccess.h>
2421 #include <asm/siginfo.h>
....@@ -54,7 +51,7 @@
5451 struct vm_area_struct *vma;
5552 int si_code;
5653 vm_fault_t fault;
57
- unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
54
+ unsigned int flags = FAULT_FLAG_DEFAULT;
5855
5956 tsk = current;
6057
....@@ -107,8 +104,10 @@
107104 if (in_interrupt() || !mm)
108105 goto no_context;
109106
107
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
108
+
110109 retry:
111
- down_read(&mm->mmap_sem);
110
+ mmap_read_lock(mm);
112111 vma = find_vma(mm, address);
113112
114113 if (!vma)
....@@ -163,9 +162,9 @@
163162 * the fault.
164163 */
165164
166
- fault = handle_mm_fault(vma, address, flags);
165
+ fault = handle_mm_fault(vma, address, flags, regs);
167166
168
- if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
167
+ if (fault_signal_pending(fault, regs))
169168 return;
170169
171170 if (unlikely(fault & VM_FAULT_ERROR)) {
....@@ -180,15 +179,10 @@
180179
181180 if (flags & FAULT_FLAG_ALLOW_RETRY) {
182181 /*RGD modeled on Cris */
183
- if (fault & VM_FAULT_MAJOR)
184
- tsk->maj_flt++;
185
- else
186
- tsk->min_flt++;
187182 if (fault & VM_FAULT_RETRY) {
188
- flags &= ~FAULT_FLAG_ALLOW_RETRY;
189183 flags |= FAULT_FLAG_TRIED;
190184
191
- /* No need to up_read(&mm->mmap_sem) as we would
185
+ /* No need to mmap_read_unlock(mm) as we would
192186 * have already released it in __lock_page_or_retry
193187 * in mm/filemap.c.
194188 */
....@@ -197,7 +191,7 @@
197191 }
198192 }
199193
200
- up_read(&mm->mmap_sem);
194
+ mmap_read_unlock(mm);
201195 return;
202196
203197 /*
....@@ -206,14 +200,14 @@
206200 */
207201
208202 bad_area:
209
- up_read(&mm->mmap_sem);
203
+ mmap_read_unlock(mm);
210204
211205 bad_area_nosemaphore:
212206
213207 /* User mode accesses just cause a SIGSEGV */
214208
215209 if (user_mode(regs)) {
216
- force_sig_fault(SIGSEGV, si_code, (void __user *)address, tsk);
210
+ force_sig_fault(SIGSEGV, si_code, (void __user *)address);
217211 return;
218212 }
219213
....@@ -265,20 +259,20 @@
265259 __asm__ __volatile__("l.nop 42");
266260 __asm__ __volatile__("l.nop 1");
267261
268
- up_read(&mm->mmap_sem);
262
+ mmap_read_unlock(mm);
269263 if (!user_mode(regs))
270264 goto no_context;
271265 pagefault_out_of_memory();
272266 return;
273267
274268 do_sigbus:
275
- up_read(&mm->mmap_sem);
269
+ mmap_read_unlock(mm);
276270
277271 /*
278272 * Send a sigbus, regardless of whether we were in kernel
279273 * or user mode.
280274 */
281
- force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address, tsk);
275
+ force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address);
282276
283277 /* Kernel mode? Handle exceptions or die */
284278 if (!user_mode(regs))
....@@ -300,6 +294,7 @@
300294
301295 int offset = pgd_index(address);
302296 pgd_t *pgd, *pgd_k;
297
+ p4d_t *p4d, *p4d_k;
303298 pud_t *pud, *pud_k;
304299 pmd_t *pmd, *pmd_k;
305300 pte_t *pte_k;
....@@ -326,8 +321,13 @@
326321 * it exists.
327322 */
328323
329
- pud = pud_offset(pgd, address);
330
- pud_k = pud_offset(pgd_k, address);
324
+ p4d = p4d_offset(pgd, address);
325
+ p4d_k = p4d_offset(pgd_k, address);
326
+ if (!p4d_present(*p4d_k))
327
+ goto no_context;
328
+
329
+ pud = pud_offset(p4d, address);
330
+ pud_k = pud_offset(p4d_k, address);
331331 if (!pud_present(*pud_k))
332332 goto no_context;
333333