1 #pragma once
2
3 #ifdef __cplusplus
4 extern "C"
5 {
6 #endif
7
8 FORCEINLINE
9 PKGDTENTRY
KiGetGdtEntry(_In_ PVOID pGdt,_In_ USHORT Selector)10 KiGetGdtEntry(
11 _In_ PVOID pGdt,
12 _In_ USHORT Selector)
13 {
14 return (PKGDTENTRY)((ULONG_PTR)pGdt + (Selector & ~RPL_MASK));
15 }
16
17 FORCEINLINE
18 VOID
KiSetGdtDescriptorBase(_Inout_ PKGDTENTRY Entry,_In_ ULONG32 Base)19 KiSetGdtDescriptorBase(
20 _Inout_ PKGDTENTRY Entry,
21 _In_ ULONG32 Base)
22 {
23 Entry->BaseLow = (USHORT)(Base & 0xffff);
24 Entry->HighWord.Bytes.BaseMid = (UCHAR)((Base >> 16) & 0xff);
25 Entry->HighWord.Bytes.BaseHi = (UCHAR)((Base >> 24) & 0xff);
26 // Entry->BaseUpper = (ULONG)(Base >> 32);
27 }
28
29 FORCEINLINE
30 VOID
KiSetGdtDescriptorLimit(_Inout_ PKGDTENTRY Entry,_In_ ULONG Limit)31 KiSetGdtDescriptorLimit(
32 _Inout_ PKGDTENTRY Entry,
33 _In_ ULONG Limit)
34 {
35 if (Limit < 0x100000)
36 {
37 Entry->HighWord.Bits.Granularity = 0;
38 }
39 else
40 {
41 Limit >>= 12;
42 Entry->HighWord.Bits.Granularity = 1;
43 }
44 Entry->LimitLow = (USHORT)(Limit & 0xffff);
45 Entry->HighWord.Bits.LimitHi = ((Limit >> 16) & 0x0f);
46 }
47
48 FORCEINLINE
49 VOID
KiSetGdtEntryEx(_Inout_ PKGDTENTRY Entry,_In_ ULONG32 Base,_In_ ULONG Limit,_In_ UCHAR Type,_In_ UCHAR Dpl,_In_ BOOLEAN Granularity,_In_ UCHAR SegMode)50 KiSetGdtEntryEx(
51 _Inout_ PKGDTENTRY Entry,
52 _In_ ULONG32 Base,
53 _In_ ULONG Limit,
54 _In_ UCHAR Type,
55 _In_ UCHAR Dpl,
56 _In_ BOOLEAN Granularity,
57 _In_ UCHAR SegMode) // 0: 16-bit, 1: 32-bit, 2: 64-bit
58 {
59 KiSetGdtDescriptorBase(Entry, Base);
60 KiSetGdtDescriptorLimit(Entry, Limit);
61 Entry->HighWord.Bits.Type = (Type & 0x1f);
62 Entry->HighWord.Bits.Dpl = (Dpl & 0x3);
63 Entry->HighWord.Bits.Pres = (Type != 0); // Present, must be 1 when the GDT entry is valid.
64 Entry->HighWord.Bits.Sys = 0; // System
65 Entry->HighWord.Bits.Reserved_0 = 0; // LongMode = !!(SegMode & 1);
66 Entry->HighWord.Bits.Default_Big = !!(SegMode & 2);
67 Entry->HighWord.Bits.Granularity |= !!Granularity; // The flag may have been already set by KiSetGdtDescriptorLimit().
68 // Entry->MustBeZero = 0;
69 }
70
71 FORCEINLINE
72 VOID
KiSetGdtEntry(_Inout_ PKGDTENTRY Entry,_In_ ULONG32 Base,_In_ ULONG Limit,_In_ UCHAR Type,_In_ UCHAR Dpl,_In_ UCHAR SegMode)73 KiSetGdtEntry(
74 _Inout_ PKGDTENTRY Entry,
75 _In_ ULONG32 Base,
76 _In_ ULONG Limit,
77 _In_ UCHAR Type,
78 _In_ UCHAR Dpl,
79 _In_ UCHAR SegMode) // 0: 16-bit, 1: 32-bit, 2: 64-bit
80 {
81 KiSetGdtEntryEx(Entry, Base, Limit, Type, Dpl, FALSE, SegMode);
82 }
83
84 #if defined(__GNUC__)
85
86 FORCEINLINE
87 VOID
__lgdt(_Out_ PVOID Descriptor)88 __lgdt(_Out_ PVOID Descriptor)
89 {
90 PVOID* desc = (PVOID*)Descriptor;
91 __asm__ __volatile__(
92 "lgdt %0"
93 : "=m" (*desc)
94 : /* no input */
95 : "memory");
96 }
97
98 FORCEINLINE
99 VOID
__sgdt(_Out_ PVOID Descriptor)100 __sgdt(_Out_ PVOID Descriptor)
101 {
102 PVOID* desc = (PVOID*)Descriptor;
103 __asm__ __volatile__(
104 "sgdt %0"
105 : "=m" (*desc)
106 : /* no input */
107 : "memory");
108 }
109
110 FORCEINLINE
111 VOID
Ke386FxStore(IN PFX_SAVE_AREA SaveArea)112 Ke386FxStore(IN PFX_SAVE_AREA SaveArea)
113 {
114 asm volatile ("fxrstor (%0)" : : "r"(SaveArea));
115 }
116
117 FORCEINLINE
118 VOID
Ke386FxSave(IN PFX_SAVE_AREA SaveArea)119 Ke386FxSave(IN PFX_SAVE_AREA SaveArea)
120 {
121 asm volatile ("fxsave (%0)" : : "r"(SaveArea));
122 }
123
124 FORCEINLINE
125 VOID
Ke386FnSave(IN PFLOATING_SAVE_AREA SaveArea)126 Ke386FnSave(IN PFLOATING_SAVE_AREA SaveArea)
127 {
128 asm volatile ("fnsave (%0); wait" : : "r"(SaveArea));
129 }
130
131 FORCEINLINE
132 VOID
Ke386SaveFpuState(IN PFX_SAVE_AREA SaveArea)133 Ke386SaveFpuState(IN PFX_SAVE_AREA SaveArea)
134 {
135 extern ULONG KeI386FxsrPresent;
136 if (KeI386FxsrPresent)
137 {
138 __asm__ __volatile__ ("fxsave %0\n" : : "m"(*SaveArea));
139 }
140 else
141 {
142 __asm__ __volatile__ ("fnsave %0\n wait\n" : : "m"(*SaveArea));
143 }
144 }
145
146 FORCEINLINE
147 VOID
Ke386RestoreFpuState(_In_ PFX_SAVE_AREA SaveArea)148 Ke386RestoreFpuState(_In_ PFX_SAVE_AREA SaveArea)
149 {
150 extern ULONG KeI386FxsrPresent;
151 if (KeI386FxsrPresent)
152 {
153 __asm__ __volatile__ ("fxrstor %0\n" : : "m"(*SaveArea));
154 }
155 else
156 {
157 __asm__ __volatile__ ("frstor %0\n\t" : "=m" (*SaveArea));
158 }
159 }
160
161 FORCEINLINE
162 VOID
Ke386ClearFpExceptions(VOID)163 Ke386ClearFpExceptions(VOID)
164 {
165 __asm__ __volatile__ ("fnclex");
166 }
167
168 FORCEINLINE
169 VOID
__sldt(PVOID Descriptor)170 __sldt(PVOID Descriptor)
171 {
172 __asm__ __volatile__(
173 "sldt %0"
174 : "=m" (*((short*)Descriptor))
175 : /* no input */
176 : "memory");
177 }
178
179 #define Ke386SetLocalDescriptorTable(X) \
180 __asm__("lldt %w0\n\t" \
181 : /* no outputs */ \
182 : "q" (X));
183
184 #define Ke386SetTr(X) __asm__ __volatile__("ltr %%ax" : :"a" (X));
185
186 FORCEINLINE
187 USHORT
Ke386GetTr(VOID)188 Ke386GetTr(VOID)
189 {
190 USHORT Tr;
191 __asm__("str %0\n\t"
192 : "=m" (Tr));
193 return Tr;
194 }
195
196 #define _Ke386GetSeg(N) ({ \
197 unsigned int __d; \
198 __asm__("movl %%" #N ",%0\n\t" :"=r" (__d)); \
199 __d; \
200 })
201
202 #define _Ke386SetSeg(N,X) __asm__ __volatile__("movl %0,%%" #N : :"r" (X));
203
204 #define Ke386FnInit() __asm__("fninit\n\t");
205 #define Ke386ClearDirectionFlag() __asm__ __volatile__ ("cld")
206
207
208 //
209 // CR Macros
210 //
211 #define Ke386SetCr2(X) __asm__ __volatile__("movl %0,%%cr2" : :"r" (X));
212
213 //
214 // Segment Macros
215 //
216 #define Ke386GetSs() _Ke386GetSeg(ss)
217 #define Ke386GetFs() _Ke386GetSeg(fs)
218 #define Ke386GetDs() _Ke386GetSeg(ds)
219 #define Ke386GetEs() _Ke386GetSeg(es)
220 #define Ke386GetGs() _Ke386GetSeg(gs)
221 #define Ke386SetFs(X) _Ke386SetSeg(fs, X)
222 #define Ke386SetDs(X) _Ke386SetSeg(ds, X)
223 #define Ke386SetEs(X) _Ke386SetSeg(es, X)
224 #define Ke386SetSs(X) _Ke386SetSeg(ss, X)
225 #define Ke386SetGs(X) _Ke386SetSeg(gs, X)
226
227 #elif defined(_MSC_VER)
228
229 FORCEINLINE
230 VOID
Ke386FnInit(VOID)231 Ke386FnInit(VOID)
232 {
233 __asm fninit;
234 }
235
236 FORCEINLINE
237 VOID
__sgdt(OUT PVOID Descriptor)238 __sgdt(OUT PVOID Descriptor)
239 {
240 __asm
241 {
242 mov eax, Descriptor
243 sgdt [eax]
244 }
245 }
246
247 FORCEINLINE
248 VOID
__fxsave(OUT PFX_SAVE_AREA SaveArea)249 __fxsave(OUT PFX_SAVE_AREA SaveArea)
250 {
251 __asm mov eax, SaveArea
252 __asm fxsave [eax]
253 }
254
255 FORCEINLINE
256 VOID
__fxrstor(IN PFX_SAVE_AREA SaveArea)257 __fxrstor(IN PFX_SAVE_AREA SaveArea)
258 {
259 __asm mov eax, SaveArea
260 __asm fxrstor [eax]
261 }
262
263 FORCEINLINE
264 VOID
__frstor(_In_ PFX_SAVE_AREA SaveArea)265 __frstor(_In_ PFX_SAVE_AREA SaveArea)
266 {
267 __asm mov eax, SaveArea
268 __asm frstor [eax]
269 }
270
271 FORCEINLINE
272 VOID
__fnsave(OUT PFLOATING_SAVE_AREA SaveArea)273 __fnsave(OUT PFLOATING_SAVE_AREA SaveArea)
274 {
275 __asm mov eax, SaveArea
276 __asm fnsave [eax]
277 __asm wait;
278 }
279
280 FORCEINLINE
281 VOID
__lgdt(IN PVOID Descriptor)282 __lgdt(IN PVOID Descriptor)
283 {
284 __asm
285 {
286 mov eax, Descriptor
287 lgdt [eax]
288 }
289 }
290
291 FORCEINLINE
292 VOID
__sldt(PVOID Descriptor)293 __sldt(PVOID Descriptor)
294 {
295 __asm
296 {
297 sldt ax
298 mov ecx, Descriptor
299 mov [ecx], ax
300 }
301 }
302
303 FORCEINLINE
304 VOID
Ke386SetLocalDescriptorTable(IN USHORT Descriptor)305 Ke386SetLocalDescriptorTable(IN USHORT Descriptor)
306 {
307 __asm lldt Descriptor;
308 }
309
310 FORCEINLINE
311 VOID
Ke386SetTr(IN USHORT Tr)312 Ke386SetTr(IN USHORT Tr)
313 {
314 __asm ltr Tr;
315 }
316
317 FORCEINLINE
318 USHORT
Ke386GetTr(VOID)319 Ke386GetTr(VOID)
320 {
321 __asm str ax;
322 }
323
324 //
325 // CR Macros
326 //
327 FORCEINLINE
328 VOID
Ke386SetCr2(IN ULONG Value)329 Ke386SetCr2(IN ULONG Value)
330 {
331 __asm mov eax, Value;
332 __asm mov cr2, eax;
333 }
334
335 //
336 // Segment Macros
337 //
338 FORCEINLINE
339 USHORT
Ke386GetSs(VOID)340 Ke386GetSs(VOID)
341 {
342 __asm mov ax, ss;
343 }
344
345 FORCEINLINE
346 USHORT
Ke386GetFs(VOID)347 Ke386GetFs(VOID)
348 {
349 __asm mov ax, fs;
350 }
351
352 FORCEINLINE
353 USHORT
Ke386GetDs(VOID)354 Ke386GetDs(VOID)
355 {
356 __asm mov ax, ds;
357 }
358
359 FORCEINLINE
360 USHORT
Ke386GetEs(VOID)361 Ke386GetEs(VOID)
362 {
363 __asm mov ax, es;
364 }
365
366 FORCEINLINE
367 VOID
Ke386SetSs(IN USHORT Value)368 Ke386SetSs(IN USHORT Value)
369 {
370 __asm mov ax, Value;
371 __asm mov ss, ax;
372 }
373
374 FORCEINLINE
375 VOID
Ke386SetFs(IN USHORT Value)376 Ke386SetFs(IN USHORT Value)
377 {
378 __asm mov ax, Value;
379 __asm mov fs, ax;
380 }
381
382 FORCEINLINE
383 VOID
Ke386SetDs(IN USHORT Value)384 Ke386SetDs(IN USHORT Value)
385 {
386 __asm mov ax, Value;
387 __asm mov ds, ax;
388 }
389
390 FORCEINLINE
391 VOID
Ke386SetEs(IN USHORT Value)392 Ke386SetEs(IN USHORT Value)
393 {
394 __asm mov ax, Value;
395 __asm mov es, ax;
396 }
397
398 FORCEINLINE
399 VOID
Ke386SetGs(IN USHORT Value)400 Ke386SetGs(IN USHORT Value)
401 {
402 __asm mov ax, Value;
403 __asm mov gs, ax;
404 }
405
406 extern ULONG KeI386FxsrPresent;
407
408 FORCEINLINE
409 VOID
Ke386SaveFpuState(IN PVOID SaveArea)410 Ke386SaveFpuState(IN PVOID SaveArea)
411 {
412 if (KeI386FxsrPresent)
413 {
414 __fxsave((PFX_SAVE_AREA)SaveArea);
415 }
416 else
417 {
418 __fnsave((PFLOATING_SAVE_AREA)SaveArea);
419 }
420 }
421
422 FORCEINLINE
423 VOID
Ke386RestoreFpuState(_In_ PVOID SaveArea)424 Ke386RestoreFpuState(_In_ PVOID SaveArea)
425 {
426 if (KeI386FxsrPresent)
427 {
428 __fxrstor((PFX_SAVE_AREA)SaveArea);
429 }
430 else
431 {
432 __frstor((PFX_SAVE_AREA)SaveArea);
433 }
434 }
435
436 FORCEINLINE
437 VOID
Ke386ClearFpExceptions(VOID)438 Ke386ClearFpExceptions(VOID)
439 {
440 __asm fnclex;
441 }
442
443 #define Ke386FnSave __fnsave
444 #define Ke386FxSave __fxsave
445 // The name suggest, that the original author didn't understand what frstor means
446 #define Ke386FxStore __fxrstor
447
448 #else
449 #error Unknown compiler for inline assembler
450 #endif
451
452 #define Ke386GetGlobalDescriptorTable __sgdt
453 #define Ke386SetGlobalDescriptorTable __lgdt
454 #define Ke386GetLocalDescriptorTable __sldt
455
456 #ifdef __cplusplus
457 } // extern "C"
458 #endif
459
460 /* EOF */
461