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 27#include <machine/asmacros.h> /* miscellaneous asm macros */ 28#include <machine/trap.h> 29 30#include "assym.inc" 31 32#define SCR_NEWPTD PCB_ESI /* readability macros */ 33#define SCR_VMFRAME PCB_EBP /* see vm86.c for explanation */ 34#define SCR_STACK PCB_ESP 35#define SCR_PGTABLE PCB_EBX 36#define SCR_ARGFRAME PCB_EIP 37#define SCR_TSS0 PCB_VM86 38#define SCR_TSS1 (PCB_VM86+4) 39 40 .data 41 ALIGN_DATA 42 43 .globl vm86pcb 44 45vm86pcb: .long 0 46 47 .text 48 49/* 50 * vm86_bioscall(struct trapframe_vm86 *vm86) 51 */ 52ENTRY(vm86_bioscall) 53 movl vm86pcb,%edx /* scratch data area */ 54 movl 4(%esp),%eax 55 movl %eax,SCR_ARGFRAME(%edx) /* save argument pointer */ 56 pushl %ebx 57 pushl %ebp 58 pushl %esi 59 pushl %edi 60 pushl %gs 61 62 movl PCPU(CURTHREAD),%ecx 63 cmpl %ecx,PCPU(FPCURTHREAD) /* do we need to save fp? */ 64 jne 1f 65 pushl %edx 66 movl TD_PCB(%ecx),%ecx 67 pushl PCB_SAVEFPU(%ecx) 68 movl $npxsave,%eax 69 call *%eax 70 addl $4,%esp 71 popl %edx /* recover our pcb */ 721: 73 movl SCR_VMFRAME(%edx),%ebx /* target frame location */ 74 movl %ebx,%edi /* destination */ 75 movl SCR_ARGFRAME(%edx),%esi /* source (set on entry) */ 76 movl $VM86_FRAMESIZE/4,%ecx /* sizeof(struct vm86frame)/4 */ 77 cld 78 rep 79 movsl /* copy frame to new stack */ 80 81 movl PCPU(CURPCB),%eax 82 pushl %eax /* save curpcb */ 83 movl %edx,PCPU(CURPCB) /* set curpcb to vm86pcb */ 84 85 movl PCPU(TSS_GDT),%ebx /* entry in GDT */ 86 movl 0(%ebx),%eax 87 movl %eax,SCR_TSS0(%edx) /* save first word */ 88 movl 4(%ebx),%eax 89 andl $~0x200, %eax /* flip 386BSY -> 386TSS */ 90 movl %eax,SCR_TSS1(%edx) /* save second word */ 91 92 movl PCB_EXT(%edx),%edi /* vm86 tssd entry */ 93 movl 0(%edi),%eax 94 movl %eax,0(%ebx) 95 movl 4(%edi),%eax 96 movl %eax,4(%ebx) 97 movl $GPROC0_SEL*8,%esi /* GSEL(entry, SEL_KPL) */ 98 ltr %si 99 100 movl %cr3,%eax 101 pushl %eax /* save address space */ 102 cmpb $0,pae_mode 103 jne 2f 104 movl IdlePTD_nopae,%ecx /* va (and pa) of Idle PTD */ 105 jmp 3f 1062: movl IdlePTD_pae,%ecx 1073: movl %ecx,%ebx 108 movl 0(%ebx),%eax 109 pushl %eax /* old ptde != 0 when booting */ 110 pushl %ebx /* keep for reuse */ 111 112 movl %esp,SCR_STACK(%edx) /* save current stack location */ 113 114 movl SCR_NEWPTD(%edx),%eax /* mapping for vm86 page table */ 115 movl %eax,0(%ebx) /* ... install as PTD entry 0 */ 116 117 cmpb $0,pae_mode 118 je 4f 119 movl IdlePDPT,%ecx 1204: movl %ecx,%cr3 /* new page tables */ 121 movl SCR_VMFRAME(%edx),%esp /* switch to new stack */ 122 123 pushl %esp 124 movl $vm86_prepcall, %eax 125 call *%eax /* finish setup */ 126 add $4, %esp 127 128 /* 129 * Return via doreti 130 */ 131 jmp doreti 132 133 134/* 135 * vm86_biosret(struct trapframe_vm86 *vm86) 136 */ 137ENTRY(vm86_biosret) 138 movl vm86pcb,%edx /* data area */ 139 140 movl 4(%esp),%esi /* source */ 141 movl SCR_ARGFRAME(%edx),%edi /* destination */ 142 movl $VM86_FRAMESIZE/4,%ecx /* size */ 143 cld 144 rep 145 movsl /* copy frame to original frame */ 146 147 movl SCR_STACK(%edx),%esp /* back to old stack */ 148 popl %ebx /* saved va of Idle PTD */ 149 popl %eax 150 movl %eax,0(%ebx) /* restore old pte */ 151 popl %eax 152 movl %eax,%cr3 /* install old page table */ 153 154 movl PCPU(TSS_GDT),%ebx /* entry in GDT */ 155 movl SCR_TSS0(%edx),%eax 156 movl %eax,0(%ebx) /* restore first word */ 157 movl SCR_TSS1(%edx),%eax 158 movl %eax,4(%ebx) /* restore second word */ 159 movl $GPROC0_SEL*8,%esi /* GSEL(entry, SEL_KPL) */ 160 ltr %si 161 162 popl PCPU(CURPCB) /* restore curpcb/curproc */ 163 movl SCR_ARGFRAME(%edx),%edx /* original stack frame */ 164 movl TF_TRAPNO(%edx),%eax /* return (trapno) */ 165 166 popl %gs 167 popl %edi 168 popl %esi 169 popl %ebp 170 popl %ebx 171 ret /* back to our normal program */ 172