1/*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * William Jolitz. 7 * 8 * %sccs.include.386.c% 9 * 10 * @(#)locore.s 5.7 (Berkeley) 12/06/90 11 */ 12 13/* 14 * locore.s: 4BSD machine support for the Intel 386 15 * Preliminary version 16 * Written by William F. Jolitz, 386BSD Project 17 */ 18 19#include "machine/psl.h" 20#include "machine/pte.h" 21 22#include "errno.h" 23#include "cmap.h" 24 25#include "machine/trap.h" 26 27/* 28 * Note: This version greatly munged to avoid various assembler errors 29 * that may be fixed in newer versions of gas. Perhaps newer versions 30 * will have more pleasant appearance. 31 */ 32 33 .set IDXSHIFT,10 34 .set SYSTEM,0xFE000000 # virtual address of system start 35 /*note: gas copys sign bit (e.g. arithmetic >>), can't do SYSTEM>>22! */ 36 .set SYSPDROFF,0x3F8 # Page dir 37 38 .set IOPHYSmem,0xa0000 39 40/* IBM "compatible" nop - sensitive macro on "fast" 386 machines */ 41#define NOP jmp 7f ; nop ; 7: jmp 7f ; nop ; 7: 42 43/* 44 * User structure is UPAGES at top of user space. 45 */ 46 .set _u,0xFDFFE000 47 .globl _u 48 .set UPDROFF,0x3F7 49 .set UPTEOFF,0x3FE 50 51#define ENTRY(name) \ 52 .globl _/**/name; _/**/name: 53#define ALTENTRY(name) \ 54 .globl _/**/name; _/**/name: 55 56/* 57 * System page table 58 * Mbmap and Usrptmap are enlarged by CLSIZE entries 59 * as they are managed by resource maps starting with index 1 or CLSIZE. 60 */ 61#define SYSMAP(mname, vname, npte) \ 62_/**/mname: .globl _/**/mname; \ 63 .space (npte)*4; \ 64 .set _/**/vname,ptes*NBPG+SYSTEM; \ 65 .globl _/**/vname; \ 66 .set ptes,ptes + npte 67#define ZSYSMAP(mname, vname, npte) \ 68_/**/mname: .globl _/**/mname; \ 69 .set _/**/vname,ptes*NBPG+SYSTEM; \ 70 .globl _/**/vname; 71 72 .data 73 # assumed to start at data mod 4096 74 .set ptes,0 75 SYSMAP(Sysmap,Sysbase,SYSPTSIZE) 76 SYSMAP(Forkmap,forkutl,UPAGES) 77 SYSMAP(Xswapmap,xswaputl,UPAGES) 78 SYSMAP(Xswap2map,xswap2utl,UPAGES) 79 SYSMAP(Swapmap,swaputl,UPAGES) 80 SYSMAP(Pushmap,pushutl,UPAGES) 81 SYSMAP(Vfmap,vfutl,UPAGES) 82 SYSMAP(CMAP1,CADDR1,1) 83 SYSMAP(CMAP2,CADDR2,1) 84 SYSMAP(mmap,vmmap,1) 85 SYSMAP(alignmap,alignutl,1) /* XXX */ 86 SYSMAP(msgbufmap,msgbuf,MSGBUFPTECNT) 87 /* SYSMAP(EMCmap,EMCbase,1) */ 88 SYSMAP(Npxmap,npxutl,UPAGES) 89 SYSMAP(Swtchmap,Swtchbase,UPAGES) 90 .set mbxxx,(NMBCLUSTERS*MCLBYTES) 91 .set mbyyy,(mbxxx>>PGSHIFT) 92 .set mbpgs,(mbyyy+CLSIZE) 93 SYSMAP(Mbmap,mbutl,mbpgs) 94 /* 95 * XXX: NEED way to compute kmem size from maxusers, 96 * device complement 97 */ 98 SYSMAP(kmempt,kmembase,300*CLSIZE) 99#ifdef GPROF 100 SYSMAP(profmap,profbase,600*CLSIZE) 101#endif 102 .set atmemsz,0x100000-0xa0000 103 .set atpgs,(atmemsz>>PGSHIFT) 104 SYSMAP(ATDevmem,atdevbase,atpgs) 105/*#define USRIOSIZE 30*/ 106 SYSMAP(Usriomap,usrio,USRIOSIZE+CLSIZE) /* for PHYSIO */ 107 ZSYSMAP(ekmempt,kmemlimit,0) 108 SYSMAP(Usrptmap,usrpt,USRPTSIZE+CLSIZE) 109 110eSysmap: 111 # .set _Syssize,(eSysmap-_Sysmap)/4 112 .set _Syssize,ptes 113 .globl _Syssize 114 115 /* align on next page boundary */ 116 # . = . + NBPG - 1 & -NBPG /* align to page boundry-does not work*/ 117 # .space (PGSIZE - ((eSysmap-_Sysmap) % PGSIZE)) % PGSIZE 118 .set sz,(4*ptes)%NBPG 119 # .set rptes,(ptes)%1024 120 # .set rptes,1024-rptes 121 # .set ptes,ptes+rptes 122 .set Npdes,10 123 # .space (NBPG - sz) 124 125/* 126 * Initialization 127 */ 128 .data 129 .globl _cpu, _boothowto, _bootdev, _cyloffset, _Maxmem 130_cpu: .long 0 # are we 386, 386sx, or 486 131 .text 132 .globl start 133start: # This is assumed to be location zero! 134 movw $0x1234,%ax 135 movw %ax,0x472 # warm boot 136 jmp 1f 137 .space 0x500 # skip over warm boot shit 138 139 /* enable a20! yecchh!! */ 1401: inb $0x64,%al 141 andb $2,%al 142 jnz 1b 143 movb $0xd1,%al 144 NOP 145 outb %al,$0x64 146 NOP 1471: inb $0x64,%al 148 andb $2,%al 149 jnz 1b 150 movb $0xdf,%al 151 NOP 152 outb %al,$0x60 153 154 /* pass parameters on stack (howto, bootdev, unit, cyloffset) */ 155 156 movl 4(%esp),%eax 157 movl %eax,_boothowto-SYSTEM 158 movl 8(%esp),%eax 159 movl %eax,_bootdev-SYSTEM 160 movl 12(%esp),%eax 161 movl %eax, _cyloffset-SYSTEM 162 163 /* count up memory */ 164 165 xorl %eax,%eax # start with base memory at 0x0 166 #movl $ 0xA0000/NBPG,%ecx # look every 4K up to 640K 167 movl $ 0xA0,%ecx # look every 4K up to 640K 1681: movl 0(%eax),%ebx # save location to check 169 movl $0xa55a5aa5,0(%eax) # write test pattern 170 cmpl $0xa55a5aa5,0(%eax) # does not check yet for rollover 171 jne 2f 172 movl %ebx,0(%eax) # restore memory 173 addl $ NBPG,%eax 174 loop 1b 1752: shrl $12,%eax 176 movl %eax,_Maxmem-SYSTEM 177 178 movl $0x100000,%eax # next, talley remaining memory 179 #movl $((0xFFF000-0x100000)/NBPG),%ecx 180 movl $(0xFFF-0x100),%ecx 1811: movl 0(%eax),%ebx # save location to check 182 movl $0xa55a5aa5,0(%eax) # write test pattern 183 cmpl $0xa55a5aa5,0(%eax) # does not check yet for rollover 184 jne 2f 185 movl %ebx,0(%eax) # restore memory 186 addl $ NBPG,%eax 187 loop 1b 1882: shrl $12,%eax 189 movl %eax,_Maxmem-SYSTEM 190 191/* clear memory. */ 192 movl $_edata-SYSTEM,%edi 193 movl $_end-SYSTEM,%ecx 194 addl $ NBPG-1,%ecx 195 andl $~(NBPG-1),%ecx 196 movl %ecx,%esi 197 subl %edi,%ecx 198 addl $(UPAGES*NBPG)+NBPG+NBPG+NBPG,%ecx 199 # txt+data+proc zero pt+u. 200 # any other junk? 201 # addl $ NBPG-1,%ecx 202 # andl $~(NBPG-1),%ecx 203 # shrl $2,%ecx # convert to long word count 204 xorl %eax,%eax # pattern 205 cld 206 rep 207 stosb 208 209#ifdef notdef 210 /* pass parameters on stack (howto, bootdev, unit, cyloffset) */ 211 212 movl 4(%esp),%eax 213 movl %eax,_boothowto-SYSTEM 214 movl 8(%esp),%eax 215 movl %eax,_bootdev-SYSTEM 216 movl 12(%esp),%eax 217 movl %eax, _cyloffset-SYSTEM 218 219 220 movl $0x36000,%edi 221 movl $0x68000,%ecx 222 xorl %eax,%eax # pattern 223 cld 224 rep 225 stosb 226 227#endif 228 movl $0x100000,%edi 229 movl $0x200000,%ecx 230 xorl %eax,%eax # pattern 231 cld 232 rep 233 stosb 234/* 235 * Map Kernel 236 * N.B. don't bother with making kernel text RO, as 386 237 * ignores R/W AND U/S bits on kernel access (only v works) ! 238 * 239 * First step - build page tables 240 */ 241 movl %esi,%ecx # this much memory, 242 shrl $ PGSHIFT,%ecx # for this many pte s 243 movl $ PG_V,%eax # having these bits set, 244 movl $_Sysmap-SYSTEM,%ebx # in the kernel page table, 245 # fill in kernel page table. 2461: movl %eax,0(%ebx) 247 addl $ NBPG,%eax # increment physical address 248 addl $4,%ebx # next pte 249 loop 1b 250 251/* temporary double map virt == real */ 252 253 movl $1024,%ecx # for this many pte s, 254 movl $ PG_V,%eax # having these bits set, 255 movl $_Sysmap+4096-SYSTEM,%ebx # in the temporary page table, 256 # fill in kernel page table. 2571: movl %eax,0(%ebx) 258 addl $ NBPG,%eax # increment physical address 259 addl $4,%ebx # next pte 260 loop 1b 261 262/* map I/O memory map */ 263 264 movl $atpgs,%ecx # for this many pte s, 265 movl $(IOPHYSmem|PG_V),%eax # having these bits set, (perhaps URW?) 266 movl $_ATDevmem-SYSTEM,%ebx # in the temporary page table, 267 # fill in kernel page table. 2681: movl %eax,0(%ebx) 269 addl $ NBPG,%eax # increment physical address 270 addl $4,%ebx # next pte 271 loop 1b 272 273/* map proc 0's page table (P1 region) */ 274 275 movl $_Usrptmap-SYSTEM,%ebx # get pt map address 276 lea (0*NBPG)(%esi),%eax # physical address of pt in proc 0 277 orl $ PG_V,%eax # having these bits set, 278 movl %eax,0(%ebx) 279 280 /* map proc 0's _u */ 281 282 movl $ UPAGES,%ecx # for this many pte s, 283 lea (2*NBPG)(%esi),%eax # physical address of _u in proc 0 284 orl $ PG_V|PG_URKW,%eax # having these bits set, 285 lea (0*NBPG)(%esi),%ebx # physical address of stack pt in proc 0 286 addl $(UPTEOFF*4),%ebx 287 # fill in proc 0 stack page table. 2881: movl %eax,0(%ebx) 289 addl $ NBPG,%eax # increment physical address 290 addl $4,%ebx # next pte 291 loop 1b 292 293 /*# map proc 0's page directory*/ 294 lea (1*NBPG)(%esi),%eax # physical address of ptd in proc 0 295 movl %eax,%edi # remember ptd physical address 296#ifdef dubious 297 orl $ PG_V|PG_URKW,%eax # having these bits set, 298 lea (0*NBPG)(%esi),%ebx # physical address of stack pt in proc 0 299 addl $(UPTEOFF*4),%ebx 300 addl $(UPAGES*4),%ebx 301 movl %eax,0(%ebx) 302#endif 303 304/* 305 * Construct a page table directory 306 * (of page directory elements - pde's) 307 */ 308 /* kernel pde's */ 309 movl $_Sysmap-SYSTEM,%eax # physical address of kernel page table 310 orl $ PG_V,%eax # pde entry is valid 311 movl $ Npdes,%ecx # for this many pde s, 312 movl %edi,%ebx # phys address of ptd in proc 0 313 addl $(SYSPDROFF*4), %ebx # offset of pde for kernel 3141: movl %eax,0(%ebx) 315 addl $ NBPG,%eax # increment physical address 316 addl $4,%ebx # next pde 317 loop 1b 318 # install a pde for temporary double map 319 movl $_Sysmap+4096-SYSTEM,%eax # physical address of temp page table 320 # movl $_Sysmap-SYSTEM,%eax # physical address of temp page table 321 orl $ PG_V,%eax # pde entry is valid 322 movl %edi,%ebx # phys address of ptd in proc 0 323 movl %eax,0(%ebx) # which is where temp maps! 324 # install a pde to map _u for proc 0 325 lea (0*NBPG)(%esi),%eax # physical address of pt in proc 0 326 orl $ PG_V,%eax # pde entry is valid 327 movl %edi,%ebx # phys address of ptd in proc 0 328 addl $(UPDROFF*4), %ebx # offset of pde for kernel 329 movl %eax,0(%ebx) # which is where _u maps! 330 331 movl %edi,%eax # phys address of ptd in proc 0 332 orl $ I386_CR3PAT,%eax 333 movl %eax,%cr3 # load ptd addr into mmu 334 movl %cr0,%eax # get control word 335 orl $0x80000001,%eax # and let s page! 336 movl %eax,%cr0 # NOW! 337 338 pushl $begin # jump to high mem! 339 ret # jmp $begin does not work 340begin: 341 movl $_Sysbase,%eax # kernel stack just below system 342 movl %eax,%esp 343 xorl %eax,%eax # mark end of frames 344 movl %eax,%ebp 345 346 movl _Crtat,%eax # initialize Crt video ram address 347 subl $ IOPHYSmem,%eax 348 addl $_atdevbase,%eax 349 movl %eax,_Crtat 350 351 call _init386 # wire 386 chip for unix operation 352 353/* initialize (slightly) the pcb */ 354 movl $_u,%eax # proc0 u-area 355 movl $_usrpt,%ecx 356 movl %ecx,PCB_P0BR(%eax) # p0br: SVA of text/data user PT 357 xorl %ecx,%ecx 358 movl %ecx,PCB_P0LR(%eax) # p0lr: 0 (doesn t really exist) 359 movl $_usrpt+NBPG,%ecx # addr of end of PT 360 subl $ P1PAGES*4,%ecx # backwards size of P1 region 361 movl %ecx,PCB_P1BR(%eax) # p1br: P1PAGES from end of PT 362 movl $ P1PAGES-UPAGES,PCB_P1LR(%eax) # p1lr: vax style 363 movl $ CLSIZE,PCB_SZPT(%eax) # page table size 364 movl %edi,PCB_CR3(%eax) 365 pushl %edi # cr3 366 movl %esi,%eax 367 addl $(UPAGES*NBPG)+NBPG+NBPG+NBPG,%eax 368 shrl $ PGSHIFT,%eax 369 pushl %eax # firstaddr 370 371 pushl $20 # install signal trampoline code 372 pushl $_u+PCB_SIGC 373 pushl $sigcode 374 call _bcopy 375 addl $12,%esp 376 377 call _main 378 379 .globl __ucodesel,__udatasel 380 movzwl __ucodesel,%eax 381 movzwl __udatasel,%ecx 382 # build outer stack frame 383 pushl %ecx # user ss 384 pushl $_u # user esp 385 pushl %eax # user cs 386 pushl $0 # user ip 387 movw %cx,%ds 388 movw %cx,%es 389 movw %ax,%fs # double map cs to fs 390 movw %cx,%gs # and ds to gs 391 lret # goto user! 392 393 .globl __exit 394__exit: 395 call _reset_cpu 396 lidt xaxa # invalidate interrupt descriptor 397 movl $0,%esp # hardware "freeze" fault 398 ret 399xaxa: .long 0,0 400 401 .set exec,11 402 .set exit,1 403 .globl _icode 404 .globl _initflags 405 .globl _szicode 406/* gas fucks up offset -- */ 407#define LCALL(x,y) .byte 0x9a ; .long y; .word x 408/* 409 * Icode is copied out to process 1 to exec /etc/init. 410 * If the exec fails, process 1 exits. 411 */ 412_icode: 413 # pushl $argv-_icode 414 movl $argv,%eax 415 subl $_icode,%eax 416 pushl %eax 417 418 # pushl $init-_icode 419 movl $init,%eax 420 subl $_icode,%eax 421 pushl %eax 422 pushl %eax # dummy out rta 423 424 movl %esp,%ebp 425 movl $exec,%eax 426 LCALL(0x7,0x0) 427 pushl %eax 428 movl $exit,%eax 429 pushl %eax # dummy out rta 430 LCALL(0x7,0x0) 431 432init: .asciz "/sbin/init" 433 .align 2 434_initflags: 435 .long 0 436argv: .long init-_icode 437 .long _initflags-_icode 438 .long 0 439_szicode: 440 .long _szicode-_icode 441sigcode: 442 movl 12(%esp),%eax # unsure if call will dec stack 1st 443 call %eax 444 xorl %eax,%eax # smaller movl $103,%eax 445 movb $103,%al # sigreturn() 446 LCALL(0x7,0) # enter kernel with args on stack 447 hlt # never gets here 448 449 450 .globl ___udivsi3 451___udivsi3: 452 movl 4(%esp),%eax 453 xorl %edx,%edx 454 divl 8(%esp) 455 ret 456 457 .globl ___divsi3 458___divsi3: 459 movl 4(%esp),%eax 460 xorl %edx,%edx 461 cltd 462 idivl 8(%esp) 463 ret 464 465 .globl _inb 466_inb: movl 4(%esp),%edx 467 subl %eax,%eax # clr eax 468 NOP 469 inb %dx,%al 470 NOP 471 ret 472 473 .globl _outb 474_outb: movl 4(%esp),%edx 475 movl 8(%esp),%eax 476 NOP 477 outb %al,%dx 478 NOP 479 ret 480 481 # 482 # bzero (base,cnt) 483 # 484 485 .globl _bzero 486 .globl _blkclr 487_bzero: 488_blkclr: 489 pushl %edi 490 movl 8(%esp),%edi 491 movl 12(%esp),%ecx 492 xorl %eax,%eax 493 shrl $2,%ecx 494 cld 495 rep 496 stosl 497 movl 12(%esp),%ecx 498 andl $3,%ecx 499 rep 500 stosb 501 popl %edi 502 ret 503 504 # 505 # fillw (pat,base,cnt) 506 # 507 508 .globl _fillw 509_fillw: 510 pushl %edi 511 movl 8(%esp),%eax 512 movl 12(%esp),%edi 513 movl 16(%esp),%ecx 514 # xorl %eax,%eax 515 cld 516 rep 517 stosw 518 popl %edi 519 ret 520 521 # 522 # bcopy (src,dst,cnt) 523 # NOTE: does not (yet) handle overlapped copies 524 # 525 526 .globl _bcopy 527_bcopy: 528 pushl %esi 529 pushl %edi 530 movl 12(%esp),%esi 531 movl 16(%esp),%edi 532 movl 20(%esp),%ecx 533 shrl $2,%ecx 534 cld 535 rep 536 movsl 537 movl 20(%esp),%ecx 538 andl $3,%ecx 539 rep 540 movsb 541 popl %edi 542 popl %esi 543 xorl %eax,%eax 544 ret 545 546 .globl _copyout 547_copyout: 548 movl $cpyflt,_nofault # in case we page/protection violate 549 pushl %esi 550 pushl %edi 551 movl 12(%esp),%esi 552 movl 16(%esp),%edi 553 movl 20(%esp),%ecx 554 shrl $2,%ecx 555 cld 556 rep 557 movsl 558 movl 20(%esp),%ecx 559 andl $3,%ecx 560 rep 561 movsb 562 popl %edi 563 popl %esi 564 xorl %eax,%eax 565 movl %eax,_nofault 566 ret 567 568 .globl _copyin 569_copyin: 570 movl $cpyflt,_nofault # in case we page/protection violate 571 pushl %esi 572 pushl %edi 573 movl 12(%esp),%esi 574 movl 16(%esp),%edi 575 movl 20(%esp),%ecx 576 shrl $2,%ecx 577 cld 578 rep 579 movsl 580 movl 20(%esp),%ecx 581 andl $3,%ecx 582 rep 583 movsb 584 popl %edi 585 popl %esi 586 xorl %eax,%eax 587 movl %eax,_nofault 588 ret 589 590cpyflt: popl %edi 591 popl %esi 592 xorl %eax,%eax 593 movl %eax,_nofault 594 movl $ EFAULT,%eax 595 ret 596 597 # insb(port,addr,cnt) 598 .globl _insb 599_insb: 600 pushl %edi 601 movw 8(%esp),%dx 602 movl 12(%esp),%edi 603 movl 16(%esp),%ecx 604 cld 605 NOP 606 rep 607 insb 608 NOP 609 movl %edi,%eax 610 popl %edi 611 ret 612 613 # insw(port,addr,cnt) 614 .globl _insw 615_insw: 616 pushl %edi 617 movw 8(%esp),%dx 618 movl 12(%esp),%edi 619 movl 16(%esp),%ecx 620 cld 621 NOP 622 .byte 0x66,0xf2,0x6d # rep insw 623 NOP 624 movl %edi,%eax 625 popl %edi 626 ret 627 628 # outsw(port,addr,cnt) 629 .globl _outsw 630_outsw: 631 pushl %esi 632 movw 8(%esp),%dx 633 movl 12(%esp),%esi 634 movl 16(%esp),%ecx 635 cld 636 NOP 637 .byte 0x66,0xf2,0x6f # rep outsw 638 NOP 639 movl %esi,%eax 640 popl %esi 641 ret 642 643 # lgdt(*gdt, ngdt) 644 .globl _lgdt 645 # .globl _gdt 646xxx: .word 31 647 .long 0 648_lgdt: 649 movl 4(%esp),%eax 650 movl %eax,xxx+2 651 movl 8(%esp),%eax 652 movw %ax,xxx 653 lgdt xxx 654 jmp 1f 655 NOP 6561: movw $0x10,%ax 657 movw %ax,%ds 658 movw %ax,%es 659 movw %ax,%ss 660 movl 0(%esp),%eax 661 pushl %eax 662 movl $8,4(%esp) 663 lret 664 665 # lidt(*idt, nidt) 666 .globl _lidt 667yyy: .word 255 668 .long 0 669_lidt: 670 movl 4(%esp),%eax 671 movl %eax,yyy+2 672 movl 8(%esp),%eax 673 movw %ax,yyy 674 lidt yyy 675 ret 676 677 # lldt(sel) 678 .globl _lldt 679_lldt: 680 movl 4(%esp),%eax 681 lldt %eax 682 ret 683 684 # ltr(sel) 685 .globl _ltr 686_ltr: 687 movl 4(%esp),%eax 688 ltr %eax 689 ret 690 691 # lcr3(cr3) 692 .globl _lcr3 693 .globl _load_cr3 694_load_cr3: 695_lcr3: 696 movl 4(%esp),%eax 697 orl $ I386_CR3PAT,%eax 698 movl %eax,%cr3 699 movl %cr3,%eax 700 ret 701 702 # lcr0(cr0) 703 .globl _lcr0 704_lcr0: 705 movl 4(%esp),%eax 706 movl %eax,%cr0 707 ret 708 709 # rcr0() 710 .globl _rcr0 711_rcr0: 712 movl %cr0,%eax 713 ret 714 715 # rcr2() 716 .globl _rcr2 717_rcr2: 718 movl %cr2,%eax 719 ret 720 721 # rcr3() 722 .globl _rcr3 723 .globl __cr3 724__cr3: 725_rcr3: 726 movl %cr3,%eax 727 ret 728 729 # ssdtosd(*ssdp,*sdp) 730 .globl _ssdtosd 731_ssdtosd: 732 pushl %ebx 733 movl 8(%esp),%ecx 734 movl 8(%ecx),%ebx 735 shll $16,%ebx 736 movl (%ecx),%edx 737 roll $16,%edx 738 movb %dh,%bl 739 movb %dl,%bh 740 rorl $8,%ebx 741 movl 4(%ecx),%eax 742 movw %ax,%dx 743 andl $0xf0000,%eax 744 orl %eax,%ebx 745 movl 12(%esp),%ecx 746 movl %edx,(%ecx) 747 movl %ebx,4(%ecx) 748 popl %ebx 749 ret 750 751/* 752 * {fu,su},{byte,word} 753 */ 754ALTENTRY(fuiword) 755ENTRY(fuword) 756 movl $fusufault,_nofault # in case we page/protection violate 757 movl 4(%esp),%edx 758 .byte 0x65 # use gs 759 movl 0(%edx),%eax 760 xorl %edx,%edx 761 movl %edx,_nofault 762 ret 763 764ENTRY(fusword) 765 movl $fusufault,_nofault # in case we page/protection violate 766 movl 4(%esp),%edx 767 .byte 0x65 # use gs 768 movzwl 0(%edx),%eax 769 xorl %edx,%edx 770 movl %edx,_nofault 771 ret 772 773ALTENTRY(fuibyte) 774ENTRY(fubyte) 775 movl $fusufault,_nofault # in case we page/protection violate 776 movl 4(%esp),%edx 777 .byte 0x65 # use gs 778 movzbl 0(%edx),%eax 779 xorl %edx,%edx 780 movl %edx,_nofault 781 ret 782 783fusufault: 784 xorl %eax,%eax 785 movl %eax,_nofault 786 decl %eax 787 ret 788 789ALTENTRY(suiword) 790ENTRY(suword) 791 movl $fusufault,_nofault # in case we page/protection violate 792 movl 4(%esp),%edx 793 movl 8(%esp),%eax 794 .byte 0x65 # use gs 795 movl %eax,0(%edx) 796 xorl %eax,%eax 797 movl %eax,_nofault 798 ret 799 800ENTRY(susword) 801 movl $fusufault,_nofault # in case we page/protection violate 802 movl 4(%esp),%edx 803 movl 8(%esp),%eax 804 .byte 0x65 # use gs 805 movw %ax,0(%edx) 806 xorl %eax,%eax 807 movl %eax,_nofault 808 ret 809 810ALTENTRY(suibyte) 811ENTRY(subyte) 812 movl $fusufault,_nofault # in case we page/protection violate 813 movl 4(%esp),%edx 814 movl 8(%esp),%eax 815 .byte 0x65 # use gs 816 movb %eax,0(%edx) 817 xorl %eax,%eax 818 movl %eax,_nofault 819 ret 820 821 ALTENTRY(savectx) 822 ENTRY(setjmp) 823 movl 4(%esp),%eax 824 movl %ebx, 0(%eax) # save ebx 825 movl %esp, 4(%eax) # save esp 826 movl %ebp, 8(%eax) # save ebp 827 movl %esi,12(%eax) # save esi 828 movl %edi,16(%eax) # save edi 829 movl (%esp),%edx # get rta 830 movl %edx,20(%eax) # save eip 831 xorl %eax,%eax # return (0); 832 ret 833 834 ENTRY(longjmp) 835 movl 4(%esp),%eax 836 movl 0(%eax),%ebx # restore ebx 837 movl 4(%eax),%esp # restore esp 838 movl 8(%eax),%ebp # restore ebp 839 movl 12(%eax),%esi # restore esi 840 movl 16(%eax),%edi # restore edi 841 movl 20(%eax),%edx # get rta 842 movl %edx,(%esp) # put in return frame 843 xorl %eax,%eax # return (1); 844 incl %eax 845 ret 846/* 847 * The following primitives manipulate the run queues. 848 * _whichqs tells which of the 32 queues _qs 849 * have processes in them. Setrq puts processes into queues, Remrq 850 * removes them from queues. The running process is on no queue, 851 * other processes are on a queue related to p->p_pri, divided by 4 852 * actually to shrink the 0-127 range of priorities into the 32 available 853 * queues. 854 */ 855 856 .globl _whichqs,_qs,_cnt,_panic 857 .comm _noproc,4 858 .comm _runrun,4 859 860/* 861 * Setrq(p) 862 * 863 * Call should be made at spl6(), and p->p_stat should be SRUN 864 */ 865ENTRY(setrq) 866 movl 4(%esp),%eax 867 cmpl $0,P_RLINK(%eax) # should not be on q already 868 je set1 869 pushl $set2 870 call _panic 871set1: 872 movzbl P_PRI(%eax),%edx 873 shrl $2,%edx 874 btsl %edx,_whichqs # set q full bit 875 shll $3,%edx 876 addl $_qs,%edx # locate q hdr 877 movl %edx,P_LINK(%eax) # link process on tail of q 878 movl P_RLINK(%edx),%ecx 879 movl %ecx,P_RLINK(%eax) 880 movl %eax,P_RLINK(%edx) 881 movl %eax,P_LINK(%ecx) 882 ret 883 884set2: .asciz "setrq" 885 886/* 887 * Remrq(p) 888 * 889 * Call should be made at spl6(). 890 */ 891ENTRY(remrq) 892 movl 4(%esp),%eax 893 movzbl P_PRI(%eax),%edx 894 shrl $2,%edx 895 btrl %edx,_whichqs # clear full bit, panic if clear already 896 jb rem1 897 pushl $rem3 898 call _panic 899rem1: 900 pushl %edx 901 movl P_LINK(%eax),%ecx # unlink process 902 movl P_RLINK(%eax),%edx 903 movl %edx,P_RLINK(%ecx) 904 movl P_RLINK(%eax),%ecx 905 movl P_LINK(%eax),%edx 906 movl %edx,P_LINK(%ecx) 907 popl %edx 908 movl $_qs,%ecx 909 shll $3,%edx 910 addl %edx,%ecx 911 cmpl P_LINK(%ecx),%ecx # q still has something? 912 je rem2 913 shrl $3,%edx # yes, set bit as still full 914 btsl %edx,_whichqs 915rem2: 916 movl $0,P_RLINK(%eax) # zap reverse link to indicate off list 917 ret 918 919rem3: .asciz "remrq" 920sw0: .asciz "swtch" 921sw01: .asciz "swtch1" 922sw02: .asciz "swtch2" 923 924/* 925 * When no processes are on the runq, Swtch branches to idle 926 * to wait for something to come ready. 927 */ 928 .globl Idle 929Idle: 930idle: 931 call _spl0 932 cmpl $0,_whichqs 933 jne sw1 934 hlt # wait for interrupt 935 jmp idle 936 937badsw: 938 pushl $sw0 939 call _panic 940 /*NOTREACHED*/ 941 942/* 943 * Swtch() 944 */ 945ENTRY(swtch) 946 movw _cpl, %ax 947 movw %ax, _u+PCB_IML 948 movl $1,%eax 949 movl %eax,_noproc 950 incl _cnt+V_SWTCH 951sw1: 952 cli 953 bsfl _whichqs,%eax # find a full q 954 jz idle # if none, idle 955swfnd: 956 btrl %eax,_whichqs # clear q full status 957 jnb sw1 # if it was clear, look for another 958 pushl %eax # save which one we are using 959 shll $3,%eax 960 addl $_qs,%eax # select q 961 pushl %eax 962 963 cmpl P_LINK(%eax),%eax # linked to self? (e.g. not on list) 964 je badsw # not possible 965 movl P_LINK(%eax),%ecx # unlink from front of process q 966 movl P_LINK(%ecx),%edx 967 movl %edx,P_LINK(%eax) 968 movl P_RLINK(%ecx),%eax 969 movl %eax,P_RLINK(%edx) 970 971 popl %eax 972 popl %edx 973 cmpl P_LINK(%ecx),%eax # q empty 974 je sw2 975 btsl %edx,_whichqs # nope, indicate full 976sw2: 977 movl $0,%eax 978 movl %eax,_noproc 979 movl %eax,_runrun 980 cmpl $0,P_WCHAN(%ecx) 981 jne badsw 982 cmpb $ SRUN,P_STAT(%ecx) 983 jne badsw 984 movl %eax,P_RLINK(%ecx) 985 986 movl P_ADDR(%ecx),%edx 987 movl (%edx),%eax 988 movl %eax,_Swtchmap 989 # movl 4(%edx),%eax 990 # movl %eax,_Swtchmap+4 991 # movl %cr3,%eax 992 # movl %eax,%cr3 993 movl _Swtchbase+PCB_CR3,%edx 994 995/* switch to new process. first, save context as needed */ 996 997 movl $_u,%ecx 998 999 movl (%esp),%eax # Hardware registers 1000 movl %eax, PCB_EIP(%ecx) 1001 movl %ebx, PCB_EBX(%ecx) 1002 movl %esp, PCB_ESP(%ecx) 1003 movl %ebp, PCB_EBP(%ecx) 1004 movl %esi, PCB_ESI(%ecx) 1005 movl %edi, PCB_EDI(%ecx) 1006 1007 fsave PCB_SAVEFPU(%ecx) 1008 1009 movl _CMAP2,%eax # save temporary map PTE 1010 movl %eax,PCB_CMAP2(%ecx) # in our context 1011 1012 orl $ I386_CR3PAT,%edx 1013 movl %edx,%cr3 # context switch 1014 1015 movl $_u,%ecx 1016 1017/* restore context */ 1018 movl PCB_EBX(%ecx), %ebx 1019 movl PCB_ESP(%ecx), %esp 1020 movl PCB_EBP(%ecx), %ebp 1021 movl PCB_ESI(%ecx), %esi 1022 movl PCB_EDI(%ecx), %edi 1023 movl PCB_EIP(%ecx), %eax 1024 movl %eax, (%esp) 1025 1026 frstor PCB_SAVEFPU(%ecx) 1027 1028 movl PCB_CMAP2(%ecx),%eax # get temporary map 1029 movl %eax,_CMAP2 # reload temporary map PTE 1030#ifdef FPUNOTYET 1031#endif 1032 cmpl $0,PCB_SSWAP(%ecx) # do an alternate return? 1033 jne res3 # yes, go reload regs 1034 1035 # pushl PCB_IML(%ecx) 1036 # call _splx 1037 # popl %eax 1038 call _spl0 1039 movl $0,%eax 1040 ret 1041 1042res3: 1043 xorl %eax,%eax # inline restore context 1044 xchgl PCB_SSWAP(%ecx),%eax # addr of saved context, clear it 1045 1046 movl 0(%eax),%ebx # restore ebx 1047 movl 4(%eax),%esp # restore esp 1048 movl 8(%eax),%ebp # restore ebp 1049 movl 12(%eax),%esi # restore esi 1050 movl 16(%eax),%edi # restore edi 1051 movl 20(%eax),%edx # get rta 1052 movl %edx,(%esp) # put in return frame 1053 1054 # call _spl0 1055 pushl _u+PCB_IML 1056 call _splx 1057 popl %eax 1058 1059 xorl %eax,%eax # return (1); 1060 incl %eax 1061 ret 1062 1063/* 1064 * Resume(p_addr) 1065 * current just used to fillout u. tss so fork can fake a return to swtch 1066 * [ all thats really needed is esp and eip ] 1067 */ 1068ENTRY(resume) 1069 # movl 4(%esp),%ecx 1070 movl $_u,%ecx 1071 movw _cpl, %ax 1072 movw %ax, PCB_IML(%ecx) 1073 movl (%esp),%eax 1074 movl %eax, PCB_EIP(%ecx) 1075 movl %ebx, PCB_EBX(%ecx) 1076 movl %esp, PCB_ESP(%ecx) 1077 movl %ebp, PCB_EBP(%ecx) 1078 movl %esi, PCB_ESI(%ecx) 1079 movl %edi, PCB_EDI(%ecx) 1080#ifdef FPUNOTYET 1081#endif 1082 fsave PCB_SAVEFPU(%ecx) 1083 movl $0,%eax 1084 ret 1085 1086 1087.data 1088 .globl _cyloffset 1089_cyloffset: .long 0 1090 .globl _nofault 1091_nofault: .long 0 1092.text 1093 # To be done: 1094 .globl _addupc 1095 .globl _astoff 1096 .globl _doadump 1097 .globl _inittodr 1098 .globl _physaddr 1099_addupc: 1100 .byte 0xcc 1101_astoff: 1102 ret 1103_doadump: 1104 .byte 0xcc 1105_physaddr: 1106 .byte 0xcc 1107 1108#define IDTVEC(name) .align 4; .globl _X/**/name; _X/**/name: 1109/*#define PANIC(msg) xorl %eax,%eax; movl %eax,_waittime; pushl 1f; \ 1110 call _panic; 1: .asciz msg*/ 1111#define PRINTF(n,msg) pushal ; pushl 1f; call _printf; MSG(msg) ; popl %eax ; popal 1112#define MSG(msg) .data; 1: .asciz msg; .text 1113 1114 .text 1115 1116/* 1117 * Trap and fault vector routines 1118 */ 1119#define TRAP(a) pushl $ a; jmp alltraps 1120 1121IDTVEC(div) 1122 pushl $0; TRAP(T_DIVIDE) 1123IDTVEC(dbg) 1124 pushl $0; TRAP(T_TRCTRAP) 1125IDTVEC(nmi) 1126 pushl $0; TRAP(T_NMI) 1127IDTVEC(bpt) 1128 pushl $0; TRAP(T_BPTFLT) 1129IDTVEC(ofl) 1130 pushl $0; TRAP(T_OFLOW) 1131IDTVEC(bnd) 1132 pushl $0; TRAP(T_BOUND) 1133IDTVEC(ill) 1134 pushl $0; TRAP(T_PRIVINFLT) 1135IDTVEC(dna) 1136 pushl $0; TRAP(T_DNA) 1137IDTVEC(dble) 1138 TRAP(T_DOUBLEFLT) 1139 /*PANIC("Double Fault");*/ 1140IDTVEC(fpusegm) 1141 pushl $0; TRAP(T_FPOPFLT) 1142IDTVEC(tss) 1143 TRAP(T_TSSFLT) 1144 /*PANIC("TSS not valid");*/ 1145IDTVEC(missing) 1146 TRAP(T_SEGNPFLT) 1147IDTVEC(stk) 1148 TRAP(T_STKFLT) 1149IDTVEC(prot) 1150 TRAP(T_PROTFLT) 1151IDTVEC(page) 1152 TRAP(T_PAGEFLT) 1153IDTVEC(rsvd) 1154 pushl $0; TRAP(T_RESERVED) 1155IDTVEC(fpu) 1156 pushl $0; TRAP(T_ARITHTRAP) 1157 /* 17 - 31 reserved for future exp */ 1158IDTVEC(rsvd0) 1159 pushl $0; TRAP(17) 1160IDTVEC(rsvd1) 1161 pushl $0; TRAP(18) 1162IDTVEC(rsvd2) 1163 pushl $0; TRAP(19) 1164IDTVEC(rsvd3) 1165 pushl $0; TRAP(20) 1166IDTVEC(rsvd4) 1167 pushl $0; TRAP(21) 1168IDTVEC(rsvd5) 1169 pushl $0; TRAP(22) 1170IDTVEC(rsvd6) 1171 pushl $0; TRAP(23) 1172IDTVEC(rsvd7) 1173 pushl $0; TRAP(24) 1174IDTVEC(rsvd8) 1175 pushl $0; TRAP(25) 1176IDTVEC(rsvd9) 1177 pushl $0; TRAP(26) 1178IDTVEC(rsvd10) 1179 pushl $0; TRAP(27) 1180IDTVEC(rsvd11) 1181 pushl $0; TRAP(28) 1182IDTVEC(rsvd12) 1183 pushl $0; TRAP(29) 1184IDTVEC(rsvd13) 1185 pushl $0; TRAP(30) 1186IDTVEC(rsvd14) 1187 pushl $0; TRAP(31) 1188 1189alltraps: 1190 pushal 1191 push %ds 1192 push %es 1193 movw $0x10,%ax 1194 movw %ax,%ds 1195 movw %ax,%es 1196 incl _cnt+V_TRAP 1197 call _trap 1198 1199#ifdef junk 1200 cmpl $0xfc000000,12*4(%esp) # is it a user pc 1201 ja 1f 1202 cmpw $0x1f,13*4(%esp) # is it a user cs 1203 je 1f 1204 .data ; lx: .asciz "t user cs %x?" ; .text 12052: 1206 movl 13*4(%esp),%eax 1207 pushl %eax 1208 pushl $lx 1209 call _pg 1210 popl %eax ; popl %eax 1211 jmp 2b 12121: 1213#endif junk 1214 1215 pop %es 1216 pop %ds 1217 popal 1218 addl $8,%esp # pop type, code 1219 iret 1220 1221/* 1222 * Call gate entry for syscall 1223 */ 1224 1225IDTVEC(syscall) 1226 pushfl # only for stupid carry bit and more stupid wait3 cc kludge 1227 pushal # only need eax,ecx,edx - trap resaves others 1228 movw $0x10,%ax # switch to kernel segments 1229 movw %ax,%ds 1230 movw %ax,%es 1231 call _syscall 1232 1233#ifdef notdef 1234 cmpw $0x1f,10*4(%esp) # is user cs what it should be? 1235 jz 1f 1236 .data ; lz: .asciz "s user cs %x?" ; .text 12372: 1238 movl 10*4(%esp),%eax 1239 pushl %eax 1240 pushl $lz 1241 call _pg 1242 jmp 2b 12431: 1244#endif 1245 1246 movw __udatasel,%ax # switch back to user segments 1247 movw %ax,%ds 1248 movw %ax,%es 1249 popal 1250 popfl 1251 lret # back we go, we hope! 1252 1253ENTRY(htonl) 1254ENTRY(ntohl) 1255 movl 4(%esp),%eax 1256 xchgb %al,%ah 1257 roll $16,%eax 1258 xchgb %al,%ah 1259 ret 1260 1261ENTRY(htons) 1262ENTRY(ntohs) 1263 movzwl 4(%esp),%eax 1264 xchgb %al,%ah 1265 ret 1266