1 /* $OpenBSD: kvm86call.S,v 1.4 2006/12/11 23:45:13 gwk Exp $ */
2 /* $NetBSD: kvm86call.S,v 1.7 2006/04/11 17:14:07 drochner Exp $ */
3
4 /*-
5 * Copyright (c) 1998 Jonathan Lemon
6 * All rights reserved.
7 * Copyright (c) 2002
8 * Matthias Drochner. All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 * $FreeBSD: src/sys/i386/i386/vm86bios.s,v 1.28 2001/12/11 23:33:40 jhb Exp $
32 */
33
34 #include <machine/asm.h>
35 #include <machine/param.h>
36 #include "assym.h"
37
38 .data
39 .align 4
40
41 /* flag for trap() */
42 .globl kvm86_incall
43 kvm86_incall: .long 0
44
45 /* XXX arguments for kvm86call() */
46 .globl vm86pcb, vm86newptd, vm86frame, vm86pgtableva
47 .globl vm86tssd0, vm86tssd1
48
49 /* locals */
50 SCRARGFRAME: .long 0
51 SCRSTACK: .long 0
52 SCRTSS0: .long 0
53 SCRTSS1: .long 0
54
55 .text
56
57 #if defined MULTIPROCESSOR
58 #include <machine/i82489reg.h>
59 #endif
60
61 /* int kvm86_call(struct trapframe *) */
62 ENTRY(kvm86_call)
63 pushl %ebp
64 movl %esp,%ebp /* set up frame ptr */
65 pushl %esi
66 pushl %edi
67 pushl %ebx
68 pushl %fs
69 pushl %gs
70
71 movl 8(%ebp),%eax
72 movl %eax,SCRARGFRAME /* save argument pointer */
73
74 movl vm86frame,%edi /* target frame location */
75 movl SCRARGFRAME,%esi /* source (set on entry) */
76 movl $FRAMESIZE/4,%ecx /* sizeof(struct trapframe)/4 */
77 cld
78 rep
79 movsl /* copy frame to new stack */
80
81 #ifdef MULTIPROCESSOR
82 movl _C_LABEL(local_apic)+LAPIC_ID,%ecx
83 shrl $LAPIC_ID_SHIFT,%ecx
84 leal 0(,%ecx,4),%ecx
85 movl _C_LABEL(cpu_info)(%ecx),%edx
86 movl %edx,%ecx
87 #else
88 leal _C_LABEL(cpu_info_primary),%ecx
89 #endif
90
91 movl CPU_INFO_CURPCB(%ecx),%eax
92 pushl %eax /* save curpcb */
93
94 movl vm86pcb,%eax
95 movl %eax,CPU_INFO_CURPCB(%ecx) /* set curpcb to vm86pcb */
96 movl CPU_INFO_CURPROC(%ecx),%ecx
97 movl P_MD_TSS_SEL(%ecx),%edi
98
99 #ifdef MULTIPROCESSOR
100 movl CPU_INFO_GDT(%edx),%eax
101 #else
102 movl _C_LABEL(gdt),%eax
103 #endif
104 andl $~0x0200,4(%eax,%edi,1) /* reset "task busy" */
105
106 movl 0(%eax,%edi,1),%edx
107 movl %edx,SCRTSS0 /* save first word */
108 movl 4(%eax,%edi,1),%edx
109 movl %edx,SCRTSS1 /* save second word */
110
111 movl vm86tssd0,%edx /* vm86 tssd entry */
112 movl %edx,0(%eax,%edi,1)
113 movl vm86tssd1,%edx /* vm86 tssd entry */
114 movl %edx,4(%eax,%edi,1)
115 ltr %di
116
117 movl %cr3,%eax
118 pushl %eax /* save address space */
119 movl PTDpaddr,%ecx
120 movl %ecx,%ebx
121 addl $KERNBASE,%ebx /* va of Idle PDP */
122 movl 0(%ebx),%eax
123 pushl %eax /* old pde */
124 pushl %ebx /* keep address for reuse */
125
126 movl %esp,SCRSTACK /* save current stack location */
127
128 movl vm86newptd,%eax /* mapping for vm86 page table */
129 movl %eax,0(%ebx) /* ... install as PDP entry 0 */
130
131 movl %ecx,%cr3 /* new page tables */
132 movl vm86frame,%esp /* switch to new stack */
133
134 movl $1,kvm86_incall /* set flag for trap() */
135
136 /* INTRFASTEXIT */
137 popl %gs
138 popl %fs
139 popl %es
140 popl %ds
141 popl %edi
142 popl %esi
143 popl %ebp
144 popl %ebx
145 popl %edx
146 popl %ecx
147 popl %eax
148 addl $8,%esp
149 iret
150
151
152 /* void kvm86_ret(struct trapframe *, int) */
153 ENTRY(kvm86_ret)
154 pushl %ebp
155 movl %esp,%ebp /* set up frame ptr */
156
157 movl 8(%ebp),%esi /* source */
158 movl SCRARGFRAME,%edi /* destination */
159 movl $FRAMESIZE/4,%ecx /* size */
160 cld
161 rep
162 movsl /* copy frame to original frame */
163
164 movl SCRSTACK,%esp /* back to old stack */
165 popl %ebx /* saved va of Idle PDP */
166 popl %eax
167 movl %eax,0(%ebx) /* restore old pde */
168 popl %eax
169 movl %eax,%cr3 /* install old page table */
170
171 movl $0,kvm86_incall /* reset trapflag */
172
173
174 #ifdef MULTIPROCESSOR
175 movl _C_LABEL(local_apic)+LAPIC_ID,%ecx
176 shrl $LAPIC_ID_SHIFT,%ecx
177 leal 0(,%ecx,4),%ecx
178 movl _C_LABEL(cpu_info)(%ecx),%ecx
179 movl CPU_INFO_GDT(%ecx),%eax
180 #else
181 leal _C_LABEL(cpu_info_primary),%ecx
182 movl _C_LABEL(gdt),%eax
183 #endif
184 movl CPU_INFO_CURPROC(%ecx),%ecx
185 movl P_MD_TSS_SEL(%ecx),%edi
186 movl SCRTSS0, %edx
187 movl %edx, 0(%eax,%edi,1) /* restore first word */
188 movl SCRTSS1, %edx
189 movl %edx, 4(%eax,%edi,1) /* restore second word */
190 ltr %di
191
192
193 #ifdef MULTIPROCESSOR
194 movl _C_LABEL(local_apic)+LAPIC_ID,%ecx
195 shrl $LAPIC_ID_SHIFT,%ecx
196 leal 0(,%ecx,4),%ecx
197 movl _C_LABEL(cpu_info)(%ecx),%ecx
198 #else
199 leal _C_LABEL(cpu_info_primary),%ecx
200 #endif
201 popl %eax /* restore curpcb */
202 movl %eax,CPU_INFO_CURPCB(%ecx)
203
204 movl 12(%ebp), %eax /* will be kvm86_call()'s retval */
205
206 popl %gs
207 popl %fs
208 popl %ebx
209 popl %edi
210 popl %esi
211 popl %ebp
212 ret /* back to kvm86_call()'s caller */