Annotation of sys/arch/sh/sh/trap.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: trap.c,v 1.12 2007/03/15 10:22:29 art Exp $ */
! 2: /* $NetBSD: exception.c,v 1.32 2006/09/04 23:57:52 uwe Exp $ */
! 3: /* $NetBSD: syscall.c,v 1.6 2006/03/07 07:21:50 thorpej Exp $ */
! 4:
! 5: /*-
! 6: * Copyright (c) 2002 The NetBSD Foundation, Inc. All rights reserved.
! 7: * Copyright (c) 1990 The Regents of the University of California.
! 8: * All rights reserved.
! 9: *
! 10: * This code is derived from software contributed to Berkeley by
! 11: * the University of Utah, and William Jolitz.
! 12: *
! 13: * Redistribution and use in source and binary forms, with or without
! 14: * modification, are permitted provided that the following conditions
! 15: * are met:
! 16: * 1. Redistributions of source code must retain the above copyright
! 17: * notice, this list of conditions and the following disclaimer.
! 18: * 2. Redistributions in binary form must reproduce the above copyright
! 19: * notice, this list of conditions and the following disclaimer in the
! 20: * documentation and/or other materials provided with the distribution.
! 21: * 3. Neither the name of the University nor the names of its contributors
! 22: * may be used to endorse or promote products derived from this software
! 23: * without specific prior written permission.
! 24: *
! 25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 35: * SUCH DAMAGE.
! 36: *
! 37: * @(#)trap.c 7.4 (Berkeley) 5/13/91
! 38: */
! 39:
! 40: /*-
! 41: * Copyright (c) 1995 Charles M. Hannum. All rights reserved.
! 42: *
! 43: * This code is derived from software contributed to Berkeley by
! 44: * the University of Utah, and William Jolitz.
! 45: *
! 46: * Redistribution and use in source and binary forms, with or without
! 47: * modification, are permitted provided that the following conditions
! 48: * are met:
! 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.
! 61: *
! 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
! 72: * SUCH DAMAGE.
! 73: *
! 74: * @(#)trap.c 7.4 (Berkeley) 5/13/91
! 75: */
! 76:
! 77: /*
! 78: * SH3 Trap and System call handling
! 79: *
! 80: * T.Horiuchi 1998.06.8
! 81: */
! 82:
! 83: #include <sys/param.h>
! 84: #include <sys/systm.h>
! 85: #include <sys/proc.h>
! 86: #include <sys/pool.h>
! 87: #include <sys/user.h>
! 88: #include <sys/kernel.h>
! 89: #include <sys/signal.h>
! 90: #include <sys/syscall.h>
! 91:
! 92: #ifdef KTRACE
! 93: #include <sys/ktrace.h>
! 94: #endif
! 95:
! 96: #include "systrace.h"
! 97: #if NSYSTRACE > 0
! 98: #include <dev/systrace.h>
! 99: #endif
! 100:
! 101: #include <uvm/uvm_extern.h>
! 102:
! 103: #include <sh/cache.h>
! 104: #include <sh/cpu.h>
! 105: #include <sh/mmu.h>
! 106: #include <sh/trap.h>
! 107: #include <sh/userret.h>
! 108: #ifdef SH4
! 109: #include <sh/fpu.h>
! 110: #endif
! 111:
! 112: #ifdef DDB
! 113: #include <machine/db_machdep.h>
! 114: #endif
! 115:
! 116: const char * const exp_type[] = {
! 117: NULL, /* 000 (reset vector) */
! 118: NULL, /* 020 (reset vector) */
! 119: "TLB miss/invalid (load)", /* 040 EXPEVT_TLB_MISS_LD */
! 120: "TLB miss/invalid (store)", /* 060 EXPEVT_TLB_MISS_ST */
! 121: "initial page write", /* 080 EXPEVT_TLB_MOD */
! 122: "TLB protection violation (load)", /* 0a0 EXPEVT_TLB_PROT_LD */
! 123: "TLB protection violation (store)", /* 0c0 EXPEVT_TLB_PROT_ST */
! 124: "address error (load)", /* 0e0 EXPEVT_ADDR_ERR_LD */
! 125: "address error (store)", /* 100 EXPEVT_ADDR_ERR_ST */
! 126: "FPU", /* 120 EXPEVT_FPU */
! 127: NULL, /* 140 (reset vector) */
! 128: "unconditional trap (TRAPA)", /* 160 EXPEVT_TRAPA */
! 129: "reserved instruction code exception", /* 180 EXPEVT_RES_INST */
! 130: "illegal slot instruction exception", /* 1a0 EXPEVT_SLOT_INST */
! 131: NULL, /* 1c0 (external interrupt) */
! 132: "user break point trap", /* 1e0 EXPEVT_BREAK */
! 133: NULL, NULL, NULL, NULL, /* 200-260 */
! 134: NULL, NULL, NULL, NULL, /* 280-2e0 */
! 135: NULL, NULL, NULL, NULL, /* 300-360 */
! 136: NULL, NULL, NULL, NULL, /* 380-3e0 */
! 137: NULL, NULL, NULL, NULL, /* 400-460 */
! 138: NULL, NULL, NULL, NULL, /* 480-4e0 */
! 139: NULL, NULL, NULL, NULL, /* 500-560 */
! 140: NULL, NULL, NULL, NULL, /* 580-5e0 */
! 141: NULL, NULL, NULL, NULL, /* 600-660 */
! 142: NULL, NULL, NULL, NULL, /* 680-6e0 */
! 143: NULL, NULL, NULL, NULL, /* 700-760 */
! 144: NULL, NULL, NULL, NULL, /* 780-7e0 */
! 145: "FPU disabled", /* 800 EXPEVT_FPU_DISABLE */
! 146: "slot FPU disabled" /* 820 EXPEVT_FPU_SLOT_DISABLE */
! 147: };
! 148: const int exp_types = sizeof exp_type / sizeof exp_type[0];
! 149:
! 150: void general_exception(struct proc *, struct trapframe *, uint32_t);
! 151: void tlb_exception(struct proc *, struct trapframe *, uint32_t);
! 152: void ast(struct proc *, struct trapframe *);
! 153: void syscall(struct proc *, struct trapframe *);
! 154: void cachectl(struct proc *, struct trapframe *);
! 155:
! 156: /*
! 157: * void general_exception(struct proc *p, struct trapframe *tf):
! 158: * p ... curproc when exception occured.
! 159: * tf ... full user context.
! 160: * va ... fault va for user mode EXPEVT_ADDR_ERR_{LD,ST}
! 161: */
! 162: void
! 163: general_exception(struct proc *p, struct trapframe *tf, uint32_t va)
! 164: {
! 165: int expevt = tf->tf_expevt;
! 166: int tra;
! 167: boolean_t usermode = !KERNELMODE(tf->tf_ssr);
! 168: union sigval sv;
! 169:
! 170: uvmexp.traps++;
! 171:
! 172: /*
! 173: * This function is entered at splhigh. Restore the interrupt
! 174: * level to what it was when the trap occured.
! 175: */
! 176: splx(tf->tf_ssr & PSL_IMASK);
! 177:
! 178: if (usermode) {
! 179: if (p == NULL)
! 180: goto do_panic;
! 181: KDASSERT(p->p_md.md_regs == tf); /* check exception depth */
! 182: expevt |= EXP_USER;
! 183: }
! 184:
! 185: switch (expevt) {
! 186: case EXPEVT_BREAK:
! 187: if (kdb_trap(EXPEVT_BREAK, 0, tf))
! 188: return;
! 189: else
! 190: goto do_panic;
! 191: break;
! 192: case EXPEVT_TRAPA:
! 193: /* Check for ddb request */
! 194: tra = _reg_read_4(SH_(TRA));
! 195: if (tra == (_SH_TRA_BREAK << 2) &&
! 196: kdb_trap(expevt, tra, tf))
! 197: return;
! 198: else
! 199: goto do_panic;
! 200: break;
! 201: case EXPEVT_TRAPA | EXP_USER:
! 202: /* Check for debugger break */
! 203: tra = _reg_read_4(SH_(TRA));
! 204: switch (tra) {
! 205: case _SH_TRA_BREAK << 2:
! 206: tf->tf_spc -= 2; /* back to the breakpoint address */
! 207: sv.sival_ptr = (void *)tf->tf_spc;
! 208: trapsignal(p, SIGTRAP, expevt & ~EXP_USER, TRAP_BRKPT,
! 209: sv);
! 210: goto out;
! 211: case _SH_TRA_SYSCALL << 2:
! 212: syscall(p, tf);
! 213: return;
! 214: case _SH_TRA_CACHECTL << 2:
! 215: cachectl(p, tf);
! 216: return;
! 217: default:
! 218: sv.sival_ptr = (void *)tf->tf_spc;
! 219: trapsignal(p, SIGILL, expevt & ~EXP_USER, ILL_ILLTRP,
! 220: sv);
! 221: goto out;
! 222: }
! 223: break;
! 224:
! 225: case EXPEVT_ADDR_ERR_LD: /* FALLTHROUGH */
! 226: case EXPEVT_ADDR_ERR_ST:
! 227: KDASSERT(p && p->p_md.md_pcb->pcb_onfault != NULL);
! 228: if (p == NULL || p->p_md.md_pcb->pcb_onfault == 0)
! 229: goto do_panic;
! 230: tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault;
! 231: break;
! 232:
! 233: case EXPEVT_ADDR_ERR_LD | EXP_USER: /* FALLTHROUGH */
! 234: case EXPEVT_ADDR_ERR_ST | EXP_USER:
! 235: sv.sival_ptr = (void *)va;
! 236: if (((int)va) < 0)
! 237: trapsignal(p, SIGSEGV, expevt & ~EXP_USER, SEGV_ACCERR,
! 238: sv);
! 239: else
! 240: trapsignal(p, SIGBUS, expevt & ~EXP_USER, BUS_ADRALN,
! 241: sv);
! 242: goto out;
! 243:
! 244: case EXPEVT_RES_INST | EXP_USER: /* FALLTHROUGH */
! 245: case EXPEVT_SLOT_INST | EXP_USER:
! 246: sv.sival_ptr = (void *)tf->tf_spc;
! 247: trapsignal(p, SIGILL, expevt & ~EXP_USER, ILL_ILLOPC, sv);
! 248: goto out;
! 249:
! 250: case EXPEVT_BREAK | EXP_USER:
! 251: sv.sival_ptr = (void *)tf->tf_spc;
! 252: trapsignal(p, SIGTRAP, expevt & ~EXP_USER, TRAP_TRACE, sv);
! 253: goto out;
! 254:
! 255: #ifdef SH4
! 256: case EXPEVT_FPU_DISABLE | EXP_USER: /* FALLTHROUGH */
! 257: case EXPEVT_FPU_SLOT_DISABLE | EXP_USER:
! 258: sv.sival_ptr = (void *)tf->tf_spc;
! 259: trapsignal(p, SIGILL, expevt & ~EXP_USER, ILL_COPROC, sv);
! 260: goto out;
! 261:
! 262: case EXPEVT_FPU | EXP_USER:
! 263: {
! 264: int fpscr, sigi;
! 265:
! 266: /* XXX worth putting in the trapframe? */
! 267: __asm__ __volatile__ ("sts fpscr, %0" : "=r" (fpscr));
! 268: fpscr = (fpscr & FPSCR_CAUSE_MASK) >> FPSCR_CAUSE_SHIFT;
! 269: if (fpscr & FPEXC_E)
! 270: sigi = FPE_FLTINV; /* XXX any better value? */
! 271: else if (fpscr & FPEXC_V)
! 272: sigi = FPE_FLTINV;
! 273: else if (fpscr & FPEXC_Z)
! 274: sigi = FPE_FLTDIV;
! 275: else if (fpscr & FPEXC_O)
! 276: sigi = FPE_FLTOVF;
! 277: else if (fpscr & FPEXC_U)
! 278: sigi = FPE_FLTUND;
! 279: else if (fpscr & FPEXC_I)
! 280: sigi = FPE_FLTRES;
! 281: else
! 282: sigi = 0; /* shouldn't happen */
! 283: sv.sival_ptr = (void *)tf->tf_spc;
! 284: trapsignal(p, SIGFPE, expevt & ~EXP_USER, sigi, sv);
! 285: }
! 286: goto out;
! 287: #endif
! 288:
! 289: default:
! 290: goto do_panic;
! 291: }
! 292:
! 293: if (!usermode)
! 294: return;
! 295: out:
! 296: userret(p);
! 297: return;
! 298:
! 299: do_panic:
! 300: if ((expevt >> 5) < exp_types && exp_type[expevt >> 5] != NULL)
! 301: printf("fatal %s", exp_type[expevt >> 5]);
! 302: else
! 303: printf("EXPEVT 0x%03x", expevt);
! 304: printf(" in %s mode\n", expevt & EXP_USER ? "user" : "kernel");
! 305: printf("va %p spc %p ssr %p pr %p \n",
! 306: va, tf->tf_spc, tf->tf_ssr, tf->tf_pr);
! 307:
! 308: panic("general_exception");
! 309: /* NOTREACHED */
! 310: }
! 311:
! 312:
! 313: /*
! 314: * void tlb_exception(struct proc *p, struct trapframe *tf, uint32_t va):
! 315: * p ... curproc when exception occured.
! 316: * tf ... full user context.
! 317: * va ... fault address.
! 318: */
! 319: void
! 320: tlb_exception(struct proc *p, struct trapframe *tf, uint32_t va)
! 321: {
! 322: struct vm_map *map;
! 323: pmap_t pmap;
! 324: union sigval sv;
! 325: boolean_t usermode;
! 326: int err, track, ftype;
! 327: const char *panic_msg;
! 328:
! 329: #define TLB_ASSERT(assert, msg) \
! 330: do { \
! 331: if (!(assert)) { \
! 332: panic_msg = msg; \
! 333: goto tlb_panic; \
! 334: } \
! 335: } while(/*CONSTCOND*/0)
! 336:
! 337: /*
! 338: * This function is entered at splhigh. Restore the interrupt
! 339: * level to what it was when the trap occured.
! 340: */
! 341: splx(tf->tf_ssr & PSL_IMASK);
! 342:
! 343: usermode = !KERNELMODE(tf->tf_ssr);
! 344: if (usermode) {
! 345: KDASSERT(p->p_md.md_regs == tf);
! 346: } else {
! 347: KDASSERT(p == NULL || /* idle */
! 348: p == &proc0 || /* kthread */
! 349: p->p_md.md_regs != tf); /* other */
! 350: }
! 351:
! 352: switch (tf->tf_expevt) {
! 353: case EXPEVT_TLB_MISS_LD:
! 354: track = PVH_REFERENCED;
! 355: ftype = VM_PROT_READ;
! 356: break;
! 357: case EXPEVT_TLB_MISS_ST:
! 358: track = PVH_REFERENCED;
! 359: ftype = VM_PROT_WRITE;
! 360: break;
! 361: case EXPEVT_TLB_MOD:
! 362: track = PVH_REFERENCED | PVH_MODIFIED;
! 363: ftype = VM_PROT_WRITE;
! 364: break;
! 365: case EXPEVT_TLB_PROT_LD:
! 366: TLB_ASSERT((int)va > 0,
! 367: "kernel virtual protection fault (load)");
! 368: if (usermode) {
! 369: sv.sival_ptr = (void *)va;
! 370: trapsignal(p, SIGSEGV, tf->tf_expevt, SEGV_ACCERR, sv);
! 371: goto user_fault;
! 372: } else {
! 373: TLB_ASSERT(p->p_md.md_pcb->pcb_onfault != NULL,
! 374: "no copyin/out fault handler (load protection)");
! 375: tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault;
! 376: }
! 377: return;
! 378:
! 379: case EXPEVT_TLB_PROT_ST:
! 380: track = 0; /* call uvm_fault first. (COW) */
! 381: ftype = VM_PROT_WRITE;
! 382: break;
! 383:
! 384: default:
! 385: TLB_ASSERT(0, "impossible expevt");
! 386: }
! 387:
! 388: /* Select address space */
! 389: if (usermode) {
! 390: TLB_ASSERT(p != NULL, "no curproc");
! 391: map = &p->p_vmspace->vm_map;
! 392: pmap = map->pmap;
! 393: } else {
! 394: if ((int)va < 0) {
! 395: map = kernel_map;
! 396: pmap = pmap_kernel();
! 397: } else {
! 398: TLB_ASSERT(p != NULL &&
! 399: p->p_md.md_pcb->pcb_onfault != NULL,
! 400: "invalid user-space access from kernel mode");
! 401: if (va == 0) {
! 402: tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault;
! 403: return;
! 404: }
! 405: map = &p->p_vmspace->vm_map;
! 406: pmap = map->pmap;
! 407: }
! 408: }
! 409:
! 410: /* Lookup page table. if entry found, load it. */
! 411: if (track && __pmap_pte_load(pmap, va, track)) {
! 412: if (usermode)
! 413: userret(p);
! 414: return;
! 415: }
! 416:
! 417: err = uvm_fault(map, va, 0, ftype);
! 418:
! 419: /* User stack extension */
! 420: if (map != kernel_map &&
! 421: (va >= (vaddr_t)p->p_vmspace->vm_maxsaddr) &&
! 422: (va < USRSTACK)) {
! 423: if (err == 0)
! 424: uvm_grow(p, va);
! 425: else if (err == EACCES)
! 426: err = EFAULT;
! 427: }
! 428:
! 429: /* Page in. load PTE to TLB. */
! 430: if (err == 0) {
! 431: boolean_t loaded = __pmap_pte_load(pmap, va, track);
! 432: TLB_ASSERT(loaded, "page table entry not found");
! 433: if (usermode)
! 434: userret(p);
! 435: return;
! 436: }
! 437:
! 438: /* Page not found. */
! 439: if (usermode) {
! 440: sv.sival_ptr = (void *)va;
! 441: if (err == ENOMEM) {
! 442: printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
! 443: p->p_pid, p->p_comm,
! 444: p->p_cred && p->p_ucred ?
! 445: (int)p->p_ucred->cr_uid : -1);
! 446: trapsignal(p, SIGKILL, tf->tf_expevt, SEGV_MAPERR, sv);
! 447: } else
! 448: trapsignal(p, SIGSEGV, tf->tf_expevt, SEGV_MAPERR, sv);
! 449: goto user_fault;
! 450: } else {
! 451: TLB_ASSERT(p->p_md.md_pcb->pcb_onfault,
! 452: "no copyin/out fault handler (page not found)");
! 453: tf->tf_spc = (int)p->p_md.md_pcb->pcb_onfault;
! 454: }
! 455: return;
! 456:
! 457: user_fault:
! 458: userret(p);
! 459: ast(p, tf);
! 460: return;
! 461:
! 462: tlb_panic:
! 463: panic("tlb_exception: %s\n"
! 464: "expevt=%x va=%08x ssr=%08x spc=%08x proc=%p onfault=%p",
! 465: panic_msg, tf->tf_expevt, va, tf->tf_ssr, tf->tf_spc,
! 466: p, p ? p->p_md.md_pcb->pcb_onfault : NULL);
! 467: #undef TLB_ASSERT
! 468: }
! 469:
! 470:
! 471: /*
! 472: * void ast(struct proc *p, struct trapframe *tf):
! 473: * p ... curproc when exception occured.
! 474: * tf ... full user context.
! 475: * This is called upon exception return. if return from kernel to user,
! 476: * handle asynchronous software traps and context switch if needed.
! 477: */
! 478: void
! 479: ast(struct proc *p, struct trapframe *tf)
! 480: {
! 481: if (KERNELMODE(tf->tf_ssr))
! 482: return;
! 483: KDASSERT(p != NULL);
! 484: KDASSERT(p->p_md.md_regs == tf);
! 485:
! 486: while (p->p_md.md_astpending) {
! 487: uvmexp.softs++;
! 488: p->p_md.md_astpending = 0;
! 489:
! 490: if (p->p_flag & P_OWEUPC) {
! 491: ADDUPROF(p);
! 492: }
! 493:
! 494: if (want_resched) {
! 495: /* We are being preempted. */
! 496: preempt(NULL);
! 497: }
! 498:
! 499: userret(p);
! 500: }
! 501: }
! 502:
! 503: void
! 504: cachectl(struct proc *p, struct trapframe *tf)
! 505: {
! 506: vaddr_t va;
! 507: vsize_t len;
! 508:
! 509: if (!SH_HAS_UNIFIED_CACHE) {
! 510: va = (vaddr_t)tf->tf_r4;
! 511: len = (vsize_t)tf->tf_r5;
! 512:
! 513: if (/* va < VM_MIN_ADDRESS || */ va >= VM_MAXUSER_ADDRESS ||
! 514: va + len <= va || va + len >= VM_MAXUSER_ADDRESS)
! 515: len = 0;
! 516:
! 517: if (len != 0)
! 518: sh_icache_sync_range_index(va, len);
! 519: }
! 520:
! 521: userret(p);
! 522: }
! 523:
! 524: void
! 525: syscall(struct proc *p, struct trapframe *tf)
! 526: {
! 527: caddr_t params;
! 528: const struct sysent *callp;
! 529: int error, oerror, opc, nsys;
! 530: size_t argsize;
! 531: register_t code, args[8], rval[2], ocode;
! 532:
! 533: uvmexp.syscalls++;
! 534:
! 535: opc = tf->tf_spc;
! 536: ocode = code = tf->tf_r0;
! 537:
! 538: nsys = p->p_emul->e_nsysent;
! 539: callp = p->p_emul->e_sysent;
! 540:
! 541: params = (caddr_t)tf->tf_r15;
! 542:
! 543: switch (code) {
! 544: case SYS_syscall:
! 545: /*
! 546: * Code is first argument, followed by actual args.
! 547: */
! 548: code = tf->tf_r4;
! 549: break;
! 550: case SYS___syscall:
! 551: /*
! 552: * Like syscall, but code is a quad, so as to maintain
! 553: * quad alignment for the rest of the arguments.
! 554: */
! 555: if (callp != sysent)
! 556: break;
! 557: #if _BYTE_ORDER == BIG_ENDIAN
! 558: code = tf->tf_r5;
! 559: #else
! 560: code = tf->tf_r4;
! 561: #endif
! 562: break;
! 563: default:
! 564: break;
! 565: }
! 566: if (code < 0 || code >= nsys)
! 567: callp += p->p_emul->e_nosys; /* illegal */
! 568: else
! 569: callp += code;
! 570: argsize = callp->sy_argsize;
! 571: #ifdef DIAGNOSTIC
! 572: if (argsize > sizeof args) {
! 573: callp += p->p_emul->e_nosys - code;
! 574: goto bad;
! 575: }
! 576: #endif
! 577:
! 578: switch (ocode) {
! 579: case SYS_syscall:
! 580: if (argsize) {
! 581: args[0] = tf->tf_r5;
! 582: args[1] = tf->tf_r6;
! 583: args[2] = tf->tf_r7;
! 584: if (argsize > 3 * sizeof(int)) {
! 585: argsize -= 3 * sizeof(int);
! 586: error = copyin(params, (caddr_t)&args[3],
! 587: argsize);
! 588: } else
! 589: error = 0;
! 590: } else
! 591: error = 0;
! 592: break;
! 593: case SYS___syscall:
! 594: if (argsize) {
! 595: args[0] = tf->tf_r6;
! 596: args[1] = tf->tf_r7;
! 597: if (argsize > 2 * sizeof(int)) {
! 598: argsize -= 2 * sizeof(int);
! 599: error = copyin(params, (caddr_t)&args[2],
! 600: argsize);
! 601: } else
! 602: error = 0;
! 603: } else
! 604: error = 0;
! 605: break;
! 606: default:
! 607: if (argsize) {
! 608: args[0] = tf->tf_r4;
! 609: args[1] = tf->tf_r5;
! 610: args[2] = tf->tf_r6;
! 611: args[3] = tf->tf_r7;
! 612: if (argsize > 4 * sizeof(int)) {
! 613: argsize -= 4 * sizeof(int);
! 614: error = copyin(params, (caddr_t)&args[4],
! 615: argsize);
! 616: } else
! 617: error = 0;
! 618: } else
! 619: error = 0;
! 620: break;
! 621: }
! 622:
! 623: if (error)
! 624: goto bad;
! 625:
! 626: #ifdef SYSCALL_DEBUG
! 627: scdebug_call(p, code, args);
! 628: #endif
! 629: #ifdef KTRACE
! 630: if (KTRPOINT(p, KTR_SYSCALL))
! 631: ktrsyscall(p, code, callp->sy_argsize, args);
! 632: #endif
! 633:
! 634: rval[0] = 0;
! 635: rval[1] = tf->tf_r1;
! 636: #if NSYSTRACE > 0
! 637: if (ISSET(p->p_flag, P_SYSTRACE))
! 638: error = systrace_redirect(code, p, args, rval);
! 639: else
! 640: #endif
! 641: error = (*callp->sy_call)(p, args, rval);
! 642:
! 643: switch (oerror = error) {
! 644: case 0:
! 645: tf->tf_r0 = rval[0];
! 646: tf->tf_r1 = rval[1];
! 647: tf->tf_ssr |= PSL_TBIT; /* T bit */
! 648: break;
! 649: case ERESTART:
! 650: /* 2 = TRAPA instruction size */
! 651: tf->tf_spc = opc - 2;
! 652: break;
! 653: case EJUSTRETURN:
! 654: /* nothing to do */
! 655: break;
! 656: default:
! 657: bad:
! 658: if (p->p_emul->e_errno)
! 659: error = p->p_emul->e_errno[error];
! 660: tf->tf_r0 = error;
! 661: tf->tf_ssr &= ~PSL_TBIT; /* T bit */
! 662: break;
! 663: }
! 664:
! 665: #ifdef SYSCALL_DEBUG
! 666: scdebug_ret(p, code, oerror, rval);
! 667: #endif
! 668: userret(p);
! 669: #ifdef KTRACE
! 670: if (KTRPOINT(p, KTR_SYSRET))
! 671: ktrsysret(p, code, oerror, rval[0]);
! 672: #endif
! 673: }
! 674:
! 675: /*
! 676: * void child_return(void *arg):
! 677: *
! 678: * uvm_fork sets this routine to proc_trampoline's service function.
! 679: * when returning from here, jump to userland.
! 680: */
! 681: void
! 682: child_return(void *arg)
! 683: {
! 684: struct proc *p = arg;
! 685: struct trapframe *tf = p->p_md.md_regs;
! 686:
! 687: tf->tf_r0 = 0;
! 688: tf->tf_ssr |= PSL_TBIT; /* This indicates no error. */
! 689:
! 690: userret(p);
! 691:
! 692: #ifdef KTRACE
! 693: if (KTRPOINT(p, KTR_SYSRET))
! 694: ktrsysret(p,
! 695: (p->p_flag & P_PPWAIT) ? SYS_vfork : SYS_fork, 0, 0);
! 696: #endif
! 697: }
! 698:
CVSweb