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