[NTOS:KE]
[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
22 /* FUNCTIONS ****************************************************************/
23 .code
24
25 PUBLIC @KiSwapContextInternal@0
26 @KiSwapContextInternal@0:
27 /* Build switch frame */
28 sub esp, 2 * 4
29 mov ecx, esp
30 jmp @KiSwapContextEntry@8
31
32
33 PUBLIC @KiSwapContext@8
34 @KiSwapContext@8:
35 /* Save 4 registers */
36 sub esp, 4 * 4
37
38 /* Save all the non-volatile ones */
39 mov [esp+12], ebx
40 mov [esp+8], esi
41 mov [esp+4], edi
42 mov [esp+0], ebp
43
44 /* Get the wait IRQL */
45 or dl, cl
46
47 /* Do the swap with the registers correctly setup */
48 call @KiSwapContextInternal@0
49
50 /* Return the registers */
51 mov ebp, [esp+0]
52 mov edi, [esp+4]
53 mov esi, [esp+8]
54 mov ebx, [esp+12]
55
56 /* Clean stack */
57 add esp, 4 * 4
58 ret
59
60
61 PUBLIC @KiSwitchThreads@8
62 @KiSwitchThreads@8:
63 /* Load the new kernel stack and switch OS to new thread */
64 mov esp, edx
65 call @KiSwapContextExit@8
66
67 /* Now we're on the new thread. Return to the caller to restore registers */
68 add esp, 2 * 4
69 ret
70
71
72 PUBLIC @KiRetireDpcListInDpcStack@8
73 @KiRetireDpcListInDpcStack@8:
74 /* Switch stacks and retire DPCs */
75 mov eax, esp
76 mov esp, edx
77 push eax
78 call @KiRetireDpcList@4
79
80 /* Return on original stack */
81 pop esp
82 ret
83
84 PUBLIC _Ki386EnableCurrentLargePage@8
85 _Ki386EnableCurrentLargePage@8:
86 /* Save StartAddress in eax */
87 mov eax, [esp + 4]
88
89 /* Save new CR3 value in ecx */
90 mov ecx, [esp + 8]
91
92 /* Save flags value */
93 pushfd
94
95 /* Disable interrupts */
96 cli
97
98 /* Compute linear address */
99 sub eax, offset _Ki386EnableCurrentLargePage@8
100 add eax, offset _Ki386LargePageIdentityLabel
101
102 /* Save old CR3 in edx and replace with a new one */
103 mov edx, cr3
104 mov cr3, ecx
105
106 /* Jump to the next instruction but in linear mapping */
107 jmp eax
108
109 _Ki386LargePageIdentityLabel:
110 /* Disable paging */
111 mov eax, cr0
112 and eax, NOT CR0_PG
113 mov cr0, eax
114
115 /* Jump to the next instruction to clear the prefetch queue */
116 jmp $+2
117
118 /* Enable Page Size Extension in CR4 */
119 mov ecx, cr4
120 or ecx, CR4_PSE
121 mov cr4, ecx
122
123 /* Done, now re-enable paging */
124 or eax, CR0_PG
125 mov cr0, eax
126
127 /* Jump to virtual address */
128 mov eax, offset VirtualSpace
129 jmp eax
130
131 VirtualSpace:
132 /* Restore CR3 contents */
133 mov cr3, edx
134
135 /* Restore flags */
136 popfd
137
138 ret 8
139
140 /* FIXFIX: Move to C code ****/
141 PUBLIC _Ki386SetupAndExitToV86Mode@4
142 _Ki386SetupAndExitToV86Mode@4:
143
144 /* Enter V8086 mode */
145 pushad
146 sub esp, (12 + KTRAP_FRAME_LENGTH + NPX_FRAME_LENGTH + 16)
147 mov ecx, esp
148 call @KiEnterV86Mode@4
149 jmp $
150
151
152 PUBLIC @Ki386BiosCallReturnAddress@4
153 @Ki386BiosCallReturnAddress@4:
154
155 /* Exit V8086 mode */
156 call @KiExitV86Mode@4
157 mov esp, eax
158 add esp, (12 + KTRAP_FRAME_LENGTH + NPX_FRAME_LENGTH + 16)
159 popad
160 ret 4
161
162 END