- Fix link fix build.
[reactos.git] / reactos / ntoskrnl / ke / i386 / ctxswitch.S
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/i386/ctxswitch.S
5 * PURPOSE: Thread Context Switching
6 *
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 * Gregor Anich (FPU Code)
9 */
10
11 /* INCLUDES ******************************************************************/
12
13 #include <asm.inc>
14 #include <ks386.inc>
15
16 EXTERN @KiSwapContextEntry@8:PROC
17 EXTERN @KiSwapContextExit@8:PROC
18 EXTERN @KiRetireDpcList@4:PROC
19 EXTERN @KiEnterV86Mode@4:PROC
20 EXTERN @KiExitV86Mode@4:PROC
21 EXTERN _KeI386FxsrPresent:DWORD
22
23 /* FUNCTIONS ****************************************************************/
24 .code
25
26 PUBLIC @KiSwapContextInternal@0
27 @KiSwapContextInternal@0:
28 /* Build switch frame */
29 sub esp, 2 * 4
30 mov ecx, esp
31 jmp @KiSwapContextEntry@8
32
33
34 PUBLIC @KiSwapContext@8
35 @KiSwapContext@8:
36 /* Save 4 registers */
37 sub esp, 4 * 4
38
39 /* Save all the non-volatile ones */
40 mov [esp+12], ebx
41 mov [esp+8], esi
42 mov [esp+4], edi
43 mov [esp+0], ebp
44
45 /* Get the wait IRQL */
46 or dl, cl
47
48 /* Do the swap with the registers correctly setup */
49 call @KiSwapContextInternal@0
50
51 /* Return the registers */
52 mov ebp, [esp+0]
53 mov edi, [esp+4]
54 mov esi, [esp+8]
55 mov ebx, [esp+12]
56
57 /* Clean stack */
58 add esp, 4 * 4
59 ret
60
61
62 PUBLIC @KiSwitchThreads@8
63 @KiSwitchThreads@8:
64 /* Load the new kernel stack and switch OS to new thread */
65 mov esp, edx
66 call @KiSwapContextExit@8
67
68 /* Now we're on the new thread. Return to the caller to restore registers */
69 add esp, 2 * 4
70 ret
71
72
73 PUBLIC @KiRetireDpcListInDpcStack@8
74 @KiRetireDpcListInDpcStack@8:
75 /* Switch stacks and retire DPCs */
76 mov eax, esp
77 mov esp, edx
78 push eax
79 call @KiRetireDpcList@4
80
81 /* Return on original stack */
82 pop esp
83 ret
84
85 PUBLIC _Ki386EnableCurrentLargePage@8
86 _Ki386EnableCurrentLargePage@8:
87 /* Save StartAddress in eax */
88 mov eax, [esp + 4]
89
90 /* Save new CR3 value in ecx */
91 mov ecx, [esp + 8]
92
93 /* Save flags value */
94 pushfd
95
96 /* Disable interrupts */
97 cli
98
99 /* Compute linear address */
100 sub eax, offset _Ki386EnableCurrentLargePage@8
101 add eax, offset _Ki386LargePageIdentityLabel
102
103 /* Save old CR3 in edx and replace with a new one */
104 mov edx, cr3
105 mov cr3, ecx
106
107 /* Jump to the next instruction but in linear mapping */
108 jmp eax
109
110 _Ki386LargePageIdentityLabel:
111 /* Disable paging */
112 mov eax, cr0
113 and eax, NOT CR0_PG
114 mov cr0, eax
115
116 /* Jump to the next instruction to clear the prefetch queue */
117 jmp $+2
118
119 /* Enable Page Size Extension in CR4 */
120 mov ecx, cr4
121 or ecx, CR4_PSE
122 mov cr4, ecx
123
124 /* Done, now re-enable paging */
125 or eax, CR0_PG
126 mov cr0, eax
127
128 /* Jump to virtual address */
129 mov eax, offset VirtualSpace
130 jmp eax
131
132 VirtualSpace:
133 /* Restore CR3 contents */
134 mov cr3, edx
135
136 /* Restore flags */
137 popfd
138
139 ret 8
140
141 /* FIXFIX: Move to C code ****/
142 PUBLIC _Ki386SetupAndExitToV86Mode@4
143 _Ki386SetupAndExitToV86Mode@4:
144
145 /* Enter V8086 mode */
146 pushad
147 sub esp, (12 + KTRAP_FRAME_LENGTH + NPX_FRAME_LENGTH + 16)
148 mov ecx, esp
149 call @KiEnterV86Mode@4
150 jmp $
151
152
153 PUBLIC @Ki386BiosCallReturnAddress@4
154 @Ki386BiosCallReturnAddress@4:
155
156 /* Exit V8086 mode */
157 call @KiExitV86Mode@4
158 mov esp, eax
159 add esp, (12 + KTRAP_FRAME_LENGTH + NPX_FRAME_LENGTH + 16)
160 popad
161 ret 4
162
163 PUBLIC _FrRestore
164 PUBLIC @Ke386LoadFpuState@4
165 @Ke386LoadFpuState@4:
166
167 /* Check if we have FXSR and choose which operand to use */
168 test byte ptr [_KeI386FxsrPresent], 1
169 jz _FrRestore
170
171 /* Restore all the FPU, MMX, XMM and MXCSR registers */
172 fxrstor [ecx]
173 ret
174
175 /*
176 * Just restore the basic FPU registers.
177 * This may raise an exception depending
178 * on the status word, which KiNpxHandler will
179 * need to check for and handle during delayed load
180 * to avoid raising an unhandled exception
181 * and crashing the system.
182 */
183 _FrRestore:
184 frstor [ecx]
185 ret
186
187 END