1 /*
2 * Copyright (c) 1988 University of Utah.
3 * Copyright (c) 1982, 1986, 1990, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * the Systems Programming Group of the University of Utah Computer
8 * Science Department.
9 *
10 * %sccs.include.redist.c%
11 *
12 * from: Utah $Hdr: trap.c 1.37 92/12/20$
13 *
14 * @(#)trap.c 8.7 (Berkeley) 02/19/95
15 */
16
17 #include <sys/param.h>
18 #include <sys/systm.h>
19 #include <sys/proc.h>
20 #include <sys/acct.h>
21 #include <sys/kernel.h>
22 #include <sys/signalvar.h>
23 #include <sys/resourcevar.h>
24 #include <sys/syscall.h>
25 #include <sys/syslog.h>
26 #include <sys/user.h>
27 #ifdef KTRACE
28 #include <sys/ktrace.h>
29 #endif
30
31 #include <machine/psl.h>
32 #include <machine/trap.h>
33 #include <machine/cpu.h>
34 #include <machine/reg.h>
35 #include <machine/mtpr.h>
36
37 #include <vm/vm.h>
38 #include <vm/pmap.h>
39
40 #ifdef HPUXCOMPAT
41 #include <hp/hpux/hpux.h>
42 #endif
43
44 struct sysent sysent[];
45 int nsysent;
46
47 char *trap_type[] = {
48 "Bus error",
49 "Address error",
50 "Illegal instruction",
51 "Zero divide",
52 "CHK instruction",
53 "TRAPV instruction",
54 "Privilege violation",
55 "Trace trap",
56 "MMU fault",
57 "SSIR trap",
58 "Format error",
59 "68881 exception",
60 "Coprocessor violation",
61 "Async system trap"
62 };
63 #define TRAP_TYPES (sizeof trap_type / sizeof trap_type[0])
64
65 /*
66 * Size of various exception stack frames (minus the standard 8 bytes)
67 */
68 short exframesize[] = {
69 FMT0SIZE, /* type 0 - normal (68020/030/040) */
70 FMT1SIZE, /* type 1 - throwaway (68020/030/040) */
71 FMT2SIZE, /* type 2 - normal 6-word (68020/030/040) */
72 FMT3SIZE, /* type 3 - FP post-instruction (68040) */
73 -1, -1, -1, /* type 4-6 - undefined */
74 FMT7SIZE, /* type 7 - access error (68040) */
75 58, /* type 8 - bus fault (68010) */
76 FMT9SIZE, /* type 9 - coprocessor mid-instruction (68020/030) */
77 FMTASIZE, /* type A - short bus fault (68020/030) */
78 FMTBSIZE, /* type B - long bus fault (68020/030) */
79 -1, -1, -1, -1 /* type C-F - undefined */
80 };
81
82 #ifdef HP380
83 #define KDFAULT(c) (mmutype == MMU_68040 ? \
84 ((c) & SSW4_TMMASK) == SSW4_TMKD : \
85 ((c) & (SSW_DF|FC_SUPERD)) == (SSW_DF|FC_SUPERD))
86 #define WRFAULT(c) (mmutype == MMU_68040 ? \
87 ((c) & SSW4_RW) == 0 : \
88 ((c) & (SSW_DF|SSW_RW)) == SSW_DF)
89 #else
90 #define KDFAULT(c) (((c) & (SSW_DF|SSW_FCMASK)) == (SSW_DF|FC_SUPERD))
91 #define WRFAULT(c) (((c) & (SSW_DF|SSW_RW)) == SSW_DF)
92 #endif
93
94 #ifdef DEBUG
95 int mmudebug = 0;
96 int mmupid = -1;
97 #define MDB_FOLLOW 1
98 #define MDB_WBFOLLOW 2
99 #define MDB_WBFAILED 4
100 #define MDB_ISPID(p) (p) == mmupid
101 #endif
102
103 /*
104 * trap and syscall both need the following work done before returning
105 * to user mode.
106 */
107 static inline void
userret(p,fp,oticks,faultaddr,fromtrap)108 userret(p, fp, oticks, faultaddr, fromtrap)
109 register struct proc *p;
110 register struct frame *fp;
111 u_quad_t oticks;
112 u_int faultaddr;
113 int fromtrap;
114 {
115 int sig, s;
116 #ifdef HP380
117 int beenhere = 0;
118
119 again:
120 #endif
121 /* take pending signals */
122 while ((sig = CURSIG(p)) != 0)
123 postsig(sig);
124 p->p_priority = p->p_usrpri;
125 if (want_resched) {
126 /*
127 * Since we are curproc, clock will normally just change
128 * our priority without moving us from one queue to another
129 * (since the running process is not on a queue.)
130 * If that happened after we put ourselves on the run queue
131 * but before we mi_switch()'ed, we might not be on the queue
132 * indicated by our priority.
133 */
134 s = splstatclock();
135 setrunqueue(p);
136 p->p_stats->p_ru.ru_nivcsw++;
137 mi_switch();
138 splx(s);
139 while ((sig = CURSIG(p)) != 0)
140 postsig(sig);
141 }
142
143 /*
144 * If profiling, charge system time to the trapped pc.
145 */
146 if (p->p_flag & P_PROFIL) {
147 extern int psratio;
148
149 addupc_task(p, fp->f_pc,
150 (int)(p->p_sticks - oticks) * psratio);
151 }
152 #ifdef HP380
153 /*
154 * Deal with user mode writebacks (from trap, or from sigreturn).
155 * If any writeback fails, go back and attempt signal delivery.
156 * unless we have already been here and attempted the writeback
157 * (e.g. bad address with user ignoring SIGSEGV). In that case
158 * we just return to the user without sucessfully completing
159 * the writebacks. Maybe we should just drop the sucker?
160 */
161 if (mmutype == MMU_68040 && fp->f_format == FMT7) {
162 if (beenhere) {
163 #ifdef DEBUG
164 if (mmudebug & MDB_WBFAILED)
165 printf(fromtrap ?
166 "pid %d(%s): writeback aborted, pc=%x, fa=%x\n" :
167 "pid %d(%s): writeback aborted in sigreturn, pc=%x\n",
168 p->p_pid, p->p_comm, fp->f_pc, faultaddr);
169 #endif
170 } else if (sig = writeback(fp, fromtrap)) {
171 beenhere = 1;
172 oticks = p->p_sticks;
173 trapsignal(p, sig, faultaddr);
174 goto again;
175 }
176 }
177 #endif
178 curpriority = p->p_priority;
179 }
180
181 /*
182 * Trap is called from locore to handle most types of processor traps,
183 * including events such as simulated software interrupts/AST's.
184 * System calls are broken out for efficiency.
185 */
186 /*ARGSUSED*/
trap(type,code,v,frame)187 trap(type, code, v, frame)
188 int type;
189 unsigned code;
190 register unsigned v;
191 struct frame frame;
192 {
193 extern char fswintr[];
194 register struct proc *p;
195 register int i;
196 u_int ucode;
197 u_quad_t sticks;
198
199 cnt.v_trap++;
200 p = curproc;
201 ucode = 0;
202 if (USERMODE(frame.f_sr)) {
203 type |= T_USER;
204 sticks = p->p_sticks;
205 p->p_md.md_regs = frame.f_regs;
206 }
207 switch (type) {
208
209 default:
210 dopanic:
211 printf("trap type %d, code = %x, v = %x\n", type, code, v);
212 regdump(&frame, 128);
213 type &= ~T_USER;
214 if ((unsigned)type < TRAP_TYPES)
215 panic(trap_type[type]);
216 panic("trap");
217
218 case T_BUSERR: /* kernel bus error */
219 if (!p->p_addr->u_pcb.pcb_onfault)
220 goto dopanic;
221 /*
222 * If we have arranged to catch this fault in any of the
223 * copy to/from user space routines, set PC to return to
224 * indicated location and set flag informing buserror code
225 * that it may need to clean up stack frame.
226 */
227 copyfault:
228 frame.f_stackadj = exframesize[frame.f_format];
229 frame.f_format = frame.f_vector = 0;
230 frame.f_pc = (int) p->p_addr->u_pcb.pcb_onfault;
231 return;
232
233 case T_BUSERR|T_USER: /* bus error */
234 case T_ADDRERR|T_USER: /* address error */
235 ucode = v;
236 i = SIGBUS;
237 break;
238
239 #ifdef HP380
240 case T_ADDRERR:
241 /*
242 * Yow! Looks like we get a kernel exception if the PC
243 * in the RTE frame is odd on a 68040 (not on a 68030).
244 * It comes through as a user exception for access faults
245 * (T_MMUFLT).
246 */
247 if (*(short *)frame.f_pc != 0x4e73)
248 goto dopanic;
249 /* fall through */
250 #endif
251
252 #ifdef FPCOPROC
253 case T_COPERR: /* kernel coprocessor violation */
254 #endif
255 case T_FMTERR|T_USER: /* do all RTE errors come in as T_USER? */
256 case T_FMTERR: /* ...just in case... */
257 /*
258 * The user has most likely trashed the RTE or FP state info
259 * in the stack frame of a signal handler.
260 */
261 type |= T_USER;
262 printf("pid %d: kernel %s exception\n", p->p_pid,
263 (type==T_COPERR|T_USER) ? "coprocessor" :
264 (type==T_ADDRERR|T_USER) ? "RTE address" :
265 "RTE format");
266 p->p_sigacts->ps_sigact[SIGILL] = SIG_DFL;
267 i = sigmask(SIGILL);
268 p->p_sigignore &= ~i;
269 p->p_sigcatch &= ~i;
270 p->p_sigmask &= ~i;
271 i = SIGILL;
272 ucode = frame.f_format; /* XXX was ILL_RESAD_FAULT */
273 break;
274
275 #ifdef FPCOPROC
276 case T_COPERR|T_USER: /* user coprocessor violation */
277 /* What is a proper response here? */
278 ucode = 0;
279 i = SIGFPE;
280 break;
281
282 case T_FPERR|T_USER: /* 68881 exceptions */
283 /*
284 * We pass along the 68881 status register which locore stashed
285 * in code for us. Note that there is a possibility that the
286 * bit pattern of this register will conflict with one of the
287 * FPE_* codes defined in signal.h. Fortunately for us, the
288 * only such codes we use are all in the range 1-7 and the low
289 * 3 bits of the status register are defined as 0 so there is
290 * no clash.
291 */
292 ucode = code;
293 i = SIGFPE;
294 break;
295 #endif
296
297 #ifdef HP380
298 case T_FPEMULI|T_USER: /* unimplemented FP instuction */
299 case T_FPEMULD|T_USER: /* unimplemented FP data type */
300 /* XXX need to FSAVE */
301 printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
302 p->p_pid, p->p_comm,
303 frame.f_format == 2 ? "instruction" : "data type",
304 frame.f_pc, frame.f_fmt2.f_iaddr);
305 /* XXX need to FRESTORE */
306 i = SIGFPE;
307 break;
308 #endif
309
310 case T_ILLINST|T_USER: /* illegal instruction fault */
311 #ifdef HPUXCOMPAT
312 if (p->p_md.md_flags & MDP_HPUX) {
313 ucode = HPUX_ILL_ILLINST_TRAP;
314 i = SIGILL;
315 break;
316 }
317 /* fall through */
318 #endif
319 case T_PRIVINST|T_USER: /* privileged instruction fault */
320 #ifdef HPUXCOMPAT
321 if (p->p_md.md_flags & MDP_HPUX)
322 ucode = HPUX_ILL_PRIV_TRAP;
323 else
324 #endif
325 ucode = frame.f_format; /* XXX was ILL_PRIVIN_FAULT */
326 i = SIGILL;
327 break;
328
329 case T_ZERODIV|T_USER: /* Divide by zero */
330 #ifdef HPUXCOMPAT
331 if (p->p_md.md_flags & MDP_HPUX)
332 ucode = HPUX_FPE_INTDIV_TRAP;
333 else
334 #endif
335 ucode = frame.f_format; /* XXX was FPE_INTDIV_TRAP */
336 i = SIGFPE;
337 break;
338
339 case T_CHKINST|T_USER: /* CHK instruction trap */
340 #ifdef HPUXCOMPAT
341 if (p->p_md.md_flags & MDP_HPUX) {
342 /* handled differently under hp-ux */
343 i = SIGILL;
344 ucode = HPUX_ILL_CHK_TRAP;
345 break;
346 }
347 #endif
348 ucode = frame.f_format; /* XXX was FPE_SUBRNG_TRAP */
349 i = SIGFPE;
350 break;
351
352 case T_TRAPVINST|T_USER: /* TRAPV instruction trap */
353 #ifdef HPUXCOMPAT
354 if (p->p_md.md_flags & MDP_HPUX) {
355 /* handled differently under hp-ux */
356 i = SIGILL;
357 ucode = HPUX_ILL_TRAPV_TRAP;
358 break;
359 }
360 #endif
361 ucode = frame.f_format; /* XXX was FPE_INTOVF_TRAP */
362 i = SIGFPE;
363 break;
364
365 /*
366 * XXX: Trace traps are a nightmare.
367 *
368 * HP-UX uses trap #1 for breakpoints,
369 * HPBSD uses trap #2,
370 * SUN 3.x uses trap #15,
371 * KGDB uses trap #15 (for kernel breakpoints; handled elsewhere).
372 *
373 * HPBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
374 * SUN 3.x traps get passed through as T_TRAP15 and are not really
375 * supported yet.
376 */
377 case T_TRACE: /* kernel trace trap */
378 case T_TRAP15: /* SUN trace trap */
379 frame.f_sr &= ~PSL_T;
380 i = SIGTRAP;
381 break;
382
383 case T_TRACE|T_USER: /* user trace trap */
384 case T_TRAP15|T_USER: /* SUN user trace trap */
385 frame.f_sr &= ~PSL_T;
386 i = SIGTRAP;
387 break;
388
389 case T_ASTFLT: /* system async trap, cannot happen */
390 goto dopanic;
391
392 case T_ASTFLT|T_USER: /* user async trap */
393 astpending = 0;
394 /*
395 * We check for software interrupts first. This is because
396 * they are at a higher level than ASTs, and on a VAX would
397 * interrupt the AST. We assume that if we are processing
398 * an AST that we must be at IPL0 so we don't bother to
399 * check. Note that we ensure that we are at least at SIR
400 * IPL while processing the SIR.
401 */
402 spl1();
403 /* fall into... */
404
405 case T_SSIR: /* software interrupt */
406 case T_SSIR|T_USER:
407 if (ssir & SIR_NET) {
408 siroff(SIR_NET);
409 cnt.v_soft++;
410 netintr();
411 }
412 if (ssir & SIR_CLOCK) {
413 siroff(SIR_CLOCK);
414 cnt.v_soft++;
415 softclock();
416 }
417 /*
418 * If this was not an AST trap, we are all done.
419 */
420 if (type != (T_ASTFLT|T_USER)) {
421 cnt.v_trap--;
422 return;
423 }
424 spl0();
425 if (p->p_flag & P_OWEUPC) {
426 p->p_flag &= ~P_OWEUPC;
427 ADDUPROF(p);
428 }
429 goto out;
430
431 case T_MMUFLT: /* kernel mode page fault */
432 /*
433 * If we were doing profiling ticks or other user mode
434 * stuff from interrupt code, Just Say No.
435 */
436 if (p->p_addr->u_pcb.pcb_onfault == fswintr)
437 goto copyfault;
438 /* fall into ... */
439
440 case T_MMUFLT|T_USER: /* page fault */
441 {
442 register vm_offset_t va;
443 register struct vmspace *vm = p->p_vmspace;
444 register vm_map_t map;
445 int rv;
446 vm_prot_t ftype;
447 extern vm_map_t kernel_map;
448
449 #ifdef DEBUG
450 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
451 printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
452 p->p_pid, code, v, frame.f_pc, frame.f_sr);
453 #endif
454 /*
455 * It is only a kernel address space fault iff:
456 * 1. (type & T_USER) == 0 and
457 * 2. pcb_onfault not set or
458 * 3. pcb_onfault set but supervisor space data fault
459 * The last can occur during an exec() copyin where the
460 * argument space is lazy-allocated.
461 */
462 if (type == T_MMUFLT &&
463 (!p->p_addr->u_pcb.pcb_onfault || KDFAULT(code)))
464 map = kernel_map;
465 else
466 map = &vm->vm_map;
467 if (WRFAULT(code))
468 ftype = VM_PROT_READ | VM_PROT_WRITE;
469 else
470 ftype = VM_PROT_READ;
471 va = trunc_page((vm_offset_t)v);
472 #ifdef DEBUG
473 if (map == kernel_map && va == 0) {
474 printf("trap: bad kernel access at %x\n", v);
475 goto dopanic;
476 }
477 #endif
478 #ifdef HPUXCOMPAT
479 if (ISHPMMADDR(va)) {
480 vm_offset_t bva;
481
482 rv = pmap_mapmulti(map->pmap, va);
483 if (rv != KERN_SUCCESS) {
484 bva = HPMMBASEADDR(va);
485 rv = vm_fault(map, bva, ftype, FALSE);
486 if (rv == KERN_SUCCESS)
487 (void) pmap_mapmulti(map->pmap, va);
488 }
489 } else
490 #endif
491 rv = vm_fault(map, va, ftype, FALSE);
492 #ifdef DEBUG
493 if (rv && MDB_ISPID(p->p_pid))
494 printf("vm_fault(%x, %x, %x, 0) -> %x\n",
495 map, va, ftype, rv);
496 #endif
497 /*
498 * If this was a stack access we keep track of the maximum
499 * accessed stack size. Also, if vm_fault gets a protection
500 * failure it is due to accessing the stack region outside
501 * the current limit and we need to reflect that as an access
502 * error.
503 */
504 if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map) {
505 if (rv == KERN_SUCCESS) {
506 unsigned nss;
507
508 nss = clrnd(btoc(USRSTACK-(unsigned)va));
509 if (nss > vm->vm_ssize)
510 vm->vm_ssize = nss;
511 } else if (rv == KERN_PROTECTION_FAILURE)
512 rv = KERN_INVALID_ADDRESS;
513 }
514 if (rv == KERN_SUCCESS) {
515 if (type == T_MMUFLT) {
516 #ifdef HP380
517 if (mmutype == MMU_68040)
518 (void) writeback(&frame, 1);
519 #endif
520 return;
521 }
522 goto out;
523 }
524 if (type == T_MMUFLT) {
525 if (p->p_addr->u_pcb.pcb_onfault)
526 goto copyfault;
527 printf("vm_fault(%x, %x, %x, 0) -> %x\n",
528 map, va, ftype, rv);
529 printf(" type %x, code [mmu,,ssw]: %x\n",
530 type, code);
531 goto dopanic;
532 }
533 ucode = v;
534 i = (rv == KERN_PROTECTION_FAILURE) ? SIGBUS : SIGSEGV;
535 break;
536 }
537 }
538 trapsignal(p, i, ucode);
539 if ((type & T_USER) == 0)
540 return;
541 out:
542 userret(p, &frame, sticks, v, 1);
543 }
544
545 #ifdef HP380
546 #ifdef DEBUG
547 struct writebackstats {
548 int calls;
549 int cpushes;
550 int move16s;
551 int wb1s, wb2s, wb3s;
552 int wbsize[4];
553 } wbstats;
554
555 char *f7sz[] = { "longword", "byte", "word", "line" };
556 char *f7tt[] = { "normal", "MOVE16", "AFC", "ACK" };
557 char *f7tm[] = { "d-push", "u-data", "u-code", "M-data",
558 "M-code", "k-data", "k-code", "RES" };
559 char wberrstr[] =
560 "WARNING: pid %d(%s) writeback [%s] failed, pc=%x fa=%x wba=%x wbd=%x\n";
561 #endif
562
563 writeback(fp, docachepush)
564 struct frame *fp;
565 int docachepush;
566 {
567 register struct fmt7 *f = &fp->f_fmt7;
568 register struct proc *p = curproc;
569 int err = 0;
570 u_int fa;
571 caddr_t oonfault = p->p_addr->u_pcb.pcb_onfault;
572
573 #ifdef DEBUG
574 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
575 printf(" pid=%d, fa=%x,", p->p_pid, f->f_fa);
576 dumpssw(f->f_ssw);
577 }
578 wbstats.calls++;
579 #endif
580 /*
581 * Deal with special cases first.
582 */
583 if ((f->f_ssw & SSW4_TMMASK) == SSW4_TMDCP) {
584 /*
585 * Dcache push fault.
586 * Line-align the address and write out the push data to
587 * the indicated physical address.
588 */
589 #ifdef DEBUG
590 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid)) {
591 printf(" pushing %s to PA %x, data %x",
592 f7sz[(f->f_ssw & SSW4_SZMASK) >> 5],
593 f->f_fa, f->f_pd0);
594 if ((f->f_ssw & SSW4_SZMASK) == SSW4_SZLN)
595 printf("/%x/%x/%x",
596 f->f_pd1, f->f_pd2, f->f_pd3);
597 printf("\n");
598 }
599 if (f->f_wb1s & SSW4_WBSV)
600 panic("writeback: cache push with WB1S valid");
601 wbstats.cpushes++;
602 #endif
603 /*
604 * XXX there are security problems if we attempt to do a
605 * cache push after a signal handler has been called.
606 */
607 if (docachepush) {
608 pmap_enter(kernel_pmap, (vm_offset_t)vmmap,
609 trunc_page(f->f_fa), VM_PROT_WRITE, TRUE);
610 fa = (u_int)&vmmap[(f->f_fa & PGOFSET) & ~0xF];
611 bcopy((caddr_t)&f->f_pd0, (caddr_t)fa, 16);
612 DCFL(pmap_extract(kernel_pmap, (vm_offset_t)fa));
613 pmap_remove(kernel_pmap, (vm_offset_t)vmmap,
614 (vm_offset_t)&vmmap[NBPG]);
615 } else
616 printf("WARNING: pid %d(%s) uid %d: CPUSH not done\n",
617 p->p_pid, p->p_comm, p->p_ucred->cr_uid);
618 } else if ((f->f_ssw & (SSW4_RW|SSW4_TTMASK)) == SSW4_TTM16) {
619 /*
620 * MOVE16 fault.
621 * Line-align the address and write out the push data to
622 * the indicated virtual address.
623 */
624 #ifdef DEBUG
625 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
626 printf(" MOVE16 to VA %x(%x), data %x/%x/%x/%x\n",
627 f->f_fa, f->f_fa & ~0xF, f->f_pd0, f->f_pd1,
628 f->f_pd2, f->f_pd3);
629 if (f->f_wb1s & SSW4_WBSV)
630 panic("writeback: MOVE16 with WB1S valid");
631 wbstats.move16s++;
632 #endif
633 if (KDFAULT(f->f_wb1s))
634 bcopy((caddr_t)&f->f_pd0, (caddr_t)(f->f_fa & ~0xF), 16);
635 else
636 err = suline((caddr_t)(f->f_fa & ~0xF), (caddr_t)&f->f_pd0);
637 if (err) {
638 fa = f->f_fa & ~0xF;
639 #ifdef DEBUG
640 if (mmudebug & MDB_WBFAILED)
641 printf(wberrstr, p->p_pid, p->p_comm,
642 "MOVE16", fp->f_pc, f->f_fa,
643 f->f_fa & ~0xF, f->f_pd0);
644 #endif
645 }
646 } else if (f->f_wb1s & SSW4_WBSV) {
647 /*
648 * Writeback #1.
649 * Position the "memory-aligned" data and write it out.
650 */
651 register u_int wb1d = f->f_wb1d;
652 register int off;
653
654 #ifdef DEBUG
655 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
656 dumpwb(1, f->f_wb1s, f->f_wb1a, f->f_wb1d);
657 wbstats.wb1s++;
658 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
659 #endif
660 off = (f->f_wb1a & 3) * 8;
661 switch (f->f_wb1s & SSW4_SZMASK) {
662 case SSW4_SZLW:
663 if (off)
664 wb1d = (wb1d >> (32 - off)) | (wb1d << off);
665 if (KDFAULT(f->f_wb1s))
666 *(long *)f->f_wb1a = wb1d;
667 else
668 err = suword((caddr_t)f->f_wb1a, wb1d);
669 break;
670 case SSW4_SZB:
671 off = 24 - off;
672 if (off)
673 wb1d >>= off;
674 if (KDFAULT(f->f_wb1s))
675 *(char *)f->f_wb1a = wb1d;
676 else
677 err = subyte((caddr_t)f->f_wb1a, wb1d);
678 break;
679 case SSW4_SZW:
680 off = (off + 16) % 32;
681 if (off)
682 wb1d = (wb1d >> (32 - off)) | (wb1d << off);
683 if (KDFAULT(f->f_wb1s))
684 *(short *)f->f_wb1a = wb1d;
685 else
686 err = susword((caddr_t)f->f_wb1a, wb1d);
687 break;
688 }
689 if (err) {
690 fa = f->f_wb1a;
691 #ifdef DEBUG
692 if (mmudebug & MDB_WBFAILED)
693 printf(wberrstr, p->p_pid, p->p_comm,
694 "#1", fp->f_pc, f->f_fa,
695 f->f_wb1a, f->f_wb1d);
696 #endif
697 }
698 }
699 /*
700 * Deal with the "normal" writebacks.
701 *
702 * XXX writeback2 is known to reflect a LINE size writeback after
703 * a MOVE16 was already dealt with above. Ignore it.
704 */
705 if (err == 0 && (f->f_wb2s & SSW4_WBSV) &&
706 (f->f_wb2s & SSW4_SZMASK) != SSW4_SZLN) {
707 #ifdef DEBUG
708 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
709 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
710 wbstats.wb2s++;
711 wbstats.wbsize[(f->f_wb2s&SSW4_SZMASK)>>5]++;
712 #endif
713 switch (f->f_wb2s & SSW4_SZMASK) {
714 case SSW4_SZLW:
715 if (KDFAULT(f->f_wb2s))
716 *(long *)f->f_wb2a = f->f_wb2d;
717 else
718 err = suword((caddr_t)f->f_wb2a, f->f_wb2d);
719 break;
720 case SSW4_SZB:
721 if (KDFAULT(f->f_wb2s))
722 *(char *)f->f_wb2a = f->f_wb2d;
723 else
724 err = subyte((caddr_t)f->f_wb2a, f->f_wb2d);
725 break;
726 case SSW4_SZW:
727 if (KDFAULT(f->f_wb2s))
728 *(short *)f->f_wb2a = f->f_wb2d;
729 else
730 err = susword((caddr_t)f->f_wb2a, f->f_wb2d);
731 break;
732 }
733 if (err) {
734 fa = f->f_wb2a;
735 #ifdef DEBUG
736 if (mmudebug & MDB_WBFAILED) {
737 printf(wberrstr, p->p_pid, p->p_comm,
738 "#2", fp->f_pc, f->f_fa,
739 f->f_wb2a, f->f_wb2d);
740 dumpssw(f->f_ssw);
741 dumpwb(2, f->f_wb2s, f->f_wb2a, f->f_wb2d);
742 }
743 #endif
744 }
745 }
746 if (err == 0 && (f->f_wb3s & SSW4_WBSV)) {
747 #ifdef DEBUG
748 if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
749 dumpwb(3, f->f_wb3s, f->f_wb3a, f->f_wb3d);
750 wbstats.wb3s++;
751 wbstats.wbsize[(f->f_wb3s&SSW4_SZMASK)>>5]++;
752 #endif
753 switch (f->f_wb3s & SSW4_SZMASK) {
754 case SSW4_SZLW:
755 if (KDFAULT(f->f_wb3s))
756 *(long *)f->f_wb3a = f->f_wb3d;
757 else
758 err = suword((caddr_t)f->f_wb3a, f->f_wb3d);
759 break;
760 case SSW4_SZB:
761 if (KDFAULT(f->f_wb3s))
762 *(char *)f->f_wb3a = f->f_wb3d;
763 else
764 err = subyte((caddr_t)f->f_wb3a, f->f_wb3d);
765 break;
766 case SSW4_SZW:
767 if (KDFAULT(f->f_wb3s))
768 *(short *)f->f_wb3a = f->f_wb3d;
769 else
770 err = susword((caddr_t)f->f_wb3a, f->f_wb3d);
771 break;
772 #ifdef DEBUG
773 case SSW4_SZLN:
774 panic("writeback: wb3s indicates LINE write");
775 #endif
776 }
777 if (err) {
778 fa = f->f_wb3a;
779 #ifdef DEBUG
780 if (mmudebug & MDB_WBFAILED)
781 printf(wberrstr, p->p_pid, p->p_comm,
782 "#3", fp->f_pc, f->f_fa,
783 f->f_wb3a, f->f_wb3d);
784 #endif
785 }
786 }
787 p->p_addr->u_pcb.pcb_onfault = oonfault;
788 /*
789 * Determine the cause of the failure if any translating to
790 * a signal. If the corresponding VA is valid and RO it is
791 * a protection fault (SIGBUS) otherwise consider it an
792 * illegal reference (SIGSEGV).
793 */
794 if (err) {
795 if (vm_map_check_protection(&p->p_vmspace->vm_map,
796 trunc_page(fa), round_page(fa),
797 VM_PROT_READ) &&
798 !vm_map_check_protection(&p->p_vmspace->vm_map,
799 trunc_page(fa), round_page(fa),
800 VM_PROT_WRITE))
801 err = SIGBUS;
802 else
803 err = SIGSEGV;
804 }
805 return(err);
806 }
807
808 #ifdef DEBUG
dumpssw(ssw)809 dumpssw(ssw)
810 register u_short ssw;
811 {
812 printf(" SSW: %x: ", ssw);
813 if (ssw & SSW4_CP)
814 printf("CP,");
815 if (ssw & SSW4_CU)
816 printf("CU,");
817 if (ssw & SSW4_CT)
818 printf("CT,");
819 if (ssw & SSW4_CM)
820 printf("CM,");
821 if (ssw & SSW4_MA)
822 printf("MA,");
823 if (ssw & SSW4_ATC)
824 printf("ATC,");
825 if (ssw & SSW4_LK)
826 printf("LK,");
827 if (ssw & SSW4_RW)
828 printf("RW,");
829 printf(" SZ=%s, TT=%s, TM=%s\n",
830 f7sz[(ssw & SSW4_SZMASK) >> 5],
831 f7tt[(ssw & SSW4_TTMASK) >> 3],
832 f7tm[ssw & SSW4_TMMASK]);
833 }
834
dumpwb(num,s,a,d)835 dumpwb(num, s, a, d)
836 int num;
837 u_short s;
838 u_int a, d;
839 {
840 register struct proc *p = curproc;
841 vm_offset_t pa;
842
843 printf(" writeback #%d: VA %x, data %x, SZ=%s, TT=%s, TM=%s\n",
844 num, a, d, f7sz[(s & SSW4_SZMASK) >> 5],
845 f7tt[(s & SSW4_TTMASK) >> 3], f7tm[s & SSW4_TMMASK]);
846 printf(" PA ");
847 pa = pmap_extract(&p->p_vmspace->vm_pmap, (vm_offset_t)a);
848 if (pa == 0)
849 printf("<invalid address>");
850 else
851 printf("%x, current value %x", pa, fuword((caddr_t)a));
852 printf("\n");
853 }
854 #endif
855 #endif
856
857 /*
858 * Proces a system call.
859 */
syscall(code,frame)860 syscall(code, frame)
861 u_int code;
862 struct frame frame;
863 {
864 register caddr_t params;
865 register struct sysent *callp;
866 register struct proc *p;
867 int error, opc, numsys;
868 u_int argsize;
869 struct args {
870 int i[8];
871 } args;
872 int rval[2];
873 u_quad_t sticks;
874 #ifdef HPUXCOMPAT
875 extern struct sysent hpuxsysent[];
876 extern int hpuxnsysent, notimp();
877 #endif
878
879 cnt.v_syscall++;
880 if (!USERMODE(frame.f_sr))
881 panic("syscall");
882 p = curproc;
883 sticks = p->p_sticks;
884 p->p_md.md_regs = frame.f_regs;
885 opc = frame.f_pc - 2;
886 #ifdef HPUXCOMPAT
887 if (p->p_md.md_flags & MDP_HPUX)
888 callp = hpuxsysent, numsys = hpuxnsysent;
889 else
890 #endif
891 callp = sysent, numsys = nsysent;
892 params = (caddr_t)frame.f_regs[SP] + sizeof(int);
893 switch (code) {
894
895 case SYS_syscall:
896 /*
897 * Code is first argument, followed by actual args.
898 */
899 code = fuword(params);
900 params += sizeof(int);
901 /*
902 * XXX sigreturn requires special stack manipulation
903 * that is only done if entered via the sigreturn
904 * trap. Cannot allow it here so make sure we fail.
905 */
906 if (code == SYS_sigreturn)
907 code = numsys;
908 break;
909
910 case SYS___syscall:
911 /*
912 * Like syscall, but code is a quad, so as to maintain
913 * quad alignment for the rest of the arguments.
914 */
915 #ifdef HPUXCOMPAT
916 if (p->p_md.md_flags & MDP_HPUX)
917 break;
918 #endif
919 code = fuword(params + _QUAD_LOWWORD * sizeof(int));
920 params += sizeof(quad_t);
921 break;
922
923 default:
924 /* nothing to do by default */
925 break;
926 }
927 if (code < numsys)
928 callp += code;
929 else
930 callp += SYS_syscall; /* => nosys */
931 argsize = callp->sy_argsize;
932 if (argsize && (error = copyin(params, (caddr_t)&args, argsize))) {
933 #ifdef KTRACE
934 if (KTRPOINT(p, KTR_SYSCALL))
935 ktrsyscall(p->p_tracep, code, argsize, args.i);
936 #endif
937 goto bad;
938 }
939 #ifdef KTRACE
940 if (KTRPOINT(p, KTR_SYSCALL))
941 ktrsyscall(p->p_tracep, code, argsize, args.i);
942 #endif
943 rval[0] = 0;
944 rval[1] = frame.f_regs[D1];
945 #ifdef HPUXCOMPAT
946 /* debug kludge */
947 if (callp->sy_call == notimp)
948 error = notimp(p, args.i, rval, code, argsize);
949 else
950 #endif
951 error = (*callp->sy_call)(p, &args, rval);
952 switch (error) {
953
954 case 0:
955 /*
956 * Reinitialize proc pointer `p' as it may be different
957 * if this is a child returning from fork syscall.
958 */
959 p = curproc;
960 frame.f_regs[D0] = rval[0];
961 frame.f_regs[D1] = rval[1];
962 frame.f_sr &= ~PSL_C;
963 break;
964
965 case ERESTART:
966 frame.f_pc = opc;
967 break;
968
969 case EJUSTRETURN:
970 break; /* nothing to do */
971
972 default:
973 bad:
974 #ifdef HPUXCOMPAT
975 if (p->p_md.md_flags & MDP_HPUX)
976 error = bsdtohpuxerrno(error);
977 #endif
978 frame.f_regs[D0] = error;
979 frame.f_sr |= PSL_C;
980 break;
981 }
982
983 userret(p, &frame, sticks, (u_int)0, 0);
984 #ifdef KTRACE
985 if (KTRPOINT(p, KTR_SYSRET))
986 ktrsysret(p->p_tracep, code, error, rval[0]);
987 #endif
988 }
989