]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/sparc64/sparc64/trap.c
Partial MFV r329753:
[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 extern char fs_nofault_intr_begin[];
104 extern char fs_nofault_intr_end[];
105
106 extern char fas_fault[];
107 extern char fas_nofault_begin[];
108 extern char fas_nofault_end[];
109
110 const char *const trap_msg[] = {
111         "reserved",
112         "instruction access exception",
113         "instruction access error",
114         "instruction access protection",
115         "illtrap instruction",
116         "illegal instruction",
117         "privileged opcode",
118         "floating point disabled",
119         "floating point exception ieee 754",
120         "floating point exception other",
121         "tag overflow",
122         "division by zero",
123         "data access exception",
124         "data access error",
125         "data access protection",
126         "memory address not aligned",
127         "privileged action",
128         "async data error",
129         "trap instruction 16",
130         "trap instruction 17",
131         "trap instruction 18",
132         "trap instruction 19",
133         "trap instruction 20",
134         "trap instruction 21",
135         "trap instruction 22",
136         "trap instruction 23",
137         "trap instruction 24",
138         "trap instruction 25",
139         "trap instruction 26",
140         "trap instruction 27",
141         "trap instruction 28",
142         "trap instruction 29",
143         "trap instruction 30",
144         "trap instruction 31",
145         "fast instruction access mmu miss",
146         "fast data access mmu miss",
147         "interrupt",
148         "physical address watchpoint",
149         "virtual address watchpoint",
150         "corrected ecc error",
151         "spill",
152         "fill",
153         "fill",
154         "breakpoint",
155         "clean window",
156         "range check",
157         "fix alignment",
158         "integer overflow",
159         "syscall",
160         "restore physical watchpoint",
161         "restore virtual watchpoint",
162         "kernel stack fault",
163 };
164
165 static const int trap_sig[] = {
166         SIGILL,                 /* reserved */
167         SIGILL,                 /* instruction access exception */
168         SIGILL,                 /* instruction access error */
169         SIGILL,                 /* instruction access protection */
170         SIGILL,                 /* illtrap instruction */
171         SIGILL,                 /* illegal instruction */
172         SIGBUS,                 /* privileged opcode */
173         SIGFPE,                 /* floating point disabled */
174         SIGFPE,                 /* floating point exception ieee 754 */
175         SIGFPE,                 /* floating point exception other */
176         SIGEMT,                 /* tag overflow */
177         SIGFPE,                 /* division by zero */
178         SIGILL,                 /* data access exception */
179         SIGILL,                 /* data access error */
180         SIGBUS,                 /* data access protection */
181         SIGBUS,                 /* memory address not aligned */
182         SIGBUS,                 /* privileged action */
183         SIGBUS,                 /* async data error */
184         SIGILL,                 /* trap instruction 16 */
185         SIGILL,                 /* trap instruction 17 */
186         SIGILL,                 /* trap instruction 18 */
187         SIGILL,                 /* trap instruction 19 */
188         SIGILL,                 /* trap instruction 20 */
189         SIGILL,                 /* trap instruction 21 */
190         SIGILL,                 /* trap instruction 22 */
191         SIGILL,                 /* trap instruction 23 */
192         SIGILL,                 /* trap instruction 24 */
193         SIGILL,                 /* trap instruction 25 */
194         SIGILL,                 /* trap instruction 26 */
195         SIGILL,                 /* trap instruction 27 */
196         SIGILL,                 /* trap instruction 28 */
197         SIGILL,                 /* trap instruction 29 */
198         SIGILL,                 /* trap instruction 30 */
199         SIGILL,                 /* trap instruction 31 */
200         SIGSEGV,                /* fast instruction access mmu miss */
201         SIGSEGV,                /* fast data access mmu miss */
202         -1,                     /* interrupt */
203         -1,                     /* physical address watchpoint */
204         -1,                     /* virtual address watchpoint */
205         -1,                     /* corrected ecc error */
206         SIGILL,                 /* spill */
207         SIGILL,                 /* fill */
208         SIGILL,                 /* fill */
209         SIGTRAP,                /* breakpoint */
210         SIGILL,                 /* clean window */
211         SIGILL,                 /* range check */
212         SIGILL,                 /* fix alignment */
213         SIGILL,                 /* integer overflow */
214         SIGSYS,                 /* syscall */
215         -1,                     /* restore physical watchpoint */
216         -1,                     /* restore virtual watchpoint */
217         -1,                     /* kernel stack fault */
218 };
219
220 CTASSERT(nitems(trap_msg) == T_MAX);
221 CTASSERT(nitems(trap_sig) == T_MAX);
222
223 CTASSERT(sizeof(struct trapframe) == 256);
224
225 int debugger_on_signal = 0;
226 SYSCTL_INT(_debug, OID_AUTO, debugger_on_signal, CTLFLAG_RW,
227     &debugger_on_signal, 0, "");
228
229 u_int corrected_ecc = 0;
230 SYSCTL_UINT(_machdep, OID_AUTO, corrected_ecc, CTLFLAG_RD, &corrected_ecc, 0,
231     "corrected ECC errors");
232
233 /*
234  * SUNW,set-trap-table allows to take over %tba from the PROM, which
235  * will turn off interrupts and handle outstanding ones while doing so,
236  * in a safe way.
237  */
238 void
239 sun4u_set_traptable(void *tba_addr)
240 {
241         static struct {
242                 cell_t name;
243                 cell_t nargs;
244                 cell_t nreturns;
245                 cell_t tba_addr;
246         } args = {
247                 (cell_t)"SUNW,set-trap-table",
248                 1,
249                 0,
250         };
251
252         args.tba_addr = (cell_t)tba_addr;
253         ofw_entry(&args);
254 }
255
256 void
257 trap(struct trapframe *tf)
258 {
259         struct thread *td;
260         struct proc *p;
261         int error;
262         int sig;
263         register_t addr;
264         ksiginfo_t ksi;
265
266         td = curthread;
267
268         CTR4(KTR_TRAP, "trap: %p type=%s (%s) pil=%#lx", td,
269             trap_msg[tf->tf_type & ~T_KERNEL],
270             (TRAPF_USERMODE(tf) ? "user" : "kernel"), rdpr(pil));
271
272         VM_CNT_INC(v_trap);
273
274         if ((tf->tf_tstate & TSTATE_PRIV) == 0) {
275                 KASSERT(td != NULL, ("trap: curthread NULL"));
276                 KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
277
278                 p = td->td_proc;
279                 td->td_pticks = 0;
280                 td->td_frame = tf;
281                 addr = tf->tf_tpc;
282                 if (td->td_cowgen != p->p_cowgen)
283                         thread_cow_update(td);
284
285                 switch (tf->tf_type) {
286                 case T_DATA_MISS:
287                 case T_DATA_PROTECTION:
288                         addr = tf->tf_sfar;
289                         /* FALLTHROUGH */
290                 case T_INSTRUCTION_MISS:
291                         sig = trap_pfault(td, tf);
292                         break;
293                 case T_FILL:
294                         sig = rwindow_load(td, tf, 2);
295                         break;
296                 case T_FILL_RET:
297                         sig = rwindow_load(td, tf, 1);
298                         break;
299                 case T_SPILL:
300                         sig = rwindow_save(td);
301                         break;
302                 case T_CORRECTED_ECC_ERROR:
303                         sig = trap_cecc();
304                         break;
305                 default:
306                         if (tf->tf_type > T_MAX)
307                                 panic("trap: bad trap type %#lx (user)",
308                                     tf->tf_type);
309                         else if (trap_sig[tf->tf_type] == -1)
310                                 panic("trap: %s (user)",
311                                     trap_msg[tf->tf_type]);
312                         sig = trap_sig[tf->tf_type];
313                         break;
314                 }
315
316                 if (sig != 0) {
317                         /* Translate fault for emulators. */
318                         if (p->p_sysent->sv_transtrap != NULL) {
319                                 sig = p->p_sysent->sv_transtrap(sig,
320                                     tf->tf_type);
321                         }
322                         if (debugger_on_signal &&
323                             (sig == 4 || sig == 10 || sig == 11))
324                                 kdb_enter(KDB_WHY_TRAPSIG, "trapsig");
325                         ksiginfo_init_trap(&ksi);
326                         ksi.ksi_signo = sig;
327                         ksi.ksi_code = (int)tf->tf_type; /* XXX not POSIX */
328                         ksi.ksi_addr = (void *)addr;
329                         ksi.ksi_trapno = (int)tf->tf_type;
330                         trapsignal(td, &ksi);
331                 }
332
333                 userret(td, tf);
334         } else {
335                 KASSERT((tf->tf_type & T_KERNEL) != 0,
336                     ("trap: kernel trap isn't"));
337
338                 if (kdb_active) {
339                         kdb_reenter();
340                         return;
341                 }
342
343                 switch (tf->tf_type & ~T_KERNEL) {
344                 case T_BREAKPOINT:
345                 case T_KSTACK_FAULT:
346                         error = (kdb_trap(tf->tf_type, 0, tf) == 0);
347                         TF_DONE(tf);
348                         break;
349 #ifdef notyet
350                 case T_PA_WATCHPOINT:
351                 case T_VA_WATCHPOINT:
352                         error = db_watch_trap(tf);
353                         break;
354 #endif
355                 case T_DATA_MISS:
356                 case T_DATA_PROTECTION:
357                 case T_INSTRUCTION_MISS:
358                         error = trap_pfault(td, tf);
359                         break;
360                 case T_DATA_EXCEPTION:
361                 case T_MEM_ADDRESS_NOT_ALIGNED:
362                         if ((tf->tf_sfsr & MMU_SFSR_FV) != 0 &&
363                             MMU_SFSR_GET_ASI(tf->tf_sfsr) == ASI_AIUP) {
364                                 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
365                                     tf->tf_tpc <= (u_long)copy_nofault_end) {
366                                         tf->tf_tpc = (u_long)copy_fault;
367                                         tf->tf_tnpc = tf->tf_tpc + 4;
368                                         error = 0;
369                                         break;
370                                 }
371                                 if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
372                                     tf->tf_tpc <= (u_long)fs_nofault_end) {
373                                         tf->tf_tpc = (u_long)fs_fault;
374                                         tf->tf_tnpc = tf->tf_tpc + 4;
375                                         error = 0;
376                                         break;
377                                 }
378                         }
379                         error = 1;
380                         break;
381                 case T_DATA_ERROR:
382                         /*
383                          * Handle PCI poke/peek as per UltraSPARC IIi
384                          * User's Manual 16.2.1, modulo checking the
385                          * TPC as USIII CPUs generate a precise trap
386                          * instead of a special deferred one.
387                          */
388                         if (tf->tf_tpc > (u_long)fas_nofault_begin &&
389                             tf->tf_tpc < (u_long)fas_nofault_end) {
390                                 cache_flush();
391                                 cache_enable(PCPU_GET(impl));
392                                 tf->tf_tpc = (u_long)fas_fault;
393                                 tf->tf_tnpc = tf->tf_tpc + 4;
394                                 error = 0;
395                                 break;
396                         }
397                         error = 1;
398                         break;
399                 case T_CORRECTED_ECC_ERROR:
400                         error = trap_cecc();
401                         break;
402                 default:
403                         error = 1;
404                         break;
405                 }
406
407                 if (error != 0) {
408                         tf->tf_type &= ~T_KERNEL;
409                         if (tf->tf_type > T_MAX)
410                                 panic("trap: bad trap type %#lx (kernel)",
411                                     tf->tf_type);
412                         panic("trap: %s (kernel)", trap_msg[tf->tf_type]);
413                 }
414         }
415         CTR1(KTR_TRAP, "trap: td=%p return", td);
416 }
417
418 static int
419 trap_cecc(void)
420 {
421         u_long eee;
422
423         /*
424          * Turn off (non-)correctable error reporting while we're dealing
425          * with the error.
426          */
427         eee = ldxa(0, ASI_ESTATE_ERROR_EN_REG);
428         stxa_sync(0, ASI_ESTATE_ERROR_EN_REG, eee & ~(AA_ESTATE_NCEEN |
429             AA_ESTATE_CEEN));
430         /* Flush the caches in order ensure no corrupt data got installed. */
431         cache_flush();
432         /* Ensure the caches are still turned on (should be). */
433         cache_enable(PCPU_GET(impl));
434         /* Clear the error from the AFSR. */
435         stxa_sync(0, ASI_AFSR, ldxa(0, ASI_AFSR));
436         corrected_ecc++;
437         printf("corrected ECC error\n");
438         /* Turn (non-)correctable error reporting back on. */
439         stxa_sync(0, ASI_ESTATE_ERROR_EN_REG, eee);
440         return (0);
441 }
442
443 static int
444 trap_pfault(struct thread *td, struct trapframe *tf)
445 {
446         vm_map_t map;
447         struct proc *p;
448         vm_offset_t va;
449         vm_prot_t prot;
450         vm_map_entry_t entry;
451         u_long ctx;
452         int type;
453         int rv;
454
455         if (td == NULL)
456                 return (-1);
457         KASSERT(td->td_pcb != NULL, ("trap_pfault: pcb NULL"));
458         KASSERT(td->td_proc != NULL, ("trap_pfault: curproc NULL"));
459         KASSERT(td->td_proc->p_vmspace != NULL, ("trap_pfault: vmspace NULL"));
460
461         p = td->td_proc;
462
463         rv = KERN_SUCCESS;
464         ctx = TLB_TAR_CTX(tf->tf_tar);
465         type = tf->tf_type & ~T_KERNEL;
466         va = TLB_TAR_VA(tf->tf_tar);
467
468         CTR4(KTR_TRAP, "trap_pfault: td=%p pm_ctx=%#lx va=%#lx ctx=%#lx",
469             td, p->p_vmspace->vm_pmap.pm_context[curcpu], va, ctx);
470
471         if (type == T_DATA_PROTECTION)
472                 prot = VM_PROT_WRITE;
473         else {
474                 if (type == T_DATA_MISS)
475                         prot = VM_PROT_READ;
476                 else
477                         prot = VM_PROT_READ | VM_PROT_EXECUTE;
478         }
479
480         if (ctx != TLB_CTX_KERNEL) {
481                 if ((tf->tf_tstate & TSTATE_PRIV) != 0 &&
482                     (tf->tf_tpc >= (u_long)fs_nofault_intr_begin &&
483                     tf->tf_tpc <= (u_long)fs_nofault_intr_end)) {
484                         tf->tf_tpc = (u_long)fs_fault;
485                         tf->tf_tnpc = tf->tf_tpc + 4;
486                         return (0);
487                 }
488
489                 /* This is a fault on non-kernel virtual memory. */
490                 map = &p->p_vmspace->vm_map;
491         } else {
492                 /*
493                  * This is a fault on kernel virtual memory.  Attempts to
494                  * access kernel memory from user mode cause privileged
495                  * action traps, not page fault.
496                  */
497                 KASSERT(tf->tf_tstate & TSTATE_PRIV,
498                     ("trap_pfault: fault on nucleus context from user mode"));
499
500                 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
501                     tf->tf_tpc <= (u_long)copy_nofault_end) {
502                         vm_map_lock_read(kernel_map);
503                         if (vm_map_lookup_entry(kernel_map, va, &entry) &&
504                             (entry->eflags & MAP_ENTRY_NOFAULT) != 0) {
505                                 tf->tf_tpc = (u_long)copy_fault;
506                                 tf->tf_tnpc = tf->tf_tpc + 4;
507                                 vm_map_unlock_read(kernel_map);
508                                 return (0);
509                         }
510                         vm_map_unlock_read(kernel_map);
511                 }
512                 map = kernel_map;
513         }
514
515         /* Fault in the page. */
516         rv = vm_fault(map, va, prot, VM_FAULT_NORMAL);
517
518         CTR3(KTR_TRAP, "trap_pfault: return td=%p va=%#lx rv=%d",
519             td, va, rv);
520         if (rv == KERN_SUCCESS)
521                 return (0);
522         if (ctx != TLB_CTX_KERNEL && (tf->tf_tstate & TSTATE_PRIV) != 0) {
523                 if (tf->tf_tpc >= (u_long)fs_nofault_begin &&
524                     tf->tf_tpc <= (u_long)fs_nofault_end) {
525                         tf->tf_tpc = (u_long)fs_fault;
526                         tf->tf_tnpc = tf->tf_tpc + 4;
527                         return (0);
528                 }
529                 if (tf->tf_tpc >= (u_long)copy_nofault_begin &&
530                     tf->tf_tpc <= (u_long)copy_nofault_end) {
531                         tf->tf_tpc = (u_long)copy_fault;
532                         tf->tf_tnpc = tf->tf_tpc + 4;
533                         return (0);
534                 }
535         }
536         return ((rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV);
537 }
538
539 /* Maximum number of arguments that can be passed via the out registers. */
540 #define REG_MAXARGS     6
541
542 int
543 cpu_fetch_syscall_args(struct thread *td)
544 {
545         struct trapframe *tf;
546         struct proc *p;
547         register_t *argp;
548         struct syscall_args *sa;
549         int reg;
550         int regcnt;
551         int error;
552
553         p = td->td_proc;
554         tf = td->td_frame;
555         sa = &td->td_sa;
556         reg = 0;
557         regcnt = REG_MAXARGS;
558
559         sa->code = tf->tf_global[1];
560
561         if (sa->code == SYS_syscall || sa->code == SYS___syscall) {
562                 sa->code = tf->tf_out[reg++];
563                 regcnt--;
564         }
565
566         if (p->p_sysent->sv_mask)
567                 sa->code &= p->p_sysent->sv_mask;
568         if (sa->code >= p->p_sysent->sv_size)
569                 sa->callp = &p->p_sysent->sv_table[0];
570         else
571                 sa->callp = &p->p_sysent->sv_table[sa->code];
572
573         sa->narg = sa->callp->sy_narg;
574         KASSERT(sa->narg <= sizeof(sa->args) / sizeof(sa->args[0]),
575             ("Too many syscall arguments!"));
576         error = 0;
577         argp = sa->args;
578         bcopy(&tf->tf_out[reg], sa->args, sizeof(sa->args[0]) * regcnt);
579         if (sa->narg > regcnt)
580                 error = copyin((void *)(tf->tf_out[6] + SPOFF +
581                     offsetof(struct frame, fr_pad[6])), &sa->args[regcnt],
582                     (sa->narg - regcnt) * sizeof(sa->args[0]));
583         if (error == 0) {
584                 td->td_retval[0] = 0;
585                 td->td_retval[1] = 0;
586         }
587
588         return (error);
589 }
590
591 #include "../../kern/subr_syscall.c"
592
593 /*
594  * Syscall handler
595  * The arguments to the syscall are passed in the out registers by the caller,
596  * and are saved in the trap frame.  The syscall number is passed in %g1 (and
597  * also saved in the trap frame).
598  */
599 void
600 syscall(struct trapframe *tf)
601 {
602         struct thread *td;
603         int error;
604
605         td = curthread;
606         td->td_frame = tf;
607
608         KASSERT(td != NULL, ("trap: curthread NULL"));
609         KASSERT(td->td_proc != NULL, ("trap: curproc NULL"));
610
611         /*
612          * For syscalls, we don't want to retry the faulting instruction
613          * (usually), instead we need to advance one instruction.
614          */
615         td->td_pcb->pcb_tpc = tf->tf_tpc;
616         TF_DONE(tf);
617
618         error = syscallenter(td);
619         syscallret(td, error);
620 }