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