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