1 #pragma once
2 
3 #ifdef __cplusplus
4 extern "C"
5 {
6 #endif
7 
8 FORCEINLINE
9 PKGDTENTRY
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
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
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
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
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
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
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
112 Ke386FxStore(IN PFX_SAVE_AREA SaveArea)
113 {
114     asm volatile ("fxrstor (%0)" : : "r"(SaveArea));
115 }
116 
117 FORCEINLINE
118 VOID
119 Ke386FxSave(IN PFX_SAVE_AREA SaveArea)
120 {
121     asm volatile ("fxsave (%0)" : : "r"(SaveArea));
122 }
123 
124 FORCEINLINE
125 VOID
126 Ke386FnSave(IN PFLOATING_SAVE_AREA SaveArea)
127 {
128     asm volatile ("fnsave (%0); wait" : : "r"(SaveArea));
129 }
130 
131 FORCEINLINE
132 VOID
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
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
163 Ke386ClearFpExceptions(VOID)
164 {
165     __asm__ __volatile__ ("fnclex");
166 }
167 
168 FORCEINLINE
169 VOID
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
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
231 Ke386FnInit(VOID)
232 {
233     __asm fninit;
234 }
235 
236 FORCEINLINE
237 VOID
238 __sgdt(OUT PVOID Descriptor)
239 {
240     __asm
241     {
242         mov eax, Descriptor
243         sgdt [eax]
244     }
245 }
246 
247 FORCEINLINE
248 VOID
249 __fxsave(OUT PFX_SAVE_AREA SaveArea)
250 {
251     __asm mov eax, SaveArea
252     __asm fxsave [eax]
253 }
254 
255 FORCEINLINE
256 VOID
257 __fxrstor(IN PFX_SAVE_AREA SaveArea)
258 {
259     __asm mov eax, SaveArea
260     __asm fxrstor [eax]
261 }
262 
263 FORCEINLINE
264 VOID
265 __frstor(_In_ PFX_SAVE_AREA SaveArea)
266 {
267     __asm mov eax, SaveArea
268     __asm frstor [eax]
269 }
270 
271 FORCEINLINE
272 VOID
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
282 __lgdt(IN PVOID Descriptor)
283 {
284     __asm
285     {
286         mov eax, Descriptor
287         lgdt [eax]
288     }
289 }
290 
291 FORCEINLINE
292 VOID
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
305 Ke386SetLocalDescriptorTable(IN USHORT Descriptor)
306 {
307     __asm lldt Descriptor;
308 }
309 
310 FORCEINLINE
311 VOID
312 Ke386SetTr(IN USHORT Tr)
313 {
314     __asm ltr Tr;
315 }
316 
317 FORCEINLINE
318 USHORT
319 Ke386GetTr(VOID)
320 {
321     __asm str ax;
322 }
323 
324 //
325 // CR Macros
326 //
327 FORCEINLINE
328 VOID
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
340 Ke386GetSs(VOID)
341 {
342     __asm mov ax, ss;
343 }
344 
345 FORCEINLINE
346 USHORT
347 Ke386GetFs(VOID)
348 {
349     __asm mov ax, fs;
350 }
351 
352 FORCEINLINE
353 USHORT
354 Ke386GetDs(VOID)
355 {
356     __asm mov ax, ds;
357 }
358 
359 FORCEINLINE
360 USHORT
361 Ke386GetEs(VOID)
362 {
363     __asm mov ax, es;
364 }
365 
366 FORCEINLINE
367 VOID
368 Ke386SetSs(IN USHORT Value)
369 {
370     __asm mov ax, Value;
371     __asm mov ss, ax;
372 }
373 
374 FORCEINLINE
375 VOID
376 Ke386SetFs(IN USHORT Value)
377 {
378     __asm mov ax, Value;
379     __asm mov fs, ax;
380 }
381 
382 FORCEINLINE
383 VOID
384 Ke386SetDs(IN USHORT Value)
385 {
386     __asm mov ax, Value;
387     __asm mov ds, ax;
388 }
389 
390 FORCEINLINE
391 VOID
392 Ke386SetEs(IN USHORT Value)
393 {
394     __asm mov ax, Value;
395     __asm mov es, ax;
396 }
397 
398 FORCEINLINE
399 VOID
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
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
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
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