| @@ -22,61 +22,58 @@ | | | @@ -22,61 +22,58 @@ |
22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 22 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 23 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 26 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
27 | * POSSIBILITY OF SUCH DAMAGE. | | 27 | * POSSIBILITY OF SUCH DAMAGE. |
28 | */ | | 28 | */ |
29 | | | 29 | |
30 | #include <sys/cdefs.h> | | 30 | #include <sys/cdefs.h> |
31 | | | 31 | |
32 | #define __PMAP_PRIVATE | | 32 | #define __PMAP_PRIVATE |
33 | #define __UFETCHSTORE_PRIVATE | | 33 | #define __UFETCHSTORE_PRIVATE |
34 | | | 34 | |
35 | __RCSID("$NetBSD: trap.c,v 1.9 2020/11/01 21:06:22 skrll Exp $"); | | 35 | __RCSID("$NetBSD: trap.c,v 1.10 2020/11/01 21:09:48 skrll Exp $"); |
36 | | | 36 | |
37 | #include <sys/param.h> | | 37 | #include <sys/param.h> |
38 | #include <sys/systm.h> | | 38 | #include <sys/systm.h> |
39 | #include <sys/atomic.h> | | 39 | #include <sys/atomic.h> |
40 | | | 40 | |
41 | #include <sys/signal.h> | | 41 | #include <sys/signal.h> |
42 | #include <sys/signalvar.h> | | 42 | #include <sys/signalvar.h> |
43 | #include <sys/siginfo.h> | | 43 | #include <sys/siginfo.h> |
44 | | | 44 | |
45 | #include <uvm/uvm.h> | | 45 | #include <uvm/uvm.h> |
46 | | | 46 | |
47 | #include <riscv/locore.h> | | 47 | #include <riscv/locore.h> |
48 | | | 48 | |
49 | #define INSTRUCTION_TRAP_MASK (__BIT(CAUSE_PRIVILEGED_INSTRUCTION) \ | | 49 | #define INSTRUCTION_TRAP_MASK (__BIT(CAUSE_ILLEGAL_INSTRUCTION)) |
50 | |__BIT(CAUSE_ILLEGAL_INSTRUCTION)) | | | |
51 | | | 50 | |
52 | #define FAULT_TRAP_MASK (__BIT(CAUSE_FAULT_FETCH) \ | | 51 | #define FAULT_TRAP_MASK (__BIT(CAUSE_FETCH_ACCESS) \ |
53 | |__BIT(CAUSE_FAULT_LOAD) \ | | 52 | |__BIT(CAUSE_LOAD_ACCESS) \ |
54 | |__BIT(CAUSE_FAULT_STORE)) | | 53 | |__BIT(CAUSE_STORE_ACCESS)) |
55 | | | 54 | |
56 | #define MISALIGNED_TRAP_MASK (__BIT(CAUSE_MISALIGNED_FETCH) \ | | 55 | #define MISALIGNED_TRAP_MASK (__BIT(CAUSE_FETCH_MISALIGNED) \ |
57 | |__BIT(CAUSE_MISALIGNED_LOAD) \ | | 56 | |__BIT(CAUSE_LOAD_MISALIGNED) \ |
58 | |__BIT(CAUSE_MISALIGNED_STORE)) | | 57 | |__BIT(CAUSE_STORE_MISALIGNED)) |
59 | | | 58 | |
60 | static const char * const causenames[] = { | | 59 | static const char * const causenames[] = { |
61 | [CAUSE_MISALIGNED_FETCH] = "misaligned fetch", | | 60 | [CAUSE_FETCH_MISALIGNED] = "misaligned fetch", |
62 | [CAUSE_MISALIGNED_LOAD] = "misaligned load", | | 61 | [CAUSE_LOAD_MISALIGNED] = "misaligned load", |
63 | [CAUSE_MISALIGNED_STORE] = "misaligned store", | | 62 | [CAUSE_STORE_MISALIGNED] = "misaligned store", |
64 | [CAUSE_FAULT_FETCH] = "fetch", | | 63 | [CAUSE_FETCH_ACCESS] = "fetch", |
65 | [CAUSE_FAULT_LOAD] = "load", | | 64 | [CAUSE_LOAD_ACCESS] = "load", |
66 | [CAUSE_FAULT_STORE] = "store", | | 65 | [CAUSE_STORE_ACCESS] = "store", |
67 | [CAUSE_FP_DISABLED] = "fp disabled", | | | |
68 | [CAUSE_ILLEGAL_INSTRUCTION] = "illegal instruction", | | 66 | [CAUSE_ILLEGAL_INSTRUCTION] = "illegal instruction", |
69 | [CAUSE_PRIVILEGED_INSTRUCTION] = "privileged instruction", | | | |
70 | [CAUSE_BREAKPOINT] = "breakpoint", | | 67 | [CAUSE_BREAKPOINT] = "breakpoint", |
71 | }; | | 68 | }; |
72 | | | 69 | |
73 | void | | 70 | void |
74 | cpu_jump_onfault(struct trapframe *tf, const struct faultbuf *fb) | | 71 | cpu_jump_onfault(struct trapframe *tf, const struct faultbuf *fb) |
75 | { | | 72 | { |
76 | tf->tf_a0 = fb->fb_reg[FB_A0]; | | 73 | tf->tf_a0 = fb->fb_reg[FB_A0]; |
77 | tf->tf_ra = fb->fb_reg[FB_RA]; | | 74 | tf->tf_ra = fb->fb_reg[FB_RA]; |
78 | tf->tf_s0 = fb->fb_reg[FB_S0]; | | 75 | tf->tf_s0 = fb->fb_reg[FB_S0]; |
79 | tf->tf_s1 = fb->fb_reg[FB_S1]; | | 76 | tf->tf_s1 = fb->fb_reg[FB_S1]; |
80 | tf->tf_s2 = fb->fb_reg[FB_S2]; | | 77 | tf->tf_s2 = fb->fb_reg[FB_S2]; |
81 | tf->tf_s3 = fb->fb_reg[FB_S3]; | | 78 | tf->tf_s3 = fb->fb_reg[FB_S3]; |
82 | tf->tf_s4 = fb->fb_reg[FB_S4]; | | 79 | tf->tf_s4 = fb->fb_reg[FB_S4]; |
| @@ -210,31 +207,31 @@ trap_ksi_init(ksiginfo_t *ksi, int signo | | | @@ -210,31 +207,31 @@ trap_ksi_init(ksiginfo_t *ksi, int signo |
210 | | | 207 | |
211 | static void | | 208 | static void |
212 | cpu_trapsignal(struct trapframe *tf, ksiginfo_t *ksi) | | 209 | cpu_trapsignal(struct trapframe *tf, ksiginfo_t *ksi) |
213 | { | | 210 | { |
214 | if (cpu_printfataltraps) { | | 211 | if (cpu_printfataltraps) { |
215 | dump_trapframe(tf, printf); | | 212 | dump_trapframe(tf, printf); |
216 | } | | 213 | } |
217 | (*curlwp->l_proc->p_emul->e_trapsignal)(curlwp, ksi); | | 214 | (*curlwp->l_proc->p_emul->e_trapsignal)(curlwp, ksi); |
218 | } | | 215 | } |
219 | | | 216 | |
220 | static inline vm_prot_t | | 217 | static inline vm_prot_t |
221 | get_faulttype(register_t cause) | | 218 | get_faulttype(register_t cause) |
222 | { | | 219 | { |
223 | if (cause == CAUSE_FAULT_LOAD) | | 220 | if (cause == CAUSE_LOAD_ACCESS) |
224 | return VM_PROT_READ; | | 221 | return VM_PROT_READ; |
225 | if (cause == CAUSE_FAULT_STORE) | | 222 | if (cause == CAUSE_STORE_ACCESS) |
226 | return VM_PROT_READ | VM_PROT_WRITE; | | 223 | return VM_PROT_READ | VM_PROT_WRITE; |
227 | KASSERT(cause == CAUSE_FAULT_FETCH); | | 224 | KASSERT(cause == CAUSE_FETCH_ACCESS); |
228 | return VM_PROT_READ | VM_PROT_EXECUTE; | | 225 | return VM_PROT_READ | VM_PROT_EXECUTE; |
229 | } | | 226 | } |
230 | | | 227 | |
231 | static bool | | 228 | static bool |
232 | trap_pagefault_fixup(struct trapframe *tf, struct pmap *pmap, register_t cause, | | 229 | trap_pagefault_fixup(struct trapframe *tf, struct pmap *pmap, register_t cause, |
233 | intptr_t addr) | | 230 | intptr_t addr) |
234 | { | | 231 | { |
235 | pt_entry_t * const ptep = pmap_pte_lookup(pmap, addr); | | 232 | pt_entry_t * const ptep = pmap_pte_lookup(pmap, addr); |
236 | struct vm_page *pg; | | 233 | struct vm_page *pg; |
237 | | | 234 | |
238 | if (ptep == NULL) | | 235 | if (ptep == NULL) |
239 | return false; | | 236 | return false; |
240 | | | 237 | |
| @@ -246,32 +243,32 @@ trap_pagefault_fixup(struct trapframe *t | | | @@ -246,32 +243,32 @@ trap_pagefault_fixup(struct trapframe *t |
246 | return false; | | 243 | return false; |
247 | | | 244 | |
248 | pg = PHYS_TO_VM_PAGE(pte_to_paddr(opte)); | | 245 | pg = PHYS_TO_VM_PAGE(pte_to_paddr(opte)); |
249 | if (pg == NULL) | | 246 | if (pg == NULL) |
250 | return false; | | 247 | return false; |
251 | | | 248 | |
252 | attr = 0; | | 249 | attr = 0; |
253 | npte = opte; | | 250 | npte = opte; |
254 | if ((npte & PTE_V) == 0) { | | 251 | if ((npte & PTE_V) == 0) { |
255 | npte |= PTE_V; | | 252 | npte |= PTE_V; |
256 | attr |= VM_PAGEMD_REFERENCED; | | 253 | attr |= VM_PAGEMD_REFERENCED; |
257 | } | | 254 | } |
258 | #if 0 /* XXX Outdated */ | | 255 | #if 0 /* XXX Outdated */ |
259 | if (cause == CAUSE_FAULT_STORE) { | | 256 | if (cause == CAUSE_STORE_ACCESS) { |
260 | if ((npte & PTE_NW) != 0) { | | 257 | if ((npte & PTE_NW) != 0) { |
261 | npte &= ~PTE_NW; | | 258 | npte &= ~PTE_NW; |
262 | attr |= VM_PAGEMD_MODIFIED; | | 259 | attr |= VM_PAGEMD_MODIFIED; |
263 | } | | 260 | } |
264 | } else if (cause == CAUSE_FAULT_FETCH) { | | 261 | } else if (cause == CAUSE_FETCH_ACCESS) { |
265 | if ((npte & PTE_NX) != 0) { | | 262 | if ((npte & PTE_NX) != 0) { |
266 | npte &= ~PTE_NX; | | 263 | npte &= ~PTE_NX; |
267 | attr |= VM_PAGEMD_EXECPAGE; | | 264 | attr |= VM_PAGEMD_EXECPAGE; |
268 | } | | 265 | } |
269 | } | | 266 | } |
270 | #endif | | 267 | #endif |
271 | if (attr == 0) | | 268 | if (attr == 0) |
272 | return false; | | 269 | return false; |
273 | | | 270 | |
274 | } while (opte != atomic_cas_pte(ptep, opte, npte)); | | 271 | } while (opte != atomic_cas_pte(ptep, opte, npte)); |
275 | | | 272 | |
276 | pmap_page_set_attributes(VM_PAGE_TO_MD(pg), attr); | | 273 | pmap_page_set_attributes(VM_PAGE_TO_MD(pg), attr); |
277 | pmap_tlb_update_addr(pmap, addr, npte, 0); | | 274 | pmap_tlb_update_addr(pmap, addr, npte, 0); |
| @@ -339,29 +336,28 @@ trap_pagefault(struct trapframe *tf, reg | | | @@ -339,29 +336,28 @@ trap_pagefault(struct trapframe *tf, reg |
339 | | | 336 | |
340 | if (fb == NULL) { | | 337 | if (fb == NULL) { |
341 | return false; | | 338 | return false; |
342 | } | | 339 | } |
343 | | | 340 | |
344 | cpu_jump_onfault(tf, fb); | | 341 | cpu_jump_onfault(tf, fb); |
345 | return true; | | 342 | return true; |
346 | } | | 343 | } |
347 | | | 344 | |
348 | static bool | | 345 | static bool |
349 | trap_instruction(struct trapframe *tf, register_t epc, register_t status, | | 346 | trap_instruction(struct trapframe *tf, register_t epc, register_t status, |
350 | register_t cause, register_t badaddr, bool usertrap_p, ksiginfo_t *ksi) | | 347 | register_t cause, register_t badaddr, bool usertrap_p, ksiginfo_t *ksi) |
351 | { | | 348 | { |
352 | const bool prvopc_p = (cause == CAUSE_PRIVILEGED_INSTRUCTION); | | | |
353 | if (usertrap_p) { | | 349 | if (usertrap_p) { |
354 | trap_ksi_init(ksi, SIGILL, prvopc_p ? ILL_PRVOPC : ILL_ILLOPC, | | 350 | trap_ksi_init(ksi, SIGILL, ILL_ILLOPC, |
355 | (intptr_t)badaddr, cause); | | 351 | (intptr_t)badaddr, cause); |
356 | } | | 352 | } |
357 | return false; | | 353 | return false; |
358 | } | | 354 | } |
359 | | | 355 | |
360 | static bool | | 356 | static bool |
361 | trap_misalignment(struct trapframe *tf, register_t epc, register_t status, | | 357 | trap_misalignment(struct trapframe *tf, register_t epc, register_t status, |
362 | register_t cause, register_t badaddr, bool usertrap_p, ksiginfo_t *ksi) | | 358 | register_t cause, register_t badaddr, bool usertrap_p, ksiginfo_t *ksi) |
363 | { | | 359 | { |
364 | if (usertrap_p) { | | 360 | if (usertrap_p) { |
365 | trap_ksi_init(ksi, SIGBUS, BUS_ADRALN, | | 361 | trap_ksi_init(ksi, SIGBUS, BUS_ADRALN, |
366 | (intptr_t)badaddr, cause); | | 362 | (intptr_t)badaddr, cause); |
367 | } | | 363 | } |
| @@ -385,32 +381,34 @@ cpu_trap(struct trapframe *tf, register_ | | | @@ -385,32 +381,34 @@ cpu_trap(struct trapframe *tf, register_ |
385 | // about it. See | | 381 | // about it. See |
386 | struct pmap * const pmap = curlwp->l_proc->p_vmspace->vm_map.pmap; | | 382 | struct pmap * const pmap = curlwp->l_proc->p_vmspace->vm_map.pmap; |
387 | if ((intptr_t) addr < 0 | | 383 | if ((intptr_t) addr < 0 |
388 | && pmap != pmap_kernel() | | 384 | && pmap != pmap_kernel() |
389 | && pmap_pdetab_fixup(pmap, addr)) { | | 385 | && pmap_pdetab_fixup(pmap, addr)) { |
390 | return; | | 386 | return; |
391 | } | | 387 | } |
392 | #endif | | 388 | #endif |
393 | ok = trap_pagefault(tf, epc, status, cause, addr, | | 389 | ok = trap_pagefault(tf, epc, status, cause, addr, |
394 | usertrap_p, &ksi); | | 390 | usertrap_p, &ksi); |
395 | } else if (fault_mask & INSTRUCTION_TRAP_MASK) { | | 391 | } else if (fault_mask & INSTRUCTION_TRAP_MASK) { |
396 | ok = trap_instruction(tf, epc, status, cause, addr, | | 392 | ok = trap_instruction(tf, epc, status, cause, addr, |
397 | usertrap_p, &ksi); | | 393 | usertrap_p, &ksi); |
| | | 394 | #if 0 |
398 | } else if (fault_mask && __BIT(CAUSE_FP_DISABLED)) { | | 395 | } else if (fault_mask && __BIT(CAUSE_FP_DISABLED)) { |
399 | if (!usertrap_p) { | | 396 | if (!usertrap_p) { |
400 | panic("%s: fp used @ %#"PRIxREGISTER" in kernel!", | | 397 | panic("%s: fp used @ %#"PRIxREGISTER" in kernel!", |
401 | __func__, tf->tf_pc); | | 398 | __func__, tf->tf_pc); |
402 | } | | 399 | } |
403 | fpu_load(); | | 400 | fpu_load(); |
| | | 401 | #endif |
404 | } else if (fault_mask & MISALIGNED_TRAP_MASK) { | | 402 | } else if (fault_mask & MISALIGNED_TRAP_MASK) { |
405 | ok = trap_misalignment(tf, epc, status, cause, addr, | | 403 | ok = trap_misalignment(tf, epc, status, cause, addr, |
406 | usertrap_p, &ksi); | | 404 | usertrap_p, &ksi); |
407 | } else { | | 405 | } else { |
408 | dump_trapframe(tf, printf); | | 406 | dump_trapframe(tf, printf); |
409 | panic("%s: unknown kernel trap", __func__); | | 407 | panic("%s: unknown kernel trap", __func__); |
410 | } | | 408 | } |
411 | | | 409 | |
412 | if (usertrap_p) { | | 410 | if (usertrap_p) { |
413 | if (!ok) | | 411 | if (!ok) |
414 | cpu_trapsignal(tf, &ksi); | | 412 | cpu_trapsignal(tf, &ksi); |
415 | userret(curlwp); | | 413 | userret(curlwp); |
416 | } else if (!ok) { | | 414 | } else if (!ok) { |