vm86bios.s revision 39046
1/*- 2 * Copyright (c) 1998 Jonathan Lemon 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $Id: vm86bios.s,v 1.3 1998/07/27 16:45:05 jlemon Exp $ 27 */ 28 29#include "opt_vm86.h" 30 31#include <machine/asmacros.h> /* miscellaneous asm macros */ 32#include <machine/trap.h> 33 34#include "assym.s" 35 36#define SCR_NEWPTD PCB_ESI /* readability macros */ 37#define SCR_VMFRAME PCB_EBP /* see vm86.c for explanation */ 38#define SCR_STACK PCB_ESP 39#define SCR_PGTABLE PCB_EBX 40#define SCR_ARGFRAME PCB_EIP 41#define SCR_TSS0 PCB_FS 42#define SCR_TSS1 PCB_GS 43 44 .data 45 ALIGN_DATA 46 47 .globl _in_vm86call, _vm86pcb 48 49_in_vm86call: .long 0 50_vm86pcb: .long 0 51 52 .text 53 54/* 55 * vm86_bioscall(struct trapframe_vm86 *vm86) 56 */ 57ENTRY(vm86_bioscall) 58 movl _vm86pcb,%edx /* scratch data area */ 59 movl 4(%esp),%eax 60 movl %eax,SCR_ARGFRAME(%edx) /* save argument pointer */ 61 pushl %ebx 62 pushl %ebp 63 pushl %esi 64 pushl %edi 65 pushl %fs 66 pushl %gs 67 68#ifdef SMP 69 pushl %edx 70 ALIGN_LOCK /* Get global lock */ 71 popl %edx 72#endif 73 movl _curproc,%ecx 74 pushl %ecx /* save _curproc value */ 75 testl %ecx,%ecx 76 je 1f /* no process to save */ 77 78#if NNPX > 0 79 cmpl %ecx,_npxproc /* do we need to save fp? */ 80 jne 1f 81 pushl %edx 82 movl P_ADDR(%ecx),%ecx 83 addl $PCB_SAVEFPU,%ecx 84 pushl %ecx 85 call _npxsave 86 popl %ecx 87 popl %edx /* recover our pcb */ 88#endif 89 901: 91 movl SCR_VMFRAME(%edx),%ebx /* target frame location */ 92 movl %ebx,%edi /* destination */ 93 movl SCR_ARGFRAME(%edx),%esi /* source (set on entry) */ 94 movl $21,%ecx /* sizeof(struct vm86frame)/4 */ 95 cld 96 rep 97 movsl /* copy frame to new stack */ 98 99 movl TF_TRAPNO(%ebx),%ebx 100 cmpl $256,%ebx 101 jb 1f /* no page frame to map */ 102 103 andl $~PAGE_MASK,%ebx 104#if 0 105 orl $PG_V|PG_RW|PG_U,%ebx /* XXX assembler error?? */ 106#endif 107 orl $0x7,%ebx 108 movl SCR_PGTABLE(%edx),%eax /* va of vm86 page table */ 109 movl %ebx,4(%eax) /* set vm86 PTE entry 1 */ 1101: 111 movl _curpcb,%eax 112 pushl %eax /* save curpcb */ 113 movl %edx,_curpcb /* set curpcb to vm86pcb */ 114 movl $0,_curproc /* erase curproc */ 115 116 movl _my_tr,%esi 117 leal _gdt(,%esi,8),%ebx /* entry in GDT */ 118 movl 0(%ebx),%eax 119 movl %eax,SCR_TSS0(%edx) /* save first word */ 120 movl 4(%ebx),%eax 121 andl $~0x200, %eax /* flip 386BSY -> 386TSS */ 122 movl %eax,SCR_TSS1(%edx) /* save second word */ 123 124 movl PCB_EXT(%edx),%edi /* vm86 tssd entry */ 125 movl 0(%edi),%eax 126 movl %eax,0(%ebx) 127 movl 4(%edi),%eax 128 movl %eax,4(%ebx) 129 shll $3,%esi /* GSEL(entry, SEL_KPL) */ 130 ltr %si 131 132 movl %cr3,%eax 133 pushl %eax /* save address space */ 134#ifdef SMP 135 movl _my_idlePTD,%ecx 136#else 137 movl _IdlePTD,%ecx 138#endif 139 movl %ecx,%ebx 140 addl $KERNBASE,%ebx /* va of Idle PTD */ 141 movl 0(%ebx),%eax 142 pushl %eax /* old ptde != 0 when booting */ 143 pushl %ebx /* keep for reuse */ 144 145 movl %esp,SCR_STACK(%edx) /* save current stack location */ 146 147 movl SCR_NEWPTD(%edx),%eax /* mapping for vm86 page table */ 148 movl %eax,0(%ebx) /* ... install as PTD entry 0 */ 149 150 movl %ecx,%cr3 /* new page tables */ 151 movl SCR_VMFRAME(%edx),%esp /* switch to new stack */ 152 153 call _vm86_prepcall /* finish setup */ 154 155 movl $1,_in_vm86call /* set flag for trap() */ 156 157 /* 158 * Return via _doreti 159 */ 160#ifdef SMP 161 ECPL_LOCK 162#ifdef CPL_AND_CML 163#error Not ready for CPL_AND_CML 164#endif 165 pushl _cpl /* cpl to restore */ 166 ECPL_UNLOCK 167#else 168 pushl _cpl /* cpl to restore */ 169#endif 170 subl $4,%esp /* dummy unit */ 171 MPLOCKED incb _intr_nesting_level 172 MEXITCOUNT 173 jmp _doreti 174 175 176/* 177 * vm86_biosret(struct trapframe_vm86 *vm86) 178 */ 179ENTRY(vm86_biosret) 180 movl _vm86pcb,%edx /* data area */ 181 182 movl 4(%esp),%esi /* source */ 183 movl SCR_ARGFRAME(%edx),%edi /* destination */ 184 movl $21,%ecx /* size */ 185 cld 186 rep 187 movsl /* copy frame to original frame */ 188 189 movl SCR_STACK(%edx),%esp /* back to old stack */ 190 popl %ebx /* saved va of Idle PTD */ 191 popl %eax 192 movl %eax,0(%ebx) /* restore old pte */ 193 popl %eax 194 movl %eax,%cr3 /* install old page table */ 195 196 movl $0,_in_vm86call /* reset trapflag */ 197 movl SCR_PGTABLE(%edx),%ebx /* va of vm86 page table */ 198 movl $0,4(%ebx) /* ...clear entry 1 */ 199 200 movl _my_tr,%esi 201 leal _gdt(,%esi,8),%ebx /* entry in GDT */ 202 movl SCR_TSS0(%edx),%eax 203 movl %eax,0(%ebx) /* restore first word */ 204 movl SCR_TSS1(%edx),%eax 205 movl %eax,4(%ebx) /* restore second word */ 206 shll $3,%esi /* GSEL(entry, SEL_KPL) */ 207 ltr %si 208 209 popl _curpcb /* restore curpcb/curproc */ 210 popl _curproc 211 movl SCR_ARGFRAME(%edx),%edx /* original stack frame */ 212 movl TF_TRAPNO(%edx),%eax /* return (trapno) */ 213 214 popl %gs 215 popl %fs 216 popl %edi 217 popl %esi 218 popl %ebp 219 popl %ebx 220 ret /* back to our normal program */ 221