[NTOS]
[reactos.git] / reactos / ntoskrnl / include / internal / amd64 / intrin_i.h
1 #ifndef _INTRIN_INTERNAL_
2 #define _INTRIN_INTERNAL_
3
4 #ifdef CONFIG_SMP
5 #define LOCK "lock ; "
6 #else
7 #define LOCK ""
8 #endif
9
10 #define KeSetCurrentIrql(x) __writecr8(x)
11
12 PKGDTENTRY64
13 FORCEINLINE
14 KiGetGdtEntry(PVOID pGdt, USHORT Selector)
15 {
16 return (PKGDTENTRY64)((ULONG64)pGdt + (Selector & ~RPL_MASK));
17 }
18
19 PVOID
20 FORCEINLINE
21 KiGetGdtDescriptorBase(PKGDTENTRY Entry)
22 {
23 return (PVOID)((ULONG64)Entry->BaseLow |
24 (ULONG64)Entry->Bytes.BaseMiddle << 16 |
25 (ULONG64)Entry->Bytes.BaseHigh << 24 |
26 (ULONG64)Entry->BaseUpper << 32);
27 }
28
29 VOID
30 FORCEINLINE
31 KiSetGdtDescriptorBase(PKGDTENTRY Entry, ULONG64 Base)
32 {
33 Entry->BaseLow = Base & 0xffff;
34 Entry->Bits.BaseMiddle = (Base >> 16) & 0xff;
35 Entry->Bits.BaseHigh = (Base >> 24) & 0xff;
36 Entry->BaseUpper = Base >> 32;
37 }
38
39 VOID
40 FORCEINLINE
41 KiSetGdtDescriptorLimit(PKGDTENTRY Entry, ULONG Limit)
42 {
43 Entry->LimitLow = Limit & 0xffff;
44 Entry->Bits.LimitHigh = Limit >> 16;
45 }
46
47 VOID
48 FORCEINLINE
49 KiInitGdtEntry(PKGDTENTRY64 Entry, ULONG64 Base, ULONG Size, UCHAR Type, UCHAR Dpl)
50 {
51 KiSetGdtDescriptorBase(Entry, Base);
52 KiSetGdtDescriptorLimit(Entry, Size - 1);
53 Entry->Bits.Type = Type;
54 Entry->Bits.Dpl = Dpl;
55 Entry->Bits.Present = 1;
56 Entry->Bits.System = 0;
57 Entry->Bits.LongMode = 0;
58 Entry->Bits.DefaultBig = 0;
59 Entry->Bits.Granularity = 0;
60 Entry->MustBeZero = 0;
61 }
62
63 #if defined(__GNUC__)
64
65 static __inline__ __attribute__((always_inline)) void __lgdt(void *Source)
66 {
67 __asm__ __volatile__("lgdt %0" : : "m"(*(short*)Source));
68 }
69
70 static __inline__ __attribute__((always_inline)) void __sgdt(void *Destination)
71 {
72 __asm__ __volatile__("sgdt %0" : : "m"(*(short*)Destination) : "memory");
73 }
74
75 static __inline__ __attribute__((always_inline)) void __lldt(void *Source)
76 {
77 __asm__ __volatile__("lldt %0" : : "m"(*(short*)Source));
78 }
79
80 static __inline__ __attribute__((always_inline)) void __sldt(void *Destination)
81 {
82 __asm__ __volatile__("sldt %0" : : "m"(*(short*)Destination) : "memory");
83 }
84
85 static __inline__ __attribute__((always_inline)) void __ldmxcsr(unsigned long *Source)
86 {
87 __asm__ __volatile__("ldmxcsr %0" : : "m"(*Source));
88 }
89
90 static __inline__ __attribute__((always_inline)) void __stmxcsr(unsigned long *Destination)
91 {
92 __asm__ __volatile__("stmxcsr %0" : : "m"(*Destination) : "memory");
93 }
94
95 static __inline__ __attribute__((always_inline)) void __ltr(unsigned short Source)
96 {
97 __asm__ __volatile__("ltr %0" : : "rm"(Source));
98 }
99
100 static __inline__ __attribute__((always_inline)) void __str(unsigned short *Destination)
101 {
102 __asm__ __volatile__("str %0" : : "m"(*Destination) : "memory");
103 }
104
105
106 #define _Ke386GetSeg(N) ({ \
107 unsigned int __d; \
108 __asm__("movl %%" #N ",%0\n\t" :"=r" (__d)); \
109 __d; \
110 })
111
112 #define _Ke386SetSeg(N,X) __asm__ __volatile__("movl %0,%%" #N : :"r" (X));
113
114 #define _Ke386GetDr(N) ({ \
115 unsigned int __d; \
116 __asm__("movq %%dr" #N ",%0\n\t" :"=r" (__d)); \
117 __d; \
118 })
119
120 #define _Ke386SetDr(N,X) __asm__ __volatile__("movl %0,%%dr" #N : :"r" (X));
121
122
123 static inline void Ki386Cpuid(ULONG Op, PULONG Eax, PULONG Ebx, PULONG Ecx, PULONG Edx)
124 {
125 __asm__("cpuid"
126 : "=a" (*Eax), "=b" (*Ebx), "=c" (*Ecx), "=d" (*Edx)
127 : "0" (Op));
128 }
129
130 #define Ke386Rdmsr(msr,val1,val2) __asm__ __volatile__("rdmsr" : "=a" (val1), "=d" (val2) : "c" (msr))
131 #define Ke386Wrmsr(msr,val1,val2) __asm__ __volatile__("wrmsr" : /* no outputs */ : "c" (msr), "a" (val1), "d" (val2))
132
133 #define Ke386HaltProcessor() __asm__("hlt\n\t");
134
135 #define Ke386FnInit() __asm__("fninit\n\t");
136
137
138 //
139 // CR Macros
140 //
141 #define Ke386SetCr2(X) __asm__ __volatile__("movq %0,%%cr2" : :"r" ((void*)X));
142
143 //
144 // DR Macros
145 //
146 #define Ke386GetDr0() _Ke386GetDr(0)
147 #define Ke386GetDr1() _Ke386GetDr(1)
148 #define Ke386SetDr0(X) _Ke386SetDr(0,X)
149 #define Ke386SetDr1(X) _Ke386SetDr(1,X)
150 #define Ke386GetDr2() _Ke386GetDr(2)
151 #define Ke386SetDr2(X) _Ke386SetDr(2,X)
152 #define Ke386GetDr3() _Ke386GetDr(3)
153 #define Ke386SetDr3(X) _Ke386SetDr(3,X)
154 #define Ke386GetDr4() _Ke386GetDr(4)
155 #define Ke386SetDr4(X) _Ke386SetDr(4,X)
156 #define Ke386GetDr6() _Ke386GetDr(6)
157 #define Ke386SetDr6(X) _Ke386SetDr(6,X)
158 #define Ke386GetDr7() _Ke386GetDr(7)
159 #define Ke386SetDr7(X) _Ke386SetDr(7,X)
160
161 //
162 // Segment Macros
163 //
164 #define Ke386GetSs() _Ke386GetSeg(ss)
165 #define Ke386GetFs() _Ke386GetSeg(fs)
166 #define Ke386SetFs(X) _Ke386SetSeg(fs, X)
167 #define Ke386SetGs(X) _Ke386SetSeg(gs, X)
168 #define Ke386SetDs(X) _Ke386SetSeg(ds, X)
169 #define Ke386SetEs(X) _Ke386SetSeg(es, X)
170 #define Ke386SetSs(X) _Ke386SetSeg(ss, X)
171
172 #elif defined(_MSC_VER)
173
174 VOID
175 FORCEINLINE
176 Ke386Wrmsr(IN ULONG Register,
177 IN ULONG Var1,
178 IN ULONG Var2)
179 {
180 __asm mov eax, Var1;
181 __asm mov edx, Var2;
182 __asm wrmsr;
183 }
184
185 ULONGLONG
186 FORCEINLINE
187 Ke386Rdmsr(IN ULONG Register,
188 IN ULONG Var1,
189 IN ULONG Var2)
190 {
191 __asm mov eax, Var1;
192 __asm mov edx, Var2;
193 __asm rdmsr;
194 }
195
196 VOID
197 FORCEINLINE
198 Ki386Cpuid(IN ULONG Operation,
199 OUT PULONG Var1,
200 OUT PULONG Var2,
201 OUT PULONG Var3,
202 OUT PULONG Var4)
203 {
204 __asm mov eax, Operation;
205 __asm cpuid;
206 __asm mov [Var1], eax;
207 __asm mov [Var2], ebx;
208 __asm mov [Var3], ecx;
209 __asm mov [Var4], edx;
210 }
211
212 VOID
213 FORCEINLINE
214 Ke386FnInit(VOID)
215 {
216 __asm fninit;
217 }
218
219 VOID
220 FORCEINLINE
221 Ke386HaltProcessor(VOID)
222 {
223 __asm hlt;
224 }
225
226 VOID
227 FORCEINLINE
228 Ke386GetInterruptDescriptorTable(OUT KDESCRIPTOR Descriptor)
229 {
230 __asm sidt Descriptor;
231 }
232
233 VOID
234 FORCEINLINE
235 Ke386SetInterruptDescriptorTable(IN KDESCRIPTOR Descriptor)
236 {
237 __asm lidt Descriptor;
238 }
239
240 VOID
241 FORCEINLINE
242 Ke386GetGlobalDescriptorTable(OUT KDESCRIPTOR Descriptor)
243 {
244 __asm sgdt Descriptor;
245 }
246
247 VOID
248 FORCEINLINE
249 Ke386SetGlobalDescriptorTable(IN KDESCRIPTOR Descriptor)
250 {
251 __asm lgdt Descriptor;
252 }
253
254 VOID
255 FORCEINLINE
256 Ke386GetLocalDescriptorTable(OUT USHORT Descriptor)
257 {
258 __asm sldt Descriptor;
259 }
260
261 VOID
262 FORCEINLINE
263 Ke386SetLocalDescriptorTable(IN USHORT Descriptor)
264 {
265 __asm lldt Descriptor;
266 }
267
268 VOID
269 FORCEINLINE
270 Ke386SaveFlags(IN ULONG Flags)
271 {
272 __asm pushf;
273 __asm pop Flags;
274 }
275
276 VOID
277 FORCEINLINE
278 Ke386RestoreFlags(IN ULONG Flags)
279 {
280 __asm push Flags;
281 __asm popf;
282 }
283
284 VOID
285 FORCEINLINE
286 Ke386SetTr(IN USHORT Tr)
287 {
288 __asm ltr Tr;
289 }
290
291 USHORT
292 FORCEINLINE
293 Ke386GetTr(IN USHORT Tr)
294 {
295 __asm str Tr;
296 }
297
298 //
299 // CR Macros
300 //
301 VOID
302 FORCEINLINE
303 Ke386SetCr2(IN ULONG Value)
304 {
305 __asm mov eax, Value;
306 __asm mov cr2, eax;
307 }
308
309 //
310 // DR Macros
311 //
312 ULONG
313 FORCEINLINE
314 Ke386GetDr0(VOID)
315 {
316 __asm mov eax, dr0;
317 }
318
319 ULONG
320 FORCEINLINE
321 Ke386GetDr1(VOID)
322 {
323 __asm mov eax, dr1;
324 }
325
326 ULONG
327 FORCEINLINE
328 Ke386GetDr2(VOID)
329 {
330 __asm mov eax, dr2;
331 }
332
333 ULONG
334 FORCEINLINE
335 Ke386GetDr3(VOID)
336 {
337 __asm mov eax, dr3;
338 }
339
340 ULONG
341 FORCEINLINE
342 Ke386GetDr6(VOID)
343 {
344 __asm mov eax, dr6;
345 }
346
347 ULONG
348 FORCEINLINE
349 Ke386GetDr7(VOID)
350 {
351 __asm mov eax, dr7;
352 }
353
354 VOID
355 FORCEINLINE
356 Ke386SetDr0(IN ULONG Value)
357 {
358 __asm mov eax, Value;
359 __asm mov dr0, eax;
360 }
361
362 VOID
363 FORCEINLINE
364 Ke386SetDr1(IN ULONG Value)
365 {
366 __asm mov eax, Value;
367 __asm mov dr1, eax;
368 }
369
370 VOID
371 FORCEINLINE
372 Ke386SetDr2(IN ULONG Value)
373 {
374 __asm mov eax, Value;
375 __asm mov dr2, eax;
376 }
377
378 VOID
379 FORCEINLINE
380 Ke386SetDr3(IN ULONG Value)
381 {
382 __asm mov eax, Value;
383 __asm mov dr3, eax;
384 }
385
386 VOID
387 FORCEINLINE
388 Ke386SetDr6(IN ULONG Value)
389 {
390 __asm mov eax, Value;
391 __asm mov dr6, eax;
392 }
393
394 VOID
395 FORCEINLINE
396 Ke386SetDr7(IN ULONG Value)
397 {
398 __asm mov eax, Value;
399 __asm mov dr7, eax;
400 }
401
402 //
403 // Segment Macros
404 //
405 USHORT
406 FORCEINLINE
407 Ke386GetSs(VOID)
408 {
409 __asm mov ax, ss;
410 }
411
412 USHORT
413 FORCEINLINE
414 Ke386GetFs(VOID)
415 {
416 __asm mov ax, fs;
417 }
418
419 USHORT
420 FORCEINLINE
421 Ke386GetDs(VOID)
422 {
423 __asm mov ax, ds;
424 }
425
426 USHORT
427 FORCEINLINE
428 Ke386GetEs(VOID)
429 {
430 __asm mov ax, es;
431 }
432
433 VOID
434 FORCEINLINE
435 Ke386SetSs(IN USHORT Value)
436 {
437 __asm mov ax, Value;
438 __asm mov ss, ax;
439 }
440
441 VOID
442 FORCEINLINE
443 Ke386SetFs(IN USHORT Value)
444 {
445 __asm mov ax, Value;
446 __asm mov fs, ax;
447 }
448
449 VOID
450 FORCEINLINE
451 Ke386SetDs(IN USHORT Value)
452 {
453 __asm mov ax, Value;
454 __asm mov ds, ax;
455 }
456
457 VOID
458 FORCEINLINE
459 Ke386SetEs(IN USHORT Value)
460 {
461 __asm mov ax, Value;
462 __asm mov es, ax;
463 }
464
465 #else
466 #error Unknown compiler for inline assembler
467 #endif
468
469 #endif
470
471 /* EOF */