ReactOS  r75907
cpu.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: ntoskrnl/ke/i386/cpu.c
5  * PURPOSE: Routines for CPU-level support
6  * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7  */
8 
9 /* INCLUDES *****************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 /* GLOBALS *******************************************************************/
16 
17 /* The TSS to use for Double Fault Traps (INT 0x9) */
19 
20 /* The TSS to use for NMI Fault Traps (INT 0x2) */
22 
23 /* CPU Features and Flags */
42 
43 /* The distance between SYSEXIT and IRETD return modes */
45 
46 /* The offset that was applied -- either 0 or the value above */
48 
49 /* Whether the adjustment was already done once */
51 
52 /* Flush data */
54 
55 /* CPU Signatures */
56 static const CHAR CmpIntelID[] = "GenuineIntel";
57 static const CHAR CmpAmdID[] = "AuthenticAMD";
58 static const CHAR CmpCyrixID[] = "CyrixInstead";
59 static const CHAR CmpTransmetaID[] = "GenuineTMx86";
60 static const CHAR CmpCentaurID[] = "CentaurHauls";
61 static const CHAR CmpRiseID[] = "RiseRiseRise";
62 
63 /* SUPPORT ROUTINES FOR MSVC COMPATIBILITY ***********************************/
64 
65 /* NSC/Cyrix CPU configuration register index */
66 #define CX86_CCR1 0xc1
67 
68 /* NSC/Cyrix CPU indexed register access macros */
69 static __inline
70 UCHAR
72 {
73  WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)0x22, reg);
74  return READ_PORT_UCHAR((PUCHAR)(ULONG_PTR)0x23);
75 }
76 
77 static __inline
78 void
80 {
81  WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)0x22, reg);
82  WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)0x23, data);
83 }
84 
85 
86 /* FUNCTIONS *****************************************************************/
87 
88 VOID
89 NTAPI
92 {
93  ULONG EFlags, NewEFlags;
94  CPU_INFO CpuInfo;
95  ULONG Stepping, Type;
96 
97  /* Start by assuming no CPUID data */
98  KeGetCurrentPrcb()->CpuID = 0;
99 
100  /* Save EFlags */
101  EFlags = __readeflags();
102 
103  /* XOR out the ID bit and update EFlags */
104  NewEFlags = EFlags ^ EFLAGS_ID;
105  __writeeflags(NewEFlags);
106 
107  /* Get them back and see if they were modified */
108  NewEFlags = __readeflags();
109  if (NewEFlags != EFlags)
110  {
111  /* The modification worked, so CPUID exists. Set the ID Bit again. */
112  EFlags |= EFLAGS_ID;
113  __writeeflags(EFlags);
114 
115  /* Peform CPUID 0 to see if CPUID 1 is supported */
116  KiCpuId(&CpuInfo, 0);
117  if (CpuInfo.Eax > 0)
118  {
119  /* Do CPUID 1 now */
120  KiCpuId(&CpuInfo, 1);
121 
122  /*
123  * Get the Stepping and Type. The stepping contains both the
124  * Model and the Step, while the Type contains the returned Type.
125  * We ignore the family.
126  *
127  * For the stepping, we convert this: zzzzzzxy into this: x0y
128  */
129  Stepping = CpuInfo.Eax & 0xF0;
130  Stepping <<= 4;
131  Stepping += (CpuInfo.Eax & 0xFF);
132  Stepping &= 0xF0F;
133  Type = CpuInfo.Eax & 0xF00;
134  Type >>= 8;
135 
136  /* Save them in the PRCB */
137  KeGetCurrentPrcb()->CpuID = TRUE;
138  KeGetCurrentPrcb()->CpuType = (UCHAR)Type;
139  KeGetCurrentPrcb()->CpuStep = (USHORT)Stepping;
140  }
141  else
142  {
143  DPRINT1("CPUID Support lacking\n");
144  }
145  }
146  else
147  {
148  DPRINT1("CPUID Support lacking\n");
149  }
150 
151  /* Restore EFLAGS */
152  __writeeflags(EFlags);
153 }
154 
155 ULONG
156 NTAPI
159 {
160  PKPRCB Prcb = KeGetCurrentPrcb();
161  CPU_INFO CpuInfo;
162 
163  /* Assume no Vendor ID and fail if no CPUID Support. */
164  Prcb->VendorString[0] = 0;
165  if (!Prcb->CpuID) return 0;
166 
167  /* Get the Vendor ID */
168  KiCpuId(&CpuInfo, 0);
169 
170  /* Copy it to the PRCB and null-terminate it */
171  *(ULONG*)&Prcb->VendorString[0] = CpuInfo.Ebx;
172  *(ULONG*)&Prcb->VendorString[4] = CpuInfo.Edx;
173  *(ULONG*)&Prcb->VendorString[8] = CpuInfo.Ecx;
174  Prcb->VendorString[12] = 0;
175 
176  /* Now check the CPU Type */
177  if (!strcmp(Prcb->VendorString, CmpIntelID))
178  {
179  return CPU_INTEL;
180  }
181  else if (!strcmp(Prcb->VendorString, CmpAmdID))
182  {
183  return CPU_AMD;
184  }
185  else if (!strcmp(Prcb->VendorString, CmpCyrixID))
186  {
187  DPRINT1("Cyrix CPU support not fully tested!\n");
188  return CPU_CYRIX;
189  }
190  else if (!strcmp(Prcb->VendorString, CmpTransmetaID))
191  {
192  DPRINT1("Transmeta CPU support not fully tested!\n");
193  return CPU_TRANSMETA;
194  }
195  else if (!strcmp(Prcb->VendorString, CmpCentaurID))
196  {
197  DPRINT1("Centaur CPU support not fully tested!\n");
198  return CPU_CENTAUR;
199  }
200  else if (!strcmp(Prcb->VendorString, CmpRiseID))
201  {
202  DPRINT1("Rise CPU support not fully tested!\n");
203  return CPU_RISE;
204  }
205 
206  /* Unknown CPU */
207  DPRINT1("%s CPU support not fully tested!\n", Prcb->VendorString);
208  return CPU_UNKNOWN;
209 }
210 
211 ULONG
212 NTAPI
215 {
216  PKPRCB Prcb = KeGetCurrentPrcb();
217  ULONG Vendor;
218  ULONG FeatureBits = KF_WORKING_PTE;
219  CPU_INFO CpuInfo, DummyCpuInfo;
220  UCHAR Ccr1;
221  BOOLEAN ExtendedCPUID = TRUE;
222  ULONG CpuFeatures = 0;
223 
224  /* Get the Vendor ID */
225  Vendor = KiGetCpuVendor();
226 
227  /* Make sure we got a valid vendor ID at least. */
228  if (!Vendor) return FeatureBits;
229 
230  /* Get the CPUID Info. Features are in Reg[3]. */
231  KiCpuId(&CpuInfo, 1);
232 
233  /* Set the initial APIC ID */
234  Prcb->InitialApicId = (UCHAR)(CpuInfo.Ebx >> 24);
235 
236  switch (Vendor)
237  {
238  /* Intel CPUs */
239  case CPU_INTEL:
240 
241  /* Check if it's a P6 */
242  if (Prcb->CpuType == 6)
243  {
244  /* Perform the special sequence to get the MicroCode Signature */
245  __writemsr(0x8B, 0);
246  KiCpuId(&DummyCpuInfo, 1);
247  Prcb->UpdateSignature.QuadPart = __readmsr(0x8B);
248  }
249  else if (Prcb->CpuType == 5)
250  {
251  /* On P5, enable workaround for the LOCK errata. */
253  }
254 
255  /* Check for broken P6 with bad SMP PTE implementation */
256  if (((CpuInfo.Eax & 0x0FF0) == 0x0610 && (CpuInfo.Eax & 0x000F) <= 0x9) ||
257  ((CpuInfo.Eax & 0x0FF0) == 0x0630 && (CpuInfo.Eax & 0x000F) <= 0x4))
258  {
259  /* Remove support for correct PTE support. */
260  FeatureBits &= ~KF_WORKING_PTE;
261  }
262 
263  /* Check if the CPU is too old to support SYSENTER */
264  if ((Prcb->CpuType < 6) ||
265  ((Prcb->CpuType == 6) && (Prcb->CpuStep < 0x0303)))
266  {
267  /* Disable it */
268  CpuInfo.Edx &= ~0x800;
269  }
270 
271  break;
272 
273  /* AMD CPUs */
274  case CPU_AMD:
275 
276  /* Check if this is a K5 or K6. (family 5) */
277  if ((CpuInfo.Eax & 0x0F00) == 0x0500)
278  {
279  /* Get the Model Number */
280  switch (CpuInfo.Eax & 0x00F0)
281  {
282  /* Model 1: K5 - 5k86 (initial models) */
283  case 0x0010:
284 
285  /* Check if this is Step 0 or 1. They don't support PGE */
286  if ((CpuInfo.Eax & 0x000F) > 0x03) break;
287 
288  /* Model 0: K5 - SSA5 */
289  case 0x0000:
290 
291  /* Model 0 doesn't support PGE at all. */
292  CpuInfo.Edx &= ~0x2000;
293  break;
294 
295  /* Model 8: K6-2 */
296  case 0x0080:
297 
298  /* K6-2, Step 8 and over have support for MTRR. */
299  if ((CpuInfo.Eax & 0x000F) >= 0x8) FeatureBits |= KF_AMDK6MTRR;
300  break;
301 
302  /* Model 9: K6-III
303  Model D: K6-2+, K6-III+ */
304  case 0x0090:
305  case 0x00D0:
306 
307  FeatureBits |= KF_AMDK6MTRR;
308  break;
309  }
310  }
311  else if((CpuInfo.Eax & 0x0F00) < 0x0500)
312  {
313  /* Families below 5 don't support PGE, PSE or CMOV at all */
314  CpuInfo.Edx &= ~(0x08 | 0x2000 | 0x8000);
315 
316  /* They also don't support advanced CPUID functions. */
317  ExtendedCPUID = FALSE;
318  }
319 
320  break;
321 
322  /* Cyrix CPUs */
323  case CPU_CYRIX:
324 
325  /* Workaround the "COMA" bug on 6x family of Cyrix CPUs */
326  if (Prcb->CpuType == 6 &&
327  Prcb->CpuStep <= 1)
328  {
329  /* Get CCR1 value */
330  Ccr1 = getCx86(CX86_CCR1);
331 
332  /* Enable the NO_LOCK bit */
333  Ccr1 |= 0x10;
334 
335  /* Set the new CCR1 value */
336  setCx86(CX86_CCR1, Ccr1);
337  }
338 
339  break;
340 
341  /* Transmeta CPUs */
342  case CPU_TRANSMETA:
343 
344  /* Enable CMPXCHG8B if the family (>= 5), model and stepping (>= 4.2) support it */
345  if ((CpuInfo.Eax & 0x0FFF) >= 0x0542)
346  {
347  __writemsr(0x80860004, __readmsr(0x80860004) | 0x0100);
348  FeatureBits |= KF_CMPXCHG8B;
349  }
350 
351  break;
352 
353  /* Centaur, IDT, Rise and VIA CPUs */
354  case CPU_CENTAUR:
355  case CPU_RISE:
356 
357  /* These CPUs don't report the presence of CMPXCHG8B through CPUID.
358  However, this feature exists and operates properly without any additional steps. */
359  FeatureBits |= KF_CMPXCHG8B;
360 
361  break;
362  }
363 
364  /* Set the current features */
365  CpuFeatures = CpuInfo.Edx;
366 
367  /* Convert all CPUID Feature bits into our format */
368  if (CpuFeatures & 0x00000002) FeatureBits |= KF_V86_VIS | KF_CR4;
369  if (CpuFeatures & 0x00000008) FeatureBits |= KF_LARGE_PAGE | KF_CR4;
370  if (CpuFeatures & 0x00000010) FeatureBits |= KF_RDTSC;
371  if (CpuFeatures & 0x00000100) FeatureBits |= KF_CMPXCHG8B;
372  if (CpuFeatures & 0x00000800) FeatureBits |= KF_FAST_SYSCALL;
373  if (CpuFeatures & 0x00001000) FeatureBits |= KF_MTRR;
374  if (CpuFeatures & 0x00002000) FeatureBits |= KF_GLOBAL_PAGE | KF_CR4;
375  if (CpuFeatures & 0x00008000) FeatureBits |= KF_CMOV;
376  if (CpuFeatures & 0x00010000) FeatureBits |= KF_PAT;
377  if (CpuFeatures & 0x00200000) FeatureBits |= KF_DTS;
378  if (CpuFeatures & 0x00800000) FeatureBits |= KF_MMX;
379  if (CpuFeatures & 0x01000000) FeatureBits |= KF_FXSR;
380  if (CpuFeatures & 0x02000000) FeatureBits |= KF_XMMI;
381  if (CpuFeatures & 0x04000000) FeatureBits |= KF_XMMI64;
382 
383  /* Check if the CPU has hyper-threading */
384  if (CpuFeatures & 0x10000000)
385  {
386  /* Set the number of logical CPUs */
387  Prcb->LogicalProcessorsPerPhysicalProcessor = (UCHAR)(CpuInfo.Ebx >> 16);
389  {
390  /* We're on dual-core */
392  }
393  }
394  else
395  {
396  /* We only have a single CPU */
398  }
399 
400  /* Check if CPUID 0x80000000 is supported */
401  if (ExtendedCPUID)
402  {
403  /* Do the call */
404  KiCpuId(&CpuInfo, 0x80000000);
405  if ((CpuInfo.Eax & 0xffffff00) == 0x80000000)
406  {
407  /* Check if CPUID 0x80000001 is supported */
408  if (CpuInfo.Eax >= 0x80000001)
409  {
410  /* Check which extended features are available. */
411  KiCpuId(&CpuInfo, 0x80000001);
412 
413  /* Check if NX-bit is supported */
414  if (CpuInfo.Edx & 0x00100000) FeatureBits |= KF_NX_BIT;
415 
416  /* Now handle each features for each CPU Vendor */
417  switch (Vendor)
418  {
419  case CPU_AMD:
420  case CPU_CENTAUR:
421  if (CpuInfo.Edx & 0x80000000) FeatureBits |= KF_3DNOW;
422  break;
423  }
424  }
425  }
426  }
427 
428 #define print_supported(kf_value) ((FeatureBits & kf_value) ? #kf_value : "")
429  DPRINT1("Supported CPU features : %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
451 #undef print_supported
452 
453  /* Return the Feature Bits */
454  return FeatureBits;
455 }
456 
457 VOID
458 NTAPI
461 {
462  PKIPCR Pcr = (PKIPCR)KeGetPcr();
463  ULONG Vendor;
464  CPU_INFO CpuInfo;
465  ULONG CacheRequests = 0, i;
466  ULONG CurrentRegister;
467  UCHAR RegisterByte, Associativity = 0;
468  ULONG Size, CacheLine = 64, CurrentSize = 0;
469  BOOLEAN FirstPass = TRUE;
470 
471  /* Set default L2 size */
472  Pcr->SecondLevelCacheSize = 0;
473 
474  /* Get the Vendor ID and make sure we support CPUID */
475  Vendor = KiGetCpuVendor();
476  if (!Vendor) return;
477 
478  /* Check the Vendor ID */
479  switch (Vendor)
480  {
481  /* Handle Intel case */
482  case CPU_INTEL:
483 
484  /*Check if we support CPUID 2 */
485  KiCpuId(&CpuInfo, 0);
486  if (CpuInfo.Eax >= 2)
487  {
488  /* We need to loop for the number of times CPUID will tell us to */
489  do
490  {
491  /* Do the CPUID call */
492  KiCpuId(&CpuInfo, 2);
493 
494  /* Check if it was the first call */
495  if (FirstPass)
496  {
497  /*
498  * The number of times to loop is the first byte. Read
499  * it and then destroy it so we don't get confused.
500  */
501  CacheRequests = CpuInfo.Eax & 0xFF;
502  CpuInfo.Eax &= 0xFFFFFF00;
503 
504  /* Don't go over this again */
505  FirstPass = FALSE;
506  }
507 
508  /* Loop all 4 registers */
509  for (i = 0; i < 4; i++)
510  {
511  /* Get the current register */
512  CurrentRegister = CpuInfo.AsUINT32[i];
513 
514  /*
515  * If the upper bit is set, then this register should
516  * be skipped.
517  */
518  if (CurrentRegister & 0x80000000) continue;
519 
520  /* Keep looping for every byte inside this register */
521  while (CurrentRegister)
522  {
523  /* Read a byte, skip a byte. */
524  RegisterByte = (UCHAR)(CurrentRegister & 0xFF);
525  CurrentRegister >>= 8;
526  if (!RegisterByte) continue;
527 
528  Size = 0;
529  switch (RegisterByte)
530  {
531  case 0x06:
532  case 0x08:
534  break;
535  case 0x09:
537  break;
538  case 0x0a:
539  case 0x0c:
541  break;
542  case 0x0d:
543  case 0x0e:
545  break;
546  case 0x1d:
547  Size = 128 * 1024;
548  Associativity = 2;
549  break;
550  case 0x21:
551  Size = 256 * 1024;
552  Associativity = 8;
553  break;
554  case 0x24:
555  Size = 1024 * 1024;
556  Associativity = 16;
557  break;
558  case 0x2c:
559  case 0x30:
561  break;
562  case 0x41:
563  case 0x42:
564  case 0x43:
565  case 0x44:
566  case 0x45:
567  Size = (1 << (RegisterByte - 0x41)) * 128 * 1024;
568  Associativity = 4;
569  break;
570  case 0x48:
571  Size = 3 * 1024 * 1024;
572  Associativity = 12;
573  break;
574  case 0x49:
575  Size = 4 * 1024 * 1024;
576  Associativity = 16;
577  break;
578  case 0x4e:
579  Size = 6 * 1024 * 1024;
580  Associativity = 24;
581  break;
582  case 0x60:
583  case 0x66:
584  case 0x67:
585  case 0x68:
587  break;
588  case 0x78:
589  Size = 1024 * 1024;
590  Associativity = 4;
591  break;
592  case 0x79:
593  case 0x7a:
594  case 0x7b:
595  case 0x7c:
596  case 0x7d:
597  Size = (1 << (RegisterByte - 0x79)) * 128 * 1024;
598  Associativity = 8;
599  break;
600  case 0x7f:
601  Size = 512 * 1024;
602  Associativity = 2;
603  break;
604  case 0x80:
605  Size = 512 * 1024;
606  Associativity = 8;
607  break;
608  case 0x82:
609  case 0x83:
610  case 0x84:
611  case 0x85:
612  Size = (1 << (RegisterByte - 0x82)) * 256 * 1024;
613  Associativity = 8;
614  break;
615  case 0x86:
616  Size = 512 * 1024;
617  Associativity = 4;
618  break;
619  case 0x87:
620  Size = 1024 * 1024;
621  Associativity = 8;
622  break;
623  case 0xf0:
625  break;
626  case 0xf1:
628  break;
629  }
630  if (Size && (Size / Associativity) > CurrentSize)
631  {
632  /* Set the L2 Cache Size and Associativity */
633  CurrentSize = Size / Associativity;
634  Pcr->SecondLevelCacheSize = Size;
635  Pcr->SecondLevelCacheAssociativity = Associativity;
636  }
637  }
638  }
639  } while (--CacheRequests);
640  }
641  break;
642 
643  case CPU_AMD:
644 
645  /* Check if we support CPUID 0x80000005 */
646  KiCpuId(&CpuInfo, 0x80000000);
647  if (CpuInfo.Eax >= 0x80000005)
648  {
649  /* Get L1 size first */
650  KiCpuId(&CpuInfo, 0x80000005);
651  KePrefetchNTAGranularity = CpuInfo.Ecx & 0xFF;
652 
653  /* Check if we support CPUID 0x80000006 */
654  KiCpuId(&CpuInfo, 0x80000000);
655  if (CpuInfo.Eax >= 0x80000006)
656  {
657  /* Get 2nd level cache and tlb size */
658  KiCpuId(&CpuInfo, 0x80000006);
659 
660  /* Cache line size */
661  CacheLine = CpuInfo.Ecx & 0xFF;
662 
663  /* Hardcode associativity */
664  RegisterByte = (CpuInfo.Ecx >> 12) & 0xFF;
665  switch (RegisterByte)
666  {
667  case 2:
668  Associativity = 2;
669  break;
670 
671  case 4:
672  Associativity = 4;
673  break;
674 
675  case 6:
676  Associativity = 8;
677  break;
678 
679  case 8:
680  case 15:
681  Associativity = 16;
682  break;
683 
684  default:
685  Associativity = 1;
686  break;
687  }
688 
689  /* Compute size */
690  Size = (CpuInfo.Ecx >> 16) << 10;
691 
692  /* Hack for Model 6, Steping 300 */
693  if ((KeGetCurrentPrcb()->CpuType == 6) &&
694  (KeGetCurrentPrcb()->CpuStep == 0x300))
695  {
696  /* Stick 64K in there */
697  Size = 64 * 1024;
698  }
699 
700  /* Set the L2 Cache Size and associativity */
701  Pcr->SecondLevelCacheSize = Size;
702  Pcr->SecondLevelCacheAssociativity = Associativity;
703  }
704  }
705  break;
706 
707  case CPU_CYRIX:
708  case CPU_TRANSMETA:
709  case CPU_CENTAUR:
710  case CPU_RISE:
711 
712  /* FIXME */
713  break;
714  }
715 
716  /* Set the cache line */
717  if (CacheLine > KeLargestCacheLine) KeLargestCacheLine = CacheLine;
718  DPRINT1("Prefetch Cache: %lu bytes\tL2 Cache: %lu bytes\tL2 Cache Line: %lu bytes\tL2 Cache Associativity: %lu\n",
723 }
724 
725 VOID
726 NTAPI
729 {
730  ULONG Cr0;
731 
732  /* Save current CR0 */
733  Cr0 = __readcr0();
734 
735  /* If this is a 486, enable Write-Protection */
736  if (KeGetCurrentPrcb()->CpuType > 3) Cr0 |= CR0_WP;
737 
738  /* Set new Cr0 */
739  __writecr0(Cr0);
740 }
741 
742 VOID
743 NTAPI
746  IN PKGDTENTRY TssEntry OPTIONAL)
747 {
748  PUCHAR p;
749 
750  /* Make sure the GDT Entry is valid */
751  if (TssEntry)
752  {
753  /* Set the Limit */
754  TssEntry->LimitLow = sizeof(KTSS) - 1;
755  TssEntry->HighWord.Bits.LimitHi = 0;
756  }
757 
758  /* Now clear the I/O Map */
759  ASSERT(IOPM_COUNT == 1);
760  RtlFillMemory(Tss->IoMaps[0].IoMap, IOPM_FULL_SIZE, 0xFF);
761 
762  /* Initialize Interrupt Direction Maps */
763  p = (PUCHAR)(Tss->IoMaps[0].DirectionMap);
765 
766  /* Add DPMI support for interrupts */
767  p[0] = 4;
768  p[3] = 0x18;
769  p[4] = 0x18;
770 
771  /* Initialize the default Interrupt Direction Map */
772  p = Tss->IntDirectionMap;
773  RtlZeroMemory(Tss->IntDirectionMap, IOPM_DIRECTION_MAP_SIZE);
774 
775  /* Add DPMI support */
776  p[0] = 4;
777  p[3] = 0x18;
778  p[4] = 0x18;
779 }
780 
781 VOID
782 NTAPI
784 {
785  /* Set an invalid map base */
786  Tss->IoMapBase = KiComputeIopmOffset(IO_ACCESS_MAP_NONE);
787 
788  /* Disable traps during Task Switches */
789  Tss->Flags = 0;
790 
791  /* Set LDT and Ring 0 SS */
792  Tss->LDT = 0;
793  Tss->Ss0 = KGDT_R0_DATA;
794 }
795 
796 VOID
797 FASTCALL
800  IN PKIDTENTRY Idt,
801  IN PKGDTENTRY Gdt)
802 {
803  PKGDTENTRY TssEntry, TaskGateEntry;
804 
805  /* Initialize the boot TSS. */
806  TssEntry = &Gdt[KGDT_TSS / sizeof(KGDTENTRY)];
807  TssEntry->HighWord.Bits.Type = I386_TSS;
808  TssEntry->HighWord.Bits.Pres = 1;
809  TssEntry->HighWord.Bits.Dpl = 0;
810  KiInitializeTSS2(Tss, TssEntry);
811  KiInitializeTSS(Tss);
812 
813  /* Load the task register */
814  Ke386SetTr(KGDT_TSS);
815 
816  /* Setup the Task Gate for Double Fault Traps */
817  TaskGateEntry = (PKGDTENTRY)&Idt[8];
818  TaskGateEntry->HighWord.Bits.Type = I386_TASK_GATE;
819  TaskGateEntry->HighWord.Bits.Pres = 1;
820  TaskGateEntry->HighWord.Bits.Dpl = 0;
821  ((PKIDTENTRY)TaskGateEntry)->Selector = KGDT_DF_TSS;
822 
823  /* Initialize the TSS used for handling double faults. */
824  Tss = (PKTSS)KiDoubleFaultTSS;
825  KiInitializeTSS(Tss);
826  Tss->CR3 = __readcr3();
827  Tss->Esp0 = KiDoubleFaultStack;
828  Tss->Esp = KiDoubleFaultStack;
829  Tss->Eip = PtrToUlong(KiTrap08);
830  Tss->Cs = KGDT_R0_CODE;
831  Tss->Fs = KGDT_R0_PCR;
832  Tss->Ss = Ke386GetSs();
833  Tss->Es = KGDT_R3_DATA | RPL_MASK;
834  Tss->Ds = KGDT_R3_DATA | RPL_MASK;
835 
836  /* Setup the Double Trap TSS entry in the GDT */
837  TssEntry = &Gdt[KGDT_DF_TSS / sizeof(KGDTENTRY)];
838  TssEntry->HighWord.Bits.Type = I386_TSS;
839  TssEntry->HighWord.Bits.Pres = 1;
840  TssEntry->HighWord.Bits.Dpl = 0;
841  TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);
842  TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);
843  TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);
844  TssEntry->LimitLow = KTSS_IO_MAPS;
845 
846  /* Now setup the NMI Task Gate */
847  TaskGateEntry = (PKGDTENTRY)&Idt[2];
848  TaskGateEntry->HighWord.Bits.Type = I386_TASK_GATE;
849  TaskGateEntry->HighWord.Bits.Pres = 1;
850  TaskGateEntry->HighWord.Bits.Dpl = 0;
851  ((PKIDTENTRY)TaskGateEntry)->Selector = KGDT_NMI_TSS;
852 
853  /* Initialize the actual TSS */
854  Tss = (PKTSS)KiNMITSS;
855  KiInitializeTSS(Tss);
856  Tss->CR3 = __readcr3();
857  Tss->Esp0 = KiDoubleFaultStack;
858  Tss->Esp = KiDoubleFaultStack;
859  Tss->Eip = PtrToUlong(KiTrap02);
860  Tss->Cs = KGDT_R0_CODE;
861  Tss->Fs = KGDT_R0_PCR;
862  Tss->Ss = Ke386GetSs();
863  Tss->Es = KGDT_R3_DATA | RPL_MASK;
864  Tss->Ds = KGDT_R3_DATA | RPL_MASK;
865 
866  /* And its associated TSS Entry */
867  TssEntry = &Gdt[KGDT_NMI_TSS / sizeof(KGDTENTRY)];
868  TssEntry->HighWord.Bits.Type = I386_TSS;
869  TssEntry->HighWord.Bits.Pres = 1;
870  TssEntry->HighWord.Bits.Dpl = 0;
871  TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);
872  TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);
873  TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);
874  TssEntry->LimitLow = KTSS_IO_MAPS;
875 }
876 
877 VOID
878 NTAPI
880 {
881 
882 #if !defined(_GLOBAL_PAGES_ARE_AWESOME_)
883 
884  /* Flush the TLB by resetting CR3 */
886 
887 #else
888 
889  /* Check if global pages are enabled */
891  {
892  ULONG Cr4;
893 
894  /* Disable PGE (Note: may not have been enabled yet) */
895  Cr4 = __readcr4();
896  __writecr4(Cr4 & ~CR4_PGE);
897 
898  /* Flush everything */
900 
901  /* Re-enable PGE */
902  __writecr4(Cr4);
903  }
904  else
905  {
906  /* No global pages, resetting CR3 is enough */
908  }
909 
910 #endif
911 
912 }
913 
914 VOID
915 NTAPI
917 {
918  PKGDTENTRY TssEntry;
919 
920  //
921  // Restore the CR registers
922  //
923  __writecr0(ProcessorState->SpecialRegisters.Cr0);
924  Ke386SetCr2(ProcessorState->SpecialRegisters.Cr2);
925  __writecr3(ProcessorState->SpecialRegisters.Cr3);
926  if (KeFeatureBits & KF_CR4) __writecr4(ProcessorState->SpecialRegisters.Cr4);
927 
928  //
929  // Restore the DR registers
930  //
931  __writedr(0, ProcessorState->SpecialRegisters.KernelDr0);
932  __writedr(1, ProcessorState->SpecialRegisters.KernelDr1);
933  __writedr(2, ProcessorState->SpecialRegisters.KernelDr2);
934  __writedr(3, ProcessorState->SpecialRegisters.KernelDr3);
935  __writedr(6, ProcessorState->SpecialRegisters.KernelDr6);
936  __writedr(7, ProcessorState->SpecialRegisters.KernelDr7);
937 
938  //
939  // Restore GDT and IDT
940  //
941  Ke386SetGlobalDescriptorTable(&ProcessorState->SpecialRegisters.Gdtr.Limit);
942  __lidt(&ProcessorState->SpecialRegisters.Idtr.Limit);
943 
944  //
945  // Clear the busy flag so we don't crash if we reload the same selector
946  //
947  TssEntry = (PKGDTENTRY)(ProcessorState->SpecialRegisters.Gdtr.Base +
948  ProcessorState->SpecialRegisters.Tr);
949  TssEntry->HighWord.Bytes.Flags1 &= ~0x2;
950 
951  //
952  // Restore TSS and LDT
953  //
954  Ke386SetTr(ProcessorState->SpecialRegisters.Tr);
955  Ke386SetLocalDescriptorTable(ProcessorState->SpecialRegisters.Ldtr);
956 }
957 
958 VOID
959 NTAPI
961 {
962  /* Save the CR registers */
963  ProcessorState->SpecialRegisters.Cr0 = __readcr0();
964  ProcessorState->SpecialRegisters.Cr2 = __readcr2();
965  ProcessorState->SpecialRegisters.Cr3 = __readcr3();
966  ProcessorState->SpecialRegisters.Cr4 = (KeFeatureBits & KF_CR4) ?
967  __readcr4() : 0;
968 
969  /* Save the DR registers */
970  ProcessorState->SpecialRegisters.KernelDr0 = __readdr(0);
971  ProcessorState->SpecialRegisters.KernelDr1 = __readdr(1);
972  ProcessorState->SpecialRegisters.KernelDr2 = __readdr(2);
973  ProcessorState->SpecialRegisters.KernelDr3 = __readdr(3);
974  ProcessorState->SpecialRegisters.KernelDr6 = __readdr(6);
975  ProcessorState->SpecialRegisters.KernelDr7 = __readdr(7);
976  __writedr(7, 0);
977 
978  /* Save GDT, IDT, LDT and TSS */
979  Ke386GetGlobalDescriptorTable(&ProcessorState->SpecialRegisters.Gdtr.Limit);
980  __sidt(&ProcessorState->SpecialRegisters.Idtr.Limit);
981  ProcessorState->SpecialRegisters.Tr = Ke386GetTr();
982  ProcessorState->SpecialRegisters.Ldtr = Ke386GetLocalDescriptorTable();
983 }
984 
985 VOID
986 NTAPI
989 {
990  /* Set the Machine Type we got from NTLDR */
992 }
993 
994 ULONG_PTR
995 NTAPI
998 {
999  /* Set CS and ESP */
1000  __writemsr(0x174, KGDT_R0_CODE);
1001  __writemsr(0x175, (ULONG_PTR)KeGetCurrentPrcb()->DpcStack);
1002 
1003  /* Set LSTAR */
1005  return 0;
1006 }
1007 
1008 VOID
1009 NTAPI
1012 {
1013  /* Check if the CPU Supports fast system call */
1015  {
1016  /* Check if it has been disabled */
1018  {
1019  /* Disable fast system call */
1020  KeFeatureBits &= ~KF_FAST_SYSCALL;
1022  DPRINT1("Support for SYSENTER disabled.\n");
1023  }
1024  else
1025  {
1026  /* Do an IPI to enable it */
1028 
1029  /* It's enabled, so use the proper exit stub */
1031  DPRINT("Support for SYSENTER detected.\n");
1032  }
1033  }
1034  else
1035  {
1036  /* Use the IRET handler */
1038  DPRINT1("No support for SYSENTER detected.\n");
1039  }
1040 }
1041 
1042 ULONG_PTR
1043 NTAPI
1046 {
1047  /* Enable DE */
1049  return 0;
1050 }
1051 
1052 ULONG_PTR
1053 NTAPI
1056 {
1057  /* Enable FXSR */
1059  return 0;
1060 }
1061 
1062 ULONG_PTR
1063 NTAPI
1066 {
1068 
1069  /* Get the IDT Entry for Interrupt 0x13 */
1070  IdtEntry = &((PKIPCR)KeGetPcr())->IDT[0x13];
1071 
1072  /* Set it up */
1073  IdtEntry->Selector = KGDT_R0_CODE;
1074  IdtEntry->Offset = ((ULONG_PTR)KiTrap13 & 0xFFFF);
1075  IdtEntry->ExtendedOffset = ((ULONG_PTR)KiTrap13 >> 16) & 0xFFFF;
1076  ((PKIDT_ACCESS)&IdtEntry->Access)->Dpl = 0;
1077  ((PKIDT_ACCESS)&IdtEntry->Access)->Present = 1;
1078  ((PKIDT_ACCESS)&IdtEntry->Access)->SegmentType = I386_INTERRUPT_GATE;
1079 
1080  /* Enable XMMI exceptions */
1082  return 0;
1083 }
1084 
1085 VOID
1086 NTAPI
1089 {
1090  KDESCRIPTOR IdtDescriptor = {0, 0, 0};
1091  PKIDTENTRY NewIdt, NewIdt2;
1092 
1093  /* Allocate memory for a new IDT */
1094  NewIdt = ExAllocatePool(NonPagedPool, 2 * PAGE_SIZE);
1095 
1096  /* Put everything after the first 7 entries on a new page */
1097  NewIdt2 = (PVOID)((ULONG_PTR)NewIdt + PAGE_SIZE - (7 * sizeof(KIDTENTRY)));
1098 
1099  /* Disable interrupts */
1100  _disable();
1101 
1102  /* Get the current IDT and copy it */
1103  __sidt(&IdtDescriptor.Limit);
1104  RtlCopyMemory(NewIdt2,
1105  (PVOID)IdtDescriptor.Base,
1106  IdtDescriptor.Limit + 1);
1107  IdtDescriptor.Base = (ULONG)NewIdt2;
1108 
1109  /* Set the new IDT */
1110  __lidt(&IdtDescriptor.Limit);
1111  ((PKIPCR)KeGetPcr())->IDT = NewIdt2;
1112 
1113  /* Restore interrupts */
1114  _enable();
1115 
1116  /* Set the first 7 entries as read-only to produce a fault */
1118 }
1119 
1120 BOOLEAN
1121 NTAPI
1123 {
1124  /* Only supported on Pentium Pro and higher */
1125  if (KeI386CpuType < 6) return FALSE;
1126 
1127  /* Invalidate all caches */
1128  __wbinvd();
1129  return TRUE;
1130 }
1131 
1132 VOID
1133 FASTCALL
1135  IN ULONG Size)
1136 {
1137  /* Not using XMMI in this routine */
1138  RtlZeroMemory(Address, Size);
1139 }
1140 
1141 VOID
1142 NTAPI
1144  IN PKEXCEPTION_FRAME ExceptionFrame)
1145 {
1146  PKPRCB Prcb = KeGetCurrentPrcb();
1147 
1148  //
1149  // Save full context
1150  //
1154 
1155  //
1156  // Save control registers
1157  //
1159 }
1160 
1161 BOOLEAN
1162 NTAPI
1165 {
1166  ULONG Cr0;
1167  USHORT Magic;
1168 
1169  /* Set magic */
1170  Magic = 0xFFFF;
1171 
1172  /* Read CR0 and mask out FPU flags */
1173  Cr0 = __readcr0() & ~(CR0_MP | CR0_TS | CR0_EM | CR0_ET);
1174 
1175  /* Store on FPU stack */
1176 #ifdef _MSC_VER
1177  __asm fninit;
1178  __asm fnstsw Magic;
1179 #else
1180  asm volatile ("fninit;" "fnstsw %0" : "+m"(Magic));
1181 #endif
1182 
1183  /* Magic should now be cleared */
1184  if (Magic & 0xFF)
1185  {
1186  /* You don't have an FPU -- enable emulation for now */
1187  __writecr0(Cr0 | CR0_EM | CR0_TS);
1188  return FALSE;
1189  }
1190 
1191  /* You have an FPU, enable it */
1192  Cr0 |= CR0_ET;
1193 
1194  /* Enable INT 16 on 486 and higher */
1195  if (KeGetCurrentPrcb()->CpuType >= 3) Cr0 |= CR0_NE;
1196 
1197  /* Set FPU state */
1198  __writecr0(Cr0 | CR0_EM | CR0_TS);
1199  return TRUE;
1200 }
1201 
1202 BOOLEAN
1203 NTAPI
1206 {
1207  static double Value1 = 4195835.0, Value2 = 3145727.0;
1208  INT ErrataPresent;
1209  ULONG Cr0;
1210 
1211  /* Disable interrupts */
1212  _disable();
1213 
1214  /* Read CR0 and remove FPU flags */
1215  Cr0 = __readcr0();
1216  __writecr0(Cr0 & ~(CR0_MP | CR0_TS | CR0_EM));
1217 
1218  /* Initialize FPU state */
1219  Ke386FnInit();
1220 
1221  /* Multiply the magic values and divide, we should get the result back */
1222 #ifdef __GNUC__
1223  __asm__ __volatile__
1224  (
1225  "fldl %1\n\t"
1226  "fdivl %2\n\t"
1227  "fmull %2\n\t"
1228  "fldl %1\n\t"
1229  "fsubp\n\t"
1230  "fistpl %0\n\t"
1231  : "=m" (ErrataPresent)
1232  : "m" (Value1),
1233  "m" (Value2)
1234  );
1235 #else
1236  __asm
1237  {
1238  fld Value1
1239  fdiv Value2
1240  fmul Value2
1241  fld Value1
1242  fsubp st(1), st(0)
1243  fistp ErrataPresent
1244  };
1245 #endif
1246 
1247  /* Restore CR0 */
1248  __writecr0(Cr0);
1249 
1250  /* Enable interrupts */
1251  _enable();
1252 
1253  /* Return if there's an errata */
1254  return ErrataPresent != 0;
1255 }
1256 
1257 VOID
1258 NTAPI
1260 {
1261  ULONG EFlags, Cr0;
1262  PKTHREAD Thread, NpxThread;
1263  PFX_SAVE_AREA FxSaveArea;
1264 
1265  /* Save volatiles and disable interrupts */
1266  EFlags = __readeflags();
1267  _disable();
1268 
1269  /* Save the PCR and get the current thread */
1270  Thread = KeGetCurrentThread();
1271 
1272  /* Check if we're already loaded */
1273  if (Thread->NpxState != NPX_STATE_LOADED)
1274  {
1275  /* If there's nothing to load, quit */
1276  if (!SaveArea)
1277  {
1278  /* Restore interrupt state and return */
1279  __writeeflags(EFlags);
1280  return;
1281  }
1282 
1283  /* Need FXSR support for this */
1285 
1286  /* Check for sane CR0 */
1287  Cr0 = __readcr0();
1288  if (Cr0 & (CR0_MP | CR0_TS | CR0_EM))
1289  {
1290  /* Mask out FPU flags */
1291  __writecr0(Cr0 & ~(CR0_MP | CR0_TS | CR0_EM));
1292  }
1293 
1294  /* Get the NPX thread and check its FPU state */
1295  NpxThread = KeGetCurrentPrcb()->NpxThread;
1296  if ((NpxThread) && (NpxThread->NpxState == NPX_STATE_LOADED))
1297  {
1298  /* Get the FX frame and store the state there */
1299  FxSaveArea = KiGetThreadNpxArea(NpxThread);
1300  Ke386FxSave(FxSaveArea);
1301 
1302  /* NPX thread has lost its state */
1303  NpxThread->NpxState = NPX_STATE_NOT_LOADED;
1304  }
1305 
1306  /* Now load NPX state from the NPX area */
1307  FxSaveArea = KiGetThreadNpxArea(Thread);
1308  Ke386FxStore(FxSaveArea);
1309  }
1310  else
1311  {
1312  /* Check for sane CR0 */
1313  Cr0 = __readcr0();
1314  if (Cr0 & (CR0_MP | CR0_TS | CR0_EM))
1315  {
1316  /* Mask out FPU flags */
1317  __writecr0(Cr0 & ~(CR0_MP | CR0_TS | CR0_EM));
1318  }
1319 
1320  /* Get FX frame */
1321  FxSaveArea = KiGetThreadNpxArea(Thread);
1322  Thread->NpxState = NPX_STATE_NOT_LOADED;
1323 
1324  /* Save state if supported by CPU */
1325  if (KeI386FxsrPresent) Ke386FxSave(FxSaveArea);
1326  }
1327 
1328  /* Now save the FN state wherever it was requested */
1329  if (SaveArea) Ke386FnSave(SaveArea);
1330 
1331  /* Clear NPX thread */
1332  KeGetCurrentPrcb()->NpxThread = NULL;
1333 
1334  /* Add the CR0 from the NPX frame */
1335  Cr0 |= NPX_STATE_NOT_LOADED;
1336  Cr0 |= FxSaveArea->Cr0NpxState;
1337  __writecr0(Cr0);
1338 
1339  /* Restore interrupt state */
1340  __writeeflags(EFlags);
1341 }
1342 
1343 /* PUBLIC FUNCTIONS **********************************************************/
1344 
1345 /*
1346  * @implemented
1347  */
1348 VOID
1349 NTAPI
1351 {
1352  PFX_SAVE_AREA NpxArea;
1353 
1354  /* Get the FPU area */
1356 
1357  /* Set CR0_TS */
1358  NpxArea->Cr0NpxState = CR0_TS;
1360 }
1361 
1362 /*
1363  * @implemented
1364  */
1365 NTSTATUS
1366 NTAPI
1368 {
1369  PFNSAVE_FORMAT FpState;
1371  DPRINT1("%s is not really implemented\n", __FUNCTION__);
1372 
1373  /* check if we are doing software emulation */
1375 
1376  FpState = ExAllocatePool(NonPagedPool, sizeof (FNSAVE_FORMAT));
1377  if (!FpState) return STATUS_INSUFFICIENT_RESOURCES;
1378 
1379  *((PVOID *) Save) = FpState;
1380 #ifdef __GNUC__
1381  asm volatile("fnsave %0\n\t" : "=m" (*FpState));
1382 #else
1383  __asm
1384  {
1385  mov eax, [FpState]
1386  fnsave [eax]
1387  };
1388 #endif
1389 
1390  KeGetCurrentThread()->Header.NpxIrql = KeGetCurrentIrql();
1391  return STATUS_SUCCESS;
1392 }
1393 
1394 /*
1395  * @implemented
1396  */
1397 NTSTATUS
1398 NTAPI
1400 {
1401  PFNSAVE_FORMAT FpState = *((PVOID *) Save);
1403  DPRINT1("%s is not really implemented\n", __FUNCTION__);
1404 
1405 #ifdef __GNUC__
1406  asm volatile("fnclex\n\t");
1407  asm volatile("frstor %0\n\t" : "=m" (*FpState));
1408 #else
1409  __asm
1410  {
1411  fnclex
1412  mov eax, [FpState]
1413  frstor [eax]
1414  };
1415 #endif
1416 
1417  ExFreePool(FpState);
1418  return STATUS_SUCCESS;
1419 }
1420 
1421 /*
1422  * @implemented
1423  */
1424 ULONG
1425 NTAPI
1427 {
1428  /* Return the global variable */
1429  return KeLargestCacheLine;
1430 }
1431 
1432 VOID
1433 NTAPI
1435  IN PVOID Ignored1,
1436  IN PVOID Ignored2,
1437  IN PVOID Ignored3)
1438 {
1439  /* Signal this packet as done */
1440  KiIpiSignalPacketDone(PacketContext);
1441 
1442  /* Flush the TB for the Current CPU */
1443  KeFlushCurrentTb();
1444 }
1445 
1446 /*
1447  * @implemented
1448  */
1449 VOID
1450 NTAPI
1452  IN BOOLEAN AllProcessors)
1453 {
1454  KIRQL OldIrql;
1455 #ifdef CONFIG_SMP
1456  KAFFINITY TargetAffinity;
1457  PKPRCB Prcb = KeGetCurrentPrcb();
1458 #endif
1459 
1460  /* Raise the IRQL for the TB Flush */
1461  OldIrql = KeRaiseIrqlToSynchLevel();
1462 
1463 #ifdef CONFIG_SMP
1464  /* FIXME: Use KiTbFlushTimeStamp to synchronize TB flush */
1465 
1466  /* Get the current processor affinity, and exclude ourselves */
1467  TargetAffinity = KeActiveProcessors;
1468  TargetAffinity &= ~Prcb->SetMember;
1469 
1470  /* Make sure this is MP */
1471  if (TargetAffinity)
1472  {
1473  /* Send an IPI TB flush to the other processors */
1474  KiIpiSendPacket(TargetAffinity,
1476  NULL,
1477  0,
1478  NULL);
1479  }
1480 #endif
1481 
1482  /* Flush the TB for the Current CPU, and update the flush stamp */
1483  KeFlushCurrentTb();
1484 
1485 #ifdef CONFIG_SMP
1486  /* If this is MP, wait for the other processors to finish */
1487  if (TargetAffinity)
1488  {
1489  /* Sanity check */
1490  ASSERT(Prcb == KeGetCurrentPrcb());
1491 
1492  /* FIXME: TODO */
1493  ASSERTMSG("Not yet implemented\n", FALSE);
1494  }
1495 #endif
1496 
1497  /* Update the flush stamp and return to original IRQL */
1499  KeLowerIrql(OldIrql);
1500 }
1501 
1502 /*
1503  * @implemented
1504  */
1505 VOID
1506 NTAPI
1508 {
1509  /* Save the coherency globally */
1510  KiDmaIoCoherency = Coherency;
1511 }
1512 
1513 /*
1514  * @implemented
1515  */
1516 KAFFINITY
1517 NTAPI
1519 {
1520  PAGED_CODE();
1521 
1522  /* Simply return the number of active processors */
1523  return KeActiveProcessors;
1524 }
1525 
1526 /*
1527  * @implemented
1528  */
1529 VOID
1530 __cdecl
1532 {
1533  /* Capture the context */
1534  RtlCaptureContext(&State->ContextFrame);
1535 
1536  /* Capture the control state */
1538 }
#define CR0_MP
Definition: asm.h:246
DWORD *typedef PVOID
Definition: winlogon.h:52
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
VOID NTAPI KiFlushNPXState(IN PFLOATING_SAVE_AREA SaveArea)
Definition: cpu.c:1259
ULONG KeI386NpxPresent
Definition: cpu.c:31
__INTRIN_INLINE void __writecr4(unsigned int Data)
Definition: intrin_x86.h:1577
#define IN
Definition: typedefs.h:39
__INTRIN_INLINE void __writedr(unsigned reg, unsigned int value)
Definition: intrin_x86.h:1725
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
VOID NTAPI KiGetCacheInformation(VOID)
Definition: cpu.c:224
PVOID ULONG Address
Definition: oprghdlr.h:14
VOID NTAPI KiSaveProcessorControlState(OUT PKPROCESSOR_STATE ProcessorState)
Definition: cpu.c:382
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
static const CHAR CmpIntelID[]
Definition: cpu.c:56
#define PKGDTENTRY
Definition: ketypes.h:438
Type
Definition: Type.h:6
__INTRIN_INLINE unsigned long __readcr2(void)
Definition: intrin_x86.h:1594
#define KTSS
Definition: ketypes.h:920
ULONG Ke386NoExecute
Definition: cpu.c:34
UCHAR LogicalProcessorsPerPhysicalProcessor
Definition: ketypes.h:703
#define __cdecl
Definition: accygwin.h:79
VOID NTAPI INIT_FUNCTION KiSetCR0Bits(VOID)
Definition: cpu.c:728
union _LOADER_PARAMETER_BLOCK::@3075 u
static const CHAR CmpRiseID[]
Definition: cpu.c:61
#define KF_CMPXCHG8B
Definition: ketypes.h:150
ULONG64 KernelDr7
Definition: ketypes.h:505
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
#define I386_TASK_GATE
Definition: ketypes.h:59
USHORT BaseLow
Definition: ketypes.h:334
VOID NTAPI KiCoprocessorError(VOID)
Definition: cpu.c:1350
return STATUS_SUCCESS
Definition: btrfs.c:2664
UCHAR SecondLevelCacheAssociativity
Definition: ketypes.h:872
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
UCHAR NTAPI READ_PORT_UCHAR(PUCHAR Address)
Definition: mach.c:535
void __cdecl _enable(void)
Definition: intrin_arm.h:373
VOID NTAPI KiSetProcessorType(VOID)
Definition: cpu.c:55
#define KF_RDTSC
Definition: ketypes.h:144
#define EFLAGS_ID
Definition: cpu.c:20
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1054
struct _KIPCR * PKIPCR
#define CR4_FXSR
Definition: ketypes.h:92
#define CR0_TS
Definition: asm.h:248
static const CHAR CmpAmdID[]
Definition: cpu.c:57
#define KF_MMX
Definition: ketypes.h:151
UCHAR VendorString[13]
Definition: ketypes.h:797
DECLSPEC_NORETURN VOID __cdecl KiTrap02(VOID)
Definition: traphdlr.c:461
#define KGDT_R0_CODE
Definition: ketypes.h:74
ULONG64 KernelDr2
Definition: ketypes.h:502
static const CHAR CmpTransmetaID[]
Definition: cpu.c:59
__INTRIN_INLINE void __lidt(void *Source)
Definition: intrin_x86.h:1808
ULONG KeFeatureBits
Definition: krnlinit.c:22
#define CONTEXT_FULL
Definition: compat.h:270
struct _KGDTENTRY::@2183::@2184 Bytes
KSPECIAL_REGISTERS SpecialRegisters
Definition: ketypes.h:530
__INTRIN_INLINE unsigned long __readcr3(void)
Definition: intrin_x86.h:1601
#define KF_NX_BIT
Definition: ketypes.h:165
PVOID PKIPI_CONTEXT
Definition: ketypes.h:558
static const CHAR CmpCentaurID[]
Definition: cpu.c:60
USHORT Access
Definition: ketypes.h:386
static const CHAR CmpCyrixID[]
Definition: cpu.c:58
UCHAR KiSystemCallExitAdjusted
Definition: cpu.c:47
NTSYSAPI VOID NTAPI RtlCaptureContext(_Out_ PCONTEXT ContextRecord)
ULONG64 KernelDr1
Definition: ketypes.h:501
#define FASTCALL
Definition: nt_native.h:50
__asm__("\t.globl GetPhys\n""GetPhys:\t\n""mflr 0\n\t""stwu 0,-16(1)\n\t""mfmsr 5\n\t""andi. 6,5,0xffef\n\t""mtmsr 6\n\t""isync\n\t""sync\n\t""lwz 3,0(3)\n\t""mtmsr 5\n\t""isync\n\t""sync\n\t""lwz 0,0(1)\n\t""addi 1,1,16\n\t""mtlr 0\n\t""blr")
#define IOPM_DIRECTION_MAP_SIZE
Definition: ketypes.h:180
#define KGDTENTRY
Definition: ketypes.h:437
#define NPX_STATE_NOT_LOADED
Definition: asm.h:262
int32_t INT
Definition: typedefs.h:57
PVOID Base
Definition: ketypes.h:486
VOID FASTCALL INIT_FUNCTION Ki386InitializeTss(IN PKTSS Tss, IN PKIDTENTRY Idt, IN PKGDTENTRY Gdt)
Definition: cpu.c:799
ULONG KeIcacheFlushCount
Definition: cpu.c:19
#define KeGetPcr()
Definition: ke.h:25
#define CR0_NE
Definition: asm.h:250
ULONG NTAPI KeGetRecommendedSharedDataAlignment(VOID)
Definition: cpu.c:481
USHORT Limit
Definition: ketypes.h:485
VOID NTAPI INIT_FUNCTION KiInitializeTSS2(IN PKTSS Tss, IN PKGDTENTRY TssEntry OPTIONAL)
Definition: cpu.c:745
uint32_t ULONG_PTR
Definition: typedefs.h:64
ULONG NTAPI KiGetCpuVendor(VOID)
Definition: cpu.c:95
#define CR4_PGE
Definition: ketypes.h:91
#define KF_LARGE_PAGE
Definition: ketypes.h:148
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define KF_AMDK6MTRR
Definition: ketypes.h:158
ULONG KeI386CpuType
Definition: cpu.c:28
LARGE_INTEGER UpdateSignature
Definition: ketypes.h:800
#define KGDT_NMI_TSS
Definition: ketypes.h:83
__INTRIN_INLINE void __writecr3(unsigned int Data)
Definition: intrin_x86.h:1572
ULONG KeI386FxsrPresent
Definition: cpu.c:31
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#define KGDT_DF_TSS
Definition: ketypes.h:82
struct _KGDTENTRY::@2183::@2185 Bits
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1456
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
VOID NTAPI KeFlushCurrentTb(VOID)
Definition: cpu.c:332
#define FALSE
Definition: types.h:117
Definition: Header.h:8
#define KF_PAT
Definition: ketypes.h:153
#define KF_XMMI
Definition: ketypes.h:156
long LONG
Definition: pedump.c:60
__INTRIN_INLINE void __sidt(void *Destination)
Definition: intrin_x86.h:1813
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
union _KGDTENTRY::@2183 HighWord
CONTEXT ContextFrame
Definition: ketypes.h:531
static __inline UCHAR getCx86(UCHAR reg)
Definition: cpu.c:71
volatile LONG KiTbFlushTimeStamp
Definition: cpu.c:41
#define RPL_MASK
Definition: ketypes.h:69
I386_LOADER_BLOCK I386
Definition: arc.h:515
ULONG SecondLevelCacheSize
Definition: ketypes.h:881
USHORT CpuStep
Definition: ketypes.h:585
smooth NULL
Definition: ftsmooth.c:513
VOID NTAPI KiInitializeTSS(IN PKTSS Tss)
Definition: cpu.c:783
NTSTATUS NTAPI KeRestoreFloatingPointState(IN PKFLOATING_SAVE Save)
Definition: cpu.c:1399
__INTRIN_INLINE void __writecr0(unsigned int Data)
Definition: intrin_x86.h:1567
PPC_QUAL unsigned long long __readmsr()
Definition: intrin_ppc.h:741
Definition: ketypes.h:787
void DPRINT(...)
Definition: polytest.cpp:61
ULONG Cr0NpxState
Definition: ketypes.h:449
#define KGDT_R3_DATA
Definition: ketypes.h:77
ULONG KeI386XMMIPresent
Definition: cpu.c:30
Definition: hooks.h:42
VOID NTAPI KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame, IN OUT PCONTEXT Context)
Definition: context.c:146
static __inline void setCx86(UCHAR reg, UCHAR data)
Definition: cpu.c:79
ULONG KiDmaIoCoherency
Definition: cpu.c:33
ULONG Eax
Definition: ketypes.h:296
PLOADER_PARAMETER_BLOCK KeLoaderBlock
Definition: krnlinit.c:29
#define InterlockedExchangeAdd
Definition: interlocked.h:181
UCHAR KiDoubleFaultTSS[KTSS_IO_MAPS]
Definition: cpu.c:18
VOID NTAPI KeFlushEntireTb(IN BOOLEAN Invalid, IN BOOLEAN AllProcessors)
Definition: cpu.c:423
ULONG ContextFlags
Definition: compat.h:331
Definition: utils.h:177
#define PtrToUlong(p)
Definition: basetsd.h:82
#define print_supported(kf_value)
VOID NTAPI INIT_FUNCTION KiRestoreFastSyscallReturnState(VOID)
Definition: cpu.c:1011
UINTN Size
Definition: acefiex.h:555
FORCEINLINE PFX_SAVE_AREA KiGetThreadNpxArea(IN PKTHREAD Thread)
Definition: ke.h:582
#define CR4_DE
Definition: ketypes.h:87
ULONG KiFastSystemCallDisable
Definition: cpu.c:26
#define IO_ACCESS_MAP_NONE
Definition: ketypes.h:263
VOID NTAPI KiSaveProcessorState(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
Definition: cpu.c:1143
unsigned char BOOLEAN
ULONG MachineType
Definition: arc.h:407
#define KF_CR4
Definition: ketypes.h:145
KDESCRIPTOR Gdtr
Definition: ketypes.h:506
ULONG KePrefetchNTAGranularity
Definition: cpu.c:39
#define CR4_XMMEXCPT
Definition: ketypes.h:93
ULONG KeI386MachineType
Definition: cpu.c:30
#define KGDT_TSS
Definition: ketypes.h:78
BOOLEAN NTAPI KeInvalidateAllCaches(VOID)
Definition: cpu.c:469
UCHAR KiNMITSS[KTSS_IO_MAPS]
Definition: cpu.c:21
BOOLEAN NTAPI INIT_FUNCTION KiIsNpxPresent(VOID)
Definition: cpu.c:1164
ecx edi ebx edx edi decl ecx esi eax jecxz decl eax andl eax esi movl eax
Definition: synth_sse3d.h:85
if(!(yy_init))
Definition: macro.lex.yy.c:704
VOID __cdecl KeSaveStateForHibernate(IN PKPROCESSOR_STATE State)
Definition: cpu.c:492
#define KGDT_R0_DATA
Definition: ketypes.h:75
KAFFINITY NTAPI KeQueryActiveProcessors(VOID)
Definition: cpu.c:443
ULONG Ebx
Definition: ketypes.h:297
struct _KIDT_ACCESS * PKIDT_ACCESS
#define KF_MTRR
Definition: ketypes.h:149
ULONG Ecx
Definition: ketypes.h:298
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define KF_WORKING_PTE
Definition: ketypes.h:152
ULONG_PTR NTAPI INIT_FUNCTION Ki386EnableDE(IN ULONG_PTR Context)
Definition: cpu.c:1045
VOID NTAPI MmSetPageProtect(struct _EPROCESS *Process, PVOID Address, ULONG flProtect)
ULONG NTAPI KiGetFeatureBits(VOID)
Definition: cpu.c:135
#define KF_FAST_SYSCALL
Definition: ketypes.h:155
#define PAGED_CODE()
Definition: video.h:57
ULONG_PTR NTAPI INIT_FUNCTION KiLoadFastSyscallMachineSpecificRegisters(IN ULONG_PTR Context)
Definition: cpu.c:997
#define KF_V86_VIS
Definition: ketypes.h:143
USHORT Offset
Definition: ketypes.h:384
#define KF_FXSR
Definition: ketypes.h:154
PPC_QUAL void __wbinvd(void)
Definition: intrin_ppc.h:759
DECLSPEC_NORETURN VOID FASTCALL KiSystemCallSysExitReturn(IN PKTRAP_FRAME TrapFrame)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
#define KF_3DNOW
Definition: ketypes.h:157
#define KGDT_R0_PCR
Definition: ketypes.h:79
KPROCESSOR_STATE ProcessorState
Definition: ketypes.h:579
USHORT ExtendedOffset
Definition: ketypes.h:387
#define PKTSS
Definition: ketypes.h:921
#define STATUS_ILLEGAL_FLOAT_CONTEXT
Definition: ntstatus.h:552
unsigned char UCHAR
Definition: xmlstorage.h:181
BOOLEAN KiFastCallCopyDoneOnce
Definition: cpu.c:50
VOID __cdecl KiTrap13(VOID)
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
VOID NTAPI KiRestoreProcessorControlState(PKPROCESSOR_STATE ProcessorState)
Definition: cpu.c:340
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1451
#define ExAllocatePool(type, size)
Definition: fbtusb.h:44
#define PKIDTENTRY
Definition: ketypes.h:480
#define KF_NX_DISABLED
Definition: ketypes.h:166
#define PAGE_SIZE
Definition: env_spec_w32.h:49
__INTRIN_INLINE unsigned int __readdr(unsigned int reg)
Definition: intrin_x86.h:1692
__INTRIN_INLINE unsigned long __readcr0(void)
Definition: intrin_x86.h:1587
UCHAR NpxState
Definition: ketypes.h:998
#define IOPM_COUNT
Definition: ketypes.h:176
__INTRIN_INLINE unsigned long __readcr4(void)
Definition: intrin_x86.h:1608
VOID FASTCALL KiIpiSignalPacketDone(IN PKIPI_CONTEXT PacketContext)
Definition: ipi.c:55
ULONG_PTR NTAPI INIT_FUNCTION Ki386EnableXMMIExceptions(IN ULONG_PTR Context)
Definition: cpu.c:1065
KAFFINITY KeActiveProcessors
Definition: krnlinit.c:23
NTSTATUS NTAPI KeSaveFloatingPointState(OUT PKFLOATING_SAVE Save)
Definition: cpu.c:1367
ULONG_PTR KiDoubleFaultStack
Definition: kiinit.c:37
UCHAR KiSystemCallExitAdjust
Definition: cpu.c:44
PPC_QUAL void __writemsr(const unsigned long Value)
Definition: intrin_ppc.h:748
UINT64 SetMember
Definition: ketypes.h:578
static PUCHAR
Definition: cpu.c:25
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
UINT32 AsUINT32[4]
Definition: ketypes.h:293
#define CR0_ET
Definition: asm.h:249
ULONG64 KernelDr3
Definition: ketypes.h:503
#define KF_XMMI64
Definition: ketypes.h:159
LONG NTSTATUS
Definition: DriverTester.h:11
VOID __cdecl KiTrap08(VOID)
ULONG KeDcacheFlushCount
Definition: cpu.c:20
#define I386_INTERRUPT_GATE
Definition: ketypes.h:63
unsigned short USHORT
Definition: pedump.c:61
#define KIDTENTRY
Definition: ketypes.h:479
BOOLEAN NTAPI INIT_FUNCTION KiIsNpxErrataPresent(VOID)
Definition: cpu.c:1205
VOID NTAPI KeSetDmaIoCoherency(IN ULONG Coherency)
Definition: cpu.c:506
ULONG_PTR KAFFINITY
Definition: compat.h:75
VOID NTAPI INIT_FUNCTION KiInitializeMachineType(VOID)
Definition: cpu.c:988
#define KiComputeIopmOffset(MapNumber)
Definition: ketypes.h:265
VOID FASTCALL KeZeroPages(IN PVOID Address, IN ULONG Size)
Definition: cpu.c:56
#define PAGE_READONLY
Definition: compat.h:127
static int reg
Definition: i386-dis.c:1275
#define CX86_CCR1
Definition: cpu.c:66
#define KTSS_IO_MAPS
Definition: asm.h:81
ULONG KeI386CpuStep
Definition: cpu.c:29
#define I386_TSS
Definition: ketypes.h:60
#define DPRINT1
Definition: precomp.h:8
ULONG MxcsrFeatureMask
Definition: cpu.c:29
#define OUT
Definition: typedefs.h:40
void __cdecl _disable(void)
Definition: intrin_arm.h:365
unsigned int ULONG
Definition: retypes.h:1
ULONG64 KernelDr6
Definition: ketypes.h:504
ULONG Ke386Pae
Definition: cpu.c:33
ULONG KeLargestCacheLine
Definition: cpu.c:32
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value)
Definition: mach.c:539
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
VOID __cdecl KiFastCallEntry(VOID)
VOID NTAPI KiIpiSendPacket(IN KAFFINITY TargetProcessors, IN PKIPI_WORKER WorkerFunction, IN PKIPI_BROADCAST_WORKER BroadcastFunction, IN ULONG_PTR Context, IN PULONG Count)
Definition: ipi.c:43
#define ULONG_PTR
Definition: config.h:101
#define NPX_STATE_LOADED
Definition: asm.h:263
ULONG_PTR NTAPI INIT_FUNCTION Ki386EnableFxsr(IN ULONG_PTR Context)
Definition: cpu.c:1055
#define KF_DTS
Definition: ketypes.h:160
#define __FUNCTION__
Definition: compiler.h:205
#define IOPM_FULL_SIZE
Definition: ketypes.h:178
#define KF_GLOBAL_PAGE
Definition: ketypes.h:147
GLfloat GLfloat p
Definition: glext.h:8902
USHORT LimitLow
Definition: ketypes.h:333
#define KeGetCurrentThread
Definition: hal.h:44
ULONG Edx
Definition: ketypes.h:299
CHAR CpuID
Definition: ketypes.h:581
#define KF_NX_ENABLED
Definition: ketypes.h:167
BOOLEAN KiSMTProcessorsPresent
Definition: cpu.c:34
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
#define KF_CMOV
Definition: ketypes.h:146
USHORT Selector
Definition: ketypes.h:385
ULONG KiMXCsrMask
Definition: cpu.c:28
ULONG64 KernelDr0
Definition: ketypes.h:500
IN HDEVINFO IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
Definition: devinst.c:44
VOID NTAPI KiFlushTargetEntireTb(IN PKIPI_CONTEXT PacketContext, IN PVOID Ignored1, IN PVOID Ignored2, IN PVOID Ignored3)
Definition: cpu.c:1434
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define CONTEXT_DEBUG_REGISTERS
Definition: compat.h:268
#define CR0_WP
Definition: asm.h:251
ULONG_PTR NTAPI KeIpiGenericCall(IN PKIPI_BROADCAST_WORKER Function, IN ULONG_PTR Argument)
Definition: ipi.c:196
#define CR0_EM
Definition: asm.h:247
LONGLONG QuadPart
Definition: typedefs.h:113
DECLSPEC_NORETURN VOID FASTCALL KiSystemCallTrapReturn(IN PKTRAP_FRAME TrapFrame)
KDESCRIPTOR Idtr
Definition: ketypes.h:507
ULONG InitialApicId
Definition: ketypes.h:617
VOID NTAPI INIT_FUNCTION KiI386PentiumLockErrataFixup(VOID)
Definition: cpu.c:1088
#define INIT_FUNCTION
Definition: ntoskrnl.h:11
BOOLEAN KiI386PentiumLockErrataPresent
Definition: cpu.c:40
PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler
Definition: traphdlr.c:56
CHAR CpuType
Definition: ketypes.h:580
KIRQL NTAPI KeRaiseIrqlToSynchLevel(VOID)
Definition: pic.c:156