]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/sparc64/sparc64/trap.c
MFV r337193:
[FreeBSD/FreeBSD.git] / sys / sparc64 / sparc64 / trap.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 2001, Jake Burkholder
5  * Copyright (C) 1994, David Greenman
6  * Copyright (c) 1990, 1993
7  *      The Regents of the University of California.  All rights reserved.
8  *
9  * This code is derived from software contributed to Berkeley by
10  * the University of Utah, and William Jolitz.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  * 3. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  *      from: @(#)trap.c        7.4 (Berkeley) 5/13/91
37  *      from: FreeBSD: src/sys/i386/i386/trap.c,v 1.197 2001/07/19
38  */
39
40 #include <sys/cdefs.h>
41 __FBSDID("$FreeBSD$");
42
43 #include "opt_ddb.h"
44 #include "opt_ktr.h"
45
46 #include <sys/param.h>
47 #include <sys/kdb.h>
48 #include <sys/kernel.h>
49 #include <sys/bus.h>
50 #include <sys/interrupt.h>
51 #include <sys/ktr.h>
52 #include <sys/lock.h>
53 #include <sys/mutex.h>
54 #include <sys/systm.h>
55 #include <sys/pcpu.h>
56 #include <sys/pioctl.h>
57 #include <sys/ptrace.h>
58 #include <sys/proc.h>
59 #include <sys/smp.h>
60 #include <sys/signalvar.h>
61 #include <sys/syscall.h>
62 #include <sys/sysctl.h>
63 #include <sys/sysent.h>
64 #include <sys/vmmeter.h>
65 #include <security/audit/audit.h>
66
67 #include <dev/ofw/openfirm.h>
68
69 #include <vm/vm.h>
70 #include <vm/pmap.h>
71 #include <vm/vm_extern.h>
72 #include <vm/vm_param.h>
73 #include <vm/vm_kern.h>
74 #include <vm/vm_map.h>
75 #include <vm/vm_page.h>
76
77 #include <machine/cpu.h>
78 #include <machine/frame.h>
79 #include <machine/intr_machdep.h>
80 #include <machine/ofw_machdep.h>
81 #include <machine/pcb.h>
82 #include <machine/smp.h>
83 #include <machine/trap.h>
84 #include <machine/tstate.h>
85 #include <machine/tte.h>
86 #include <machine/tlb.h>
87 #include <machine/tsb.h>
88 #include <machine/watch.h>
89
90 void trap(struct trapframe *tf);
91 void syscall(struct trapframe *tf);
92
93 static int trap_cecc(void);
94 static int trap_pfault(struct thread *td, struct trapframe *tf);
95
96 extern char copy_fault[];
97 extern char copy_nofault_begin[];
98 extern char copy_nofault_end[];
99
100 extern char fs_fault[];
101 extern char fs_nofault_begin[];
102 extern char fs_nofault_end[];
103
104 extern char fas_fault[];
105 extern char fas_nofault_begin[];
106 extern char fas_nofault_end[];
107
108 const char *const trap_msg[] = {
109         "reserved",
110         "instruction access exception",
111         "instruction access error",
112         "instruction access protection",
113         "illtrap instruction",
114         "illegal instruction",
115         "privileged opcode",
116         "floating point disabled",
117         "floating point exception ieee 754",
118         "floating point exception other",
119         "tag overflow",
120         "division by zero",
121         "data access exception",
122         "data access error",
123         "data access protection",
124         "memory address not aligned",
125         "privileged action",
126         "async data error",
127         "trap instruction 16",
128         "trap instruction 17",
129         "trap instruction 18",
130         "trap instruction 19",
131         "trap instruction 20",
132         "trap instruction 21",
133         "trap instruction 22",
134         "trap instruction 23",
135         "trap instruction 24",
136         "trap instruction 25",
137         "trap instruction 26",
138         "trap instruction 27",
139         "trap instruction 28",
140         "trap instruction 29",
141         "trap instruction 30",
142         "trap instruction 31",
143         "fast instruction access mmu miss",
144         "fast data access mmu miss",
145         "interrupt",
146         "physical address watchpoint",
147         "virtual address watchpoint",
148         "corrected ecc error",
149         "spill",
150         "fill",
151         "fill",
152         "breakpoint",
153         "clean window",
154         "range check",
155         "fix alignment",
156         "integer overflow",
157         "syscall",
158         "restore physical watchpoint",
159         "restore virtual watchpoint",
160         "kernel stack fault",
161 };
162
163 static const int trap_sig[] = {
164         SIGILL,                 /* reserved */
165         SIGILL,                 /* instruction access exception */
166         SIGILL,                 /* instruction access error */
167         SIGILL,                 /* instruction access protection */
168         SIGILL,                 /* illtrap instruction */
169         SIGILL,                 /* illegal instruction */
170         SIGBUS,                 /* privileged opcode */
171         SIGFPE,                 /* floating point disabled */
172         SIGFPE,                 /* floating point exception ieee 754 */
173         SIGFPE,                 /* floating point exception other */
174         SIGEMT,                 /* tag overflow */
175         SIGFPE,                 /* division by zero */
176         SIGILL,                 /* data access exception */
177         SIGILL,                 /* data access error */
178         SIGBUS,                 /* data access protection */
179         SIGBUS,                 /* memory address not aligned */
180         SIGBUS,                 /* privileged action */
181         SIGBUS,                 /* async data error */
182         SIGILL,                 /* trap instruction 16 */
183         SIGILL,                 /* trap instruction 17 */
184         SIGILL,                 /* trap instruction 18 */
185         SIGILL,                 /* trap instruction 19 */
186         SIGILL,                 /* trap instruction 20 */
187         SIGILL,                 /* trap instruction 21 */
188         SIGILL,                 /* trap instruction 22 */
189         SIGILL,                 /* trap instruction 23 */
190         SIGILL,                 /* trap instruction 24 */
191         SIGILL,                 /* trap instruction 25 */
192         SIGILL,                 /* trap instruction 26 */
193         SIGILL,                 /* trap instruction 27 */
194         SIGILL,                 /* trap instruction 28 */
195         SIGILL,                 /* trap instruction 29 */
196         SIGILL,                 /* trap instruction 30 */
197         SIGILL,                 /* trap instruction 31 */
198         SIGSEGV,                /* fast instruction access mmu miss */
199         SIGSEGV,                /* fast data access mmu miss */
200         -1,                     /* interrupt */
201         -1,                     /* physical address watchpoint */
202         -1,                     /* virtual address watchpoint */
203         -1,                     /* corrected ecc error */
204         SIGILL,                 /* spill */
205         SIGILL,                 /* fill */
206         SIGILL,                 /* fill */
207         SIGTRAP,                /* breakpoint */
208         SIGILL,                 /* clean window */
209         SIGILL,                 /* range check */
210         SIGILL,                 /* fix alignment */
211         SIGILL,                 /* integer overflow */
212         SIGSYS,                 /* syscall */
213         -1,                     /* restore physical watchpoint */
214         -1,                     /* restore virtual watchpoint */
215         -1,                     /* kernel stack fault */
216 };
217
218 CTASSERT(nitems(trap_msg) == T_MAX);
219 CTASSERT(nitems(trap_sig) == T_MAX);
220
221 CTASSERT(sizeof(struct trapframe) == 256);
222
223 int debugger_on_signal = 0;
224 SYSCTL_INT(_debug, OID_AUTO, debugger_on_signal, CTLFLAG_RW,
225     &debugger_on_signal, 0, "");
226
227 u_int corrected_ecc = 0;
228 SYSCTL_UINT(_machdep, OID_AUTO, corrected_ecc, CTLFLAG_RD, &corrected_ecc, 0,
229     "corrected ECC errors");
230
231 /*
232  * SUNW,set-trap-table allows to take over %tba from the PROM, which
233  * will turn off interrupts and handle outstanding ones while doing so,
234  * in a safe way.
235  */
236 void
237 sun4u_set_traptable(void *tba_addr)
238 {
239         static struct {
240                 cell_t name;
241                 cell_t nargs;
242                 cell_t nreturns;
243                 cell_t tba_addr;
244         } args = {
245                 (cell_t)"SUNW,set-trap-table",
246                 1,
247                 0,
248         };
249
250         args.tba_addr = (cell_t)tba_addr;
251         ofw_entry(&args);
252 }
253
254 void
255 trap(struct trapframe *tf)
256 {
257         struct thread *td;
258         struct proc *p;
259         int error;
260         int sig, ucode;
261         register_t addr;
262         ksiginfo_t ksi;
263
264         td = curthread;
265
266         CTR4(KTR_TRAP, "trap: %p type=%s (%s) pil=%#lx", td,
267             trap_msg[tf->tf_type & ~T_KERNEL],
268             (TRAPF_USERMODE(tf) ? "user" : "kernel"), rdpr(pil));
269
270         VM_CNT_INC(v_trap);
271
272         if ((tf->tf_tstate & TSTATE_PRIV) == 0) {
273                 KASSERT(td != NULL, ("trap: curthread NULL"));
274                 KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
275
276                 p = td->td_proc;
277                 td->td_pticks = 0;
278                 td->td_frame = tf;
279                 addr = tf->tf_tpc;
280                 ucode = (int)tf->tf_type; /* XXX not POSIX */
281                 if (td->td_cowgen != p->p_cowgen)
282                         thread_cow_update(td);
283
284                 switch (tf->tf_type) {
285                 case T_DATA_MISS:
286                 case T_DATA_PROTECTION:
287                         addr = tf->tf_sfar;
288                         /* FALLTHROUGH */
289                 case T_INSTRUCTION_MISS:
290                         sig = trap_pfault(td, tf);
291                         break;
292                 case T_FILL:
293                         sig = rwindow_load(td, tf, 2);
294                         break;
295                 case T_FILL_RET:
296                         sig = rwindow_load(td, tf, 1);
297                         break;
298                 case T_SPILL:
299                         sig = rwindow_save(td);
300                         break;
301                 case T_CORRECTED_ECC_ERROR:
302                         sig = trap_cecc();
303                         break;
304                 case T_BREAKPOINT:
305                         sig = SIGTRAP;
306                         ucode = TRAP_BRKPT;
307                         break;
308                 default:
309                         if (tf->tf_type > T_MAX)
310                                 panic("trap: bad trap type %#lx (user)",
311                                     tf->tf_type);
312                         else if (trap_sig[tf->tf_type] == -1)
313                                 panic("trap: %s (user)",
314                                     trap_msg[tf->tf_type]);
315                         sig = trap_sig[tf->tf_type];
316                         break;
317                 }
318
319                 if (sig != 0) {
320                         /* Translate fault for emulators. */
321                         if (p->p_sysent->sv_transtrap != NULL) {
322                                 sig = p->p_sysent->sv_transtrap(sig,
323                                     tf->tf_type);
324                         }
325                         if (debugger_on_signal &&
326                             (sig == 4 || sig == 10 || sig == 11))
327                                 kdb_enter(KDB_WHY_TRAPSIG, "trapsig");
328                         ksiginfo_init_trap(&ksi);
329                         ksi.ksi_signo = sig;
330                         ksi.ksi_code = ucode;
331                         ksi.ksi_addr = (void *)addr;
332                         ksi.ksi_trapno = (int)tf->tf_type;
333                         trapsignal(td, &ksi);
334                 }
335
336                 userret(td, tf);
337         } else {
338                 KASSERT((tf->tf_type & T_KERNEL) != 0,
339                     ("trap: kernel trap isn't"));
340
341                 if (kdb_active) {
342                         kdb_reenter();
343                         return;
344                 }
345
346                 switch (tf->tf_type & ~T_KERNEL) {
347                 case T_BREAKPOINT:
348                 case T_KSTACK_FAULT:
349                         error = (kdb_trap(tf->tf_type, 0, tf) == 0);
350                         TF_DONE(tf);
351                         break;
352 #ifdef notyet
353                 case T_PA_WATCHPOINT:
354                 case T_VA_WATCHPOINT:
355                         error = db_watch_trap(tf);
356                         break;
357 #endif
358                 case T_DATA_MISS:
359                 case T_DATA_PROTECTION:
360                 case T_INSTRUCTION_MISS:
361                         error = trap_pfault(td, tf);
362                         break;
363                 case T_DATA_EXCEPTION:
364                 case T_MEM_ADDRESS_NOT_ALIGNED:
365                         if ((tf->tf_sfsr & MMU_SFSR_FV) != 0 &&
366                             MMU_SFSR_GET_ASI(tf->tf_sfsr) == ASI_AIUP) {
367                                 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
368                                     tf->tf_tpc <= (u_long)copy_nofault_end) {
369                                         tf->tf_tpc = (u_long)copy_fault;
370                                         tf->tf_tnpc = tf->tf_tpc + 4;
371                                         error = 0;
372                                         break;
373                                 }
374                                 if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
375                                     tf->tf_tpc <= (u_long)fs_nofault_end) {
376                                         tf->tf_tpc = (u_long)fs_fault;
377                                         tf->tf_tnpc = tf->tf_tpc + 4;
378                                         error = 0;
379                                         break;
380                                 }
381                         }
382                         error = 1;
383                         break;
384                 case T_DATA_ERROR:
385                         /*
386                          * Handle PCI poke/peek as per UltraSPARC IIi
387                          * User's Manual 16.2.1, modulo checking the
388                          * TPC as USIII CPUs generate a precise trap
389                          * instead of a special deferred one.
390                          */
391                         if (tf->tf_tpc > (u_long)fas_nofault_begin &&
392                             tf->tf_tpc < (u_long)fas_nofault_end) {
393                                 cache_flush();
394                                 cache_enable(PCPU_GET(impl));
395                                 tf->tf_tpc = (u_long)fas_fault;
396                                 tf->tf_tnpc = tf->tf_tpc + 4;
397                                 error = 0;
398                                 break;
399                         }
400                         error = 1;
401                         break;
402                 case T_CORRECTED_ECC_ERROR:
403                         error = trap_cecc();
404                         break;
405                 default:
406                         error = 1;
407                         break;
408                 }
409
410                 if (error != 0) {
411                         tf->tf_type &= ~T_KERNEL;
412                         if (tf->tf_type > T_MAX)
413                                 panic("trap: bad trap type %#lx (kernel)",
414                                     tf->tf_type);
415                         panic("trap: %s (kernel)", trap_msg[tf->tf_type]);
416                 }
417         }
418         CTR1(KTR_TRAP, "trap: td=%p return", td);
419 }
420
421 static int
422 trap_cecc(void)
423 {
424         u_long eee;
425
426         /*
427          * Turn off (non-)correctable error reporting while we're dealing
428          * with the error.
429          */
430         eee = ldxa(0, ASI_ESTATE_ERROR_EN_REG);
431         stxa_sync(0, ASI_ESTATE_ERROR_EN_REG, eee & ~(AA_ESTATE_NCEEN |
432             AA_ESTATE_CEEN));
433         /* Flush the caches in order ensure no corrupt data got installed. */
434         cache_flush();
435         /* Ensure the caches are still turned on (should be). */
436         cache_enable(PCPU_GET(impl));
437         /* Clear the error from the AFSR. */
438         stxa_sync(0, ASI_AFSR, ldxa(0, ASI_AFSR));
439         corrected_ecc++;
440         printf("corrected ECC error\n");
441         /* Turn (non-)correctable error reporting back on. */
442         stxa_sync(0, ASI_ESTATE_ERROR_EN_REG, eee);
443         return (0);
444 }
445
446 static int
447 trap_pfault(struct thread *td, struct trapframe *tf)
448 {
449         vm_map_t map;
450         struct proc *p;
451         vm_offset_t va;
452         vm_prot_t prot;
453         vm_map_entry_t entry;
454         u_long ctx;
455         int type;
456         int rv;
457
458         if (td == NULL)
459                 return (-1);
460         KASSERT(td->td_pcb != NULL, ("trap_pfault: pcb NULL"));
461         KASSERT(td->td_proc != NULL, ("trap_pfault: curproc NULL"));
462         KASSERT(td->td_proc->p_vmspace != NULL, ("trap_pfault: vmspace NULL"));
463
464         p = td->td_proc;
465
466         rv = KERN_SUCCESS;
467         ctx = TLB_TAR_CTX(tf->tf_tar);
468         type = tf->tf_type & ~T_KERNEL;
469         va = TLB_TAR_VA(tf->tf_tar);
470
471         CTR4(KTR_TRAP, "trap_pfault: td=%p pm_ctx=%#lx va=%#lx ctx=%#lx",
472             td, p->p_vmspace->vm_pmap.pm_context[curcpu], va, ctx);
473
474         if (type == T_DATA_PROTECTION)
475                 prot = VM_PROT_WRITE;
476         else {
477                 if (type == T_DATA_MISS)
478                         prot = VM_PROT_READ;
479                 else
480                         prot = VM_PROT_READ | VM_PROT_EXECUTE;
481         }
482
483         if (ctx != TLB_CTX_KERNEL) {
484                 /* This is a fault on non-kernel virtual memory. */
485                 map = &p->p_vmspace->vm_map;
486         } else {
487                 /*
488                  * This is a fault on kernel virtual memory.  Attempts to
489                  * access kernel memory from user mode cause privileged
490                  * action traps, not page fault.
491                  */
492                 KASSERT(tf->tf_tstate & TSTATE_PRIV,
493                     ("trap_pfault: fault on nucleus context from user mode"));
494
495                 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
496                     tf->tf_tpc <= (u_long)copy_nofault_end) {
497                         vm_map_lock_read(kernel_map);
498                         if (vm_map_lookup_entry(kernel_map, va, &entry) &&
499                             (entry->eflags & MAP_ENTRY_NOFAULT) != 0) {
500                                 tf->tf_tpc = (u_long)copy_fault;
501                                 tf->tf_tnpc = tf->tf_tpc + 4;
502                                 vm_map_unlock_read(kernel_map);
503                                 return (0);
504                         }
505                         vm_map_unlock_read(kernel_map);
506                 }
507                 map = kernel_map;
508         }
509
510         /* Fault in the page. */
511         rv = vm_fault(map, va, prot, VM_FAULT_NORMAL);
512
513         CTR3(KTR_TRAP, "trap_pfault: return td=%p va=%#lx rv=%d",
514             td, va, rv);
515         if (rv == KERN_SUCCESS)
516                 return (0);
517         if (ctx != TLB_CTX_KERNEL && (tf->tf_tstate & TSTATE_PRIV) != 0) {
518                 if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
519                     tf->tf_tpc <= (u_long)fs_nofault_end) {
520                         tf->tf_tpc = (u_long)fs_fault;
521                         tf->tf_tnpc = tf->tf_tpc + 4;
522                         return (0);
523                 }
524                 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
525                     tf->tf_tpc <= (u_long)copy_nofault_end) {
526                         tf->tf_tpc = (u_long)copy_fault;
527                         tf->tf_tnpc = tf->tf_tpc + 4;
528                         return (0);
529                 }
530         }
531         return ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
532 }
533
534 /* Maximum number of arguments that can be passed via the out registers. */
535 #define REG_MAXARGS     6
536
537 int
538 cpu_fetch_syscall_args(struct thread *td)
539 {
540         struct trapframe *tf;
541         struct proc *p;
542         register_t *argp;
543         struct syscall_args *sa;
544         int reg;
545         int regcnt;
546         int error;
547
548         p = td->td_proc;
549         tf = td->td_frame;
550         sa = &td->td_sa;
551         reg = 0;
552         regcnt = REG_MAXARGS;
553
554         sa->code = tf->tf_global[1];
555
556         if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
557                 sa->code = tf->tf_out[reg++];
558                 regcnt--;
559         }
560
561         if (p->p_sysent->sv_mask)
562                 sa->code &= p->p_sysent->sv_mask;
563         if (sa->code >= p->p_sysent->sv_size)
564                 sa->callp = &p->p_sysent->sv_table[0];
565         else
566                 sa->callp = &p->p_sysent->sv_table[sa->code];
567
568         sa->narg = sa->callp->sy_narg;
569         KASSERT(sa->narg <= sizeof(sa->args) / sizeof(sa->args[0]),
570             ("Too many syscall arguments!"));
571         error = 0;
572         argp = sa->args;
573         bcopy(&tf->tf_out[reg], sa->args, sizeof(sa->args[0]) * regcnt);
574         if (sa->narg > regcnt)
575                 error = copyin((void *)(tf->tf_out[6] + SPOFF +
576                     offsetof(struct frame, fr_pad[6])), &sa->args[regcnt],
577                     (sa->narg - regcnt) * sizeof(sa->args[0]));
578         if (error == 0) {
579                 td->td_retval[0] = 0;
580                 td->td_retval[1] = 0;
581         }
582
583         return (error);
584 }
585
586 #include "../../kern/subr_syscall.c"
587
588 /*
589  * Syscall handler
590  * The arguments to the syscall are passed in the out registers by the caller,
591  * and are saved in the trap frame.  The syscall number is passed in %g1 (and
592  * also saved in the trap frame).
593  */
594 void
595 syscall(struct trapframe *tf)
596 {
597         struct thread *td;
598         int error;
599
600         td = curthread;
601         td->td_frame = tf;
602
603         KASSERT(td != NULL, ("trap: curthread NULL"));
604         KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
605
606         /*
607          * For syscalls, we don't want to retry the faulting instruction
608          * (usually), instead we need to advance one instruction.
609          */
610         td->td_pcb->pcb_tpc = tf->tf_tpc;
611         TF_DONE(tf);
612
613         error = syscallenter(td);
614         syscallret(td, error);
615 }