update for HEAD-2003091401
[reactos.git] / 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