Annotation of coherent/b/STREAMS/i386/ndp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * ker/i386/ndp.c
                      3:  *
                      4:  * All ndp-related functions, except for assembler routines
                      5:  *
                      6:  * Revised: Mon Aug  2 02:44:03 1993 CDT
                      7:  */
                      8: 
                      9: /*
                     10:  * ----------------------------------------------------------------------
                     11:  * Includes.
                     12:  */
                     13: 
                     14: #include <common/_gregset.h>
                     15: 
                     16: #include <sys/coherent.h>
                     17: #include <sys/errno.h>
                     18: #include <sys/ndp.h>
                     19: #include <sys/seg.h>
                     20: 
                     21: /*
                     22:  * ----------------------------------------------------------------------
                     23:  * Definitions.
                     24:  *     Constants.
                     25:  *     Macros with argument lists.
                     26:  *     Typedefs.
                     27:  *     Enums.
                     28:  */
                     29: 
                     30: /*
                     31:  * ----------------------------------------------------------------------
                     32:  * Functions.
                     33:  *     Import Functions.
                     34:  *     Export Functions.
                     35:  *     Local Functions.
                     36:  */
                     37: void   emFinit();
                     38: void   emtrap();
                     39: void   fptrap();
                     40: void   ndpConRest();
                     41: void   ndpDetach();
                     42: void   ndpEmTraps();
                     43: void   ndpEndProc();
                     44: void   ndpIrq();
                     45: void   ndpMine();
                     46: void   ndpNewOwner();
                     47: void   ndpNewProc();
                     48: char * ndpTypeName();
                     49: int    rdEmTrapped();
                     50: int    rdNdpSaved();
                     51: int    rdNdpSavedU();
                     52: int    rdNdpUser();
                     53: void   senseNdp();
                     54: void   wrEmTrapped();
                     55: void   wrNdpSaved();
                     56: void   wrNdpSavedU();
                     57: void   wrNdpUser();
                     58: 
                     59: /*
                     60:  * ----------------------------------------------------------------------
                     61:  * Global Data.
                     62:  *     Import Variables.
                     63:  *     Export Variables.
                     64:  *     Local Variables.
                     65:  */
                     66: 
                     67: /*
                     68:  * ndp control word is 16 bits:
                     69:  * 0000 RC:2 PC:2 01 PM:1 UM:1 OM:1 ZM:1 DM:1 IM:1
                     70:  * RC - rounding control
                     71:  * PC - precision control
                     72:  * PM - precision mask
                     73:  * UM - underflow mask
                     74:  * OM - overflow mask
                     75:  * ZM - zero divide mask
                     76:  * DM - denormal operand mask
                     77:  * IM - invalid operation mask
                     78:  * for masks, 1 masks the exception
                     79:  *
                     80:  * iBCS2 page 3-46 specifies the following:
                     81:  *   0000 : 00 10 : 0 1 1 1 : 0 0 1 0 = 0x0272
                     82:  */
                     83: 
                     84: /* Configurable ndp-related variables. */
                     85: extern short   ndpCW;
                     86: extern short   ndpDump;
                     87: extern short   ndpType;
                     88: extern int     ndpEmSig;
                     89: 
                     90: /* Patchable emulator-related function pointers. */
                     91: extern int     (*ndpEmFn)();
                     92: extern int     (*ndpKfsave)();
                     93: extern int     (*ndpKfrstor)();
                     94: 
                     95: static int     kerEm = 1;      /* RAM copy of CR0 EM bit */
                     96: static int     ndpUseg;        /* system global address of U segment */
                     97: static PROC *  ndpOwner;       /* process whose stuff is now in ndp */
                     98: 
                     99: /*
                    100:  * ----------------------------------------------------------------------
                    101:  * Code.
                    102:  */
                    103: 
                    104: /*
                    105:  * Called from trap handler the first time a process executes an ndp
                    106:  * instruction.
                    107:  */
                    108: void
                    109: ndpNewOwner ()
                    110: {
                    111:        UPROC *         up;
                    112: 
                    113:        /* disable further emulator traps for this process */
                    114:        wrNdpUser (1);
                    115:        ndpEmTraps (0);
                    116: 
                    117:        /* save old ndp status, if any process was using it */
                    118:        if (ndpOwner) {
                    119:                int work = workAlloc ();
                    120:                ptable1_v [work] = sysmem.u.pbase [btocrd (ndpUseg)] | SEG_RW;
                    121:                up = (UPROC *) (ctob(work) + U_OFFSET);
                    122:                ndpSave (& up->u_ndpCon);
                    123:                wrNdpSavedU (1, up);
                    124:                workFree (work);
                    125:        }
                    126: 
                    127:        /* Make current process NDP owner */
                    128:        ndpMine ();
                    129: 
                    130:        /* give process a clean ndp */
                    131:        ndpInit (ndpCW);
                    132: }
                    133: 
                    134: /*
                    135:  * NDP initialization for a new process.
                    136:  * Called at exec time.
                    137:  * Sets defaults, before it is known whether the process uses NDP or not.
                    138:  */
                    139: void
                    140: ndpNewProc()
                    141: {
                    142:        /* default for a process is to trap on NDP instructions */
                    143:        ndpEmTraps (1);
                    144:        wrNdpUser (0);
                    145:        wrNdpSaved (0);
                    146:        wrEmTrapped (0);
                    147: }
                    148: 
                    149: /*
                    150:  * Restore some ndp info when doing a regular conrest().
                    151:  * Called just after conrest - u area has just been restored.
                    152:  */
                    153: void
                    154: ndpConRest()
                    155: {
                    156:        UPROC *         up;
                    157: 
                    158:        /* make CR0 EM bit match what this process needs */
                    159:        ndpEmTraps (rdNdpUser () ? 0 : 1);
                    160: 
                    161:        /*
                    162:         * If current process uses ndp, may need to fix ndp state
                    163:         *
                    164:         * By the nature of NDP save op's, if the NDP owner's NDP state
                    165:         * is saved, then it's not in the NDP.
                    166:         *
                    167:         * So, we have to be careful (1) not to save twice, and (2) to
                    168:         * restore, even if we are NDP owner, if NDP state is saved.
                    169:         */
                    170: 
                    171:        if (rdNdpUser ()) {
                    172:                if (ndpOwner != SELF) {
                    173:                        if (ndpOwner) {         /* save old ndp state */
                    174:                                int work = workAlloc ();
                    175:                                ptable1_v [work] =
                    176:                                  sysmem.u.pbase [btocrd (ndpUseg)] | SEG_RW;
                    177:                                up = (UPROC *) (ctob(work) + U_OFFSET);
                    178:                                if (! rdNdpSavedU (up)) {
                    179:                                        ndpSave (& up->u_ndpCon);
                    180:                                        wrNdpSavedU (1, up);
                    181:                                }
                    182:                                workFree (work);
                    183:                        }
                    184: 
                    185:                        /* Make current process NDP owner and reload ndp state */
                    186:                        ndpMine ();
                    187:                        ndpRestore (& u.u_ndpCon);
                    188:                        wrNdpSaved (0);
                    189:                } else if (rdNdpSaved()) {
                    190:                        ndpRestore (& u.u_ndpCon);
                    191:                        wrNdpSaved (0);
                    192:                }
                    193:        }
                    194: }
                    195: 
                    196: /*
                    197:  * When a process exits, it relinquishes the ndp.
                    198:  */
                    199: void
                    200: ndpEndProc()
                    201: {
                    202:        if (SELF == ndpOwner)
                    203:                ndpDetach();
                    204: }
                    205: 
                    206: /*
                    207:  * ----------------------------------------------------------------------
                    208:  * Trap handlers.
                    209:  */
                    210: 
                    211: /*
                    212:  * fptrap()
                    213:  *
                    214:  * Entered when NDP generates a CPU error.
                    215:  * err is either SIFP or 0x0D40
                    216:  */
                    217: 
                    218: void
                    219: fptrap (regset)
                    220: gregset_t      regset;
                    221: {
                    222:        unsigned short  sw;             /* ndp status word */
                    223:        struct _fpstate * fsp = & u.u_ndpCon;
                    224: 
                    225:        /* NIGEL: removed set of u.u_regl here */
                    226:        /*
                    227:         * Send user a signal.
                    228:         */
                    229: 
                    230:        ndpSave (fsp);
                    231:        /* Clear exception flag in NDP to prevent runaway trap. */
                    232:        sw = fsp->status = fsp->sw;
                    233:        fsp->sw &= 0x7f00;
                    234:        wrNdpSaved (1);
                    235:        if (ndpDump) {
                    236:                curr_register_dump (& regset);
                    237:                printf ("\nfcs=%x  fip=%x  fos=%x  foo=%x\n",
                    238:                        fsp->cssel & 0xffff, fsp->ipoff,
                    239:                        fsp->datasel & 0xffff, fsp->dataoff);
                    240:                printf("User Floating Point Trap: ");
                    241:                if (sw & 1)
                    242:                        printf("Invalid Operation");
                    243:                else if (sw & 2)
                    244:                        printf("Denormalized Operand");
                    245:                else if (sw & 4)
                    246:                        printf("Divide by Zero");
                    247:                else if (sw & 8)
                    248:                        printf("Overflow");
                    249:                else if (sw & 0x10)
                    250:                        printf("Underflow");
                    251:                else if (sw & 0x20)
                    252:                        printf("Precision");
                    253:                else
                    254:                        printf("???");
                    255:        }
                    256:        sendsig (SIGFPE, SELF);
                    257: }
                    258: 
                    259: /*
                    260:  * emtrap()
                    261:  *
                    262:  * Entered when NDP opcode is executed and EM bit of CR0 is 1.
                    263:  * err is SIXNP (Device Not Available Fault)
                    264:  */
                    265: void
                    266: emtrap (regset)
                    267: gregset_t      regset;
                    268: {
                    269:        switch (ndpType) {
                    270:        case NDP_TYPE_287:
                    271:        case NDP_TYPE_387:
                    272:        case NDP_TYPE_486:
                    273:                ndpNewOwner ();
                    274:                break;
                    275: 
                    276:        default:
                    277:                if (ndpDump) {
                    278:                        curr_register_dump (& regset);
                    279:                        printf ("emulation trap\n");
                    280:                }
                    281:                if (! rdEmTrapped ()) {
                    282:                        wrEmTrapped (1);
                    283:                        emFinit (& u.u_ndpCon);
                    284:                }
                    285:                if (ndpEmFn) {
                    286:                        int looker = 1;
                    287: 
                    288:                        /*
                    289:                         * No emulator lookahead if ptraced or
                    290:                         * single step process.
                    291:                         */
                    292:                        if ((SELF->p_flags & PFTRAC) != 0 ||
                    293:                            (regset._i386._eflags & MFTTB) != 0)
                    294:                                looker = 0;
                    295:                        (* ndpEmFn) (& regset, & u.u_ndpCon, looker);
                    296:                } else
                    297:                        sendsig(ndpEmSig, SELF);
                    298:        }
                    299: }
                    300: 
                    301: /*
                    302:  * IRQ 13 handler.  Not used with 486.
                    303:  */
                    304: void
                    305: ndpIrq()
                    306: {
                    307:        struct _fpstate * fsp = &u.u_ndpCon;
                    308:        unsigned short sw;
                    309: 
                    310:        outb(NDP_PORT, 0);
                    311:        /*
                    312:         * Send user a signal.
                    313:         */
                    314:        ndpSave(fsp);
                    315:        /* Clear exception flag in NDP to prevent runaway trap. */
                    316:        sw = fsp->status = fsp->sw;
                    317:        fsp->sw &= 0x7f00;
                    318:        wrNdpSaved(1);
                    319:        if (ndpDump) {
                    320:                printf("\nfcs=%x  fip=%x  fos=%x  foo=%x\n",
                    321:                  fsp->cssel&0xffff, fsp->ipoff,
                    322:                  fsp->datasel&0xffff, fsp->dataoff);
                    323:                printf("User 387 Trap: ");
                    324:                if (sw & 1)
                    325:                        printf("Invalid Operation");
                    326:                else if (sw & 2)
                    327:                        printf("Denormalized Operand");
                    328:                else if (sw & 4)
                    329:                        printf("Divide by Zero");
                    330:                else if (sw & 8)
                    331:                        printf("Overflow");
                    332:                else if (sw & 0x10)
                    333:                        printf("Underflow");
                    334:                else if (sw & 0x20)
                    335:                        printf("Precision");
                    336:                else
                    337:                        printf("???");
                    338:        }
                    339:        sendsig(SIGFPE, SELF);
                    340: }
                    341: 
                    342: /*
                    343:  * ----------------------------------------------------------------------
                    344:  * Routines concerned with whether current process has used the ndp.
                    345:  */
                    346: int
                    347: rdNdpUser()
                    348: {
                    349:        return (u.u_ndpFlags & NF_NDP_USER) ? 1 : 0;
                    350: }
                    351: 
                    352: void
                    353: wrNdpUser(n)
                    354: int n;
                    355: {
                    356:        if (n)
                    357:                u.u_ndpFlags |= NF_NDP_USER;
                    358:        else
                    359:                u.u_ndpFlags &= ~NF_NDP_USER;
                    360: }
                    361: 
                    362: /*
                    363:  * Since saving NDP state is destructive, we need to keep track
                    364:  * of where the current NDP state is - u area, or NDP?
                    365:  */
                    366: int
                    367: rdNdpSaved()
                    368: {
                    369:        return (u.u_ndpFlags & NF_NDP_SAVED) ? 1 : 0;
                    370: }
                    371: 
                    372: int
                    373: rdNdpSavedU(up)
                    374: UPROC * up;
                    375: {
                    376:        return (up->u_ndpFlags & NF_NDP_SAVED) ? 1 : 0;
                    377: }
                    378: 
                    379: void
                    380: wrNdpSaved(n)
                    381: int n;
                    382: {
                    383:        if (n)
                    384:                u.u_ndpFlags |= NF_NDP_SAVED;
                    385:        else
                    386:                u.u_ndpFlags &= ~NF_NDP_SAVED;
                    387: }
                    388: 
                    389: void
                    390: wrNdpSavedU(n, up)
                    391: int n;
                    392: UPROC * up;
                    393: {
                    394:        if (n)
                    395:                up->u_ndpFlags |= NF_NDP_SAVED;
                    396:        else
                    397:                up->u_ndpFlags &= ~NF_NDP_SAVED;
                    398: }
                    399: 
                    400: /*
                    401:  * Enable (1) or disable (0) emulator traps.
                    402:  */
                    403: void
                    404: ndpEmTraps(n)
                    405: int n;
                    406: {
                    407:        if (kerEm != n) {
                    408:                kerEm = n;
                    409:                setEm (n);
                    410:        }
                    411: }
                    412: 
                    413: /*
                    414:  * Make ndp owned by no one.
                    415:  */
                    416: void
                    417: ndpDetach()
                    418: {
                    419:        ndpOwner = 0;
                    420:        ndpUseg = 0;
                    421: }
                    422: 
                    423: /*
                    424:  * Make ndp owned by the current process.
                    425:  */
                    426: void
                    427: ndpMine()
                    428: {
                    429:        SR *            srp = & u.u_segl [SIUSERP];
                    430:        SEG *           sp = srp->sr_segp;
                    431: 
                    432:        ndpOwner = SELF;
                    433:        ndpUseg = MAPIO (sp->s_vmem, U_OFFSET);
                    434: }
                    435: 
                    436: /*
                    437:  * ----------------------------------------------------------------------
                    438:  * Code concerned with identifying coprocessor type, and taking specialized
                    439:  * action depending on the type.
                    440:  */
                    441: 
                    442: /*
                    443:  * Using usual algorithms, determine existence and type of NDP.
                    444:  * If interrupt vector needs to be set for FP exception, do it.
                    445:  *
                    446:  * If 2's bit of int11 is on, NDP is present.
                    447:  */
                    448: void
                    449: senseNdp()
                    450: {
                    451:        if (ndpType == NDP_TYPE_AUTO) {
                    452:                ndpEmTraps (0);         /* Will need to do some FP code. */
                    453:                ndpType = ndpSense ();  /* Rely on assembler tricks now. */
                    454:                ndpEmTraps (1);
                    455:        }
                    456:        if (ndpType == NDP_TYPE_387 || ndpType == NDP_TYPE_287)
                    457:                setivec (NDP_IRQ, ndpIrq);
                    458: }
                    459: 
                    460: /*
                    461:  * Called from main().
                    462:  * Return name string for the type of coprocessor detected.
                    463:  */
                    464: char *
                    465: ndpTypeName()
                    466: {
                    467:        char * ret = "**ERROR: Bad ndp type**";
                    468: 
                    469:        switch(ndpType) {
                    470:        case NDP_TYPE_NONE:
                    471:                ret = "No NDP.  ";
                    472:                break;
                    473:        case NDP_TYPE_287:
                    474:                ret = "NDP=287.  ";
                    475:                break;
                    476:        case NDP_TYPE_387:
                    477:                ret = "NDP=387.  ";
                    478:                break;
                    479:        case NDP_TYPE_486:
                    480:                ret = "NDP=486.  ";
                    481:                break;
                    482:        }
                    483:        return ret;
                    484: }
                    485: 
                    486: /*
                    487:  * ----------------------------------------------------------------------
                    488:  * Little routines for tracking emulator state.
                    489:  */
                    490: 
                    491: int
                    492: rdEmTrapped()
                    493: {
                    494:        return (u.u_ndpFlags & NF_EM_TRAPPED) ? 1 : 0;
                    495: }
                    496: 
                    497: void
                    498: wrEmTrapped(n)
                    499: int n;
                    500: {
                    501:        if (n)
                    502:                u.u_ndpFlags |= NF_EM_TRAPPED;
                    503:        else
                    504:                u.u_ndpFlags &= ~NF_EM_TRAPPED;
                    505: }
                    506: 
                    507: /*
                    508:  * Provide the emulator with a fresh context.
                    509:  */
                    510: void
                    511: emFinit(fpsp)
                    512: struct _fpemstate * fpsp;
                    513: {
                    514:        register int r;
                    515: 
                    516:        memset(fpsp, '\0', sizeof(struct _fpemstate));  /* mostly zeroes */
                    517:        fpsp->cw = ndpCW;
                    518:        for(r = 0; r < 8; r++)
                    519:                fpsp->regs[r].tag = 7;          /* Empty */
                    520: }
                    521: 
                    522: /*
                    523:  * ----------------------------------------------------------------------
                    524:  * Functions to interface with the emulator.
                    525:  */
                    526: get_fs_byte(cp)
                    527: char *cp;
                    528: {
                    529:        char getubd();
                    530: 
                    531:        return getubd(cp);
                    532: }
                    533: 
                    534: get_fs_word(sp)
                    535: short *sp;
                    536: {
                    537:        short getusd();
                    538: 
                    539:        return getusd(sp);
                    540: }
                    541: 
                    542: get_fs_long(lp)
                    543: long *lp;
                    544: {
                    545:        long getuwd();
                    546: 
                    547:        return getuwd(lp);
                    548: }
                    549: 
                    550: void
                    551: put_fs_byte(data, cp)
                    552: char *cp;
                    553: char data;
                    554: {
                    555:        putubd(cp, data);
                    556: }
                    557: 
                    558: void
                    559: put_fs_word(data, sp)
                    560: short *sp;
                    561: short data;
                    562: {
                    563:        putusd(sp, data);
                    564: }
                    565: 
                    566: void
                    567: put_fs_long(data, lp)
                    568: long *lp;
                    569: long data;
                    570: {
                    571:        putuwd(lp, data);
                    572: }
                    573: 
                    574: /*
                    575:  * Return zero if out of bounds for write.
                    576:  */
                    577: int
                    578: verify_area(cp, len)
                    579: int * cp;
                    580: int len;
                    581: {
                    582:        int ret = useracc(cp, len, 1);
                    583: 
                    584:        if (!ret) {
                    585: #if 0
                    586:                printf("Bad Em write, base=%x, len=%x, r.a.=%x",
                    587:                        cp, len, *(int *)((&cp) - 1));
                    588: #endif
                    589:                sendsig(SIGSEGV, SELF);
                    590:        }
                    591:        return ret;
                    592: }
                    593: 
                    594: /*
                    595:  * print kernel message.
                    596:  */
                    597: printk(s)
                    598: char *s;
                    599: {
                    600:        puts(s);
                    601: }
                    602: 
                    603: emSendsig()
                    604: {
                    605:        sendsig(SIGFPE, SELF);
                    606: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.