Annotation of sys/arch/hppa64/hppa64/trap.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: trap.c,v 1.7 2007/03/15 10:22:29 art Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2005 Michael Shalayeff
! 5: * All rights reserved.
! 6: *
! 7: * Permission to use, copy, modify, and distribute this software for any
! 8: * purpose with or without fee is hereby granted, provided that the above
! 9: * copyright notice and this permission notice appear in all copies.
! 10: *
! 11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 15: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
! 16: * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
! 17: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 18: */
! 19:
! 20: #define TRAPDEBUG
! 21:
! 22: #include <sys/param.h>
! 23: #include <sys/systm.h>
! 24: #include <sys/syscall.h>
! 25: #include <sys/ktrace.h>
! 26: #include <sys/proc.h>
! 27: #include <sys/signalvar.h>
! 28: #include <sys/user.h>
! 29:
! 30: #include <net/netisr.h>
! 31:
! 32: #include "systrace.h"
! 33: #include <dev/systrace.h>
! 34:
! 35: #include <uvm/uvm.h>
! 36:
! 37: #include <machine/autoconf.h>
! 38: #include <machine/psl.h>
! 39:
! 40: #include <machine/db_machdep.h> /* XXX always needed for inst_store() */
! 41: #ifdef DDB
! 42: #ifdef TRAPDEBUG
! 43: #include <ddb/db_output.h>
! 44: #endif
! 45: #endif
! 46:
! 47: const char *trap_type[] = {
! 48: "invalid",
! 49: "HPMC",
! 50: "power failure",
! 51: "recovery counter",
! 52: "external interrupt",
! 53: "LPMC",
! 54: "ITLB miss fault",
! 55: "instruction protection",
! 56: "Illegal instruction",
! 57: "break instruction",
! 58: "privileged operation",
! 59: "privileged register",
! 60: "overflow",
! 61: "conditional",
! 62: "assist exception",
! 63: "DTLB miss",
! 64: "ITLB non-access miss",
! 65: "DTLB non-access miss",
! 66: "data protection/rights/alignment",
! 67: "data break",
! 68: "TLB dirty",
! 69: "page reference",
! 70: "assist emulation",
! 71: "higher-priv transfer",
! 72: "lower-priv transfer",
! 73: "taken branch",
! 74: "data access rights",
! 75: "data protection",
! 76: "unaligned data ref",
! 77: };
! 78: int trap_types = sizeof(trap_type)/sizeof(trap_type[0]);
! 79:
! 80: int want_resched, astpending;
! 81:
! 82: #define frame_regmap(tf,r) (((register_t *)(tf))[hppa64_regmap[(r)]])
! 83: u_char hppa64_regmap[32] = {
! 84: offsetof(struct trapframe, tf_pad[0]) / 8, /* r0 XXX */
! 85: offsetof(struct trapframe, tf_r1) / 8,
! 86: offsetof(struct trapframe, tf_rp) / 8,
! 87: offsetof(struct trapframe, tf_r3) / 8,
! 88: offsetof(struct trapframe, tf_r4) / 8,
! 89: offsetof(struct trapframe, tf_r5) / 8,
! 90: offsetof(struct trapframe, tf_r6) / 8,
! 91: offsetof(struct trapframe, tf_r7) / 8,
! 92: offsetof(struct trapframe, tf_r8) / 8,
! 93: offsetof(struct trapframe, tf_r9) / 8,
! 94: offsetof(struct trapframe, tf_r10) / 8,
! 95: offsetof(struct trapframe, tf_r11) / 8,
! 96: offsetof(struct trapframe, tf_r12) / 8,
! 97: offsetof(struct trapframe, tf_r13) / 8,
! 98: offsetof(struct trapframe, tf_r14) / 8,
! 99: offsetof(struct trapframe, tf_r15) / 8,
! 100: offsetof(struct trapframe, tf_r16) / 8,
! 101: offsetof(struct trapframe, tf_r17) / 8,
! 102: offsetof(struct trapframe, tf_r18) / 8,
! 103: offsetof(struct trapframe, tf_args[7]) / 8,
! 104: offsetof(struct trapframe, tf_args[6]) / 8,
! 105: offsetof(struct trapframe, tf_args[5]) / 8,
! 106: offsetof(struct trapframe, tf_args[4]) / 8,
! 107: offsetof(struct trapframe, tf_args[3]) / 8,
! 108: offsetof(struct trapframe, tf_args[2]) / 8,
! 109: offsetof(struct trapframe, tf_args[1]) / 8,
! 110: offsetof(struct trapframe, tf_args[0]) / 8,
! 111: offsetof(struct trapframe, tf_dp) / 8,
! 112: offsetof(struct trapframe, tf_ret0) / 8,
! 113: offsetof(struct trapframe, tf_ret1) / 8,
! 114: offsetof(struct trapframe, tf_sp) / 8,
! 115: offsetof(struct trapframe, tf_r31) / 8,
! 116: };
! 117:
! 118: void
! 119: userret(struct proc *p, register_t pc, u_quad_t oticks)
! 120: {
! 121: int sig;
! 122:
! 123: /* take pending signals */
! 124: while ((sig = CURSIG(p)) != 0)
! 125: postsig(sig);
! 126:
! 127: p->p_priority = p->p_usrpri;
! 128: if (astpending) {
! 129: astpending = 0;
! 130: if (p->p_flag & P_OWEUPC) {
! 131: ADDUPROF(p);
! 132: }
! 133: }
! 134: if (want_resched) {
! 135: /*
! 136: * We're being preempted.
! 137: */
! 138: preempt(NULL);
! 139: while ((sig = CURSIG(p)) != 0)
! 140: postsig(sig);
! 141: }
! 142:
! 143: /*
! 144: * If profiling, charge recent system time to the trapped pc.
! 145: */
! 146: if (p->p_flag & P_PROFIL) {
! 147: extern int psratio;
! 148:
! 149: addupc_task(p, pc, (int)(p->p_sticks - oticks) * psratio);
! 150: }
! 151:
! 152: p->p_cpu->ci_schedstate.spc_curpriority = p->p_priority;
! 153: }
! 154:
! 155: void
! 156: trap(type, frame)
! 157: int type;
! 158: struct trapframe *frame;
! 159: {
! 160: extern int cpl; /* from locore.o */
! 161: struct proc *p = curproc;
! 162: vaddr_t va;
! 163: struct vm_map *map;
! 164: struct vmspace *vm;
! 165: register vm_prot_t vftype;
! 166: register pa_space_t space;
! 167: union sigval sv;
! 168: u_int opcode;
! 169: int ret, trapnum;
! 170: const char *tts;
! 171: vm_fault_t fault = VM_FAULT_INVALID;
! 172: #ifdef DIAGNOSTIC
! 173: long oldcpl;
! 174: #endif
! 175:
! 176: trapnum = type & ~T_USER;
! 177: opcode = frame->tf_iir;
! 178: if (trapnum <= T_EXCEPTION || trapnum == T_HIGHERPL ||
! 179: trapnum == T_LOWERPL || trapnum == T_TAKENBR ||
! 180: trapnum == T_IDEBUG || trapnum == T_PERFMON) {
! 181: va = frame->tf_iioq[0];
! 182: space = frame->tf_iisq[0];
! 183: vftype = UVM_PROT_EXEC;
! 184: } else {
! 185: va = frame->tf_ior;
! 186: space = frame->tf_isr;
! 187: if (va == frame->tf_iioq[0])
! 188: vftype = UVM_PROT_EXEC;
! 189: else if (inst_store(opcode))
! 190: vftype = UVM_PROT_WRITE;
! 191: else
! 192: vftype = UVM_PROT_READ;
! 193: }
! 194:
! 195: if (frame->tf_flags & TFF_LAST)
! 196: p->p_md.md_regs = frame;
! 197:
! 198: if (trapnum > trap_types)
! 199: tts = "reserved";
! 200: else
! 201: tts = trap_type[trapnum];
! 202:
! 203: #ifdef TRAPDEBUG
! 204: if (trapnum != T_INTERRUPT && trapnum != T_IBREAK)
! 205: db_printf("trap: %x, %s for %x:%lx at %x:%lx, fl=%x, fp=%p\n",
! 206: type, tts, space, va, frame->tf_iisq[0],
! 207: frame->tf_iioq[0], frame->tf_flags, frame);
! 208: else if (trapnum == T_IBREAK)
! 209: db_printf("trap: break instruction %x:%x at %x:%lx, fp=%p\n",
! 210: opcode & 0x1f, (opcode >> 13) & 0x1fff,
! 211: frame->tf_iisq[0], frame->tf_iioq[0], frame);
! 212:
! 213: {
! 214: extern int etext;
! 215: if (frame < (struct trapframe *)&etext) {
! 216: printf("trap: bogus frame ptr %p\n", frame);
! 217: goto dead_end;
! 218: }
! 219: }
! 220: #endif
! 221: if (trapnum != T_INTERRUPT) {
! 222: uvmexp.traps++;
! 223: /* TODO mtctl(frame->tf_eiem, CR_EIEM); */
! 224: }
! 225:
! 226: switch (type) {
! 227: case T_NONEXIST:
! 228: case T_NONEXIST | T_USER:
! 229: /* we've got screwed up by the central scrutinizer */
! 230: printf("trap: elvis has just left the building!\n");
! 231: goto dead_end;
! 232:
! 233: case T_RECOVERY:
! 234: case T_RECOVERY | T_USER:
! 235: /* XXX will implement later */
! 236: printf("trap: handicapped");
! 237: goto dead_end;
! 238:
! 239: #ifdef DIAGNOSTIC
! 240: case T_EXCEPTION:
! 241: panic("FPU/SFU emulation botch");
! 242:
! 243: /* these just can't happen ever */
! 244: case T_PRIV_OP:
! 245: case T_PRIV_REG:
! 246: /* these just can't make it to the trap() ever */
! 247: case T_HPMC:
! 248: case T_HPMC | T_USER:
! 249: #endif
! 250: case T_IBREAK:
! 251: case T_DATALIGN:
! 252: case T_DBREAK:
! 253: dead_end:
! 254: #ifdef DDB
! 255: if (kdb_trap (type, va, frame)) {
! 256: if (type == T_IBREAK) {
! 257: /* skip break instruction */
! 258: frame->tf_iioq[0] = frame->tf_iioq[1];
! 259: frame->tf_iioq[1] += 4;
! 260: }
! 261: return;
! 262: }
! 263: #else
! 264: if (type == T_DATALIGN)
! 265: panic ("trap: %s at 0x%x", tts, va);
! 266: else
! 267: panic ("trap: no debugger for \"%s\" (%d)", tts, type);
! 268: #endif
! 269: break;
! 270:
! 271: case T_IBREAK | T_USER:
! 272: case T_DBREAK | T_USER:
! 273: /* pass to user debugger */
! 274: trapsignal(p, SIGTRAP, type &~ T_USER, TRAP_BRKPT, sv);
! 275: break;
! 276:
! 277: case T_EXCEPTION | T_USER: {
! 278: u_int64_t *fpp = (u_int64_t *)frame->tf_cr30;
! 279: u_int32_t *pex;
! 280: int i, flt;
! 281:
! 282: pex = (u_int32_t *)&fpp[0];
! 283: for (i = 0, pex++; i < 7 && !*pex; i++, pex++);
! 284: flt = 0;
! 285: if (i < 7) {
! 286: u_int32_t stat = HPPA_FPU_OP(*pex);
! 287: if (stat & HPPA_FPU_UNMPL)
! 288: flt = FPE_FLTINV;
! 289: else if (stat & (HPPA_FPU_V << 1))
! 290: flt = FPE_FLTINV;
! 291: else if (stat & (HPPA_FPU_Z << 1))
! 292: flt = FPE_FLTDIV;
! 293: else if (stat & (HPPA_FPU_I << 1))
! 294: flt = FPE_FLTRES;
! 295: else if (stat & (HPPA_FPU_O << 1))
! 296: flt = FPE_FLTOVF;
! 297: else if (stat & (HPPA_FPU_U << 1))
! 298: flt = FPE_FLTUND;
! 299: /* still left: under/over-flow w/ inexact */
! 300:
! 301: /* cleanup exceptions (XXX deliver all ?) */
! 302: while (i++ < 7)
! 303: *pex++ = 0;
! 304: }
! 305: /* reset the trap flag, as if there was none */
! 306: fpp[0] &= ~(((u_int64_t)HPPA_FPU_T) << 32);
! 307: /* flush out, since load is done from phys, only 4 regs */
! 308: fdcache(HPPA_SID_KERNEL, (vaddr_t)fpp, 8 * 4);
! 309:
! 310: sv.sival_int = va;
! 311: trapsignal(p, SIGFPE, type &~ T_USER, flt, sv);
! 312: }
! 313: break;
! 314:
! 315: case T_EMULATION:
! 316: panic("trap: emulation trap in the kernel");
! 317: break;
! 318:
! 319: case T_EMULATION | T_USER:
! 320: sv.sival_int = va;
! 321: trapsignal(p, SIGILL, type &~ T_USER, ILL_COPROC, sv);
! 322: break;
! 323:
! 324: case T_OVERFLOW | T_USER:
! 325: sv.sival_int = va;
! 326: trapsignal(p, SIGFPE, type &~ T_USER, FPE_INTOVF, sv);
! 327: break;
! 328:
! 329: case T_CONDITION | T_USER:
! 330: sv.sival_int = va;
! 331: trapsignal(p, SIGFPE, type &~ T_USER, FPE_INTDIV, sv);
! 332: break;
! 333:
! 334: case T_PRIV_OP | T_USER:
! 335: sv.sival_int = va;
! 336: trapsignal(p, SIGILL, type &~ T_USER, ILL_PRVOPC, sv);
! 337: break;
! 338:
! 339: case T_PRIV_REG | T_USER:
! 340: sv.sival_int = va;
! 341: trapsignal(p, SIGILL, type &~ T_USER, ILL_PRVREG, sv);
! 342: break;
! 343:
! 344: /* these should never got here */
! 345: case T_HIGHERPL | T_USER:
! 346: case T_LOWERPL | T_USER:
! 347: sv.sival_int = va;
! 348: trapsignal(p, SIGSEGV, vftype, SEGV_ACCERR, sv);
! 349: break;
! 350:
! 351: case T_IPROT | T_USER:
! 352: case T_DPROT | T_USER:
! 353: sv.sival_int = va;
! 354: trapsignal(p, SIGSEGV, vftype, SEGV_ACCERR, sv);
! 355: break;
! 356:
! 357: case T_ITLBMISSNA:
! 358: case T_ITLBMISSNA | T_USER:
! 359: case T_DTLBMISSNA:
! 360: case T_DTLBMISSNA | T_USER:
! 361: if (space == HPPA_SID_KERNEL)
! 362: map = kernel_map;
! 363: else {
! 364: vm = p->p_vmspace;
! 365: map = &vm->vm_map;
! 366: }
! 367:
! 368: /* dig probei?,[rw] insns */
! 369: if ((opcode & 0xfc001f80) == 0x04001180) {
! 370: int pl;
! 371:
! 372: if (opcode & 0x2000)
! 373: pl = (opcode >> 16) & 3;
! 374: else
! 375: pl = frame_regmap(frame,
! 376: (opcode >> 16) & 0x1f) & 3;
! 377:
! 378: if ((type & T_USER && space == HPPA_SID_KERNEL) ||
! 379: (type & T_USER && !pl) ||
! 380: (type & T_USER && va >= VM_MAXUSER_ADDRESS) ||
! 381: uvm_fault(map, trunc_page(va), fault,
! 382: opcode & 0x40? UVM_PROT_WRITE : UVM_PROT_READ)) {
! 383: frame_regmap(frame, opcode & 0x1f) = 0;
! 384: frame->tf_ipsw |= PSL_N;
! 385: }
! 386: } else if (type & T_USER) {
! 387: sv.sival_int = va;
! 388: trapsignal(p, SIGILL, type & ~T_USER, ILL_ILLTRP, sv);
! 389: } else
! 390: panic("trap: %s @ 0x%x:0x%x for 0x%x:0x%x irr 0x%08x",
! 391: tts, frame->tf_iisq[0], frame->tf_iioq[0],
! 392: space, va, opcode);
! 393: break;
! 394:
! 395: case T_TLB_DIRTY:
! 396: case T_TLB_DIRTY | T_USER:
! 397: case T_DATACC:
! 398: case T_DATACC | T_USER:
! 399: fault = VM_FAULT_PROTECT;
! 400: case T_ITLBMISS:
! 401: case T_ITLBMISS | T_USER:
! 402: case T_DTLBMISS:
! 403: case T_DTLBMISS | T_USER:
! 404: /*
! 405: * it could be a kernel map for exec_map faults
! 406: */
! 407: if (space == HPPA_SID_KERNEL)
! 408: map = kernel_map;
! 409: else {
! 410: vm = p->p_vmspace;
! 411: map = &vm->vm_map;
! 412: }
! 413:
! 414: /*
! 415: * user faults out of user addr space are always a fail,
! 416: * this happens on va >= VM_MAXUSER_ADDRESS, where
! 417: * space id will be zero and therefore cause
! 418: * a misbehave lower in the code.
! 419: *
! 420: * also check that faulted space id matches the curproc.
! 421: */
! 422: if ((type & T_USER && va >= VM_MAXUSER_ADDRESS) ||
! 423: (type & T_USER && map->pmap->pm_space != space)) {
! 424: sv.sival_int = va;
! 425: trapsignal(p, SIGSEGV, vftype, SEGV_ACCERR, sv);
! 426: break;
! 427: }
! 428:
! 429: printf("here\n");
! 430: ret = uvm_fault(map, trunc_page(va), fault, vftype);
! 431:
! 432: /*
! 433: * If this was a stack access we keep track of the maximum
! 434: * accessed stack size. Also, if uvm_fault gets a protection
! 435: * failure it is due to accessing the stack region outside
! 436: * the current limit and we need to reflect that as an access
! 437: * error.
! 438: */
! 439: if (space != HPPA_SID_KERNEL &&
! 440: va < (vaddr_t)vm->vm_minsaddr) {
! 441: if (ret == 0)
! 442: uvm_grow(p, va);
! 443: else if (ret == EACCES)
! 444: ret = EFAULT;
! 445: }
! 446:
! 447: if (ret != 0) {
! 448: if (type & T_USER) {
! 449: sv.sival_int = va;
! 450: trapsignal(p, SIGSEGV, vftype,
! 451: ret == EACCES? SEGV_ACCERR : SEGV_MAPERR,
! 452: sv);
! 453: } else {
! 454: if (p && p->p_addr->u_pcb.pcb_onfault) {
! 455: frame->tf_iioq[1] = 4 +
! 456: (frame->tf_iioq[0] =
! 457: p->p_addr->u_pcb.pcb_onfault);
! 458: #ifdef DDB
! 459: frame->tf_iir = 0;
! 460: #endif
! 461: } else {
! 462: panic("trap: "
! 463: "uvm_fault(%p, %lx, %d, %d): %d",
! 464: map, va, fault, vftype, ret);
! 465: }
! 466: }
! 467: }
! 468: break;
! 469:
! 470: case T_DATALIGN | T_USER:
! 471: sv.sival_int = va;
! 472: trapsignal(p, SIGBUS, vftype, BUS_ADRALN, sv);
! 473: break;
! 474:
! 475: case T_INTERRUPT:
! 476: case T_INTERRUPT | T_USER:
! 477: /* cpu_intr(frame); */
! 478: printf("eirr 0x%08x\n", mfctl(CR_EIRR));
! 479: break;
! 480:
! 481: case T_CONDITION:
! 482: panic("trap: divide by zero in the kernel");
! 483: break;
! 484:
! 485: case T_ILLEGAL:
! 486: case T_ILLEGAL | T_USER:
! 487: /* see if it's a SPOP1,,0 */
! 488: if ((opcode & 0xfffffe00) == 0x10000200) {
! 489: frame_regmap(frame, opcode & 0x1f) = 0;
! 490: frame->tf_ipsw |= PSL_N;
! 491: break;
! 492: }
! 493: if (type & T_USER) {
! 494: sv.sival_int = va;
! 495: trapsignal(p, SIGILL, type &~ T_USER, ILL_ILLOPC, sv);
! 496: break;
! 497: }
! 498: /* FALLTHROUGH */
! 499:
! 500: case T_LOWERPL:
! 501: case T_DPROT:
! 502: case T_IPROT:
! 503: case T_OVERFLOW:
! 504: case T_HIGHERPL:
! 505: case T_TAKENBR:
! 506: case T_POWERFAIL:
! 507: case T_LPMC:
! 508: case T_PAGEREF:
! 509: case T_DATAPID:
! 510: case T_DATAPID | T_USER:
! 511: if (0 /* T-chip */) {
! 512: break;
! 513: }
! 514: /* FALLTHROUGH to unimplemented */
! 515: default:
! 516: #if 1
! 517: if (kdb_trap (type, va, frame))
! 518: return;
! 519: #endif
! 520: panic("trap: unimplemented \'%s\' (%d)", tts, trapnum);
! 521: }
! 522:
! 523: #ifdef DIAGNOSTIC
! 524: if (cpl != oldcpl)
! 525: printf("WARNING: SPL (%d) NOT LOWERED ON "
! 526: "TRAP (%d) EXIT\n", cpl, trapnum);
! 527: #endif
! 528:
! 529: if (trapnum != T_INTERRUPT)
! 530: splx(cpl); /* process softints */
! 531:
! 532: /*
! 533: * in case we were interrupted from the syscall gate page
! 534: * treat this as we were not realy running user code no more
! 535: * for weird things start to happen on return to the userland
! 536: * and also see a note in locore.S:TLABEL(all)
! 537: */
! 538: if ((type & T_USER) &&
! 539: (frame->tf_iioq[0] & ~PAGE_MASK) != SYSCALLGATE)
! 540: userret(p, frame->tf_iioq[0], 0);
! 541: }
! 542:
! 543: void
! 544: child_return(arg)
! 545: void *arg;
! 546: {
! 547: struct proc *p = (struct proc *)arg;
! 548: struct trapframe *tf = p->p_md.md_regs;
! 549:
! 550: /*
! 551: * Set up return value registers as libc:fork() expects
! 552: */
! 553: tf->tf_ret0 = 0;
! 554: tf->tf_ret1 = 1; /* ischild */
! 555: tf->tf_r1 = 0; /* errno */
! 556:
! 557: userret(p, tf->tf_iioq[0], 0);
! 558: #ifdef KTRACE
! 559: if (KTRPOINT(p, KTR_SYSRET))
! 560: ktrsysret(p,
! 561: (p->p_flag & P_PPWAIT) ? SYS_vfork : SYS_fork, 0, 0);
! 562: #endif
! 563: }
! 564:
! 565:
! 566: /*
! 567: * call actual syscall routine
! 568: */
! 569: void
! 570: syscall(struct trapframe *frame)
! 571: {
! 572: extern int cpl; /* from locore.o */
! 573: register struct proc *p = curproc;
! 574: register const struct sysent *callp;
! 575: int retq, nsys, code, argsize, argoff, oerror, error;
! 576: register_t args[8], rval[2];
! 577: #ifdef DIAGNOSTIC
! 578: long oldcpl;
! 579: #endif
! 580:
! 581: /* TODO syscall */
! 582:
! 583: uvmexp.syscalls++;
! 584:
! 585: if (!USERMODE(frame->tf_iioq[0]))
! 586: panic("syscall");
! 587:
! 588: p->p_md.md_regs = frame;
! 589: nsys = p->p_emul->e_nsysent;
! 590: callp = p->p_emul->e_sysent;
! 591:
! 592: argoff = 4; retq = 0;
! 593: switch (code = frame->tf_r1) {
! 594: case SYS_syscall:
! 595: code = frame->tf_args[0];
! 596: args[0] = frame->tf_args[1];
! 597: args[1] = frame->tf_args[2];
! 598: args[2] = frame->tf_args[3];
! 599: argoff = 3;
! 600: break;
! 601: case SYS___syscall:
! 602: if (callp != sysent)
! 603: break;
! 604: /*
! 605: * this works, because quads get magically swapped
! 606: * due to the args being laid backwards on the stack
! 607: * and then copied in words
! 608: */
! 609: code = frame->tf_args[0];
! 610: args[0] = frame->tf_args[2];
! 611: args[1] = frame->tf_args[3];
! 612: argoff = 2;
! 613: retq = 1;
! 614: break;
! 615: default:
! 616: args[0] = frame->tf_args[0];
! 617: args[1] = frame->tf_args[1];
! 618: args[2] = frame->tf_args[2];
! 619: args[3] = frame->tf_args[3];
! 620: break;
! 621: }
! 622:
! 623: if (code < 0 || code >= nsys)
! 624: callp += p->p_emul->e_nosys; /* bad syscall # */
! 625: else
! 626: callp += code;
! 627:
! 628: oerror = error = 0;
! 629: if ((argsize = callp->sy_argsize)) {
! 630: int i;
! 631:
! 632: /* TODO syscallargs */
! 633:
! 634: /*
! 635: * coming from syscall() or __syscall we must be
! 636: * having one of those w/ a 64 bit arguments,
! 637: * which needs a word swap due to the order
! 638: * of the arguments on the stack.
! 639: * this assumes that none of 'em are called
! 640: * by their normal syscall number, maybe a regress
! 641: * test should be used, to watch the behaviour.
! 642: */
! 643: if (!error && argoff < 4) {
! 644: int t;
! 645:
! 646: i = 0;
! 647: switch (code) {
! 648: case SYS_lseek: retq = 0;
! 649: case SYS_truncate:
! 650: case SYS_ftruncate: i = 2; break;
! 651: case SYS_preadv:
! 652: case SYS_pwritev:
! 653: case SYS_pread:
! 654: case SYS_pwrite: i = 4; break;
! 655: case SYS_mquery:
! 656: case SYS_mmap: i = 6; break;
! 657: }
! 658:
! 659: if (i) {
! 660: t = args[i];
! 661: args[i] = args[i + 1];
! 662: args[i + 1] = t;
! 663: }
! 664: }
! 665: }
! 666:
! 667: #ifdef SYSCALL_DEBUG
! 668: scdebug_call(p, code, args);
! 669: #endif
! 670: #ifdef KTRACE
! 671: if (KTRPOINT(p, KTR_SYSCALL))
! 672: ktrsyscall(p, code, callp->sy_argsize, args);
! 673: #endif
! 674: if (error)
! 675: goto bad;
! 676:
! 677: rval[0] = 0;
! 678: rval[1] = frame->tf_ret1;
! 679: #if NSYSTRACE > 0
! 680: if (ISSET(p->p_flag, P_SYSTRACE))
! 681: oerror = error = systrace_redirect(code, p, args, rval);
! 682: else
! 683: #endif
! 684: oerror = error = (*callp->sy_call)(p, args, rval);
! 685: switch (error) {
! 686: case 0:
! 687: frame->tf_ret0 = rval[0];
! 688: frame->tf_ret1 = rval[!retq];
! 689: frame->tf_r1 = 0;
! 690: break;
! 691: case ERESTART:
! 692: frame->tf_iioq[0] -= 12;
! 693: frame->tf_iioq[1] -= 12;
! 694: case EJUSTRETURN:
! 695: break;
! 696: default:
! 697: bad:
! 698: if (p->p_emul->e_errno)
! 699: error = p->p_emul->e_errno[error];
! 700: frame->tf_r1 = error;
! 701: frame->tf_ret0 = error;
! 702: frame->tf_ret1 = 0;
! 703: break;
! 704: }
! 705: #ifdef SYSCALL_DEBUG
! 706: scdebug_ret(p, code, oerror, rval);
! 707: #endif
! 708: userret(p, frame->tf_iioq[1], 0);
! 709: #ifdef KTRACE
! 710: if (KTRPOINT(p, KTR_SYSRET))
! 711: ktrsysret(p, code, oerror, rval[0]);
! 712: #endif
! 713: #ifdef DIAGNOSTIC
! 714: if (cpl != oldcpl) {
! 715: printf("WARNING: SPL (0x%x) NOT LOWERED ON "
! 716: "syscall(0x%x, 0x%x, 0x%x, 0x%x...) EXIT, PID %d\n",
! 717: cpl, code, args[0], args[1], args[2], p->p_pid);
! 718: cpl = oldcpl;
! 719: }
! 720: #endif
! 721: splx(cpl); /* process softints */
! 722: }
CVSweb