[BACK]Return to trap.c CVS log [TXT][DIR] Up to [local] / sys / arch / hppa / hppa

Annotation of sys/arch/hppa/hppa/trap.c, Revision 1.1.1.1

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

CVSweb