2003-08-11 Casper S. Hornstrup <chorns@users.sourceforge.net>
[reactos.git] / reactos / ntoskrnl / ke / i386 / v86m_sup.S
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2000 David Welch <welch@cwcom.net>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * FILE: ntoskrnl/ke/i386/vm86_sup.S
21 * PURPOSE: V86 mode support
22 * PROGRAMMER: David Welch (welch@cwcom.net)
23 * UPDATE HISTORY:
24 * Created 09/10/00
25 */
26
27 #include <internal/v86m.h>
28 #include <ntos/tss.h>
29 #include <internal/trap.h>
30 #include <internal/ps.h>
31
32 .globl _Ki386RetToV86Mode
33 .globl _KiV86Complete
34
35 /*
36 * VOID Ki386RetToV86Mode(KV86M_REGISTERS* InRegs,
37 * KV86M_REGISTERS* OutRegs);
38 *
39 * Starts in v86 mode with the registers set to the
40 * specified values.
41 */
42 _Ki386RetToV86Mode:
43 /*
44 * Setup a stack frame
45 */
46 pushl %ebp
47 movl %esp, %ebp
48
49 /*
50 * Save registers
51 */
52 pusha
53
54 /*
55 * Get a pointer to IN_REGS
56 */
57 movl 8(%ebp), %ebx
58
59 /*
60 * Save ebp
61 */
62 pushl %ebp
63
64 /*
65 * Save a pointer to IN_REGS which the v86m exception handler will
66 * use to handle exceptions
67 */
68 pushl %ebx
69
70 /*
71 * Since we are going to fiddle with the stack pointer this must be
72 * a critical section for this processor
73 */
74
75 /*
76 * Save the old initial stack
77 */
78 movl %fs:KPCR_CURRENT_THREAD, %esi
79 movl KTHREAD_INITIAL_STACK(%esi), %edi
80 pushl %edi
81
82 /*
83 * We also need to set the stack in the kthread structure
84 */
85 movl %esp, KTHREAD_INITIAL_STACK(%esi)
86
87 /*
88 * The stack used for handling exceptions from v86 mode in this thread
89 * will be the current stack adjusted so we don't overwrite the
90 * existing stack frames
91 */
92 movl %fs:KPCR_TSS, %esi
93 movl %esp, KTSS_ESP0(%esi)
94
95 /*
96 * Create the stack frame for an iret to v86 mode
97 */
98 pushl KV86M_REGISTERS_GS(%ebx)
99 pushl KV86M_REGISTERS_FS(%ebx)
100 pushl KV86M_REGISTERS_DS(%ebx)
101 pushl KV86M_REGISTERS_ES(%ebx)
102 pushl KV86M_REGISTERS_SS(%ebx)
103 pushl KV86M_REGISTERS_ESP(%ebx)
104 pushl KV86M_REGISTERS_EFLAGS(%ebx)
105 pushl KV86M_REGISTERS_CS(%ebx)
106 pushl KV86M_REGISTERS_EIP(%ebx)
107
108 /*
109 * Setup the CPU registers
110 */
111 movl KV86M_REGISTERS_EAX(%ebx), %eax
112 movl KV86M_REGISTERS_ECX(%ebx), %ecx
113 movl KV86M_REGISTERS_EDX(%ebx), %edx
114 movl KV86M_REGISTERS_ESI(%ebx), %esi
115 movl KV86M_REGISTERS_EDI(%ebx), %edi
116 movl KV86M_REGISTERS_EBP(%ebx), %ebp
117 movl KV86M_REGISTERS_EBX(%ebx), %ebx
118
119 /*
120 * Go to v86 mode
121 */
122 iret
123
124 /*
125 * Handle the completion of a vm86 routine. We are called from
126 * an exception handler with the registers at the point of the
127 * exception on the stack.
128 */
129 _KiV86Complete:
130 /* Restore the original ebp */
131 movl TF_ORIG_EBP(%esp), %ebp
132
133 /* Get a pointer to the OUT_REGS structure */
134 movl 12(%ebp), %ebx
135
136 /* Skip debug information and unsaved registers */
137 addl $0x30, %esp
138
139 /* Ignore 32-bit segment registers */
140 addl $12, %esp
141
142 /* Save the vm86 registers into the OUT_REGS structure */
143 popl KV86M_REGISTERS_EDX(%ebx)
144 popl KV86M_REGISTERS_ECX(%ebx)
145 popl KV86M_REGISTERS_EAX(%ebx)
146
147 /* Restore the old previous mode */
148 popl %eax
149 movb %al, %ss:KTHREAD_PREVIOUS_MODE(%esi)
150
151 /* Restore the old exception handler list */
152 popl %eax
153 movl %eax, %fs:KPCR_EXCEPTION_LIST
154
155 /* Ignore the 32-bit fs register */
156 addl $4, %esp
157
158 popl KV86M_REGISTERS_EDI(%ebx)
159 popl KV86M_REGISTERS_ESI(%ebx)
160 popl KV86M_REGISTERS_EBX(%ebx)
161 popl KV86M_REGISTERS_EBP(%ebx)
162
163 /* Ignore error code */
164 addl $4, %esp
165
166 popl KV86M_REGISTERS_EIP(%ebx)
167 popl KV86M_REGISTERS_CS(%ebx)
168 popl KV86M_REGISTERS_EFLAGS(%ebx)
169 popl KV86M_REGISTERS_ESP(%ebx)
170 popl KV86M_REGISTERS_SS(%ebx)
171 popl KV86M_REGISTERS_ES(%ebx)
172 popl KV86M_REGISTERS_DS(%ebx)
173 popl KV86M_REGISTERS_FS(%ebx)
174 popl KV86M_REGISTERS_GS(%ebx)
175
176 /*
177 * We are going to fiddle with the stack so this must be a critical
178 * section for this process
179 */
180 cli
181
182 /*
183 * Restore the initial stack
184 */
185 popl %eax
186 movl %fs:KPCR_TSS, %esi
187 movl %eax, KTSS_ESP0(%esi)
188
189 /*
190 * We also need to set the stack in the kthread structure
191 */
192 movl %fs:KPCR_CURRENT_THREAD, %esi
193 movl KTHREAD_INITIAL_STACK(%esi), %edi
194 movl %eax, KTHREAD_INITIAL_STACK(%esi)
195
196 /* Exit the critical section */
197 sti
198
199 /* Ignore IN_REGS pointer */
200 addl $4, %esp
201
202 /* Ignore ebp restored above */
203 addl $4, %esp
204
205 /* Return to caller */
206 popa
207 movl %ebp, %esp
208 popl %ebp
209 ret
210
211
212
213
214
215