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 * $FreeBSD$
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 */
57 ENTRY(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
74 #if NNPX > 0
75 movl _curproc,%ecx
76 cmpl %ecx,_npxproc /* do we need to save fp? */
77 jne 1f
78 testl %ecx,%ecx
79 je 1f /* no curproc/npxproc */
80 pushl %edx
81 movl P_ADDR(%ecx),%ecx
82 addl $PCB_SAVEFPU,%ecx
83 pushl %ecx
84 call _npxsave
85 popl %ecx
86 popl %edx /* recover our pcb */
87 #endif
88
89 1:
90 movl SCR_VMFRAME(%edx),%ebx /* target frame location */
91 movl %ebx,%edi /* destination */
92 movl SCR_ARGFRAME(%edx),%esi /* source (set on entry) */
93 movl $21,%ecx /* sizeof(struct vm86frame)/4 */
94 cld
95 rep
96 movsl /* copy frame to new stack */
97
98 movl _curpcb,%eax
99 pushl %eax /* save curpcb */
100 movl %edx,_curpcb /* set curpcb to vm86pcb */
101
102 movl _my_tr,%esi
103 leal _gdt(,%esi,8),%ebx /* entry in GDT */
104 movl 0(%ebx),%eax
105 movl %eax,SCR_TSS0(%edx) /* save first word */
106 movl 4(%ebx),%eax
107 andl $~0x200, %eax /* flip 386BSY -> 386TSS */
108 movl %eax,SCR_TSS1(%edx) /* save second word */
109
110 movl PCB_EXT(%edx),%edi /* vm86 tssd entry */
111 movl 0(%edi),%eax
112 movl %eax,0(%ebx)
113 movl 4(%edi),%eax
114 movl %eax,4(%ebx)
115 shll $3,%esi /* GSEL(entry, SEL_KPL) */
116 ltr %si
117
118 movl %cr3,%eax
119 pushl %eax /* save address space */
120 #ifdef SMP
121 movl _cpuid, %ecx
122 movl CNAME(IdlePTDS)(,%ecx,4), %ebx
123 movl _my_idlePTD,%ecx
124 #else
125 movl _IdlePTD,%ecx
126 movl %ecx,%ebx
127 addl $KERNBASE,%ebx /* va of Idle PTD */
128 #endif
129 movl 0(%ebx),%eax
130 pushl %eax /* old ptde != 0 when booting */
131 pushl %ebx /* keep for reuse */
132
133 movl %esp,SCR_STACK(%edx) /* save current stack location */
134
135 movl SCR_NEWPTD(%edx),%eax /* mapping for vm86 page table */
136 movl %eax,0(%ebx) /* ... install as PTD entry 0 */
137
138 movl %ecx,%cr3 /* new page tables */
139 movl SCR_VMFRAME(%edx),%esp /* switch to new stack */
140
141 call _vm86_prepcall /* finish setup */
142
143 movl $1,_in_vm86call /* set flag for trap() */
144
145 /*
146 * Return via _doreti
147 */
148 #ifdef SMP
149 ECPL_LOCK
150 #ifdef CPL_AND_CML
151 #error Not ready for CPL_AND_CML
152 #endif
153 pushl _cpl /* cpl to restore */
154 ECPL_UNLOCK
155 #else
156 pushl _cpl /* cpl to restore */
157 #endif
158 subl $4,%esp /* dummy unit */
159 MPLOCKED incb _intr_nesting_level
160 MEXITCOUNT
161 jmp _doreti
162
163
164 /*
165 * vm86_biosret(struct trapframe_vm86 *vm86)
166 */
167 ENTRY(vm86_biosret)
168 movl _vm86pcb,%edx /* data area */
169
170 movl 4(%esp),%esi /* source */
171 movl SCR_ARGFRAME(%edx),%edi /* destination */
172 movl $21,%ecx /* size */
173 cld
174 rep
175 movsl /* copy frame to original frame */
176
177 movl SCR_STACK(%edx),%esp /* back to old stack */
178 popl %ebx /* saved va of Idle PTD */
179 popl %eax
180 movl %eax,0(%ebx) /* restore old pte */
181 popl %eax
182 movl %eax,%cr3 /* install old page table */
183
184 movl $0,_in_vm86call /* reset trapflag */
185
186 movl _my_tr,%esi
187 leal _gdt(,%esi,8),%ebx /* entry in GDT */
188 movl SCR_TSS0(%edx),%eax
189 movl %eax,0(%ebx) /* restore first word */
190 movl SCR_TSS1(%edx),%eax
191 movl %eax,4(%ebx) /* restore second word */
192 shll $3,%esi /* GSEL(entry, SEL_KPL) */
193 ltr %si
194
195 popl _curpcb /* restore curpcb/curproc */
196 movl SCR_ARGFRAME(%edx),%edx /* original stack frame */
197 movl TF_TRAPNO(%edx),%eax /* return (trapno) */
198
199 popl %gs
200 popl %fs
201 popl %edi
202 popl %esi
203 popl %ebp
204 popl %ebx
205 ret /* back to our normal program */
Cache object: 4cb876bd052550447566e1bf4af48f76
|