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