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