1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/amd64/cpu.c
5 * PURPOSE: Routines for CPU-level support
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 * Timo Kreuzer (timo.kreuzer@reactos.org)
8 */
9
10 /* INCLUDES *****************************************************************/
11
12 #include <ntoskrnl.h>
13 #include <x86x64/Cpuid.h>
14 #include <x86x64/Msr.h>
15 #define NDEBUG
16 #include <debug.h>
17
18 /* GLOBALS *******************************************************************/
19
20 /* The Boot TSS */
21 KTSS64 KiBootTss;
22
23 /* CPU Features and Flags */
24 ULONG KeI386CpuType;
25 ULONG KeI386CpuStep;
26 ULONG KeI386MachineType;
27 ULONG KeI386NpxPresent = 1;
28 ULONG KeLargestCacheLine = 0x40;
29 ULONG KiDmaIoCoherency = 0;
30 BOOLEAN KiSMTProcessorsPresent;
31
32 /* Flush data */
33 volatile LONG KiTbFlushTimeStamp;
34
35 /* CPU Signatures */
36 static const CHAR CmpIntelID[] = "GenuineIntel";
37 static const CHAR CmpAmdID[] = "AuthenticAMD";
38 static const CHAR CmpCentaurID[] = "CentaurHauls";
39
40 typedef union _CPU_SIGNATURE
41 {
42 struct
43 {
44 ULONG Step : 4;
45 ULONG Model : 4;
46 ULONG Family : 4;
47 ULONG Unused : 4;
48 ULONG ExtendedModel : 4;
49 ULONG ExtendedFamily : 8;
50 ULONG Unused2 : 4;
51 };
52 ULONG AsULONG;
53 } CPU_SIGNATURE;
54
55 /* FUNCTIONS *****************************************************************/
56
57 ULONG
58 NTAPI
KiGetCpuVendor(VOID)59 KiGetCpuVendor(VOID)
60 {
61 PKPRCB Prcb = KeGetCurrentPrcb();
62 CPU_INFO CpuInfo;
63
64 /* Get the Vendor ID and null-terminate it */
65 KiCpuId(&CpuInfo, 0);
66
67 /* Copy it to the PRCB and null-terminate it */
68 *(ULONG*)&Prcb->VendorString[0] = CpuInfo.Ebx;
69 *(ULONG*)&Prcb->VendorString[4] = CpuInfo.Edx;
70 *(ULONG*)&Prcb->VendorString[8] = CpuInfo.Ecx;
71 Prcb->VendorString[12] = 0;
72
73 /* Now check the CPU Type */
74 if (!strcmp((PCHAR)Prcb->VendorString, CmpIntelID))
75 {
76 Prcb->CpuVendor = CPU_INTEL;
77 }
78 else if (!strcmp((PCHAR)Prcb->VendorString, CmpAmdID))
79 {
80 Prcb->CpuVendor = CPU_AMD;
81 }
82 else if (!strcmp((PCHAR)Prcb->VendorString, CmpCentaurID))
83 {
84 DPRINT1("VIA CPUs not fully supported\n");
85 Prcb->CpuVendor = CPU_VIA;
86 }
87 else
88 {
89 /* Invalid CPU */
90 DPRINT1("%s CPU support not fully tested!\n", Prcb->VendorString);
91 Prcb->CpuVendor = CPU_UNKNOWN;
92 }
93
94 return Prcb->CpuVendor;
95 }
96
97 VOID
98 NTAPI
KiSetProcessorType(VOID)99 KiSetProcessorType(VOID)
100 {
101 CPU_INFO CpuInfo;
102 CPU_SIGNATURE CpuSignature;
103 BOOLEAN ExtendModel;
104 ULONG Stepping, Type, Vendor;
105
106 /* This initializes Prcb->CpuVendor */
107 Vendor = KiGetCpuVendor();
108
109 /* Do CPUID 1 now */
110 KiCpuId(&CpuInfo, 1);
111
112 /*
113 * Get the Stepping and Type. The stepping contains both the
114 * Model and the Step, while the Type contains the returned Family.
115 *
116 * For the stepping, we convert this: zzzzzzxy into this: x0y
117 */
118 CpuSignature.AsULONG = CpuInfo.Eax;
119 Stepping = CpuSignature.Model;
120 ExtendModel = (CpuSignature.Family == 15);
121 #if ( (NTDDI_VERSION >= NTDDI_WINXPSP2) && (NTDDI_VERSION < NTDDI_WS03) ) || (NTDDI_VERSION >= NTDDI_WS03SP1)
122 if (CpuSignature.Family == 6)
123 {
124 ExtendModel |= (Vendor == CPU_INTEL);
125 #if (NTDDI_VERSION >= NTDDI_WIN8)
126 ExtendModel |= (Vendor == CPU_CENTAUR);
127 #endif
128 }
129 #endif
130 if (ExtendModel)
131 {
132 /* Add ExtendedModel to distinguish from non-extended values. */
133 Stepping |= (CpuSignature.ExtendedModel << 4);
134 }
135 Stepping = (Stepping << 8) | CpuSignature.Step;
136 Type = CpuSignature.Family;
137 if (CpuSignature.Family == 15)
138 {
139 /* Add ExtendedFamily to distinguish from non-extended values.
140 * It must not be larger than 0xF0 to avoid overflow. */
141 Type += min(CpuSignature.ExtendedFamily, 0xF0);
142 }
143
144 /* Save them in the PRCB */
145 KeGetCurrentPrcb()->CpuID = TRUE;
146 KeGetCurrentPrcb()->CpuType = (UCHAR)Type;
147 KeGetCurrentPrcb()->CpuStep = (USHORT)Stepping;
148 }
149
150 /*!
151 \brief Evaluates the KeFeatureFlag bits for the current CPU.
152
153 \return The feature flags for this CPU.
154
155 \see https://www.geoffchappell.com/studies/windows/km/ntoskrnl/structs/kprcb/featurebits.htm
156
157 \todo
158 - KF_VIRT_FIRMWARE_ENABLED 0x08000000 (see notes from Geoff Chappell)
159 - KF_FPU_LEAKAGE 0x0000020000000000ULL
160 - KF_CAT 0x0000100000000000ULL
161 - KF_CET_SS 0x0000400000000000ULL
162 */
163 ULONG64
164 NTAPI
KiGetFeatureBits(VOID)165 KiGetFeatureBits(VOID)
166 {
167 PKPRCB Prcb = KeGetCurrentPrcb();
168 ULONG Vendor;
169 ULONG64 FeatureBits = 0;
170 CPUID_SIGNATURE_REGS signature;
171 CPUID_VERSION_INFO_REGS VersionInfo;
172 CPUID_EXTENDED_FUNCTION_REGS extendedFunction;
173
174 /* Get the Vendor ID */
175 Vendor = Prcb->CpuVendor;
176
177 /* Make sure we got a valid vendor ID at least. */
178 if (Vendor == CPU_UNKNOWN) return FeatureBits;
179
180 /* Get signature CPUID for the maximum function */
181 __cpuid(signature.AsInt32, CPUID_SIGNATURE);
182
183 /* Get the CPUID Info. */
184 __cpuid(VersionInfo.AsInt32, CPUID_VERSION_INFO);
185
186 /* Set the initial APIC ID */
187 Prcb->InitialApicId = (UCHAR)VersionInfo.Ebx.Bits.InitialLocalApicId;
188
189 /* Convert all CPUID Feature bits into our format */
190 if (VersionInfo.Edx.Bits.VME) FeatureBits |= KF_CR4;
191 if (VersionInfo.Edx.Bits.PSE) FeatureBits |= KF_LARGE_PAGE | KF_CR4;
192 if (VersionInfo.Edx.Bits.TSC) FeatureBits |= KF_RDTSC;
193 if (VersionInfo.Edx.Bits.CX8) FeatureBits |= KF_CMPXCHG8B;
194 if (VersionInfo.Edx.Bits.SEP) FeatureBits |= KF_FAST_SYSCALL;
195 if (VersionInfo.Edx.Bits.MTRR) FeatureBits |= KF_MTRR;
196 if (VersionInfo.Edx.Bits.PGE) FeatureBits |= KF_GLOBAL_PAGE | KF_CR4;
197 if (VersionInfo.Edx.Bits.CMOV) FeatureBits |= KF_CMOV;
198 if (VersionInfo.Edx.Bits.PAT) FeatureBits |= KF_PAT;
199 if (VersionInfo.Edx.Bits.DS) FeatureBits |= KF_DTS;
200 if (VersionInfo.Edx.Bits.MMX) FeatureBits |= KF_MMX;
201 if (VersionInfo.Edx.Bits.FXSR) FeatureBits |= KF_FXSR;
202 if (VersionInfo.Edx.Bits.SSE) FeatureBits |= KF_XMMI;
203 if (VersionInfo.Edx.Bits.SSE2) FeatureBits |= KF_XMMI64;
204
205 if (VersionInfo.Ecx.Bits.SSE3) FeatureBits |= KF_SSE3;
206 if (VersionInfo.Ecx.Bits.SSSE3) FeatureBits |= KF_SSSE3;
207 if (VersionInfo.Ecx.Bits.CMPXCHG16B) FeatureBits |= KF_CMPXCHG16B;
208 if (VersionInfo.Ecx.Bits.SSE4_1) FeatureBits |= KF_SSE4_1;
209 if (VersionInfo.Ecx.Bits.XSAVE) FeatureBits |= KF_XSTATE;
210 if (VersionInfo.Ecx.Bits.RDRAND) FeatureBits |= KF_RDRAND;
211
212 /* Check if the CPU has hyper-threading */
213 if (VersionInfo.Edx.Bits.HTT)
214 {
215 /* Set the number of logical CPUs */
216 Prcb->LogicalProcessorsPerPhysicalProcessor =
217 VersionInfo.Ebx.Bits.MaximumAddressableIdsForLogicalProcessors;
218 if (Prcb->LogicalProcessorsPerPhysicalProcessor > 1)
219 {
220 /* We're on dual-core */
221 KiSMTProcessorsPresent = TRUE;
222 }
223 }
224 else
225 {
226 /* We only have a single CPU */
227 Prcb->LogicalProcessorsPerPhysicalProcessor = 1;
228 }
229
230 /* Check if CPUID_THERMAL_POWER_MANAGEMENT (0x06) is supported */
231 if (signature.MaxLeaf >= CPUID_THERMAL_POWER_MANAGEMENT)
232 {
233 /* Read CPUID_THERMAL_POWER_MANAGEMENT */
234 CPUID_THERMAL_POWER_MANAGEMENT_REGS PowerInfo;
235 __cpuid(PowerInfo.AsInt32, CPUID_THERMAL_POWER_MANAGEMENT);
236
237 if (PowerInfo.Undoc.Ecx.ACNT2) FeatureBits |= KF_ACNT2;
238 }
239
240 /* Check if CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS (0x07) is supported */
241 if (signature.MaxLeaf >= CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS)
242 {
243 /* Read CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS */
244 CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_REGS ExtFlags;
245 __cpuidex(ExtFlags.AsInt32,
246 CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS,
247 CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO);
248
249 if (ExtFlags.Ebx.Bits.SMEP) FeatureBits |= KF_SMEP;
250 if (ExtFlags.Ebx.Bits.FSGSBASE) FeatureBits |= KF_RDWRFSGSBASE;
251 if (ExtFlags.Ebx.Bits.SMAP) FeatureBits |= KF_SMAP;
252 }
253
254 /* Check if CPUID_EXTENDED_STATE (0x0D) is supported */
255 if (signature.MaxLeaf >= CPUID_EXTENDED_STATE)
256 {
257 /* Read CPUID_EXTENDED_STATE */
258 CPUID_EXTENDED_STATE_SUB_LEAF_REGS ExtStateSub;
259 __cpuidex(ExtStateSub.AsInt32,
260 CPUID_EXTENDED_STATE,
261 CPUID_EXTENDED_STATE_SUB_LEAF);
262
263 if (ExtStateSub.Eax.Bits.XSAVEOPT) FeatureBits |= KF_XSAVEOPT;
264 if (ExtStateSub.Eax.Bits.XSAVES) FeatureBits |= KF_XSAVES;
265 }
266
267 /* Check extended cpuid features */
268 __cpuid(extendedFunction.AsInt32, CPUID_EXTENDED_FUNCTION);
269 if ((extendedFunction.MaxLeaf & 0xffffff00) == 0x80000000)
270 {
271 /* Check if CPUID_EXTENDED_CPU_SIG (0x80000001) is supported */
272 if (extendedFunction.MaxLeaf >= CPUID_EXTENDED_CPU_SIG)
273 {
274 /* Read CPUID_EXTENDED_CPU_SIG */
275 CPUID_EXTENDED_CPU_SIG_REGS ExtSig;
276 __cpuid(ExtSig.AsInt32, CPUID_EXTENDED_CPU_SIG);
277
278 /* Check if NX-bit is supported */
279 if (ExtSig.Intel.Edx.Bits.NX) FeatureBits |= KF_NX_BIT;
280 if (ExtSig.Intel.Edx.Bits.Page1GB) FeatureBits |= KF_HUGEPAGE;
281 if (ExtSig.Intel.Edx.Bits.RDTSCP) FeatureBits |= KF_RDTSCP;
282
283 /* AMD specific */
284 if (Vendor == CPU_AMD)
285 {
286 if (ExtSig.Amd.Edx.Bits.ThreeDNow) FeatureBits |= KF_3DNOW;
287 }
288 }
289 }
290
291 /* Vendor specific */
292 if (Vendor == CPU_INTEL)
293 {
294 FeatureBits |= KF_GENUINE_INTEL;
295
296 /* Check for models that support LBR */
297 if (VersionInfo.Eax.Bits.FamilyId == 6)
298 {
299 if ((VersionInfo.Eax.Bits.Model == 15) ||
300 (VersionInfo.Eax.Bits.Model == 22) ||
301 (VersionInfo.Eax.Bits.Model == 23) ||
302 (VersionInfo.Eax.Bits.Model == 26))
303 {
304 FeatureBits |= KF_BRANCH;
305 }
306 }
307
308 /* Check if VMX is available */
309 if (VersionInfo.Ecx.Bits.VMX)
310 {
311 /* Read PROCBASED ctls and check if secondary are allowed */
312 MSR_IA32_VMX_PROCBASED_CTLS_REGISTER ProcBasedCtls;
313 ProcBasedCtls.Uint64 = __readmsr(MSR_IA32_VMX_PROCBASED_CTLS);
314 if (ProcBasedCtls.Bits.Allowed1.ActivateSecondaryControls)
315 {
316 /* Read secondary controls and check if EPT is allowed */
317 MSR_IA32_VMX_PROCBASED_CTLS2_REGISTER ProcBasedCtls2;
318 ProcBasedCtls2.Uint64 = __readmsr(MSR_IA32_VMX_PROCBASED_CTLS2);
319 if (ProcBasedCtls2.Bits.Allowed1.EPT)
320 FeatureBits |= KF_SLAT;
321 }
322 }
323 }
324 else if (Vendor == CPU_AMD)
325 {
326 FeatureBits |= KF_AUTHENTICAMD;
327 FeatureBits |= KF_BRANCH;
328
329 /* Check extended cpuid features */
330 if ((extendedFunction.MaxLeaf & 0xffffff00) == 0x80000000)
331 {
332 /* Check if CPUID_AMD_SVM_FEATURES (0x8000000A) is supported */
333 if (extendedFunction.MaxLeaf >= CPUID_AMD_SVM_FEATURES)
334 {
335 /* Read CPUID_AMD_SVM_FEATURES and check if Nested Paging is available */
336 CPUID_AMD_SVM_FEATURES_REGS SvmFeatures;
337 __cpuid(SvmFeatures.AsInt32, CPUID_AMD_SVM_FEATURES);
338 if (SvmFeatures.Edx.Bits.NP) FeatureBits |= KF_SLAT;
339 }
340 }
341 }
342
343 /* Return the Feature Bits */
344 return FeatureBits;
345 }
346
347 #if DBG
348 VOID
KiReportCpuFeatures(IN PKPRCB Prcb)349 KiReportCpuFeatures(IN PKPRCB Prcb)
350 {
351 ULONG CpuFeatures = 0;
352 CPU_INFO CpuInfo;
353
354 if (Prcb->CpuVendor)
355 {
356 KiCpuId(&CpuInfo, 1);
357 CpuFeatures = CpuInfo.Edx;
358 }
359
360 DPRINT1("Supported CPU features: ");
361
362 #define print_kf_bit(kf_value) if (Prcb->FeatureBits & kf_value) DbgPrint(#kf_value " ")
363 print_kf_bit(KF_SMEP);
364 print_kf_bit(KF_RDTSC);
365 print_kf_bit(KF_CR4);
366 print_kf_bit(KF_CMOV);
367 print_kf_bit(KF_GLOBAL_PAGE);
368 print_kf_bit(KF_LARGE_PAGE);
369 print_kf_bit(KF_MTRR);
370 print_kf_bit(KF_CMPXCHG8B);
371 print_kf_bit(KF_MMX);
372 print_kf_bit(KF_DTS);
373 print_kf_bit(KF_PAT);
374 print_kf_bit(KF_FXSR);
375 print_kf_bit(KF_FAST_SYSCALL);
376 print_kf_bit(KF_XMMI);
377 print_kf_bit(KF_3DNOW);
378 print_kf_bit(KF_XSAVEOPT);
379 print_kf_bit(KF_XMMI64);
380 print_kf_bit(KF_BRANCH);
381 print_kf_bit(KF_00040000);
382 print_kf_bit(KF_SSE3);
383 print_kf_bit(KF_CMPXCHG16B);
384 print_kf_bit(KF_AUTHENTICAMD);
385 print_kf_bit(KF_ACNT2);
386 print_kf_bit(KF_XSTATE);
387 print_kf_bit(KF_GENUINE_INTEL);
388 print_kf_bit(KF_SLAT);
389 print_kf_bit(KF_VIRT_FIRMWARE_ENABLED);
390 print_kf_bit(KF_RDWRFSGSBASE);
391 print_kf_bit(KF_NX_BIT);
392 print_kf_bit(KF_NX_DISABLED);
393 print_kf_bit(KF_NX_ENABLED);
394 print_kf_bit(KF_RDRAND);
395 print_kf_bit(KF_SMAP);
396 print_kf_bit(KF_RDTSCP);
397 print_kf_bit(KF_HUGEPAGE);
398 print_kf_bit(KF_XSAVES);
399 print_kf_bit(KF_FPU_LEAKAGE);
400 print_kf_bit(KF_CAT);
401 print_kf_bit(KF_CET_SS);
402 print_kf_bit(KF_SSSE3);
403 print_kf_bit(KF_SSE4_1);
404 print_kf_bit(KF_SSE4_2);
405 #undef print_kf_bit
406
407 #define print_cf(cpu_flag) if (CpuFeatures & cpu_flag) DbgPrint(#cpu_flag " ")
408 print_cf(X86_FEATURE_PAE);
409 print_cf(X86_FEATURE_HT);
410 #undef print_cf
411
412 DbgPrint("\n");
413 }
414 #endif // DBG
415
416 VOID
417 NTAPI
KiGetCacheInformation(VOID)418 KiGetCacheInformation(VOID)
419 {
420 PKIPCR Pcr = (PKIPCR)KeGetPcr();
421 ULONG Vendor;
422 ULONG CacheRequests = 0, i;
423 ULONG CurrentRegister;
424 UCHAR RegisterByte;
425 BOOLEAN FirstPass = TRUE;
426 CPU_INFO CpuInfo;
427
428 /* Set default L2 size */
429 Pcr->SecondLevelCacheSize = 0;
430
431 /* Get the Vendor ID and make sure we support CPUID */
432 Vendor = KiGetCpuVendor();
433 if (!Vendor) return;
434
435 /* Check the Vendor ID */
436 switch (Vendor)
437 {
438 /* Handle Intel case */
439 case CPU_INTEL:
440
441 /*Check if we support CPUID 2 */
442 KiCpuId(&CpuInfo, 0);
443 if (CpuInfo.Eax >= 2)
444 {
445 /* We need to loop for the number of times CPUID will tell us to */
446 do
447 {
448 /* Do the CPUID call */
449 KiCpuId(&CpuInfo, 2);
450
451 /* Check if it was the first call */
452 if (FirstPass)
453 {
454 /*
455 * The number of times to loop is the first byte. Read
456 * it and then destroy it so we don't get confused.
457 */
458 CacheRequests = CpuInfo.Eax & 0xFF;
459 CpuInfo.Eax &= 0xFFFFFF00;
460
461 /* Don't go over this again */
462 FirstPass = FALSE;
463 }
464
465 /* Loop all 4 registers */
466 for (i = 0; i < 4; i++)
467 {
468 /* Get the current register */
469 CurrentRegister = CpuInfo.AsUINT32[i];
470
471 /*
472 * If the upper bit is set, then this register should
473 * be skipped.
474 */
475 if (CurrentRegister & 0x80000000) continue;
476
477 /* Keep looping for every byte inside this register */
478 while (CurrentRegister)
479 {
480 /* Read a byte, skip a byte. */
481 RegisterByte = (UCHAR)(CurrentRegister & 0xFF);
482 CurrentRegister >>= 8;
483 if (!RegisterByte) continue;
484
485 /*
486 * Valid values are from 0x40 (0 bytes) to 0x49
487 * (32MB), or from 0x80 to 0x89 (same size but
488 * 8-way associative.
489 */
490 if (((RegisterByte > 0x40) &&
491 (RegisterByte <= 0x49)) ||
492 ((RegisterByte > 0x80) &&
493 (RegisterByte <= 0x89)))
494 {
495 /* Mask out only the first nibble */
496 RegisterByte &= 0x0F;
497
498 /* Set the L2 Cache Size */
499 Pcr->SecondLevelCacheSize = 0x10000 <<
500 RegisterByte;
501 }
502 }
503 }
504 } while (--CacheRequests);
505 }
506 break;
507
508 case CPU_AMD:
509
510 /* Check if we support CPUID 0x80000006 */
511 KiCpuId(&CpuInfo, 0x80000000);
512 if (CpuInfo.Eax >= 6)
513 {
514 /* Get 2nd level cache and tlb size */
515 KiCpuId(&CpuInfo, 0x80000006);
516
517 /* Set the L2 Cache Size */
518 Pcr->SecondLevelCacheSize = (CpuInfo.Ecx & 0xFFFF0000) >> 6;
519 }
520 break;
521 }
522 }
523
524 VOID
525 NTAPI
KeFlushCurrentTb(VOID)526 KeFlushCurrentTb(VOID)
527 {
528 /* Flush the TLB by resetting CR3 */
529 __writecr3(__readcr3());
530 }
531
532 VOID
533 NTAPI
KiRestoreProcessorControlState(PKPROCESSOR_STATE ProcessorState)534 KiRestoreProcessorControlState(PKPROCESSOR_STATE ProcessorState)
535 {
536 /* Restore the CR registers */
537 __writecr0(ProcessorState->SpecialRegisters.Cr0);
538 // __writecr2(ProcessorState->SpecialRegisters.Cr2);
539 __writecr3(ProcessorState->SpecialRegisters.Cr3);
540 __writecr4(ProcessorState->SpecialRegisters.Cr4);
541 __writecr8(ProcessorState->SpecialRegisters.Cr8);
542
543 /* Restore the DR registers */
544 __writedr(0, ProcessorState->SpecialRegisters.KernelDr0);
545 __writedr(1, ProcessorState->SpecialRegisters.KernelDr1);
546 __writedr(2, ProcessorState->SpecialRegisters.KernelDr2);
547 __writedr(3, ProcessorState->SpecialRegisters.KernelDr3);
548 __writedr(6, ProcessorState->SpecialRegisters.KernelDr6);
549 __writedr(7, ProcessorState->SpecialRegisters.KernelDr7);
550
551 /* Restore GDT, IDT, LDT and TSS */
552 __lgdt(&ProcessorState->SpecialRegisters.Gdtr.Limit);
553 // __lldt(&ProcessorState->SpecialRegisters.Ldtr);
554 // __ltr(&ProcessorState->SpecialRegisters.Tr);
555 __lidt(&ProcessorState->SpecialRegisters.Idtr.Limit);
556
557 _mm_setcsr(ProcessorState->SpecialRegisters.MxCsr);
558 // ProcessorState->SpecialRegisters.DebugControl
559 // ProcessorState->SpecialRegisters.LastBranchToRip
560 // ProcessorState->SpecialRegisters.LastBranchFromRip
561 // ProcessorState->SpecialRegisters.LastExceptionToRip
562 // ProcessorState->SpecialRegisters.LastExceptionFromRip
563
564 /* Restore MSRs */
565 __writemsr(X86_MSR_GSBASE, ProcessorState->SpecialRegisters.MsrGsBase);
566 __writemsr(X86_MSR_KERNEL_GSBASE, ProcessorState->SpecialRegisters.MsrGsSwap);
567 __writemsr(X86_MSR_STAR, ProcessorState->SpecialRegisters.MsrStar);
568 __writemsr(X86_MSR_LSTAR, ProcessorState->SpecialRegisters.MsrLStar);
569 __writemsr(X86_MSR_CSTAR, ProcessorState->SpecialRegisters.MsrCStar);
570 __writemsr(X86_MSR_SFMASK, ProcessorState->SpecialRegisters.MsrSyscallMask);
571
572 }
573
574 VOID
575 NTAPI
KiSaveProcessorControlState(OUT PKPROCESSOR_STATE ProcessorState)576 KiSaveProcessorControlState(OUT PKPROCESSOR_STATE ProcessorState)
577 {
578 /* Save the CR registers */
579 ProcessorState->SpecialRegisters.Cr0 = __readcr0();
580 ProcessorState->SpecialRegisters.Cr2 = __readcr2();
581 ProcessorState->SpecialRegisters.Cr3 = __readcr3();
582 ProcessorState->SpecialRegisters.Cr4 = __readcr4();
583 ProcessorState->SpecialRegisters.Cr8 = __readcr8();
584
585 /* Save the DR registers */
586 ProcessorState->SpecialRegisters.KernelDr0 = __readdr(0);
587 ProcessorState->SpecialRegisters.KernelDr1 = __readdr(1);
588 ProcessorState->SpecialRegisters.KernelDr2 = __readdr(2);
589 ProcessorState->SpecialRegisters.KernelDr3 = __readdr(3);
590 ProcessorState->SpecialRegisters.KernelDr6 = __readdr(6);
591 ProcessorState->SpecialRegisters.KernelDr7 = __readdr(7);
592
593 /* Save GDT, IDT, LDT and TSS */
594 __sgdt(&ProcessorState->SpecialRegisters.Gdtr.Limit);
595 __sldt(&ProcessorState->SpecialRegisters.Ldtr);
596 __str(&ProcessorState->SpecialRegisters.Tr);
597 __sidt(&ProcessorState->SpecialRegisters.Idtr.Limit);
598
599 ProcessorState->SpecialRegisters.MxCsr = _mm_getcsr();
600 // ProcessorState->SpecialRegisters.DebugControl =
601 // ProcessorState->SpecialRegisters.LastBranchToRip =
602 // ProcessorState->SpecialRegisters.LastBranchFromRip =
603 // ProcessorState->SpecialRegisters.LastExceptionToRip =
604 // ProcessorState->SpecialRegisters.LastExceptionFromRip =
605
606 /* Save MSRs */
607 ProcessorState->SpecialRegisters.MsrGsBase = __readmsr(X86_MSR_GSBASE);
608 ProcessorState->SpecialRegisters.MsrGsSwap = __readmsr(X86_MSR_KERNEL_GSBASE);
609 ProcessorState->SpecialRegisters.MsrStar = __readmsr(X86_MSR_STAR);
610 ProcessorState->SpecialRegisters.MsrLStar = __readmsr(X86_MSR_LSTAR);
611 ProcessorState->SpecialRegisters.MsrCStar = __readmsr(X86_MSR_CSTAR);
612 ProcessorState->SpecialRegisters.MsrSyscallMask = __readmsr(X86_MSR_SFMASK);
613 }
614
615 VOID
616 NTAPI
KiSaveProcessorState(_In_ PKTRAP_FRAME TrapFrame,_In_ PKEXCEPTION_FRAME ExceptionFrame)617 KiSaveProcessorState(
618 _In_ PKTRAP_FRAME TrapFrame,
619 _In_ PKEXCEPTION_FRAME ExceptionFrame)
620 {
621 PKPRCB Prcb = KeGetCurrentPrcb();
622
623 /* Save all context */
624 Prcb->ProcessorState.ContextFrame.ContextFlags = CONTEXT_ALL;
625 KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Prcb->ProcessorState.ContextFrame);
626
627 /* Save control registers */
628 KiSaveProcessorControlState(&Prcb->ProcessorState);
629 }
630
631 VOID
632 NTAPI
KiRestoreProcessorState(_Out_ PKTRAP_FRAME TrapFrame,_Out_ PKEXCEPTION_FRAME ExceptionFrame)633 KiRestoreProcessorState(
634 _Out_ PKTRAP_FRAME TrapFrame,
635 _Out_ PKEXCEPTION_FRAME ExceptionFrame)
636 {
637 PKPRCB Prcb = KeGetCurrentPrcb();
638
639 /* Restore all context */
640 KeContextToTrapFrame(&Prcb->ProcessorState.ContextFrame,
641 ExceptionFrame,
642 TrapFrame,
643 CONTEXT_ALL,
644 TrapFrame->PreviousMode);
645
646 /* Restore control registers */
647 KiRestoreProcessorControlState(&Prcb->ProcessorState);
648 }
649
650 VOID
651 NTAPI
KeFlushEntireTb(IN BOOLEAN Invalid,IN BOOLEAN AllProcessors)652 KeFlushEntireTb(IN BOOLEAN Invalid,
653 IN BOOLEAN AllProcessors)
654 {
655 KIRQL OldIrql;
656
657 // FIXME: halfplemented
658 /* Raise the IRQL for the TB Flush */
659 OldIrql = KeRaiseIrqlToSynchLevel();
660
661 /* Flush the TB for the Current CPU, and update the flush stamp */
662 KeFlushCurrentTb();
663
664 /* Update the flush stamp and return to original IRQL */
665 InterlockedExchangeAdd(&KiTbFlushTimeStamp, 1);
666 KeLowerIrql(OldIrql);
667
668 }
669
670 KAFFINITY
671 NTAPI
KeQueryActiveProcessors(VOID)672 KeQueryActiveProcessors(VOID)
673 {
674 PAGED_CODE();
675
676 /* Simply return the number of active processors */
677 return KeActiveProcessors;
678 }
679
680 NTSTATUS
681 NTAPI
KxSaveFloatingPointState(OUT PKFLOATING_SAVE FloatingState)682 KxSaveFloatingPointState(OUT PKFLOATING_SAVE FloatingState)
683 {
684 UNREFERENCED_PARAMETER(FloatingState);
685 return STATUS_SUCCESS;
686 }
687
688 NTSTATUS
689 NTAPI
KxRestoreFloatingPointState(IN PKFLOATING_SAVE FloatingState)690 KxRestoreFloatingPointState(IN PKFLOATING_SAVE FloatingState)
691 {
692 UNREFERENCED_PARAMETER(FloatingState);
693 return STATUS_SUCCESS;
694 }
695
696 BOOLEAN
697 NTAPI
KeInvalidateAllCaches(VOID)698 KeInvalidateAllCaches(VOID)
699 {
700 /* Invalidate all caches */
701 __wbinvd();
702 return TRUE;
703 }
704
705 /*
706 * @implemented
707 */
708 ULONG
709 NTAPI
KeGetRecommendedSharedDataAlignment(VOID)710 KeGetRecommendedSharedDataAlignment(VOID)
711 {
712 /* Return the global variable */
713 return KeLargestCacheLine;
714 }
715
716 /*
717 * @implemented
718 */
719 VOID
720 __cdecl
KeSaveStateForHibernate(IN PKPROCESSOR_STATE State)721 KeSaveStateForHibernate(IN PKPROCESSOR_STATE State)
722 {
723 /* Capture the context */
724 RtlCaptureContext(&State->ContextFrame);
725
726 /* Capture the control state */
727 KiSaveProcessorControlState(State);
728 }
729
730 /*
731 * @implemented
732 */
733 VOID
734 NTAPI
KeSetDmaIoCoherency(IN ULONG Coherency)735 KeSetDmaIoCoherency(IN ULONG Coherency)
736 {
737 /* Save the coherency globally */
738 KiDmaIoCoherency = Coherency;
739 }
740