ReactOS  0.4.15-dev-3287-gfec35dc
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 {
74  return READ_PORT_UCHAR((PUCHAR)(ULONG_PTR)0x23);
75 }
76 
77 static __inline
78 void
80 {
83 }
84 
85 
86 /* FUNCTIONS *****************************************************************/
87 
88 CODE_SEG("INIT")
89 VOID
90 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 CODE_SEG("INIT")
156 ULONG
157 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 CODE_SEG("INIT")
212 ULONG
213 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  if (CpuFeatures & 0x00000040)
384  {
385  DPRINT1("Support PAE\n");
386  }
387 
388  /* Check if the CPU has hyper-threading */
389  if (CpuFeatures & 0x10000000)
390  {
391  /* Set the number of logical CPUs */
392  Prcb->LogicalProcessorsPerPhysicalProcessor = (UCHAR)(CpuInfo.Ebx >> 16);
394  {
395  /* We're on dual-core */
397  }
398  }
399  else
400  {
401  /* We only have a single CPU */
403  }
404 
405  /* Check if CPUID 0x80000000 is supported */
406  if (ExtendedCPUID)
407  {
408  /* Do the call */
409  KiCpuId(&CpuInfo, 0x80000000);
410  if ((CpuInfo.Eax & 0xffffff00) == 0x80000000)
411  {
412  /* Check if CPUID 0x80000001 is supported */
413  if (CpuInfo.Eax >= 0x80000001)
414  {
415  /* Check which extended features are available. */
416  KiCpuId(&CpuInfo, 0x80000001);
417 
418  /* Check if NX-bit is supported */
419  if (CpuInfo.Edx & 0x00100000) FeatureBits |= KF_NX_BIT;
420 
421  /* Now handle each features for each CPU Vendor */
422  switch (Vendor)
423  {
424  case CPU_AMD:
425  case CPU_CENTAUR:
426  if (CpuInfo.Edx & 0x80000000) FeatureBits |= KF_3DNOW;
427  break;
428  }
429  }
430  }
431  }
432 
433 #define print_supported(kf_value) ((FeatureBits & kf_value) ? #kf_value : "")
434  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",
456 #undef print_supported
457 
458  /* Return the Feature Bits */
459  return FeatureBits;
460 }
461 
462 CODE_SEG("INIT")
463 VOID
464 NTAPI
466 {
467  PKIPCR Pcr = (PKIPCR)KeGetPcr();
468  ULONG Vendor;
469  CPU_INFO CpuInfo;
470  ULONG CacheRequests = 0, i;
471  ULONG CurrentRegister;
472  UCHAR RegisterByte, Associativity = 0;
473  ULONG Size, CacheLine = 64, CurrentSize = 0;
474  BOOLEAN FirstPass = TRUE;
475 
476  /* Set default L2 size */
477  Pcr->SecondLevelCacheSize = 0;
478 
479  /* Get the Vendor ID and make sure we support CPUID */
480  Vendor = KiGetCpuVendor();
481  if (!Vendor) return;
482 
483  /* Check the Vendor ID */
484  switch (Vendor)
485  {
486  /* Handle Intel case */
487  case CPU_INTEL:
488 
489  /*Check if we support CPUID 2 */
490  KiCpuId(&CpuInfo, 0);
491  if (CpuInfo.Eax >= 2)
492  {
493  /* We need to loop for the number of times CPUID will tell us to */
494  do
495  {
496  /* Do the CPUID call */
497  KiCpuId(&CpuInfo, 2);
498 
499  /* Check if it was the first call */
500  if (FirstPass)
501  {
502  /*
503  * The number of times to loop is the first byte. Read
504  * it and then destroy it so we don't get confused.
505  */
506  CacheRequests = CpuInfo.Eax & 0xFF;
507  CpuInfo.Eax &= 0xFFFFFF00;
508 
509  /* Don't go over this again */
510  FirstPass = FALSE;
511  }
512 
513  /* Loop all 4 registers */
514  for (i = 0; i < 4; i++)
515  {
516  /* Get the current register */
517  CurrentRegister = CpuInfo.AsUINT32[i];
518 
519  /*
520  * If the upper bit is set, then this register should
521  * be skipped.
522  */
523  if (CurrentRegister & 0x80000000) continue;
524 
525  /* Keep looping for every byte inside this register */
526  while (CurrentRegister)
527  {
528  /* Read a byte, skip a byte. */
529  RegisterByte = (UCHAR)(CurrentRegister & 0xFF);
530  CurrentRegister >>= 8;
531  if (!RegisterByte) continue;
532 
533  Size = 0;
534  switch (RegisterByte)
535  {
536  case 0x06:
537  case 0x08:
539  break;
540  case 0x09:
542  break;
543  case 0x0a:
544  case 0x0c:
546  break;
547  case 0x0d:
548  case 0x0e:
550  break;
551  case 0x1d:
552  Size = 128 * 1024;
553  Associativity = 2;
554  break;
555  case 0x21:
556  Size = 256 * 1024;
557  Associativity = 8;
558  break;
559  case 0x24:
560  Size = 1024 * 1024;
561  Associativity = 16;
562  break;
563  case 0x2c:
564  case 0x30:
566  break;
567  case 0x41:
568  case 0x42:
569  case 0x43:
570  case 0x44:
571  case 0x45:
572  Size = (1 << (RegisterByte - 0x41)) * 128 * 1024;
573  Associativity = 4;
574  break;
575  case 0x48:
576  Size = 3 * 1024 * 1024;
577  Associativity = 12;
578  break;
579  case 0x49:
580  Size = 4 * 1024 * 1024;
581  Associativity = 16;
582  break;
583  case 0x4e:
584  Size = 6 * 1024 * 1024;
585  Associativity = 24;
586  break;
587  case 0x60:
588  case 0x66:
589  case 0x67:
590  case 0x68:
592  break;
593  case 0x78:
594  Size = 1024 * 1024;
595  Associativity = 4;
596  break;
597  case 0x79:
598  case 0x7a:
599  case 0x7b:
600  case 0x7c:
601  case 0x7d:
602  Size = (1 << (RegisterByte - 0x79)) * 128 * 1024;
603  Associativity = 8;
604  break;
605  case 0x7f:
606  Size = 512 * 1024;
607  Associativity = 2;
608  break;
609  case 0x80:
610  Size = 512 * 1024;
611  Associativity = 8;
612  break;
613  case 0x82:
614  case 0x83:
615  case 0x84:
616  case 0x85:
617  Size = (1 << (RegisterByte - 0x82)) * 256 * 1024;
618  Associativity = 8;
619  break;
620  case 0x86:
621  Size = 512 * 1024;
622  Associativity = 4;
623  break;
624  case 0x87:
625  Size = 1024 * 1024;
626  Associativity = 8;
627  break;
628  case 0xf0:
630  break;
631  case 0xf1:
633  break;
634  }
635  if (Size && (Size / Associativity) > CurrentSize)
636  {
637  /* Set the L2 Cache Size and Associativity */
638  CurrentSize = Size / Associativity;
639  Pcr->SecondLevelCacheSize = Size;
640  Pcr->SecondLevelCacheAssociativity = Associativity;
641  }
642  }
643  }
644  } while (--CacheRequests);
645  }
646  break;
647 
648  case CPU_AMD:
649 
650  /* Check if we support CPUID 0x80000005 */
651  KiCpuId(&CpuInfo, 0x80000000);
652  if (CpuInfo.Eax >= 0x80000005)
653  {
654  /* Get L1 size first */
655  KiCpuId(&CpuInfo, 0x80000005);
656  KePrefetchNTAGranularity = CpuInfo.Ecx & 0xFF;
657 
658  /* Check if we support CPUID 0x80000006 */
659  KiCpuId(&CpuInfo, 0x80000000);
660  if (CpuInfo.Eax >= 0x80000006)
661  {
662  /* Get 2nd level cache and tlb size */
663  KiCpuId(&CpuInfo, 0x80000006);
664 
665  /* Cache line size */
666  CacheLine = CpuInfo.Ecx & 0xFF;
667 
668  /* Hardcode associativity */
669  RegisterByte = (CpuInfo.Ecx >> 12) & 0xFF;
670  switch (RegisterByte)
671  {
672  case 2:
673  Associativity = 2;
674  break;
675 
676  case 4:
677  Associativity = 4;
678  break;
679 
680  case 6:
681  Associativity = 8;
682  break;
683 
684  case 8:
685  case 15:
686  Associativity = 16;
687  break;
688 
689  default:
690  Associativity = 1;
691  break;
692  }
693 
694  /* Compute size */
695  Size = (CpuInfo.Ecx >> 16) << 10;
696 
697  /* Hack for Model 6, Steping 300 */
698  if ((KeGetCurrentPrcb()->CpuType == 6) &&
699  (KeGetCurrentPrcb()->CpuStep == 0x300))
700  {
701  /* Stick 64K in there */
702  Size = 64 * 1024;
703  }
704 
705  /* Set the L2 Cache Size and associativity */
706  Pcr->SecondLevelCacheSize = Size;
707  Pcr->SecondLevelCacheAssociativity = Associativity;
708  }
709  }
710  break;
711 
712  case CPU_CYRIX:
713  case CPU_TRANSMETA:
714  case CPU_CENTAUR:
715  case CPU_RISE:
716 
717  /* FIXME */
718  break;
719  }
720 
721  /* Set the cache line */
722  if (CacheLine > KeLargestCacheLine) KeLargestCacheLine = CacheLine;
723  DPRINT1("Prefetch Cache: %lu bytes\tL2 Cache: %lu bytes\tL2 Cache Line: %lu bytes\tL2 Cache Associativity: %lu\n",
728 }
729 
730 CODE_SEG("INIT")
731 VOID
732 NTAPI
734 {
735  ULONG Cr0;
736 
737  /* Save current CR0 */
738  Cr0 = __readcr0();
739 
740  /* If this is a 486, enable Write-Protection */
741  if (KeGetCurrentPrcb()->CpuType > 3) Cr0 |= CR0_WP;
742 
743  /* Set new Cr0 */
744  __writecr0(Cr0);
745 }
746 
747 CODE_SEG("INIT")
748 VOID
749 NTAPI
751  IN PKGDTENTRY TssEntry OPTIONAL)
752 {
753  PUCHAR p;
754 
755  /* Make sure the GDT Entry is valid */
756  if (TssEntry)
757  {
758  /* Set the Limit */
759  TssEntry->LimitLow = sizeof(KTSS) - 1;
760  TssEntry->HighWord.Bits.LimitHi = 0;
761  }
762 
763  /* Now clear the I/O Map */
764  ASSERT(IOPM_COUNT == 1);
765  RtlFillMemory(Tss->IoMaps[0].IoMap, IOPM_FULL_SIZE, 0xFF);
766 
767  /* Initialize Interrupt Direction Maps */
768  p = (PUCHAR)(Tss->IoMaps[0].DirectionMap);
770 
771  /* Add DPMI support for interrupts */
772  p[0] = 4;
773  p[3] = 0x18;
774  p[4] = 0x18;
775 
776  /* Initialize the default Interrupt Direction Map */
777  p = Tss->IntDirectionMap;
778  RtlZeroMemory(Tss->IntDirectionMap, IOPM_DIRECTION_MAP_SIZE);
779 
780  /* Add DPMI support */
781  p[0] = 4;
782  p[3] = 0x18;
783  p[4] = 0x18;
784 }
785 
786 VOID
787 NTAPI
789 {
790  /* Set an invalid map base */
791  Tss->IoMapBase = KiComputeIopmOffset(IO_ACCESS_MAP_NONE);
792 
793  /* Disable traps during Task Switches */
794  Tss->Flags = 0;
795 
796  /* Set LDT and Ring 0 SS */
797  Tss->LDT = 0;
798  Tss->Ss0 = KGDT_R0_DATA;
799 }
800 
801 CODE_SEG("INIT")
802 VOID
803 FASTCALL
805  IN PKIDTENTRY Idt,
806  IN PKGDTENTRY Gdt)
807 {
808  PKGDTENTRY TssEntry, TaskGateEntry;
809 
810  /* Initialize the boot TSS. */
811  TssEntry = &Gdt[KGDT_TSS / sizeof(KGDTENTRY)];
812  TssEntry->HighWord.Bits.Type = I386_TSS;
813  TssEntry->HighWord.Bits.Pres = 1;
814  TssEntry->HighWord.Bits.Dpl = 0;
815  KiInitializeTSS2(Tss, TssEntry);
816  KiInitializeTSS(Tss);
817 
818  /* Load the task register */
819  Ke386SetTr(KGDT_TSS);
820 
821  /* Setup the Task Gate for Double Fault Traps */
822  TaskGateEntry = (PKGDTENTRY)&Idt[8];
823  TaskGateEntry->HighWord.Bits.Type = I386_TASK_GATE;
824  TaskGateEntry->HighWord.Bits.Pres = 1;
825  TaskGateEntry->HighWord.Bits.Dpl = 0;
826  ((PKIDTENTRY)TaskGateEntry)->Selector = KGDT_DF_TSS;
827 
828  /* Initialize the TSS used for handling double faults. */
829  Tss = (PKTSS)KiDoubleFaultTSS;
830  KiInitializeTSS(Tss);
831  Tss->CR3 = __readcr3();
832  Tss->Esp0 = KiDoubleFaultStack;
833  Tss->Esp = KiDoubleFaultStack;
834  Tss->Eip = PtrToUlong(KiTrap08);
835  Tss->Cs = KGDT_R0_CODE;
836  Tss->Fs = KGDT_R0_PCR;
837  Tss->Ss = Ke386GetSs();
838  Tss->Es = KGDT_R3_DATA | RPL_MASK;
839  Tss->Ds = KGDT_R3_DATA | RPL_MASK;
840 
841  /* Setup the Double Trap TSS entry in the GDT */
842  TssEntry = &Gdt[KGDT_DF_TSS / sizeof(KGDTENTRY)];
843  TssEntry->HighWord.Bits.Type = I386_TSS;
844  TssEntry->HighWord.Bits.Pres = 1;
845  TssEntry->HighWord.Bits.Dpl = 0;
846  TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);
847  TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);
848  TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);
849  TssEntry->LimitLow = KTSS_IO_MAPS;
850 
851  /* Now setup the NMI Task Gate */
852  TaskGateEntry = (PKGDTENTRY)&Idt[2];
853  TaskGateEntry->HighWord.Bits.Type = I386_TASK_GATE;
854  TaskGateEntry->HighWord.Bits.Pres = 1;
855  TaskGateEntry->HighWord.Bits.Dpl = 0;
856  ((PKIDTENTRY)TaskGateEntry)->Selector = KGDT_NMI_TSS;
857 
858  /* Initialize the actual TSS */
859  Tss = (PKTSS)KiNMITSS;
860  KiInitializeTSS(Tss);
861  Tss->CR3 = __readcr3();
862  Tss->Esp0 = KiDoubleFaultStack;
863  Tss->Esp = KiDoubleFaultStack;
864  Tss->Eip = PtrToUlong(KiTrap02);
865  Tss->Cs = KGDT_R0_CODE;
866  Tss->Fs = KGDT_R0_PCR;
867  Tss->Ss = Ke386GetSs();
868  Tss->Es = KGDT_R3_DATA | RPL_MASK;
869  Tss->Ds = KGDT_R3_DATA | RPL_MASK;
870 
871  /* And its associated TSS Entry */
872  TssEntry = &Gdt[KGDT_NMI_TSS / sizeof(KGDTENTRY)];
873  TssEntry->HighWord.Bits.Type = I386_TSS;
874  TssEntry->HighWord.Bits.Pres = 1;
875  TssEntry->HighWord.Bits.Dpl = 0;
876  TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);
877  TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);
878  TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);
879  TssEntry->LimitLow = KTSS_IO_MAPS;
880 }
881 
882 VOID
883 NTAPI
885 {
886 
887 #if !defined(_GLOBAL_PAGES_ARE_AWESOME_)
888 
889  /* Flush the TLB by resetting CR3 */
891 
892 #else
893 
894  /* Check if global pages are enabled */
896  {
897  ULONG Cr4;
898 
899  /* Disable PGE (Note: may not have been enabled yet) */
900  Cr4 = __readcr4();
901  __writecr4(Cr4 & ~CR4_PGE);
902 
903  /* Flush everything */
905 
906  /* Re-enable PGE */
907  __writecr4(Cr4);
908  }
909  else
910  {
911  /* No global pages, resetting CR3 is enough */
913  }
914 
915 #endif
916 
917 }
918 
919 VOID
920 NTAPI
922 {
923  PKGDTENTRY TssEntry;
924 
925  //
926  // Restore the CR registers
927  //
928  __writecr0(ProcessorState->SpecialRegisters.Cr0);
929  Ke386SetCr2(ProcessorState->SpecialRegisters.Cr2);
930  __writecr3(ProcessorState->SpecialRegisters.Cr3);
931  if (KeFeatureBits & KF_CR4) __writecr4(ProcessorState->SpecialRegisters.Cr4);
932 
933  //
934  // Restore the DR registers
935  //
936  __writedr(0, ProcessorState->SpecialRegisters.KernelDr0);
937  __writedr(1, ProcessorState->SpecialRegisters.KernelDr1);
938  __writedr(2, ProcessorState->SpecialRegisters.KernelDr2);
939  __writedr(3, ProcessorState->SpecialRegisters.KernelDr3);
940  __writedr(6, ProcessorState->SpecialRegisters.KernelDr6);
941  __writedr(7, ProcessorState->SpecialRegisters.KernelDr7);
942 
943  //
944  // Restore GDT and IDT
945  //
947  __lidt(&ProcessorState->SpecialRegisters.Idtr.Limit);
948 
949  //
950  // Clear the busy flag so we don't crash if we reload the same selector
951  //
952  TssEntry = (PKGDTENTRY)(ProcessorState->SpecialRegisters.Gdtr.Base +
953  ProcessorState->SpecialRegisters.Tr);
954  TssEntry->HighWord.Bytes.Flags1 &= ~0x2;
955 
956  //
957  // Restore TSS and LDT
958  //
959  Ke386SetTr(ProcessorState->SpecialRegisters.Tr);
960  Ke386SetLocalDescriptorTable(ProcessorState->SpecialRegisters.Ldtr);
961 }
962 
963 VOID
964 NTAPI
966 {
967  /* Save the CR registers */
968  ProcessorState->SpecialRegisters.Cr0 = __readcr0();
969  ProcessorState->SpecialRegisters.Cr2 = __readcr2();
970  ProcessorState->SpecialRegisters.Cr3 = __readcr3();
971  ProcessorState->SpecialRegisters.Cr4 = (KeFeatureBits & KF_CR4) ?
972  __readcr4() : 0;
973 
974  /* Save the DR registers */
975  ProcessorState->SpecialRegisters.KernelDr0 = __readdr(0);
976  ProcessorState->SpecialRegisters.KernelDr1 = __readdr(1);
977  ProcessorState->SpecialRegisters.KernelDr2 = __readdr(2);
978  ProcessorState->SpecialRegisters.KernelDr3 = __readdr(3);
979  ProcessorState->SpecialRegisters.KernelDr6 = __readdr(6);
980  ProcessorState->SpecialRegisters.KernelDr7 = __readdr(7);
981  __writedr(7, 0);
982 
983  /* Save GDT, IDT, LDT and TSS */
984  Ke386GetGlobalDescriptorTable(&ProcessorState->SpecialRegisters.Gdtr.Limit);
985  __sidt(&ProcessorState->SpecialRegisters.Idtr.Limit);
986  ProcessorState->SpecialRegisters.Tr = Ke386GetTr();
987  Ke386GetLocalDescriptorTable(&ProcessorState->SpecialRegisters.Ldtr);
988 }
989 
990 CODE_SEG("INIT")
991 VOID
992 NTAPI
994 {
995  /* Set the Machine Type we got from NTLDR */
997 }
998 
999 CODE_SEG("INIT")
1000 ULONG_PTR
1001 NTAPI
1003 {
1004  /* Set CS and ESP */
1005  __writemsr(0x174, KGDT_R0_CODE);
1006  __writemsr(0x175, (ULONG_PTR)KeGetCurrentPrcb()->DpcStack);
1007 
1008  /* Set LSTAR */
1010  return 0;
1011 }
1012 
1013 CODE_SEG("INIT")
1014 VOID
1015 NTAPI
1017 {
1018  /* Check if the CPU Supports fast system call */
1020  {
1021  /* Check if it has been disabled */
1023  {
1024  /* Disable fast system call */
1027  DPRINT1("Support for SYSENTER disabled.\n");
1028  }
1029  else
1030  {
1031  /* Do an IPI to enable it */
1033 
1034  /* It's enabled, so use the proper exit stub */
1036  DPRINT("Support for SYSENTER detected.\n");
1037  }
1038  }
1039  else
1040  {
1041  /* Use the IRET handler */
1043  DPRINT1("No support for SYSENTER detected.\n");
1044  }
1045 }
1046 
1047 CODE_SEG("INIT")
1048 ULONG_PTR
1049 NTAPI
1051 {
1052  /* Enable DE */
1054  return 0;
1055 }
1056 
1057 CODE_SEG("INIT")
1058 ULONG_PTR
1059 NTAPI
1061 {
1062  /* Enable FXSR */
1064  return 0;
1065 }
1066 
1067 CODE_SEG("INIT")
1068 ULONG_PTR
1069 NTAPI
1071 {
1073 
1074  /* Get the IDT Entry for Interrupt 0x13 */
1075  IdtEntry = &((PKIPCR)KeGetPcr())->IDT[0x13];
1076 
1077  /* Set it up */
1078  IdtEntry->Selector = KGDT_R0_CODE;
1079  IdtEntry->Offset = ((ULONG_PTR)KiTrap13 & 0xFFFF);
1080  IdtEntry->ExtendedOffset = ((ULONG_PTR)KiTrap13 >> 16) & 0xFFFF;
1081  ((PKIDT_ACCESS)&IdtEntry->Access)->Dpl = 0;
1082  ((PKIDT_ACCESS)&IdtEntry->Access)->Present = 1;
1083  ((PKIDT_ACCESS)&IdtEntry->Access)->SegmentType = I386_INTERRUPT_GATE;
1084 
1085  /* Enable XMMI exceptions */
1087  return 0;
1088 }
1089 
1090 CODE_SEG("INIT")
1091 VOID
1092 NTAPI
1094 {
1095  KDESCRIPTOR IdtDescriptor = {0, 0, 0};
1096  PKIDTENTRY NewIdt, NewIdt2;
1097  PMMPTE PointerPte;
1098 
1099  /* Allocate memory for a new IDT */
1100  NewIdt = ExAllocatePool(NonPagedPool, 2 * PAGE_SIZE);
1101 
1102  /* Put everything after the first 7 entries on a new page */
1103  NewIdt2 = (PVOID)((ULONG_PTR)NewIdt + PAGE_SIZE - (7 * sizeof(KIDTENTRY)));
1104 
1105  /* Disable interrupts */
1106  _disable();
1107 
1108  /* Get the current IDT and copy it */
1109  __sidt(&IdtDescriptor.Limit);
1110  RtlCopyMemory(NewIdt2,
1111  (PVOID)IdtDescriptor.Base,
1112  IdtDescriptor.Limit + 1);
1113  IdtDescriptor.Base = (ULONG)NewIdt2;
1114 
1115  /* Set the new IDT */
1116  __lidt(&IdtDescriptor.Limit);
1117  ((PKIPCR)KeGetPcr())->IDT = NewIdt2;
1118 
1119  /* Restore interrupts */
1120  _enable();
1121 
1122  /* Set the first 7 entries as read-only to produce a fault */
1123  PointerPte = MiAddressToPte(NewIdt);
1124  ASSERT(PointerPte->u.Hard.Write == 1);
1125  PointerPte->u.Hard.Write = 0;
1126  KeInvalidateTlbEntry(NewIdt);
1127 }
1128 
1129 BOOLEAN
1130 NTAPI
1132 {
1133  /* Only supported on Pentium Pro and higher */
1134  if (KeI386CpuType < 6) return FALSE;
1135 
1136  /* Invalidate all caches */
1137  __wbinvd();
1138  return TRUE;
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 CODE_SEG("INIT")
1162 BOOLEAN
1163 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 CODE_SEG("INIT")
1203 BOOLEAN
1204 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 */
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;
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);
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 */
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 */
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 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:1259
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:204
VOID NTAPI KiSaveProcessorControlState(OUT PKPROCESSOR_STATE ProcessorState)
Definition: cpu.c:362
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
static const CHAR CmpIntelID[]
Definition: cpu.c:56
#define PKGDTENTRY
Definition: ketypes.h:442
#define CR0_NE
Definition: asm.h:250
__INTRIN_INLINE unsigned long __readcr2(void)
Definition: intrin_x86.h:1812
#define KTSS
Definition: ketypes.h:924
ULONG Ke386NoExecute
Definition: cpu.c:34
UCHAR LogicalProcessorsPerPhysicalProcessor
Definition: ketypes.h:705
#define __cdecl
Definition: accygwin.h:79
ULONG Edx
Definition: ketypes.h:303
BOOLEAN NTAPI KiIsNpxPresent(VOID)
Definition: cpu.c:1164
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:509
#define TRUE
Definition: types.h:120
#define I386_TASK_GATE
Definition: ketypes.h:59
USHORT BaseLow
Definition: ketypes.h:336
VOID NTAPI KiCoprocessorError(VOID)
Definition: cpu.c:1350
UCHAR SecondLevelCacheAssociativity
Definition: ketypes.h:876
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
void __cdecl _enable(void)
Definition: intrin_arm.h:373
VOID NTAPI KiSetProcessorType(VOID)
Definition: cpu.c:45
#define KF_RDTSC
Definition: ketypes.h:144
LONG NTSTATUS
Definition: precomp.h:26
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1079
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:804
static const CHAR CmpAmdID[]
Definition: cpu.c:57
#define KF_MMX
Definition: ketypes.h:151
UCHAR VendorString[13]
Definition: ketypes.h:801
#define KGDT_R0_CODE
Definition: ketypes.h:75
ULONG64 KernelDr2
Definition: ketypes.h:506
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:534
__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:301
UCHAR KiSystemCallExitAdjusted
Definition: cpu.c:47
NTSYSAPI VOID NTAPI RtlCaptureContext(_Out_ PCONTEXT ContextRecord)
ULONG64 KernelDr1
Definition: ketypes.h:505
#define FASTCALL
Definition: nt_native.h:50
#define IOPM_DIRECTION_MAP_SIZE
Definition: ketypes.h:182
#define KGDTENTRY
Definition: ketypes.h:441
int32_t INT
Definition: typedefs.h:58
PVOID Base
Definition: ketypes.h:490
VOID NTAPI KiInitializeMachineType(VOID)
Definition: cpu.c:993
ULONG KeIcacheFlushCount
Definition: cpu.c:19
#define KeGetPcr()
Definition: ke.h:26
struct _KGDTENTRY::@2371::@2372 Bytes
ULONG NTAPI KeGetRecommendedSharedDataAlignment(VOID)
Definition: cpu.c:461
USHORT Limit
Definition: ketypes.h:489
uint32_t ULONG_PTR
Definition: typedefs.h:65
ULONG NTAPI KiGetCpuVendor(VOID)
Definition: cpu.c:75
#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:804
#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:312
#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:1016
__INTRIN_INLINE void __sidt(void *Destination)
Definition: intrin_x86.h:2024
#define ASSERTMSG(msg, exp)
Definition: nt_native.h:431
#define CR0_ET
Definition: asm.h:249
#define Ke386GetGlobalDescriptorTable
Definition: intrin_i.h:328
CONTEXT ContextFrame
Definition: ketypes.h:535
static __inline UCHAR getCx86(UCHAR reg)
Definition: cpu.c:71
volatile LONG KiTbFlushTimeStamp
Definition: cpu.c:31
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:885
USHORT CpuStep
Definition: ketypes.h:589
VOID NTAPI KiInitializeTSS(IN PKTSS Tss)
Definition: cpu.c:788
NTSTATUS NTAPI KeRestoreFloatingPointState(IN PKFLOATING_SAVE Save)
Definition: cpu.c:1399
__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:750
PPC_QUAL unsigned long long __readmsr()
Definition: intrin_ppc.h:741
#define NPX_STATE_LOADED
Definition: asm.h:265
Definition: ketypes.h:789
#define EFLAGS_ID
Definition: ketypes.h:136
struct _KGDTENTRY::@2371::@2373 Bits
ULONG Cr0NpxState
Definition: ketypes.h:451
#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:79
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
union _KGDTENTRY::@2371 HighWord
UCHAR KiDoubleFaultTSS[KTSS_IO_MAPS]
Definition: cpu.c:18
VOID NTAPI KeFlushEntireTb(IN BOOLEAN Invalid, IN BOOLEAN AllProcessors)
Definition: cpu.c:403
#define PtrToUlong(u)
Definition: config.h:107
ULONG_PTR NTAPI Ki386EnableXMMIExceptions(IN ULONG_PTR Context)
Definition: cpu.c:1070
ULONG ContextFlags
Definition: nt_native.h:1426
Definition: utils.h:177
#define print_supported(kf_value)
KIRQL OldIrql
Definition: mm.h:1502
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:2000
#define IO_ACCESS_MAP_NONE
Definition: ketypes.h:267
VOID NTAPI KiSaveProcessorState(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
Definition: cpu.c:1143
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:510
#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:449
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:472
#define KGDT_R0_DATA
Definition: ketypes.h:76
KAFFINITY NTAPI KeQueryActiveProcessors(VOID)
Definition: cpu.c:423
#define RtlFillMemory(Dest, Length, Fill)
Definition: winternl.h:593
ULONG_PTR NTAPI Ki386EnableDE(IN ULONG_PTR Context)
Definition: cpu.c:1050
union _LOADER_PARAMETER_BLOCK::@3290 u
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
union _MMPTE::@2275 u
ULONG NTAPI KiGetFeatureBits(VOID)
Definition: cpu.c:115
#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:583
#define PKTSS
Definition: ketypes.h:925
#define STATUS_ILLEGAL_FLOAT_CONTEXT
Definition: ntstatus.h:566
unsigned char UCHAR
Definition: xmlstorage.h:181
BOOLEAN KiFastCallCopyDoneOnce
Definition: cpu.c:50
VOID __cdecl KiTrap13(VOID)
#define WRITE_PORT_UCHAR(p, d)
Definition: pc98vid.h:21
VOID NTAPI KiRestoreProcessorControlState(PKPROCESSOR_STATE ProcessorState)
Definition: cpu.c:320
__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:302
#define CONTEXT_DEBUG_REGISTERS
Definition: nt_native.h:1373
UINT32 AsUINT32[4]
Definition: ketypes.h:297
#define PKIDTENTRY
Definition: ketypes.h:484
#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:178
__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
NTSTATUS NTAPI KeSaveFloatingPointState(OUT PKFLOATING_SAVE Save)
Definition: cpu.c:1367
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:582
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
MMPTE_HARDWARE Hard
Definition: mmtypes.h:217
ULONG64 KernelDr3
Definition: ketypes.h:507
#define KF_XMMI64
Definition: ketypes.h:159
ULONG_PTR NTAPI Ki386EnableFxsr(IN ULONG_PTR Context)
Definition: cpu.c:1060
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:483
VOID NTAPI KeSetDmaIoCoherency(IN ULONG Coherency)
Definition: cpu.c:486
ULONG_PTR KAFFINITY
Definition: compat.h:85
#define KiComputeIopmOffset(MapNumber)
Definition: ketypes.h:269
#define CR0_TS
Definition: asm.h:248
VOID NTAPI KiSetCR0Bits(VOID)
Definition: cpu.c:733
BOOLEAN NTAPI KiIsNpxErrataPresent(VOID)
Definition: cpu.c:1205
#define NULL
Definition: types.h:112
#define CX86_CCR1
Definition: cpu.c:66
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:1093
#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:1002
void __cdecl _disable(void)
Definition: intrin_arm.h:365
unsigned int ULONG
Definition: retypes.h:1
ULONG64 KernelDr6
Definition: ketypes.h:508
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
#define Ke386GetLocalDescriptorTable
Definition: intrin_i.h:330
#define STATUS_SUCCESS
Definition: shellext.h:65
#define IOPM_FULL_SIZE
Definition: ketypes.h:180
#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:335
#define KeGetCurrentThread
Definition: hal.h:55
CHAR CpuID
Definition: ketypes.h:585
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
#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:504
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
ULONG_PTR NTAPI KeIpiGenericCall(IN PKIPI_BROADCAST_WORKER Function, IN ULONG_PTR Argument)
Definition: ipi.c:196
LONGLONG QuadPart
Definition: typedefs.h:114
DECLSPEC_NORETURN VOID FASTCALL KiSystemCallTrapReturn(IN PKTRAP_FRAME TrapFrame)
KDESCRIPTOR Idtr
Definition: ketypes.h:511
ULONG InitialApicId
Definition: ketypes.h:621
ULONG Eax
Definition: ketypes.h:300
BOOLEAN KiI386PentiumLockErrataPresent
Definition: cpu.c:40
#define PAGED_CODE()
PFAST_SYSTEM_CALL_EXIT KiFastCallExitHandler
Definition: traphdlr.c:56
CHAR CpuType
Definition: ketypes.h:584
KIRQL NTAPI KeRaiseIrqlToSynchLevel(VOID)
Definition: pic.c:156
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68