vm86bios.s revision 87702
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: head/sys/i386/i386/vm86bios.s 87702 2001-12-11 23:33:44Z jhb $
27 */
28
29#include "opt_npx.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_SPARE
42#define SCR_TSS1	(PCB_SPARE+4)
43
44	.data
45	ALIGN_DATA
46
47	.globl	in_vm86call, vm86pcb
48
49in_vm86call:		.long	0
50vm86pcb:		.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	%gs
66
67#ifdef DEV_NPX
68	pushfl
69	cli
70	movl	PCPU(CURTHREAD),%ecx
71	cmpl	%ecx,PCPU(FPCURTHREAD)	/* do we need to save fp? */
72	jne	1f
73	testl	%ecx,%ecx
74	je 	1f			/* no curproc/npxproc */
75	pushl	%edx
76	movl	TD_PCB(%ecx),%ecx
77	addl	$PCB_SAVEFPU,%ecx
78	pushl	%ecx
79	call	npxsave
80	popl	%ecx
81	popl	%edx			/* recover our pcb */
821:
83	popfl
84#endif
85
86	movl	SCR_VMFRAME(%edx),%ebx	/* target frame location */
87	movl	%ebx,%edi		/* destination */
88	movl    SCR_ARGFRAME(%edx),%esi	/* source (set on entry) */
89	movl	$VM86_FRAMESIZE/4,%ecx	/* sizeof(struct vm86frame)/4 */
90	cld
91	rep
92	movsl				/* copy frame to new stack */
93
94	movl	PCPU(CURPCB),%eax
95	pushl	%eax			/* save curpcb */
96	movl	%edx,PCPU(CURPCB)	/* set curpcb to vm86pcb */
97
98	movl	PCPU(TSS_GDT),%ebx	/* entry in GDT */
99	movl	0(%ebx),%eax
100	movl	%eax,SCR_TSS0(%edx)	/* save first word */
101	movl	4(%ebx),%eax
102	andl    $~0x200, %eax		/* flip 386BSY -> 386TSS */
103	movl	%eax,SCR_TSS1(%edx)	/* save second word */
104
105	movl	PCB_EXT(%edx),%edi	/* vm86 tssd entry */
106	movl	0(%edi),%eax
107	movl	%eax,0(%ebx)
108	movl	4(%edi),%eax
109	movl	%eax,4(%ebx)
110	movl	$GPROC0_SEL*8,%esi	/* GSEL(entry, SEL_KPL) */
111	ltr	%si
112
113	movl	%cr3,%eax
114	pushl	%eax			/* save address space */
115	movl	IdlePTD,%ecx
116	movl	%ecx,%ebx
117	addl	$KERNBASE,%ebx		/* va of Idle PTD */
118	movl	0(%ebx),%eax
119	pushl	%eax			/* old ptde != 0 when booting */
120	pushl	%ebx			/* keep for reuse */
121
122	movl	%esp,SCR_STACK(%edx)	/* save current stack location */
123
124	movl	SCR_NEWPTD(%edx),%eax	/* mapping for vm86 page table */
125	movl	%eax,0(%ebx)		/* ... install as PTD entry 0 */
126
127	movl	%ecx,%cr3		/* new page tables */
128	movl	SCR_VMFRAME(%edx),%esp	/* switch to new stack */
129
130	call	vm86_prepcall		/* finish setup */
131
132	movl	$1,in_vm86call		/* set flag for trap() */
133
134	/*
135	 * Return via doreti
136	 */
137	MEXITCOUNT
138	jmp	doreti
139
140
141/*
142 * vm86_biosret(struct trapframe_vm86 *vm86)
143 */
144ENTRY(vm86_biosret)
145	movl	vm86pcb,%edx		/* data area */
146
147	movl	4(%esp),%esi		/* source */
148	movl	SCR_ARGFRAME(%edx),%edi	/* destination */
149	movl	$VM86_FRAMESIZE/4,%ecx	/* size */
150	cld
151	rep
152	movsl				/* copy frame to original frame */
153
154	movl	SCR_STACK(%edx),%esp	/* back to old stack */
155	popl	%ebx			/* saved va of Idle PTD */
156	popl	%eax
157	movl	%eax,0(%ebx)		/* restore old pte */
158	popl	%eax
159	movl	%eax,%cr3		/* install old page table */
160
161	movl	$0,in_vm86call		/* reset trapflag */
162
163	movl	PCPU(TSS_GDT),%ebx		/* entry in GDT */
164	movl	SCR_TSS0(%edx),%eax
165	movl	%eax,0(%ebx)		/* restore first word */
166	movl	SCR_TSS1(%edx),%eax
167	movl	%eax,4(%ebx)		/* restore second word */
168	movl	$GPROC0_SEL*8,%esi	/* GSEL(entry, SEL_KPL) */
169	ltr	%si
170
171	popl	PCPU(CURPCB)		/* restore curpcb/curproc */
172	movl	SCR_ARGFRAME(%edx),%edx	/* original stack frame */
173	movl	TF_TRAPNO(%edx),%eax	/* return (trapno) */
174
175	popl	%gs
176	popl	%edi
177	popl	%esi
178	popl	%ebp
179	popl	%ebx
180	ret				/* back to our normal program */
181