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