xref: /freebsd/sys/i386/i386/vm86bios.S (revision e0c4386e7e71d93b0edc0c8fa156263fc4a8b0b6)
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