1# 2# Machine Language Assist for UC Berkeley Virtual Vax/Unix 3# 4# locore.s 3.14 09/09/80 5# 6 7 .set HIGH,31 # mask for total disable 8 .set MCKVEC,4 # offset into Scbbase of machine check vector 9 .set NBPG,512 10 .set PGSHIFT,9 11 12 .set CLSIZE,2 13 .set BSIZE,NBPG*CLSIZE 14 .set NBUF,62 15 .set UPAGES,6 # size of user area, in pages 16 17# ==================================== 18# Trap vectors and C interface for Vax 19# ==================================== 20 21# 22# System control block 23# 24 25 .set INTSTK,1 # handle this interrupt on the interrupt stack 26 .set HALT,3 # halt if this interrupt occurs 27# .align PGSHIFT 28 .globl Scbbase 29Scbbase: 30 .long Xstray + INTSTK # unused 31 .long Xmachcheck + HALT # machine check interrupt 32 .long Xkspnotval + HALT # kernel stack not valid 33 .long Xpowfail + HALT # power fail 34 .long Xprivinflt # privileged instruction 35 .long Xxfcflt # xfc instruction 36 .long Xresopflt # reserved operand 37 .long Xresadflt # reserved addressing 38 .long Xprotflt # protection and pt length violation 39 .long Xtransflt # address translation not valid fault 40 .long Xtracep # trace pending 41 .long Xbptflt # bpt instruction 42 .long Xcompatflt # compatibility mode fault 43 .long Xarithtrap # arithmetic trap 44 .long Xstray + INTSTK # unused 45 .long Xstray + INTSTK # unused 46 .long Xsyscall # chmk 47 .long Xchme+HALT # chme 48 .long Xchms+HALT # chms 49 .long Xchmu+HALT # chmu 50 .long Xstray + INTSTK # unused 51 .long Xstray + INTSTK # unused 52 .long Xstray + INTSTK # unused 53 .long Xstray + INTSTK # unused 54 .long Xstray + INTSTK # unused 55 .long Xstray + INTSTK # unused 56 .long Xstray + INTSTK # unused 57 .long Xstray + INTSTK # unused 58 .long Xstray + INTSTK # unused 59 .long Xstray + INTSTK # unused 60 .long Xstray + INTSTK # unused 61 .long Xstray + INTSTK # unused 62 .long Xstray + INTSTK # unused 63 .long Xstray + INTSTK # software level 1 64 .long Xstray + INTSTK # software level 2 (asts) 65 .long Xresched # reschedule nudge 66 .long Xstray + INTSTK # unused 67 .long Xstray + INTSTK # unused 68 .long Xstray + INTSTK # unused 69 .long Xstray + INTSTK # unused 70 .long Xstray + INTSTK # unused 71 .long Xstray + INTSTK # unused 72 .long Xstray + INTSTK # unused 73 .long Xstray + INTSTK # unused 74 .long Xstray + INTSTK # unused 75 .long Xstray + INTSTK # unused 76 .long Xstray + INTSTK # unused 77 .long Xstray + INTSTK # unused 78ubabase: 79 .long Xclockint # clock 80 .long Xstray + INTSTK # unused 81 .long Xstray + INTSTK # unused 82 .long Xstray + INTSTK # unused 83 .long Xstray + INTSTK # unused 84 .long Xstray + INTSTK # unused 85 .long Xstray + INTSTK # unused 86 .long Xstray + INTSTK # unused 87 .long Xstray + INTSTK # unused 88 .long Xstray + INTSTK # unused 89 .long Xstray + INTSTK # unused 90 .long Xstray + INTSTK # unused 91 .long Xstray + INTSTK # unused 92 .long Xstray + INTSTK # unused 93 .long Xcnrint + INTSTK # console receiver 94 .long Xcnxint + INTSTK # console transmitter 95 96# 97# I/O vectors 98# 99 100# IPL 14 101 .long Xstray + INTSTK # unused 102 .long Xstray + INTSTK # unused 103 .long Xstray + INTSTK # unused 104 .long Xua0int + INTSTK # UBA 0 br4 105 .long Xstray + INTSTK # unused 106 .long Xstray + INTSTK # unused 107 .long Xstray + INTSTK # unused 108 .long Xstray + INTSTK # unused 109 .long Xstray + INTSTK # unused 110 .long Xstray + INTSTK # unused 111 .long Xstray + INTSTK # unused 112 .long Xstray + INTSTK # unused 113 .long Xstray + INTSTK # unused 114 .long Xstray + INTSTK # unused 115 .long Xstray + INTSTK # unused 116 .long Xstray + INTSTK # unused 117 118# IPL 15 119 .long Xstray + INTSTK # unused 120 .long Xstray + INTSTK # unused 121 .long Xstray + INTSTK # unused 122 .long Xua0int + INTSTK # UBA 0 br5 123 .long Xstray + INTSTK # unused 124 .long Xstray + INTSTK # unused 125 .long Xstray + INTSTK # unused 126 .long Xstray + INTSTK # unused 127 .long Xmba0int + INTSTK # mass bus adapter 0 128 .long Xmba1int + INTSTK # mass bus adapter 1 129 .long Xstray + INTSTK # unused 130 .long Xstray + INTSTK # unused 131 .long Xstray + INTSTK # unused 132 .long Xstray + INTSTK # unused 133 .long Xstray + INTSTK # unused 134 .long Xstray + INTSTK # unused 135 136# IPL 16 137 .long Xstray + INTSTK # unused 138 .long Xstray + INTSTK # unused 139 .long Xstray + INTSTK # unused 140 .long Xua0int + INTSTK # UBA 0 br6 141 .long Xstray + INTSTK # unused 142 .long Xstray + INTSTK # unused 143 .long Xstray + INTSTK # unused 144 .long Xstray + INTSTK # unused 145 .long Xstray + INTSTK # unused 146 .long Xstray + INTSTK # unused 147 .long Xstray + INTSTK # unused 148 .long Xstray + INTSTK # unused 149 .long Xstray + INTSTK # unused 150 .long Xstray + INTSTK # unused 151 .long Xstray + INTSTK # unused 152 .long Xstray + INTSTK # unused 153 154# IPL 17 155 .long Xstray + INTSTK # unused 156 .long Xstray + INTSTK # unused 157 .long Xstray + INTSTK # unused 158 .long Xstray + INTSTK # unused 159 .long Xstray + INTSTK # unused 160 .long Xstray + INTSTK # unused 161 .long Xstray + INTSTK # unused 162 .long Xstray + INTSTK # unused 163 .long Xstray + INTSTK # unused 164 .long Xstray + INTSTK # unused 165 .long Xstray + INTSTK # unused 166 .long Xstray + INTSTK # unused 167 .long Xstray + INTSTK # unused 168 .long Xstray + INTSTK # unused 169 .long Xstray + INTSTK # unused 170 .long Xstray + INTSTK # unused 171 172# 0x200 173 174# ===================================== 175# Produce a core image dump on mag tape 176# ===================================== 177 .globl doadump 178doadump: 179 movl sp,dumpstack # save stack pointer 180 movab dumpstack,sp # reinit stack 181 mfpr $PCBB,-(sp) # save u-area pointer 182 mfpr $MAPEN,-(sp) # save value 183 mfpr $IPL,-(sp) # ... 184 mtpr $0,$MAPEN # turn off memory mapping 185 mtpr $HIGH,$IPL # disable interrupts 186 pushr $0x3fff # save regs 0 - 13 187 calls $0,_dumptrc # print out trace information, if any 188 calls $0,_dump # produce dump 189 halt 190 191 .data 192 .align 2 193 .globl dumpstack 194 .space 58*4 # separate stack for tape dumps 195dumpstack: 196 .space 4 197 .text 198 199# 200# Debugging print switches given here so they won't move around 201# 202 .data 203 .align 2 204 .globl _printsw 205_printsw: 206 .space 4 207 .globl _coresw 208_coresw: 209 .space 4 210 .text 211 212# ============================= 213# I/O interrupt vector routines 214# ============================= 215 216# 217# Physical i/o addresses 218# 219 .set PHYSMCR,0x20002000 # memory controller register 220 .set PHYSUBA,0x20006000 # uba 0 221 .set PHYSUMEM,0x2013e000 # unibus memory 222 223# 224# Catch random or unexpected interrupts 225# 226 .align 2 227Xrandom: 228Xmachcheck: 229Xkspnotval: 230Xpowfail: 231Xchme: 232Xchms: 233Xchmu: 234 halt 235 236 .align 2 237Xstray: 238 pushr $0x3f 239 pushab straym 240 calls $1,_printf 241 popr $0x3f 242 rei 243 244# 245# Massbus 0 adapter interrupts 246# 247 .align 2 248Xmba0int: 249 pushr $0x3f # save r0 - r5 250 movab MBA0_CSR,r0 # point at mba regs 251 movl MBA_AS(r0),r1 # get attn summary bits 252 cvtwl r1,-(sp) # push attn summary as arg 253 pushl MBA_SR(r0) # pass sr as argument 254 mnegl $1,MBA_SR(r0) # clear attention bit 255 calls $2,_hpintr # call rp06 interrupt dispatcher 256 brw int_ret # merge with common interrupt code 257 258# 259# Massbus 1 adapter interrupts 260# 261 .align 2 262Xmba1int: 263 pushr $0x3f 264 movab MBA1_CSR,r0 265 pushl MBA_AS(r0) 266 mnegl $1,MBA_AS(r0) 267 pushl MBA_SR(r0) # pass sr as argument 268 mnegl $1,MBA_SR(r0) # clear attention bit 269 calls $2,_htintr # call te16 interrupt dispatcher 270 brw int_ret # return from interrupt 271 272# 273# Unibus adapter interrupts 274# 275 .align 2 276Xua0int: 277 pushr $0x3f # save regs 0-5 278 mfpr $IPL,r2 # get br level 279 movl UBA0+UBR_OFF-20*4[r2],r3# get unibus device vector 280 bleq ubasrv # branch if zero vector 281 # ... or UBA service required 282 283# 284# Normal UBA interrupt point - device on a UBA has generated an 285# interrupt - r3 holds interrupt vector. Get the service routine 286# address and controller code from the UNIBUS vector area 287# and service the interrupt. 288# 289ubanorm: 290 movl _UNIvec(r3),r1 291 extzv $27,$4,r1,r0 # controller code is in 4 most 292 # significant bits-1 of ISR addr 293 bicl2 $0x78000000,r1 # clear code 294 jlbc r1,ubanpdma # no pseudo dma here 295 jmp -1(r1) # branch to pseudo dma rtn 296ubanpdma: 297 pushl r0 # controller code 298 calls $1,(r1) # call ISR 299 brw int_ret # go to common interrupt return 300 301# 302# Come here for zero or negative UBA interrupt vector. 303# Negative vector -> UBA requires service. 304# 305ubasrv: 306 beql ubapass 307# 308# UBA service required. 309# The following 'printf' calls should probably be replaced 310# with calls to an error logger and/or some corrective action. 311# 312 bitl $CFGFLT,UBA0+UCN_OFF # any SBI faults ? 313 beql UBAflt 314 pushr $0xf # save regs 0-3 315 pushab SBImsg 316 calls $1,_printf 317 popr $0xf 318# 319# No SBI fault bits set in UBA config reg - must be 320# some error bits set in UBA status reg. 321# 322UBAflt: 323 movl UBA0+UST_OFF,r2 # UBA status reg 324 pushr $0xf # save regs 0-3 325 mfpr $IPL,-(sp) 326 mtpr $HIGH,$IPL 327 pushl UBA0+UFUBAR_OFF 328 pushl UBA0+UFMER_OFF 329 pushl r2 330 pushab UBAmsg 331 calls $4,_printf 332 mtpr (sp)+,$IPL 333 popr $0xf 334 movl r2,UBA0+UST_OFF # clear error bits 335 bicl2 $0x80000000,r3 # clear neg bit in vector 336 jneq ubanorm # branch if normal UBA interrupt 337 # to process 338 brw int_ret # restore regs and return 339# 340# Zero interrupt vector - count 'em 341# 342ubapass: 343 incl _zvcnt 344 cmpl _zvcnt,$250000 345 jlss int_ret 346 pushab ZERmsg 347 calls $1,_printf 348 clrl _zvcnt 349 calls $0,_ubareset 350 brw int_ret 351 .data 352 .globl _zvcnt 353_zvcnt: .space 4 354 .globl _dzdcnt 355_dzdcnt:.space 4 356 .text 357 358# 359# DZ pseudo dma routine: 360# r0 - controller number 361# 362 .align 1 363 .globl _dzdma 364_dzdma: 365# bisw2 $4,*_draddr # leading edge for dr11-c 366 mull2 $8*20,r0 367 movab _dzpdma(r0),r3 # pdma structure base 368 # for this controller 369dzploop: 370 movl r3,r0 371 movl (r0)+,r1 # device register address 372 movzbl 1(r1),r2 # get line number 373 bitb $0x80,r2 # TRDY on? 374 beql dzprei # no 375 incl _dzdcnt ## loop trips 376 bicb2 $0xf8,r2 # clear garbage bits 377 mull2 $20,r2 378 addl2 r2,r0 # point at line's pdma structure 379 movl (r0)+,r2 # p_mem 380 cmpl r2,(r0)+ # p_mem < p_end ? 381 bgequ dzpcall # no, go call dzxint 382 movb (r2)+,6(r1) # dztbuf = *p_mem++ 383 movl r2,-8(r0) 384 brb dzploop # check for another line 385dzprei: 386# bicw2 $4,*_draddr # trailing edge for dr11-c 387 popr $0x3f 388 incl _cnt+V_PDMA 389 rei 390 391dzpcall: 392 pushl (r0) # push tty address 393 calls $1,_dzxint # call interrupt rtn 394 brb dzploop # check for another line 395 396# 397# Console receiver interrupt 398# 399 .align 2 400Xcnrint: 401 pushr $0x3f # save registers 0 - 5 402 calls $0,_cnrint 403 brb int_ret # merge 404 405# 406# Console transmit interrupt 407# 408 .align 2 409Xcnxint: 410 pushr $0x3f # save registers 0 - 5 411 calls $0,_cnxint 412 brb int_ret 413 414# 415# Clock interrupt 416# 417 .align 2 418Xclockint: 419 pushr $0x3f # save regs 0 - 5 420 pushl 4+6*4(sp) # push psl 421 pushl 4+6*4(sp) # push pc 422 calls $2,_clock 423 brb int_ret 424 425# 426# Common code for interrupts. 427# At this point, the interrupt stack looks like: 428# 429# r0 <- isp 430# ... 431# r5 432# pc 433# psl 434# 435 436int_ret: 437 incl _cnt+V_INTR 438# bbssi $0,idleflag,int_r0 # escape from idle() if old switch code 439#int_r0: 440 popr $0x3f # restore regs 0 - 5 441 bitl $PSL_CURMOD,4(sp) # interrupt from user mode? 442 beql int_r1 # no, from kernel, just rei 443 tstb _runrun # should we reschedule? 444 beql int_r1 # no, just rei 445# 446# If here, interrupt from user mode, and time to reschedule. 447# To do this, we set a software level 3 interrupt to 448# change to kernel mode, switch stacks, and format 449# kernel stack for a `qswitch' trap to force a reschedule. 450# 451 mtpr $0x18,$IPL 452 mtpr $3,$SIRR # request level 1 software interrupt 453int_r1: 454 rei # return to interrupted process 455 456# ================================== 457# User area virtual addresses 458# ================================== 459 460 .globl _u 461 .set _u,0x80000000 - UPAGES*NBPG 462 463 .data 464 .align 2 465 .globl _Sysmap 466_Sysmap: 467 .space 6*NBPG 468UBA0map: 469 .space 16*4 470 .globl _umbabeg 471 .set _umbabeg,((UBA0map-_Sysmap)/4)*512+0x80000000 472UMEMmap: 473 .space 16*4 474 .globl _MBA0map 475_MBA0map: 476 .space 16*4 477 .globl _MBA1map 478_MBA1map: 479 .space 16*4 480umend: 481 .globl _umbaend 482 .set _umbaend,((umend-_Sysmap)/4)*512+0x80000000 483 484 .globl _Usrptmap 485_Usrptmap: 486 .space 8*NBPG 487 .globl _usrpt 488 .set _usrpt,((_Usrptmap-_Sysmap)/4)*NBPG+0x80000000 489 490 .globl _Forkmap 491_Forkmap: 492 .space 4*UPAGES 493 .globl _forkutl 494 .set _forkutl,((_Forkmap-_Sysmap)/4)*NBPG+0x80000000 495 496 .globl _Xswapmap 497_Xswapmap: 498 .space 4*UPAGES 499 .globl _xswaputl 500 .set _xswaputl,((_Xswapmap-_Sysmap)/4)*NBPG+0x80000000 501 502 .globl _Xswap2map 503_Xswap2map: 504 .space 4*UPAGES 505 .globl _xswap2utl 506 .set _xswap2utl,((_Xswap2map-_Sysmap)/4)*NBPG+0x80000000 507 508 .globl _Swapmap 509_Swapmap: 510 .space 4*UPAGES 511 .globl _swaputl 512 .set _swaputl,((_Swapmap-_Sysmap)/4)*NBPG+0x80000000 513 514 .globl _Pushmap 515_Pushmap: 516 .space 4*UPAGES 517 .globl _pushutl 518 .set _pushutl,((_Pushmap-_Sysmap)/4)*NBPG+0x80000000 519 520 .globl _Vfmap 521_Vfmap: 522 .space 4*UPAGES 523 .globl _vfutl 524 .set _vfutl,((_Vfmap-_Sysmap)/4)*NBPG+0x80000000 525 526CMAP1: 527 .space 4 528 .set CADDR1,((CMAP1-_Sysmap)/4)*NBPG+0x80000000 529CMAP2: 530 .space 4 531 .set CADDR2,((CMAP2-_Sysmap)/4)*NBPG+0x80000000 532 533 .globl _mcrmap 534_mcrmap: 535 .space 4 536 .globl _mcr 537 .set _mcr,((_mcrmap-_Sysmap)/4)*NBPG+0x80000000 538 539 .globl _mmap 540_mmap: 541 .space 4 542 .globl _vmmap 543 .set _vmmap,((_mmap-_Sysmap)/4)*NBPG+0x80000000 544 545 .globl _bufmap 546_bufmap: 547 .space 4*NBUF*CLSIZE 548 .globl _buffers 549 .set _buffers,((_bufmap-_Sysmap)/4)*NBPG+0x80000000 550 .globl eSysmap 551eSysmap: 552 .set Syssize,(eSysmap-_Sysmap)/4 553 .text 554 555# ============================== 556# Trap and fault vector routines 557# ============================== 558 559# 560# Reschedule trap (Software level 3 interrupt) 561# 562 .align 2 563Xresched: 564 mtpr $0,$IPL # lower ipl 565 pushl $0 # dummy code 566 pushl $RESCHED # type 567 bitl $PSL_CURMOD,12(sp) 568 bneq alltraps 569 addl2 $8,sp 570 mtpr $HIGH,$IPL 571 rei 572 573# 574# Privileged instruction fault 575# 576 .align 2 577Xprivinflt: 578 pushl $0 # push dummy code 579 pushl $PRIVINFLT # push type 580 brw alltraps # merge 581 582# 583# Xfc instruction fault 584# 585 .align 2 586Xxfcflt: 587 pushl $0 # push dummy code value 588 pushl $XFCFLT # push type value 589 brw alltraps # merge 590 591# 592# Reserved operand fault 593# 594 .align 2 595Xresopflt: 596 pushl $0 # push dummy code value 597 pushl $RESOPFLT # push type value 598 brw alltraps # merge 599 600# 601# Reserved addressing mode fault 602# 603 .align 2 604Xresadflt: 605 pushl $0 # push dummy code value 606 pushl $RESADFLT # push type value 607 brw alltraps # merge with common code 608 609# 610# Bpt instruction fault 611# 612 .align 2 613Xbptflt: 614 pushl $0 # push dummy code value 615 pushl $BPTFLT # push type value 616 brw alltraps # merge with common code 617 618# 619# Compatibility mode fault 620# 621 .align 2 622Xcompatflt: 623 pushl $COMPATFLT # push type value 624 brw alltraps # merge with common code 625 626# 627# Trace trap 628# 629 .align 2 630Xtracep: 631 pushl $0 # push dummy code value 632 pushl $TRCTRAP # push type value 633 brw alltraps # go do it 634 635# 636# Arithmetic trap 637# 638 .align 2 639Xarithtrap: 640 pushl $ARITHTRAP # push type value 641 brw alltraps # merge with common code 642 643# 644# Protection and segmentation fault 645# 646 .align 2 647Xprotflt: 648 blbs (sp),segflt # check for pt length violation 649 addl2 $4,sp # pop fault param word 650 pushl $PROTFLT 651 brw alltraps 652 653# 654# Segmentation fault 655# 656segflt: 657 addl2 $4,sp 658 pushl $SEGFLT 659 brb alltraps 660 661# 662# Translation Not Valid Fault 663# 664 .align 2 665Xtransflt: 666 bbs $1,(sp),tableflt # check for page table fault 667 addl2 $4,sp # pop fault parameter word 668 pushl $PAGEFLT # push type value 669 brb alltraps 670 671# 672# Page table fault 673# 674tableflt: 675 addl2 $4,sp # pop fault parameter word 676 pushl $TABLEFLT # push type value 677 brb alltraps 678 679# 680# all traps but syscalls... 681# 682alltraps: 683 mfpr $USP,-(sp) # get usp 684 calls $0,_trap # $0 so ret wont pop args 685 incl _cnt+V_TRAP 686 mtpr (sp)+,$USP # restore usp 687 addl2 $8,sp # pop type, code 688 mtpr $HIGH,$IPL # make sure we are not going to 689 # a higher IPL 690 rei 691 692# 693# CHMK trap (syscall trap) 694# 695# Kernel stack on entry: 696# 697# code <- ksp 698# pc 699# psl 700# 701# 702# Stack (parameters) at calls to _trap or _syscall 703# 704# usp <- ksp 705# type 706# code 707# pc 708# psl 709# 710 711 .align 2 712Xsyscall: 713 pushl $SYSCALL # push type value 714 mfpr $USP,-(sp) # get usp 715 calls $0,_syscall # $0 so ret wont pop args 716 incl _cnt+V_SYSCALL 717 mtpr (sp)+,$USP # restore usp 718 addl2 $8,sp # pop type, code 719 mtpr $HIGH,$IPL # make sure we are not going to 720 # a higher IPL 721 rei 722 723# ============== 724# Initialization 725# ============== 726# 727# IPL == 1F 728# MAPEN == off 729# SCBB, PCBB not set 730# SBR, SLR not set 731# ISP, KSP not set 732# 733 .globl start 734start: 735 .word 0x0000 736 mtpr $HIGH,$IPL # no interrupts yet 737 mtpr $Scbbase,$SCBB # set SCBB 738 mtpr $_Sysmap,$SBR # set SBR 739 mtpr $Syssize,$SLR # set SLR 740 mtpr $_Sysmap,$P0BR # set temp P0BR 741 mtpr $Syssize,$P0LR # set temp P0LR 742 movl $_intstack+2048,sp # set ISP 743# 744# Initialize I/O adapters. 745# 746 movl $1,PHYSUBA+4 # init & interrupt enable 747 movl $0x78,PHYSUBA+4 # init & interrupt enable 748 749 movl Scbbase+MCKVEC,r5 # save machine check entry 750 movab 2f+INTSTK,Scbbase+MCKVEC # set new vector address 751# 752# Will now see how much memory there really is 753# in 64kb chunks. Save number of bytes in r7. 754# 755 mtpr $HIGH-1,$IPL # allow machine check interrupts 756 clrl r7 7571: 758 tstl (r7) # this chunk really there? 759 acbl $8096*1024-1,$64*1024,r7,1b # loop till mach check 760 brb 2f # full load of memory 761 762 .align 2 7632: 764 mtpr $0,$SBIFS # clear sbi fault status 765 movl r5,Scbbase+MCKVEC # restore machine check vector 766 movl $_intstack+2048,sp # reset interrupt stack pointer 767# 768# calculate size of cmap[] based on available memory, and allocate space for it 769# 770 movab _end,r5 771 movl r5,_cmap 772 bbss $31,_cmap,0f; 0: 773 subl3 r5,r7,r1 774 divl2 $(NBPG*CLSIZE)+CMSIZE,r1 775 mull2 $CMSIZE,r1 776 addl3 _cmap,r1,_ecmap 777# 778# Clear memory starting with kernel bss, and extra pages for 779# proc 0 u. and proc 0 paget. 780# 781 movab _edata,r6 782 movl _ecmap,r5 # clear to end of cmap[] 783 bbcc $31,r5,0f; 0: 784 addl2 $(UPAGES*NBPG)+NBPG+NBPG,r5 7851: 786 clrq (r6) 787 acbl r5,$8,r6,1b 788 789# 790# Finagle _trap and _syscall to save r0-r11 so 791# that it won't be necessary to pushr/popr what 792# the (already time consuming) calls is prepared to do. 793# The fact that this is done is well known (e.g. in the definition 794# of the stack offsets of the registers in ../h/reg.h) 795# 796 bisw2 $0x0fff,_trap # so _trap saves r0-r11 797 bisw2 $0x0fff,_syscall # so _syscall saves r0-r11 798 799# 800# Initialize system page table 801# 802 movab _etext+NBPG-1,r1 # end of kernel text segment 803 bbcc $31,r1,0f; 0: # turn off high order bit 804 ashl $-9,r1,r1 # last page of kernel text 805 clrl r2 # point at first kernel text page 8061: 807 bisl3 $PG_V|PG_KR,r2,_Sysmap[r2] # initialize page table entry 808 aoblss r1,r2,1b # fill text entries 809 addl3 _ecmap,$NBPG-1,r1 # end of cmap[] 810 bbcc $31,r1,0f; 0: # turn off high order bit 811 ashl $-9,r1,r1 # last page of kernel data 8121: 813 bisl3 $PG_V|PG_KW,r2,_Sysmap[r2] # fill data entries 814 aoblss r1,r2,1b 815# 816# initialize memory controller mapping 817# 818 movl $PHYSMCR/NBPG,r1 819 movab _mcrmap,r2 820 bisl3 $PG_V|PG_KW,r1,(r2) 821# 822# Initialize UNIBUS page table entries 823# 824 movl $PHYSUBA/NBPG,r1 # page frame number for uba 825 movab UBA0map,r2 # page table address 826 movab 15(r1),r3 # last pt entry 8271: 828 bisl3 $PG_V|PG_KW,r1,(r2)+ # init pt entry 829 aobleq r3,r1,1b 830 movl $PHYSUMEM/NBPG,r1 831 movab UMEMmap,r2 # page table address 832 movab 15(r1),r3 # limit 8331: 834 bisl3 $PG_V|PG_KW,r1,(r2)+ 835 aobleq r3,r1,1b 836 mtpr $1,$TBIA # invalidate all trans buffer entries 837 mtpr $1,$MAPEN # turn on memory mapping 838 jmp *$0f # put system virtual address in pc 839# 840# Now we move forward, virtually. 841# 8420: 843 ashl $-9,r7,_maxmem # set maxmem = btoc(r7) 844 movl _maxmem,_physmem 845 movl _maxmem,_freemem 846 847# 848# Setup context for proc[0] == Scheduler 849# 850# First page: paget for proc[0] 851# Next UPAGES: _u for proc[0] 852# Initialize (slightly) the pcb. 853# 854 addl3 _ecmap,$NBPG-1,r6 855 bicl2 $NBPG-1,r6 # make page boundary 856# 857# set up u area page table 858# 859 bbcc $31,r6,0f; 0: 860 ashl $-9,r6,r3 # r3 = btoc(r6) 861 bisl3 $PG_V|PG_KW,r3,_Usrptmap # init first upt entry 862 movab _usrpt,r0 863 mtpr r0,$TBIS 864 mtpr r0,$P0BR 865 mtpr $0,$P0LR 866 movab NBPG(r0),r0 867 movl $0x200000-UPAGES,r1 868 mtpr r1,$P1LR 869 mnegl r1,r1 870 moval -4*UPAGES(r0)[r1],r2 871 mtpr r2,$P1BR 872 movl $UPAGES,r2 873 movab _u+NBPG*UPAGES,r1 874 jbr 2f 8751: 876 incl r3 877 moval -NBPG(r1),r1 878 bisl3 $PG_V|PG_URKW,r3,-(r0) 879 mtpr r1,$TBIS 8802: 881 sobgeq r2,1b 882 883 movab UPAGES*NBPG(r1),PCB_KSP(r1) # init ksp 884 mnegl $1,PCB_ESP(r1) # invalidate esp 885 mnegl $1,PCB_SSP(r1) # invalidate ssp 886 movl r1,PCB_USP(r1) # set user sp 887 mfpr $P0BR,PCB_P0BR(r1) 888 mfpr $P0LR,PCB_P0LR(r1) 889 movb $4,PCB_P0LR+3(r1) # disable ast 890 mfpr $P1BR,PCB_P1BR(r1) 891 mfpr $P1LR,PCB_P1LR(r1) 892 movl $CLSIZE,PCB_SZPT(r1) # init u.u_pcb.pcb_szpt 893 894 movab 1f,PCB_PC(r1) # initial pc 895 clrl PCB_PSL(r1) # mode(k,k), ipl=0 896 ashl $9,r3,r3 897 mtpr r3,$PCBB # first pcbb 898# 899# set regs, p0br, p0lr, p1br, p1lr 900# astlvl, ksp and change to kernel mode 901# 902 ldpctx 903 rei 904 905# 906# put signal trampoline code in u. area 907# 9081: 909 movab _u,r0 910 movc3 $12,sigcode,PCB_SIGC(r0) 911 912 addl3 _ecmap,$NBPG-1,r0 # calculate firstaddr 913 bbcc $31,r0,0f; 0: 914 ashl $-9,r0,-(sp) # convert to clicks and stack 915 calls $1,_main # startup, fork off /etc/init.vm 916# 917# proc[1] == /etc/init now running here. 918# execute code at location 0, in user mode. 919# 920 pushl $PSL_CURMOD|PSL_PRVMOD # psl, user mode, ipl = 0 921 pushl $0 # pc, $location 0 922 rei # do /etc/init.vm 923 924# 925# signal trampoline code 926# it is known that this code takes exactly 12 bytes 927# in ../h/pcb.h and in the movc3 above 928# 929sigcode: 930 calls $3,1(pc) 931 rei 932 .word 0x7f 933 callg (ap),*12(ap) # registers 0-6 (6==sp/compat) 934 ret 935 936# ========== 937# Primitives 938# ========== 939 940_addupc: .globl _addupc 941 .word 0x0000 942 movl 8(ap),r2 # &u.u_prof 943 subl3 8(r2),4(ap),r0 # corrected pc 944 blss 9f 945 extzv $1,$31,r0,r0 # logical right shift 946 extzv $1,$31,12(r2),r1 # ditto for scale 947 emul r1,r0,$0,r0 948 ashq $-14,r0,r0 949 tstl r1 950 bneq 9f 951 incl r0 952 bicb2 $1,r0 953 blss 9f 954 cmpl r0,4(r2) # length 955 bgequ 9f 956 addl2 (r2),r0 # base 957 probew $3,$2,(r0) 958 beql 8f 959 addw2 12(ap),(r0) 9609: 961 ret 9628: 963 clrl 12(r2) 964 ret 965 966_Copyin: .globl _Copyin # <<<massaged for jsb by asm.sed>>> 967 movl 12(sp),r0 # copy length 968 blss ersb 969 movl 4(sp),r1 # copy user address 970 cmpl $NBPG,r0 # probing one page or less ? 971 bgeq cishort # yes 972ciloop: 973 prober $3,$NBPG,(r1) # bytes accessible ? 974 beql ersb # no 975 addl2 $NBPG,r1 # incr user address ptr 976 acbl $NBPG+1,$-NBPG,r0,ciloop # reduce count and loop 977cishort: 978 prober $3,r0,(r1) # bytes accessible ? 979 beql ersb # no 980 movc3 12(sp),*4(sp),*8(sp) 981 clrl r0 982 rsb 983 984ersb: 985 mnegl $1,r0 986 rsb 987 988_Copyout: .globl _Copyout # <<<massaged for jsb by asm.sed >>> 989 movl 12(sp),r0 # get count 990 blss ersb 991 movl 8(sp),r1 # get user address 992 cmpl $NBPG,r0 # can do in one probew? 993 bgeq coshort # yes 994coloop: 995 probew $3,$NBPG,(r1) # bytes accessible? 996 beql ersb # no 997 addl2 $NBPG,r1 # increment user address 998 acbl $NBPG+1,$-NBPG,r0,coloop # reduce count and loop 999coshort: 1000 probew $3,r0,(r1) # bytes accessible? 1001 beql ersb # no 1002 movc3 12(sp),*4(sp),*8(sp) 1003 clrl r0 1004 rsb 1005 1006# 1007# non-local goto's 1008# 1009 .globl _Setjmp 1010_Setjmp: 1011 movq r6,(r0)+ 1012 movq r8,(r0)+ 1013 movq r10,(r0)+ 1014 movq r12,(r0)+ 1015 addl3 $4,sp,(r0)+ 1016 movl (sp),(r0) 1017 clrl r0 1018 rsb 1019 1020 .globl _Longjmp 1021_Longjmp: 1022 movq (r0)+,r6 1023 movq (r0)+,r8 1024 movq (r0)+,r10 1025 movq (r0)+,r12 1026 movl (r0)+,r1 1027 cmpl r1,sp # must be a pop 1028 bgequ lj2 1029 pushab lj1 1030 calls $1,_panic 1031lj2: 1032 movl r1,sp 1033 jmp *(r0) # ``rsb'' 1034 1035lj1: .asciz "longjmp" 1036 1037 .globl _whichqs 1038 .globl _qs 1039 .globl _cnt 1040 1041 .globl _noproc 1042 .comm _noproc,4 1043 .globl _runrun 1044 .comm _runrun,4 1045 1046# 1047# The following primitives use the fancy VAX instructions 1048# much like VMS does. _whichqs tells which of the 32 queues _qs 1049# have processes in them. Setrq puts processes into queues, Remrq 1050# removes them from queues. The running process is on no queue, 1051# other processes are on a queue related to p->p_pri, divided by 4 1052# actually to shrink the 0-127 range of priorities into the 32 available 1053# queues. 1054# 1055 1056# 1057# Setrq(p), using fancy VAX instructions. 1058# 1059# Call should be made at spl6(), and p->p_stat should be SRUN 1060# 1061 .globl _Setrq # <<<massaged to jsb by "asm.sed">>> 1062_Setrq: 1063 tstl P_RLINK(r0) ## firewall: p->p_rlink must be 0 1064 beql set1 ## 1065 pushab set3 ## 1066 calls $1,_panic ## 1067set1: 1068 movzbl P_PRI(r0),r1 # put on queue which is p->p_pri / 4 1069 ashl $-2,r1,r1 1070 movaq _qs[r1],r2 1071 insque (r0),*4(r2) # at end of queue 1072 bbss r1,_whichqs,set2 # mark queue non-empty 1073set2: 1074 rsb 1075 1076set3: .asciz "setrq" 1077 1078# 1079# Remrq(p), using fancy VAX instructions 1080# 1081# Call should be made at spl6(). 1082# 1083 .globl _Remrq # <<<massaged to jsb by "asm.sed">>> 1084_Remrq: 1085 movzbl P_PRI(r0),r1 1086 ashl $-2,r1,r1 1087 bbsc r1,_whichqs,rem1 1088 pushab rem3 # it wasn't recorded to be on its q 1089 calls $1,_panic 1090rem1: 1091 remque (r0),r2 1092 beql rem2 1093 bbss r1,_whichqs,rem2 1094rem2: 1095 clrl P_RLINK(r0) ## for firewall checking 1096 rsb 1097 1098rem3: .asciz "remrq" 1099 1100sw0: .asciz "swtch" 1101# 1102# Swtch(), using fancy VAX instructions 1103# 1104 .globl _Swtch 1105_Swtch: # <<<massaged to jsb by "asm.sed">>> 1106 movl $1,_noproc 1107 clrl _runrun 1108sw1: ffs $0,$32,_whichqs,r0 # look for non-empty queue 1109 bneq sw1a 1110 mtpr $0,$IPL # must allow interrupts here 1111 brw sw1 # this is an idle loop! 1112sw1a: mtpr $0x18,$IPL # lock out all so _whichqs==_qs 1113 bbcc r0,_whichqs,sw1 # proc moved via lbolt interrupt 1114 movaq _qs[r0],r1 1115 remque *(r1),r2 # r2 = p = highest pri process 1116 bvc sw2 # make sure something was there 1117sw1b: pushab sw0 1118 calls $1,_panic 1119sw2: beql sw3 1120 insv $1,r0,$1,_whichqs # still more procs in this queue 1121sw3: 1122 clrl _noproc 1123 tstl P_WCHAN(r2) ## firewalls 1124 bneq sw1b ## 1125 movzbl P_STAT(r2),r3 ## 1126 cmpl $SRUN,r3 ## 1127 bneq sw1b ## 1128 clrl P_RLINK(r2) ## 1129 ashl $PGSHIFT,*P_ADDR(r2),r0 # r0 = pcbb(p) 1130# mfpr $PCBB,r1 # resume of current proc is easy 1131# cmpl r0,r1 1132# beql res0 1133 incl _cnt+V_SWTCH 1134# fall into... 1135 1136# 1137# Resume(pf) 1138# 1139 .globl _Resume # <<<massaged to jsb by "asm.sed">>> 1140_Resume: 1141 mtpr $0x18,$IPL # no interrupts, please 1142 movl CMAP2,_u+PCB_CMAP2 # yech 1143 svpctx 1144 mtpr r0,$PCBB 1145 ldpctx 1146 movl _u+PCB_CMAP2,CMAP2 # yech 1147res0: 1148 tstl _u+PCB_SSWAP 1149 beql res1 1150 movl _u+PCB_SSWAP,r0 1151 clrl _u+PCB_SSWAP 1152 movab _Longjmp,(sp) 1153 movl $PSL_PRVMOD,4(sp) # ``cheating'' (jfr) 1154res1: 1155 rei 1156 1157# 1158# {fu,su},{byte,word}, all massaged by asm.sed to jsb's 1159# 1160 .globl _Fuword 1161_Fuword: 1162 prober $3,$4,(r0) 1163 beql fserr 1164 movl (r0),r0 1165 rsb 1166fserr: 1167 mnegl $1,r0 1168 rsb 1169 1170 .globl _Fubyte 1171_Fubyte: 1172 prober $3,$1,(r0) 1173 beql fserr 1174 movzbl (r0),r0 1175 rsb 1176 1177 .globl _Suword 1178_Suword: 1179 probew $3,$4,(r0) 1180 beql fserr 1181 movl r1,(r0) 1182 clrl r0 1183 rsb 1184 1185 .globl _Subyte 1186_Subyte: 1187 probew $3,$1,(r0) 1188 beql fserr 1189 movb r1,(r0) 1190 clrl r0 1191 rsb 1192 1193# 1194# Copy 1 relocation unit (NBPG bytes) 1195# from user virtual address to physical address 1196# 1197_copyseg: .globl _copyseg 1198 .word 0x0000 1199 mfpr $IPL,r0 # get current pri level 1200 mtpr $HIGH,$IPL # turn off interrupts 1201 bisl3 $PG_V|PG_KW,8(ap),CMAP2 1202 mtpr $CADDR2,$TBIS # invalidate entry for copy 1203 movc3 $NBPG,*4(ap),CADDR2 1204 bicl3 $PG_V|PG_M|PG_KW,CMAP2,r1 1205 cmpl r1,8(ap) 1206 beql okcseg 1207badcseg: 1208 halt 1209 jmp badcseg 1210okcseg: 1211 mtpr r0,$IPL # restore pri level 1212 ret 1213 1214# 1215# zero out physical memory 1216# specified in relocation units (NBPG bytes) 1217# 1218_clearseg: .globl _clearseg 1219 .word 0x0000 1220 mfpr $IPL,r0 # get current pri level 1221 mtpr $HIGH,$IPL # extreme pri level 1222 bisl3 $PG_V|PG_KW,4(ap),CMAP1 1223 mtpr $CADDR1,$TBIS 1224 movc5 $0,(sp),$0,$NBPG,CADDR1 1225 mtpr r0,$IPL # restore pri level 1226 ret 1227 1228# 1229# Check address. 1230# Given virtual address, byte count, and rw flag 1231# returns 0 on no access. 1232# 1233_useracc: .globl _useracc 1234 .word 0x0000 1235 movl 4(ap),r0 # get va 1236 movl 8(ap),r1 # count 1237 tstl 12(ap) # test for read access ? 1238 bneq userar # yes 1239 cmpl $NBPG,r1 # can we do it in one probe ? 1240 bgeq uaw2 # yes 1241uaw1: 1242 probew $3,$NBPG,(r0) 1243 beql uaerr # no access 1244 addl2 $NBPG,r0 1245 acbl $NBPG+1,$-NBPG,r1,uaw1 1246uaw2: 1247 probew $3,r1,(r0) 1248 beql uaerr 1249 movl $1,r0 1250 ret 1251 1252userar: 1253 cmpl $NBPG,r1 1254 bgeq uar2 1255uar1: 1256 prober $3,$NBPG,(r0) 1257 beql uaerr 1258 addl2 $NBPG,r0 1259 acbl $NBPG+1,$-NBPG,r1,uar1 1260uar2: 1261 prober $3,r1,(r0) 1262 beql uaerr 1263 movl $1,r0 1264 ret 1265uaerr: 1266 clrl r0 1267 ret 1268 1269# 1270# kernacc - check for kernel access privileges 1271# 1272# We can't use the probe instruction directly because 1273# it ors together current and previous mode. 1274# 1275 .globl _kernacc 1276_kernacc: 1277 .word 0x0000 1278 movl 4(ap),r0 # virtual address 1279 bbcc $31,r0,kacc1 1280 mfpr $SBR,r2 # address and length of page table (system) 1281 mfpr $SLR,r3 1282 brb kacc2 1283kacc1: 1284 bbsc $30,r0,kacc3 1285 mfpr $P0BR,r2 # user P0 1286 mfpr $P0LR,r3 1287 brb kacc2 1288kacc3: 1289 mfpr $P1BR,r2 # user P1 (stack) 1290 mfpr $P1LR,r3 1291kacc2: 1292 addl3 8(ap),r0,r1 # ending virtual address 1293 ashl $-9,r0,r0 # page number 1294 ashl $-9,r1,r1 1295 bbs $31,4(ap),kacc6 1296 bbc $30,4(ap),kacc6 1297 cmpl r0,r3 # user stack 1298 blss kacerr # address too low 1299 brb kacc4 1300kacc6: 1301 cmpl r1,r3 # compare last page to P0LR or SLR 1302 bgeq kacerr # address too high 1303kacc4: 1304 movl (r2)[r0],r3 1305 bbc $31,4(ap),kacc4a 1306 bbc $31,r3,kacerr # valid bit is off 1307kacc4a: 1308 cmpzv $27,$4,r3,$1 # check protection code 1309 bleq kacerr # no access allowed 1310 tstb 12(ap) 1311 bneq kacc5 # only check read access 1312 cmpzv $27,$2,r3,$3 # check low 2 bits of prot code 1313 beql kacerr # no write access 1314kacc5: 1315 aobleq r1,r0,kacc4 # next page 1316 movl $1,r0 # no errors 1317 ret 1318kacerr: 1319 clrl r0 # error 1320 ret 1321 1322# 1323# unsigned int divide: 1324# (int) i = udiv( (int)dvdnd , (int) divis) 1325# 1326# unsigned int remainder: 1327# (int) j = urem( (int)dvdnd , (int) divis) 1328# 1329 .text 1330 .align 1 1331 .globl _udiv 1332_udiv : 1333 .word 0 # no reg save 1334 movl 4(ap),r0 # dividend 1335 clrl r1 1336 ediv 8(ap),r0,r0,r1 # quotient in r0 1337 ret 1338 1339# .globl _urem 1340# .align 1 1341#_urem: 1342# .word 0 1343# movl 4(ap),r0 1344# clrl r1 1345# ediv 8(ap),r0,r1,r0 # remainder in r0 1346# ret 1347 1348# ============== 1349# Error messages 1350# ============== 1351 1352 .data 1353SBImsg: .asciz "SBI fault\n" 1354UBAmsg: .asciz "UBA error UBASR %X, FMER %X, FUBAR %X\n" 1355straym: .asciz "Stray Interrupt\n" 1356ZERmsg: .asciz "ZERO VECTOR " 1357 1358# 1359# Junk. 1360# 1361 1362# 1363# This is needed when running old-style switch code. 1364# Be sure to enable setting of idleflag in interrupt code above also. 1365# 1366#_idle: .globl _idle 1367# .word 0x0000 1368# mtpr $0,$IPL # enable interrupts 1369#waitloc: 1370# blbc idleflag,waitloc # loop until interrupt 1371#ewaitloc: 1372# bbcci $0,idleflag,idle1 # clear idle escape flag 1373#idle1: 1374# ret 1375# .data 1376# .globl _waitloc 1377# .globl _ewaitloc 1378#l .align 2 1379#_waitloc: .long waitloc 1380#_ewaitloc: .long ewaitloc 1381#idleflag: .long 0 1382# .text 1383 1384