update for HEAD-2003091401
[reactos.git] / ntoskrnl / ke / i386 / tskswitch.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/tskswitch.S
21  * PURPOSE:         Microkernel thread support
22  * PROGRAMMER:      David Welch (welch@cwcom.net)
23  * UPDATE HISTORY:
24  *                  Created 09/10/00
25  */
26
27 /* INCLUDES ******************************************************************/
28
29 #include <internal/i386/segment.h>
30 #include <internal/ps.h>
31 #include <ntos/tss.h>
32 #include <internal/ntoskrnl.h>
33                 
34 /* FUNCTIONS ****************************************************************/
35         
36 .globl _Ki386ContextSwitch
37 _Ki386ContextSwitch:
38 /* 
39  * FUNCTIONS: Switches to another thread's context
40  * ARGUMENTS:
41  *        Thread = Thread to switch to
42  *        OldThread = Thread to switch from
43  */
44         pushl   %ebp
45         movl    %esp, %ebp
46
47         /*
48          * Save callee save registers.
49          */
50         pushl   %ebx
51         pushl   %esi
52         pushl   %edi
53
54         /*
55          * This is a critical section for this processor.
56          */
57         cli
58
59         /*
60          * Get the pointer to the new thread.
61          */
62         movl    8(%ebp), %ebx
63                 
64         /*
65          * Set the base of the TEB selector to the base of the TEB for
66          * this thread.
67          */
68         pushl   %ebx
69         pushl   KTHREAD_TEB(%ebx)
70         pushl   $TEB_SELECTOR
71         call    _KeSetBaseGdtSelector
72         addl    $8, %esp
73         popl    %ebx
74
75         /*
76          * Load the PCR selector.
77          */
78         movl    $PCR_SELECTOR, %eax
79         movl    %eax, %fs
80
81         /*
82          * Set the current thread information in the PCR.
83          */
84         movl    %ebx, %fs:KPCR_CURRENT_THREAD
85
86         /*
87          * Set the current LDT
88          */
89         xorl    %eax, %eax
90         movl    ETHREAD_THREADS_PROCESS(%ebx), %edi
91         testw   $0xFFFF, KPROCESS_LDT_DESCRIPTOR0(%edi)
92         jz      .L4
93
94         pushl   KPROCESS_LDT_DESCRIPTOR1(%edi)
95         pushl   KPROCESS_LDT_DESCRIPTOR0(%edi)
96         pushl   $LDT_SELECTOR
97         call    _KeSetGdtSelector
98         addl    $12, %esp
99
100         movl    $LDT_SELECTOR, %eax
101
102 .L4:
103         lldtw   %ax
104
105         /*
106          * Load up the iomap offset for this thread in
107          * preparation for setting it below.
108          */
109         movl    KPROCESS_IOPM_OFFSET(%edi), %eax
110
111         /*
112          * FIXME: Save debugging state.
113          */
114
115         /*
116          * FIXME: Save floating point state.
117          */
118
119         /*
120          * Switch stacks
121          */
122         movl    12(%ebp), %ebx
123         movl    %esp, KTHREAD_KERNEL_STACK(%ebx)        
124         movl    8(%ebp), %ebx
125         movl    KTHREAD_KERNEL_STACK(%ebx), %esp
126         movl    KTHREAD_STACK_LIMIT(%ebx), %edi
127
128         /*
129          * Set the stack pointer in this processors TSS
130          */
131         movl    %fs:KPCR_TSS, %esi
132
133         /*
134          * Set current IOPM offset in the TSS
135          */
136         movw    %ax, KTSS_IOMAPBASE(%esi)
137
138         movl    KTHREAD_INITIAL_STACK(%ebx), %eax
139         movl    %eax, KTSS_ESP0(%esi)
140
141         /*
142          * Change the address space
143          */
144         movl    ETHREAD_THREADS_PROCESS(%ebx), %ebx
145         movl    KPROCESS_DIRECTORY_TABLE_BASE(%ebx), %eax
146         movl    %eax, %cr3
147
148         /*
149          * Set up the PDE for the top of the new stack.
150          */
151         movl    $0, %ebx
152 .L2:    movl    %edi, %esi
153         shr     $22, %esi
154         movl    0xF03C0000(,%esi, 4), %eax
155         cmpl    $0, %eax
156         jne     .L1
157         movl    _MmGlobalKernelPageDirectory(,%esi, 4), %eax
158         movl    %eax, 0xF03C0000(,%esi, 4)
159 .L1:
160         addl    $4096, %edi
161         incl    %ebx
162         cmp     $(MM_STACK_SIZE / 4096), %ebx
163         jl      .L2
164                 
165         /*
166          * FIXME: Restore floating point state
167          */
168
169         /*
170          * FIXME: Restore debugging state
171          */
172
173         /*
174          * Exit the critical section
175          */
176         sti
177         
178         push    $_PiThreadListLock
179         call    _KeReleaseSpinLockFromDpcLevel@4
180         
181         cmpl    $0, _PiNrThreadsAwaitingReaping
182         je      .L3
183         call    _PiWakeupReaperThread@0
184 .L3:    
185         
186         /*
187          * Restore the saved register and exit
188          */
189         popl    %edi
190         popl    %esi
191         popl    %ebx
192         
193         popl    %ebp
194         ret