1*479ab7f0SSascha Wildner/* 2*479ab7f0SSascha Wildner * Copyright (c) 2003,2004 The DragonFly Project. All rights reserved. 3*479ab7f0SSascha Wildner * 4*479ab7f0SSascha Wildner * This code is derived from software contributed to The DragonFly Project 5*479ab7f0SSascha Wildner * by Matthew Dillon <dillon@backplane.com> 6*479ab7f0SSascha Wildner * 7*479ab7f0SSascha Wildner * Redistribution and use in source and binary forms, with or without 8*479ab7f0SSascha Wildner * modification, are permitted provided that the following conditions 9*479ab7f0SSascha Wildner * are met: 10*479ab7f0SSascha Wildner * 11*479ab7f0SSascha Wildner * 1. Redistributions of source code must retain the above copyright 12*479ab7f0SSascha Wildner * notice, this list of conditions and the following disclaimer. 13*479ab7f0SSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright 14*479ab7f0SSascha Wildner * notice, this list of conditions and the following disclaimer in 15*479ab7f0SSascha Wildner * the documentation and/or other materials provided with the 16*479ab7f0SSascha Wildner * distribution. 17*479ab7f0SSascha Wildner * 3. Neither the name of The DragonFly Project nor the names of its 18*479ab7f0SSascha Wildner * contributors may be used to endorse or promote products derived 19*479ab7f0SSascha Wildner * from this software without specific, prior written permission. 20*479ab7f0SSascha Wildner * 21*479ab7f0SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22*479ab7f0SSascha Wildner * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23*479ab7f0SSascha Wildner * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24*479ab7f0SSascha Wildner * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25*479ab7f0SSascha Wildner * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26*479ab7f0SSascha Wildner * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27*479ab7f0SSascha Wildner * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28*479ab7f0SSascha Wildner * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29*479ab7f0SSascha Wildner * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30*479ab7f0SSascha Wildner * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31*479ab7f0SSascha Wildner * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32*479ab7f0SSascha Wildner * SUCH DAMAGE. 33*479ab7f0SSascha Wildner * 34*479ab7f0SSascha Wildner * Copyright (c) 1998 Robert Nordier 35*479ab7f0SSascha Wildner * All rights reserved. 36*479ab7f0SSascha Wildner * 37*479ab7f0SSascha Wildner * Redistribution and use in source and binary forms are freely 38*479ab7f0SSascha Wildner * permitted provided that the above copyright notice and this 39*479ab7f0SSascha Wildner * paragraph and the following disclaimer are duplicated in all 40*479ab7f0SSascha Wildner * such forms. 41*479ab7f0SSascha Wildner * 42*479ab7f0SSascha Wildner * This software is provided "AS IS" and without any express or 43*479ab7f0SSascha Wildner * implied warranties, including, without limitation, the implied 44*479ab7f0SSascha Wildner * warranties of merchantability and fitness for a particular 45*479ab7f0SSascha Wildner * purpose. 46*479ab7f0SSascha Wildner * 47*479ab7f0SSascha Wildner * $FreeBSD: src/sys/boot/i386/btx/btx/btx.s,v 1.32 2002/10/08 18:19:02 jhb Exp $ 48*479ab7f0SSascha Wildner * $DragonFly: src/sys/boot/pc32/btx/btx/btx.S,v 1.8 2006/01/18 09:59:34 swildner Exp $ 49*479ab7f0SSascha Wildner */ 50*479ab7f0SSascha Wildner 51*479ab7f0SSascha Wildner#include "../../bootasm.h" 52*479ab7f0SSascha Wildner 53*479ab7f0SSascha Wildner/* 54*479ab7f0SSascha Wildner * Paging control. 55*479ab7f0SSascha Wildner */ 56*479ab7f0SSascha Wildner .set PAG_SIZ,0x1000 # Page size 57*479ab7f0SSascha Wildner .set PAG_CNT,0x1000 # Pages to map 58*479ab7f0SSascha Wildner/* 59*479ab7f0SSascha Wildner * Fields in %eflags. 60*479ab7f0SSascha Wildner */ 61*479ab7f0SSascha Wildner .set PSL_RESERVED_DEFAULT,0x00000002 62*479ab7f0SSascha Wildner .set PSL_T,0x00000100 # Trap flag 63*479ab7f0SSascha Wildner .set PSL_I,0x00000200 # Interrupt enable flag 64*479ab7f0SSascha Wildner .set PSL_D,0x00000400 # String instruction direction 65*479ab7f0SSascha Wildner .set PSL_NT,0x00004000 # Nested task flag 66*479ab7f0SSascha Wildner .set PSL_VM,0x00020000 # Virtual 8086 mode flag 67*479ab7f0SSascha Wildner .set PSL_AC,0x00040000 # Alignment check flag 68*479ab7f0SSascha Wildner 69*479ab7f0SSascha Wildner/* 70*479ab7f0SSascha Wildner * Segment selectors. 71*479ab7f0SSascha Wildner */ 72*479ab7f0SSascha Wildner .set SEL_SCODE,0x8 # Supervisor code 73*479ab7f0SSascha Wildner .set SEL_SDATA,0x10 # Supervisor data 74*479ab7f0SSascha Wildner .set SEL_RCODE,0x18 # Real mode code 75*479ab7f0SSascha Wildner .set SEL_RDATA,0x20 # Real mode data 76*479ab7f0SSascha Wildner .set SEL_UCODE,0x28|3 # User code 77*479ab7f0SSascha Wildner .set SEL_UDATA,0x30|3 # User data 78*479ab7f0SSascha Wildner .set SEL_TSS,0x38 # TSS 79*479ab7f0SSascha Wildner 80*479ab7f0SSascha Wildner/* 81*479ab7f0SSascha Wildner * Task state segment fields. 82*479ab7f0SSascha Wildner */ 83*479ab7f0SSascha Wildner .set TSS_ESP0,0x4 # PL 0 ESP 84*479ab7f0SSascha Wildner .set TSS_SS0,0x8 # PL 0 SS 85*479ab7f0SSascha Wildner .set TSS_MAP,0x66 # I/O bit map base 86*479ab7f0SSascha Wildner 87*479ab7f0SSascha Wildner/* 88*479ab7f0SSascha Wildner * System calls. 89*479ab7f0SSascha Wildner */ 90*479ab7f0SSascha Wildner .set SYS_EXIT,0x0 # Exit 91*479ab7f0SSascha Wildner .set SYS_EXEC,0x1 # Exec 92*479ab7f0SSascha Wildner 93*479ab7f0SSascha Wildner/* 94*479ab7f0SSascha Wildner * Fields in V86 interface structure. 95*479ab7f0SSascha Wildner */ 96*479ab7f0SSascha Wildner .set V86_CTL,0x0 # Control flags 97*479ab7f0SSascha Wildner .set V86_ADDR,0x4 # Int number/address 98*479ab7f0SSascha Wildner .set V86_ES,0x8 # V86 ES 99*479ab7f0SSascha Wildner .set V86_DS,0xc # V86 DS 100*479ab7f0SSascha Wildner .set V86_FS,0x10 # V86 FS 101*479ab7f0SSascha Wildner .set V86_GS,0x14 # V86 GS 102*479ab7f0SSascha Wildner/* 103*479ab7f0SSascha Wildner * V86 control flags. 104*479ab7f0SSascha Wildner */ 105*479ab7f0SSascha Wildner .set V86F_ADDR,0x10000 # Segment:offset address 106*479ab7f0SSascha Wildner .set V86F_CALLF,0x20000 # Emulate far call 107*479ab7f0SSascha Wildner .set V86F_FLAGS,0x40000 # Return flags 108*479ab7f0SSascha Wildner 109*479ab7f0SSascha Wildner/* 110*479ab7f0SSascha Wildner * Dump format control bytes. 111*479ab7f0SSascha Wildner */ 112*479ab7f0SSascha Wildner .set DMP_X16,0x1 # Word 113*479ab7f0SSascha Wildner .set DMP_X32,0x2 # Long 114*479ab7f0SSascha Wildner .set DMP_MEM,0x4 # Memory 115*479ab7f0SSascha Wildner .set DMP_EOL,0x8 # End of line 116*479ab7f0SSascha Wildner 117*479ab7f0SSascha Wildner/* 118*479ab7f0SSascha Wildner * Screen defaults and assumptions. 119*479ab7f0SSascha Wildner */ 120*479ab7f0SSascha Wildner .set SCR_MAT,0x7 # Mode/attribute 121*479ab7f0SSascha Wildner .set SCR_COL,0x50 # Columns per row 122*479ab7f0SSascha Wildner .set SCR_ROW,0x19 # Rows per screen 123*479ab7f0SSascha Wildner 124*479ab7f0SSascha Wildner/* 125*479ab7f0SSascha Wildner * Derivations, for brevity. 126*479ab7f0SSascha Wildner */ 127*479ab7f0SSascha Wildner .set _ESP0H,MEM_BTX_ESP0>>0x8 # Byte 1 of ESP0 128*479ab7f0SSascha Wildner .set _TSSIO,MEM_BTX_MAP-MEM_BTX_TSS # TSS I/O base 129*479ab7f0SSascha Wildner .set _TSSLM,MEM_BTX_TSS_END-MEM_BTX_TSS # TSS limit 130*479ab7f0SSascha Wildner .set _IDTLM,MEM_BTX_TSS-MEM_BTX_IDT-1 # IDT limit 131*479ab7f0SSascha Wildner 132*479ab7f0SSascha Wildner/* 133*479ab7f0SSascha Wildner * Code segment. 134*479ab7f0SSascha Wildner * 135*479ab7f0SSascha Wildner * BTX start. 136*479ab7f0SSascha Wildner */ 137*479ab7f0SSascha Wildner .globl start 138*479ab7f0SSascha Wildner .code16 139*479ab7f0SSascha Wildnerstart: # Start of code 140*479ab7f0SSascha Wildner 141*479ab7f0SSascha Wildner/* 142*479ab7f0SSascha Wildner * BTX header. 143*479ab7f0SSascha Wildner */ 144*479ab7f0SSascha Wildnerbtx_hdr: .byte 0xeb # Machine ID 145*479ab7f0SSascha Wildner .byte 0xe # Header size 146*479ab7f0SSascha Wildner .ascii "BTX" # Magic 147*479ab7f0SSascha Wildner .byte 0x1 # Major version 148*479ab7f0SSascha Wildner .byte 0x2 # Minor version 149*479ab7f0SSascha Wildner .byte BTX_FLAGS # Flags 150*479ab7f0SSascha Wildner .word PAG_CNT-MEM_BTX_ORG>>0xc # Paging control 151*479ab7f0SSascha Wildner .word break-start # Text size 152*479ab7f0SSascha Wildner .long 0x0 # Entry address 153*479ab7f0SSascha Wildner 154*479ab7f0SSascha Wildner/* 155*479ab7f0SSascha Wildner * Initialization routine. 156*479ab7f0SSascha Wildner */ 157*479ab7f0SSascha Wildnerinit: cli # Disable interrupts 158*479ab7f0SSascha Wildner xor %ax,%ax # Zero/segment 159*479ab7f0SSascha Wildner mov %ax,%ss # Set up 160*479ab7f0SSascha Wildner mov $MEM_BTX_ESP0,%sp # stack 161*479ab7f0SSascha Wildner mov %ax,%es # Address 162*479ab7f0SSascha Wildner mov %ax,%ds # data 163*479ab7f0SSascha Wildner pushl $0x2 # Clear 164*479ab7f0SSascha Wildner popfl # flags 165*479ab7f0SSascha Wildner 166*479ab7f0SSascha Wildner/* 167*479ab7f0SSascha Wildner * Initialize memory. 168*479ab7f0SSascha Wildner */ 169*479ab7f0SSascha Wildner mov $MEM_BTX_IDT,%di # Memory to initialize 170*479ab7f0SSascha Wildner mov $(MEM_BTX_ZEND-MEM_BTX_IDT)/2,%cx # Words to zero 171*479ab7f0SSascha Wildner rep # Zero-fill 172*479ab7f0SSascha Wildner stosw # memory 173*479ab7f0SSascha Wildner 174*479ab7f0SSascha Wildner/* 175*479ab7f0SSascha Wildner * Update real mode IDT for reflecting hardware interrupts. 176*479ab7f0SSascha Wildner */ 177*479ab7f0SSascha Wildner mov $intr20,%bx # Address first handler 178*479ab7f0SSascha Wildner mov $0x10,%cx # Number of handlers 179*479ab7f0SSascha Wildner mov $0x20*4,%di # First real mode IDT entry 180*479ab7f0SSascha Wildnerinit.0: mov %bx,(%di) # Store IP 181*479ab7f0SSascha Wildner inc %di # Address next 182*479ab7f0SSascha Wildner inc %di # entry 183*479ab7f0SSascha Wildner stosw # Store CS 184*479ab7f0SSascha Wildner add $4,%bx # Next handler 185*479ab7f0SSascha Wildner loop init.0 # Next IRQ 186*479ab7f0SSascha Wildner/* 187*479ab7f0SSascha Wildner * Create IDT. 188*479ab7f0SSascha Wildner */ 189*479ab7f0SSascha Wildner mov $MEM_BTX_IDT,%di 190*479ab7f0SSascha Wildner mov $idtctl,%si # Control string 191*479ab7f0SSascha Wildnerinit.1: lodsb # Get entry 192*479ab7f0SSascha Wildner cbw # count 193*479ab7f0SSascha Wildner xchg %ax,%cx # as word 194*479ab7f0SSascha Wildner jcxz init.4 # If done 195*479ab7f0SSascha Wildner lodsb # Get segment 196*479ab7f0SSascha Wildner xchg %ax,%dx # P:DPL:type 197*479ab7f0SSascha Wildner lodsw # Get control 198*479ab7f0SSascha Wildner xchg %ax,%bx # set 199*479ab7f0SSascha Wildner lodsw # Get handler offset 200*479ab7f0SSascha Wildner mov $SEL_SCODE,%dh # Segment selector 201*479ab7f0SSascha Wildnerinit.2: shr %bx # Handle this int? 202*479ab7f0SSascha Wildner jnc init.3 # No 203*479ab7f0SSascha Wildner mov %ax,(%di) # Set handler offset 204*479ab7f0SSascha Wildner mov %dh,0x2(%di) # and selector 205*479ab7f0SSascha Wildner mov %dl,0x5(%di) # Set P:DPL:type 206*479ab7f0SSascha Wildner add $0x4,%ax # Next handler 207*479ab7f0SSascha Wildnerinit.3: lea 0x8(%di),%di # Next entry 208*479ab7f0SSascha Wildner loop init.2 # Till set done 209*479ab7f0SSascha Wildner jmp init.1 # Continue 210*479ab7f0SSascha Wildner 211*479ab7f0SSascha Wildner/* 212*479ab7f0SSascha Wildner * Initialize TSS. 213*479ab7f0SSascha Wildner */ 214*479ab7f0SSascha Wildnerinit.4: movb $_ESP0H,TSS_ESP0+1(%di) # Set ESP0 215*479ab7f0SSascha Wildner movb $SEL_SDATA,TSS_SS0(%di) # Set SS0 216*479ab7f0SSascha Wildner movb $_TSSIO,TSS_MAP(%di) # Set I/O bit map base 217*479ab7f0SSascha Wildner/* 218*479ab7f0SSascha Wildner * Bring up the system. 219*479ab7f0SSascha Wildner */ 220*479ab7f0SSascha Wildner mov $0x2820,%bx # Set protected mode 221*479ab7f0SSascha Wildner callw setpic # IRQ offsets 222*479ab7f0SSascha Wildner lidt idtdesc # Set IDT 223*479ab7f0SSascha Wildner lgdt gdtdesc # Set GDT 224*479ab7f0SSascha Wildner mov %cr0,%eax # Switch to protected 225*479ab7f0SSascha Wildner or $0x01,%eax # mode 226*479ab7f0SSascha Wildner mov %eax,%cr0 # 227*479ab7f0SSascha Wildner ljmp $SEL_SCODE,$init.8 # To 32-bit code 228*479ab7f0SSascha Wildner .code32 229*479ab7f0SSascha Wildnerinit.8: xorl %ecx,%ecx # Zero 230*479ab7f0SSascha Wildner movb $SEL_SDATA,%cl # To 32-bit 231*479ab7f0SSascha Wildner movw %cx,%ss # stack 232*479ab7f0SSascha Wildner 233*479ab7f0SSascha Wildner/* 234*479ab7f0SSascha Wildner * Launch user task. 235*479ab7f0SSascha Wildner */ 236*479ab7f0SSascha Wildner movb $SEL_TSS,%cl # Set task 237*479ab7f0SSascha Wildner ltr %cx # register 238*479ab7f0SSascha Wildner 239*479ab7f0SSascha Wildner/* 240*479ab7f0SSascha Wildner * BTX user area base of VM, for converting physical stack 241*479ab7f0SSascha Wildner * addresses to btx-client virtual stack addresses. 242*479ab7f0SSascha Wildner */ 243*479ab7f0SSascha Wildner movl $MEM_BTX_USR,%edx 244*479ab7f0SSascha Wildner#if !defined(MEM_BTX_USR_STK) 245*479ab7f0SSascha Wildner/* 246*479ab7f0SSascha Wildner * XXX We should NOT use BDA_MEM here. Use a fixed location 247*479ab7f0SSascha Wildner * instead. (%eax is a physical stack addr) 248*479ab7f0SSascha Wildner * 249*479ab7f0SSascha Wildner * (must match stack specified in btxldr) 250*479ab7f0SSascha Wildner */ 251*479ab7f0SSascha Wildner movzwl %ss:BDA_MEM,%eax # Get free memory 252*479ab7f0SSascha Wildner decl %eax # Don't quite trust bios 253*479ab7f0SSascha Wildner shll $0xa,%eax # To bytes 254*479ab7f0SSascha Wildner#else 255*479ab7f0SSascha Wildner/* 256*479ab7f0SSascha Wildner * Use a fixed user stack instead of depending on BDA_MEM. 257*479ab7f0SSascha Wildner * %eax is a physical * stack address. 258*479ab7f0SSascha Wildner */ 259*479ab7f0SSascha Wildner movl $MEM_BTX_USR_STK,%eax 260*479ab7f0SSascha Wildner#endif 261*479ab7f0SSascha Wildner subl $USR_ARGSPACE,%eax # Less arg space 262*479ab7f0SSascha Wildner subl %edx,%eax # Less base Phys->Virt 263*479ab7f0SSascha Wildner movb $SEL_UDATA,%cl # User data selector 264*479ab7f0SSascha Wildner pushl %ecx # Set SS 265*479ab7f0SSascha Wildner pushl %eax # Set ESP (virtual address) 266*479ab7f0SSascha Wildner push $0x202 # Set flags (IF set) 267*479ab7f0SSascha Wildner push $SEL_UCODE # Set CS 268*479ab7f0SSascha Wildner pushl btx_hdr+0xc # Set EIP 269*479ab7f0SSascha Wildner pushl %ecx # Set GS 270*479ab7f0SSascha Wildner pushl %ecx # Set FS 271*479ab7f0SSascha Wildner pushl %ecx # Set DS 272*479ab7f0SSascha Wildner pushl %ecx # Set ES 273*479ab7f0SSascha Wildner pushl %edx # Set EAX (phys base addr of VM) 274*479ab7f0SSascha Wildner movb $0x7,%cl # Set remaining 275*479ab7f0SSascha Wildnerinit.9: push $0x0 # general 276*479ab7f0SSascha Wildner loop init.9 # registers 277*479ab7f0SSascha Wildner#ifdef BTX_SERIAL 278*479ab7f0SSascha Wildner call sio_init # setup the serial console 279*479ab7f0SSascha Wildner#endif 280*479ab7f0SSascha Wildner popa # and initialize 281*479ab7f0SSascha Wildner popl %es # Initialize 282*479ab7f0SSascha Wildner popl %ds # user 283*479ab7f0SSascha Wildner popl %fs # segment 284*479ab7f0SSascha Wildner popl %gs # registers 285*479ab7f0SSascha Wildner iret # To user mode 286*479ab7f0SSascha Wildner 287*479ab7f0SSascha Wildner/* 288*479ab7f0SSascha Wildner * Exit routine. 289*479ab7f0SSascha Wildner */ 290*479ab7f0SSascha Wildnerexit: cli # Disable interrupts 291*479ab7f0SSascha Wildner movl $MEM_BTX_ESP0,%esp # Clear stack 292*479ab7f0SSascha Wildner 293*479ab7f0SSascha Wildner/* 294*479ab7f0SSascha Wildner * Turn off paging. 295*479ab7f0SSascha Wildner */ 296*479ab7f0SSascha Wildner movl %cr0,%eax # Get CR0 297*479ab7f0SSascha Wildner andl $~0x80000000,%eax # Disable 298*479ab7f0SSascha Wildner movl %eax,%cr0 # paging 299*479ab7f0SSascha Wildner xorl %ecx,%ecx # Zero 300*479ab7f0SSascha Wildner movl %ecx,%cr3 # Flush TLB 301*479ab7f0SSascha Wildner 302*479ab7f0SSascha Wildner/* 303*479ab7f0SSascha Wildner * Restore the GDT in case we caught a kernel trap. 304*479ab7f0SSascha Wildner */ 305*479ab7f0SSascha Wildner lgdt %cs:gdtdesc # Set GDT 306*479ab7f0SSascha Wildner 307*479ab7f0SSascha Wildner/* 308*479ab7f0SSascha Wildner * To 16 bits. 309*479ab7f0SSascha Wildner */ 310*479ab7f0SSascha Wildner ljmpw $SEL_RCODE,$exit.1 # Reload CS 311*479ab7f0SSascha Wildner .code16 312*479ab7f0SSascha Wildnerexit.1: mov $SEL_RDATA,%cl # 16-bit selector 313*479ab7f0SSascha Wildner mov %cx,%ss # Reload SS 314*479ab7f0SSascha Wildner mov %cx,%ds # Load 315*479ab7f0SSascha Wildner mov %cx,%es # remaining 316*479ab7f0SSascha Wildner mov %cx,%fs # segment 317*479ab7f0SSascha Wildner mov %cx,%gs # registers 318*479ab7f0SSascha Wildner 319*479ab7f0SSascha Wildner/* 320*479ab7f0SSascha Wildner * To real-address mode. 321*479ab7f0SSascha Wildner */ 322*479ab7f0SSascha Wildner dec %ax # Switch to 323*479ab7f0SSascha Wildner mov %eax,%cr0 # real mode 324*479ab7f0SSascha Wildner ljmp $0x0,$exit.2 # Reload CS 325*479ab7f0SSascha Wildnerexit.2: xor %ax,%ax # Real mode segment 326*479ab7f0SSascha Wildner mov %ax,%ss # Reload SS 327*479ab7f0SSascha Wildner mov %ax,%ds # Address data 328*479ab7f0SSascha Wildner mov $0x7008,%bx # Set real mode 329*479ab7f0SSascha Wildner callw setpic # IRQ offsets 330*479ab7f0SSascha Wildner lidt ivtdesc # Set IVT 331*479ab7f0SSascha Wildner 332*479ab7f0SSascha Wildner/* 333*479ab7f0SSascha Wildner * Reboot or await reset. 334*479ab7f0SSascha Wildner */ 335*479ab7f0SSascha Wildner sti # Enable interrupts 336*479ab7f0SSascha Wildner testb $0x1,btx_hdr+0x7 # Reboot? 337*479ab7f0SSascha Wildnerexit.3: jz exit.3 # No 338*479ab7f0SSascha Wildner movw $0x1234, BDA_BOOT # Do a warm boot 339*479ab7f0SSascha Wildner ljmp $0xf000,$0xfff0 # reboot the machine 340*479ab7f0SSascha Wildner 341*479ab7f0SSascha Wildner/* 342*479ab7f0SSascha Wildner * Set IRQ offsets by reprogramming 8259A PICs. 343*479ab7f0SSascha Wildner */ 344*479ab7f0SSascha Wildnersetpic: in $0x21,%al # Save master 345*479ab7f0SSascha Wildner push %ax # IMR 346*479ab7f0SSascha Wildner in $0xa1,%al # Save slave 347*479ab7f0SSascha Wildner push %ax # IMR 348*479ab7f0SSascha Wildner movb $0x11,%al # ICW1 to 349*479ab7f0SSascha Wildner outb %al,$0x20 # master, 350*479ab7f0SSascha Wildner outb %al,$0xa0 # slave 351*479ab7f0SSascha Wildner movb %bl,%al # ICW2 to 352*479ab7f0SSascha Wildner outb %al,$0x21 # master 353*479ab7f0SSascha Wildner movb %bh,%al # ICW2 to 354*479ab7f0SSascha Wildner outb %al,$0xa1 # slave 355*479ab7f0SSascha Wildner movb $0x4,%al # ICW3 to 356*479ab7f0SSascha Wildner outb %al,$0x21 # master 357*479ab7f0SSascha Wildner movb $0x2,%al # ICW3 to 358*479ab7f0SSascha Wildner outb %al,$0xa1 # slave 359*479ab7f0SSascha Wildner movb $0x1,%al # ICW4 to 360*479ab7f0SSascha Wildner outb %al,$0x21 # master, 361*479ab7f0SSascha Wildner outb %al,$0xa1 # slave 362*479ab7f0SSascha Wildner pop %ax # Restore slave 363*479ab7f0SSascha Wildner outb %al,$0xa1 # IMR 364*479ab7f0SSascha Wildner pop %ax # Restore master 365*479ab7f0SSascha Wildner outb %al,$0x21 # IMR 366*479ab7f0SSascha Wildner retw # To caller 367*479ab7f0SSascha Wildner .code32 368*479ab7f0SSascha Wildner 369*479ab7f0SSascha Wildner/* 370*479ab7f0SSascha Wildner * Exception jump table. 371*479ab7f0SSascha Wildner */ 372*479ab7f0SSascha Wildnerintx00: push $0x0 # Int 0x0: #DE 373*479ab7f0SSascha Wildner jmp ex_noc # Divide error 374*479ab7f0SSascha Wildner push $0x1 # Int 0x1: #DB 375*479ab7f0SSascha Wildner jmp ex_noc # Debug 376*479ab7f0SSascha Wildner push $0x3 # Int 0x3: #BP 377*479ab7f0SSascha Wildner jmp ex_noc # Breakpoint 378*479ab7f0SSascha Wildner push $0x4 # Int 0x4: #OF 379*479ab7f0SSascha Wildner jmp ex_noc # Overflow 380*479ab7f0SSascha Wildner push $0x5 # Int 0x5: #BR 381*479ab7f0SSascha Wildner jmp ex_noc # BOUND range exceeded 382*479ab7f0SSascha Wildner push $0x6 # Int 0x6: #UD 383*479ab7f0SSascha Wildner jmp ex_noc # Invalid opcode 384*479ab7f0SSascha Wildner push $0x7 # Int 0x7: #NM 385*479ab7f0SSascha Wildner jmp ex_noc # Device not available 386*479ab7f0SSascha Wildner push $0x8 # Int 0x8: #DF 387*479ab7f0SSascha Wildner jmp except # Double fault 388*479ab7f0SSascha Wildner push $0xa # Int 0xa: #TS 389*479ab7f0SSascha Wildner jmp except # Invalid TSS 390*479ab7f0SSascha Wildner push $0xb # Int 0xb: #NP 391*479ab7f0SSascha Wildner jmp except # Segment not present 392*479ab7f0SSascha Wildner push $0xc # Int 0xc: #SS 393*479ab7f0SSascha Wildner jmp except # Stack segment fault 394*479ab7f0SSascha Wildner push $0xd # Int 0xd: #GP 395*479ab7f0SSascha Wildner jmp except # General protection 396*479ab7f0SSascha Wildner push $0xe # Int 0xe: #PF 397*479ab7f0SSascha Wildner jmp except # Page fault 398*479ab7f0SSascha Wildnerintx10: push $0x10 # Int 0x10: #MF 399*479ab7f0SSascha Wildner jmp ex_noc # Floating-point error 400*479ab7f0SSascha Wildner 401*479ab7f0SSascha Wildner/* 402*479ab7f0SSascha Wildner * Save a zero error code. 403*479ab7f0SSascha Wildner */ 404*479ab7f0SSascha Wildnerex_noc: pushl (%esp,1) # Duplicate int no 405*479ab7f0SSascha Wildner movb $0x0,0x4(%esp,1) # Fake error code 406*479ab7f0SSascha Wildner 407*479ab7f0SSascha Wildner/* 408*479ab7f0SSascha Wildner * Handle exception. 409*479ab7f0SSascha Wildner */ 410*479ab7f0SSascha Wildnerexcept: cld # String ops inc 411*479ab7f0SSascha Wildner pushl %ds # Save 412*479ab7f0SSascha Wildner pushl %es # most 413*479ab7f0SSascha Wildner pusha # registers 414*479ab7f0SSascha Wildner pushl %gs # Set GS 415*479ab7f0SSascha Wildner pushl %fs # Set FS 416*479ab7f0SSascha Wildner pushl %ds # Set DS 417*479ab7f0SSascha Wildner pushl %es # Set ES 418*479ab7f0SSascha Wildner cmpw $SEL_SCODE,0x44(%esp,1) # Supervisor mode? 419*479ab7f0SSascha Wildner jne except.1 # No 420*479ab7f0SSascha Wildner pushl %ss # Set SS 421*479ab7f0SSascha Wildner jmp except.2 # Join common code 422*479ab7f0SSascha Wildnerexcept.1: pushl 0x50(%esp,1) # Set SS 423*479ab7f0SSascha Wildnerexcept.2: pushl 0x50(%esp,1) # Set ESP 424*479ab7f0SSascha Wildner push $SEL_SDATA # Set up 425*479ab7f0SSascha Wildner popl %ds # to 426*479ab7f0SSascha Wildner pushl %ds # address 427*479ab7f0SSascha Wildner popl %es # data 428*479ab7f0SSascha Wildner movl %esp,%ebx # Stack frame 429*479ab7f0SSascha Wildner movl $dmpfmt,%esi # Dump format string 430*479ab7f0SSascha Wildner movl $MEM_BTX_BUF,%edi # Buffer 431*479ab7f0SSascha Wildner pushl %edi # Dump to 432*479ab7f0SSascha Wildner call dump # buffer 433*479ab7f0SSascha Wildner popl %esi # and 434*479ab7f0SSascha Wildner call putstr # display 435*479ab7f0SSascha Wildner leal 0x18(%esp,1),%esp # Discard frame 436*479ab7f0SSascha Wildner popa # Restore 437*479ab7f0SSascha Wildner popl %es # registers 438*479ab7f0SSascha Wildner popl %ds # saved 439*479ab7f0SSascha Wildner cmpb $0x3,(%esp,1) # Breakpoint? 440*479ab7f0SSascha Wildner je except.3 # Yes 441*479ab7f0SSascha Wildner cmpb $0x1,(%esp,1) # Debug? 442*479ab7f0SSascha Wildner jne except.2a # No 443*479ab7f0SSascha Wildner testl $PSL_T,0x10(%esp,1) # Trap flag set? 444*479ab7f0SSascha Wildner jnz except.3 # Yes 445*479ab7f0SSascha Wildnerexcept.2a: jmp exit # Exit 446*479ab7f0SSascha Wildnerexcept.3: leal 0x8(%esp,1),%esp # Discard err, int no 447*479ab7f0SSascha Wildner iret # From interrupt 448*479ab7f0SSascha Wildner 449*479ab7f0SSascha Wildner/* 450*479ab7f0SSascha Wildner * Reboot the machine by setting the reboot flag and exiting 451*479ab7f0SSascha Wildner */ 452*479ab7f0SSascha Wildnerreboot: orb $0x1,btx_hdr+0x7 # Set the reboot flag 453*479ab7f0SSascha Wildner jmp exit # Terminate BTX and reboot 454*479ab7f0SSascha Wildner 455*479ab7f0SSascha Wildner/* 456*479ab7f0SSascha Wildner * Protected Mode Hardware interrupt jump table. 457*479ab7f0SSascha Wildner */ 458*479ab7f0SSascha Wildnerintx20: push $0x8 # Int 0x20: IRQ0 459*479ab7f0SSascha Wildner jmp int_hw # V86 int 0x8 460*479ab7f0SSascha Wildner push $0x9 # Int 0x21: IRQ1 461*479ab7f0SSascha Wildner jmp int_hw # V86 int 0x9 462*479ab7f0SSascha Wildner push $0xa # Int 0x22: IRQ2 463*479ab7f0SSascha Wildner jmp int_hw # V86 int 0xa 464*479ab7f0SSascha Wildner push $0xb # Int 0x23: IRQ3 465*479ab7f0SSascha Wildner jmp int_hw # V86 int 0xb 466*479ab7f0SSascha Wildner push $0xc # Int 0x24: IRQ4 467*479ab7f0SSascha Wildner jmp int_hw # V86 int 0xc 468*479ab7f0SSascha Wildner push $0xd # Int 0x25: IRQ5 469*479ab7f0SSascha Wildner jmp int_hw # V86 int 0xd 470*479ab7f0SSascha Wildner push $0xe # Int 0x26: IRQ6 471*479ab7f0SSascha Wildner jmp int_hw # V86 int 0xe 472*479ab7f0SSascha Wildner push $0xf # Int 0x27: IRQ7 473*479ab7f0SSascha Wildner jmp int_hw # V86 int 0xf 474*479ab7f0SSascha Wildner push $0x70 # Int 0x28: IRQ8 475*479ab7f0SSascha Wildner jmp int_hw # V86 int 0x70 476*479ab7f0SSascha Wildner push $0x71 # Int 0x29: IRQ9 477*479ab7f0SSascha Wildner jmp int_hw # V86 int 0x71 478*479ab7f0SSascha Wildner push $0x72 # Int 0x2a: IRQ10 479*479ab7f0SSascha Wildner jmp int_hw # V86 int 0x72 480*479ab7f0SSascha Wildner push $0x73 # Int 0x2b: IRQ11 481*479ab7f0SSascha Wildner jmp int_hw # V86 int 0x73 482*479ab7f0SSascha Wildner push $0x74 # Int 0x2c: IRQ12 483*479ab7f0SSascha Wildner jmp int_hw # V86 int 0x74 484*479ab7f0SSascha Wildner push $0x75 # Int 0x2d: IRQ13 485*479ab7f0SSascha Wildner jmp int_hw # V86 int 0x75 486*479ab7f0SSascha Wildner push $0x76 # Int 0x2e: IRQ14 487*479ab7f0SSascha Wildner jmp int_hw # V86 int 0x76 488*479ab7f0SSascha Wildner push $0x77 # Int 0x2f: IRQ15 489*479ab7f0SSascha Wildner jmp int_hw # V86 int 0x77 490*479ab7f0SSascha Wildner 491*479ab7f0SSascha Wildner/* 492*479ab7f0SSascha Wildner * Invoke real mode interrupt/function call from user mode with arguments. 493*479ab7f0SSascha Wildner */ 494*479ab7f0SSascha Wildnerintx31: pushl $-1 # Dummy int no for btx_v86 495*479ab7f0SSascha Wildner 496*479ab7f0SSascha Wildner/* 497*479ab7f0SSascha Wildner * Invoke real mode interrupt/function call from protected mode. 498*479ab7f0SSascha Wildner * 499*479ab7f0SSascha Wildner * We place a trampoline on the user stack that will return to rret_tramp 500*479ab7f0SSascha Wildner * which will reenter protected mode and then finally return to the user 501*479ab7f0SSascha Wildner * client. 502*479ab7f0SSascha Wildner * 503*479ab7f0SSascha Wildner * Kernel frame %esi points to: Real mode stack frame at MEM_BTX_ESPR: 504*479ab7f0SSascha Wildner * 505*479ab7f0SSascha Wildner * -0x00 user %ss -0x04 kernel %esp (with full frame) 506*479ab7f0SSascha Wildner * -0x04 user %esp -0x08 btx_v86 pointer 507*479ab7f0SSascha Wildner * -0x08 user %eflags -0x0c flags (only used if interrupt) 508*479ab7f0SSascha Wildner * -0x0c user %cs -0x10 real mode CS:IP return trampoline 509*479ab7f0SSascha Wildner * -0x10 user %eip -0x12 real mode flags 510*479ab7f0SSascha Wildner * -0x14 int no -0x16 real mode CS:IP (target) 511*479ab7f0SSascha Wildner * -0x18 %eax 512*479ab7f0SSascha Wildner * -0x1c %ecx 513*479ab7f0SSascha Wildner * -0x20 %edx 514*479ab7f0SSascha Wildner * -0x24 %ebx 515*479ab7f0SSascha Wildner * -0x28 %esp 516*479ab7f0SSascha Wildner * -0x2c %ebp 517*479ab7f0SSascha Wildner * -0x30 %esi 518*479ab7f0SSascha Wildner * -0x34 %edi 519*479ab7f0SSascha Wildner * -0x38 %gs 520*479ab7f0SSascha Wildner * -0x3c %fs 521*479ab7f0SSascha Wildner * -0x40 %ds 522*479ab7f0SSascha Wildner * -0x44 %es 523*479ab7f0SSascha Wildner * -0x48 zero %eax (hardware int only) 524*479ab7f0SSascha Wildner * -0x4c zero %ecx (hardware int only) 525*479ab7f0SSascha Wildner * -0x50 zero %edx (hardware int only) 526*479ab7f0SSascha Wildner * -0x54 zero %ebx (hardware int only) 527*479ab7f0SSascha Wildner * -0x58 zero %esp (hardware int only) 528*479ab7f0SSascha Wildner * -0x5c zero %ebp (hardware int only) 529*479ab7f0SSascha Wildner * -0x60 zero %esi (hardware int only) 530*479ab7f0SSascha Wildner * -0x64 zero %edi (hardware int only) 531*479ab7f0SSascha Wildner * -0x68 zero %gs (hardware int only) 532*479ab7f0SSascha Wildner * -0x6c zero %fs (hardware int only) 533*479ab7f0SSascha Wildner * -0x70 zero %ds (hardware int only) 534*479ab7f0SSascha Wildner * -0x74 zero %es (hardware int only) 535*479ab7f0SSascha Wildner */ 536*479ab7f0SSascha Wildnerint_hw: cld # String ops inc 537*479ab7f0SSascha Wildner pusha # Save gp regs 538*479ab7f0SSascha Wildner pushl %gs # Save 539*479ab7f0SSascha Wildner pushl %fs # seg 540*479ab7f0SSascha Wildner pushl %ds # regs 541*479ab7f0SSascha Wildner pushl %es 542*479ab7f0SSascha Wildner push $SEL_SDATA # Set up 543*479ab7f0SSascha Wildner popl %ds # to 544*479ab7f0SSascha Wildner pushl %ds # address 545*479ab7f0SSascha Wildner popl %es # data 546*479ab7f0SSascha Wildner leal 0x44(%esp,1),%esi # Base of frame 547*479ab7f0SSascha Wildner movl %esp,MEM_BTX_ESPR-0x04 # Save kernel stack pointer 548*479ab7f0SSascha Wildner movl -0x14(%esi),%eax # Get Int no 549*479ab7f0SSascha Wildner cmpl $-1,%eax # Hardware interrupt? 550*479ab7f0SSascha Wildner jne intusr.1 # Yes 551*479ab7f0SSascha Wildner/* 552*479ab7f0SSascha Wildner * v86 calls save the btx_v86 pointer on the real mode stack and read 553*479ab7f0SSascha Wildner * the address and flags from the btx_v86 structure. For interrupt 554*479ab7f0SSascha Wildner * handler invocations (VM86 INTx requests), disable interrupts, 555*479ab7f0SSascha Wildner * tracing, and alignment checking while the handler runs. 556*479ab7f0SSascha Wildner */ 557*479ab7f0SSascha Wildner movl $MEM_BTX_USR,%ebx # User base 558*479ab7f0SSascha Wildner movl %ebx,%edx # address 559*479ab7f0SSascha Wildner addl -0x4(%esi),%ebx # User ESP 560*479ab7f0SSascha Wildner movl (%ebx),%ebp # btx_v86 pointer 561*479ab7f0SSascha Wildner addl %ebp,%edx # Flatten btx_v86 ptr 562*479ab7f0SSascha Wildner movl %edx,MEM_BTX_ESPR-0x08 # Save btx_v86 ptr 563*479ab7f0SSascha Wildner movl V86_ADDR(%edx),%eax # Get int no/address 564*479ab7f0SSascha Wildner movl V86_CTL(%edx),%edx # Get control flags 565*479ab7f0SSascha Wildner movl -0x08(%esi),%ebx # Save user flags in %ebx 566*479ab7f0SSascha Wildner testl $V86F_ADDR,%edx # Segment:offset? 567*479ab7f0SSascha Wildner jnz intusr.4 # Yes 568*479ab7f0SSascha Wildner andl $~(PSL_I|PSL_T|PSL_AC),%ebx # Disable interrupts, tracing, 569*479ab7f0SSascha Wildner # and alignment checking for 570*479ab7f0SSascha Wildner # interrupt handler 571*479ab7f0SSascha Wildner jmp intusr.3 # Skip hardware interrupt 572*479ab7f0SSascha Wildner/* 573*479ab7f0SSascha Wildner * Hardware interrupts store a NULL btx_v86 pointer and use the 574*479ab7f0SSascha Wildner * address (interrupt number) from the stack with empty flags. Also, 575*479ab7f0SSascha Wildner * push a dummy frame of zeros onto the stack for all the general 576*479ab7f0SSascha Wildner * purpose and segment registers and clear %eflags. This gives the 577*479ab7f0SSascha Wildner * hardware interrupt handler a clean slate. 578*479ab7f0SSascha Wildner */ 579*479ab7f0SSascha Wildnerintusr.1: xorl %edx,%edx # Control flags 580*479ab7f0SSascha Wildner movl %edx,MEM_BTX_ESPR-0x08 # NULL btx_v86 ptr 581*479ab7f0SSascha Wildner movl $12,%ecx # Frame is 12 dwords 582*479ab7f0SSascha Wildnerintusr.2: pushl $0x0 # Fill frame 583*479ab7f0SSascha Wildner loop intusr.2 # with zeros 584*479ab7f0SSascha Wildner movl $PSL_RESERVED_DEFAULT,%ebx # Set clean %eflags 585*479ab7f0SSascha Wildner/* 586*479ab7f0SSascha Wildner * Look up real mode IDT entry for hardware interrupts and VM86 INTx 587*479ab7f0SSascha Wildner * requests. 588*479ab7f0SSascha Wildner */ 589*479ab7f0SSascha Wildnerintusr.3: shll $0x2,%eax # Scale 590*479ab7f0SSascha Wildner movl (%eax),%eax # Load int vector 591*479ab7f0SSascha Wildner jmp intusr.5 # Skip CALLF test 592*479ab7f0SSascha Wildner/* 593*479ab7f0SSascha Wildner * Panic if V86F_CALLF isn't set with V86F_ADDR. 594*479ab7f0SSascha Wildner */ 595*479ab7f0SSascha Wildnerintusr.4: testl $V86F_CALLF,%edx # Far call? 596*479ab7f0SSascha Wildner jnz intusr.5 # Ok 597*479ab7f0SSascha Wildner movl %edx,0x30(%esp,1) # Place VM86 flags in int no 598*479ab7f0SSascha Wildner movl $badvm86,%esi # Display bad 599*479ab7f0SSascha Wildner call putstr # VM86 call 600*479ab7f0SSascha Wildner popl %es # Restore 601*479ab7f0SSascha Wildner popl %ds # seg 602*479ab7f0SSascha Wildner popl %fs # regs 603*479ab7f0SSascha Wildner popl %gs 604*479ab7f0SSascha Wildner popal # Restore gp regs 605*479ab7f0SSascha Wildner jmp ex_noc # Panic 606*479ab7f0SSascha Wildner/* 607*479ab7f0SSascha Wildner * %eax now holds the segment:offset of the function. 608*479ab7f0SSascha Wildner * %ebx now holds the %eflags to pass to real mode. 609*479ab7f0SSascha Wildner * %edx now holds the V86F_* flags. 610*479ab7f0SSascha Wildner */ 611*479ab7f0SSascha Wildnerintusr.5: movw %bx,MEM_BTX_ESPR-0x12 # Pass user flags to real mode 612*479ab7f0SSascha Wildner # target 613*479ab7f0SSascha Wildner/* 614*479ab7f0SSascha Wildner * If this is a v86 call, copy the seg regs out of the btx_v86 structure. 615*479ab7f0SSascha Wildner */ 616*479ab7f0SSascha Wildner movl MEM_BTX_ESPR-0x08,%ecx # Get btx_v86 ptr 617*479ab7f0SSascha Wildner jecxz intusr.6 # Skip for hardware ints 618*479ab7f0SSascha Wildner leal -0x44(%esi),%edi # %edi => kernel stack seg regs 619*479ab7f0SSascha Wildner pushl %esi # Save 620*479ab7f0SSascha Wildner leal V86_ES(%ecx),%esi # %esi => btx_v86 seg regs 621*479ab7f0SSascha Wildner movl $4,%ecx # Copy seg regs 622*479ab7f0SSascha Wildner rep # from btx_v86 623*479ab7f0SSascha Wildner movsl # to kernel stack 624*479ab7f0SSascha Wildner popl %esi # Restore 625*479ab7f0SSascha Wildnerintusr.6: movl -0x08(%esi),%ebx # Copy user flags to real 626*479ab7f0SSascha Wildner movl %ebx,MEM_BTX_ESPR-0x0c # mode return trampoline 627*479ab7f0SSascha Wildner movl $rret_tramp,%ebx # Set return trampoline 628*479ab7f0SSascha Wildner movl %ebx,MEM_BTX_ESPR-0x10 # CS:IP 629*479ab7f0SSascha Wildner movl %eax,MEM_BTX_ESPR-0x16 # Real mode target CS:IP 630*479ab7f0SSascha Wildner ljmpw $SEL_RCODE,$intusr.7 # Change to 16-bit segment 631*479ab7f0SSascha Wildner .code16 632*479ab7f0SSascha Wildnerintusr.7: movl %cr0,%eax # Leave 633*479ab7f0SSascha Wildner dec %al # protected 634*479ab7f0SSascha Wildner movl %eax,%cr0 # mode 635*479ab7f0SSascha Wildner ljmpw $0x0,$intusr.8 636*479ab7f0SSascha Wildnerintusr.8: xorw %ax,%ax # Reset %ds 637*479ab7f0SSascha Wildner movw %ax,%ds # and 638*479ab7f0SSascha Wildner movw %ax,%ss # %ss 639*479ab7f0SSascha Wildner lidt ivtdesc # Set IVT 640*479ab7f0SSascha Wildner popl %es # Restore 641*479ab7f0SSascha Wildner popl %ds # seg 642*479ab7f0SSascha Wildner popl %fs # regs 643*479ab7f0SSascha Wildner popl %gs 644*479ab7f0SSascha Wildner popal # Restore gp regs 645*479ab7f0SSascha Wildner movw $MEM_BTX_ESPR-0x16,%sp # Switch to real mode stack 646*479ab7f0SSascha Wildner iret # Call target routine 647*479ab7f0SSascha Wildner/* 648*479ab7f0SSascha Wildner * For the return to real mode we setup a stack frame like this on the real 649*479ab7f0SSascha Wildner * mode stack. Note that callf calls won't pop off the flags, but we just 650*479ab7f0SSascha Wildner * ignore that by repositioning %sp to be just above the btx_v86 pointer 651*479ab7f0SSascha Wildner * so it is aligned. The stack is relative to MEM_BTX_ESPR. 652*479ab7f0SSascha Wildner * 653*479ab7f0SSascha Wildner * -0x04 kernel %esp 654*479ab7f0SSascha Wildner * -0x08 btx_v86 655*479ab7f0SSascha Wildner * -0x0c %eax 656*479ab7f0SSascha Wildner * -0x10 %ecx 657*479ab7f0SSascha Wildner * -0x14 %edx 658*479ab7f0SSascha Wildner * -0x18 %ebx 659*479ab7f0SSascha Wildner * -0x1c %esp 660*479ab7f0SSascha Wildner * -0x20 %ebp 661*479ab7f0SSascha Wildner * -0x24 %esi 662*479ab7f0SSascha Wildner * -0x28 %edi 663*479ab7f0SSascha Wildner * -0x2c %gs 664*479ab7f0SSascha Wildner * -0x30 %fs 665*479ab7f0SSascha Wildner * -0x34 %ds 666*479ab7f0SSascha Wildner * -0x38 %es 667*479ab7f0SSascha Wildner * -0x3c %eflags 668*479ab7f0SSascha Wildner */ 669*479ab7f0SSascha Wildnerrret_tramp: movw $MEM_BTX_ESPR-0x08,%sp # Reset stack pointer 670*479ab7f0SSascha Wildner pushal # Save gp regs 671*479ab7f0SSascha Wildner pushl %gs # Save 672*479ab7f0SSascha Wildner pushl %fs # seg 673*479ab7f0SSascha Wildner pushl %ds # regs 674*479ab7f0SSascha Wildner pushl %es 675*479ab7f0SSascha Wildner pushfl # Save %eflags 676*479ab7f0SSascha Wildner pushl $PSL_RESERVED_DEFAULT|PSL_D # Use clean %eflags with 677*479ab7f0SSascha Wildner popfl # string ops dec 678*479ab7f0SSascha Wildner xorw %ax,%ax # Reset seg 679*479ab7f0SSascha Wildner movw %ax,%ds # regs 680*479ab7f0SSascha Wildner movw %ax,%es # (%ss is already 0) 681*479ab7f0SSascha Wildner lidt idtdesc # Set IDT 682*479ab7f0SSascha Wildner lgdt gdtdesc # Set GDT 683*479ab7f0SSascha Wildner mov %cr0,%eax # Switch to protected 684*479ab7f0SSascha Wildner inc %ax # mode 685*479ab7f0SSascha Wildner mov %eax,%cr0 # 686*479ab7f0SSascha Wildner ljmp $SEL_SCODE,$rret_tramp.1 # To 32-bit code 687*479ab7f0SSascha Wildner .code32 688*479ab7f0SSascha Wildnerrret_tramp.1: xorl %ecx,%ecx # Zero 689*479ab7f0SSascha Wildner movb $SEL_SDATA,%cl # Setup 690*479ab7f0SSascha Wildner movw %cx,%ss # 32-bit 691*479ab7f0SSascha Wildner movw %cx,%ds # seg 692*479ab7f0SSascha Wildner movw %cx,%es # regs 693*479ab7f0SSascha Wildner movl MEM_BTX_ESPR-0x04,%esp # Switch to kernel stack 694*479ab7f0SSascha Wildner leal 0x44(%esp,1),%esi # Base of frame 695*479ab7f0SSascha Wildner andb $~0x2,tss_desc+0x5 # Clear TSS busy 696*479ab7f0SSascha Wildner movb $SEL_TSS,%cl # Set task 697*479ab7f0SSascha Wildner ltr %cx # register 698*479ab7f0SSascha Wildner/* 699*479ab7f0SSascha Wildner * Now we are back in protected mode. The kernel stack frame set up 700*479ab7f0SSascha Wildner * before entering real mode is still intact. For hardware interrupts, 701*479ab7f0SSascha Wildner * leave the frame unchanged. 702*479ab7f0SSascha Wildner */ 703*479ab7f0SSascha Wildner cmpl $0,MEM_BTX_ESPR-0x08 # Leave saved regs unchanged 704*479ab7f0SSascha Wildner jz rret_tramp.3 # for hardware ints 705*479ab7f0SSascha Wildner/* 706*479ab7f0SSascha Wildner * For V86 calls, copy the registers off of the real mode stack onto 707*479ab7f0SSascha Wildner * the kernel stack as we want their updated values. Also, initialize 708*479ab7f0SSascha Wildner * the segment registers on the kernel stack. 709*479ab7f0SSascha Wildner * 710*479ab7f0SSascha Wildner * Note that the %esp in the kernel stack after this is garbage, but popa 711*479ab7f0SSascha Wildner * ignores it, so we don't have to fix it up. 712*479ab7f0SSascha Wildner */ 713*479ab7f0SSascha Wildner leal -0x18(%esi),%edi # Kernel stack GP regs 714*479ab7f0SSascha Wildner pushl %esi # Save 715*479ab7f0SSascha Wildner movl $MEM_BTX_ESPR-0x0c,%esi # Real mode stack GP regs 716*479ab7f0SSascha Wildner movl $8,%ecx # Copy GP regs from 717*479ab7f0SSascha Wildner rep # real mode stack 718*479ab7f0SSascha Wildner movsl # to kernel stack 719*479ab7f0SSascha Wildner movl $SEL_UDATA,%eax # Selector for data seg regs 720*479ab7f0SSascha Wildner movl $4,%ecx # Initialize %ds, 721*479ab7f0SSascha Wildner rep # %es, %fs, and 722*479ab7f0SSascha Wildner stosl # %gs 723*479ab7f0SSascha Wildner/* 724*479ab7f0SSascha Wildner * For V86 calls, copy the saved seg regs on the real mode stack back 725*479ab7f0SSascha Wildner * over to the btx_v86 structure. Also, conditionally update the 726*479ab7f0SSascha Wildner * saved eflags on the kernel stack based on the flags from the user. 727*479ab7f0SSascha Wildner */ 728*479ab7f0SSascha Wildner movl MEM_BTX_ESPR-0x08,%ecx # Get btx_v86 ptr 729*479ab7f0SSascha Wildner leal V86_GS(%ecx),%edi # %edi => btx_v86 seg regs 730*479ab7f0SSascha Wildner leal MEM_BTX_ESPR-0x2c,%esi # %esi => real mode seg regs 731*479ab7f0SSascha Wildner xchgl %ecx,%edx # Save btx_v86 ptr 732*479ab7f0SSascha Wildner movl $4,%ecx # Copy seg regs 733*479ab7f0SSascha Wildner rep # from real mode stack 734*479ab7f0SSascha Wildner movsl # to btx_v86 735*479ab7f0SSascha Wildner popl %esi # Restore 736*479ab7f0SSascha Wildner movl V86_CTL(%edx),%edx # Read V86 control flags 737*479ab7f0SSascha Wildner testl $V86F_FLAGS,%edx # User wants flags? 738*479ab7f0SSascha Wildner jz rret_tramp.3 # No 739*479ab7f0SSascha Wildner movl MEM_BTX_ESPR-0x3c,%eax # Read real mode flags 740*479ab7f0SSascha Wildner andl $~(PSL_T|PSL_NT),%eax # Clear unsafe flags 741*479ab7f0SSascha Wildner movw %ax,-0x08(%esi) # Update user flags (low 16) 742*479ab7f0SSascha Wildner/* 743*479ab7f0SSascha Wildner * Return to the user task 744*479ab7f0SSascha Wildner */ 745*479ab7f0SSascha Wildnerrret_tramp.3: popl %es # Restore 746*479ab7f0SSascha Wildner popl %ds # seg 747*479ab7f0SSascha Wildner popl %fs # regs 748*479ab7f0SSascha Wildner popl %gs 749*479ab7f0SSascha Wildner popal # Restore gp regs 750*479ab7f0SSascha Wildner addl $4,%esp # Discard int no 751*479ab7f0SSascha Wildner iret # Return to user mode 752*479ab7f0SSascha Wildner 753*479ab7f0SSascha Wildner/* 754*479ab7f0SSascha Wildner * System Call. 755*479ab7f0SSascha Wildner */ 756*479ab7f0SSascha Wildnerintx30: cmpl $SYS_EXEC,%eax # Exec system call? 757*479ab7f0SSascha Wildner jne intx30.1 # No 758*479ab7f0SSascha Wildner pushl %ss # Set up 759*479ab7f0SSascha Wildner popl %es # all 760*479ab7f0SSascha Wildner pushl %es # segment 761*479ab7f0SSascha Wildner popl %ds # registers 762*479ab7f0SSascha Wildner pushl %ds # for the 763*479ab7f0SSascha Wildner popl %fs # program 764*479ab7f0SSascha Wildner pushl %fs # were 765*479ab7f0SSascha Wildner popl %gs # invoking 766*479ab7f0SSascha Wildner movl $MEM_BTX_USR,%eax # User base address 767*479ab7f0SSascha Wildner addl 0xc(%esp,1),%eax # Change to user 768*479ab7f0SSascha Wildner leal 0x4(%eax),%esp # stack 769*479ab7f0SSascha Wildner popl %eax # Call 770*479ab7f0SSascha Wildner call *%eax # program 771*479ab7f0SSascha Wildnerintx30.1: orb $0x1,%ss:btx_hdr+0x7 # Flag reboot 772*479ab7f0SSascha Wildner jmp exit # Exit 773*479ab7f0SSascha Wildner 774*479ab7f0SSascha Wildner/* 775*479ab7f0SSascha Wildner * Dump structure [EBX] to [EDI], using format string [ESI]. 776*479ab7f0SSascha Wildner */ 777*479ab7f0SSascha Wildnerdump.0: stosb # Save char 778*479ab7f0SSascha Wildnerdump: lodsb # Load char 779*479ab7f0SSascha Wildner testb %al,%al # End of string? 780*479ab7f0SSascha Wildner jz dump.10 # Yes 781*479ab7f0SSascha Wildner testb $0x80,%al # Control? 782*479ab7f0SSascha Wildner jz dump.0 # No 783*479ab7f0SSascha Wildner movb %al,%ch # Save control 784*479ab7f0SSascha Wildner movb $'=',%al # Append 785*479ab7f0SSascha Wildner stosb # "=" 786*479ab7f0SSascha Wildner lodsb # Get offset 787*479ab7f0SSascha Wildner pushl %esi # Save 788*479ab7f0SSascha Wildner movsbl %al,%esi # To 789*479ab7f0SSascha Wildner addl %ebx,%esi # pointer 790*479ab7f0SSascha Wildner testb $DMP_X16,%ch # Dump word? 791*479ab7f0SSascha Wildner jz dump.1 # No 792*479ab7f0SSascha Wildner lodsw # Get and 793*479ab7f0SSascha Wildner call hex16 # dump it 794*479ab7f0SSascha Wildnerdump.1: testb $DMP_X32,%ch # Dump long? 795*479ab7f0SSascha Wildner jz dump.2 # No 796*479ab7f0SSascha Wildner lodsl # Get and 797*479ab7f0SSascha Wildner call hex32 # dump it 798*479ab7f0SSascha Wildnerdump.2: testb $DMP_MEM,%ch # Dump memory? 799*479ab7f0SSascha Wildner jz dump.8 # No 800*479ab7f0SSascha Wildner pushl %ds # Save 801*479ab7f0SSascha Wildner testl $PSL_VM,0x50(%ebx) # V86 mode? 802*479ab7f0SSascha Wildner jnz dump.3 # Yes 803*479ab7f0SSascha Wildner verr 0x4(%esi) # Readable selector? 804*479ab7f0SSascha Wildner jnz dump.3 # No 805*479ab7f0SSascha Wildner ldsl (%esi),%esi # Load pointer 806*479ab7f0SSascha Wildner jmp dump.4 # Join common code 807*479ab7f0SSascha Wildnerdump.3: lodsl # Set offset 808*479ab7f0SSascha Wildner xchgl %eax,%edx # Save 809*479ab7f0SSascha Wildner lodsl # Get segment 810*479ab7f0SSascha Wildner shll $0x4,%eax # * 0x10 811*479ab7f0SSascha Wildner addl %edx,%eax # + offset 812*479ab7f0SSascha Wildner xchgl %eax,%esi # Set pointer 813*479ab7f0SSascha Wildnerdump.4: movb $2,%dl # Num lines 814*479ab7f0SSascha Wildnerdump.4a: movb $0x10,%cl # Bytes to dump 815*479ab7f0SSascha Wildnerdump.5: lodsb # Get byte and 816*479ab7f0SSascha Wildner call hex8 # dump it 817*479ab7f0SSascha Wildner decb %cl # Keep count 818*479ab7f0SSascha Wildner jz dump.6a # If done 819*479ab7f0SSascha Wildner movb $'-',%al # Separator 820*479ab7f0SSascha Wildner cmpb $0x8,%cl # Half way? 821*479ab7f0SSascha Wildner je dump.6 # Yes 822*479ab7f0SSascha Wildner movb $' ',%al # Use space 823*479ab7f0SSascha Wildnerdump.6: stosb # Save separator 824*479ab7f0SSascha Wildner jmp dump.5 # Continue 825*479ab7f0SSascha Wildnerdump.6a: decb %dl # Keep count 826*479ab7f0SSascha Wildner jz dump.7 # If done 827*479ab7f0SSascha Wildner movb $0xa,%al # Line feed 828*479ab7f0SSascha Wildner stosb # Save one 829*479ab7f0SSascha Wildner movb $7,%cl # Leading 830*479ab7f0SSascha Wildner movb $' ',%al # spaces 831*479ab7f0SSascha Wildnerdump.6b: stosb # Dump 832*479ab7f0SSascha Wildner decb %cl # spaces 833*479ab7f0SSascha Wildner jnz dump.6b 834*479ab7f0SSascha Wildner jmp dump.4a # Next line 835*479ab7f0SSascha Wildnerdump.7: popl %ds # Restore 836*479ab7f0SSascha Wildnerdump.8: popl %esi # Restore 837*479ab7f0SSascha Wildner movb $0xa,%al # Line feed 838*479ab7f0SSascha Wildner testb $DMP_EOL,%ch # End of line? 839*479ab7f0SSascha Wildner jnz dump.9 # Yes 840*479ab7f0SSascha Wildner movb $' ',%al # Use spaces 841*479ab7f0SSascha Wildner stosb # Save one 842*479ab7f0SSascha Wildnerdump.9: jmp dump.0 # Continue 843*479ab7f0SSascha Wildnerdump.10: stosb # Terminate string 844*479ab7f0SSascha Wildner ret # To caller 845*479ab7f0SSascha Wildner 846*479ab7f0SSascha Wildner/* 847*479ab7f0SSascha Wildner * Convert EAX, AX, or AL to hex, saving the result to [EDI]. 848*479ab7f0SSascha Wildner */ 849*479ab7f0SSascha Wildnerhex32: pushl %eax # Save 850*479ab7f0SSascha Wildner shrl $0x10,%eax # Do upper 851*479ab7f0SSascha Wildner call hex16 # 16 852*479ab7f0SSascha Wildner popl %eax # Restore 853*479ab7f0SSascha Wildnerhex16: call hex16.1 # Do upper 8 854*479ab7f0SSascha Wildnerhex16.1: xchgb %ah,%al # Save/restore 855*479ab7f0SSascha Wildnerhex8: pushl %eax # Save 856*479ab7f0SSascha Wildner shrb $0x4,%al # Do upper 857*479ab7f0SSascha Wildner call hex8.1 # 4 858*479ab7f0SSascha Wildner popl %eax # Restore 859*479ab7f0SSascha Wildnerhex8.1: andb $0xf,%al # Get lower 4 860*479ab7f0SSascha Wildner cmpb $0xa,%al # Convert 861*479ab7f0SSascha Wildner sbbb $0x69,%al # to hex 862*479ab7f0SSascha Wildner das # digit 863*479ab7f0SSascha Wildner orb $0x20,%al # To lower case 864*479ab7f0SSascha Wildner stosb # Save char 865*479ab7f0SSascha Wildner ret # (Recursive) 866*479ab7f0SSascha Wildner 867*479ab7f0SSascha Wildner/* 868*479ab7f0SSascha Wildner * Output zero-terminated string [ESI] to the console. 869*479ab7f0SSascha Wildner */ 870*479ab7f0SSascha Wildnerputstr.0: call putchr # Output char 871*479ab7f0SSascha Wildnerputstr: lodsb # Load char 872*479ab7f0SSascha Wildner testb %al,%al # End of string? 873*479ab7f0SSascha Wildner jnz putstr.0 # No 874*479ab7f0SSascha Wildner ret # To caller 875*479ab7f0SSascha Wildner#ifdef BTX_SERIAL 876*479ab7f0SSascha Wildner .set SIO_PRT,SIOPRT # Base port 877*479ab7f0SSascha Wildner .set SIO_FMT,SIOFMT # 8N1 878*479ab7f0SSascha Wildner .set SIO_DIV,(115200/SIOSPD) # 115200 / SPD 879*479ab7f0SSascha Wildner 880*479ab7f0SSascha Wildner/* 881*479ab7f0SSascha Wildner * void sio_init(void) 882*479ab7f0SSascha Wildner */ 883*479ab7f0SSascha Wildnersio_init: movw $SIO_PRT+0x3,%dx # Data format reg 884*479ab7f0SSascha Wildner movb $SIO_FMT|0x80,%al # Set format 885*479ab7f0SSascha Wildner outb %al,(%dx) # and DLAB 886*479ab7f0SSascha Wildner pushl %edx # Save 887*479ab7f0SSascha Wildner subb $0x3,%dl # Divisor latch reg 888*479ab7f0SSascha Wildner movw $SIO_DIV,%ax # Set 889*479ab7f0SSascha Wildner outw %ax,(%dx) # BPS 890*479ab7f0SSascha Wildner popl %edx # Restore 891*479ab7f0SSascha Wildner movb $SIO_FMT,%al # Clear 892*479ab7f0SSascha Wildner outb %al,(%dx) # DLAB 893*479ab7f0SSascha Wildner incl %edx # Modem control reg 894*479ab7f0SSascha Wildner movb $0x3,%al # Set RTS, 895*479ab7f0SSascha Wildner outb %al,(%dx) # DTR 896*479ab7f0SSascha Wildner incl %edx # Line status reg 897*479ab7f0SSascha Wildner 898*479ab7f0SSascha Wildner/* 899*479ab7f0SSascha Wildner * void sio_flush(void) 900*479ab7f0SSascha Wildner */ 901*479ab7f0SSascha Wildnersio_flush.0: call sio_getc.1 # Get character 902*479ab7f0SSascha Wildnersio_flush: call sio_ischar # Check for character 903*479ab7f0SSascha Wildner jnz sio_flush.0 # Till none 904*479ab7f0SSascha Wildner ret # To caller 905*479ab7f0SSascha Wildner 906*479ab7f0SSascha Wildner/* 907*479ab7f0SSascha Wildner * void sio_putc(int c) 908*479ab7f0SSascha Wildner */ 909*479ab7f0SSascha Wildnersio_putc: movw $SIO_PRT+0x5,%dx # Line status reg 910*479ab7f0SSascha Wildner xor %ecx,%ecx # Timeout 911*479ab7f0SSascha Wildner movb $0x40,%ch # counter 912*479ab7f0SSascha Wildnersio_putc.1: inb (%dx),%al # Transmitter 913*479ab7f0SSascha Wildner testb $0x20,%al # buffer empty? 914*479ab7f0SSascha Wildner loopz sio_putc.1 # No 915*479ab7f0SSascha Wildner jz sio_putc.2 # If timeout 916*479ab7f0SSascha Wildner movb 0x4(%esp,1),%al # Get character 917*479ab7f0SSascha Wildner subb $0x5,%dl # Transmitter hold reg 918*479ab7f0SSascha Wildner outb %al,(%dx) # Write character 919*479ab7f0SSascha Wildnersio_putc.2: ret $0x4 # To caller 920*479ab7f0SSascha Wildner 921*479ab7f0SSascha Wildner/* 922*479ab7f0SSascha Wildner * int sio_getc(void) 923*479ab7f0SSascha Wildner */ 924*479ab7f0SSascha Wildnersio_getc: call sio_ischar # Character available? 925*479ab7f0SSascha Wildner jz sio_getc # No 926*479ab7f0SSascha Wildnersio_getc.1: subb $0x5,%dl # Receiver buffer reg 927*479ab7f0SSascha Wildner inb (%dx),%al # Read character 928*479ab7f0SSascha Wildner ret # To caller 929*479ab7f0SSascha Wildner 930*479ab7f0SSascha Wildner/* 931*479ab7f0SSascha Wildner * int sio_ischar(void) 932*479ab7f0SSascha Wildner */ 933*479ab7f0SSascha Wildnersio_ischar: movw $SIO_PRT+0x5,%dx # Line status register 934*479ab7f0SSascha Wildner xorl %eax,%eax # Zero 935*479ab7f0SSascha Wildner inb (%dx),%al # Received data 936*479ab7f0SSascha Wildner andb $0x1,%al # ready? 937*479ab7f0SSascha Wildner ret # To caller 938*479ab7f0SSascha Wildner 939*479ab7f0SSascha Wildner/* 940*479ab7f0SSascha Wildner * Output character AL to the serial console. 941*479ab7f0SSascha Wildner */ 942*479ab7f0SSascha Wildnerputchr: pusha # Save 943*479ab7f0SSascha Wildner cmpb $10, %al # is it a newline? 944*479ab7f0SSascha Wildner jne putchr.1 # no?, then leave 945*479ab7f0SSascha Wildner push $13 # output a carriage 946*479ab7f0SSascha Wildner call sio_putc # return first 947*479ab7f0SSascha Wildner movb $10, %al # restore %al 948*479ab7f0SSascha Wildnerputchr.1: pushl %eax # Push the character 949*479ab7f0SSascha Wildner # onto the stack 950*479ab7f0SSascha Wildner call sio_putc # Output the character 951*479ab7f0SSascha Wildner popa # Restore 952*479ab7f0SSascha Wildner ret # To caller 953*479ab7f0SSascha Wildner#else 954*479ab7f0SSascha Wildner/* 955*479ab7f0SSascha Wildner * Output character AL to the console. 956*479ab7f0SSascha Wildner */ 957*479ab7f0SSascha Wildnerputchr: pusha # Save 958*479ab7f0SSascha Wildner xorl %ecx,%ecx # Zero for loops 959*479ab7f0SSascha Wildner movb $SCR_MAT,%ah # Mode/attribute 960*479ab7f0SSascha Wildner movl $BDA_POS,%ebx # BDA pointer 961*479ab7f0SSascha Wildner movw (%ebx),%dx # Cursor position 962*479ab7f0SSascha Wildner movl $0xb8000,%edi # Regen buffer (color) 963*479ab7f0SSascha Wildner cmpb %ah,BDA_SCR-BDA_POS(%ebx) # Mono mode? 964*479ab7f0SSascha Wildner jne putchr.1 # No 965*479ab7f0SSascha Wildner xorw %di,%di # Regen buffer (mono) 966*479ab7f0SSascha Wildnerputchr.1: cmpb $0xa,%al # New line? 967*479ab7f0SSascha Wildner je putchr.2 # Yes 968*479ab7f0SSascha Wildner xchgl %eax,%ecx # Save char 969*479ab7f0SSascha Wildner movb $SCR_COL,%al # Columns per row 970*479ab7f0SSascha Wildner mulb %dh # * row position 971*479ab7f0SSascha Wildner addb %dl,%al # + column 972*479ab7f0SSascha Wildner adcb $0x0,%ah # position 973*479ab7f0SSascha Wildner shll %eax # * 2 974*479ab7f0SSascha Wildner xchgl %eax,%ecx # Swap char, offset 975*479ab7f0SSascha Wildner movw %ax,(%edi,%ecx,1) # Write attr:char 976*479ab7f0SSascha Wildner incl %edx # Bump cursor 977*479ab7f0SSascha Wildner cmpb $SCR_COL,%dl # Beyond row? 978*479ab7f0SSascha Wildner jb putchr.3 # No 979*479ab7f0SSascha Wildnerputchr.2: xorb %dl,%dl # Zero column 980*479ab7f0SSascha Wildner incb %dh # Bump row 981*479ab7f0SSascha Wildnerputchr.3: cmpb $SCR_ROW,%dh # Beyond screen? 982*479ab7f0SSascha Wildner jb putchr.4 # No 983*479ab7f0SSascha Wildner leal 2*SCR_COL(%edi),%esi # New top line 984*479ab7f0SSascha Wildner movw $(SCR_ROW-1)*SCR_COL/2,%cx # Words to move 985*479ab7f0SSascha Wildner rep # Scroll 986*479ab7f0SSascha Wildner movsl # screen 987*479ab7f0SSascha Wildner movb $0x20,%al # Space 988*479ab7f0SSascha Wildner movb $SCR_COL,%cl # Columns to clear 989*479ab7f0SSascha Wildner rep # Clear 990*479ab7f0SSascha Wildner stosw # line 991*479ab7f0SSascha Wildner movb $SCR_ROW-1,%dh # Bottom line 992*479ab7f0SSascha Wildnerputchr.4: movw %dx,(%ebx) # Update position 993*479ab7f0SSascha Wildner popa # Restore 994*479ab7f0SSascha Wildner ret # To caller 995*479ab7f0SSascha Wildner#endif 996*479ab7f0SSascha Wildner 997*479ab7f0SSascha Wildner .code16 998*479ab7f0SSascha Wildner/* 999*479ab7f0SSascha Wildner * Real Mode Hardware interrupt jump table. 1000*479ab7f0SSascha Wildner */ 1001*479ab7f0SSascha Wildnerintr20: push $0x8 # Int 0x20: IRQ0 1002*479ab7f0SSascha Wildner jmp int_hwr # V86 int 0x8 1003*479ab7f0SSascha Wildner push $0x9 # Int 0x21: IRQ1 1004*479ab7f0SSascha Wildner jmp int_hwr # V86 int 0x9 1005*479ab7f0SSascha Wildner push $0xa # Int 0x22: IRQ2 1006*479ab7f0SSascha Wildner jmp int_hwr # V86 int 0xa 1007*479ab7f0SSascha Wildner push $0xb # Int 0x23: IRQ3 1008*479ab7f0SSascha Wildner jmp int_hwr # V86 int 0xb 1009*479ab7f0SSascha Wildner push $0xc # Int 0x24: IRQ4 1010*479ab7f0SSascha Wildner jmp int_hwr # V86 int 0xc 1011*479ab7f0SSascha Wildner push $0xd # Int 0x25: IRQ5 1012*479ab7f0SSascha Wildner jmp int_hwr # V86 int 0xd 1013*479ab7f0SSascha Wildner push $0xe # Int 0x26: IRQ6 1014*479ab7f0SSascha Wildner jmp int_hwr # V86 int 0xe 1015*479ab7f0SSascha Wildner push $0xf # Int 0x27: IRQ7 1016*479ab7f0SSascha Wildner jmp int_hwr # V86 int 0xf 1017*479ab7f0SSascha Wildner push $0x70 # Int 0x28: IRQ8 1018*479ab7f0SSascha Wildner jmp int_hwr # V86 int 0x70 1019*479ab7f0SSascha Wildner push $0x71 # Int 0x29: IRQ9 1020*479ab7f0SSascha Wildner jmp int_hwr # V86 int 0x71 1021*479ab7f0SSascha Wildner push $0x72 # Int 0x2a: IRQ10 1022*479ab7f0SSascha Wildner jmp int_hwr # V86 int 0x72 1023*479ab7f0SSascha Wildner push $0x73 # Int 0x2b: IRQ11 1024*479ab7f0SSascha Wildner jmp int_hwr # V86 int 0x73 1025*479ab7f0SSascha Wildner push $0x74 # Int 0x2c: IRQ12 1026*479ab7f0SSascha Wildner jmp int_hwr # V86 int 0x74 1027*479ab7f0SSascha Wildner push $0x75 # Int 0x2d: IRQ13 1028*479ab7f0SSascha Wildner jmp int_hwr # V86 int 0x75 1029*479ab7f0SSascha Wildner push $0x76 # Int 0x2e: IRQ14 1030*479ab7f0SSascha Wildner jmp int_hwr # V86 int 0x76 1031*479ab7f0SSascha Wildner push $0x77 # Int 0x2f: IRQ15 1032*479ab7f0SSascha Wildner jmp int_hwr # V86 int 0x77 1033*479ab7f0SSascha Wildner/* 1034*479ab7f0SSascha Wildner * Reflect hardware interrupts in real mode. 1035*479ab7f0SSascha Wildner */ 1036*479ab7f0SSascha Wildnerint_hwr: push %ax # Save 1037*479ab7f0SSascha Wildner push %ds # Save 1038*479ab7f0SSascha Wildner push %bp # Save 1039*479ab7f0SSascha Wildner mov %sp,%bp # Address stack frame 1040*479ab7f0SSascha Wildner xchg %bx,6(%bp) # Swap BX, int no 1041*479ab7f0SSascha Wildner xor %ax,%ax # Set %ds:%bx to 1042*479ab7f0SSascha Wildner shl $2,%bx # point to 1043*479ab7f0SSascha Wildner mov %ax,%ds # IDT entry 1044*479ab7f0SSascha Wildner mov (%bx),%ax # Load IP 1045*479ab7f0SSascha Wildner mov 2(%bx),%bx # Load CS 1046*479ab7f0SSascha Wildner xchg %ax,4(%bp) # Swap saved %ax,%bx with 1047*479ab7f0SSascha Wildner xchg %bx,6(%bp) # CS:IP of handler 1048*479ab7f0SSascha Wildner pop %bp # Restore 1049*479ab7f0SSascha Wildner pop %ds # Restore 1050*479ab7f0SSascha Wildner lret # Jump to handler 1051*479ab7f0SSascha Wildner 1052*479ab7f0SSascha Wildner/* 1053*479ab7f0SSascha Wildner * Global descriptor table. 1054*479ab7f0SSascha Wildner * 1055*479ab7f0SSascha Wildner * 16: segment extent lsb 1056*479ab7f0SSascha Wildner * 24: segment base lsb 1057*479ab7f0SSascha Wildner * 1058*479ab7f0SSascha Wildner * 5:TYPE 1059*479ab7f0SSascha Wildner * 2:DPL 1060*479ab7f0SSascha Wildner * 1:PRESENT 1061*479ab7f0SSascha Wildner * 1062*479ab7f0SSascha Wildner * 4: segment extent msb 1063*479ab7f0SSascha Wildner * 2: unused 1064*479ab7f0SSascha Wildner * 1: 32 bit, else 16 bit 1065*479ab7f0SSascha Wildner * 1: limit granularity byte/page units 1066*479ab7f0SSascha Wildner 1067*479ab7f0SSascha Wildner * 8: segment base msb 1068*479ab7f0SSascha Wildner * 1069*479ab7f0SSascha Wildner */ 1070*479ab7f0SSascha Wildner .p2align 4 1071*479ab7f0SSascha Wildnergdt: .word 0x0,0x0,0x0,0x0 # Null entry 1072*479ab7f0SSascha Wildner .word 0xffff,0x0,0x9a00,0xcf # SEL_SCODE 1073*479ab7f0SSascha Wildner .word 0xffff,0x0,0x9200,0xcf # SEL_SDATA 1074*479ab7f0SSascha Wildner .word 0xffff,0x0,0x9a00,0x0 # SEL_RCODE 1075*479ab7f0SSascha Wildner .word 0xffff,0x0,0x9200,0x0 # SEL_RDATA 1076*479ab7f0SSascha Wildner .word 0xffff,MEM_BTX_USR,0xfa00,0xcf# SEL_UCODE 1077*479ab7f0SSascha Wildner .word 0xffff,MEM_BTX_USR,0xf200,0xcf# SEL_UDATA 1078*479ab7f0SSascha Wildnertss_desc: .word _TSSLM,MEM_BTX_TSS,0x8900,0x0 # SEL_TSS 1079*479ab7f0SSascha Wildnergdt.1: 1080*479ab7f0SSascha Wildner/* 1081*479ab7f0SSascha Wildner * Pseudo-descriptors. 1082*479ab7f0SSascha Wildner */ 1083*479ab7f0SSascha Wildnergdtdesc: .word gdt.1-gdt-1,gdt,0x0 # GDT 1084*479ab7f0SSascha Wildneridtdesc: .word _IDTLM,MEM_BTX_IDT,0x0 # IDT 1085*479ab7f0SSascha Wildnerivtdesc: .word 0x400-0x0-1,0x0,0x0 # IVT 1086*479ab7f0SSascha Wildner 1087*479ab7f0SSascha Wildner/* 1088*479ab7f0SSascha Wildner * IDT construction control string. 1089*479ab7f0SSascha Wildner */ 1090*479ab7f0SSascha Wildneridtctl: .byte 0x10, 0x8e # Int 0x0-0xf 1091*479ab7f0SSascha Wildner .word 0x7dfb,intx00 # (exceptions) 1092*479ab7f0SSascha Wildner .byte 0x10, 0x8e # Int 0x10 1093*479ab7f0SSascha Wildner .word 0x1, intx10 # (exception) 1094*479ab7f0SSascha Wildner .byte 0x10, 0x8e # Int 0x20-0x2f 1095*479ab7f0SSascha Wildner .word 0xffff,intx20 # (hardware) 1096*479ab7f0SSascha Wildner .byte 0x1, 0xee # int 0x30 1097*479ab7f0SSascha Wildner .word 0x1, intx30 # (system call) 1098*479ab7f0SSascha Wildner .byte 0x2, 0xee # Int 0x31-0x32 1099*479ab7f0SSascha Wildner .word 0x1, intx31 # (V86, null) 1100*479ab7f0SSascha Wildner .byte 0x0 # End of string 1101*479ab7f0SSascha Wildner 1102*479ab7f0SSascha Wildner/* 1103*479ab7f0SSascha Wildner * Dump format string. 1104*479ab7f0SSascha Wildner */ 1105*479ab7f0SSascha Wildnerdmpfmt: .byte '\n' # "\n" 1106*479ab7f0SSascha Wildner .ascii "int" # "int=" 1107*479ab7f0SSascha Wildner .byte 0x80|DMP_X32, 0x40 # "00000000 " 1108*479ab7f0SSascha Wildner .ascii "err" # "err=" 1109*479ab7f0SSascha Wildner .byte 0x80|DMP_X32, 0x44 # "00000000 " 1110*479ab7f0SSascha Wildner .ascii "efl" # "efl=" 1111*479ab7f0SSascha Wildner .byte 0x80|DMP_X32, 0x50 # "00000000 " 1112*479ab7f0SSascha Wildner .ascii "eip" # "eip=" 1113*479ab7f0SSascha Wildner .byte 0x80|DMP_X32|DMP_EOL,0x48 # "00000000\n" 1114*479ab7f0SSascha Wildner .ascii "eax" # "eax=" 1115*479ab7f0SSascha Wildner .byte 0x80|DMP_X32, 0x34 # "00000000 " 1116*479ab7f0SSascha Wildner .ascii "ebx" # "ebx=" 1117*479ab7f0SSascha Wildner .byte 0x80|DMP_X32, 0x28 # "00000000 " 1118*479ab7f0SSascha Wildner .ascii "ecx" # "ecx=" 1119*479ab7f0SSascha Wildner .byte 0x80|DMP_X32, 0x30 # "00000000 " 1120*479ab7f0SSascha Wildner .ascii "edx" # "edx=" 1121*479ab7f0SSascha Wildner .byte 0x80|DMP_X32|DMP_EOL,0x2c # "00000000\n" 1122*479ab7f0SSascha Wildner .ascii "esi" # "esi=" 1123*479ab7f0SSascha Wildner .byte 0x80|DMP_X32, 0x1c # "00000000 " 1124*479ab7f0SSascha Wildner .ascii "edi" # "edi=" 1125*479ab7f0SSascha Wildner .byte 0x80|DMP_X32, 0x18 # "00000000 " 1126*479ab7f0SSascha Wildner .ascii "ebp" # "ebp=" 1127*479ab7f0SSascha Wildner .byte 0x80|DMP_X32, 0x20 # "00000000 " 1128*479ab7f0SSascha Wildner .ascii "esp" # "esp=" 1129*479ab7f0SSascha Wildner .byte 0x80|DMP_X32|DMP_EOL,0x0 # "00000000\n" 1130*479ab7f0SSascha Wildner .ascii "cs" # "cs=" 1131*479ab7f0SSascha Wildner .byte 0x80|DMP_X16, 0x4c # "0000 " 1132*479ab7f0SSascha Wildner .ascii "ds" # "ds=" 1133*479ab7f0SSascha Wildner .byte 0x80|DMP_X16, 0xc # "0000 " 1134*479ab7f0SSascha Wildner .ascii "es" # "es=" 1135*479ab7f0SSascha Wildner .byte 0x80|DMP_X16, 0x8 # "0000 " 1136*479ab7f0SSascha Wildner .ascii " " # " " 1137*479ab7f0SSascha Wildner .ascii "fs" # "fs=" 1138*479ab7f0SSascha Wildner .byte 0x80|DMP_X16, 0x10 # "0000 " 1139*479ab7f0SSascha Wildner .ascii "gs" # "gs=" 1140*479ab7f0SSascha Wildner .byte 0x80|DMP_X16, 0x14 # "0000 " 1141*479ab7f0SSascha Wildner .ascii "ss" # "ss=" 1142*479ab7f0SSascha Wildner .byte 0x80|DMP_X16|DMP_EOL,0x4 # "0000\n" 1143*479ab7f0SSascha Wildner .ascii "cs:eip" # "cs:eip=" 1144*479ab7f0SSascha Wildner .byte 0x80|DMP_MEM|DMP_EOL,0x48 # "00 00 ... 00 00\n" 1145*479ab7f0SSascha Wildner .ascii "ss:esp" # "ss:esp=" 1146*479ab7f0SSascha Wildner .byte 0x80|DMP_MEM|DMP_EOL,0x0 # "00 00 ... 00 00\n" 1147*479ab7f0SSascha Wildner .asciz "BTX halted\n" # End 1148*479ab7f0SSascha Wildner/* 1149*479ab7f0SSascha Wildner * Bad VM86 call panic 1150*479ab7f0SSascha Wildner */ 1151*479ab7f0SSascha Wildnerbadvm86: .asciz "Invalid VM86 Request\n" 1152*479ab7f0SSascha Wildner 1153*479ab7f0SSascha Wildner 1154*479ab7f0SSascha Wildner/* 1155*479ab7f0SSascha Wildner * End of BTX memory. 1156*479ab7f0SSascha Wildner */ 1157*479ab7f0SSascha Wildner .p2align 4 1158*479ab7f0SSascha Wildnerbreak: 1159