1 /* $NetBSD: trap.c,v 1.60 2009/01/27 20:30:13 martin Exp $ */
4 * Copyright (c) 1982, 1986, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * the Systems Programming Group of the University of Utah Computer
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * from: Utah $Hdr: trap.c 1.37 92/12/20$
37 * @(#)trap.c 8.5 (Berkeley) 1/4/94
40 * Copyright (c) 1988 University of Utah.
42 * This code is derived from software contributed to Berkeley by
43 * the Systems Programming Group of the University of Utah Computer
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
49 * 1. Redistributions of source code must retain the above copyright
50 * notice, this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright
52 * notice, this list of conditions and the following disclaimer in the
53 * documentation and/or other materials provided with the distribution.
54 * 3. All advertising materials mentioning features or use of this software
55 * must display the following acknowledgement:
56 * This product includes software developed by the University of
57 * California, Berkeley and its contributors.
58 * 4. Neither the name of the University nor the names of its contributors
59 * may be used to endorse or promote products derived from this software
60 * without specific prior written permission.
62 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
63 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
64 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
65 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
66 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
67 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
68 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
70 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
71 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
74 * from: Utah $Hdr: trap.c 1.37 92/12/20$
76 * @(#)trap.c 8.5 (Berkeley) 1/4/94
79 #include <sys/cdefs.h>
80 __KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.60 2009/01/27 20:30:13 martin Exp $");
83 #include "opt_execfmt.h"
85 #include "opt_compat_sunos.h"
87 #include <sys/param.h>
88 #include <sys/systm.h>
92 #include <sys/savar.h>
93 #include <sys/syscall.h>
94 #include <sys/userret.h>
95 #include <sys/kauth.h>
97 #include <m68k/frame.h>
98 #include <m68k/cacheops.h>
100 #include <machine/cpu.h>
101 #include <machine/db_machdep.h>
102 #include <machine/reg.h>
103 #include <machine/trap.h>
105 #include <uvm/uvm_extern.h>
107 #include <dev/cons.h>
110 #include <compat/sunos/sunos_exec.h>
111 #include <compat/sunos/sunos_syscall.h>
114 int writeback(struct frame
*fp
, int docachepush
);
115 void trap(struct frame
*fp
, int type
, u_int code
, u_int v
);
118 void dumpssw(u_short
);
119 void dumpwb(int, u_short
, u_int
, u_int
);
122 static inline void userret(struct lwp
*l
, struct frame
*fp
,
123 u_quad_t oticks
, u_int faultaddr
, int fromtrap
);
127 const char *trap_type
[] = {
130 "Illegal instruction",
134 "Privilege violation",
140 "Coprocessor violation",
143 const int trap_types
= sizeof trap_type
/ sizeof trap_type
[0];
146 * Size of various exception stack frames (minus the standard 8 bytes)
148 short exframesize
[] = {
149 FMT0SIZE
, /* type 0 - normal (68020/030/040/060) */
150 FMT1SIZE
, /* type 1 - throwaway (68020/030/040) */
151 FMT2SIZE
, /* type 2 - normal 6-word (68020/030/040/060) */
152 FMT3SIZE
, /* type 3 - FP post-instruction (68040/060) */
153 FMT4SIZE
, /* type 4 - access error/fp disabled (68060) */
154 -1, -1, /* type 5-6 - undefined */
155 FMT7SIZE
, /* type 7 - access error (68040) */
156 58, /* type 8 - bus fault (68010) */
157 FMT9SIZE
, /* type 9 - coprocessor mid-instruction (68020/030) */
158 FMTASIZE
, /* type A - short bus fault (68020/030) */
159 FMTBSIZE
, /* type B - long bus fault (68020/030) */
160 -1, -1, -1, -1 /* type C-F - undefined */
164 #define KDFAULT_060(c) (cputype == CPU_68060 && ((c) & FSLW_TM_SV))
165 #define WRFAULT_060(c) (cputype == CPU_68060 && ((c) & FSLW_RW_W))
167 #define KDFAULT_060(c) 0
168 #define WRFAULT_060(c) 0
172 #define KDFAULT_040(c) (cputype == CPU_68040 && \
173 ((c) & SSW4_TMMASK) == SSW4_TMKD)
174 #define WRFAULT_040(c) (cputype == CPU_68040 && \
175 ((c) & (SSW4_LK|SSW4_RW)) != SSW4_RW)
177 #define KDFAULT_040(c) 0
178 #define WRFAULT_040(c) 0
181 #if defined(M68030) || defined(M68020)
182 #define KDFAULT_OTH(c) (cputype <= CPU_68030 && \
183 ((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
184 #define WRFAULT_OTH(c) (cputype <= CPU_68030 && \
185 (((c) & SSW_DF) != 0 && \
186 ((((c) & SSW_RW) == 0) || (((c) & SSW_RM) != 0))))
188 #define KDFAULT_OTH(c) 0
189 #define WRFAULT_OTH(c) 0
192 #define KDFAULT(c) (KDFAULT_060(c) || KDFAULT_040(c) || KDFAULT_OTH(c))
193 #define WRFAULT(c) (WRFAULT_060(c) || WRFAULT_040(c) || WRFAULT_OTH(c))
199 #define MDB_WBFOLLOW 2
200 #define MDB_WBFAILED 4
201 #define MDB_ISPID(p) ((p) == mmupid)
205 * trap and syscall both need the following work done before returning
209 userret(struct lwp
*l
, struct frame
*fp
, u_quad_t oticks
,
210 u_int faultaddr
, int fromtrap
)
212 struct proc
*p
= l
->l_proc
;
219 /* Invoke MI userret code */
223 * If profiling, charge system time to the trapped pc.
225 if (p
->p_stflag
& PST_PROFIL
) {
228 addupc_task(l
, fp
->f_pc
,
229 (int)(p
->p_sticks
- oticks
) * psratio
);
233 * Deal with user mode writebacks (from trap, or from sigreturn).
234 * If any writeback fails, go back and attempt signal delivery.
235 * unless we have already been here and attempted the writeback
236 * (e.g. bad address with user ignoring SIGSEGV). In that case
237 * we just return to the user without successfully completing
238 * the writebacks. Maybe we should just drop the sucker?
240 if (cputype
== CPU_68040
&& fp
->f_format
== FMT7
) {
243 if (mmudebug
& MDB_WBFAILED
)
245 "pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
246 "pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
247 p
->p_pid
, p
->p_comm
, fp
->f_pc
, faultaddr
);
249 } else if ((sig
= writeback(fp
, fromtrap
))) {
252 oticks
= p
->p_sticks
;
253 (void)memset(&ksi
, 0, sizeof(ksi
));
255 ksi
.ksi_addr
= (void *)faultaddr
;
256 ksi
.ksi_code
= BUS_OBJERR
;
265 * Used by the common m68k syscall() and child_return() functions.
266 * XXX: Temporary until all m68k ports share common trap()/userret() code.
268 void machine_userret(struct lwp
*, struct frame
*, u_quad_t
);
271 machine_userret(struct lwp
*l
, struct frame
*f
, u_quad_t t
)
274 userret(l
, f
, t
, 0, 0);
278 * Trap is called from locore to handle most types of processor traps,
279 * including events such as simulated software interrupts/AST's.
280 * System calls are broken out for efficiency.
284 trap(struct frame
*fp
, int type
, u_int code
, u_int v
)
286 extern char fubail
[], subail
[];
292 u_quad_t sticks
= 0 /* XXX initializer works around compiler bug */;
298 ksi
.ksi_trap
= type
& ~T_USER
;
302 KASSERT(pcb
!= NULL
);
304 if (USERMODE(fp
->f_sr
)) {
306 sticks
= p
->p_sticks
;
307 l
->l_md
.md_regs
= fp
->f_regs
;
308 LWP_CACHE_CREDS(l
, p
);
314 printf("trap type %d, code = 0x%x, v = 0x%x\n", type
, code
, v
);
315 printf("%s program counter = 0x%x\n",
316 (type
& T_USER
) ? "user" : "kernel", fp
->f_pc
);
318 * Let the kernel debugger see the trap frame that
319 * caused us to panic. This is a convenience so
320 * one can see registers at the point of failure.
324 /* If connected, step or cont returns 1 */
325 if (kgdb_trap(type
, fp
))
329 (void)kdb_trap(type
, (db_regs_t
*)fp
);
336 printf("trap during panic!\n");
338 /* XXX should be a machine-dependent hook */
339 printf("(press a key)\n"); (void)cngetc();
342 regdump((struct trapframe
*)fp
, 128);
344 if ((u_int
)type
< trap_types
)
345 panic(trap_type
[type
]);
348 case T_BUSERR
: /* kernel bus error */
349 if (pcb
->pcb_onfault
== 0)
355 * If we have arranged to catch this fault in any of the
356 * copy to/from user space routines, set PC to return to
357 * indicated location and set flag informing buserror code
358 * that it may need to clean up stack frame.
360 fp
->f_stackadj
= exframesize
[fp
->f_format
];
361 fp
->f_format
= fp
->f_vector
= 0;
362 fp
->f_pc
= (int)pcb
->pcb_onfault
;
365 case T_BUSERR
|T_USER
: /* bus error */
366 case T_ADDRERR
|T_USER
: /* address error */
367 ksi
.ksi_addr
= (void *)v
;
368 ksi
.ksi_signo
= SIGBUS
;
369 ksi
.ksi_code
= (type
== (T_BUSERR
|T_USER
)) ?
370 BUS_OBJERR
: BUS_ADRERR
;
373 case T_COPERR
: /* kernel coprocessor violation */
374 case T_FMTERR
|T_USER
: /* do all RTE errors come in as T_USER? */
375 case T_FMTERR
: /* ...just in case... */
377 * The user has most likely trashed the RTE or FP state info
378 * in the stack frame of a signal handler.
380 printf("pid %d: kernel %s exception\n", p
->p_pid
,
381 type
==T_COPERR
? "coprocessor" : "format");
384 mutex_enter(p
->p_lock
);
385 SIGACTION(p
, SIGILL
).sa_handler
= SIG_DFL
;
386 sigdelset(&p
->p_sigctx
.ps_sigignore
, SIGILL
);
387 sigdelset(&p
->p_sigctx
.ps_sigcatch
, SIGILL
);
388 sigdelset(&l
->l_sigmask
, SIGILL
);
389 mutex_exit(p
->p_lock
);
391 ksi
.ksi_signo
= SIGILL
;
392 ksi
.ksi_addr
= (void *)(int)fp
->f_format
;
393 /* XXX was ILL_RESAD_FAULT */
394 ksi
.ksi_code
= (type
== T_COPERR
) ?
395 ILL_COPROC
: ILL_ILLOPC
;
398 case T_COPERR
|T_USER
: /* user coprocessor violation */
399 /* What is a proper response here? */
400 ksi
.ksi_signo
= SIGFPE
;
401 ksi
.ksi_code
= FPE_FLTINV
;
404 case T_FPERR
|T_USER
: /* 68881 exceptions */
406 * We pass along the 68881 status register which locore stashed
409 ksi
.ksi_signo
= SIGFPE
;
410 ksi
.ksi_code
= fpsr2siginfocode(code
);
414 case T_FPEMULI
|T_USER
: /* unimplemented FP instruction */
415 case T_FPEMULD
|T_USER
: /* unimplemented FP data type */
416 /* XXX need to FSAVE */
417 printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
419 fp
->f_format
== 2 ? "instruction" : "data type",
420 fp
->f_pc
, fp
->f_fmt2
.f_iaddr
);
421 /* XXX need to FRESTORE */
422 ksi
.ksi_signo
= SIGFPE
;
423 ksi
.ksi_code
= FPE_FLTINV
;
427 case T_ILLINST
|T_USER
: /* illegal instruction fault */
428 case T_PRIVINST
|T_USER
: /* privileged instruction fault */
429 ksi
.ksi_addr
= (void *)(int)fp
->f_format
;
430 /* XXX was ILL_PRIVIN_FAULT */
431 ksi
.ksi_signo
= SIGILL
;
432 ksi
.ksi_code
= (type
== (T_PRIVINST
|T_USER
)) ?
433 ILL_PRVOPC
: ILL_ILLOPC
;
436 case T_ZERODIV
|T_USER
: /* Divide by zero */
437 ksi
.ksi_addr
= (void *)(int)fp
->f_format
;
438 /* XXX was FPE_INTDIV_TRAP */
439 ksi
.ksi_signo
= SIGFPE
;
440 ksi
.ksi_code
= FPE_FLTDIV
;
443 case T_CHKINST
|T_USER
: /* CHK instruction trap */
444 ksi
.ksi_addr
= (void *)(int)fp
->f_format
;
445 /* XXX was FPE_SUBRNG_TRAP */
446 ksi
.ksi_signo
= SIGFPE
;
449 case T_TRAPVINST
|T_USER
: /* TRAPV instruction trap */
450 ksi
.ksi_addr
= (void *)(int)fp
->f_format
;
451 /* XXX was FPE_INTOVF_TRAP */
452 ksi
.ksi_signo
= SIGFPE
;
456 * XXX: Trace traps are a nightmare.
458 * HP-UX uses trap #1 for breakpoints,
459 * NetBSD/m68k uses trap #2,
460 * SUN 3.x uses trap #15,
461 * DDB and KGDB uses trap #15 (for kernel breakpoints;
462 * handled elsewhere).
464 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
465 * SUN 3.x traps get passed through as T_TRAP15 and are not really
468 * XXX: We should never get kernel-mode T_TRAP15
469 * XXX: because locore.s now gives them special treatment.
471 case T_TRAP15
: /* kernel breakpoint */
473 printf("unexpected kernel trace trap, type = %d\n", type
);
474 printf("program counter = 0x%x\n", fp
->f_pc
);
479 case T_TRACE
|T_USER
: /* user trace trap */
482 * SunOS uses Trap #2 for a "CPU cache flush".
483 * Just flush the on-chip caches and return.
485 if (p
->p_emul
== &emul_sunos
) {
492 case T_TRACE
: /* tracing a trap instruction */
493 case T_TRAP15
|T_USER
: /* SUN user trace trap */
495 ksi
.ksi_signo
= SIGTRAP
;
498 case T_ASTFLT
: /* system async trap, cannot happen */
501 case T_ASTFLT
|T_USER
: /* user async trap */
503 /* T_SSIR is not used on news68k */
504 if (l
->l_pflag
& LP_OWEUPC
) {
505 l
->l_pflag
&= ~LP_OWEUPC
;
508 if (curcpu()->ci_want_resched
)
512 case T_MMUFLT
: /* kernel mode page fault */
514 * If we were doing profiling ticks or other user mode
515 * stuff from interrupt code, Just Say No.
517 if (pcb
->pcb_onfault
== fubail
|| pcb
->pcb_onfault
== subail
)
521 case T_MMUFLT
|T_USER
: /* page fault */
524 struct vmspace
*vm
= p
->p_vmspace
;
528 extern struct vm_map
*kernel_map
;
531 if ((mmudebug
& MDB_WBFOLLOW
) || MDB_ISPID(p
->p_pid
))
532 printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
533 p
->p_pid
, code
, v
, fp
->f_pc
, fp
->f_sr
);
536 * It is only a kernel address space fault iff:
537 * 1. (type & T_USER) == 0 and
538 * 2. pcb_onfault not set or
539 * 3. pcb_onfault set but supervisor space data fault
540 * The last can occur during an exec() copyin where the
541 * argument space is lazy-allocated.
543 if ((type
& T_USER
) == 0 &&
544 ((pcb
->pcb_onfault
== 0) || KDFAULT(code
)))
547 map
= vm
? &vm
->vm_map
: kernel_map
;
548 if ((l
->l_flag
& LW_SA
)
549 && (~l
->l_pflag
& LP_SA_NOBLOCK
)) {
550 l
->l_savp
->savp_faultaddr
= (vaddr_t
)v
;
551 l
->l_pflag
|= LP_SA_PAGEFAULT
;
556 ftype
= VM_PROT_WRITE
;
558 ftype
= VM_PROT_READ
;
560 va
= trunc_page((vaddr_t
)v
);
562 if (map
== kernel_map
&& va
== 0) {
563 printf("trap: bad kernel %s access at 0x%x\n",
564 (ftype
& VM_PROT_WRITE
) ? "read/write" :
569 rv
= uvm_fault(map
, va
, ftype
);
571 if (rv
&& MDB_ISPID(p
->p_pid
))
572 printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
576 * If this was a stack access we keep track of the maximum
577 * accessed stack size. Also, if vm_fault gets a protection
578 * failure it is due to accessing the stack region outside
579 * the current limit and we need to reflect that as an access
583 if (map
!= kernel_map
&& (void *)va
>= vm
->vm_maxsaddr
)
586 if (type
== T_MMUFLT
) {
588 if (cputype
== CPU_68040
)
589 (void) writeback(fp
, 1);
593 l
->l_pflag
&= ~LP_SA_PAGEFAULT
;
597 ksi
.ksi_code
= SEGV_ACCERR
;
600 ksi
.ksi_code
= SEGV_MAPERR
;
601 if (type
== T_MMUFLT
) {
602 if (pcb
->pcb_onfault
)
604 printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
606 printf(" type %x, code [mmu,,ssw]: %x\n",
610 l
->l_pflag
&= ~LP_SA_PAGEFAULT
;
611 ksi
.ksi_addr
= (void *)v
;
613 printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
616 kauth_cred_geteuid(l
->l_cred
) : -1);
617 ksi
.ksi_signo
= SIGKILL
;
619 ksi
.ksi_signo
= SIGSEGV
;
625 if ((type
& T_USER
) == 0)
628 userret(l
, fp
, sticks
, v
, 1);
633 struct writebackstats
{
637 int wb1s
, wb2s
, wb3s
;
641 static const char *f7sz
[] = { "longword", "byte", "word", "line" };
642 static const char *f7tt
[] = { "normal", "MOVE16", "AFC", "ACK" };
643 static const char *f7tm
[] = { "d-push", "u-data", "u-code", "M-data",
644 "M-code", "k-data", "k-code", "RES" };
645 static const char wberrstr
[] =
646 "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
650 writeback(struct frame
*fp
, int docachepush
)
652 struct fmt7
*f
= &fp
->f_fmt7
;
653 struct lwp
*l
= curlwp
;
654 struct proc
*p
= l
->l_proc
;
655 struct pcb
*pcb
= lwp_getpcb(l
);
658 void *oonfault
= pcb
->pcb_onfault
;
662 if ((mmudebug
& MDB_WBFOLLOW
) || MDB_ISPID(p
->p_pid
)) {
663 printf(" pid=%d, fa=%x,", p
->p_pid
, f
->f_fa
);
669 * Deal with special cases first.
671 if ((f
->f_ssw
& SSW4_TMMASK
) == SSW4_TMDCP
) {
674 * Line-align the address and write out the push data to
675 * the indicated physical address.
678 if ((mmudebug
& MDB_WBFOLLOW
) || MDB_ISPID(p
->p_pid
)) {
679 printf(" pushing %s to PA %x, data %x",
680 f7sz
[(f
->f_ssw
& SSW4_SZMASK
) >> 5],
682 if ((f
->f_ssw
& SSW4_SZMASK
) == SSW4_SZLN
)
684 f
->f_pd1
, f
->f_pd2
, f
->f_pd3
);
687 if (f
->f_wb1s
& SSW4_WBSV
)
688 panic("writeback: cache push with WB1S valid");
692 * XXX there are security problems if we attempt to do a
693 * cache push after a signal handler has been called.
696 pmap_enter(pmap_kernel(), (vaddr_t
)vmmap
,
697 trunc_page(f
->f_fa
), VM_PROT_WRITE
,
698 VM_PROT_WRITE
|PMAP_WIRED
);
699 pmap_update(pmap_kernel());
700 fa
= (u_int
)&vmmap
[m68k_page_offset(f
->f_fa
) & ~0xF];
701 memcpy((void *)fa
, (void *)&f
->f_pd0
, 16);
702 (void) pmap_extract(pmap_kernel(), (vaddr_t
)fa
, &pa
);
704 pmap_remove(pmap_kernel(), (vaddr_t
)vmmap
,
705 (vaddr_t
)&vmmap
[PAGE_SIZE
]);
706 pmap_update(pmap_kernel());
708 printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
709 p
->p_pid
, p
->p_comm
, kauth_cred_geteuid(l
->l_cred
));
710 } else if ((f
->f_ssw
& (SSW4_RW
|SSW4_TTMASK
)) == SSW4_TTM16
) {
713 * Line-align the address and write out the push data to
714 * the indicated virtual address.
717 if ((mmudebug
& MDB_WBFOLLOW
) || MDB_ISPID(p
->p_pid
))
718 printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
719 f
->f_fa
, f
->f_fa
& ~0xF, f
->f_pd0
, f
->f_pd1
,
721 if (f
->f_wb1s
& SSW4_WBSV
)
722 panic("writeback: MOVE16 with WB1S valid");
725 if (KDFAULT(f
->f_wb1s
))
726 memcpy((void *)(f
->f_fa
& ~0xF),
727 (void *)&f
->f_pd0
, 16);
729 err
= suline((void *)(f
->f_fa
& ~0xF),
734 if (mmudebug
& MDB_WBFAILED
)
735 printf(wberrstr
, p
->p_pid
, p
->p_comm
,
736 "MOVE16", fp
->f_pc
, f
->f_fa
,
737 f
->f_fa
& ~0xF, f
->f_pd0
);
740 } else if (f
->f_wb1s
& SSW4_WBSV
) {
743 * Position the "memory-aligned" data and write it out.
745 u_int wb1d
= f
->f_wb1d
;
749 if ((mmudebug
& MDB_WBFOLLOW
) || MDB_ISPID(p
->p_pid
))
750 dumpwb(1, f
->f_wb1s
, f
->f_wb1a
, f
->f_wb1d
);
752 wbstats
.wbsize
[(f
->f_wb2s
&SSW4_SZMASK
)>>5]++;
754 off
= (f
->f_wb1a
& 3) * 8;
755 switch (f
->f_wb1s
& SSW4_SZMASK
) {
758 wb1d
= (wb1d
>> (32 - off
)) | (wb1d
<< off
);
759 if (KDFAULT(f
->f_wb1s
))
760 *(long *)f
->f_wb1a
= wb1d
;
762 err
= suword((void *)f
->f_wb1a
, wb1d
);
768 if (KDFAULT(f
->f_wb1s
))
769 *(char *)f
->f_wb1a
= wb1d
;
771 err
= subyte((void *)f
->f_wb1a
, wb1d
);
774 off
= (off
+ 16) % 32;
776 wb1d
= (wb1d
>> (32 - off
)) | (wb1d
<< off
);
777 if (KDFAULT(f
->f_wb1s
))
778 *(short *)f
->f_wb1a
= wb1d
;
780 err
= susword((void *)f
->f_wb1a
, wb1d
);
786 if (mmudebug
& MDB_WBFAILED
)
787 printf(wberrstr
, p
->p_pid
, p
->p_comm
,
788 "#1", fp
->f_pc
, f
->f_fa
,
789 f
->f_wb1a
, f
->f_wb1d
);
794 * Deal with the "normal" writebacks.
796 * XXX writeback2 is known to reflect a LINE size writeback after
797 * a MOVE16 was already dealt with above. Ignore it.
799 if (err
== 0 && (f
->f_wb2s
& SSW4_WBSV
) &&
800 (f
->f_wb2s
& SSW4_SZMASK
) != SSW4_SZLN
) {
802 if ((mmudebug
& MDB_WBFOLLOW
) || MDB_ISPID(p
->p_pid
))
803 dumpwb(2, f
->f_wb2s
, f
->f_wb2a
, f
->f_wb2d
);
805 wbstats
.wbsize
[(f
->f_wb2s
&SSW4_SZMASK
)>>5]++;
807 switch (f
->f_wb2s
& SSW4_SZMASK
) {
809 if (KDFAULT(f
->f_wb2s
))
810 *(long *)f
->f_wb2a
= f
->f_wb2d
;
812 err
= suword((void *)f
->f_wb2a
, f
->f_wb2d
);
815 if (KDFAULT(f
->f_wb2s
))
816 *(char *)f
->f_wb2a
= f
->f_wb2d
;
818 err
= subyte((void *)f
->f_wb2a
, f
->f_wb2d
);
821 if (KDFAULT(f
->f_wb2s
))
822 *(short *)f
->f_wb2a
= f
->f_wb2d
;
824 err
= susword((void *)f
->f_wb2a
, f
->f_wb2d
);
830 if (mmudebug
& MDB_WBFAILED
) {
831 printf(wberrstr
, p
->p_pid
, p
->p_comm
,
832 "#2", fp
->f_pc
, f
->f_fa
,
833 f
->f_wb2a
, f
->f_wb2d
);
835 dumpwb(2, f
->f_wb2s
, f
->f_wb2a
, f
->f_wb2d
);
840 if (err
== 0 && (f
->f_wb3s
& SSW4_WBSV
)) {
842 if ((mmudebug
& MDB_WBFOLLOW
) || MDB_ISPID(p
->p_pid
))
843 dumpwb(3, f
->f_wb3s
, f
->f_wb3a
, f
->f_wb3d
);
845 wbstats
.wbsize
[(f
->f_wb3s
&SSW4_SZMASK
)>>5]++;
847 switch (f
->f_wb3s
& SSW4_SZMASK
) {
849 if (KDFAULT(f
->f_wb3s
))
850 *(long *)f
->f_wb3a
= f
->f_wb3d
;
852 err
= suword((void *)f
->f_wb3a
, f
->f_wb3d
);
855 if (KDFAULT(f
->f_wb3s
))
856 *(char *)f
->f_wb3a
= f
->f_wb3d
;
858 err
= subyte((void *)f
->f_wb3a
, f
->f_wb3d
);
861 if (KDFAULT(f
->f_wb3s
))
862 *(short *)f
->f_wb3a
= f
->f_wb3d
;
864 err
= susword((void *)f
->f_wb3a
, f
->f_wb3d
);
868 panic("writeback: wb3s indicates LINE write");
874 if (mmudebug
& MDB_WBFAILED
)
875 printf(wberrstr
, p
->p_pid
, p
->p_comm
,
876 "#3", fp
->f_pc
, f
->f_fa
,
877 f
->f_wb3a
, f
->f_wb3d
);
881 pcb
->pcb_onfault
= oonfault
;
892 printf(" SSW: %x: ", ssw
);
909 printf(" SZ=%s, TT=%s, TM=%s\n",
910 f7sz
[(ssw
& SSW4_SZMASK
) >> 5],
911 f7tt
[(ssw
& SSW4_TTMASK
) >> 3],
912 f7tm
[ssw
& SSW4_TMMASK
]);
916 dumpwb(int num
, u_short s
, u_int a
, u_int d
)
918 struct lwp
*l
= curlwp
;
919 struct proc
*p
= l
->l_proc
;
922 printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
923 num
, a
, d
, f7sz
[(s
& SSW4_SZMASK
) >> 5],
924 f7tt
[(s
& SSW4_TTMASK
) >> 3], f7tm
[s
& SSW4_TMMASK
]);
926 if (pmap_extract(p
->p_vmspace
->vm_map
.pmap
, (vaddr_t
)a
, &pa
) == false)
927 printf("<invalid address>");
929 printf("%lx, current value %lx", pa
, fuword((void *)a
));