]> Git Repo - linux.git/blob - arch/riscv/mm/fault.c
enetc: Migrate to PHYLINK and PCS_LYNX
[linux.git] / arch / riscv / mm / fault.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
4  *  Lennox Wu <[email protected]>
5  *  Chen Liqin <[email protected]>
6  * Copyright (C) 2012 Regents of the University of California
7  */
8
9
10 #include <linux/mm.h>
11 #include <linux/kernel.h>
12 #include <linux/interrupt.h>
13 #include <linux/perf_event.h>
14 #include <linux/signal.h>
15 #include <linux/uaccess.h>
16
17 #include <asm/ptrace.h>
18 #include <asm/tlbflush.h>
19
20 #include "../kernel/head.h"
21
22 /*
23  * This routine handles page faults.  It determines the address and the
24  * problem, and then passes it off to one of the appropriate routines.
25  */
26 asmlinkage void do_page_fault(struct pt_regs *regs)
27 {
28         struct task_struct *tsk;
29         struct vm_area_struct *vma;
30         struct mm_struct *mm;
31         unsigned long addr, cause;
32         unsigned int flags = FAULT_FLAG_DEFAULT;
33         int code = SEGV_MAPERR;
34         vm_fault_t fault;
35
36         cause = regs->cause;
37         addr = regs->badaddr;
38
39         tsk = current;
40         mm = tsk->mm;
41
42         /*
43          * Fault-in kernel-space virtual memory on-demand.
44          * The 'reference' page table is init_mm.pgd.
45          *
46          * NOTE! We MUST NOT take any locks for this case. We may
47          * be in an interrupt or a critical region, and should
48          * only copy the information from the master page table,
49          * nothing more.
50          */
51         if (unlikely((addr >= VMALLOC_START) && (addr <= VMALLOC_END)))
52                 goto vmalloc_fault;
53
54         /* Enable interrupts if they were enabled in the parent context. */
55         if (likely(regs->status & SR_PIE))
56                 local_irq_enable();
57
58         /*
59          * If we're in an interrupt, have no user context, or are running
60          * in an atomic region, then we must not take the fault.
61          */
62         if (unlikely(faulthandler_disabled() || !mm))
63                 goto no_context;
64
65         if (user_mode(regs))
66                 flags |= FAULT_FLAG_USER;
67
68         perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr);
69
70 retry:
71         mmap_read_lock(mm);
72         vma = find_vma(mm, addr);
73         if (unlikely(!vma))
74                 goto bad_area;
75         if (likely(vma->vm_start <= addr))
76                 goto good_area;
77         if (unlikely(!(vma->vm_flags & VM_GROWSDOWN)))
78                 goto bad_area;
79         if (unlikely(expand_stack(vma, addr)))
80                 goto bad_area;
81
82         /*
83          * Ok, we have a good vm_area for this memory access, so
84          * we can handle it.
85          */
86 good_area:
87         code = SEGV_ACCERR;
88
89         switch (cause) {
90         case EXC_INST_PAGE_FAULT:
91                 if (!(vma->vm_flags & VM_EXEC))
92                         goto bad_area;
93                 break;
94         case EXC_LOAD_PAGE_FAULT:
95                 if (!(vma->vm_flags & VM_READ))
96                         goto bad_area;
97                 break;
98         case EXC_STORE_PAGE_FAULT:
99                 if (!(vma->vm_flags & VM_WRITE))
100                         goto bad_area;
101                 flags |= FAULT_FLAG_WRITE;
102                 break;
103         default:
104                 panic("%s: unhandled cause %lu", __func__, cause);
105         }
106
107         /*
108          * If for any reason at all we could not handle the fault,
109          * make sure we exit gracefully rather than endlessly redo
110          * the fault.
111          */
112         fault = handle_mm_fault(vma, addr, flags, regs);
113
114         /*
115          * If we need to retry but a fatal signal is pending, handle the
116          * signal first. We do not need to release the mmap_lock because it
117          * would already be released in __lock_page_or_retry in mm/filemap.c.
118          */
119         if (fault_signal_pending(fault, regs))
120                 return;
121
122         if (unlikely(fault & VM_FAULT_ERROR)) {
123                 if (fault & VM_FAULT_OOM)
124                         goto out_of_memory;
125                 else if (fault & VM_FAULT_SIGBUS)
126                         goto do_sigbus;
127                 BUG();
128         }
129
130         if (flags & FAULT_FLAG_ALLOW_RETRY) {
131                 if (fault & VM_FAULT_RETRY) {
132                         flags |= FAULT_FLAG_TRIED;
133
134                         /*
135                          * No need to mmap_read_unlock(mm) as we would
136                          * have already released it in __lock_page_or_retry
137                          * in mm/filemap.c.
138                          */
139                         goto retry;
140                 }
141         }
142
143         mmap_read_unlock(mm);
144         return;
145
146         /*
147          * Something tried to access memory that isn't in our memory map.
148          * Fix it, but check if it's kernel or user first.
149          */
150 bad_area:
151         mmap_read_unlock(mm);
152         /* User mode accesses just cause a SIGSEGV */
153         if (user_mode(regs)) {
154                 do_trap(regs, SIGSEGV, code, addr);
155                 return;
156         }
157
158 no_context:
159         /* Are we prepared to handle this kernel fault? */
160         if (fixup_exception(regs))
161                 return;
162
163         /*
164          * Oops. The kernel tried to access some bad page. We'll have to
165          * terminate things with extreme prejudice.
166          */
167         bust_spinlocks(1);
168         pr_alert("Unable to handle kernel %s at virtual address " REG_FMT "\n",
169                 (addr < PAGE_SIZE) ? "NULL pointer dereference" :
170                 "paging request", addr);
171         die(regs, "Oops");
172         do_exit(SIGKILL);
173
174         /*
175          * We ran out of memory, call the OOM killer, and return the userspace
176          * (which will retry the fault, or kill us if we got oom-killed).
177          */
178 out_of_memory:
179         mmap_read_unlock(mm);
180         if (!user_mode(regs))
181                 goto no_context;
182         pagefault_out_of_memory();
183         return;
184
185 do_sigbus:
186         mmap_read_unlock(mm);
187         /* Kernel mode? Handle exceptions or die */
188         if (!user_mode(regs))
189                 goto no_context;
190         do_trap(regs, SIGBUS, BUS_ADRERR, addr);
191         return;
192
193 vmalloc_fault:
194         {
195                 pgd_t *pgd, *pgd_k;
196                 pud_t *pud, *pud_k;
197                 p4d_t *p4d, *p4d_k;
198                 pmd_t *pmd, *pmd_k;
199                 pte_t *pte_k;
200                 int index;
201
202                 /* User mode accesses just cause a SIGSEGV */
203                 if (user_mode(regs))
204                         return do_trap(regs, SIGSEGV, code, addr);
205
206                 /*
207                  * Synchronize this task's top level page-table
208                  * with the 'reference' page table.
209                  *
210                  * Do _not_ use "tsk->active_mm->pgd" here.
211                  * We might be inside an interrupt in the middle
212                  * of a task switch.
213                  */
214                 index = pgd_index(addr);
215                 pgd = (pgd_t *)pfn_to_virt(csr_read(CSR_SATP)) + index;
216                 pgd_k = init_mm.pgd + index;
217
218                 if (!pgd_present(*pgd_k))
219                         goto no_context;
220                 set_pgd(pgd, *pgd_k);
221
222                 p4d = p4d_offset(pgd, addr);
223                 p4d_k = p4d_offset(pgd_k, addr);
224                 if (!p4d_present(*p4d_k))
225                         goto no_context;
226
227                 pud = pud_offset(p4d, addr);
228                 pud_k = pud_offset(p4d_k, addr);
229                 if (!pud_present(*pud_k))
230                         goto no_context;
231
232                 /*
233                  * Since the vmalloc area is global, it is unnecessary
234                  * to copy individual PTEs
235                  */
236                 pmd = pmd_offset(pud, addr);
237                 pmd_k = pmd_offset(pud_k, addr);
238                 if (!pmd_present(*pmd_k))
239                         goto no_context;
240                 set_pmd(pmd, *pmd_k);
241
242                 /*
243                  * Make sure the actual PTE exists as well to
244                  * catch kernel vmalloc-area accesses to non-mapped
245                  * addresses. If we don't do this, this will just
246                  * silently loop forever.
247                  */
248                 pte_k = pte_offset_kernel(pmd_k, addr);
249                 if (!pte_present(*pte_k))
250                         goto no_context;
251
252                 /*
253                  * The kernel assumes that TLBs don't cache invalid
254                  * entries, but in RISC-V, SFENCE.VMA specifies an
255                  * ordering constraint, not a cache flush; it is
256                  * necessary even after writing invalid entries.
257                  */
258                 local_flush_tlb_page(addr);
259
260                 return;
261         }
262 }
This page took 0.066126 seconds and 4 git commands to generate.