Annotation of 43BSDTahoe/sys/tahoe/locore.s, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1988 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  *
                      6:  *     @(#)locore.s    7.6 (Berkeley) 5/1/89
                      7:  *     9/8/89 (bostic) -- added delay in wbadaddr from 7.10
                      8:  *     This had already been patched, but I have no idea by whom; the
                      9:  *     following lines had been added:
                     10:  *
                     11:  *     #if NVX > 0
                     12:  *             ADDMAP( NVX * 16384/NBPG )
                     13:  *     #endif
                     14:  */
                     15: 
                     16: #include "../tahoe/mtpr.h"
                     17: #include "../tahoe/trap.h"
                     18: #include "../tahoe/psl.h"
                     19: #include "../tahoe/pte.h"
                     20: #include "../tahoe/cp.h"
                     21: #include "../tahoe/mem.h"
                     22: #include "../tahoe/SYS.h"
                     23: 
                     24: #include "../tahoemath/fp.h"
                     25: 
                     26: #include "errno.h"
                     27: #include "syscall.h"
                     28: #include "cmap.h"
                     29: 
                     30:        .set    HIGH,0x1f               # mask for total disable
                     31:        .set    NISP,3                  # number of interrupt stack pages
                     32:        .set    SYSTEM,0xC0000000       # virtual address of system start
                     33:        .set    PPAGES,0x100000         # possible pages in P0,P1, etc.
                     34: 
                     35: /* ACBL for non-negative '_add' */
                     36: #define ACBL(_limit,_add,_index,_displ) \
                     37:        addl2   _add,_index; \
                     38:        cmpl    _index,_limit; \
                     39:        bleq    _displ
                     40: 
                     41: /* _ACBL for negative '_add' */
                     42: #define _ACBL(_limit,_add,_index,_displ) \
                     43:        addl2   _add,_index; \
                     44:        cmpl    _index,_limit; \
                     45:        bgeq    _displ
                     46: 
                     47: #define        MOVC3(_srcaddr,_dstaddr,_len) \
                     48:        movl    _srcaddr,r0; \
                     49:        movl    _dstaddr,r1; \
                     50:        movl    _len,r2; \
                     51:        movblk
                     52: 
                     53: /* keep address of psl if coming from user mode */
                     54: #define CHECK_SFE(_delta) \
                     55:        bitl    $PSL_CURMOD,_delta(sp); \
                     56:        jeql    1f; \
                     57:        moval   _delta(sp),_user_psl; \
                     58: 1:
                     59: 
                     60: /*
                     61:  * User structure is UPAGES at top of user space.
                     62:  */
                     63:        .globl  _u
                     64:        .set    _u,SYSTEM - UPAGES*NBPG
                     65: 
                     66: /*
                     67:  * Restart stack. Used on power recovery or panic.
                     68:  * Takes a core-dump and then halts.
                     69:  */ 
                     70:        .globl  _rsstk
                     71:        .globl  pwfl_stk        
                     72: _rsstk:
                     73:        .space  1024-8
                     74: pwfl_stk:
                     75:        .space  4
                     76: dumpflag:
                     77:        .space  4
                     78: 
                     79:        .globl  _intstack
                     80: _intstack:
                     81:        .space  NISP*NBPG
                     82: eintstack:
                     83: 
                     84: /*
                     85:  * Power failure storage block and
                     86:  * macros for saving and restoring.
                     87:  */
                     88: #define        POWERFAIL(id,longs) \
                     89:        .globl  pwfl_/**/id \
                     90: pwfl_/**/id: .space longs*4
                     91:        .data
                     92:        POWERFAIL(r0,   14)             # r0-r13
                     93:        POWERFAIL(sp,   1)              # r14
                     94:        POWERFAIL(SCBB, 1)              # system control block base
                     95:        POWERFAIL(SBR,  1)              # system pte base
                     96:        POWERFAIL(SLR,  1)              # system pte length
                     97:        POWERFAIL(P0BR, 1)              # p0 pte base
                     98:        POWERFAIL(P0LR, 1)              # p0 pte length
                     99:        POWERFAIL(P1BR, 1)              # p1 pte base
                    100:        POWERFAIL(P1LR, 1)              # p1 pte length
                    101:        POWERFAIL(P2BR, 1)              # p2 pte base
                    102:        POWERFAIL(P2LR, 1)              # p2 pte length
                    103:        POWERFAIL(IPL,  1)              # interrupt priority level
                    104:        POWERFAIL(DCK,  1)              # data cache key
                    105:        POWERFAIL(CCK,  1)              # code cache key
                    106:        POWERFAIL(PCBB, 1)              # process control block base
                    107:        POWERFAIL(ISP,  1)              # interrupt stack pointer
                    108:        POWERFAIL(KSP,  1)              # kernel mode stack pointer
                    109:        POWERFAIL(USP,  1)              # user mode stack pointer
                    110:        POWERFAIL(MME,  1)              # memory management enable
                    111:        POWERFAIL(PSL,  1)              # processor status longword
                    112: 
                    113: /*
                    114:  * Save current state in power fail storage block.
                    115:  */
                    116: #define        SAVEpwfl() \
                    117:        movpsl  pwfl_PSL        # Keeps all flags, etc. \
                    118:        storer  $0x3fff,pwfl_r0 # Saves r0-r13 \
                    119:        moval   0(sp),pwfl_sp   # Saves sp (=r14) \
                    120:        mfpr    $SBR,pwfl_SBR   # Save all re_loadable registers \
                    121:        mfpr    $SLR,pwfl_SLR \
                    122:        mfpr    $P0BR,pwfl_P0BR \
                    123:        mfpr    $P0LR,pwfl_P0LR \
                    124:        mfpr    $P1BR,pwfl_P1BR \
                    125:        mfpr    $P1LR,pwfl_P1LR \
                    126:        mfpr    $P2BR,pwfl_P2BR \
                    127:        mfpr    $P2LR,pwfl_P2LR \
                    128:        mfpr    $IPL,pwfl_IPL \
                    129:        mfpr    $MME,pwfl_MME \
                    130:        mfpr    $DCK,pwfl_DCK \
                    131:        mfpr    $CCK,pwfl_CCK \
                    132:        mfpr    $PCBB,pwfl_PCBB \
                    133:        mfpr    $ISP,pwfl_ISP \
                    134:        mfpr    $SCBB,pwfl_SCBB \
                    135:        mfpr    $KSP,pwfl_KSP \
                    136:        mfpr    $USP,pwfl_USP
                    137: 
                    138: /*
                    139:  * Restore state saved in power fail block and
                    140:  * jmp to location specified after (possibly)
                    141:  * enabling memory management.
                    142:  */
                    143: #define        RESTOREpwfl(loc) \
                    144:        loadr   $0x3fff,pwfl_r0 # Restore r0-r13 \
                    145:        movl    pwfl_sp,sp      # Restore sp (=r14) \
                    146:        mtpr    pwfl_SCBB,$SCBB \
                    147:        mtpr    pwfl_SBR,$SBR   # Restore all re_loadable registers \
                    148:        mtpr    pwfl_SLR,$SLR \
                    149:        mtpr    pwfl_P0BR,$P0BR \
                    150:        mtpr    pwfl_P0LR,$P0LR \
                    151:        mtpr    pwfl_P1BR,$P1BR \
                    152:        mtpr    pwfl_P1LR,$P1LR \
                    153:        mtpr    pwfl_P2BR,$P2BR \
                    154:        mtpr    pwfl_P2LR,$P2LR \
                    155:        mtpr    pwfl_IPL,$IPL \
                    156:        mtpr    pwfl_DCK,$DCK \
                    157:        mtpr    pwfl_CCK,$CCK \
                    158:        mtpr    pwfl_PCBB,$PCBB \
                    159:        mtpr    pwfl_ISP,$ISP \
                    160:        mtpr    pwfl_KSP,$KSP \
                    161:        mtpr    pwfl_USP,$USP \
                    162: \
                    163:        bicpsw  $0xff           # Restore PSW. \
                    164:        bispsw  pwfl_PSL+2      # Set original bits back (just in case..) \
                    165: # now go to mapped mode \
                    166: # Have to change PC to system addresses \
                    167:        mtpr    $1,$PACC        # Thoroughly clean up caches. \
                    168:        mtpr    $1,$PADC \
                    169:        mtpr    $1,$TBIA \
                    170:        mtpr    pwfl_MME,$MME   # Restore MME. Last thing to be done. \
                    171:        jmp     loc
                    172: 
                    173: /*
                    174:  * Do a dump.
                    175:  * Called by auto-restart.
                    176:  * May be called manually.
                    177:  */
                    178:        .align  2
                    179:        .text
                    180:        .globl  _Xdoadump
                    181:        .globl  _doadump
                    182: _Xdoadump:                                     # CP comes here after power fail
                    183:        RESTOREpwfl(*0f)                        # restore state
                    184: _doadump:
                    185:        .word 0
                    186: 0:     mtpr    $HIGH,$IPL
                    187: #define        _rsstkmap _Sysmap+12    # powerfail storage, scb, rsstk, int stack
                    188:        tstl    dumpflag                        # dump only once!
                    189:        bneq    1f
                    190:        andl2   $~PG_PROT,_rsstkmap
                    191:        orl2    $PG_KW,_rsstkmap                # Make dump stack r/w
                    192:        mtpr    $0,$TBIA
                    193:        movl    $1,dumpflag
                    194:        movab   dumpflag,sp
                    195:        callf   $4,_dumpsys
                    196: 1:
                    197:        halt
                    198: 
                    199: /*
                    200:  * Interrupt vector routines
                    201:  */ 
                    202:        .globl  _waittime
                    203: #define        SCBVEC(name) \
                    204:        .align 2; \
                    205:        .globl _X/**/name; \
                    206: _X/**/name
                    207: #define        PANIC(msg) \
                    208:        clrl _waittime; pushab 1f; callf $8,_panic; 1: .asciz msg
                    209: #define        PRINTF(n,msg) \
                    210:        pushab 1f; callf $(n+2)*4,_printf; MSG(msg)
                    211: #define        MSG(msg) .data; 1: .asciz msg; .text
                    212: /*
                    213:  * r0-r5 are saved across all faults and interrupts.
                    214:  * Routines below and those hidden in vbglue.s (device
                    215:  * interrupts) invoke the PUSHR/POPR macros to execute
                    216:  * this.  Also, certain stack frame offset calculations
                    217:  * use this, using the REGSPC definition (and FPSPC defined below).
                    218:  */
                    219: #define        REGSPC  6*4
                    220: #define        PUSHR   movab -REGSPC(sp),sp; storer $0x3f,(sp)
                    221: #define        POPR    loadr $0x3f,(sp); movab REGSPC(sp),sp
                    222: 
                    223: /*
                    224:  * Floating point state is saved across faults and
                    225:  * interrupts.  The state occupies 4 longwords on
                    226:  * the stack:
                    227:  *     precision indicator (single = 0/double = 1)
                    228:  *     double representation of accumulator
                    229:  *     save accumulator status flag (pcb_savacc)
                    230:  */
                    231: #define        FPSPC   (4*4)
                    232: 
                    233: #define SAVE_FPSTAT(_delta) \
                    234:        bitl    $PSL_DBL,_delta(sp); \
                    235:        beql    1f; \
                    236:        pushl   $1; \
                    237:        pushd; \
                    238:        jmp     2f; \
                    239: 1:     pushl   $0; \
                    240:        pushl   $0; \
                    241:        stf     -(sp); \
                    242: 2:     tstl    _u+PCB_SAVACC; \
                    243:        bneq    3f; \
                    244:        moval   0(sp),_u+PCB_SAVACC; \
                    245:        orl2    $2,8(sp);\
                    246: 3:     pushl   $0;
                    247: 
                    248: #define REST_FPSTAT \
                    249:        tstl    (sp)+; \
                    250:        bitl    $2,8(sp);\
                    251:        beql    1f;\
                    252:        movl    $0,_u+PCB_SAVACC; \
                    253: 1:     bitl    $1,8(sp); \
                    254:        beql    2f; \
                    255:        ldd     (sp); \
                    256:        jmp     3f; \
                    257: 2:     ldf     (sp); \
                    258: 3:     moval   12(sp),sp;
                    259: 
                    260: #define REST_ACC \
                    261:        tstl    _u+PCB_SAVACC; \
                    262:        beql    2f; \
                    263:        movl    _u+PCB_SAVACC,r1; \
                    264:        andl3   $(EXPMASK|SIGNBIT),(r1),-(sp); \
                    265:        cmpl    $0x80000000,(sp)+; \
                    266:        bneq    3f; \
                    267:        clrl    (r1); \
                    268: 3:     bitl    $1,8(r1); \
                    269:        beql    1f; \
                    270:        ldd     (r1); \
                    271:        jmp     2f; \
                    272: 1:     ldf     (r1); \
                    273: 2:     ;
                    274: 
                    275:        .data
                    276: nofault: .space        4                       # bus error non-local goto label
                    277: 
                    278:        .text
                    279: SCBVEC(buserr):
                    280:        CHECK_SFE(12)
                    281:        SAVE_FPSTAT(12)
                    282:        incl    _intrcnt+I_BUSERR       # keep stats...
                    283:        pushl   r0                      # must save
                    284:        andl3   24(sp),$ERRCD,r0        # grab pushed MER value
                    285:        cmpl    r0,$APE                 # address parity error?
                    286:        jneq    1f
                    287:        halt    
                    288: 1:     cmpl    r0,$VBE                 # versabus error?
                    289:        jneq    2f
                    290:        halt
                    291: 2:
                    292:        movl    (sp)+,r0                # restore r0 and...
                    293:        bitl    $PSL_CURMOD,4*4+3*4(sp) # check if happened in user mode?
                    294:        jeql    3f                      # yes, then shift stack up for trap...
                    295:        movl    12(sp),16(sp)           # sorry, no space for which-buss...
                    296:        movl    8(sp),12(sp)
                    297:        movl    4(sp),8(sp)
                    298:        movl    0(sp),4(sp)
                    299:        movl    $T_BUSERR,0(sp)         # push trap type code and...
                    300:        jbr     alltraps                # ...merge with all other traps
                    301: 3:                                     # kernel mode, check to see if...
                    302:        tstl    nofault                 # ...doing peek/poke?
                    303:        jeql    4f                      # nofault set? if so, jump to it...
                    304:        movl    nofault,4*4+2*4(sp)     # ...setup for non-local goto
                    305:        clrl    nofault
                    306:        jbr     5f
                    307: 4:
                    308:        PUSHR
                    309:        pushab  4*4+REGSPC(sp)          # address of bus error parameters
                    310:        callf   $8,_buserror
                    311:        POPR
                    312: 5:
                    313:        REST_FPSTAT
                    314:        movab   8(sp),sp                # remove bus error parameters
                    315:        rei
                    316: 
                    317: SCBVEC(powfail):                       # We should be on interrupt stack now.
                    318:        SAVEpwfl()                      # save machine state
                    319:        moval   _Xdoadump-SYSTEM,_scb+SCB_DOADUMP
                    320:        halt
                    321: 
                    322: SCBVEC(stray):
                    323:        incl    _cnt+V_INTR             # add to statistics
                    324:        rei
                    325: 
                    326: #include "../net/netisr.h"
                    327:        .globl  _netisr
                    328: SCBVEC(netintr):
                    329:        CHECK_SFE(4)
                    330:        SAVE_FPSTAT(4); PUSHR
                    331: #include "imp.h"
                    332: #if NIMP > 0
                    333:        bbc     $NETISR_IMP,_netisr,1f;
                    334:        andl2   $~(1<<NETISR_IMP),_netisr
                    335:        callf   $4,_impintr;
                    336: 1:
                    337: #endif
                    338: #ifdef INET
                    339:        bbc     $NETISR_IP,_netisr,1f   
                    340:        andl2   $~(1<<NETISR_IP),_netisr
                    341:        callf   $4,_ipintr      
                    342: 1:
                    343: #endif
                    344: #ifdef NS
                    345:        bbc     $NETISR_NS,_netisr,1f   
                    346:        andl2   $~(1<<NETISR_NS),_netisr
                    347:        callf   $4,_nsintr      
                    348: 1:
                    349: #endif
                    350:        bbc     $NETISR_RAW,_netisr,1f
                    351:        andl2   $~(1<<NETISR_RAW),_netisr       
                    352:        callf   $4,_rawintr     
                    353: 1:
                    354:        incl    _cnt+V_SOFT
                    355:        POPR; REST_FPSTAT
                    356:        rei
                    357: 
                    358: SCBVEC(cnrint):
                    359:        CHECK_SFE(4)
                    360:        SAVE_FPSTAT(4); PUSHR; 
                    361:        pushl $CPCONS; callf $8,_cnrint;
                    362:        incl    _intrcnt+I_CNR
                    363:        incl    _cnt+V_INTR
                    364:        POPR; REST_FPSTAT;
                    365:        rei
                    366: SCBVEC(cnxint):
                    367:        CHECK_SFE(4)
                    368:        SAVE_FPSTAT(4); PUSHR; 
                    369:        pushl $CPCONS; callf $8,_cnxint;
                    370:        incl    _intrcnt+I_CNX
                    371:        incl    _cnt+V_INTR
                    372:        POPR; REST_FPSTAT;
                    373:        rei
                    374: SCBVEC(rmtrint):
                    375:        CHECK_SFE(4)
                    376:        SAVE_FPSTAT(4); PUSHR; 
                    377:        pushl $CPREMOT; callf $8,_cnrint;
                    378:        incl    _intrcnt+I_RMTR
                    379:        incl    _cnt+V_INTR
                    380:        POPR; REST_FPSTAT;
                    381:        rei
                    382: SCBVEC(rmtxint):
                    383:        CHECK_SFE(4)
                    384:        SAVE_FPSTAT(4); PUSHR; 
                    385:        pushl $CPREMOT; callf $8,_cnxint;
                    386:        incl    _intrcnt+I_RMTX
                    387:        incl    _cnt+V_INTR
                    388:        POPR; REST_FPSTAT;
                    389:        rei
                    390: 
                    391: #define PUSHPCPSL      pushl 4+FPSPC+REGSPC(sp); pushl 4+FPSPC+REGSPC(sp);
                    392: 
                    393: SCBVEC(hardclock):
                    394:        tstl    _clk_enable
                    395:        bneq    1f
                    396:        rei
                    397: 1:
                    398:        CHECK_SFE(4)
                    399:        SAVE_FPSTAT(4); PUSHR
                    400:        PUSHPCPSL                       # push pc and psl
                    401:        callf   $12,_hardclock          # hardclock(pc,psl)
                    402:        incl    _intrcnt+I_CLOCK
                    403:        incl    _cnt+V_INTR             ## temp so not to break vmstat -= HZ
                    404:        POPR; REST_FPSTAT
                    405:        rei
                    406: SCBVEC(softclock):
                    407:        CHECK_SFE(4)
                    408:        SAVE_FPSTAT(4); PUSHR;
                    409:        PUSHPCPSL                               # push pc and psl
                    410:        callf   $12,_softclock                  # softclock(pc,psl)
                    411:        incl    _cnt+V_SOFT
                    412:        POPR; REST_FPSTAT
                    413:        rei
                    414: 
                    415: /*
                    416:  * Stray VERSAbus interrupt catch routines
                    417:  */
                    418:        .data
                    419: #define        PJ      .align 2; callf $4,_Xvstray
                    420:        .globl  _catcher
                    421: _catcher:
                    422:        PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
                    423:        PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
                    424:        PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
                    425:        PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
                    426:        PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
                    427:        PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
                    428:        PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
                    429:        PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
                    430:        PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
                    431:        PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
                    432:        PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
                    433:        PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ
                    434: 
                    435:        .align  2
                    436:        .globl  _cold
                    437: _cold: .long   0x3
                    438: 
                    439:        .text
                    440: SCBVEC(vstray):
                    441:        .word   0
                    442:        bbc     $0,_cold,2f             # system running?
                    443:        bbc     $1,_cold,1f             # doing autoconfig?
                    444:        jbr     3f                      # random interrupt, ignore
                    445: 1:
                    446:        mfpr    $IPL,r12                # ...setup br and cvec
                    447:        subl3   $_catcher+7,-8(fp),r11; shar $3,r11,r11
                    448:        addl2   $SCB_DEVBASE,r11
                    449:        jbr     3f
                    450: 2:
                    451:        PUSHR
                    452:        subl3   $_catcher+7,-8(fp),r0; shar $3,r0,r0
                    453:        addl3   $SCB_DEVBASE,r0,-(sp);
                    454:        mfpr    $IPL,-(sp)
                    455:        PRINTF(2, "stray intr ipl %x vec %x\n")
                    456:        POPR
                    457: 3:     moval   0f,-8(fp); ret          # pop callf frame...
                    458: 0:     rei                             # ...and return
                    459: 
                    460: /*
                    461:  * Trap and fault vector routines
                    462:  */ 
                    463: #define        TRAP(a) pushl $T_/**/a; jbr alltraps
                    464: 
                    465: /*
                    466:  * Ast delivery (profiling and/or reschedule)
                    467:  */
                    468: 
                    469: SCBVEC(kspnotval):
                    470:        CHECK_SFE(4)
                    471:        pushl $0;
                    472:        SAVE_FPSTAT(8)
                    473:        TRAP(KSPNOTVAL)
                    474: SCBVEC(privinflt):
                    475:        CHECK_SFE(4)
                    476:        pushl $0;
                    477:        SAVE_FPSTAT(8)
                    478:        TRAP(PRIVINFLT)
                    479: SCBVEC(resopflt):
                    480:        CHECK_SFE(4)
                    481:        pushl $0;
                    482:        SAVE_FPSTAT(8)
                    483:        TRAP(RESOPFLT)
                    484: SCBVEC(resadflt):
                    485:        CHECK_SFE(4)
                    486:        pushl $0;
                    487:        SAVE_FPSTAT(8)
                    488:        TRAP(RESADFLT)
                    489: SCBVEC(bptflt):
                    490:        CHECK_SFE(4)
                    491:        pushl $0;
                    492:        SAVE_FPSTAT(8)
                    493:        TRAP(BPTFLT)
                    494: SCBVEC(kdbintr):
                    495:        CHECK_SFE(4);
                    496:        pushl $0;
                    497:        SAVE_FPSTAT(8);
                    498:        TRAP(KDBTRAP);
                    499: SCBVEC(tracep):
                    500:        CHECK_SFE(4)
                    501:        pushl $0;
                    502:        SAVE_FPSTAT(8)
                    503:        TRAP(TRCTRAP)
                    504: SCBVEC(alignflt):
                    505: #ifdef ALIGN
                    506:        bitl    $PSL_CURMOD,4(sp)
                    507:        jeql    align_excp              # Can't emulate for kernel mode !
                    508:        jbr     non_aligned             # Only emulated for user mode.
                    509: align_excp:
                    510: #else
                    511:        CHECK_SFE(4)
                    512: #endif
                    513:        pushl $0;
                    514:        SAVE_FPSTAT(8)
                    515:        TRAP(ALIGNFLT)
                    516: SCBVEC(arithtrap):
                    517:        CHECK_SFE(8)
                    518:        SAVE_FPSTAT(8)
                    519:        TRAP(ARITHTRAP)
                    520: 
                    521: SCBVEC(protflt):
                    522:        CHECK_SFE(12)
                    523:        bitl    $1,(sp)+
                    524:        jneq    segflt
                    525:        SAVE_FPSTAT(8)
                    526:        TRAP(PROTFLT)
                    527: segflt:
                    528:        SAVE_FPSTAT(8)
                    529:        TRAP(SEGFLT)
                    530: 
                    531: SCBVEC(fpm):                   # Floating Point Emulation
                    532: #ifdef FPE
                    533:        CHECK_SFE(16)
                    534:        SAVE_FPSTAT(16)
                    535:        incl    _cnt+V_FPE      # count emulation traps
                    536:        callf   $4,_fpemulate
                    537:        REST_FPSTAT
                    538: #endif
                    539:        moval   8(sp),sp        # Pop operand
                    540:        tstl    (sp)            # Stack= PSL, PC, return_code
                    541:        jneq    _Xarithtrap     # If not OK, emulate F.P. exception
                    542:        movab   4(sp),sp        # Else remove return_code and
                    543:        rei
                    544: 
                    545: SCBVEC(sfexcep):
                    546:        CHECK_SFE(4)
                    547:        pushl $0
                    548:        SAVE_FPSTAT(8)
                    549:        TRAP(ASTFLT)
                    550: 
                    551: SCBVEC(transflt):
                    552:        CHECK_SFE(12)
                    553:        bitl    $2,(sp)+
                    554:        bneq    tableflt
                    555: pageflt:
                    556:        SAVE_FPSTAT(8)
                    557:        TRAP(PAGEFLT)
                    558: tableflt:
                    559:        SAVE_FPSTAT(8)
                    560:        TRAP(TABLEFLT)
                    561: 
                    562: #define REST_STACK     movab 4(sp), sp; REST_FPSTAT; movab 4(sp), sp
                    563: 
                    564: alltraps:
                    565:        mfpr    $USP,-(sp); 
                    566:        callf   $4,_trap;
                    567:        mtpr    (sp)+,$USP
                    568:        incl    _cnt+V_TRAP
                    569:        REST_STACK                      # pop type, code, and fp stuff
                    570:        mtpr    $HIGH,$IPL              ## dont go to a higher IPL (GROT)
                    571:        rei
                    572: 
                    573: SCBVEC(syscall):
                    574:        CHECK_SFE(8)
                    575:        SAVE_FPSTAT(8)
                    576:        pushl   $T_SYSCALL
                    577:        mfpr    $USP,-(sp);
                    578:        callf   $4,_syscall;
                    579:        mtpr    (sp)+,$USP
                    580:        incl    _cnt+V_SYSCALL
                    581:        REST_STACK                      # pop type, code, and fp stuff
                    582:        mtpr    $HIGH,$IPL              ## dont go to a higher IPL (GROT)
                    583:        rei
                    584: 
                    585: /*
                    586:  * System page table.
                    587:  *
                    588:  * Mbmap and Usrptmap are enlarged by CLSIZE entries
                    589:  * as they are managed by resource maps starting with index 1 or CLSIZE.
                    590:  */ 
                    591: #define        vaddr(x)        ((((x)-_Sysmap)/4)*NBPG+SYSTEM)
                    592: #define        SYSMAP(mname, vname, npte)                      \
                    593: _/**/mname:    .globl  _/**/mname;             \
                    594:        .space  (npte)*4;                       \
                    595:        .globl  _/**/vname;                     \
                    596:        .set    _/**/vname,vaddr(_/**/mname)
                    597: #define        ADDMAP(npte)    .space  (npte)*4
                    598: 
                    599:        .data
                    600:        .align  2
                    601:        SYSMAP(Sysmap   ,Sysbase        ,SYSPTSIZE      )
                    602:        SYSMAP(Forkmap  ,forkutl        ,UPAGES         )
                    603:        SYSMAP(Xswapmap ,xswaputl       ,UPAGES         )
                    604:        SYSMAP(Xswap2map,xswap2utl      ,UPAGES         )
                    605:        SYSMAP(Swapmap  ,swaputl        ,UPAGES         )
                    606:        SYSMAP(Pushmap  ,pushutl        ,UPAGES         )
                    607:        SYSMAP(Vfmap    ,vfutl          ,UPAGES         )
                    608:        SYSMAP(CMAP1    ,CADDR1         ,1              )
                    609:        SYSMAP(CMAP2    ,CADDR2         ,1              )
                    610:        SYSMAP(mmap     ,vmmap          ,1              )
                    611:        SYSMAP(alignmap ,alignutl       ,1              )       /* XXX */
                    612:        SYSMAP(msgbufmap,msgbuf         ,MSGBUFPTECNT   )
                    613:        SYSMAP(Mbmap    ,mbutl          ,NMBCLUSTERS*MCLBYTES/NBPG+CLSIZE )
                    614:        SYSMAP(kmempt   ,kmembase       ,300*CLSIZE     )
                    615: #ifdef GPROF
                    616:        SYSMAP(profmap  ,profbase       ,600*CLSIZE     )
                    617: #endif
                    618:        /*
                    619:         * Enlarge kmempt as needed for bounce buffers allocated
                    620:         * by tahoe controllers.
                    621:         */
                    622: #include "hd.h"
                    623: #if NHD > 0
                    624:                                ADDMAP( NHDC*(MAXPHYS/NBPG+CLSIZE) )
                    625: #endif
                    626: #include "dk.h"
                    627: #if NDK > 0
                    628:                                ADDMAP( NVD*(MAXPHYS/NBPG+CLSIZE) )
                    629: #endif
                    630: #include "yc.h"
                    631: #if NYC > 0
                    632:                                ADDMAP( NCY*(MAXPHYS/NBPG+CLSIZE) )
                    633: #endif
                    634: #include "mp.h"
                    635:                                ADDMAP( NMP*14          )
                    636:        SYSMAP(ekmempt  ,kmemlimit      ,0              )
                    637: 
                    638:        SYSMAP(VMEMbeg  ,vmembeg        ,0              )
                    639:        SYSMAP(VMEMmap  ,vmem           ,VBIOSIZE       )
                    640:        SYSMAP(VMEMmap1 ,vmem1          ,0              )
                    641: #include "ace.h"
                    642: #if NACE > 0
                    643:                                ADDMAP( NACE*32 )
                    644: #endif
                    645: #if NHD > 0
                    646:                                ADDMAP( NHDC )
                    647: #endif
                    648: #include "vx.h"
                    649: #if NVX > 0
                    650:                                ADDMAP( NVX * 16384/NBPG )
                    651: #endif
                    652:        SYSMAP(VMEMend  ,vmemend        ,0              )
                    653: 
                    654:        SYSMAP(VBmap    ,vbbase         ,CLSIZE         )
                    655: #if NHD > 0
                    656:                                ADDMAP( NHDC*(MAXPHYS/NBPG+CLSIZE) )
                    657: #endif
                    658: #if NDK > 0
                    659:                                ADDMAP( NVD*(MAXPHYS/NBPG+CLSIZE) )
                    660: #endif
                    661: #if NYC > 0
                    662:                                ADDMAP( NCY*(MAXPHYS/NBPG+CLSIZE) )
                    663: #endif
                    664:                                ADDMAP( NMP*14          )
                    665:        SYSMAP(eVBmap   ,vbend          ,0              )
                    666: 
                    667:        SYSMAP(Usrptmap ,usrpt          ,USRPTSIZE+CLSIZE )
                    668: eSysmap:
                    669:        .globl  _Syssize
                    670:        .set    _Syssize,(eSysmap-_Sysmap)/4
                    671: 
                    672:        .text
                    673: /*
                    674:  * Initialization
                    675:  *
                    676:  * IPL 0x1f; MME 0; scbb, pcbb, sbr, slr, isp, ksp not set
                    677:  */
                    678:        .align  2
                    679:        .globl  start
                    680: start:
                    681:        .word   0
                    682: /* set system control block base and system page table params */
                    683:        mtpr    $_scb-SYSTEM,$SCBB
                    684:        mtpr    $_Sysmap-SYSTEM,$SBR
                    685:        mtpr    $_Syssize,$SLR
                    686: /* double map the kernel into the virtual user addresses of phys mem */
                    687:        mtpr    $_Sysmap,$P0BR
                    688:        mtpr    $_Syssize,$P0LR
                    689:        mtpr    $_Sysmap,$P1BR                  # against Murphy
                    690:        mtpr    $_Syssize,$P1LR
                    691: /* set ISP */
                    692:        movl    $_intstack-SYSTEM+NISP*NBPG,sp  # still physical
                    693:        mtpr    $_intstack+NISP*NBPG,$ISP
                    694: /* count up memory */
                    695:        clrl    r7
                    696: 1:     pushl   $1; pushl r7; callf $12,_badaddr; tstl r0; bneq 9f
                    697:        ACBL($MAXMEM*1024-1,$64*1024,r7,1b)
                    698: 9:
                    699: /* clear memory from kernel bss and pages for proc 0 u. and page table */
                    700:        movab   _edata,r6; andl2 $~SYSTEM,r6
                    701:        movab   _end,r5; andl2 $~SYSTEM,r5
                    702: #ifdef KADB
                    703:        subl2   $4,r5
                    704: 1:     clrl    (r6); ACBL(r5,$4,r6,1b)         # clear just bss
                    705:        addl2   $4,r5
                    706:        bbc     $6,r11,0f                       # check RB_KDB
                    707:        andl3   $~SYSTEM,r9,r5                  # skip symbol & string tables
                    708:        andl3   $~SYSTEM,r9,r6
                    709: #endif
                    710: 0:     orl3    $SYSTEM,r5,r9                   # convert to virtual address
                    711:        addl2   $NBPG-1,r9                      # roundup to next page
                    712:        addl2   $(UPAGES*NBPG)+NBPG+NBPG,r5
                    713: 1:     clrl    (r6); ACBL(r5,$4,r6,1b)
                    714: /* trap(), syscall(), and fpemulate() save r0-r12 in the entry mask */
                    715:        orw2    $0x01fff,_trap
                    716:        orw2    $0x01fff,_syscall
                    717: #ifdef FPE
                    718:        orw2    $0x01fff,_fpemulate
                    719: #endif
                    720:        orw2    $0x01ffc,_panic                 # for debugging (no r0|r1)
                    721:        callf   $4,_fixctlrmask                 # setup for autoconfig
                    722: /* initialize system page table: scb and int stack writeable */
                    723:        clrl    r2
                    724:        movab   eintstack,r1 
                    725:        andl2   $~SYSTEM,r1
                    726:        shrl    $PGSHIFT,r1,r1                  # r1-page number of eintstack
                    727: /* make 1st page processor storage read/only, 2nd read/write */
                    728:        orl3    $PG_V|PG_KR,r2,_Sysmap[r2]; incl r2;
                    729:        orl3    $PG_V|PG_KW,r2,_Sysmap[r2]; incl r2;
                    730: /* other parts of the system are read/write for kernel */
                    731: 1:     orl3    $PG_V|PG_KW,r2,_Sysmap[r2];     # data:kernel write+phys=virtual
                    732:        aoblss r1,r2,1b
                    733: /* make rsstk read-only as red zone for interrupt stack */
                    734:        andl2   $~PG_PROT,_rsstkmap
                    735:        orl2    $PG_V|PG_KR,_rsstkmap
                    736: /* make kernel text space read-only */
                    737:        movab   _etext+NBPG-1,r1
                    738:        andl2   $~SYSTEM,r1
                    739:        shrl    $PGSHIFT,r1,r1
                    740: 1:     orl3    $PG_V|PG_KR,r2,_Sysmap[r2]
                    741:        aoblss r1,r2,1b
                    742: /* make kernel data, bss, read-write */
                    743:        andl3   $~SYSTEM,r9,r1
                    744:        shrl    $PGSHIFT,r1,r1
                    745: 1:     orl3    $PG_V|PG_KW,r2,_Sysmap[r2]
                    746:        aoblss r1,r2,1b
                    747: /* go to mapped mode, have to change both pc and sp to system addresses */
                    748:        mtpr    $1,$TBIA
                    749:        mtpr    $1,$PADC                        # needed by HW parity&ECC logic
                    750:        mtpr    $1,$PACC                        # just in case
                    751:        mtpr    $1,$MME
                    752:        movab   SYSTEM(sp),sp
                    753:        jmp     *$0f
                    754: 0:
                    755: /* disable any interrupts */
                    756:        movl    $0,_intenable
                    757: /* init mem sizes */
                    758:        shrl    $PGSHIFT,r7,_maxmem
                    759:        movl    _maxmem,_physmem
                    760:        movl    _maxmem,_freemem
                    761: /* setup context for proc[0] == scheduler */
                    762:        andl3   $~SYSTEM,r9,r6                  # convert to physical
                    763:        andl2   $~(NBPG-1),r6                   # make page boundary
                    764: /* setup page table for proc[0] */
                    765:        shrl    $PGSHIFT,r6,r3                  # r3 = btoc(r6)
                    766:        orl3    $PG_V|PG_KW,r3,_Usrptmap        # init first upt entry
                    767:        incl    r3                              # r3 - next page
                    768:        movab   _usrpt,r0                       # r0 - first user page
                    769:        mtpr    r0,$TBIS
                    770: /* init p0br, p0lr */
                    771:        mtpr    r0,$P0BR                        # no p0 for proc[0]
                    772:        mtpr    $0,$P0LR
                    773:        mtpr    r0,$P1BR                        # no p1 either
                    774:        mtpr    $0,$P1LR
                    775: /* init p2br, p2lr */
                    776:        movab   NBPG(r0),r0
                    777:        movl    $PPAGES-UPAGES,r1
                    778:        mtpr    r1,$P2LR
                    779:        moval   -4*PPAGES(r0),r2
                    780:        mtpr    r2,$P2BR
                    781: /* setup mapping for UPAGES of _u */
                    782:        clrl    r2
                    783:        movl    $SYSTEM,r1
                    784:        addl2   $UPAGES,r3
                    785:        jbr 2f
                    786: 1:     decl    r3
                    787:        moval   -NBPG(r1),r1    # r1 = virtual add of next (downward) _u page
                    788:        subl2   $4,r0           # r0 = pte address
                    789:        orl3    $PG_V|PG_URKW,r3,(r0)
                    790:        mtpr    r1,$TBIS
                    791: 2:     aobleq  $UPAGES,r2,1b
                    792: /* initialize (slightly) the pcb */
                    793:        movab   UPAGES*NBPG(r1),PCB_KSP(r1)     # KSP starts at end of _u
                    794:        movl    r1,PCB_USP(r1)                  # USP starts just below _u
                    795:        mfpr    $P0BR,PCB_P0BR(r1)
                    796:        mfpr    $P0LR,PCB_P0LR(r1)
                    797:        mfpr    $P1BR,PCB_P1BR(r1)
                    798:        mfpr    $P1LR,PCB_P1LR(r1)
                    799:        mfpr    $P2BR,PCB_P2BR(r1)
                    800:        mfpr    $P2LR,PCB_P2LR(r1)
                    801:        movl    $CLSIZE,PCB_SZPT(r1)            # init u.u_pcb.pcb_szpt
                    802:        movl    r9,PCB_R9(r1)                   # r9 obtained from boot
                    803:        movl    r10,PCB_R10(r1)                 # r10 obtained from boot
                    804:        movl    r11,PCB_R11(r1)                 # r11 obtained from CP on boot
                    805:        movab   1f,PCB_PC(r1)                   # initial pc
                    806:        clrl    PCB_PSL(r1)                     # kernel mode, ipl=0
                    807:        shll    $PGSHIFT,r3,r3
                    808:        mtpr    r3,$PCBB                        # first pcbb (physical)
                    809: /* go to kernel mode */
                    810:        ldpctx
                    811:        rei                                     # Actually next instruction:
                    812: /* put signal trampoline code in u. area */
                    813: 1:     movab   sigcode,r0
                    814:        movab   _u+PCB_SIGC,r1
                    815:        movl    $19,r2
                    816:        movblk
                    817: /* save boot device in global _bootdev */
                    818:        movl    r10,_bootdev
                    819: /* save reboot flags in global _boothowto */
                    820:        movl    r11,_boothowto
                    821: #ifdef KADB
                    822: /* save end of symbol & string table in global _bootesym */
                    823:        subl3   $NBPG-1,r9,_bootesym
                    824: #endif
                    825: /* calculate firstaddr, and call main() */
                    826:        andl3   $~SYSTEM,r9,r0
                    827:        shrl    $PGSHIFT,r0,-(sp)
                    828:        addl2   $UPAGES+1,(sp)                  # first physical unused page
                    829:        callf   $8,_main
                    830: /* proc[1] == /etc/init now running here in kernel mode; run icode */
                    831:        pushl   $PSL_CURMOD                     # User mode PSL
                    832:        pushl $0                                # PC = 0 (virtual now)
                    833:        rei
                    834: 
                    835: /*
                    836:  * Mask for saving/restoring registers on entry to
                    837:  * a user signal handler.  Space for the registers
                    838:  * is reserved in sendsig, so beware if you want
                    839:  * to change the mask.
                    840:  */
                    841: #define        SIGREGS (R0|R1|R2|R3|R4|R5)
                    842:        .align  2
                    843:        .globl  sigcode
                    844: sigcode:
                    845:        storer  $SIGREGS,16(sp) # save volatile registers
                    846:        calls   $4*3+4,*12(sp)  # params pushed by sendsig for handler
                    847:        loadr   $SIGREGS,4(sp)  # restore volatile registers
                    848:        movab   24(sp),fp       # use parameter list set up in sendsig
                    849:        kcall   $SYS_sigreturn  # cleanup mask and onsigstack
                    850:        halt                    # sigreturn does not return!
                    851: 
                    852:        .globl  _icode
                    853:        .globl  _initflags
                    854:        .globl  _szicode
                    855: /*
                    856:  * Icode is copied out to process 1 to exec /etc/init.
                    857:  * If the exec fails, process 1 exits.
                    858:  */
                    859:        .align  2
                    860: _icode:
                    861:        /* try /sbin/init */
                    862:        pushab  b`argv1-l0(pc)
                    863: l0:    pushab  b`init1-l1(pc)
                    864: l1:    pushl   $2
                    865:        movab   (sp),fp
                    866:        kcall   $SYS_execv
                    867:        /* try /etc/init */
                    868:        pushab  b`argv2-l2(pc)
                    869: l2:    pushab  b`init2-l3(pc)
                    870: l3:    pushl   $2
                    871:        movab   (sp),fp
                    872:        kcall   $SYS_execv
                    873:        /* give up */
                    874:        pushl   r0
                    875:        pushl   $1
                    876:        movab   (sp),fp
                    877:        kcall   $SYS_exit
                    878: 
                    879: init1: .asciz  "/sbin/init"
                    880: init2: .asciz  "/etc/init"
                    881:        .align  2
                    882: _initflags:
                    883:        .long   0
                    884: argv1: .long   init1+6-_icode
                    885:        .long   _initflags-_icode
                    886:        .long   0
                    887: argv2: .long   init2+5-_icode
                    888:        .long   _initflags-_icode
                    889:        .long   0
                    890: _szicode:
                    891:        .long   _szicode-_icode
                    892: 
                    893: /*
                    894:  * Primitives
                    895:  */ 
                    896: 
                    897: /*
                    898:  * badaddr(addr, len)
                    899:  *     see if access addr with a len type instruction causes a machine check
                    900:  *     len is length of access (1=byte, 2=short, 4=long)
                    901:  *     r0 = 0 means good(exists); r0 =1 means does not exist.
                    902:  */
                    903: ENTRY(badaddr, R3|R4)
                    904:        mfpr    $IPL,r1
                    905:        mtpr    $HIGH,$IPL
                    906:        movl    _scb+SCB_BUSERR,r2
                    907:        movl    4(fp),r3
                    908:        movl    8(fp),r4
                    909:        movab   9f,_scb+SCB_BUSERR
                    910:        bbc     $0,r4,1f; tstb  (r3)
                    911: 1:     bbc     $1,r4,1f; tstw  (r3)
                    912: 1:     bbc     $2,r4,1f; tstl  (r3)
                    913: 1:     clrl    r0
                    914: 2:     movl    r2,_scb+SCB_BUSERR
                    915:        mtpr    r1,$IPL
                    916:        ret
                    917: 
                    918: /*
                    919:  * wbadaddr(addr, len, value)
                    920:  *     see if write of value to addr with a len type instruction causes
                    921:  *     a machine check
                    922:  *     len is length of access (1=byte, 2=short, 4=long)
                    923:  *     r0 = 0 means good(exists); r0 =1 means does not exist.
                    924:  */
                    925: ENTRY(wbadaddr, R3|R4)
                    926:        mfpr    $IPL,r1
                    927:        mtpr    $HIGH,$IPL
                    928:        movl    _scb+SCB_BUSERR,r2
                    929:        movl    4(fp),r3
                    930:        movl    8(fp),r4
                    931:        movab   9f,_scb+SCB_BUSERR
                    932:        bbc     $0,r4,1f; movb  15(fp), (r3)
                    933: 1:     bbc     $1,r4,1f; movw  14(fp), (r3)
                    934: 1:     bbc     $2,r4,1f; movl  12(fp), (r3)
                    935: 1:     movl    $30000,r0               # delay for error interrupt
                    936: 1:     decl    r0
                    937:        jneq    1b
                    938: 2:     movl    r2,_scb+SCB_BUSERR      # made it w/o machine checks; r0 is 0
                    939:        mtpr    r1,$IPL
                    940:        ret
                    941: 
                    942:        .align  2
                    943: 9:                             # catch buss error (if it comes)
                    944:        andl3   4(sp),$ERRCD,r0
                    945:        cmpl    r0,$APE
                    946:        jneq    1f
                    947:        halt                    # address parity error
                    948: 1:     cmpl    r0,$VBE
                    949:        jneq    1f
                    950:        halt                    # Versabus error
                    951: 1:
                    952:        movl    $1,r0           # Anything else = bad address
                    953:        movab   8(sp),sp        # discard buss error trash
                    954:        movab   2b,(sp)         # new program counter on stack.
                    955:        rei
                    956: 
                    957: /*
                    958:  * badcyaddr(addr)
                    959:  *     see if access tape master controller addr causes a bus error
                    960:  *     r0 = 0: no error; r0 = 1: timeout error.
                    961:  */
                    962: ENTRY(badcyaddr, 0)
                    963:        mfpr    $IPL,r1
                    964:        mtpr    $HIGH,$IPL
                    965:        clrl    r2
                    966:        movab   2f,nofault
                    967:        movob   $-1, *4(fp)
                    968: 1:     aobleq  $1000, r2, 1b
                    969:        clrl    nofault                 # made it w/o bus error
                    970:        clrl    r0
                    971:        jbr     3f
                    972: 2:     movl    $1,r0
                    973: 3:     mtpr    r1,$IPL
                    974:        ret
                    975: 
                    976: /*
                    977:  * peek(addr)
                    978:  *     fetch word and catch any bus error
                    979:  */
                    980: ENTRY(peek, 0)
                    981:        mfpr    $IPL,r1
                    982:        mtpr    $0x18,$IPL      # not reentrant
                    983:        movl    4(fp),r2
                    984:        movab   1f,nofault
                    985:        movw    (r2),r0
                    986:        clrl    nofault
                    987:        andl2   $0xffff,r0
                    988:        jbr     2f
                    989: 1:     movl    $-1,r0          # bus error
                    990: 2:     mtpr    r1,$IPL
                    991:        ret
                    992: 
                    993: /*
                    994:  * poke(addr, val)
                    995:  *     write word and catch any bus error
                    996:  */
                    997: ENTRY(poke, R3)
                    998:        mfpr    $IPL,r1
                    999:        mtpr    $0x18,$IPL      # not reentrant
                   1000:        movl    4(fp),r2
                   1001:        movl    8(fp),r3
                   1002:        clrl    r0
                   1003:        movab   1f,nofault
                   1004:        movw    r3,(r2)
                   1005:        clrl    nofault
                   1006:        jbr     2f
                   1007: 1:     movl    $-1,r0          # bus error
                   1008: 2:     mtpr    r1,$IPL
                   1009:        ret
                   1010: 
                   1011: /*
                   1012:  * Copy a potentially overlapping block of memory.
                   1013:  *
                   1014:  * ovbcopy(src, dst, count)
                   1015:  *     caddr_t src, dst; unsigned count;
                   1016:  */
                   1017: ENTRY(ovbcopy, R3|R4)
                   1018:        movl    4(fp),r0
                   1019:        movl    8(fp),r1
                   1020:        movl    12(fp),r2
                   1021:        cmpl    r0,r1
                   1022:        bgtru   1f                      # normal forward case
                   1023:        beql    2f                      # equal, nothing to do
                   1024:        addl2   r2,r0                   # may be overlapping
                   1025:        cmpl    r0,r1
                   1026:        bgtru   3f
                   1027:        subl2   r2,r0                   # normal forward case
                   1028: 1:
                   1029:        movblk
                   1030: 2:
                   1031:        ret
                   1032: 3:
                   1033:        addl2   r2,r1                   # overlapping, must do backwards
                   1034:        subl3   r0,r1,r3
                   1035:        movl    r2,r4
                   1036:        jbr     5f
                   1037: 4:
                   1038:        subl2   r3,r0
                   1039:        subl2   r3,r1
                   1040:        movl    r3,r2
                   1041:        movblk
                   1042:        subl2   r3,r0
                   1043:        subl2   r3,r1
                   1044:        subl2   r3,r4
                   1045: 5:
                   1046:        cmpl    r4,r3
                   1047:        jgtr    4b
                   1048:        movl    r4,r2
                   1049:        subl2   r2,r0
                   1050:        subl2   r2,r1
                   1051:        movblk
                   1052:        ret
                   1053: 
                   1054: /*
                   1055:  * Copy a null terminated string from the user address space into
                   1056:  * the kernel address space.
                   1057:  *
                   1058:  * copyinstr(fromaddr, toaddr, maxlength, &lencopied)
                   1059:  */
                   1060: ENTRY(copyinstr, 0)
                   1061:        movl    12(fp),r5               # r5 = max length
                   1062:        jlss    5f
                   1063:        movl    8(fp),r4                # r4 = kernel address
                   1064:        movl    4(fp),r0                # r0 = user address
                   1065:        andl3   $(NBPG*CLSIZE-1),r0,r2  # r2 = bytes on first page
                   1066:        subl3   r2,$(NBPG*CLSIZE),r2
                   1067: 1:
                   1068:        cmpl    r5,r2                   # r2 = min(bytes on page, length left);
                   1069:        jgeq    2f
                   1070:        movl    r5,r2
                   1071: 2:
                   1072:        prober  $1,(r0),r2              # bytes accessible?
                   1073:        jeql    5f
                   1074:        subl2   r2,r5                   # update bytes left count
                   1075:        movl    r2,r3                   # r3 = saved count
                   1076:        movl    r0,r1
                   1077:        cmps3                           # check for null
                   1078:        tstl    r2
                   1079:        jneq    3f
                   1080:        subl2   r3,r0                   # back up r0
                   1081:        movl    r4,r1
                   1082:        movl    r3,r2
                   1083:        movblk                          # copy in next piece
                   1084:        movl    r1,r4
                   1085:        movl    $(NBPG*CLSIZE),r2       # check next page
                   1086:        tstl    r5                      # run out of space?
                   1087:        jneq    1b
                   1088:        movl    $ENOENT,r0              # set error code and return
                   1089:        jbr     6f
                   1090: 3:
                   1091:        tstl    16(fp)                  # return length?
                   1092:        beql    4f
                   1093:        subl3   r5,12(fp),r5            # actual len = maxlen - unused pages
                   1094:        subl2   r2,r5                   #       - unused on this page
                   1095:        addl3   $1,r5,*16(fp)           #       + the null byte
                   1096: 4:
                   1097:        movl    r4,r1
                   1098:        subl3   r2,r3,r2                # calc char cnt
                   1099:        subl2   r2,r0                   # back up r0
                   1100:        incl    r2                      # add on null byte
                   1101:        movblk                          # copy last piece
                   1102:        clrl    r0
                   1103:        ret
                   1104: 5:
                   1105:        movl    $EFAULT,r0
                   1106: 6:
                   1107:        tstl    16(fp)
                   1108:        beql    7f
                   1109:        subl3   r5,12(fp),*16(fp)
                   1110: 7:
                   1111:        ret
                   1112: 
                   1113: /*
                   1114:  * Copy a null terminated string from the kernel
                   1115:  * address space to the user address space.
                   1116:  *
                   1117:  * copyoutstr(fromaddr, toaddr, maxlength, &lencopied)
                   1118:  */
                   1119: ENTRY(copyoutstr, 0)
                   1120:        movl    12(fp),r5               # r5 = max length
                   1121:        jlss    5f
                   1122:        movl    4(fp),r0                # r0 = kernel address
                   1123:        movl    8(fp),r4                # r4 = user address
                   1124:        andl3   $(NBPG*CLSIZE-1),r4,r2  # r2 = bytes on first page
                   1125:        subl3   r2,$(NBPG*CLSIZE),r2
                   1126: 1:
                   1127:        cmpl    r5,r2                   # r2 = min(bytes on page, length left);
                   1128:        jgeq    2f
                   1129:        movl    r5,r2
                   1130: 2:
                   1131:        probew  $1,(r4),r2              # bytes accessible?
                   1132:        jeql    5f
                   1133:        subl2   r2,r5                   # update bytes left count
                   1134:        movl    r2,r3                   # r3 = saved count
                   1135:        movl    r0,r1
                   1136: /*
                   1137:  * This is a workaround for a microcode bug that causes
                   1138:  * a trap type 9 when cmps3/movs3 touches the last byte
                   1139:  * on a valid page immediately followed by an invalid page.
                   1140:  */
                   1141: #ifdef good_cmps3
                   1142:        cmps3                           # check for null
                   1143:        tstl    r2
                   1144:        jneq    3b
                   1145: #else
                   1146:        decl    r2
                   1147:        beql    9f                      # cannot handle case of r2 == 0!
                   1148:        cmps3                           # check for null up to last byte
                   1149: 9:
                   1150:        incl    r2
                   1151:        cmpl    $1,r2                   # get to last byte on page?
                   1152:        bneq    3b
                   1153:        tstb    (r0)                    # last byte on page null?
                   1154:        beql    3b
                   1155:        incl    r0                      # not null, so bump pointer
                   1156: #endif not good_cmps3
                   1157:        subl2   r3,r0                   # back up r0
                   1158:        movl    r4,r1
                   1159:        movl    r3,r2
                   1160:        movblk                          # copy out next piece
                   1161:        movl    r1,r4
                   1162:        movl    $(NBPG*CLSIZE),r2       # check next page
                   1163:        tstl    r5                      # run out of space?
                   1164:        jneq    1b
                   1165:        movl    $ENOENT,r0              # set error code and return
                   1166:        jbr     6b
                   1167: 5:
                   1168:        clrl    *$0             # this should never execute, if it does
                   1169:        movl    $EFAULT,r0      #  save me a core dump (mkm - 9/87)
                   1170: 6:
                   1171:        tstl    16(fp)
                   1172:        beql    7f
                   1173:        subl3   r5,12(fp),*16(fp)
                   1174: 7:
                   1175:        ret
                   1176: 
                   1177: 
                   1178: /*
                   1179:  * Copy a null terminated string from one point to another in
                   1180:  * the kernel address space.
                   1181:  *
                   1182:  * copystr(fromaddr, toaddr, maxlength, &lencopied)
                   1183:  */
                   1184: ENTRY(copystr, 0)
                   1185:        movl    12(fp),r3               # r3 = max length
                   1186:        jlss    5b
                   1187:        movl    4(fp),r0                # r0 = src address
                   1188:        movl    8(fp),r4                # r4 = dest address
                   1189:        clrl    r5                      # r5 = bytes left
                   1190:        movl    r3,r2                   # r2 = max bytes to copy
                   1191:        movl    r0,r1
                   1192:        cmps3                           # check for null
                   1193:        tstl    r2
                   1194:        jneq    3b
                   1195:        subl2   r3,r0                   # back up r0
                   1196:        movl    r4,r1
                   1197:        movl    r3,r2
                   1198:        movblk                          # copy next piece
                   1199:        movl    $ENOENT,r0              # set error code and return
                   1200:        jbr     6b
                   1201: 
                   1202: /*
                   1203:  * Copy a block of data from the user address space into
                   1204:  * the kernel address space.
                   1205:  *
                   1206:  * copyin(fromaddr, toaddr, count)
                   1207:  */
                   1208: ENTRY(copyin, 0)
                   1209:        movl    12(fp),r0               # copy length
                   1210:        blss    9f
                   1211:        movl    4(fp),r1                # copy user address
                   1212:        cmpl    $(CLSIZE*NBPG),r0       # probing one page or less ?
                   1213:        bgeq    2f                      # yes
                   1214: 1:
                   1215:        prober  $1,(r1),$(CLSIZE*NBPG)  # bytes accessible ?
                   1216:        beql    9f                      # no
                   1217:        addl2   $(CLSIZE*NBPG),r1       # incr user address ptr
                   1218:        _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r0,1b)   # reduce count and loop
                   1219: 2:
                   1220:        prober  $1,(r1),r0              # bytes accessible ?
                   1221:        beql    9f                      # no
                   1222:        MOVC3(4(fp),8(fp),12(fp))
                   1223:        clrl    r0
                   1224:        ret
                   1225: 9:
                   1226:        movl    $EFAULT,r0
                   1227:        ret
                   1228: 
                   1229: /*
                   1230:  * Copy a block of data from the kernel 
                   1231:  * address space to the user address space.
                   1232:  *
                   1233:  * copyout(fromaddr, toaddr, count)
                   1234:  */
                   1235: ENTRY(copyout, 0)
                   1236:        movl    12(fp),r0               # get count
                   1237:        blss    9b
                   1238:        movl    8(fp),r1                # get user address
                   1239:        cmpl    $(CLSIZE*NBPG),r0       # can do in one probew?
                   1240:        bgeq    2f                      # yes
                   1241: 1:
                   1242:        probew  $1,(r1),$(CLSIZE*NBPG)  # bytes accessible?
                   1243:        beql    9b                      # no 
                   1244:        addl2   $(CLSIZE*NBPG),r1       # increment user address
                   1245:        _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r0,1b)   # reduce count and loop
                   1246: 2:
                   1247:        probew  $1,(r1),r0              # bytes accessible?
                   1248:        beql    9b                      # no
                   1249:        MOVC3(4(fp),8(fp),12(fp))
                   1250:        clrl    r0
                   1251:        ret
                   1252: 
                   1253: /*
                   1254:  * non-local goto's
                   1255:  */
                   1256: #ifdef notdef
                   1257: ENTRY(setjmp, 0)
                   1258:        movl    4(fp),r0
                   1259:        movl    (fp),(r0); addl2 $4,r0          # save fp
                   1260:        movl    -8(fp),(r0)                     # save pc
                   1261:        clrl    r0
                   1262:        ret
                   1263: #endif
                   1264: 
                   1265: ENTRY(longjmp, 0)
                   1266:        movl    4(fp),r0
                   1267:        movl    (r0),newfp; addl2 $4,r0         # must save parameters in memory
                   1268:        movl    (r0),newpc                      # as all regs may be clobbered.
                   1269: 1:
                   1270:        cmpl    fp,newfp                        # are we there yet?
                   1271:        bgequ   2f                              # yes
                   1272:        moval   1b,-8(fp)                       # redirect return pc to us!
                   1273:        ret                                     # pop next frame
                   1274: 2:
                   1275:        beql    3f                              # did we miss our frame?
                   1276:        pushab  4f                              # yep ?!?
                   1277:        callf   $8,_panic
                   1278: 3:
                   1279:        movl    newpc,r0                        # all done, just return
                   1280:        jmp     (r0)                            # to setjmp `ret'
                   1281: 
                   1282:        .data
                   1283: newpc: .space  4
                   1284: newfp: .space  4
                   1285: 4:     .asciz  "longjmp"
                   1286:        .text
                   1287: 
                   1288: /*
                   1289:  * setjmp that saves all registers as the call frame may not
                   1290:  * be available to recover them in the usual manner by longjmp.
                   1291:  * Called before swapping out the u. area, restored by resume()
                   1292:  * below.
                   1293:  */
                   1294: ENTRY(savectx, 0)
                   1295:        movl    4(fp),r2
                   1296:        storer  $0x1ff8,(r2); addl2 $40,r2      # r3-r12
                   1297:        movl    (fp),(r2); addl2 $4,r2          # fp
                   1298:        movab   8(fp),(r2); addl2 $4,r2         # sp
                   1299:        movl    -8(fp),(r2)                     # pc
                   1300:        clrl    r0
                   1301:        ret
                   1302: 
                   1303: #ifdef KADB
                   1304: /*
                   1305:  * C library -- reset, setexit
                   1306:  *
                   1307:  *     reset(x)
                   1308:  * will generate a "return" from
                   1309:  * the last call to
                   1310:  *     setexit()
                   1311:  * by restoring r2 - r12, fp
                   1312:  * and doing a return.
                   1313:  * The returned value is x; on the original
                   1314:  * call the returned value is 0.
                   1315:  */
                   1316: ENTRY(setexit, 0)
                   1317:        movab   setsav,r0
                   1318:        storer  $0x1ffc, (r0)
                   1319:        movl    (fp),44(r0)             # fp
                   1320:        moval   4(fp),48(r0)            # sp
                   1321:        movl    -8(fp),52(r0)           # pc
                   1322:        clrl    r0
                   1323:        ret
                   1324: 
                   1325: ENTRY(reset, 0)
                   1326:        movl    4(fp),r0        # returned value
                   1327:        movab   setsav,r1
                   1328:        loadr   $0x1ffc,(r1)
                   1329:        movl    44(r1),fp
                   1330:        movl    48(r1),sp
                   1331:        jmp     *52(r1)
                   1332: 
                   1333:        .data
                   1334:        .align  2
                   1335: setsav:        .space  14*4
                   1336:        .text
                   1337: #endif
                   1338: 
                   1339:        .globl  _whichqs
                   1340:        .globl  _qs
                   1341:        .globl  _cnt
                   1342: 
                   1343:        .globl  _noproc
                   1344:        .comm   _noproc,4
                   1345:        .globl  _runrun
                   1346:        .comm   _runrun,4
                   1347: /*
                   1348:  * The following primitives use the fancy TAHOE instructions.
                   1349:  * _whichqs tells which of the 32 queues _qs
                   1350:  * have processes in them.  setrq puts processes into queues, remrq
                   1351:  * removes them from queues.  The running process is on no queue,
                   1352:  * other processes are on a queue related to p->p_pri, divided by 4
                   1353:  * actually to shrink the 0-127 range of priorities into the 32 available
                   1354:  * queues.
                   1355:  */
                   1356: 
                   1357: /*
                   1358:  * setrq(p), using fancy TAHOE instructions.
                   1359:  *
                   1360:  * Call should be made at spl8(), and p->p_stat should be SRUN
                   1361:  */
                   1362: ENTRY(setrq, 0)
                   1363:        movl    4(fp),r0
                   1364:        tstl    P_RLINK(r0)             ## firewall: p->p_rlink must be 0
                   1365:        beql    set1                    ##
                   1366:        pushab  set3                    ##
                   1367:        callf   $8,_panic               ##
                   1368: set1:
                   1369:        movzbl  P_PRI(r0),r1            # put on queue which is p->p_pri / 4
                   1370:        shar    $2,r1,r1
                   1371:        shal    $1,r1,r2
                   1372:        moval   _qs[r2],r2
                   1373:        insque  (r0),*4(r2)             # at end of queue
                   1374:        shal    r1,$1,r1
                   1375:        orl2    r1,_whichqs             # mark queue non-empty
                   1376:        ret
                   1377: 
                   1378: set3:  .asciz  "setrq"
                   1379: 
                   1380: /*
                   1381:  * remrq(p), using fancy TAHOE instructions
                   1382:  *
                   1383:  * Call should be made at spl8().
                   1384:  */
                   1385: ENTRY(remrq, 0)
                   1386:        movl    4(fp),r0
                   1387:        movzbl  P_PRI(r0),r1
                   1388:        shar    $2,r1,r1
                   1389:        bbs     r1,_whichqs,rem1
                   1390:        pushab  rem3                    # it wasn't recorded to be on its q
                   1391:        callf   $8,_panic
                   1392: rem1:
                   1393:        remque  (r0)
                   1394:        bneq    rem2                    # q not empty yet
                   1395:        shal    r1,$1,r1
                   1396:        mcoml   r1,r1
                   1397:        andl2   r1,_whichqs             # mark queue empty
                   1398: rem2:
                   1399:        clrl    P_RLINK(r0)             ## for firewall checking
                   1400:        ret
                   1401: 
                   1402: rem3:  .asciz  "remrq"
                   1403: 
                   1404: /*
                   1405:  * Masterpaddr is the p->p_addr of the running process on the master
                   1406:  * processor.  When a multiprocessor system, the slave processors will have
                   1407:  * an array of slavepaddr's.
                   1408:  */
                   1409:        .globl  _masterpaddr
                   1410:        .data
                   1411:        .align  2
                   1412: _masterpaddr: .long    0
                   1413: 
                   1414:        .text
                   1415: sw0:   .asciz  "swtch"
                   1416: 
                   1417: /*
                   1418:  * When no processes are on the runq, swtch branches to idle
                   1419:  * to wait for something to come ready.
                   1420:  */
                   1421:        .globl  Idle
                   1422: Idle: idle:
                   1423:        movl    $1,_noproc
                   1424:        mtpr    $0,$IPL                 # must allow interrupts here
                   1425: 1:
                   1426:        tstl    _whichqs                # look for non-empty queue
                   1427:        bneq    sw1
                   1428:        brb     1b
                   1429: 
                   1430: badsw: pushab  sw0
                   1431:        callf   $8,_panic
                   1432:        /* NOTREACHED */
                   1433: 
                   1434:        .align  2
                   1435: /*
                   1436:  * swtch(), using fancy tahoe instructions
                   1437:  */
                   1438: ENTRY(swtch, 0)
                   1439:        movl    (fp),fp                 # prepare for rei
                   1440:        movl    (sp),4(sp)              # saved pc
                   1441:        tstl    (sp)+
                   1442:        movpsl  4(sp)
                   1443:        incl    _cnt+V_SWTCH
                   1444: sw1:   ffs     _whichqs,r0             # look for non-empty queue
                   1445:        blss    idle                    # if none, idle
                   1446:        mtpr    $0x18,$IPL              # lock out all so _whichqs==_qs
                   1447:        bbc     r0,_whichqs,sw1         # proc moved via interrupt
                   1448:        shal    $1,r0,r1
                   1449:        moval   _qs[r1],r1
                   1450:        movl    (r1),r2                 # r2 = p = highest pri process
                   1451:        remque  *(r1)
                   1452:        bvs     badsw                   # make sure something was there
                   1453:        bneq    sw2
                   1454:        shal    r0,$1,r1
                   1455:        mcoml   r1,r1
                   1456:        andl2   r1,_whichqs             # no more procs in this queue
                   1457: sw2:
                   1458:        clrl    _noproc
                   1459:        clrl    _runrun
                   1460: #ifdef notdef
                   1461:        tstl    P_WCHAN(r2)             ## firewalls
                   1462:        bneq    badsw                   ##
                   1463:        cmpb    P_STAT(r2),$SRUN        ##
                   1464:        bneq    badsw                   ##
                   1465: #endif
                   1466:        clrl    P_RLINK(r2)             ##
                   1467:        movl    *P_ADDR(r2),r0
                   1468: #ifdef notdef
                   1469:        cmpl    r0,_masterpaddr         # resume of current proc is easy
                   1470:        beql    res0
                   1471: #endif
                   1472:        movl    r0,_masterpaddr
                   1473:        shal    $PGSHIFT,r0,r0          # r0 = pcbb(p)
                   1474:        brb     swresume
                   1475: 
                   1476: /*
                   1477:  * resume(pf)
                   1478:  */
                   1479: ENTRY(resume, 0)
                   1480:        shal    $PGSHIFT,4(fp),r0       # r0 = pcbb(pf)
                   1481:        movl    (fp),fp                 # prepare for rei
                   1482:        movl    (sp)+,4(sp)             # saved pc
                   1483:        tstl    (sp)+
                   1484:        movpsl  4(sp)
                   1485: swresume:
                   1486:        mtpr    $0x18,$IPL              # no interrupts, please
                   1487:        movl    _CMAP2,_u+PCB_CMAP2     # yech
                   1488:        REST_ACC                        # restore original accumulator
                   1489:        svpctx
                   1490:        mtpr    r0,$PCBB
                   1491:        ldpctx
                   1492:        movl    _u+PCB_CMAP2,_CMAP2     # yech
                   1493:        mtpr    $_CADDR2,$TBIS
                   1494: res0:
                   1495:        movl    _u+U_PROCP,r2           # r2 = u.u_procp
                   1496:        tstl    P_CKEY(r2)              # does proc have code key?
                   1497:        bneq    1f
                   1498:        callf   $4,_getcodekey          # no, give him one
                   1499:        movl    _u+U_PROCP,r2           # r2 = u.u_procp
                   1500:        movl    r0,P_CKEY(r2)
                   1501: 1:
                   1502:        tstl    P_DKEY(r2)              # does proc have data key?
                   1503:        bneq    1f
                   1504:        callf   $4,_getdatakey          # no, give him one
                   1505:        movl    _u+U_PROCP,r2           # r2 = u.u_procp
                   1506:        movl    r0,P_DKEY(r2)
                   1507: 1:
                   1508:        mtpr    P_CKEY(r2),$CCK         # set code cache key
                   1509:        mtpr    P_DKEY(r2),$DCK         # set data cache key
                   1510:        tstl    _u+PCB_SSWAP
                   1511:        bneq    res1
                   1512:        rei
                   1513: res1:                                  # longjmp to saved context
                   1514:        movl    _u+PCB_SSWAP,r2
                   1515:        clrl    _u+PCB_SSWAP
                   1516:        loadr   $0x3ff8,(r2); addl2 $44,r2      # restore r3-r13 (r13=fp)
                   1517:        movl    (r2),r1; addl2 $4,r2    # fetch previous sp ...
                   1518:        movab   (sp),r0                 # ... and current sp and
                   1519:        cmpl    r1,r0                   # check for credibility,
                   1520:        bgequ   1f                      # if further up stack ...
                   1521:        pushab 2f; callf $8,_panic      # ... panic
                   1522:        /*NOTREACHED*/
                   1523: 1:                                     # sp ok, complete return
                   1524:        movl    r1,sp                   # restore sp
                   1525:        pushl   $PSL_PRVMOD             # kernel mode, ipl 0
                   1526:        pushl   (r2)                    # return address
                   1527:        rei
                   1528: 2:     .asciz  "ldctx"
                   1529: 
                   1530: /*
                   1531:  * {fu,su},{byte,word}
                   1532:  */
                   1533: ENTRY(fuword, 0)
                   1534:        movl    4(fp), r1
                   1535:        prober  $1,(r1),$4              # check access
                   1536:        beql    fserr                   # page unreadable
                   1537:        bitl    $1,r1                   # check byte alignment
                   1538:        bneq    2f                      # odd, do byte-word-byte
                   1539:        bitl    $2,r1                   # check word alignment
                   1540:        bneq    1f                      # odd, do in 2 words
                   1541:        movl    (r1),r0                 # move longword
                   1542:        ret
                   1543: 1:
                   1544:        movw    (r1),r0                 # move two words
                   1545:        shal    $16,r0,r0
                   1546:        movzwl  2(r1),r1                # orw2 sign extends
                   1547:        orl2    r1,r0
                   1548:        ret
                   1549: 2:
                   1550:        movb    (r1),r0                 # move byte-word-byte
                   1551:        shal    $24,r0,r0
                   1552:        movzwl  1(r1),r2                # orw2 sign extends
                   1553:        shal    $8,r2,r2
                   1554:        movzbl  3(r1),r1                # orb2 sign extends
                   1555:        orl2    r2,r1
                   1556:        orl2    r1,r0
                   1557:        ret
                   1558: fserr:
                   1559:        mnegl   $1,r0
                   1560:        ret
                   1561: 
                   1562: ENTRY(fubyte, 0)
                   1563:        prober  $1,*4(fp),$1
                   1564:        beql    fserr
                   1565:        movzbl  *4(fp),r0
                   1566:        ret
                   1567: 
                   1568: ENTRY(suword, 0)
                   1569:        movl    4(fp), r0
                   1570:        probew  $1,(r0),$4              # check access
                   1571:        beql    fserr                   # page unwritable
                   1572:        bitl    $1,r0                   # check byte alignment
                   1573:        bneq    1f                      # odd byte boundary
                   1574:        bitl    $2,r0                   # check word alignment
                   1575:        beql    2f                      # longword aligned
                   1576:        movw    8(fp),(r0)              # move two words
                   1577:        movw    10(fp),2(r0)
                   1578:        jbr     3f
                   1579: 1:
                   1580:        movb    8(fp),(r0)
                   1581:        movb    9(fp),1(r0)
                   1582:        movb    10(fp),2(r0)
                   1583:        movb    11(fp),3(r0)
                   1584:        jbr     3f
                   1585: 2:
                   1586:        movl    8(fp),(r0)
                   1587: 3:
                   1588:        clrl    r0
                   1589:        ret
                   1590: 
                   1591: ENTRY(subyte, 0)
                   1592:        probew  $1,*4(fp),$1
                   1593:        beql    fserr
                   1594:        movb    11(fp),*4(fp)
                   1595:        clrl    r0
                   1596:        ret
                   1597: 
                   1598: /*
                   1599:  * Copy 1 relocation unit (NBPG bytes)
                   1600:  * from user virtual address to physical address
                   1601:  */
                   1602: ENTRY(copyseg, 0)
                   1603:        orl3    $PG_V|PG_KW,8(fp),_CMAP2
                   1604:        mtpr    $_CADDR2,$TBIS  # invalidate entry for copy 
                   1605:        MOVC3(4(fp),$_CADDR2,$NBPG)
                   1606:        ret
                   1607: 
                   1608: /*
                   1609:  * Clear a page of memory.  The page frame is specified.
                   1610:  *
                   1611:  * clearseg(pf);
                   1612:  */
                   1613: ENTRY(clearseg, 0)
                   1614:        orl3    $PG_V|PG_KW,4(fp),_CMAP1        # Maps to virtual addr CADDR1
                   1615:        mtpr    $_CADDR1,$TBIS
                   1616:        movl    $255,r0                         # r0 = limit
                   1617:        clrl    r1                              # r1 = index of cleared long
                   1618: 1:
                   1619:        clrl    _CADDR1[r1]
                   1620:        aobleq  r0,r1,1b
                   1621:        ret
                   1622: 
                   1623: /*
                   1624:  * Check user mode read/write access.
                   1625:  *
                   1626:  * useracc(addr, count, mode)
                   1627:  *     caddr_t addr; int count, mode;
                   1628:  * mode = 0    write access
                   1629:  * mode = 1    read access
                   1630:  */
                   1631: ENTRY(useracc, 0)
                   1632:        movl    $1,r2                   # r2 = 'user mode' for probew/probew
                   1633: probes:
                   1634:        movl    4(fp),r0                # get va
                   1635:        movl    8(fp),r1                # count
                   1636:        tstl    12(fp)                  # test for read access ?
                   1637:        bneq    userar                  # yes
                   1638:        cmpl    $(CLSIZE*NBPG),r1       # can we do it in one probe ?
                   1639:        bgeq    uaw2                    # yes
                   1640: uaw1:
                   1641:        probew  r2,(r0),$(CLSIZE*NBPG)
                   1642:        beql    uaerr                   # no access
                   1643:        addl2   $(CLSIZE*NBPG),r0
                   1644:        _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r1,uaw1)
                   1645: uaw2:
                   1646:        probew  r2,(r0),r1
                   1647:        beql    uaerr
                   1648:        movl    $1,r0
                   1649:        ret
                   1650: userar:
                   1651:        cmpl    $(CLSIZE*NBPG),r1
                   1652:        bgeq    uar2
                   1653: uar1:
                   1654:        prober  r2,(r0),$(CLSIZE*NBPG)
                   1655:        beql    uaerr
                   1656:        addl2   $(CLSIZE*NBPG),r0
                   1657:        _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r1,uar1)
                   1658: uar2:
                   1659:        prober  r2,(r0),r1
                   1660:        beql    uaerr
                   1661:        movl    $1,r0
                   1662:        ret
                   1663: uaerr:
                   1664:        clrl    r0
                   1665:        ret
                   1666: 
                   1667: /*
                   1668:  * Check kernel mode read/write access.
                   1669:  *
                   1670:  * kernacc(addr, count, mode)
                   1671:  *     caddr_t addr; int count, mode;
                   1672:  * mode = 0    write access
                   1673:  * mode = 1    read access
                   1674:  */
                   1675: ENTRY(kernacc, 0)
                   1676:        clrl    r2              # r2 = 0 means kernel mode probe.
                   1677:        jbr     probes          # Dijkstra would get gastric distress here.
                   1678: 
                   1679: /*
                   1680:  * addupc - increment some histogram counter
                   1681:  *     in the profiling buffer
                   1682:  *
                   1683:  * addupc(pc, prof, delta)
                   1684:  *     long pc; short delta; struct uprof *prof;
                   1685:  * 
                   1686:  * struct uprof {              # profile arguments 
                   1687:  *     short   *r_base;        # buffer base 
                   1688:  *     unsigned pr_size;       # buffer size 
                   1689:  *     unsigned pr_off;        # pc offset 
                   1690:  *     unsigned pr_scale;      # pc scaling 
                   1691:  * }
                   1692:  */
                   1693: ENTRY(addupc, 0)
                   1694:        movl    8(fp),r2                # r2 points to structure
                   1695:        subl3   8(r2),4(fp),r0          # r0 = PC - lowpc
                   1696:        jlss    9f                      # PC < lowpc , out of range !
                   1697:        shrl    $1,r0,r0                # the unit is words
                   1698:        shrl    $1,12(r2),r1            # ditto for scale
                   1699:        emul    r1,r0,$0,r0
                   1700:        shrq    $14,r0,r0
                   1701:        tstl    r0                      # too big
                   1702:        jneq    9f
                   1703:        cmpl    r1,4(r2)                # Check buffer overflow
                   1704:        jgequ   9f
                   1705:        probew  $1,*0(r2)[r1],$2        # counter accessible?
                   1706:        jeql    9f
                   1707:        shrl    $1,r1,r1                # make r1 word index
                   1708:        addw2   14(fp),*0(r2)[r1]
                   1709: 9:     ret
                   1710: 
                   1711: /*
                   1712:  * scanc(size, cp, table, mask)
                   1713:  */
                   1714: ENTRY(scanc, R3|R4)
                   1715:        movl    8(fp),r0                # r0 = cp
                   1716:        addl3   4(fp),r0,r2             # end = &cp[size]
                   1717:        movl    12(fp),r1               # r1 = table
                   1718:        movb    19(fp),r4               # r4 = mask
                   1719:        decl    r0                      # --cp
                   1720:        jbr     0f                      # just like Fortran...
                   1721: 1:                                     # do {
                   1722:        movzbl  (r0),r3 
                   1723:        bitb    r4,(r1)[r3]             #       if (table[*cp] & mask)
                   1724:        jneq    2f                      #               break;
                   1725: 0:     aoblss  r2,r0,1b                # } while (++cp < end);
                   1726: 2:
                   1727:        subl3   r0,r2,r0; ret           # return (end - cp);
                   1728: 
                   1729: /*
                   1730:  * skpc(mask, size, cp)
                   1731:  */
                   1732: ENTRY(skpc, 0)
                   1733:        movl    12(fp),r0               # r0 = cp
                   1734:        addl3   8(fp),r0,r1             # r1 = end = &cp[size];
                   1735:        movb    7(fp),r2                # r2 = mask
                   1736:        decl    r0                      # --cp;
                   1737:        jbr     0f
                   1738: 1:                                     # do
                   1739:        cmpb    (r0),r2                 #       if (*cp != mask)
                   1740:        jneq    2f                      #               break;
                   1741: 0:     aoblss  r1,r0,1b                # while (++cp < end);
                   1742: 2:
                   1743:        subl3   r0,r1,r0; ret           # return (end - cp);
                   1744: 
                   1745: /*
                   1746:  * locc(mask, size, cp)
                   1747:  */
                   1748: ENTRY(locc, 0)
                   1749:        movl    12(fp),r0               # r0 = cp
                   1750:        addl3   8(fp),r0,r1             # r1 = end = &cp[size]
                   1751:        movb    7(fp),r2                # r2 = mask
                   1752:        decl    r0                      # --cp;
                   1753:        jbr     0f
                   1754: 1:                                     # do
                   1755:        cmpb    (r0),r2                 #       if (*cp == mask)
                   1756:        jeql    2f                      #               break;
                   1757: 0:     aoblss  r1,r0,1b                # while (++cp < end);
                   1758: 2:
                   1759:        subl3   r0,r1,r0; ret           # return (end - cp);
                   1760: 
                   1761: #ifdef ALIGN
                   1762: #include "../tahoealign/align.h"
                   1763: 
                   1764:        .globl  _alignment
                   1765: /*
                   1766:  * There's an intimate relationship between this piece of code
                   1767:  * and the alignment emulation code (especially the layout
                   1768:  * of local variables in alignment.c! Don't change unless
                   1769:  * you update both this, alignment.h and alignment.c !!
                   1770:  */
                   1771: non_aligned:
                   1772:        orb2    $EMULATEALIGN,_u+U_EOSYS
                   1773:        incl    _cnt+V_TRAP
                   1774:        incl    _cnt+V_ALIGN            # count emulated alignment traps
                   1775:        moval   4(sp),_user_psl
                   1776:        SAVE_FPSTAT(4)                  # Also zeroes out ret_exception !
                   1777:        pushl   $0                      # ret_addr
                   1778:        pushl   $0                      # ret_code
                   1779:        mfpr    $USP,-(sp)              # user sp
                   1780:        callf   $4,_alignment           # call w/o parms so regs may be modified
                   1781:        /*
                   1782:         * We return here after a successful emulation or an exception.
                   1783:         * The registers have been restored and we must not alter them
                   1784:         * before returning to the user.
                   1785:         */
                   1786: 2:     mtpr    (sp)+,$USP              # restore user sp
                   1787:        tstl    8(sp)                   # Any exception ?
                   1788:        bneq    got_excp                # Yes, reflect it back to user.
                   1789:        moval   8(sp),sp                # pop 2 zeroes pushed above
                   1790:        REST_FPSTAT
                   1791:        xorb2   $EMULATEALIGN,_u+U_EOSYS
                   1792: 
                   1793:        bitl    $PSL_T,4(sp)            # check for trace bit set
                   1794:        beql    9f
                   1795:        CHECK_SFE(4)
                   1796:        pushl $0
                   1797:        SAVE_FPSTAT(8)
                   1798:        TRAP(TRCTRAP)
                   1799: 9:     rei
                   1800: 
                   1801: got_excp:                              # decode exception
                   1802:        casel   8(sp),$ILL_ADDRMOD,$ALIGNMENT
                   1803:        .align  1
                   1804: L1:
                   1805:        .word   ill_addrmod-L1
                   1806:        .word   ill_access-L1
                   1807:        .word   ill_oprnd-L1
                   1808:        .word   arithmetic-L1
                   1809:        .word   alignment-L1
                   1810:        brw     alignment               # default - shouldn't come here at all !
                   1811: 
                   1812: ill_addrmod:                           # No other parameters. Set up stack as
                   1813:        moval   8(sp),sp                # the HW would do it in a real case.
                   1814:        REST_FPSTAT
                   1815:        jbr     _Xresadflt
                   1816: ill_oprnd:
                   1817:        moval   8(sp),sp
                   1818:        REST_FPSTAT
                   1819:        jbr     _Xresopflt
                   1820: alignment:
                   1821:        moval   8(sp),sp
                   1822:        REST_FPSTAT
                   1823:        jbr     align_excp      # NB: going to _Xalignflt would cause loop
                   1824: ill_access:
                   1825:        /*
                   1826:         * Must restore accumulator w/o modifying sp and w/o using
                   1827:         * registers.  Solution: copy things needed by REST_FPSTAT.
                   1828:         */
                   1829:        pushl   20(sp)                  # The flags longword
                   1830:        pushl   20(sp)                  # acc_low
                   1831:        pushl   20(sp)                  # acc_high
                   1832:        pushl   20(sp)                  # ret_exception ignored by REST_FPSTAT 
                   1833:        REST_FPSTAT                     # Back where we were with the sp !
                   1834:        movl    (sp),16(sp)             # code for illegal access
                   1835:        movl    4(sp),20(sp)            # original virtual address
                   1836:        moval   16(sp),sp               # Just like the HW would set it up
                   1837:        jbr     _Xprotflt
                   1838: arithmetic:                            # same trickery as above
                   1839:        pushl   20(sp)                  # The flags longword
                   1840:        pushl   20(sp)                  # acc_low
                   1841:        pushl   20(sp)                  # acc_high
                   1842:        pushl   20(sp)                  # ret_exception ignored by REST_FPSTAT 
                   1843:        REST_FPSTAT                     # Back where we were with the sp !
                   1844:        movl    (sp),20(sp)             # code for arithmetic exception
                   1845:        moval   20(sp),sp               # Just like the HW would set it up
                   1846:        jbr     _Xarithtrap
                   1847: #endif

unix.superglobalmegacorp.com

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