Annotation of coherent/b/STREAMS/i386/ndp.c, revision 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.