1/* locore.s 1.8 86/07/16 */ 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 andl2 $~PG_PROT,_rsstkmap 175 orl2 $PG_KW,_rsstkmap # Make dump stack r/w 176 tstl dumpflag # dump only once! 177 bneq 1f 178 movl $1,dumpflag 179 mtpr $0,$TBIA 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-r2 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 * (such as in hardclock) understand this, using the 204 * REGSPC definition (and FPSPC defined below). 205 * Finally, many routines, including those expanded 206 * inline depend on this! Should probably save all 207 * live C compiler temp registers to eliminate potentially 208 * grievous problems caused by incorrect register save masks. 209 */ 210#define REGSPC (3*4) 211#define PUSHR pushl r0; pushl r1; pushl r2; 212#define POPR movl (sp)+,r2; movl (sp)+,r1; movl (sp)+,r0; 213 214/* 215 * Floating point state is saved across faults and 216 * interrupts. The state occupies 4 longwords on 217 * the stack: 218 * precision indicator (single = 0/double = 1) 219 * double representation of accumulator 220 * save accumulator status flag (pcb_savacc) 221 */ 222#define FPSPC (4*4) 223 224#define SAVE_FPSTAT(_delta) \ 225 bitl $PSL_DBL,_delta(sp); \ 226 beql 1f; \ 227 pushl $1; \ 228 pushd; \ 229 jmp 2f; \ 2301: pushl $0; \ 231 pushl $0; \ 232 stf -(sp); \ 2332: tstl _u+PCB_SAVACC; \ 234 bneq 3f; \ 235 moval 0(sp),_u+PCB_SAVACC; \ 236 orl2 $2,8(sp);\ 2373: pushl $0; 238 239#define REST_FPSTAT \ 240 tstl (sp)+; \ 241 bitl $2,8(sp);\ 242 beql 1f;\ 243 movl $0,_u+PCB_SAVACC; \ 2441: bitl $1,8(sp); \ 245 beql 2f; \ 246 ldd (sp); \ 247 jmp 3f; \ 2482: ldf (sp); \ 2493: moval 12(sp),sp; 250 251#define REST_ACC \ 252 tstl _u+PCB_SAVACC; \ 253 beql 2f; \ 254 movl _u+PCB_SAVACC,r1; \ 255 andl3 $(EXPMASK|SIGNBIT),(r1),-(sp); \ 256 cmpl $0x80000000,(sp)+; \ 257 bneq 3f; \ 258 clrl (r1); \ 2593: bitl $1,8(r1); \ 260 beql 1f; \ 261 ldd (r1); \ 262 jmp 2f; \ 2631: ldf (r1); \ 2642: ; 265 266 .data 267nofault: .space 4 # bus error non-local goto label 268 269 .text 270SCBVEC(buserr): 271 CHECK_SFE(12) 272 SAVE_FPSTAT(12) 273 incl _intrcnt+I_BUSERR # keep stats... 274 pushl r0 # must save 275 andl3 24(sp),$ERRCD,r0 # grab pushed MER value 276 cmpl r0,$APE # address parity error? 277 jneq 1f 278 halt 2791: cmpl r0,$VBE # versabus error? 280 jneq 2f 281 halt 2822: 283 movl (sp)+,r0 # restore r0 and... 284 bitl $PSL_CURMOD,4*4+3*4(sp) # check if happened in user mode? 285 jeql 3f # yes, then shift stack up for trap... 286 movl 12(sp),16(sp) # sorry, no space for which-buss... 287 movl 8(sp),12(sp) 288 movl 4(sp),8(sp) 289 movl 0(sp),4(sp) 290 movl $T_BUSERR,0(sp) # push trap type code and... 291 jbr alltraps # ...merge with all other traps 2923: # kernel mode, check to see if... 293 tstl nofault # ...doing peek/poke? 294 jeql 4f # nofault set? if so, jump to it... 295 movl nofault,4*4+2*4(sp) # ...setup for non-local goto 296 clrl nofault 297 jbr 5f 2984: 299 PUSHR 300 pushab 7*4(sp) # address of bus error parameters 301 callf $8,_buserror 302 POPR 3035: 304 REST_FPSTAT 305 movab 8(sp),sp # remove bus error parameters 306 rei 307 308SCBVEC(powfail): # We should be on interrupt stack now. 309 SAVEpwfl() # save machine state 310 moval _Xdoadump-SYSTEM,_scb+SCB_DOADUMP 311 halt 312 313SCBVEC(stray): 314 rei 315 316#include "../net/netisr.h" 317 .globl _netisr 318SCBVEC(netintr): 319 CHECK_SFE(4) 320 SAVE_FPSTAT(4); PUSHR 321#include "imp.h" 322#if NIMP > 0 323 bbc $NETISR_IMP,_netisr,1f; 324 andl2 $~(1<<NETISR_IMP),_netisr 325 callf $4,_impintr; 3261: 327#endif 328#ifdef INET 329 bbc $NETISR_IP,_netisr,1f 330 andl2 $~(1<<NETISR_IP),_netisr 331 callf $4,_ipintr 3321: 333#endif 334#ifdef NS 335 bbc $NETISR_NS,_netisr,1f 336 andl2 $~(1<<NETISR_NS),_netisr 337 callf $4,_nsintr 3381: 339#endif 340 bbc $NETISR_RAW,_netisr,1f 341 andl2 $~(1<<NETISR_RAW),_netisr 342 callf $4,_rawintr 3431: 344 incl _cnt+V_SOFT 345 POPR; REST_FPSTAT 346 rei 347 348SCBVEC(cnrint): 349 CHECK_SFE(4) 350 SAVE_FPSTAT(4); PUSHR; 351 pushl $CPCONS; callf $8,_cnrint; 352 incl _intrcnt+I_CNR 353 incl _cnt+V_INTR 354 POPR; REST_FPSTAT; 355 rei 356SCBVEC(cnxint): 357 CHECK_SFE(4) 358 SAVE_FPSTAT(4); PUSHR; 359 pushl $CPCONS; callf $8,_cnxint; 360 incl _intrcnt+I_CNX 361 incl _cnt+V_INTR 362 POPR; REST_FPSTAT; 363 rei 364SCBVEC(rmtrint): 365 CHECK_SFE(4) 366 SAVE_FPSTAT(4); PUSHR; 367 pushl $CPREMOT; callf $8,_cnrint; 368 incl _intrcnt+I_RMTR 369 incl _cnt+V_INTR 370 POPR; REST_FPSTAT; 371 rei 372SCBVEC(rmtxint): 373 CHECK_SFE(4) 374 SAVE_FPSTAT(4); PUSHR; 375 pushl $CPREMOT; callf $8,_cnxint; 376 incl _intrcnt+I_RMTX 377 incl _cnt+V_INTR 378 POPR; REST_FPSTAT; 379 rei 380 381#define PUSHPCPSL pushl 4+FPSPC+REGSPC(sp); pushl 4+FPSPC+REGSPC(sp); 382 383SCBVEC(hardclock): 384 tstl _clk_enable 385 bneq 1f 386 rei 3871: 388 CHECK_SFE(4) 389 SAVE_FPSTAT(4); PUSHR 390 PUSHPCPSL # push pc and psl 391 callf $12,_hardclock # hardclock(pc,psl) 392 incl _intrcnt+I_CLOCK 393 incl _cnt+V_INTR ## temp so not to break vmstat -= HZ 394 POPR; REST_FPSTAT 395 rei 396SCBVEC(softclock): 397 CHECK_SFE(4) 398 SAVE_FPSTAT(4); PUSHR; 399 PUSHPCPSL # push pc and psl 400 callf $12,_softclock # softclock(pc,psl) 401 incl _cnt+V_SOFT 402 POPR; REST_FPSTAT 403 rei 404 405/* 406 * Stray VERSAbus interrupt catch routines 407 */ 408 .data 409#define PJ .align 2; callf $4,_Xvstray 410 .globl _catcher 411_catcher: 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 PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 421 PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 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 425 .align 2 426 .globl _cold 427_cold: .long 0x3 428 429 .text 430SCBVEC(vstray): 431 .word 0 432 bbc $0,_cold,2f # system running? 433 bbc $1,_cold,1f # doing autoconfig? 434 jbr 3f # random interrupt, ignore 4351: 436 mfpr $IPL,r12 # ...setup br and cvec 437 subl3 $_catcher+7,-8(fp),r11; shar $3,r11,r11 438 addl2 $SCB_DEVBASE,r11 439 jbr 3f 4402: 441 PUSHR 442 subl3 $_catcher+7,-8(fp),r0; shar $3,r0,r0 443 addl3 $SCB_DEVBASE,r0,-(sp); 444 mfpr $IPL,-(sp) 445 PRINTF(2, "stray intr ipl %x vec %x\n") 446 POPR 4473: moval 0f,-8(fp); ret # pop callf frame... 4480: rei # ...and return 449 450/* 451 * Trap and fault vector routines 452 */ 453#define TRAP(a) pushl $T_/**/a; jbr alltraps 454 455/* 456 * Ast delivery (profiling and/or reschedule) 457 */ 458/* 459 * When we want to reschedule we will force a 460 * memory fault by setting the ASTBIT of P0LR. 461 * Then, on memory fault if the ASTBIT of the 462 * p0lr is set we will clear it and TRAP(astflt). 463 */ 464#define ASTBIT 0x00100000 465#define P0MASK 0xc0000000 466 467SCBVEC(kspnotval): 468 CHECK_SFE(4) 469 pushl $0; 470 SAVE_FPSTAT(8) 471 TRAP(KSPNOTVAL) 472SCBVEC(privinflt): 473 CHECK_SFE(4) 474 pushl $0; 475 SAVE_FPSTAT(8) 476 TRAP(PRIVINFLT) 477SCBVEC(resopflt): 478 CHECK_SFE(4) 479 pushl $0; 480 SAVE_FPSTAT(8) 481 TRAP(RESOPFLT) 482SCBVEC(resadflt): 483 CHECK_SFE(4) 484 pushl $0; 485 SAVE_FPSTAT(8) 486 TRAP(RESADFLT) 487SCBVEC(bptflt): 488 CHECK_SFE(4) 489 pushl $0; 490 SAVE_FPSTAT(8) 491 TRAP(BPTFLT) 492SCBVEC(tracep): 493 CHECK_SFE(4) 494 pushl $0; 495 SAVE_FPSTAT(8) 496 TRAP(TRCTRAP) 497SCBVEC(alignflt): 498 CHECK_SFE(4) 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 CHECK_SFE(16) 519 SAVE_FPSTAT(16) 520 callf $4,_fpemulate 521 REST_FPSTAT 522 moval 8(sp),sp # Pop operand 523 tstl (sp) # Stack= PSL, PC, return_code 524 jneq _Xarithtrap # If not OK, emulate F.P. exception 525 movab 4(sp),sp # Else remove return_code and 526 rei 527 528SCBVEC(sfexcep): 529 CHECK_SFE(4) 530 pushl $0 531 SAVE_FPSTAT(8) 532 TRAP(ASTFLT) 533 534SCBVEC(transflt): 535 CHECK_SFE(12) 536 bitl $1,(sp)+ 537 bneq tableflt 538pageflt: 539 SAVE_FPSTAT(8) 540 TRAP(PAGEFLT) 541tableflt: 542 SAVE_FPSTAT(8) 543 TRAP(TABLEFLT) 544 545#define REST_STACK movab 4(sp), sp; REST_FPSTAT; movab 4(sp), sp 546 547alltraps: 548 mfpr $USP,-(sp); 549 callf $4,_trap; 550 mtpr (sp)+,$USP 551 incl _cnt+V_TRAP 552 REST_STACK # pop type, code, and fp stuff 553 mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT) 554 rei 555 556SCBVEC(syscall): 557 CHECK_SFE(8) 558 SAVE_FPSTAT(8) 559 pushl $T_SYSCALL 560 mfpr $USP,-(sp); 561 callf $4,_syscall; 562 mtpr (sp)+,$USP 563 incl _cnt+V_SYSCALL 564 REST_STACK # pop type, code, and fp stuff 565 mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT) 566 rei 567 568/* 569 * System page table. 570 * 571 * Mbmap and Usrptmap are enlarged by CLSIZE entries 572 * as they are managed by resource maps starting with index 1 or CLSIZE. 573 */ 574#define vaddr(x) ((((x)-_Sysmap)/4)*NBPG+SYSTEM) 575#define SYSMAP(mname, vname, npte) \ 576_/**/mname: .globl _/**/mname; \ 577 .space (npte)*4; \ 578 .globl _/**/vname; \ 579 .set _/**/vname,vaddr(_/**/mname) 580 581 .data 582 .align 2 583 SYSMAP(Sysmap ,Sysbase ,SYSPTSIZE ) 584 SYSMAP(Forkmap ,forkutl ,UPAGES ) 585 SYSMAP(Xswapmap ,xswaputl ,UPAGES ) 586 SYSMAP(Xswap2map,xswap2utl ,UPAGES ) 587 SYSMAP(Swapmap ,swaputl ,UPAGES ) 588 SYSMAP(Pushmap ,pushutl ,UPAGES ) 589 SYSMAP(Vfmap ,vfutl ,UPAGES ) 590 SYSMAP(CMAP1 ,CADDR1 ,1 ) 591 SYSMAP(CMAP2 ,CADDR2 ,1 ) 592 SYSMAP(mmap ,vmmap ,1 ) 593 SYSMAP(alignmap ,alignutl ,1 ) /* XXX */ 594 SYSMAP(msgbufmap,msgbuf ,MSGBUFPTECNT ) 595 SYSMAP(Mbmap ,mbutl ,NMBCLUSTERS*CLSIZE+CLSIZE ) 596 SYSMAP(camap ,cabase ,(4*32+4)*CLSIZE ) 597#ifdef GPROF 598 SYSMAP(profmap ,profbase ,600*CLSIZE ) 599#endif 600 SYSMAP(ecamap ,calimit ,0 ) 601 SYSMAP(VMEMbeg ,vmembeg ,0 ) 602 SYSMAP(VMEMmap ,vmem ,VBIOSIZE ) 603 SYSMAP(VMEMmap1 ,vmem1 ,VBMEMSIZE ) 604 SYSMAP(VMEMend ,vmemend ,0 ) 605 SYSMAP(VBmap ,vbbase ,VBPTSIZE ) 606 SYSMAP(eVBmap ,vbend ,0 ) 607 SYSMAP(Usrptmap ,usrpt ,USRPTSIZE+CLSIZE ) 608eSysmap: 609 .globl _Syssize 610 .set _Syssize,(eSysmap-_Sysmap)/4 611 612 .text 613/* 614 * Initialization 615 * 616 * IPL 0x1f; MME 0; scbb, pcbb, sbr, slr, isp, ksp not set 617 */ 618 .align 2 619 .globl start 620start: 621 .word 0 622/* set system control block base and system page table params */ 623 mtpr $_scb-SYSTEM,$SCBB 624 mtpr $_Sysmap-SYSTEM,$SBR 625 mtpr $_Syssize,$SLR 626/* double map the kernel into the virtual user addresses of phys mem */ 627 mtpr $_Sysmap,$P0BR 628 mtpr $_Syssize,$P0LR 629 mtpr $_Sysmap,$P1BR # against Murphy 630 mtpr $_Syssize,$P1LR 631/* set ISP */ 632 movl $_intstack-SYSTEM+NISP*NBPG,sp # still physical 633 mtpr $_intstack+NISP*NBPG,$ISP 634/* count up memory */ 635 clrl r7 6361: pushl $1; pushl r7; callf $12,_badaddr; tstl r0; bneq 9f 637 ACBL($MAXMEM*1024-1,$64*1024,r7,1b) 6389: 639/* clear memory from kernel bss and pages for proc 0 u. and page table */ 640 movab _edata,r6 641 movab _end,r5 642 andl2 $~SYSTEM,r6 643 andl2 $~SYSTEM,r5 644 addl2 $(UPAGES*NBPG)+NBPG+NBPG,r5 6451: clrl (r6); ACBL(r5,$4,r6,1b) 646/* trap(), syscall(), and fpemulate() save r0-r12 in the entry mask */ 647 orw2 $0x01fff,_trap 648 orw2 $0x01fff,_syscall 649 orw2 $0x01fff,_fpemulate 650 orw2 $0x01ffc,_panic # for debugging (no r0|r1) 651 callf $4,_fixctlrmask # setup for autoconfig 652/* initialize system page table: scb and int stack writeable */ 653 clrl r2 654 movab eintstack,r1 655 andl2 $~SYSTEM,r1 656 shrl $PGSHIFT,r1,r1 # r1-page number of eintstack 657/* make processor storage read/only */ 658 orl3 $PG_V|PG_KR,r2,_Sysmap[r2]; incl r2; 659 orl3 $PG_V|PG_KR,r2,_Sysmap[r2]; incl r2; 660/* other parts of the system are read/write for kernel */ 6611: orl3 $PG_V|PG_KW,r2,_Sysmap[r2]; # data:kernel write+phys=virtual 662 aoblss r1,r2,1b 663/* make rsstk read-only as red zone for interrupt stack */ 664 andl2 $~PG_PROT,_rsstkmap 665 orl2 $PG_V|PG_KR,_rsstkmap 666/* make kernel text space read-only */ 667 movab _etext+NBPG-1,r1 668 andl2 $~SYSTEM,r1 669 shrl $PGSHIFT,r1,r1 6701: orl3 $PG_V|PG_KR,r2,_Sysmap[r2] 671 aoblss r1,r2,1b 672/* make kernel data, bss, read-write */ 673 movab _end+NBPG-1,r1 674 andl2 $~SYSTEM,r1 675 shrl $PGSHIFT,r1,r1 6761: orl3 $PG_V|PG_KW,r2,_Sysmap[r2] 677 aoblss r1,r2,1b 678/* go to mapped mode, have to change both pc and sp to system addresses */ 679 mtpr $1,$TBIA 680 mtpr $1,$PADC # needed by HW parity&ECC logic 681 mtpr $1,$PACC # just in case 682 mtpr $1,$MME 683 movab SYSTEM(sp),sp 684 jmp *$0f 6850: 686/* disable any interrupts */ 687 movl $0,_intenable 688/* init mem sizes */ 689 shrl $PGSHIFT,r7,_maxmem 690 movl _maxmem,_physmem 691 movl _maxmem,_freemem 692/* setup context for proc[0] == scheduler */ 693 movab _end-SYSTEM+NBPG-1,r6 694 andl2 $~(NBPG-1),r6 # make page boundary 695/* setup page table for proc[0] */ 696 shrl $PGSHIFT,r6,r3 # r3 = btoc(r6) 697 orl3 $PG_V|PG_KW,r3,_Usrptmap # init first upt entry 698 incl r3 # r3 - next page 699 movab _usrpt,r0 # r0 - first user page 700 mtpr r0,$TBIS 701/* init p0br, p0lr */ 702 mtpr r0,$P0BR # no p0 for proc[0] 703 mtpr $0,$P0LR 704 mtpr r0,$P1BR # no p1 either 705 mtpr $0,$P1LR 706/* init p2br, p2lr */ 707 movab NBPG(r0),r0 708 movl $PPAGES-UPAGES,r1 709 mtpr r1,$P2LR 710 moval -4*PPAGES(r0),r2 711 mtpr r2,$P2BR 712/* setup mapping for UPAGES of _u */ 713 clrl r2 714 movl $SYSTEM,r1 715 addl2 $UPAGES,r3 716 jbr 2f 7171: decl r3 718 moval -NBPG(r1),r1 # r1 = virtual add of next (downward) _u page 719 subl2 $4,r0 # r0 = pte address 720 orl3 $PG_V|PG_URKW,r3,(r0) 721 mtpr r1,$TBIS 7222: aobleq $UPAGES,r2,1b 723/* initialize (slightly) the pcb */ 724 movab UPAGES*NBPG(r1),PCB_KSP(r1) # KSP starts at end of _u 725 movl r1,PCB_USP(r1) # USP starts just below _u 726 mfpr $P0BR,PCB_P0BR(r1) 727 mfpr $P0LR,PCB_P0LR(r1) 728 mfpr $P1BR,PCB_P1BR(r1) 729 mfpr $P1LR,PCB_P1LR(r1) 730 mfpr $P2BR,PCB_P2BR(r1) 731 mfpr $P2LR,PCB_P2LR(r1) 732 movl $CLSIZE,PCB_SZPT(r1) # init u.u_pcb.pcb_szpt 733 movl r11,PCB_R11(r1) # r11 obtained from CP on boot 734 movab 1f,PCB_PC(r1) # initial pc 735 clrl PCB_PSL(r1) # kernel mode, ipl=0 736 shll $PGSHIFT,r3,r3 737 mtpr r3,$PCBB # first pcbb (physical) 738/* go to kernel mode */ 739 ldpctx 740 rei # Actually next instruction: 741/* put signal trampoline code in u. area */ 7421: movab sigcode,r0 743 movab _u+PCB_SIGC,r1 744 movl $19,r2 745 movblk 746/* save boot device in global _bootdev */ 747 movl r10,_bootdev 748/* save reboot flags in global _boothowto */ 749 movl r11,_boothowto 750/* calculate firstaddr, and call main() */ 751 movab _end-SYSTEM+NBPG-1,r0 752 shrl $PGSHIFT,r0,-(sp) 753 addl2 $UPAGES+1,(sp) # first physical unused page 754 callf $8,_main 755/* proc[1] == /etc/init now running here in kernel mode; run icode */ 756 pushl $PSL_CURMOD # User mode PSL 757 pushl $0 # PC = 0 (virtual now) 758 rei 759 760/* 761 * Mask for saving/restoring registers on entry to 762 * a user signal handler. Space for the registers 763 * is reserved in sendsig, so beware if you want 764 * to change the mask. 765 */ 766#define SIGREGS (R0|R1|R2|R3|R4|R5) 767 .align 2 768 .globl sigcode 769sigcode: 770 storer $SIGREGS,16(sp) # save volatile registers 771 calls $4*3+4,*12(sp) # params pushed by sendsig for handler 772 loadr $SIGREGS,4(sp) # restore volatile registers 773 movab 24(sp),fp # use parameter list set up in sendsig 774 kcall $SYS_sigreturn # cleanup mask and onsigstack 775 halt # sigreturn does not return! 776 777 .globl _icode 778 .globl _initflags 779 .globl _szicode 780/* 781 * Icode is copied out to process 1 to exec /etc/init. 782 * If the exec fails, process 1 exits. 783 */ 784 .align 2 785_icode: 786 pushab b`argv-l0(pc) 787l0: pushab b`init-l1(pc) 788l1: pushl $2 789 movab (sp),fp 790 kcall $SYS_execv 791 kcall $SYS_exit 792 793init: .asciz "/etc/init" 794 .align 2 795_initflags: 796 .long 0 797argv: .long init+5-_icode 798 .long _initflags-_icode 799 .long 0 800_szicode: 801 .long _szicode-_icode 802 803/* 804 * Primitives 805 */ 806 807/* 808 * badaddr(addr, len) 809 * see if access addr with a len type instruction causes a machine check 810 * len is length of access (1=byte, 2=short, 4=long) 811 * r0 = 0 means good(exists); r0 =1 means does not exist. 812 */ 813ENTRY(badaddr, R3|R4) 814 mfpr $IPL,r1 815 mtpr $HIGH,$IPL 816 movl _scb+SCB_BUSERR,r2 817 movl 4(fp),r3 818 movl 8(fp),r4 819 movab 9f,_scb+SCB_BUSERR 820 bbc $0,r4,1f; tstb (r3) 8211: bbc $1,r4,1f; tstw (r3) 8221: bbc $2,r4,1f; tstl (r3) 8231: clrl r0 8242: movl r2,_scb+SCB_BUSERR 825 mtpr r1,$IPL 826 ret 827 828 .align 2 8299: # catch buss error (if it comes) 830 andl3 4(sp),$ERRCD,r0 831 cmpl r0,$APE 832 jneq 1f 833 halt # address parity error 8341: cmpl r0,$VBE 835 jneq 1f 836 halt # Versabus error 8371: 838 movl $1,r0 # Anything else = bad address 839 movab 8(sp),sp # discard buss error trash 840 movab 2b,(sp) # new program counter on stack. 841 rei 842 843/* 844 * badcyaddr(addr) 845 * see if access tape master controller addr causes a bus error 846 * r0 = 0: no error; r0 = 1: timeout error. 847 */ 848ENTRY(badcyaddr, 0) 849 mfpr $IPL,r1 850 mtpr $HIGH,$IPL 851 clrl r2 852 movab 2f,nofault 853 movob $-1, *4(fp) 8541: aobleq $1000, r2, 1b 855 clrl nofault # made it w/o bus error 856 clrl r0 857 jbr 3f 8582: movl $1,r0 8593: mtpr r1,$IPL 860 ret 861 862/* 863 * peek(addr) 864 * fetch word and catch any bus error 865 */ 866ENTRY(peek, 0) 867 mfpr $IPL,r1 868 mtpr $0x18,$IPL # not reentrant 869 movl 4(fp),r2 870 movab 1f,nofault 871 movw (r2),r0 872 clrl nofault 873 andl2 $0xffff,r0 874 jbr 2f 8751: movl $-1,r0 # bus error 8762: mtpr r1,$IPL 877 ret 878 879/* 880 * poke(addr, val) 881 * write word and catch any bus error 882 */ 883ENTRY(poke, R3) 884 mfpr $IPL,r1 885 mtpr $0x18,$IPL # not reentrant 886 movl 4(fp),r2 887 movl 8(fp),r3 888 clrl r0 889 movab 1f,nofault 890 movw r3,(r2) 891 clrl nofault 892 jbr 2f 8931: movl $-1,r0 # bus error 8942: mtpr r1,$IPL 895 ret 896 897/* 898 * Copy a potentially overlapping block of memory. 899 * 900 * ovbcopy(src, dst, count) 901 * caddr_t src, dst; unsigned count; 902 */ 903ENTRY(ovbcopy, R3|R4) 904 movl 4(fp),r0 905 movl 8(fp),r1 906 movl 12(fp),r2 907 cmpl r0,r1 908 bgtru 1f # normal forward case 909 beql 2f # equal, nothing to do 910 addl2 r2,r0 # may be overlapping 911 cmpl r0,r1 912 bgtru 3f 913 subl2 r2,r0 # normal forward case 9141: 915 movblk 9162: 917 ret 9183: 919 addl2 r2,r1 # overlapping, must do backwards 920 subl3 r0,r1,r3 921 movl r2,r4 922 jbr 5f 9234: 924 subl2 r3,r0 925 subl2 r3,r1 926 movl r3,r2 927 movblk 928 subl2 r3,r0 929 subl2 r3,r1 930 subl2 r3,r4 9315: 932 cmpl r4,r3 933 jgtr 4b 934 movl r4,r2 935 subl2 r2,r0 936 subl2 r2,r1 937 movblk 938 ret 939 940/* 941 * Copy a null terminated string from the user address space into 942 * the kernel address space. 943 * 944 * copyinstr(fromaddr, toaddr, maxlength, &lencopied) 945 */ 946ENTRY(copyinstr, R3|R4|R5) 947 movl 12(fp),r5 # r5 = max length 948 jlss 8f 949 movl 4(fp),r0 # r0 = user address 950 movl r0,r3 # r3 = copy of src for null byte test 951 andl3 $(NBPG*CLSIZE-1),r0,r2 # r2 = bytes on first page 952 subl3 r2,$(NBPG*CLSIZE),r2 953 movl 8(fp),r1 # r1 = kernel address 9541: 955 cmpl r5,r2 # r2 = min(bytes on page, length left); 956 jgeq 2f 957 movl r5,r2 9582: 959 prober $1,(r0),r2 # bytes accessible? 960 jeql 8f 961 subl2 r2,r5 # update bytes left count 962 addl2 r2,r3 # calculate src+count 963 movs3 # copy in next piece 964 subl3 r0,r3,r2 # null byte found? 965 jneq 3f 966 movl $(NBPG*CLSIZE),r2 # check next page 967 tstl r5 # run out of space? 968 jneq 1b 969 movl $ENOENT,r0 # set error code and return 970 jbr 9f 9713: 972 tstl 16(fp) # return length? 973 beql 4f 974 subl3 r5,12(fp),r5 # actual len = maxlen - unused pages 975 subl2 r2,r5 # - unused on this page 976 addl3 $1,r5,*16(fp) # + the null byte 9774: 978 clrl r0 979 ret 9808: 981 movl $EFAULT,r0 9829: 983 tstl 16(fp) 984 beql 1f 985 subl3 r5,12(fp),*16(fp) 9861: 987 ret 988 989/* 990 * Copy a null terminated string from the kernel 991 * address space to the user address space. 992 * 993 * copyoutstr(fromaddr, toaddr, maxlength, &lencopied) 994 */ 995ENTRY(copyoutstr, R3|R4|R5) 996 movl 12(fp),r5 # r5 = max length 997 jlss 8b 998 movl 4(fp),r0 # r0 = kernel address 999 movl r0,r3 # r3 = copy of src for null byte test 1000 movl 8(fp),r1 # r1 = user address 1001 andl3 $(NBPG*CLSIZE-1),r1,r2 # r2 = bytes on first page 1002 subl3 r2,$(NBPG*CLSIZE),r2 10031: 1004 cmpl r5,r2 # r2 = min(bytes on page, length left); 1005 jgeq 2f 1006 movl r5,r2 10072: 1008 probew $1,(r1),r2 # bytes accessible? 1009 jeql 8b 1010 subl2 r2,r5 # update bytes left count 1011 addl2 r2,r3 # calculate src+count 1012#ifdef notdef 1013 movs3 # copy out next piece 1014#else 1015 tstl r2 1016 beql 6f 10174: 1018 movb (r0),(r1) 1019 beql 5f 1020 incl r0 1021 incl r1 1022 decl r2 1023 bneq 4b 1024 jbr 6f 10255: 1026 incl r1 1027 decl r2 10286: 1029#endif 1030 subl3 r0,r3,r2 # null byte found? 1031 jneq 3b 1032 movl $(NBPG*CLSIZE),r2 # check next page 1033 tstl r5 # run out of space? 1034 jneq 1b 1035 movl $ENOENT,r0 # set error code and return 1036 jbr 9b 1037 1038/* 1039 * Copy a null terminated string from one point to another in 1040 * the kernel address space. 1041 * 1042 * copystr(fromaddr, toaddr, maxlength, &lencopied) 1043 */ 1044ENTRY(copystr, R3|R4|R5) 1045 movl 12(fp),r5 # r5 = max length 1046 jlss 8b 1047 movl 4(fp),r0 # r0 = src address 1048 movl r0,r3 # r3 = copy of src for null byte test 1049 movl 8(fp),r1 # r1 = dest address 10501: 1051 movzwl $65535,r2 # r2 = bytes in first chunk 1052 cmpl r5,r2 # r2 = min(bytes in chunk, length left); 1053 jgeq 2f 1054 movl r5,r2 10552: 1056 subl2 r2,r5 # update bytes left count 1057 addl2 r2,r3 # calculate src+count 1058 movs3 # copy next piece 1059 subl3 r0,r3,r2 # null byte found? 1060 jneq 3b 1061 tstl r5 # run out of space? 1062 jneq 1b 1063 movl $ENOENT,r0 # set error code and return 1064 jbr 9b 1065 1066/* 1067 * Copy a block of data from the user address space into 1068 * the kernel address space. 1069 * 1070 * copyin(fromaddr, toaddr, count) 1071 */ 1072ENTRY(copyin, 0) 1073 movl 12(fp),r0 # copy length 1074 blss 9f 1075 movl 4(fp),r1 # copy user address 1076 cmpl $(CLSIZE*NBPG),r0 # probing one page or less ? 1077 bgeq 2f # yes 10781: 1079 prober $1,(r1),$(CLSIZE*NBPG) # bytes accessible ? 1080 beql 9f # no 1081 addl2 $(CLSIZE*NBPG),r1 # incr user address ptr 1082 _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r0,1b) # reduce count and loop 10832: 1084 prober $1,(r1),r0 # bytes accessible ? 1085 beql 9f # no 1086 MOVC3(4(fp),8(fp),12(fp)) 1087 clrl r0 1088 ret 10899: 1090 movl $EFAULT,r0 1091 ret 1092 1093/* 1094 * Copy a block of data from the kernel 1095 * address space to the user address space. 1096 * 1097 * copyout(fromaddr, toaddr, count) 1098 */ 1099ENTRY(copyout, 0) 1100 movl 12(fp),r0 # get count 1101 blss 9b 1102 movl 8(fp),r1 # get user address 1103 cmpl $(CLSIZE*NBPG),r0 # can do in one probew? 1104 bgeq 2f # yes 11051: 1106 probew $1,(r1),$(CLSIZE*NBPG) # bytes accessible? 1107 beql 9b # no 1108 addl2 $(CLSIZE*NBPG),r1 # increment user address 1109 _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r0,1b) # reduce count and loop 11102: 1111 probew $1,(r1),r0 # bytes accessible? 1112 beql 9b # no 1113 MOVC3(4(fp),8(fp),12(fp)) 1114 clrl r0 1115 ret 1116 1117/* 1118 * non-local goto's 1119 */ 1120#ifdef notdef 1121ENTRY(setjmp, 0) 1122 movl 4(fp),r0 1123 movl (fp),(r0); addl2 $4,r0 # save fp 1124 movl -8(fp),(r0) # save pc 1125 clrl r0 1126 ret 1127#endif 1128 1129ENTRY(longjmp, 0) 1130 movl 4(fp),r0 1131 movl (r0),newfp; addl2 $4,r0 # must save parameters in memory 1132 movl (r0),newpc # as all regs may be clobbered. 11331: 1134 cmpl fp,newfp # are we there yet? 1135 bgequ 2f # yes 1136 moval 1b,-8(fp) # redirect return pc to us! 1137 ret # pop next frame 11382: 1139 beql 3f # did we miss our frame? 1140 pushab 4f # yep ?!? 1141 callf $8,_panic 11423: 1143 movl newpc,r0 # all done, just return 1144 jmp (r0) # to setjmp `ret' 1145 1146 .data 1147newpc: .space 4 1148newfp: .space 4 11494: .asciz "longjmp" 1150 1151/* 1152 * setjmp that saves all registers as the call frame may not 1153 * be available to recover them in the usual manner by longjmp. 1154 * Called before swapping out the u. area, restored by resume() 1155 * below. 1156 */ 1157ENTRY(savectx, 0) 1158 movl 4(fp),r2 1159 storer $0x1ff8,(r2); addl2 $40,r2 # r3-r12 1160 movl (fp),(r2); addl2 $4,r2 # fp 1161 movab 8(fp),(r2); addl2 $4,r2 # sp 1162 movl -8(fp),(r2) # pc 1163 clrl r0 1164 ret 1165 1166 .globl _whichqs 1167 .globl _qs 1168 .globl _cnt 1169 1170 .globl _noproc 1171 .comm _noproc,4 1172 .globl _runrun 1173 .comm _runrun,4 1174/* 1175 * The following primitives use the fancy TAHOE instructions. 1176 * _whichqs tells which of the 32 queues _qs 1177 * have processes in them. setrq puts processes into queues, remrq 1178 * removes them from queues. The running process is on no queue, 1179 * other processes are on a queue related to p->p_pri, divided by 4 1180 * actually to shrink the 0-127 range of priorities into the 32 available 1181 * queues. 1182 */ 1183 1184/* 1185 * setrq(p), using fancy TAHOE instructions. 1186 * 1187 * Call should be made at spl8(), and p->p_stat should be SRUN 1188 */ 1189ENTRY(setrq, 0) 1190 movl 4(fp),r0 1191 tstl P_RLINK(r0) ## firewall: p->p_rlink must be 0 1192 beql set1 ## 1193 pushab set3 ## 1194 callf $8,_panic ## 1195set1: 1196 movzbl P_PRI(r0),r1 # put on queue which is p->p_pri / 4 1197 shar $2,r1,r1 1198 shal $1,r1,r2 1199 moval _qs[r2],r2 1200 insque (r0),*4(r2) # at end of queue 1201 shal r1,$1,r1 1202 orl2 r1,_whichqs # mark queue non-empty 1203 ret 1204 1205set3: .asciz "setrq" 1206 1207/* 1208 * remrq(p), using fancy TAHOE instructions 1209 * 1210 * Call should be made at spl8(). 1211 */ 1212ENTRY(remrq, 0) 1213 movl 4(fp),r0 1214 movzbl P_PRI(r0),r1 1215 shar $2,r1,r1 1216 bbs r1,_whichqs,rem1 1217 pushab rem3 # it wasn't recorded to be on its q 1218 callf $8,_panic 1219rem1: 1220 remque (r0) 1221 bneq rem2 # q not empty yet 1222 shal r1,$1,r1 1223 mcoml r1,r1 1224 andl2 r1,_whichqs # mark queue empty 1225rem2: 1226 clrl P_RLINK(r0) ## for firewall checking 1227 ret 1228 1229rem3: .asciz "remrq" 1230 1231/* 1232 * Masterpaddr is the p->p_addr of the running process on the master 1233 * processor. When a multiprocessor system, the slave processors will have 1234 * an array of slavepaddr's. 1235 */ 1236 .globl _masterpaddr 1237 .data 1238_masterpaddr: .long 0 1239 1240 .text 1241sw0: .asciz "swtch" 1242/* 1243 * swtch(), using fancy tahoe instructions 1244 */ 1245ENTRY(swtch, 0) 1246 movl (fp),fp # prepare for rei 1247 movl (sp),4(sp) # saved pc 1248 tstl (sp)+ 1249 movpsl 4(sp) 1250 movl $1,_noproc 1251 clrl _runrun 1252mtpr0: mtpr $0,$IPL # must allow interrupts here 1253sw1: ffs _whichqs,r0 # look for non-empty queue 1254 bgeq sw1a 1255 brb sw1 # this is an idle loop! 1256sw1a: mtpr $0x18,$IPL # lock out all so _whichqs==_qs 1257 bbc r0,_whichqs,mtpr0 # proc moved via lbolt interrupt 1258 shal $1,r0,r1 1259 moval _qs[r1],r1 1260 movl (r1),r2 # r2 = p = highest pri process 1261 remque *(r1) 1262 bvc sw2 # make sure something was there 1263sw1b: pushab sw0 1264 callf $8,_panic 1265sw2: bneq sw3 1266 shal r0,$1,r1 1267 mcoml r1,r1 1268 andl2 r1,_whichqs # no more procs in this queue 1269sw3: 1270 clrl _noproc 1271 tstl P_WCHAN(r2) ## firewalls 1272 bneq sw1b ## 1273 cmpb P_STAT(r2),$SRUN ## 1274 bneq sw1b ## 1275 clrl P_RLINK(r2) ## 1276 movl *P_ADDR(r2),r0 1277 movl r0,_masterpaddr 1278 shal $PGSHIFT,r0,r0 # r0 = pcbb(p) 1279#ifdef notdef 1280 mfpr $PCBB,r1 # resume of current proc is easy 1281 cmpl r0,r1 1282 beql res0 1283#endif 1284 incl _cnt+V_SWTCH 1285 brb swresume 1286 /* fall into... */ 1287 1288 .globl _prevpcb 1289_prevpcb: .long 0 1290 .text 1291/* 1292 * resume(pf) 1293 */ 1294ENTRY(resume, 0) 1295 shal $PGSHIFT,4(fp),r0 # r0 = pcbb(pf) 1296 movl (fp),fp # prepare for rei 1297 movl (sp)+,4(sp) # saved pc 1298 tstl (sp)+ 1299 movpsl 4(sp) 1300swresume: 1301 mtpr $0x18,$IPL # no interrupts, please 1302 movl _CMAP2,_u+PCB_CMAP2 # yech 1303 REST_ACC # restore original accumulator 1304 svpctx 1305 mtpr r0,$PCBB 1306 ldpctx 1307 movl _u+PCB_CMAP2,_CMAP2 # yech 1308 mtpr $_CADDR2,$TBIS 1309res0: 1310 movl _u+U_PROCP,r2 # r2 = u.u_procp 1311 tstl P_CKEY(r2) # does proc have code key? 1312 bneq 1f 1313 callf $4,_getcodekey # no, give him one 1314 movl _u+U_PROCP,r2 # r2 = u.u_procp 1315 movl r0,P_CKEY(r2) 13161: 1317 tstl P_DKEY(r2) # does proc have data key? 1318 bneq 1f 1319 callf $4,_getdatakey # no, give him one 1320 movl _u+U_PROCP,r2 # r2 = u.u_procp 1321 movl r0,P_DKEY(r2) 13221: 1323 mtpr P_CKEY(r2),$CCK # set code cache key 1324 mtpr P_DKEY(r2),$DCK # set data cache key 1325 tstl _u+PCB_SSWAP 1326 bneq res1 1327 rei 1328res1: # longjmp to saved context 1329 movl _u+PCB_SSWAP,r2 1330 clrl _u+PCB_SSWAP 1331 loadr $0x3ff8,(r2); addl2 $44,r2 # restore r3-r13 (r13=fp) 1332 movl (r2),r1; addl2 $4,r2 # fetch previous sp ... 1333 movab (sp),r0 # ... and current sp and 1334 cmpl r1,r0 # check for credibility, 1335 bgequ 1f # if further up stack ... 1336 pushab 2f; callf $8,_panic # ... panic 1337 /*NOTREACHED*/ 13381: # sp ok, complete return 1339 movl r1,sp # restore sp 1340 movl (r2),(sp) # return address 1341 movl $PSL_PRVMOD,4(sp) # kernel mode, ipl 0 1342 rei 13432: .asciz "ldctx" 1344 1345/* 1346 * {fu,su},{byte,word} 1347 */ 1348ENTRY(fuword, 0) 1349 movl 4(fp), r1 1350 prober $1,(r1),$4 # check access 1351 beql fserr # page unreadable 1352 bitl $1,r1 # check byte alignment 1353 bneq 2f # odd, do byte-word-byte 1354 bitl $2,r1 # check word alignment 1355 bneq 1f # odd, do in 2 words 1356 movl (r1),r0 # move longword 1357 ret 13581: 1359 movw (r1),r0 # move two words 1360 shal $16,r0,r0 1361 movzwl 2(r1),r1 # orw2 sign extends 1362 orl2 r1,r0 1363 ret 13642: 1365 movb (r1),r0 # move byte-word-byte 1366 shal $24,r0,r0 1367 movzwl 1(r1),r2 # orw2 sign extends 1368 shal $8,r2,r2 1369 movzbl 3(r1),r1 # orb2 sign extends 1370 orl2 r2,r1 1371 orl2 r1,r0 1372 ret 1373fserr: 1374 mnegl $1,r0 1375 ret 1376 1377ENTRY(fubyte, 0) 1378 prober $1,*4(fp),$1 1379 beql fserr 1380 movzbl *4(fp),r0 1381 ret 1382 1383ENTRY(suword, 0) 1384 movl 4(fp), r0 1385 probew $1,(r0),$4 # check access 1386 beql fserr # page unwritable 1387 bitl $1,r0 # check byte alignment 1388 bneq 1f # odd byte boundary 1389 bitl $2,r0 # check word alignment 1390 beql 2f # longword aligned 1391 movw 8(fp),(r0) # move two words 1392 movw 10(fp),2(r0) 1393 jbr 3f 13941: 1395 movb 8(fp),(r0) 1396 movb 9(fp),1(r0) 1397 movb 10(fp),2(r0) 1398 movb 11(fp),3(r0) 1399 jbr 3f 14002: 1401 movl 8(fp),(r0) 14023: 1403 clrl r0 1404 ret 1405 1406ENTRY(subyte, 0) 1407 probew $1,*4(fp),$1 1408 beql fserr 1409 movb 11(fp),*4(fp) 1410 clrl r0 1411 ret 1412 1413/* 1414 * Copy 1 relocation unit (NBPG bytes) 1415 * from user virtual address to physical address 1416 */ 1417ENTRY(copyseg, 0) 1418 orl3 $PG_V|PG_KW,8(fp),_CMAP2 1419 mtpr $_CADDR2,$TBIS # invalidate entry for copy 1420 MOVC3(4(fp),$_CADDR2,$NBPG) 1421 ret 1422 1423/* 1424 * Clear a page of memory. The page frame is specified. 1425 * 1426 * clearseg(pf); 1427 */ 1428ENTRY(clearseg, 0) 1429 orl3 $PG_V|PG_KW,4(fp),_CMAP1 # Maps to virtual addr CADDR1 1430 mtpr $_CADDR1,$TBIS 1431 movl $255,r0 # r0 = limit 1432 clrl r1 # r1 = index of cleared long 14331: 1434 clrl _CADDR1[r1] 1435 aobleq r0,r1,1b 1436 ret 1437 1438/* 1439 * Check user mode read/write access. 1440 * 1441 * useracc(addr, count, mode) 1442 * caddr_t addr; int count, mode; 1443 * mode = 0 write access 1444 * mode = 1 read access 1445 */ 1446ENTRY(useracc, 0) 1447 movl $1,r2 # r2 = 'user mode' for probew/probew 1448probes: 1449 movl 4(fp),r0 # get va 1450 movl 8(fp),r1 # count 1451 tstl 12(fp) # test for read access ? 1452 bneq userar # yes 1453 cmpl $(CLSIZE*NBPG),r1 # can we do it in one probe ? 1454 bgeq uaw2 # yes 1455uaw1: 1456 probew r2,(r0),$(CLSIZE*NBPG) 1457 beql uaerr # no access 1458 addl2 $(CLSIZE*NBPG),r0 1459 _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r1,uaw1) 1460uaw2: 1461 probew r2,(r0),r1 1462 beql uaerr 1463 movl $1,r0 1464 ret 1465userar: 1466 cmpl $(CLSIZE*NBPG),r1 1467 bgeq uar2 1468uar1: 1469 prober r2,(r0),$(CLSIZE*NBPG) 1470 beql uaerr 1471 addl2 $(CLSIZE*NBPG),r0 1472 _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r1,uar1) 1473uar2: 1474 prober r2,(r0),r1 1475 beql uaerr 1476 movl $1,r0 1477 ret 1478uaerr: 1479 clrl r0 1480 ret 1481 1482/* 1483 * Check kernel mode read/write access. 1484 * 1485 * kernacc(addr, count, mode) 1486 * caddr_t addr; int count, mode; 1487 * mode = 0 write access 1488 * mode = 1 read access 1489 */ 1490ENTRY(kernacc, 0) 1491 clrl r2 # r2 = 0 means kernel mode probe. 1492 jbr probes # Dijkstra would get gastric distress here. 1493 1494/* 1495 * addupc - increment some histogram counter 1496 * in the profiling buffer 1497 * 1498 * addupc(pc, prof, delta) 1499 * long pc; short delta; struct uprof *prof; 1500 * 1501 * struct uprof { # profile arguments 1502 * short *r_base; # buffer base 1503 * unsigned pr_size; # buffer size 1504 * unsigned pr_off; # pc offset 1505 * unsigned pr_scale; # pc scaling 1506 * } 1507 */ 1508ENTRY(addupc, 0) 1509 movl 8(fp),r2 # r2 points to structure 1510 subl3 8(r2),4(fp),r0 # r0 = PC - lowpc 1511 jlss 9f # PC < lowpc , out of range ! 1512 shrl $1,r0,r0 # the unit is words 1513 shrl $1,12(r2),r1 # ditto for scale 1514 emul r1,r0,$0,r0 1515 shrq $14,r0,r0 1516 tstl r0 # too big 1517 jneq 9f 1518 cmpl r1,4(r2) # Check buffer overflow 1519 jgequ 9f 1520 probew $1,*0(r2)[r1],$2 # counter accessible? 1521 jeql 9f 1522 shrl $1,r1,r1 # make r1 word index 1523 addw2 14(fp),*0(r2)[r1] 15249: ret 1525 1526/* 1527 * scanc(size, cp, table, mask) 1528 */ 1529ENTRY(scanc, R3|R4) 1530 movl 8(fp),r0 # r0 = cp 1531 addl3 4(fp),r0,r2 # end = &cp[size] 1532 movl 12(fp),r1 # r1 = table 1533 movb 19(fp),r4 # r4 = mask 1534 decl r0 # --cp 1535 jbr 0f # just like Fortran... 15361: # do { 1537 movzbl (r0),r3 1538 bitb r4,(r1)[r3] # if (table[*cp] & mask) 1539 jneq 2f # break; 15400: aoblss r2,r0,1b # } while (++cp < end); 15412: 1542 subl3 r0,r2,r0; ret # return (end - cp); 1543 1544/* 1545 * skpc(mask, size, cp) 1546 */ 1547ENTRY(skpc, 0) 1548 movl 12(fp),r0 # r0 = cp 1549 addl3 8(fp),r0,r1 # r1 = end = &cp[size]; 1550 movb 7(fp),r2 # r2 = mask 1551 decl r0 # --cp; 1552 jbr 0f 15531: # do 1554 cmpb (r0),r2 # if (*cp != mask) 1555 jneq 2f # break; 15560: aoblss r1,r0,1b # while (++cp < end); 15572: 1558 subl3 r0,r1,r0; ret # return (end - cp); 1559 1560#ifdef notdef 1561/* 1562 * locc(mask, size, cp) 1563 */ 1564ENTRY(locc, 0) 1565 movl 12(fp),r0 # r0 = cp 1566 addl3 8(fp),r0,r1 # r1 = end = &cp[size] 1567 movb 7(fp),r2 # r2 = mask 1568 decl r0 # --cp; 1569 jbr 0f 15701: # do 1571 cmpb (r0),r2 # if (*cp == mask) 1572 jeql 2f # break; 15730: aoblss r1,r0,1b # while (++cp < end); 15742: 1575 subl3 r0,r1,r0; ret # return (end - cp); 1576#endif 1577