kernel - Fix some rare pmap races in i386 and x86_64.
[dragonfly.git] / sys / platform / pc32 / i386 / vm86bios.s
blobe557c961ff84de885ab6ebf6cdc247e0c5bede89
1 /*-
2 * Copyright (c) 1998 Jonathan Lemon
3 * All rights reserved.
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.
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.
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.14 2007/01/22 19:37:04 corecode Exp $
30 #include <machine/asmacros.h> /* miscellaneous asm macros */
31 #include <machine/trap.h>
33 #include "assym.s"
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)
43 .data
44 ALIGN_DATA
46 .globl in_vm86call, vm86pcb
48 in_vm86call: .long 0
49 vm86pcb: .long 0
51 .text
54 * vm86_bioscall(struct trapframe_vm86 *vm86)
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
66 #if NNPX > 0
67 movl PCPU(curthread),%ecx
68 cmpl %ecx,PCPU(npxthread) /* do we need to save fp? */
69 jne 1f
70 testl %ecx,%ecx
71 je 1f /* no curthread/npxthread */
72 pushl %edx
73 pushl TD_SAVEFPU(%ecx)
74 call npxsave
75 popl %ecx /* pop argument (now garabge) */
76 popl %edx /* recover our pcb */
77 #endif
79 /* %ecx is garbage at this point */
81 movl SCR_VMFRAME(%edx),%ebx /* target frame location */
82 movl %ebx,%edi /* destination */
83 movl SCR_ARGFRAME(%edx),%esi /* source (set on entry) */
84 movl $VM86_FRAMESIZE/4,%ecx /* sizeof(struct vm86frame)/4 */
85 cld
86 rep
87 movsl /* copy frame to new stack */
89 /*
90 * YYY I really dislike replacing td_pcb, even temporarily. Find
91 * another way.
93 movl PCPU(curthread),%ebx
94 movl TD_PCB(%ebx),%eax /* save curpcb */
95 pushl %eax /* save curpcb */
96 pushl TD_SAVEFPU(%ebx) /* save fpu pointer */
97 movl %edx,TD_PCB(%ebx) /* set curpcb to vm86pcb */
98 leal PCB_SAVEFPU(%edx),%eax /* new savefpu pointer */
99 movl %eax,TD_SAVEFPU(%ebx)
101 movl PCPU(tss_gdt),%ebx /* entry in GDT */
102 movl 0(%ebx),%eax
103 movl %eax,SCR_TSS0(%edx) /* save first word */
104 movl 4(%ebx),%eax
105 andl $~0x200, %eax /* flip 386BSY -> 386TSS */
106 movl %eax,SCR_TSS1(%edx) /* save second word */
108 movl PCB_EXT(%edx),%edi /* vm86 tssd entry */
109 movl 0(%edi),%eax
110 movl %eax,0(%ebx)
111 movl 4(%edi),%eax
112 movl %eax,4(%ebx)
113 movl $GPROC0_SEL*8,%esi /* GSEL(entry, SEL_KPL) */
114 ltr %si
116 movl %cr3,%eax
117 pushl %eax /* save address space */
118 movl IdlePTD,%ecx
119 movl %ecx,%ebx
120 addl $KERNBASE,%ebx /* va of Idle PTD */
121 movl 0(%ebx),%eax
122 pushl %eax /* old ptde != 0 when booting */
123 pushl %ebx /* keep for reuse */
125 movl %esp,SCR_STACK(%edx) /* save current stack location */
127 movl SCR_NEWPTD(%edx),%eax /* mapping for vm86 page table */
128 movl %eax,0(%ebx) /* ... install as PTD entry 0 */
130 movl %ecx,%cr3 /* new page tables */
131 movl SCR_VMFRAME(%edx),%esp /* switch to new stack */
133 pushl %esp /* pass frame by reference */
134 call vm86_prepcall /* finish setup */
135 addl $4,%esp
137 movl $1,in_vm86call /* set flag for trap() */
140 * Return via _doreti, restore the same cpl as our current cpl
142 movl PCPU(curthread),%eax
143 pushl $0 /* DUMMY CPL FOR DORETI */
144 MEXITCOUNT
145 jmp doreti
149 * vm86_biosret(struct trapframe_vm86 *vm86)
151 ENTRY(vm86_biosret)
152 movl vm86pcb,%edx /* data area */
154 movl 4(%esp),%esi /* source */
155 movl SCR_ARGFRAME(%edx),%edi /* destination */
156 movl $VM86_FRAMESIZE/4,%ecx /* size */
159 movsl /* copy frame to original frame */
161 movl SCR_STACK(%edx),%esp /* back to old stack */
162 popl %ebx /* saved va of Idle PTD */
163 popl %eax
164 movl %eax,0(%ebx) /* restore old pte */
165 popl %eax
166 movl %eax,%cr3 /* install old page table */
168 movl $0,in_vm86call /* reset trapflag */
170 movl PCPU(tss_gdt),%ebx /* entry in GDT */
171 movl SCR_TSS0(%edx),%eax
172 movl %eax,0(%ebx) /* restore first word */
173 movl SCR_TSS1(%edx),%eax
174 movl %eax,4(%ebx) /* restore second word */
175 movl $GPROC0_SEL*8,%esi /* GSEL(entry, SEL_KPL) */
176 ltr %si
178 movl PCPU(curthread),%eax
179 popl TD_SAVEFPU(%eax) /* restore savefpu pointer */
180 popl TD_PCB(%eax) /* restore curpcb */
181 movl SCR_ARGFRAME(%edx),%edx /* original stack frame */
182 movl TF_TRAPNO(%edx),%eax /* return (trapno) */
184 popl %gs
185 popl %edi
186 popl %esi
187 popl %ebp
188 popl %ebx
189 ret /* back to our normal program */