Annotation of coherent/b/kernel/i386/ndp.c, revision 1.1

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

unix.superglobalmegacorp.com

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