|
|
1.1 ! root 1: .unixorder ! 2: .llen 132 ! 3: .include as.inc ! 4: ! 5: IODELAY .macro ! 6: jmp .+2 / DELAY ! 7: jmp .+2 / DELAY ! 8: .endm ! 9: ! 10: / Most places where %cr3 is refreshed, it can be done through a Ring 0 gate. ! 11: MMUUPD .macro ! 12: pushfl ! 13: cli ! 14: lcall $SEG_MMUUPD,$0 / gate to mmuupdfR0 ! 15: popfl ! 16: .endm ! 17: ! 18: / ! 19: / USTART and ESP_START map kernel stack and u area within top 4k page ! 20: / of virtual space. ! 21: / NDP context starts 0x100 bytes below u area. ! 22: / See also U_OFFSET, NDP_OFFSET in uproc.h ! 23: / ! 24: .set USTART,0xFFFFFB00 ! 25: .set ESP0_START,0xFFFFF300 ! 26: .set ESP1_START,USTART ! 27: ! 28: .set u,USTART ! 29: .set PSW_VAL,0x1200 / set system IOPL to 1, enable IRQ ! 30: / .set PSW_VAL,0x3200 / set system IOPL to 3, enable IRQ ! 31: ! 32: / (lgl- ! 33: / The information contained herein is a trade secret of Mark Williams ! 34: / Company, and is confidential information. It is provided under a ! 35: / license agreement, and may be copied or disclosed only under the ! 36: / terms of that agreement. Any reproduction or disclosure of this ! 37: / material without the express written authorization of Mark Williams ! 38: / Company or persuant to the license agreement is unlawful. ! 39: ! 40: / Copyright (c) 1982, 1992. ! 41: / An unpublished work by Mark Williams Company, Chicago. ! 42: / All rights reserved. ! 43: ! 44: / Intel 386 port and extensions ! 45: / Copyright (c) Ciaran O'Donnell, Bievres (FRANCE), 1991 ! 46: / -lgl) ! 47: / ! 48: / $Log: as.s,v $ ! 49: / Revision 2.3 93/07/26 13:55:44 nigel ! 50: / Nigel's R80 ! 51: / ! 52: / Revision 1.17 92/12/08 16:43:10 root ! 53: / ker 70 ! 54: / ! 55: / Revision 1.16 92/11/12 10:04:31 root ! 56: / Ker #68 ! 57: / ! 58: / Revision 1.15 92/11/09 17:08:28 root ! 59: / Just before adding vio segs. ! 60: / ! 61: / Revision 1.13 92/10/06 23:47:48 root ! 62: / Ker #64 ! 63: / ! 64: / Revision 1.12 92/10/06 20:45:40 root ! 65: / Ker #63d ! 66: / ! 67: / Revision 1.10 92/07/27 18:15:43 hal ! 68: / Kernel #59 ! 69: / ! 70: / Revision 1.9 92/07/16 16:38:14 hal ! 71: / Kernel #58 ! 72: / ! 73: / Revision 1.8 92/07/15 13:50:55 root ! 74: / COH 4.0.0 ! 75: / ! 76: / Revision 1.6 92/04/03 11:05:28 hal ! 77: / Fix missed IRQ bug. ! 78: / Add read_t0(), read_psw(), getusd(), putusd(). ! 79: / ! 80: ! 81: /////// ! 82: / Machine language assist for ! 83: / Intel 80386/80486 Coherent. This contains the parts ! 84: / that are common to all machines as well as the machine-specific code ! 85: / for the IBM PC-386 ! 86: ! 87: ! 88: /////// ! 89: ! 90: / System entry point. ! 91: ! 92: / When this code is entered, the boot program has done the following: ! 93: / Relocate itself above where the kernel will be (e.g., 0x20600). ! 94: / Load as.s binary; text at 0x02000, data at next paragraph (16-byte) ! 95: / boundary at or beyond end of kernel text. ! 96: / CS = 0x02000 <- start of kernel text ("physical" stext) ! 97: / ES = 0x02xxx <- start of kernel data ! 98: / SS,DS = 0x20xxx <- ....some address in boot data space.... ! 99: ! 100: / Due to the way the kernel has been linked (see ld.master), symbol "stext" ! 101: / has a value of 0xFFC0_0000, which is the start of the last 4 meg segment. ! 102: / This value is the address in linear space once we have entered paging mode, ! 103: / but until that time relocation arithmetic is necessary: ! 104: / ! 105: / Before segmentation is turned on, symbols in kernel text or data space ! 106: / must be relocated by -SBASE<<BPCSHIFT for memory reference instructions ! 107: / to work. ! 108: ! 109: /////// ! 110: ! 111: stext: / kernel code starts at stext+0x100 ! 112: .org .+0x100 / reserve stack space ! 113: cli / No interrupts, please. ! 114: ! 115: / put up a debugging "!" on the screen. We can still use the BIOS. ! 116: push %si / Save registers. ! 117: push %di ! 118: ! 119: movb $'!', %al ! 120: ! 121: movw $0x0007, %bx / Page 0, white on black ! 122: movb $0x0E, %ah / Write TTY. ! 123: int $VIDEO / Call video I/O in ROM. ! 124: pop %di ! 125: pop %si ! 126: ! 127: / equipment status word to AX ! 128: int $0x11 / Obtain int 11 value before printf(). ! 129: movl %eax,%ecx / esw -> cx ! 130: ! 131: / val11 is a long, initially zero, in the CS. ! 132: / copy (long)esw to val11 ! 133: .byte PX_ADDR / 32-bit address ! 134: .byte PX_OPND / 32-bit operand ! 135: movl %ecx,%cs:[[-SBASE]<<BPCSHIFT]+val11 ! 136: ! 137: / last use of boot block's stack ! 138: .byte PX_ADDR / 32-bit address ! 139: .byte PX_OPND / 32-bit operand ! 140: lgdtl %cs:[[-SBASE]<<BPCSHIFT]+gdtinit ! 141: ! 142: / turn on lsbit of cr0 - Protection Enable ! 143: mov %cr0,%eax ! 144: orb $1,%al ! 145: mov %eax,%cr0 ! 146: ! 147: / intersegment jump (48-bit address) ! 148: / jumping flushes the cache... ! 149: / ! 150: .byte PX_OPND ! 151: ljmp $SEG_386_II, $next ! 152: ! 153: next: ! 154: movw $SEG_386_ID, %ax ! 155: movw %ax, %ds ! 156: movw %ax, %es ! 157: movw %ax, %ss ! 158: movw $SEG_386_UD|R_USR, %ax ! 159: movw %ax, %fs ! 160: mov $stext+0x100,%eax / 256 byte stack for initialization ! 161: mov %eax,%esp ! 162: ! 163: / Enable the A20 address line, which is normally disabled by the ROM BIOS. ! 164: / This line is under the control of the 8042 keyboard interface controller. ! 165: ! 166: sub %ecx, %ecx ! 167: loc0: inb $KBCTRL / Wait for 8042 input buffer to empty. ! 168: testb $2,%al ! 169: loopne loc0 ! 170: IODELAY ! 171: ! 172: movb $0xD1, %al / Request next output byte to be ! 173: outb $KBCTRL / sent to the 8042 output port. ! 174: IODELAY ! 175: ! 176: sub %ecx, %ecx ! 177: loc1: inb $KBCTRL / Wait for 8042 input buffer to empty. ! 178: testb $2, %al ! 179: loopne loc1 ! 180: IODELAY ! 181: ! 182: movb $0xDF,%al / Enable A20 address line. ! 183: outb $KBDATA / See Page 1-44, IBM-AT Tech Ref. ! 184: IODELAY ! 185: ! 186: sub %ecx, %ecx ! 187: loc2: inb $KBCTRL / Wait for 8042 input buffer to empty. ! 188: testb $2,%al / NOTE: A20 not enabled for up to 20 us. ! 189: loopne loc2 ! 190: ! 191: ! 192: / Reprogram the 8253 timer so that channel 0, ! 193: / which is used as the clock, interrupts at exactly ! 194: / 100 HZ, instead of 18.2 HZ. ! 195: ! 196: movb $0x36,%al / Timer 0, LSB, MSB, mode 3 ! 197: outb $PIT+3 ! 198: IODELAY ! 199: movb $0x9C,%al / Lsb of 59659/5 = 11932 ! 200: outb $PIT ! 201: IODELAY ! 202: movb $0x2E,%al / Msb of 59659/5 = 11932 ! 203: outb $PIT ! 204: IODELAY ! 205: ! 206: / Reprogram the 1st programmable interrupt controller. ! 207: / Its default vector table collides with iAPX 286 protection vectors. ! 208: movb $0x11,%al / ICW1 - edge, ICW4 ! 209: outb $PIC ! 210: IODELAY ! 211: movb $0x20,%al / ICW2 - Reserve 1st 32 vectors for 286 ! 212: outb $PICM ! 213: IODELAY ! 214: movb $0x04,%al / ICW3 - master level 2 ! 215: outb $PICM ! 216: IODELAY ! 217: movb $0x01,%al / ICW4 - 8086 mode, master. ! 218: outb $PICM ! 219: IODELAY ! 220: ! 221: / NIGEL: The original code here (and related code in "i386/md.c") turned off ! 222: / the chain bit in the first PIC by default (and at every subsequent ! 223: / opportunity) even though all the mask bits in the slave PIC are set to off. ! 224: / In order to support an enhanced interrupt architecture for the STREAMS and ! 225: / DDI/DDK subsystems I want to remove the state knowledge from the code in ! 226: / "i386/md.c" so that the chain bit is always left on. ! 227: / In order to do this, I have modified the startup code below so that the ! 228: / system by default allows the slave PIC to interrupt (of course, it still ! 229: / won't interrupt unless it is enabled to; the masking I have removed was ! 230: / totally redundant). ! 231: ! 232: movb $0xFA,%al / Disable interrupts from master PIC. ! 233: outb $PICM / (except for clock and slave PIC interrupt). ! 234: ! 235: movb $0x11,%al / ICW1 - edge, ICW4 ! 236: outb $SPIC ! 237: IODELAY ! 238: movb $0x70,%al / ICW2 - slave starts at 0x70th interrupt ! 239: outb $SPICM ! 240: IODELAY ! 241: movb $0x02,%al / ICW3 - master level 2 ! 242: outb $SPICM ! 243: IODELAY ! 244: movb $0x01,%al / ICW4 - 8086 mode. ! 245: outb $SPICM ! 246: IODELAY ! 247: movb $0xFF,%al ! 248: outb $SPICM / Disable interrupts from slave PIC. ! 249: /DEBUG ! 250: xor %ebp, %ebp / Halt stack backtraces ! 251: cli ! 252: call __cinit ! 253: call mchinit / C initialization ! 254: mov %cr0,%eax / Turn on paging ! 255: / use 80000001 to allow FP ! 256: / or $0x80000001,%eax ! 257: / use 80000005 to disallow FP ! 258: or $0x80000005,%eax ! 259: mov %eax,%cr0 ! 260: ljmp $SEG_RNG0_TXT,$loc3 / clear pipeline; jump far, direct ! 261: ! 262: / ! 263: / Ring 0 startup code ! 264: / ! 265: loc3: ! 266: movw $SEG_386_KD, %ax ! 267: movw %ax, %ds ! 268: movw $SEG_RNG0_STK, %ax ! 269: movw %ax, %ss ! 270: movl $ESP0_START,%esp / Stack pointer for init ! 271: clts / Clear task switched flag. ! 272: ! 273: / Call the machine setup code. ! 274: / Call Coherent main. ! 275: / On return, send control off to the user ! 276: / at its entry point. ! 277: ! 278: sub %eax, %eax / Load local descriptor table register. ! 279: lldt %ax ! 280: ! 281: / movw $tss,%ax / Fix low 16 bits of tss base in gdt ! 282: / movw %ax,gdt+SEG_TSS+2 ! 283: ! 284: / Fix tss base in gdt ! 285: movl $tss,%eax ! 286: movw %ax,gdt+SEG_TSS+2 / Fix bits 0..15 ! 287: rorl $16,%eax / Get tss bits 16..31 ! 288: movb %al,gdt+SEG_TSS+4 / Fix bits 16..23 ! 289: movb %ah,gdt+SEG_TSS+7 / Fix bits 24..31 ! 290: ! 291: movw $SEG_TSS,%ax / Load task state segment register. ! 292: ltr %ax ! 293: lidt idtmap / Load interrupt descriptor table ! 294: lgdt gdtmap ! 295: ! 296: / movw $ldt,%ax / Relocate ldt in gdt ! 297: / movw %ax,gdt+SEG_LDT+2 ! 298: ! 299: / Fix ldt base in gdt ! 300: movl $ldt,%eax ! 301: movw %ax,gdt+SEG_LDT+2 / Fix bits 0..15 ! 302: rorl $16,%eax / Get ldt bits 16..31 ! 303: movb %al,gdt+SEG_LDT+4 / Fix bits 16..23 ! 304: movb %ah,gdt+SEG_LDT+7 / Fix bits 24..31 ! 305: ! 306: movw $SEG_LDT,%ax ! 307: lldt %ax ! 308: ! 309: call i8086 / i8086() does fixup of tss_sp0 ! 310: ! 311: / ! 312: / Enter Ring 1 kernel from Ring 0 ! 313: / ! 314: push $SEG_RNG1_STK / SS ! 315: push $ESP1_START / ESP ! 316: push $PSW_VAL / PSW ! 317: push $SEG_RNG1_TXT / CS ! 318: push $__xmain__ / IP ! 319: movw $SEG_386_KD, %ax / DS, ES ! 320: movw %ax, %ds / Map data segment ! 321: movw %ax, %es / Map extra segment ! 322: iret / Go to ring 1 ! 323: ! 324: / ! 325: / Start of Ring 1 kernel. ! 326: / Need Ring 1 because interrupts are about to turn on, and all irpt gates ! 327: / have DPL (descriptor privilege level) 1. ! 328: / ! 329: __xmain__: ! 330: sti / Interrupts on, and ! 331: call main / call Coherent mainline. ! 332: cli / Interrupts off. ! 333: ! 334: / ! 335: / Enter User mode from Ring 1 kernel ! 336: / ! 337: push $SEG_386_UD|R_USR / SS ! 338: push $NBPC / ESP ! 339: push $PSW_VAL / PSW ! 340: push $SEG_386_UI|R_USR / CS ! 341: push $0 / IP ! 342: movw $SEG_386_UD|R_USR, %ax / DS, ES ! 343: movw %ax, %ds / Map data segment ! 344: movw %ax, %es / Map extra segment ! 345: iret / Go to user state. ! 346: ! 347: /////// ! 348: / ! 349: / Trap and interrupt save. ! 350: / ! 351: / This version of tsave runs from Ring 1 trap/irpt gates. ! 352: / ! 353: /////// ! 354: .globl disflag ! 355: ! 356: tsave: / What level of interrupt ? ! 357: pusha ! 358: push %ds / Save current state ! 359: push %es ! 360: push %fs ! 361: push %gs ! 362: ! 363: xor %ebp, %ebp / Halt backtraces ! 364: ! 365: movw $SEG_386_KD, %ax / Map ds ! 366: movw %ax, %ds ! 367: movw %ax, %es ! 368: movw $SEG_386_UD|R_USR, %ax / Map es ! 369: movw %ax, %fs ! 370: ! 371: sti ! 372: icall X_TRAPNO(%esp) / and call the caller ! 373: cli ! 374: ! 375: / if got here from user mode or from idle process, call stand() ! 376: / else just do cleanup and return ! 377: ! 378: movb X_ERR+8(%esp),%al / trapped CS: user RPL? ! 379: andb $3,%al ! 380: cmpb $R_USR,%al ! 381: je tsave1a / jmp if user mode ! 382: cmpl $__idle__,X_ERR+4(%esp) / trapped EIP == idle process? ! 383: jnz tsave1b / Call stand() only if idle ! 384: movl $1,disflag ! 385: ! 386: tsave1a: ! 387: sti ! 388: call stand ! 389: tsave1b: ! 390: cli / No more interrupts ! 391: pop %gs / Restore ! 392: pop %fs ! 393: pop %es ! 394: pop %ds ! 395: popa ! 396: add $8,%esp / forget err, trapno ! 397: iret / Done. ! 398: ! 399: / ! 400: / Here is another version of tsave, called only from the GP vector (RING 0) ! 401: / ! 402: ! 403: BYPASS .macro addr ! 404: cmpl $addr,X_ERR+4(%esp) / trapped EIP ! 405: jz tsave0b ! 406: .endm ! 407: ! 408: tsave0: / What level of interrupt ? ! 409: pusha ! 410: push %ds / Save current state ! 411: push %es ! 412: push %fs ! 413: push %gs ! 414: ! 415: movw $SEG_386_KD, %ax / Map ds ! 416: movw %ax, %ds ! 417: movw %ax, %es ! 418: movw $SEG_386_UD|R_USR, %ax / Map es ! 419: movw %ax, %fs ! 420: ! 421: jmp tsave0b ! 422: ! 423: //The following lines help find traps during startup. ! 424: BYPASS read_cr0 ! 425: BYPASS read_cr2 ! 426: BYPASS read_cr3 ! 427: tsave0q: ! 428: mov 52(%esp),%eax / Print fault code. ! 429: cmpb $0x40,%al ! 430: je tsave0b / Skip over hardware interrupts. ! 431: push %eax ! 432: call print32 ! 433: pop %ecx ! 434: ! 435: push $' ' ! 436: call mchirp ! 437: pop %ecx ! 438: ! 439: mov 56(%esp),%eax / Print eip. ! 440: push %eax ! 441: call print32 ! 442: pop %ecx ! 443: ! 444: push $' ' ! 445: call mchirp ! 446: pop %ecx ! 447: ! 448: push %esp / Print esp. ! 449: call print32 ! 450: pop %ecx ! 451: ! 452: tsave0a: jmp tsave0a ! 453: tsave0b: ! 454: // ! 455: ! 456: icall X_TRAPNO(%esp) / and call the caller ! 457: ! 458: pop %gs / Restore ! 459: pop %fs ! 460: pop %es ! 461: pop %ds ! 462: popa ! 463: add $8,%esp / forget err, trapno ! 464: iret / Done. ! 465: ! 466: /////// ! 467: ! 468: / Save the environment of a process ! 469: / envsave(p) ! 470: / MENV *p; ! 471: ! 472: / Save the context of a process ! 473: / consave(p) ! 474: / MCON *p; ! 475: ! 476: /////// ! 477: ! 478: envsave: ! 479: consave: ! 480: mov %edi, %ecx / Hide di. ! 481: mov 4(%esp), %edi / di at the MCON block. ! 482: ! 483: cld / Ensure increment. ! 484: mov %ecx, %eax / Save di ! 485: stosl ! 486: mov %esi, %eax / Save si ! 487: stosl ! 488: mov %ebx, %eax / Save bx ! 489: stosl ! 490: mov %ebp, %eax / Save bp ! 491: stosl ! 492: mov %esp, %eax / Save sp ! 493: stosl ! 494: mov (%esp), %eax / Save ra as pc ! 495: stosl ! 496: pushfl / Save fw ! 497: pop %eax ! 498: stosl ! 499: xorl %eax, %eax ! 500: movw %fs, %ax / save space pointer ! 501: stosl ! 502: mov %ecx, %edi / Put di back, ! 503: sub %eax, %eax / indicate a state save and ! 504: ret / return to caller. ! 505: ! 506: /////// ! 507: ! 508: / Restore the environment of a process. ! 509: / envrest(p) ! 510: / MENV *p; ! 511: ! 512: /////// ! 513: ! 514: envrest: ! 515: cli ! 516: cld ! 517: mov 4(%esp),%esi / Pointer to context ! 518: lodsl / Restore di ! 519: mov %eax, %edi ! 520: lodsl / Restore si ! 521: mov %eax, %ecx / Save for later ! 522: lodsl / Restore bx ! 523: mov %eax, %ebx ! 524: lodsl / Restore bp ! 525: mov %eax, %ebp ! 526: lodsl / Restore sp ! 527: mov %eax, %esp ! 528: push %cs / Push current CS ! 529: lodsl / Restore pc ! 530: push %eax ! 531: lodsl / Restore flags ! 532: mov %eax, 8(%esp) / Stack now in form PSW,CS,IP. ! 533: lodsl ! 534: movw %ax, %fs / Restore space ! 535: mov %ecx, %esi / Restore si ! 536: mov $1,%eax / We are restoring ! 537: iret / Return through PSW,CS,IP. ! 538: ! 539: /////// ! 540: ! 541: / Restore the context of a process. ! 542: / Called with interrupts disabled from dispatch. ! 543: / conrest(u, o) ! 544: / saddr_t u; ! 545: ! 546: /////// ! 547: ! 548: conrest: ! 549: mov 8(%esp), %esi / Fetch syscon offset ! 550: ! 551: cli / Interrupts on hold ! 552: cld ! 553: ! 554: / Map new u area into linear space and update paging hardware ! 555: ! 556: mov 4(%esp),%eax / Fetch new u area saddr_t ! 557: orb $SEG_SRW,%al ! 558: mov %eax,[PTABLE1_V<<BPCSHIFT]+UADDR ! 559: ! 560: lcall $SEG_MMUUPD,$0 / strobe CR3 ! 561: ! 562: / Restore context ! 563: ! 564: lodsl / Restore di ! 565: mov %eax,%edi ! 566: lodsl / Restore si ! 567: mov %eax,%ecx / Save for later ! 568: lodsl / Restore bx ! 569: mov %eax,%ebx ! 570: lodsl / Restore bp ! 571: mov %eax,%ebp ! 572: lodsl / Restore sp ! 573: mov %eax,%esp ! 574: push %cs / Push current CS ! 575: lodsl / Restore pc ! 576: push %eax ! 577: ! 578: lodsl / Restore flags ! 579: mov %eax,8(%esp) / Stack now in form PSW,CS,IP. ! 580: ! 581: lodsl ! 582: movw %ax, %fs / Restore space ! 583: ! 584: mov %ecx,%esi / Restore si ! 585: mov $1,%eax / We are restoring ! 586: iret / Return through PSW,CS,IP. ! 587: ! 588: / Save useful registers. ! 589: ! 590: / msysgen(p) ! 591: / MGEN *p; ! 592: ! 593: msysgen: ! 594: ret / Nothing useful to save ! 595: ! 596: / Disable interrupts. Previous value is returned. ! 597: ! 598: sphi: ! 599: pushf / Save flags ! 600: pop %eax / Return current value ! 601: cli / Disable interrupts ! 602: ret / And return ! 603: ! 604: / Enable interrupts. Previous value is returned. ! 605: ! 606: splo: ! 607: pushf ! 608: pop %eax ! 609: sti ! 610: ret ! 611: ! 612: / Change interrupt flag, with no return value. Since we want to test bit 10 ! 613: / of the flags word, we test bit 2 of the second byte with a byte test. ! 614: / (An earlier version of this routine used IRET, which is a bad idea beacuse ! 615: / it is a) very slow, and b) dangerous). ! 616: ! 617: spl: ! 618: pushf / Transfer previous flags to ! 619: pop %eax / %eax by way of the stack ! 620: testb $0x2,5(%esp) / Test argument interrupt flag ! 621: je ?cleari / Branch if flag was clear ! 622: sti ! 623: ret ! 624: ?cleari: ! 625: cli ! 626: ret ! 627: ! 628: /////// ! 629: ! 630: / Idle routine. ! 631: / Enable interupts, and wait for something to ! 632: / happen. Does not do anything to the 8259, bacause ! 633: / this will be set up correctly. ! 634: ! 635: /////// ! 636: .globl idle ! 637: idle: ! 638: sti / Interupts on. ! 639: __idle__: ! 640: jmp __idle__ / Wait for an interrupt ! 641: ret / and return. ! 642: ! 643: /////// ! 644: ! 645: / The world is indeed grim. ! 646: / Hang. Keep the interrupts on so that the ! 647: / keyboard can get int. ! 648: ! 649: /////// ! 650: ! 651: halt: sti / Be safe, ! 652: __halt__ ! 653: jmp __halt__ / And hang. ! 654: ! 655: /////// ! 656: ! 657: / Basic port level I/O. ! 658: ! 659: / Byte I/O (8 bits) ! 660: / int inb(port); ! 661: / int outb(port, data); ! 662: ! 663: / Word I/O (16 bits) ! 664: / int inw(port); ! 665: / int outw(port, data); ! 666: ! 667: / Long I/O (32 bits) ! 668: / int inl(port); ! 669: / int outl(port, data); ! 670: ! 671: /////// ! 672: ! 673: inb: mov 4(%esp),%edx ! 674: sub %eax,%eax ! 675: inb (%dx) ! 676: ret ! 677: ! 678: outb: movl 4(%esp),%edx ! 679: movl 8(%esp),%eax ! 680: outb (%dx) ! 681: ret ! 682: ! 683: inw: mov 4(%esp),%edx ! 684: sub %eax,%eax ! 685: inw (%dx) ! 686: ret ! 687: ! 688: outw: movl 4(%esp),%edx ! 689: movl 8(%esp),%eax ! 690: outw (%dx) ! 691: ret ! 692: ! 693: inl: mov 4(%esp),%edx ! 694: sub %eax,%eax ! 695: inl (%dx) ! 696: ret ! 697: ! 698: outl: movl 4(%esp),%edx ! 699: movl 8(%esp),%eax ! 700: outl (%dx) ! 701: ret ! 702: ! 703: /////// ! 704: ! 705: / AT Hard Disk Assembler Support ! 706: ! 707: / atsend( va ) - send 512 bytes from virtual address to hard disk ! 708: / atrecv( va ) - receive 512 bytes from hard disk into virtual address ! 709: / DRQ is not checked. DRQ must be true before atsend/atrecv are called. ! 710: ! 711: / va is a system global address ! 712: /////// ! 713: ! 714: .globl atsend ! 715: ! 716: va = 8 / va offset from %ebp ! 717: work0 = -4 / work0 offset from %ebp ! 718: atsend: ! 719: enter $0,$4 / reserve 4 bytes (1 int) of local storage ! 720: push %esi ! 721: call workAlloc / get a temp virt page ! 722: movl %eax, work0(%ebp) / this is "work0" - a click number ! 723: ! 724: cld ! 725: mov va(%ebp), %eax / fetch argument va ! 726: shr $BPCSHIFT,%eax / get page table index from va ! 727: mov sysmem,%edx ! 728: leal (%edx,%eax,4),%esi / base = sysmem.u.pbase + btocrd(va) ! 729: ! 730: / Since the requested transfer may span a click boundary, have two clicks ! 731: / ready in the page table - the one containing the virtual address of the ! 732: / start of the user area, and the click which follows in virtual memory. ! 733: ! 734: lodsl / ptable1_V[WORK0] = *base++ | SEG_SRW ! 735: or $SEG_SRW,%eax ! 736: movl work0(%ebp), %edx / work0 ! 737: movl %eax,[PTABLE1_V<<BPCSHIFT](%edx,4) ! 738: ! 739: lodsl / ptable1_V[WORK1] = *base++ | SEG_SRW ! 740: or $SEG_SRW,%eax ! 741: inc %edx / work1 ! 742: movl %eax,[PTABLE1_V<<BPCSHIFT](%edx,4) ! 743: ! 744: / Now that page boundaries are set, work on the offsets. ! 745: ! 746: mov va(%ebp), %esi / va = ctob(WORK0) + (va & (NBPC-1)) ! 747: and $NBPC-1,%esi / get click offset part of va ! 748: movl work0(%ebp), %edx / work0 ! 749: shl $BPCSHIFT,%edx / ctob(work0) ! 750: add %edx,%esi ! 751: ! 752: mov $256, %ecx / copy one disk block ! 753: mov $0x1F0, %edx ! 754: ! 755: / Do the block transfer. ! 756: ! 757: rep ! 758: outsw ! 759: ! 760: push work0(%ebp) / workFree(work0) ! 761: call workFree ! 762: pop %edx ! 763: pop %esi ! 764: leave ! 765: ret ! 766: ! 767: .globl atrecv ! 768: atrecv: ! 769: enter $0,$4 / reserve 4 bytes (1 int) of local storage ! 770: push %esi ! 771: call workAlloc / get a temp virt page ! 772: movl %eax, work0(%ebp) / this is "work0" - a click number ! 773: ! 774: cld ! 775: mov va(%ebp), %eax ! 776: shr $BPCSHIFT,%eax ! 777: mov sysmem,%edx ! 778: leal (%edx,%eax,4),%esi / base = sysmem.u.pbase + btocrd(va) ! 779: ! 780: lodsl / ptable1_V[WORK1] = *base++ | SEG_SRW ! 781: or $SEG_SRW,%eax ! 782: movl work0(%ebp), %edx / work0 ! 783: movl %eax,[PTABLE1_V<<BPCSHIFT](%edx,4) ! 784: ! 785: lodsl / ptable1_V[WORK1] = *base++ | SEG_SRW ! 786: or $SEG_SRW,%eax ! 787: inc %edx / work1 ! 788: movl %eax,[PTABLE1_V<<BPCSHIFT](%edx,4) ! 789: ! 790: mov va(%ebp), %esi / va = ctob(WORK0) + (va & (NBPC-1)) ! 791: and $NBPC-1,%esi ! 792: movl work0(%ebp), %edx / work0 ! 793: shl $BPCSHIFT,%edx / ctob(work0) ! 794: add %edx,%esi ! 795: ! 796: mov $256, %ecx / copy one disk block ! 797: mov $0x1F0, %edx ! 798: ! 799: xchg %esi,%edi ! 800: rep / Value of the ECX register is not ! 801: insw ! 802: xchg %esi,%edi ! 803: ! 804: push work0(%ebp) / workFree(work0) ! 805: call workFree ! 806: pop %edx ! 807: pop %esi ! 808: leave ! 809: ret ! 810: ! 811: /////// ! 812: ! 813: / This dummy routine is put in vector ! 814: / table slots that are unused. All it does is ! 815: / return to the caller. ! 816: ! 817: /////// ! 818: ! 819: vret: ret ! 820: ! 821: / mmuupd() uses a call gate. ! 822: mmuupd: ! 823: pushf ! 824: cli ! 825: lcall $SEG_MMUUPD,$0 / gates to mmuupdfR0 ! 826: popf ! 827: ret ! 828: ! 829: / Ring 0 far mmu update. Called via a gate. Uses %eax. ! 830: / Want interrupts off when we arrive since the interrupt gates ! 831: / lead into Ring 1. ! 832: mmuupdfR0: ! 833: mov $PTABLE0_P<<BPCSHIFT,%eax ! 834: mov %eax,%cr3 ! 835: lret ! 836: ! 837: / Ring 0 near mmu update. Called from ring 0 startup. Uses %eax. ! 838: mmuupdnR0: ! 839: mov $PTABLE0_P<<BPCSHIFT,%eax ! 840: mov %eax,%cr3 ! 841: ret ! 842: ! 843: /////// ! 844: / Get cs selector - return 0 if in kernel, CS if not in kernel. ! 845: / This version is for resident drivers. ! 846: / There is a different version (cs_self.s) for loadable drivers. ! 847: / int cs_sel(); ! 848: /////// ! 849: ! 850: cs_sel: ! 851: sub %eax, %eax ! 852: ret ! 853: ! 854: / load the 'alternate address space register' (fs) ! 855: / with the segment reference passed as an argument. ! 856: ! 857: / The value returned is the old value of the 'fs' register ! 858: ! 859: setspace: ! 860: xorl %eax, %eax ! 861: movw %fs, %ax ! 862: movw 4(%esp), %fs ! 863: ret ! 864: ! 865: ///////////////////////// ! 866: / ! 867: / From __xtrap_on__ to __xtrap_off__, GP fault and page fault will not ! 868: / cause panic. Normally, these two traps coming from kernel text result ! 869: / in panic. ! 870: / ! 871: ///////////////////////// ! 872: .globl __xtrap_on__ ! 873: .globl __xtrap_break__ ! 874: .globl __xtrap_off__ ! 875: __xtrap_on__: ! 876: ! 877: /////// ! 878: ! 879: start_copy .macro ! 880: movl %esp, %edx / Frame pointer for copy code ! 881: .endm ! 882: ! 883: end_copy .macro ! 884: ret ! 885: .endm ! 886: ! 887: copy_frame .define %edx ! 888: ! 889: /////// ! 890: / Fetch a byte from the user's data space. ! 891: / getubd(u) ! 892: / char *u; ! 893: /////// ! 894: ! 895: getubd: ! 896: start_copy ! 897: movl %ss:4(copy_frame), %ecx ! 898: movzxb %fs:(%ecx), %eax ! 899: end_copy ! 900: ! 901: / Fetch a short from the user's data space. ! 902: / Coherent 386 fetches a 16 bit short ! 903: / getusd(u) ! 904: / char *u; ! 905: /////// ! 906: ! 907: getusd: ! 908: start_copy ! 909: movl %ss:4(copy_frame), %ecx ! 910: movzxw %fs:(%ecx), %eax ! 911: end_copy ! 912: ! 913: /////// ! 914: / Fetch a word from the user's data space. ! 915: / Coherent 386 fetches a 32 bit word ! 916: / getuwd(u) ! 917: / char *u; ! 918: /////// ! 919: ! 920: getuwd: ! 921: getupd: ! 922: start_copy ! 923: movl %ss:4(copy_frame), %ecx ! 924: movl %fs:(%ecx), %eax ! 925: end_copy ! 926: ! 927: /////// ! 928: / Store a byte into the user's data space. ! 929: / putubd(u, w) ! 930: / char *u; ! 931: / int w; ! 932: /////// ! 933: ! 934: putubd: ! 935: start_copy ! 936: movl %ss:4(copy_frame), %ecx ! 937: movb %ss:8(copy_frame), %al ! 938: movb %al, %fs:(%ecx) ! 939: end_copy ! 940: ! 941: /////// ! 942: / Store a short into the user's data space. ! 943: / Coherent 386 stores a 16 bit short ! 944: / putusd(u, w) ! 945: / char *u; ! 946: / int w; ! 947: /////// ! 948: ! 949: putusd: ! 950: start_copy ! 951: movl %ss:4(copy_frame), %ecx ! 952: movw %ss:8(copy_frame), %ax ! 953: movw %ax, %fs:(%ecx) ! 954: end_copy ! 955: ! 956: /////// ! 957: / Store a word into the user's data space. ! 958: / Coherent 386 stores a 32 bit word ! 959: / putuwd(u, w) ! 960: / char *u; ! 961: / int w; ! 962: /////// ! 963: ! 964: putuwi: ! 965: putuwd: ! 966: start_copy ! 967: movl %ss:4(copy_frame), %ecx ! 968: movl %ss:8(copy_frame), %eax ! 969: movl %eax, %fs:(%ecx) ! 970: end_copy ! 971: ! 972: /////// ! 973: / Perform a block-clear of user-space memory ! 974: / size_t umemclear (caddr_t * dest, size_t size) ! 975: ////// ! 976: .globl umemclear ! 977: umemclear: ! 978: start_copy ! 979: ! 980: push %ds / Preserve %ds ! 981: push %es / Preserve %es (?) ! 982: pushl %esi / Preserve %esi ! 983: pushl %edi / Preserve %esi ! 984: ! 985: movw %fs, %ax ! 986: movw %ax, %es / Dest segment ! 987: ! 988: movl %ss:4(copy_frame), %edi / Dest ! 989: ! 990: movl %ss:8(copy_frame), %ecx / Length ! 991: sarl $2, %ecx / in longwords. ! 992: ! 993: xorl %eax, %eax / Zero-fill target ! 994: rep stosl / If %ecx > 0, clear longwords ! 995: ! 996: movl %ss:8(copy_frame), %ecx / Length ! 997: andl $3, %ecx / residual byte count ! 998: rep stosb / If %ecx > 0, clear bytes ! 999: ! 1000: movl %ss:8(copy_frame), %eax / Return value ! 1001: ! 1002: popl %edi / Restore registers ! 1003: popl %esi ! 1004: pop %es ! 1005: pop %ds ! 1006: end_copy ! 1007: ! 1008: //////// ! 1009: / Block transfer "n" bytes from location ! 1010: / "k" in the system map to location "u" in the ! 1011: / user's data space. Return the number of bytes ! 1012: / transferred. ! 1013: / kucopy(k, u, n) ! 1014: / char *k; ! 1015: / char *u; ! 1016: / int n; ! 1017: /////// ! 1018: ! 1019: kucopy: ! 1020: start_copy ! 1021: ! 1022: push %ds / Preserve %ds ! 1023: push %es / Preserve %es (?) ! 1024: pushl %esi / Preserve %esi ! 1025: pushl %edi / Preserve %esi ! 1026: ! 1027: movw %fs, %ax ! 1028: movw %ax, %es / Dest segment ! 1029: ! 1030: movl %ss:4(copy_frame), %esi / Source ! 1031: movl %ss:8(copy_frame), %edi / Dest ! 1032: ! 1033: movl %ss:12(copy_frame), %eax / Return value ! 1034: movl %eax, %ecx / Length ! 1035: sarl $2, %ecx / in longwords. ! 1036: rep movsl / If %ecx > 0, move longwords ! 1037: ! 1038: movl %eax, %ecx / Length ! 1039: andl $3, %ecx / residual byte count ! 1040: rep movsb / If %ecx > 0, move bytes ! 1041: ! 1042: popl %edi / Restore registers ! 1043: popl %esi ! 1044: pop %es ! 1045: pop %ds ! 1046: end_copy ! 1047: ! 1048: ! 1049: /////// ! 1050: / Block copy "n" bytes from location "u" in ! 1051: / the user data space to location "k" in the system ! 1052: / data space. Return the actual number of bytes ! 1053: / moved. ! 1054: / ukcopy(u, k, n) ! 1055: / char *u; ! 1056: / char *k; ! 1057: / int n; ! 1058: /////// ! 1059: ! 1060: ukcopy: ! 1061: start_copy ! 1062: ! 1063: push %ds / Preserve %ds ! 1064: push %es / Preserve %es (assume == %ds) ! 1065: pushl %esi / Preserve %si ! 1066: pushl %edi / Preserve %di ! 1067: ! 1068: movw %fs, %ax ! 1069: movw %ax, %ds / Source segment ! 1070: ! 1071: mov %ss:4(copy_frame), %esi / Source ! 1072: mov %ss:8(copy_frame), %edi / Dest ! 1073: ! 1074: movl %ss:12(copy_frame), %eax / Return value ! 1075: movl %eax, %ecx / Length ! 1076: sarl $2, %ecx / in longwords ! 1077: rep movsl / If %ecx > 0, move longwords ! 1078: ! 1079: movl %eax, %ecx / Length ! 1080: andl $3, %ecx / residual byte count ! 1081: rep movsb / if %ecx > 0, move bytes ! 1082: ! 1083: popl %edi / Restore registers ! 1084: popl %esi ! 1085: pop %es ! 1086: pop %ds ! 1087: end_copy / Return ! 1088: ! 1089: //////// ! 1090: / Block copy "n" bytes from far location "src" in ! 1091: / an arbitrary (but valid) to location "dst" in ! 1092: / data space. Return the actual number of bytes ! 1093: / moved. ! 1094: / ! 1095: / ffcopy(src, dst, n) ! 1096: / char far *src; ! 1097: / char far *dst; ! 1098: / int n; ! 1099: //////// ! 1100: .globl ffcopy ! 1101: ffcopy: ! 1102: start_copy ! 1103: ! 1104: push %ds / Preserve %ds ! 1105: push %es / Preserve %es ! 1106: pushl %esi / Preserve %esi ! 1107: pushl %edi / Preserve %edi ! 1108: ! 1109: les %ss:12(copy_frame), %edi / Dest segment, length ! 1110: lds %ss:4(copy_frame), %esi / Source segment, length ! 1111: ! 1112: movl %ss:20(copy_frame), %eax / Return value ! 1113: movl %eax, %ecx / Length ! 1114: sarl $2, %ecx / in longwords ! 1115: rep movsl / if %ecx > 0, move longwords ! 1116: ! 1117: movl %eax, %ecx / Length ! 1118: andl $3, %ecx / residual byte count ! 1119: rep movsb / if %ecx > 0, move bytes ! 1120: ! 1121: popl %edi ! 1122: popl %esi ! 1123: pop %es ! 1124: pop %ds ! 1125: end_copy / Return ! 1126: ! 1127: //////// ! 1128: / Read a byte from a selector and offset. ! 1129: / ! 1130: / ffbyte(off, sel) ! 1131: / unsigned long sel; ! 1132: / unsigned long off; ! 1133: //////// ! 1134: .globl ffbyte ! 1135: ffbyte: ! 1136: start_copy ! 1137: lgs %ss:4(copy_frame), %ecx / Source seg:offset ! 1138: movzxb %gs:(%ecx), %eax / Move with zero-fill ! 1139: end_copy ! 1140: ! 1141: //////// ! 1142: / Read a (short) word from a selector and offset. ! 1143: / ! 1144: / ffword(off, sel) ! 1145: / unsigned long sel; ! 1146: / unsigned long off; ! 1147: //////// ! 1148: .globl ffword ! 1149: ffword: ! 1150: start_copy ! 1151: lgs %ss:4(copy_frame), %ecx / Source seg:offset ! 1152: movzxw %gs:(%ecx), %eax / Move with zero-fill ! 1153: end_copy ! 1154: ! 1155: //////// ! 1156: / write a byte using a selector and offset. ! 1157: / ! 1158: / sfbyte(off, sel, byte) ! 1159: / unsigned long sel; ! 1160: / unsigned long off; ! 1161: / int byte; ! 1162: //////// ! 1163: .globl sfbyte ! 1164: sfbyte: ! 1165: start_copy ! 1166: lgs %ss:4(copy_frame), %ecx / Dest seg:offset ! 1167: movb %ss:12(copy_frame), %al ! 1168: movb %al, %gs:(%ecx) ! 1169: end_copy ! 1170: ! 1171: //////// ! 1172: / write a (short) word using a selector and offset. ! 1173: / ! 1174: / sfword(off, sel, word) ! 1175: / unsigned long sel; ! 1176: / unsigned long off; ! 1177: / int word; ! 1178: //////// ! 1179: .globl sfword ! 1180: sfword: ! 1181: start_copy ! 1182: lgs %ss:4(copy_frame), %ecx / Dest seg:offset ! 1183: movw %ss:12(copy_frame), %ax ! 1184: movw %ax, %gs:(%ecx) ! 1185: end_copy ! 1186: ! 1187: /////// ! 1188: / The n-element copy routines jump here with the stack untouched if they ! 1189: / detect a bounds error or page fault on a user address. The only routines ! 1190: / above that use the stack at all do so with a standard format, so we detect ! 1191: / what is on the stack and restore appropriately. ! 1192: / [ For simplicity, just assume that the pushed values will either all be ! 1193: / there or not be there at all, which is a very good assumption. ] ! 1194: /////// ! 1195: ! 1196: __xtrap_break__: ! 1197: subl %eax, %eax / Return 0 to indicate error ! 1198: / condition. ! 1199: cmpl %esp, %edx / Anything on stack? ! 1200: je ?no_stack ! 1201: ! 1202: popl %edi / Restore registers ! 1203: popl %esi ! 1204: pop %es ! 1205: pop %ds ! 1206: ?no_stack: ! 1207: end_copy / Return ! 1208: ! 1209: __xtrap_off__: / See __xtrap_on__ above. ! 1210: ! 1211: / seg2io(long nbytes, vaddr_t p, long port) ! 1212: ! 1213: / nbytes must be a short word multiple ! 1214: ! 1215: seg2io: ! 1216: movl %esp,%edx ! 1217: push %esi ! 1218: ! 1219: mov 4(%edx),%ecx ! 1220: mov 8(%edx),%esi ! 1221: mov 12(%edx),%edx / mov edx,2(dx) ! 1222: sar $1,%ecx / char to short ! 1223: ! 1224: cld ! 1225: rep ! 1226: outsw ! 1227: ! 1228: pop %esi ! 1229: ret ! 1230: ! 1231: ! 1232: ! 1233: / io2seg(long nbytes, vaddr_t p, long port) ! 1234: ! 1235: / nbytes must be a short word multiple ! 1236: ! 1237: io2seg: ! 1238: mov %esp,%edx ! 1239: push %edi ! 1240: ! 1241: mov 4(%edx),%ecx ! 1242: mov 8(%edx),%edi ! 1243: mov 12(%edx),%edx / mov edx,2(dx) ! 1244: sar $1,%ecx / char to short ! 1245: ! 1246: cld ! 1247: rep / Value of the ECX register is not ! 1248: insw ! 1249: ! 1250: pop %edi ! 1251: ret ! 1252: ! 1253: ! 1254: /////// ! 1255: / ! 1256: / Profile scaling - special multiply routine is used for speed. ! 1257: / ! 1258: / pscale(a,b) is product a*b shifted right 16 bits ! 1259: / ! 1260: /////// ! 1261: ! 1262: .globl pscale ! 1263: pscale: ! 1264: mov 4(%esp),%eax / fetch first argument ! 1265: mull 8(%esp) / unsigned multiply by second argument ! 1266: shrd $16,%edx,%eax / shift 64-bit product right 16 bits ! 1267: ret ! 1268: ! 1269: /////// ! 1270: ! 1271: / Trap an interrupt linkage. ! 1272: / Each of the machine traps has a special little ! 1273: / linkage, that sets up the type code and sends ! 1274: / control off to the common trap processor. Device ! 1275: / interrupts, other than the clock (IR0), are ! 1276: / done here. ! 1277: ! 1278: /////// ! 1279: ! 1280: trap0: ! 1281: push $0x00 / Divide error. ! 1282: call tsave ! 1283: jmp trap ! 1284: ! 1285: / The debug vector is tricky. ! 1286: / ! 1287: / If single stepping user code, the vector must point into Ring 1 code ! 1288: / so that a ptraced child can be synchronized with its parent. ! 1289: / use trap1_usr for this ! 1290: / ! 1291: / If single stepping the kernel, the vector must point into Ring 0 code ! 1292: / so context switches switch out the debug stack frame. ! 1293: / use trap1_ker for this ! 1294: ! 1295: .globl __debug_usr__ ! 1296: trap1_usr: ! 1297: push $0x01 / Single step. ! 1298: call tsave ! 1299: jmp __debug_usr__ ! 1300: ! 1301: .globl __debug_ker__ ! 1302: trap1_ker: ! 1303: push $0x01 / Single step. ! 1304: call tsave0 ! 1305: jmp __debug_ker__ ! 1306: ! 1307: trap2: ! 1308: push $0x02 / Non-maskable interrupt. ! 1309: call tsave ! 1310: jmp trap ! 1311: ! 1312: trap3: ! 1313: push $0x03 / INT 3 (breakpoint). ! 1314: call tsave ! 1315: jmp trap ! 1316: ! 1317: trap4: ! 1318: push $0x04 / Overflow. ! 1319: call tsave ! 1320: jmp trap ! 1321: ! 1322: trap5: ! 1323: push $0x05 / Bound check. ! 1324: call tsave ! 1325: jmp trap ! 1326: ! 1327: trap6: ! 1328: push $0x06 / Invalid opcode. ! 1329: call tsave ! 1330: jmp trap ! 1331: ! 1332: trap7: ! 1333: push $0x07 / Processor Extension not available. ! 1334: call tsave ! 1335: jmp emtrap ! 1336: ! 1337: trap8: ! 1338: / pop %ss:trapcode / Get error code from stack [always 0] ! 1339: add $4,%esp ! 1340: push $0x08 / Double Exception detected ! 1341: call tsave ! 1342: jmp trap ! 1343: ! 1344: trap9: ! 1345: push $0x09 / Processor extension segment overrun ! 1346: call tsave ! 1347: jmp trap ! 1348: ! 1349: trap10: ! 1350: / pop %ss:trapcode / Get error code from stack ! 1351: add $4,%esp ! 1352: push $0x0A / Invalid task state segment ! 1353: call tsave ! 1354: jmp trap ! 1355: ! 1356: trap11: ! 1357: / pop %ss:trapcode / Get error code from stack ! 1358: add $4,%esp ! 1359: push $0x0B / Segment not present ! 1360: call tsave ! 1361: jmp trap ! 1362: ! 1363: trap12: ! 1364: / pop %ss:trapcode / Get error code from stack ! 1365: add $4,%esp ! 1366: push $0x0C / Stack segment overrun or not present ! 1367: call tsave ! 1368: jmp trap ! 1369: ! 1370: trap13: ! 1371: / pop %ss:trapcode / Get error code from stack ! 1372: / add $4,%esp ! 1373: / push $0x0D / General protection ! 1374: call tsave0 ! 1375: jmp gpfault ! 1376: ! 1377: trap14: ! 1378: / pop %ss:trapcode / Get error code from stack ! 1379: / add $4,%esp ! 1380: / push $0x0E / Page Fault ! 1381: call tsave ! 1382: jmp pagefault ! 1383: ! 1384: trap16: ! 1385: push $0x10 / Floating point error ! 1386: call tsave ! 1387: jmp fptrap ! 1388: ! 1389: syc: ! 1390: push $0x22 / Old format system calls. ! 1391: call tsave ! 1392: jmp trap ! 1393: ! 1394: .set FAKE_EFL,12 ! 1395: syc32: ! 1396: push %eax / save %eax ! 1397: pushf / modify current flags ! 1398: pop %eax ! 1399: orw $PSW_VAL,%ax / set IF=1, IOPL=1 (user) on iret ! 1400: mov %eax,FAKE_EFL(%esp) ! 1401: pop %eax / restore %eax ! 1402: push $0x20 / New format system calls. ! 1403: call tsave ! 1404: jmp trap ! 1405: ! 1406: sig32: ! 1407: push %eax ! 1408: pushf ! 1409: pop %eax ! 1410: orw $PSW_VAL,%ax ! 1411: mov %eax,FAKE_EFL(%esp) ! 1412: pop %eax ! 1413: push $0x20 / New format signal return. ! 1414: call tsave ! 1415: jmp msigend ! 1416: ! 1417: ran: ! 1418: push $0x21 / Random trap. ! 1419: call tsave ! 1420: jmp trap ! 1421: ! 1422: dev1: ! 1423: push $0x0140 / Device 1: keyboard ! 1424: call tsave ! 1425: icall [1<<2]+vecs ! 1426: jmp eoi / Dismiss interrupt ! 1427: ! 1428: / Device 2: mapped into device 9 ! 1429: dev3: ! 1430: push $0x0340 / Device 3: al1 ! 1431: call tsave ! 1432: icall [3<<2]+vecs ! 1433: jmp eoi / Dismiss interrupt ! 1434: ! 1435: dev4: ! 1436: push $0x0440 / Device 4: al0 ! 1437: call tsave ! 1438: icall [4<<2]+vecs ! 1439: jmp eoi / Dismiss interrupt ! 1440: ! 1441: dev5: ! 1442: push $0x0540 / Device 5: hard disk ! 1443: call tsave ! 1444: icall [5<<2]+vecs ! 1445: jmp eoi / Dismiss interrupt ! 1446: ! 1447: dev6: ! 1448: push $0x0640 / Device 6: floppy ! 1449: call tsave ! 1450: icall [6<<2]+vecs ! 1451: jmp eoi / Dismiss interrupt ! 1452: ! 1453: dev7: ! 1454: push $0x0740 / Device 7: lp ! 1455: call tsave ! 1456: icall [7<<2]+vecs ! 1457: jmp eoi / Dismiss interrupt ! 1458: ! 1459: dev8: ! 1460: push $0x0840 / Device 8: ! 1461: call tsave ! 1462: icall [8<<2]+vecs ! 1463: jmp eoi2 / Dismiss interrupt ! 1464: ! 1465: dev9: ! 1466: push $0x0940 / Device 9: ! 1467: call tsave ! 1468: icall [9<<2]+vecs ! 1469: jmp eoi2 / Dismiss interrupt ! 1470: ! 1471: dev10: ! 1472: push $0x0A40 / Device 10: ! 1473: call tsave ! 1474: icall [10<<2]+vecs ! 1475: jmp eoi2 / Dismiss interrupt ! 1476: ! 1477: dev11: ! 1478: push $0x0B40 / Device 11: ! 1479: call tsave ! 1480: icall [11<<2]+vecs ! 1481: jmp eoi2 / Dismiss interrupt ! 1482: ! 1483: dev12: ! 1484: push $0x0C40 / Device 12: ! 1485: call tsave ! 1486: icall [12<<2]+vecs ! 1487: jmp eoi2 / Dismiss interrupt ! 1488: ! 1489: .align 4 ! 1490: dev13: ! 1491: / Used to be coprocessor exception interrupt ! 1492: / Coprocessor err had to be cleared by writing a 0 byte to port 0xF0 ! 1493: / ! 1494: push $0x0D40 / Device 13: ! 1495: call tsave ! 1496: icall [13<<2]+vecs ! 1497: jmp eoi2 / Dismiss interrupt ! 1498: ! 1499: dev14: ! 1500: push $0x0E40 / Device 14: ! 1501: call tsave ! 1502: icall [14<<2]+vecs ! 1503: jmp eoi2 / Dismiss interrupt ! 1504: ! 1505: dev15: ! 1506: push $0x0F40 / Device 15: ! 1507: call tsave ! 1508: icall [15<<2]+vecs ! 1509: jmp eoi2 / Dismiss interrupt ! 1510: ! 1511: /////// ! 1512: ! 1513: / Clock interrupt. ! 1514: ! 1515: /////// ! 1516: ! 1517: clk: ! 1518: push $0x0040 ! 1519: call tsave / Perform trap save. ! 1520: mov X_ERR+12(%esp),%eax / ECS at tick time ! 1521: and $3,%eax / This will be R_USR iff user mode ! 1522: push %eax ! 1523: mov X_ERR+12(%esp),%eax / EIP at tick time ! 1524: push %eax ! 1525: call clock / clock(eip, umode) ! 1526: add $8,%esp / pop arguments. ! 1527: jmp eoi / Dismiss interrupt ! 1528: ! 1529: /////// ! 1530: ! 1531: / This co-routine is called to dismiss an interrupt. ! 1532: / The interrupt code is in X_ERR(%esp) ! 1533: ! 1534: / Control returns to "tsave" ! 1535: ! 1536: /////// ! 1537: ! 1538: .globl eoi2 ! 1539: eoi2: ! 1540: cli ! 1541: movb $0x20,%al / Send a non specific EOI ! 1542: outb $SPIC / to the slave PIC. ! 1543: IODELAY ! 1544: movb $0x0B,%al / OCW3 - read isr ! 1545: outb $SPIC ! 1546: IODELAY ! 1547: / inb $SPIC / in-service register to %eax:8..15 ! 1548: / testb %al,%al ! 1549: / jnz eoi2x / no EOI to master if slave isr nonzero ! 1550: eoi: ! 1551: cli ! 1552: movb $0x20,%al / Send a non specific EOI ! 1553: outb $PIC / to the master PIC. ! 1554: IODELAY ! 1555: eoi2x: ret / Done. ! 1556: ! 1557: /////// ! 1558: ! 1559: / Read the equipment description. Use ! 1560: / the "int 11" interface, so that the IBM ! 1561: / ROM will do all the details. ! 1562: ! 1563: /////// ! 1564: ! 1565: int11: mov %cs:val11,%eax / Ask the ROM ! 1566: ret / to put stuff in AX ! 1567: ! 1568: /////// ! 1569: ! 1570: / Bootstrap. ! 1571: / Called by the keyboard driver on control-alt-del. ! 1572: / Requests the 8042 controller to initiate a processor reset, ! 1573: / which is the only way to terminate protected mode operation. ! 1574: ! 1575: / Reference: IBM-AT Technical Reference Manual, ! 1576: / Real-time Clock/CMOS RAM [Page 1-45] ! 1577: / Keyboard controller [Page 1-40] ! 1578: / Test 3, Page 5-68. ! 1579: ! 1580: /////// ! 1581: boot: ! 1582: cli / Disable interrupts. ! 1583: ! 1584: subl %ecx,%ecx ! 1585: loc12: inb $KBCTRL / Wait for 8042 input buffer to empty. ! 1586: testb $2, %al ! 1587: loopne loc12 ! 1588: IODELAY ! 1589: ! 1590: movb $0xFE,%al / Issue a shutdown command ! 1591: outb $KBCTRL / to the 8042 control port. ! 1592: ! 1593: loc13: hlt / Halt until processor reset occurs. ! 1594: jmp loc13 ! 1595: ! 1596: .globl putchar ! 1597: ! 1598: / Comment in the line below if debugging output is to go to the ! 1599: / printer ! 1600: ! 1601: /putchar: ! 1602: ! 1603: movb 4(%esp),%al ! 1604: cmpb $0xa,%al ! 1605: jne loc18 ! 1606: push $0xd ! 1607: call putchar ! 1608: add $4,%esp ! 1609: loc18: mov $LPSTAT,%edx ! 1610: inb (%dx) ! 1611: testb $IBMNBSY,%al ! 1612: je loc18 ! 1613: ! 1614: mov $LPCSR,%edx ! 1615: movb $SEL+NINIT, %al ! 1616: outb (%dx) ! 1617: ! 1618: mov $LPDATA, %edx ! 1619: movb 4(%esp),%al ! 1620: outb (%dx) ! 1621: ! 1622: mov $LPCSR,%edx ! 1623: movb $SEL+NINIT+STROBE,%al ! 1624: outb (%dx) ! 1625: movb $8, %cl ! 1626: l_1: decb %cl ! 1627: jne l_1 ! 1628: movb $SEL+NINIT, %al ! 1629: outb (%dx) ! 1630: ret ! 1631: ! 1632: / long _canl(l) long l; ! 1633: / This is called by the routines that ! 1634: / transform longs to and from the ! 1635: / canonical formats. ! 1636: ! 1637: _canl: ! 1638: mov 4(%esp),%eax ! 1639: rol $16,%eax ! 1640: ret ! 1641: ! 1642: regcr2: mov %cr2,%eax ! 1643: ret ! 1644: ! 1645: regfp: mov %ebp,%eax ! 1646: ret ! 1647: ! 1648: / .align 4 / CPU resets if val11 isn't aligned. ! 1649: .byte 0 ! 1650: val11: .long 0 / Value obtained from int11 [in code]. ! 1651: ! 1652: aicodep: ! 1653: sub %ebx,%ebx ! 1654: sub $aicodep,%ebx ! 1655: lea fn(%ebx),%eax ! 1656: mov %eax,argl(%ebx) ! 1657: lea a1(%ebx),%eax ! 1658: mov %eax,argl+4(%ebx) ! 1659: lea argl+8(%ebx),%eax / No environment ! 1660: push %eax ! 1661: lea argl(%ebx),%eax / Argument list ! 1662: push %eax ! 1663: lea fn(%ebx),%eax / File name ! 1664: push %eax ! 1665: sub $4,%esp / Dummy word for exec ! 1666: movl $59, %eax ! 1667: lcall $0x7,$0 ! 1668: jmp . / Instant page fault if exec failed! ! 1669: .alignoff ! 1670: .align 2 ! 1671: argl: .long 0 / argv[0] = "/etc/init"; ! 1672: .long 0 / argv[1] = ""; ! 1673: .long 0 / argv[2] = NULL; ! 1674: ! 1675: fn: .byte "/etc/init",0 ! 1676: a1: .byte 0 ! 1677: sb: ! 1678: .set aicodes, .-aicodep ! 1679: ! 1680: /////// ! 1681: ! 1682: / Task State Segment - Coherent runs as a single protected mode 386 task. ! 1683: ! 1684: /////// ! 1685: .alignon ! 1686: .align 4 ! 1687: .globl tss_sp0 / Use run-time fixup for tss_sp0 ! 1688: .globl tssIoMap ! 1689: .globl tssIoEnd ! 1690: tss: / Task State Segment. ! 1691: tss_lnk:.long 0 / 0: Back link selector to TSS. ! 1692: tss_sp0:.long ESP0_START / 4: SP for CPL 0. ! 1693: tss_ss0:.long SEG_RNG0_STK / 8: SS for CPL 0. ! 1694: tss_sp1:.long ESP1_START / C: SP for CPL 1. ! 1695: tss_ss1:.long SEG_RNG1_STK / 10: SS for CPL 1. ! 1696: tss_sp2:.long u+NBPC / 14: SP for CPL 2. ! 1697: tss_ss2:.long SEG_386_KD / 18: SS for CPL 2. ! 1698: tss_cr3:.long PTABLE0_P<<BPCSHIFT / 1C: CR3 (PDBR) ! 1699: tss_ip: .long 0 / 20: EIP (Entry point). ! 1700: tss_psw:.long 0 / 24: Flag word. ! 1701: tss_ax: .long 0 / 28: Register AX. ! 1702: tss_cx: .long 0 / 2C: Register CX. ! 1703: tss_dx: .long 0 / 30: Register DX. ! 1704: tss_bx: .long 0 / 34: Register BX. ! 1705: tss_bp: .long 0 / 38: Register BP. ! 1706: tss_sp: .long 0 / 3C: Register SP. ! 1707: tss_si: .long 0 / 40: Register SI. ! 1708: tss_di: .long 0 / 44: Register DI. ! 1709: tss_es: .long 0 / 48: Register ES. ! 1710: tss_cs: .long 0 / 4C: Register CS. ! 1711: tss_ss: .long 0 / 50: Register SS. ! 1712: tss_ds: .long 0 / 54: Register DS. ! 1713: tss_fs: .long 0 / 58: Register FS. ! 1714: tss_gs: .long 0 / 5C: Register GS. ! 1715: tss_ldt:.long SEG_LDT / 60: Task LDT Selector. ! 1716: .long TSS_IOMAP_OFF / 64: T bit & I/O map base ! 1717: / I/O map is part of tss. ! 1718: / Bitmap up to port address TSS_IOMAP_LEN. ! 1719: / Initialize to all 1's, meaning no I/O allowed. ! 1720: / tss + 0x68 = tssIoMap ! 1721: tssIoMap: ! 1722: .long [[TSS_IOMAP_LEN + 31] .div 32] # -1 ! 1723: tssIoEnd: ! 1724: .long [[0x1000 - TSS_IOMAP_LEN] .div 32] # -1 ! 1725: .long -1 ! 1726: /////// ! 1727: ! 1728: / Data. ! 1729: ! 1730: /////// ! 1731: .data ! 1732: sdata: ! 1733: ! 1734: vecs: .long 16 # vret / Interrupt vector table ! 1735: ! 1736: trapcode:.long 0 ! 1737: ! 1738: .text ! 1739: /////// ! 1740: ! 1741: / Read a byte from the CMOS. Takes one argument--the ! 1742: / CMOS address to read from as an int; returns the ! 1743: / value read as a char. ! 1744: / ! 1745: / int read_cmos(int addr); ! 1746: ! 1747: read_cmos: ! 1748: push %esi ! 1749: push %edi ! 1750: movb 12(%esp), %al / Fetch address from stack. ! 1751: outb $CMOSA / Send address to CMOS. ! 1752: IODELAY ! 1753: sub %eax, %eax / Zero out everything we don't want. ! 1754: inb $CMOSD / Get Value from CMOS into al. ! 1755: pop %edi ! 1756: pop %esi ! 1757: ret / Return from read_cmos(). ! 1758: ! 1759: / Write a byte to the CMOS. ! 1760: / ! 1761: / void write_cmos(int addr, int data) ! 1762: ! 1763: write_cmos: ! 1764: push %esi ! 1765: push %edi ! 1766: movb 12(%esp), %al / Fetch address from stack. ! 1767: outb $CMOSA / Send address to CMOS. ! 1768: IODELAY ! 1769: movb 16(%esp), %al / Fetch address from stack. ! 1770: outb $CMOSD / Get Value from CMOS into al. ! 1771: IODELAY ! 1772: pop %edi ! 1773: pop %esi ! 1774: ret / Return from read_cmos(). ! 1775: ! 1776: / Read timer channel 0 into int value. ! 1777: / Clock counts down from 11932 to 0 with each clock tick. ! 1778: .globl read_t0 ! 1779: read_t0: ! 1780: pushfl ! 1781: cli ! 1782: xorl %eax,%eax / Counter latch timer 0 and clear return val ! 1783: outb $PIT+3 ! 1784: IODELAY ! 1785: inb $PIT / low byte of counter latch ! 1786: IODELAY ! 1787: movb %al,%ah ! 1788: inb $PIT / high byte of counter latch ! 1789: IODELAY ! 1790: xchgb %al,%ah ! 1791: popfl ! 1792: ret ! 1793: ! 1794: / return current contents of psw ! 1795: .globl read_psw ! 1796: read_psw: ! 1797: pushfl ! 1798: popl %eax ! 1799: ret ! 1800: ! 1801: ! 1802: / return current contents of cr0 ! 1803: .globl read_cr0 ! 1804: read_cr0: ! 1805: movl %cr0,%eax ! 1806: ret ! 1807: ! 1808: / return current contents of cr2 ! 1809: .globl read_cr2 ! 1810: read_cr2: ! 1811: movl %cr2,%eax ! 1812: ret ! 1813: ! 1814: / return current contents of cr3 ! 1815: .globl read_cr3 ! 1816: read_cr3: ! 1817: movl %cr3,%eax ! 1818: ret ! 1819: ! 1820: ///////// ! 1821: / ! 1822: / Debugging support. ! 1823: / ! 1824: ///////// ! 1825: .globl write_dr0 ! 1826: .globl write_dr1 ! 1827: .globl write_dr2 ! 1828: .globl write_dr3 ! 1829: .globl write_dr6 ! 1830: .globl write_dr7 ! 1831: ! 1832: .globl read_dr0 ! 1833: .globl read_dr1 ! 1834: .globl read_dr2 ! 1835: .globl read_dr3 ! 1836: .globl read_dr6 ! 1837: .globl read_dr7 ! 1838: ! 1839: / write arg to dr0 ! 1840: write_dr0: ! 1841: movl 4(%esp),%eax ! 1842: movl %eax,%dr0 ! 1843: ret ! 1844: ! 1845: / write arg to dr1 ! 1846: write_dr1: ! 1847: movl 4(%esp),%eax ! 1848: movl %eax,%dr1 ! 1849: ret ! 1850: ! 1851: / write arg to dr2 ! 1852: write_dr2: ! 1853: movl 4(%esp),%eax ! 1854: movl %eax,%dr2 ! 1855: ret ! 1856: ! 1857: / write arg to dr3 ! 1858: write_dr3: ! 1859: movl 4(%esp),%eax ! 1860: movl %eax,%dr3 ! 1861: ret ! 1862: ! 1863: / write arg to dr6 ! 1864: write_dr6: ! 1865: movl 4(%esp),%eax ! 1866: movl %eax,%dr6 ! 1867: ret ! 1868: ! 1869: / write arg to dr7 ! 1870: write_dr7: ! 1871: movl 4(%esp),%eax ! 1872: movl %eax,%dr7 ! 1873: ret ! 1874: ! 1875: read_dr0: ! 1876: movl %dr0,%eax ! 1877: ret ! 1878: ! 1879: read_dr1: ! 1880: movl %dr1,%eax ! 1881: ret ! 1882: ! 1883: read_dr2: ! 1884: movl %dr2,%eax ! 1885: ret ! 1886: ! 1887: read_dr3: ! 1888: movl %dr3,%eax ! 1889: ret ! 1890: ! 1891: read_dr6: ! 1892: movl %dr6,%eax ! 1893: ret ! 1894: ! 1895: read_dr7: ! 1896: movl %dr7,%eax ! 1897: ret ! 1898: ! 1899: / write to the EM bit of CR0 ! 1900: / this routine is a stub for the ring 0 code ! 1901: / argument is 0 or 1 ! 1902: / ! 1903: / void setEm(int bit) ! 1904: .globl setEm ! 1905: setEm: ! 1906: movl 4(%esp),%eax / fetch argument ! 1907: pushf ! 1908: cli ! 1909: pushl %eax ! 1910: lcall $SEG_SET_EM,$0 / gate to setEmfR0 ! 1911: / setEmfR0 will delete 4 bytes worth of args ! 1912: popf ! 1913: ret ! 1914: ! 1915: / Ring 0 write to CR0 EM bit. Called via a gate. ! 1916: / Want interrupts off when we arrive since the interrupt gates ! 1917: / lead into Ring 1. ! 1918: setEmfR0: ! 1919: movb 8(%esp),%cl / fetch argument ! 1920: ! 1921: cmpb $0,%cl ! 1922: movl %cr0,%eax ! 1923: jz se00 ! 1924: orb $4,%al / set EM bit ! 1925: andb $0xDF,%al / clear NE bit ! 1926: jmp se01 ! 1927: se00: ! 1928: andb $0xFB,%al / clear EM bit ! 1929: orb $0x20,%al / set NE bit ! 1930: se01: ! 1931: mov %eax,%cr0 ! 1932: / make 4-byte arg list disappear ! 1933: lret $4 ! 1934: ! 1935: / return nonzero if paging is turned on ! 1936: .globl paging ! 1937: paging: ! 1938: movl (%esp),%eax / fetch return address ! 1939: cmpl $[SBASE<<BPCSHIFT],%eax / is it >= unsigned FFC0_0000? ! 1940: jae pagingMaybe ! 1941: xorl %eax,%eax / if not, no paging ! 1942: ret ! 1943: pagingMaybe: ! 1944: movw %cs,%ax / if return addr high, cs is a selector ! 1945: cmpw $0x58,%ax / selectors 58-6F are nonpaging ! 1946: jb pagingYes ! 1947: cmpw $0x6F,%ax / selectors 58-6F are nonpaging ! 1948: ja pagingYes ! 1949: xorl %eax,%eax / no paging ! 1950: ret ! 1951: pagingYes: ! 1952: movl $1,%eax ! 1953: ret
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.