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