Initial import from FreeBSD RELENG_4:
[games.git] / sys / platform / pc32 / i386 / vm86bios.s
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: src/sys/i386/i386/vm86bios.s,v 1.15.2.1 2000/05/16 06:58:07 dillon Exp $
27  */
28
29 #include <machine/asmacros.h>           /* miscellaneous asm macros */
30 #include <machine/trap.h>
31
32 #include "assym.s"
33
34 #define SCR_NEWPTD      PCB_ESI         /* readability macros */ 
35 #define SCR_VMFRAME     PCB_EBP         /* see vm86.c for explanation */
36 #define SCR_STACK       PCB_ESP
37 #define SCR_PGTABLE     PCB_EBX
38 #define SCR_ARGFRAME    PCB_EIP
39 #define SCR_TSS0        PCB_SPARE
40 #define SCR_TSS1        (PCB_SPARE+4)
41
42         .data
43         ALIGN_DATA
44
45         .globl  _in_vm86call, _vm86pcb
46
47 _in_vm86call:           .long   0
48 _vm86pcb:               .long   0
49
50         .text
51
52 /*
53  * vm86_bioscall(struct trapframe_vm86 *vm86)
54  */
55 ENTRY(vm86_bioscall)
56         movl    _vm86pcb,%edx           /* scratch data area */
57         movl    4(%esp),%eax
58         movl    %eax,SCR_ARGFRAME(%edx) /* save argument pointer */
59         pushl   %ebx
60         pushl   %ebp
61         pushl   %esi
62         pushl   %edi
63         pushl   %gs
64
65 #ifdef SMP      
66         pushl   %edx
67         MP_LOCK                         /* Get global lock */
68         popl    %edx
69 #endif
70
71 #if NNPX > 0
72         movl    _curproc,%ecx
73         cmpl    %ecx,_npxproc           /* do we need to save fp? */
74         jne     1f
75         testl   %ecx,%ecx
76         je      1f                      /* no curproc/npxproc */
77         pushl   %edx
78         movl    P_ADDR(%ecx),%ecx
79         addl    $PCB_SAVEFPU,%ecx
80         pushl   %ecx
81         call    _npxsave
82         popl    %ecx
83         popl    %edx                    /* recover our pcb */
84 #endif
85
86 1:
87         movl    SCR_VMFRAME(%edx),%ebx  /* target frame location */
88         movl    %ebx,%edi               /* destination */
89         movl    SCR_ARGFRAME(%edx),%esi /* source (set on entry) */
90         movl    $VM86_FRAMESIZE/4,%ecx  /* sizeof(struct vm86frame)/4 */
91         cld
92         rep
93         movsl                           /* copy frame to new stack */
94
95         movl    _curpcb,%eax
96         pushl   %eax                    /* save curpcb */
97         movl    %edx,_curpcb            /* set curpcb to vm86pcb */
98
99         movl    _tss_gdt,%ebx           /* entry in GDT */
100         movl    0(%ebx),%eax
101         movl    %eax,SCR_TSS0(%edx)     /* save first word */
102         movl    4(%ebx),%eax
103         andl    $~0x200, %eax           /* flip 386BSY -> 386TSS */
104         movl    %eax,SCR_TSS1(%edx)     /* save second word */
105
106         movl    PCB_EXT(%edx),%edi      /* vm86 tssd entry */
107         movl    0(%edi),%eax
108         movl    %eax,0(%ebx)
109         movl    4(%edi),%eax
110         movl    %eax,4(%ebx)
111         movl    $GPROC0_SEL*8,%esi      /* GSEL(entry, SEL_KPL) */
112         ltr     %si
113
114         movl    %cr3,%eax
115         pushl   %eax                    /* save address space */
116         movl    _IdlePTD,%ecx
117         movl    %ecx,%ebx
118         addl    $KERNBASE,%ebx          /* va of Idle PTD */
119         movl    0(%ebx),%eax
120         pushl   %eax                    /* old ptde != 0 when booting */
121         pushl   %ebx                    /* keep for reuse */
122
123         movl    %esp,SCR_STACK(%edx)    /* save current stack location */
124
125         movl    SCR_NEWPTD(%edx),%eax   /* mapping for vm86 page table */
126         movl    %eax,0(%ebx)            /* ... install as PTD entry 0 */
127
128         movl    %ecx,%cr3               /* new page tables */
129         movl    SCR_VMFRAME(%edx),%esp  /* switch to new stack */
130         
131         call    _vm86_prepcall          /* finish setup */
132
133         movl    $1,_in_vm86call         /* set flag for trap() */
134
135         /*
136          * Return via _doreti
137          */
138 #ifdef SMP
139         pushl   _cpl                    /* cpl to restore */
140 #else
141         pushl   _cpl                    /* cpl to restore */
142 #endif
143         subl    $4,%esp                 /* dummy unit */
144         incb    _intr_nesting_level
145         MEXITCOUNT
146         jmp     _doreti
147
148
149 /*
150  * vm86_biosret(struct trapframe_vm86 *vm86)
151  */
152 ENTRY(vm86_biosret)
153         movl    _vm86pcb,%edx           /* data area */
154
155         movl    4(%esp),%esi            /* source */
156         movl    SCR_ARGFRAME(%edx),%edi /* destination */
157         movl    $VM86_FRAMESIZE/4,%ecx  /* size */
158         cld
159         rep
160         movsl                           /* copy frame to original frame */
161
162         movl    SCR_STACK(%edx),%esp    /* back to old stack */
163         popl    %ebx                    /* saved va of Idle PTD */
164         popl    %eax
165         movl    %eax,0(%ebx)            /* restore old pte */
166         popl    %eax
167         movl    %eax,%cr3               /* install old page table */
168
169         movl    $0,_in_vm86call         /* reset trapflag */
170
171         movl    _tss_gdt,%ebx           /* entry in GDT */
172         movl    SCR_TSS0(%edx),%eax
173         movl    %eax,0(%ebx)            /* restore first word */
174         movl    SCR_TSS1(%edx),%eax
175         movl    %eax,4(%ebx)            /* restore second word */
176         movl    $GPROC0_SEL*8,%esi      /* GSEL(entry, SEL_KPL) */
177         ltr     %si
178         
179         popl    _curpcb                 /* restore curpcb/curproc */
180         movl    SCR_ARGFRAME(%edx),%edx /* original stack frame */
181         movl    TF_TRAPNO(%edx),%eax    /* return (trapno) */
182
183         popl    %gs
184         popl    %edi
185         popl    %esi
186         popl    %ebp
187         popl    %ebx
188         ret                             /* back to our normal program */