ReactOS  0.4.15-dev-2945-g7100a24
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  /* Check if the CPU has hyper-threading */
384  if (CpuFeatures & 0x10000000)
385  {
386  /* Set the number of logical CPUs */
387  Prcb->LogicalProcessorsPerPhysicalProcessor = (UCHAR)(CpuInfo.Ebx >> 16);
389  {
390  /* We're on dual-core */
392  }
393  }
394  else
395  {
396  /* We only have a single CPU */
398  }
399 
400  /* Check if CPUID 0x80000000 is supported */
401  if (ExtendedCPUID)
402  {
403  /* Do the call */
404  KiCpuId(&CpuInfo, 0x80000000);
405  if ((CpuInfo.Eax & 0xffffff00) == 0x80000000)
406  {
407  /* Check if CPUID 0x80000001 is supported */
408  if (CpuInfo.Eax >= 0x80000001)
409  {
410  /* Check which extended features are available. */
411  KiCpuId(&CpuInfo, 0x80000001);
412 
413  /* Check if NX-bit is supported */
414  if (CpuInfo.Edx & 0x00100000) FeatureBits |= KF_NX_BIT;
415 
416  /* Now handle each features for each CPU Vendor */
417  switch (Vendor)
418  {
419  case CPU_AMD:
420  case CPU_CENTAUR:
421  if (CpuInfo.Edx & 0x80000000) FeatureBits |= KF_3DNOW;
422  break;
423  }
424  }
425  }
426  }
427 
428 #define print_supported(kf_value) ((FeatureBits & kf_value) ? #kf_value : "")
429  DPRINT1("Supported CPU features : %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n",
451 #undef print_supported
452 
453  /* Return the Feature Bits */
454  return FeatureBits;
455 }
456 
457 CODE_SEG("INIT")
458 VOID
459 NTAPI
461 {
462  PKIPCR Pcr = (PKIPCR)KeGetPcr();
463  ULONG Vendor;
464  CPU_INFO CpuInfo;
465  ULONG CacheRequests = 0, i;
466  ULONG CurrentRegister;
467  UCHAR RegisterByte, Associativity = 0;
468  ULONG Size, CacheLine = 64, CurrentSize = 0;
469  BOOLEAN FirstPass = TRUE;
470 
471  /* Set default L2 size */
472  Pcr->SecondLevelCacheSize = 0;
473 
474  /* Get the Vendor ID and make sure we support CPUID */
475  Vendor = KiGetCpuVendor();
476  if (!Vendor) return;
477 
478  /* Check the Vendor ID */
479  switch (Vendor)
480  {
481  /* Handle Intel case */
482  case CPU_INTEL:
483 
484  /*Check if we support CPUID 2 */
485  KiCpuId(&CpuInfo, 0);
486  if (CpuInfo.Eax >= 2)
487  {
488  /* We need to loop for the number of times CPUID will tell us to */
489  do
490  {
491  /* Do the CPUID call */
492  KiCpuId(&CpuInfo, 2);
493 
494  /* Check if it was the first call */
495  if (FirstPass)
496  {
497  /*
498  * The number of times to loop is the first byte. Read
499  * it and then destroy it so we don't get confused.
500  */
501  CacheRequests = CpuInfo.Eax & 0xFF;
502  CpuInfo.Eax &= 0xFFFFFF00;
503 
504  /* Don't go over this again */
505  FirstPass = FALSE;
506  }
507 
508  /* Loop all 4 registers */
509  for (i = 0; i < 4; i++)
510  {
511  /* Get the current register */
512  CurrentRegister = CpuInfo.AsUINT32[i];
513 
514  /*
515  * If the upper bit is set, then this register should
516  * be skipped.
517  */
518  if (CurrentRegister & 0x80000000) continue;
519 
520  /* Keep looping for every byte inside this register */
521  while (CurrentRegister)
522  {
523  /* Read a byte, skip a byte. */
524  RegisterByte = (UCHAR)(CurrentRegister & 0xFF);
525  CurrentRegister >>= 8;
526  if (!RegisterByte) continue;
527 
528  Size = 0;
529  switch (RegisterByte)
530  {
531  case 0x06:
532  case 0x08:
534  break;
535  case 0x09:
537  break;
538  case 0x0a:
539  case 0x0c:
541  break;
542  case 0x0d:
543  case 0x0e:
545  break;
546  case 0x1d:
547  Size = 128 * 1024;
548  Associativity = 2;
549  break;
550  case 0x21:
551  Size = 256 * 1024;
552  Associativity = 8;
553  break;
554  case 0x24:
555  Size = 1024 * 1024;
556  Associativity = 16;
557  break;
558  case 0x2c:
559  case 0x30:
561  break;
562  case 0x41:
563  case 0x42:
564  case 0x43:
565  case 0x44:
566  case 0x45:
567  Size = (1 << (RegisterByte - 0x41)) * 128 * 1024;
568  Associativity = 4;
569  break;
570  case 0x48:
571  Size = 3 * 1024 * 1024;
572  Associativity = 12;
573  break;
574  case 0x49:
575  Size = 4 * 1024 * 1024;
576  Associativity = 16;
577  break;
578  case 0x4e:
579  Size = 6 * 1024 * 1024;
580  Associativity = 24;
581  break;
582  case 0x60:
583  case 0x66:
584  case 0x67:
585  case 0x68:
587  break;
588  case 0x78:
589  Size = 1024 * 1024;
590  Associativity = 4;
591  break;
592  case 0x79:
593  case 0x7a:
594  case 0x7b:
595  case 0x7c:
596  case 0x7d:
597  Size = (1 << (RegisterByte - 0x79)) * 128 * 1024;
598  Associativity = 8;
599  break;
600  case 0x7f:
601  Size = 512 * 1024;
602  Associativity = 2;
603  break;
604  case 0x80:
605  Size = 512 * 1024;
606  Associativity = 8;
607  break;
608  case 0x82:
609  case 0x83:
610  case 0x84:
611  case 0x85:
612  Size = (1 << (RegisterByte - 0x82)) * 256 * 1024;
613  Associativity = 8;
614  break;
615  case 0x86:
616  Size = 512 * 1024;
617  Associativity = 4;
618  break;
619  case 0x87:
620  Size = 1024 * 1024;
621  Associativity = 8;
622  break;
623  case 0xf0:
625  break;
626  case 0xf1:
628  break;
629  }
630  if (Size && (Size / Associativity) > CurrentSize)
631  {
632  /* Set the L2 Cache Size and Associativity */
633  CurrentSize = Size / Associativity;
634  Pcr->SecondLevelCacheSize = Size;
635  Pcr->SecondLevelCacheAssociativity = Associativity;
636  }
637  }
638  }
639  } while (--CacheRequests);
640  }
641  break;
642 
643  case CPU_AMD:
644 
645  /* Check if we support CPUID 0x80000005 */
646  KiCpuId(&CpuInfo, 0x80000000);
647  if (CpuInfo.Eax >= 0x80000005)
648  {
649  /* Get L1 size first */
650  KiCpuId(&CpuInfo, 0x80000005);
651  KePrefetchNTAGranularity = CpuInfo.Ecx & 0xFF;
652 
653  /* Check if we support CPUID 0x80000006 */
654  KiCpuId(&CpuInfo, 0x80000000);
655  if (CpuInfo.Eax >= 0x80000006)
656  {
657  /* Get 2nd level cache and tlb size */
658  KiCpuId(&CpuInfo, 0x80000006);
659 
660  /* Cache line size */
661  CacheLine = CpuInfo.Ecx & 0xFF;
662 
663  /* Hardcode associativity */
664  RegisterByte = (CpuInfo.Ecx >> 12) & 0xFF;
665  switch (RegisterByte)
666  {
667  case 2:
668  Associativity = 2;
669  break;
670 
671  case 4:
672  Associativity = 4;
673  break;
674 
675  case 6:
676  Associativity = 8;
677  break;
678 
679  case 8:
680  case 15:
681  Associativity = 16;
682  break;
683 
684  default:
685  Associativity = 1;
686  break;
687  }
688 
689  /* Compute size */
690  Size = (CpuInfo.Ecx >> 16) << 10;
691 
692  /* Hack for Model 6, Steping 300 */
693  if ((KeGetCurrentPrcb()->CpuType == 6) &&
694  (KeGetCurrentPrcb()->CpuStep == 0x300))
695  {
696  /* Stick 64K in there */
697  Size = 64 * 1024;
698  }
699 
700  /* Set the L2 Cache Size and associativity */
701  Pcr->SecondLevelCacheSize = Size;
702  Pcr->SecondLevelCacheAssociativity = Associativity;
703  }
704  }
705  break;
706 
707  case CPU_CYRIX:
708  case CPU_TRANSMETA:
709  case CPU_CENTAUR:
710  case CPU_RISE:
711 
712  /* FIXME */
713  break;
714  }
715 
716  /* Set the cache line */
717  if (CacheLine > KeLargestCacheLine) KeLargestCacheLine = CacheLine;
718  DPRINT1("Prefetch Cache: %lu bytes\tL2 Cache: %lu bytes\tL2 Cache Line: %lu bytes\tL2 Cache Associativity: %lu\n",
723 }
724 
725 CODE_SEG("INIT")
726 VOID
727 NTAPI
729 {
730  ULONG Cr0;
731 
732  /* Save current CR0 */
733  Cr0 = __readcr0();
734 
735  /* If this is a 486, enable Write-Protection */
736  if (KeGetCurrentPrcb()->CpuType > 3) Cr0 |= CR0_WP;
737 
738  /* Set new Cr0 */
739  __writecr0(Cr0);
740 }
741 
742 CODE_SEG("INIT")
743 VOID
744 NTAPI
746  IN PKGDTENTRY TssEntry OPTIONAL)
747 {
748  PUCHAR p;
749 
750  /* Make sure the GDT Entry is valid */
751  if (TssEntry)
752  {
753  /* Set the Limit */
754  TssEntry->LimitLow = sizeof(KTSS) - 1;
755  TssEntry->HighWord.Bits.LimitHi = 0;
756  }
757 
758  /* Now clear the I/O Map */
759  ASSERT(IOPM_COUNT == 1);
760  RtlFillMemory(Tss->IoMaps[0].IoMap, IOPM_FULL_SIZE, 0xFF);
761 
762  /* Initialize Interrupt Direction Maps */
763  p = (PUCHAR)(Tss->IoMaps[0].DirectionMap);
765 
766  /* Add DPMI support for interrupts */
767  p[0] = 4;
768  p[3] = 0x18;
769  p[4] = 0x18;
770 
771  /* Initialize the default Interrupt Direction Map */
772  p = Tss->IntDirectionMap;
773  RtlZeroMemory(Tss->IntDirectionMap, IOPM_DIRECTION_MAP_SIZE);
774 
775  /* Add DPMI support */
776  p[0] = 4;
777  p[3] = 0x18;
778  p[4] = 0x18;
779 }
780 
781 VOID
782 NTAPI
784 {
785  /* Set an invalid map base */
786  Tss->IoMapBase = KiComputeIopmOffset(IO_ACCESS_MAP_NONE);
787 
788  /* Disable traps during Task Switches */
789  Tss->Flags = 0;
790 
791  /* Set LDT and Ring 0 SS */
792  Tss->LDT = 0;
793  Tss->Ss0 = KGDT_R0_DATA;
794 }
795 
796 CODE_SEG("INIT")
797 VOID
798 FASTCALL
800  IN PKIDTENTRY Idt,
801  IN PKGDTENTRY Gdt)
802 {
803  PKGDTENTRY TssEntry, TaskGateEntry;
804 
805  /* Initialize the boot TSS. */
806  TssEntry = &Gdt[KGDT_TSS / sizeof(KGDTENTRY)];
807  TssEntry->HighWord.Bits.Type = I386_TSS;
808  TssEntry->HighWord.Bits.Pres = 1;
809  TssEntry->HighWord.Bits.Dpl = 0;
810  KiInitializeTSS2(Tss, TssEntry);
811  KiInitializeTSS(Tss);
812 
813  /* Load the task register */
814  Ke386SetTr(KGDT_TSS);
815 
816  /* Setup the Task Gate for Double Fault Traps */
817  TaskGateEntry = (PKGDTENTRY)&Idt[8];
818  TaskGateEntry->HighWord.Bits.Type = I386_TASK_GATE;
819  TaskGateEntry->HighWord.Bits.Pres = 1;
820  TaskGateEntry->HighWord.Bits.Dpl = 0;
821  ((PKIDTENTRY)TaskGateEntry)->Selector = KGDT_DF_TSS;
822 
823  /* Initialize the TSS used for handling double faults. */
824  Tss = (PKTSS)KiDoubleFaultTSS;
825  KiInitializeTSS(Tss);
826  Tss->CR3 = __readcr3();
827  Tss->Esp0 = KiDoubleFaultStack;
828  Tss->Esp = KiDoubleFaultStack;
829  Tss->Eip = PtrToUlong(KiTrap08);
830  Tss->Cs = KGDT_R0_CODE;
831  Tss->Fs = KGDT_R0_PCR;
832  Tss->Ss = Ke386GetSs();
833  Tss->Es = KGDT_R3_DATA | RPL_MASK;
834  Tss->Ds = KGDT_R3_DATA | RPL_MASK;
835 
836  /* Setup the Double Trap TSS entry in the GDT */
837  TssEntry = &Gdt[KGDT_DF_TSS / sizeof(KGDTENTRY)];
838  TssEntry->HighWord.Bits.Type = I386_TSS;
839  TssEntry->HighWord.Bits.Pres = 1;
840  TssEntry->HighWord.Bits.Dpl = 0;
841  TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);
842  TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);
843  TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);
844  TssEntry->LimitLow = KTSS_IO_MAPS;
845 
846  /* Now setup the NMI Task Gate */
847  TaskGateEntry = (PKGDTENTRY)&Idt[2];
848  TaskGateEntry->HighWord.Bits.Type = I386_TASK_GATE;
849  TaskGateEntry->HighWord.Bits.Pres = 1;
850  TaskGateEntry->HighWord.Bits.Dpl = 0;
851  ((PKIDTENTRY)TaskGateEntry)->Selector = KGDT_NMI_TSS;
852 
853  /* Initialize the actual TSS */
854  Tss = (PKTSS)KiNMITSS;
855  KiInitializeTSS(Tss);
856  Tss->CR3 = __readcr3();
857  Tss->Esp0 = KiDoubleFaultStack;
858  Tss->Esp = KiDoubleFaultStack;
859  Tss->Eip = PtrToUlong(KiTrap02);
860  Tss->Cs = KGDT_R0_CODE;
861  Tss->Fs = KGDT_R0_PCR;
862  Tss->Ss = Ke386GetSs();
863  Tss->Es = KGDT_R3_DATA | RPL_MASK;
864  Tss->Ds = KGDT_R3_DATA | RPL_MASK;
865 
866  /* And its associated TSS Entry */
867  TssEntry = &Gdt[KGDT_NMI_TSS / sizeof(KGDTENTRY)];
868  TssEntry->HighWord.Bits.Type = I386_TSS;
869  TssEntry->HighWord.Bits.Pres = 1;
870  TssEntry->HighWord.Bits.Dpl = 0;
871  TssEntry->BaseLow = (USHORT)((ULONG_PTR)Tss & 0xFFFF);
872  TssEntry->HighWord.Bytes.BaseMid = (UCHAR)((ULONG_PTR)Tss >> 16);
873  TssEntry->HighWord.Bytes.BaseHi = (UCHAR)((ULONG_PTR)Tss >> 24);
874  TssEntry->LimitLow = KTSS_IO_MAPS;
875 }
876 
877 VOID
878 NTAPI
880 {
881 
882 #if !defined(_GLOBAL_PAGES_ARE_AWESOME_)
883 
884  /* Flush the TLB by resetting CR3 */
886 
887 #else
888 
889  /* Check if global pages are enabled */
891  {
892  ULONG Cr4;
893 
894  /* Disable PGE (Note: may not have been enabled yet) */
895  Cr4 = __readcr4();
896  __writecr4(Cr4 & ~CR4_PGE);
897 
898  /* Flush everything */
900 
901  /* Re-enable PGE */
902  __writecr4(Cr4);
903  }
904  else
905  {
906  /* No global pages, resetting CR3 is enough */
908  }
909 
910 #endif
911 
912 }
913 
914 VOID
915 NTAPI
917 {
918  PKGDTENTRY TssEntry;
919 
920  //
921  // Restore the CR registers
922  //
923  __writecr0(ProcessorState->SpecialRegisters.Cr0);
924  Ke386SetCr2(ProcessorState->SpecialRegisters.Cr2);
925  __writecr3(ProcessorState->SpecialRegisters.Cr3);
926  if (KeFeatureBits & KF_CR4) __writecr4(ProcessorState->SpecialRegisters.Cr4);
927 
928  //
929  // Restore the DR registers
930  //
931  __writedr(0, ProcessorState->SpecialRegisters.KernelDr0);
932  __writedr(1, ProcessorState->SpecialRegisters.KernelDr1);
933  __writedr(2, ProcessorState->SpecialRegisters.KernelDr2);
934  __writedr(3, ProcessorState->SpecialRegisters.KernelDr3);
935  __writedr(6, ProcessorState->SpecialRegisters.KernelDr6);
936  __writedr(7, ProcessorState->SpecialRegisters.KernelDr7);
937 
938  //
939  // Restore GDT and IDT
940  //
942  __lidt(&ProcessorState->SpecialRegisters.Idtr.Limit);
943 
944  //
945  // Clear the busy flag so we don't crash if we reload the same selector
946  //
947  TssEntry = (PKGDTENTRY)(ProcessorState->SpecialRegisters.Gdtr.Base +
948  ProcessorState->SpecialRegisters.Tr);
949  TssEntry->HighWord.Bytes.Flags1 &= ~0x2;
950 
951  //
952  // Restore TSS and LDT
953  //
954  Ke386SetTr(ProcessorState->SpecialRegisters.Tr);
955  Ke386SetLocalDescriptorTable(ProcessorState->SpecialRegisters.Ldtr);
956 }
957 
958 VOID
959 NTAPI
961 {
962  /* Save the CR registers */
963  ProcessorState->SpecialRegisters.Cr0 = __readcr0();
964  ProcessorState->SpecialRegisters.Cr2 = __readcr2();
965  ProcessorState->SpecialRegisters.Cr3 = __readcr3();
966  ProcessorState->SpecialRegisters.Cr4 = (KeFeatureBits & KF_CR4) ?
967  __readcr4() : 0;
968 
969  /* Save the DR registers */
970  ProcessorState->SpecialRegisters.KernelDr0 = __readdr(0);
971  ProcessorState->SpecialRegisters.KernelDr1 = __readdr(1);
972  ProcessorState->SpecialRegisters.KernelDr2 = __readdr(2);
973  ProcessorState->SpecialRegisters.KernelDr3 = __readdr(3);
974  ProcessorState->SpecialRegisters.KernelDr6 = __readdr(6);
975  ProcessorState->SpecialRegisters.KernelDr7 = __readdr(7);
976  __writedr(7, 0);
977 
978  /* Save GDT, IDT, LDT and TSS */
979  Ke386GetGlobalDescriptorTable(&ProcessorState->SpecialRegisters.Gdtr.Limit);
980  __sidt(&ProcessorState->SpecialRegisters.Idtr.Limit);
981  ProcessorState->SpecialRegisters.Tr = Ke386GetTr();
982  Ke386GetLocalDescriptorTable(&ProcessorState->SpecialRegisters.Ldtr);
983 }
984 
985 CODE_SEG("INIT")
986 VOID
987 NTAPI
989 {
990  /* Set the Machine Type we got from NTLDR */
992 }
993 
994 CODE_SEG("INIT")
995 ULONG_PTR
996 NTAPI
998 {
999  /* Set CS and ESP */
1000  __writemsr(0x174, KGDT_R0_CODE);
1001  __writemsr(0x175, (ULONG_PTR)KeGetCurrentPrcb()->DpcStack);
1002 
1003  /* Set LSTAR */
1005  return 0;
1006 }
1007 
1008 CODE_SEG("INIT")
1009 VOID
1010 NTAPI
1012 {
1013  /* Check if the CPU Supports fast system call */
1015  {
1016  /* Check if it has been disabled */
1018  {
1019  /* Disable fast system call */
1022  DPRINT1("Support for SYSENTER disabled.\n");
1023  }
1024  else
1025  {
1026  /* Do an IPI to enable it */
1028 
1029  /* It's enabled, so use the proper exit stub */
1031  DPRINT("Support for SYSENTER detected.\n");
1032  }
1033  }
1034  else
1035  {
1036  /* Use the IRET handler */
1038  DPRINT1("No support for SYSENTER detected.\n");
1039  }
1040 }
1041 
1042 CODE_SEG("INIT")
1043 ULONG_PTR
1044 NTAPI
1046 {
1047  /* Enable DE */
1049  return 0;
1050 }
1051 
1052 CODE_SEG("INIT")
1053 ULONG_PTR
1054 NTAPI
1056 {
1057  /* Enable FXSR */
1059  return 0;
1060 }
1061 
1062 CODE_SEG("INIT")
1063 ULONG_PTR
1064 NTAPI
1066 {
1068 
1069  /* Get the IDT Entry for Interrupt 0x13 */
1070  IdtEntry = &((PKIPCR)KeGetPcr())->IDT[0x13];
1071 
1072  /* Set it up */
1073  IdtEntry->Selector = KGDT_R0_CODE;
1074  IdtEntry->Offset = ((ULONG_PTR)KiTrap13 & 0xFFFF);
1075  IdtEntry->ExtendedOffset = ((ULONG_PTR)KiTrap13 >> 16) & 0xFFFF;
1076  ((PKIDT_ACCESS)&IdtEntry->Access)->Dpl = 0;
1077  ((PKIDT_ACCESS)&IdtEntry->Access)->Present = 1;
1078  ((PKIDT_ACCESS)&IdtEntry->Access)->SegmentType = I386_INTERRUPT_GATE;
1079 
1080  /* Enable XMMI exceptions */
1082  return 0;
1083 }
1084 
1085 CODE_SEG("INIT")
1086 VOID
1087 NTAPI
1089 {
1090  KDESCRIPTOR IdtDescriptor = {0, 0, 0};
1091  PKIDTENTRY NewIdt, NewIdt2;
1092  PMMPTE PointerPte;
1093 
1094  /* Allocate memory for a new IDT */
1095  NewIdt = ExAllocatePool(NonPagedPool, 2 * PAGE_SIZE);
1096 
1097  /* Put everything after the first 7 entries on a new page */
1098  NewIdt2 = (PVOID)((ULONG_PTR)NewIdt + PAGE_SIZE - (7 * sizeof(KIDTENTRY)));
1099 
1100  /* Disable interrupts */
1101  _disable();
1102 
1103  /* Get the current IDT and copy it */
1104  __sidt(&IdtDescriptor.Limit);
1105  RtlCopyMemory(NewIdt2,
1106  (PVOID)IdtDescriptor.Base,
1107  IdtDescriptor.Limit + 1);
1108  IdtDescriptor.Base = (ULONG)NewIdt2;
1109 
1110  /* Set the new IDT */
1111  __lidt(&IdtDescriptor.Limit);
1112  ((PKIPCR)KeGetPcr())->IDT = NewIdt2;
1113 
1114  /* Restore interrupts */
1115  _enable();
1116 
1117  /* Set the first 7 entries as read-only to produce a fault */
1118  PointerPte = MiAddressToPte(NewIdt);
1119  ASSERT(PointerPte->u.Hard.Write == 1);
1120  PointerPte->u.Hard.Write = 0;
1121  KeInvalidateTlbEntry(NewIdt);
1122 }
1123 
1124 BOOLEAN
1125 NTAPI
1127 {
1128  /* Only supported on Pentium Pro and higher */
1129  if (KeI386CpuType < 6) return FALSE;
1130 
1131  /* Invalidate all caches */
1132  __wbinvd();
1133  return TRUE;
1134 }
1135 
1136 VOID
1137 FASTCALL
1139  IN ULONG Size)
1140 {
1141  /* Not using XMMI in this routine */
1143 }
1144 
1145 VOID
1146 NTAPI
1148  IN PKEXCEPTION_FRAME ExceptionFrame)
1149 {
1150  PKPRCB Prcb = KeGetCurrentPrcb();
1151 
1152  //
1153  // Save full context
1154  //
1158 
1159  //
1160  // Save control registers
1161  //
1163 }
1164 
1165 CODE_SEG("INIT")
1166 BOOLEAN
1167 NTAPI
1169 {
1170  ULONG Cr0;
1171  USHORT Magic;
1172 
1173  /* Set magic */
1174  Magic = 0xFFFF;
1175 
1176  /* Read CR0 and mask out FPU flags */
1177  Cr0 = __readcr0() & ~(CR0_MP | CR0_TS | CR0_EM | CR0_ET);
1178 
1179  /* Store on FPU stack */
1180 #ifdef _MSC_VER
1181  __asm fninit;
1182  __asm fnstsw Magic;
1183 #else
1184  asm volatile ("fninit;" "fnstsw %0" : "+m"(Magic));
1185 #endif
1186 
1187  /* Magic should now be cleared */
1188  if (Magic & 0xFF)
1189  {
1190  /* You don't have an FPU -- enable emulation for now */
1191  __writecr0(Cr0 | CR0_EM | CR0_TS);
1192  return FALSE;
1193  }
1194 
1195  /* You have an FPU, enable it */
1196  Cr0 |= CR0_ET;
1197 
1198  /* Enable INT 16 on 486 and higher */
1199  if (KeGetCurrentPrcb()->CpuType >= 3) Cr0 |= CR0_NE;
1200 
1201  /* Set FPU state */
1202  __writecr0(Cr0 | CR0_EM | CR0_TS);
1203  return TRUE;
1204 }
1205 
1206 CODE_SEG("INIT")
1207 BOOLEAN
1208 NTAPI
1210 {
1211  static double Value1 = 4195835.0, Value2 = 3145727.0;
1212  INT ErrataPresent;
1213  ULONG Cr0;
1214 
1215  /* Disable interrupts */
1216  _disable();
1217 
1218  /* Read CR0 and remove FPU flags */
1219  Cr0 = __readcr0();
1220  __writecr0(Cr0 & ~(CR0_MP | CR0_TS | CR0_EM));
1221 
1222  /* Initialize FPU state */
1223  Ke386FnInit();
1224 
1225  /* Multiply the magic values and divide, we should get the result back */
1226 #ifdef __GNUC__
1227  __asm__ __volatile__
1228  (
1229  "fldl %1\n\t"
1230  "fdivl %2\n\t"
1231  "fmull %2\n\t"
1232  "fldl %1\n\t"
1233  "fsubp\n\t"
1234  "fistpl %0\n\t"
1235  : "=m" (ErrataPresent)
1236  : "m" (Value1),
1237  "m" (Value2)
1238  );
1239 #else
1240  __asm
1241  {
1242  fld Value1
1243  fdiv Value2
1244  fmul Value2
1245  fld Value1
1246  fsubp st(1), st(0)
1247  fistp ErrataPresent
1248  };
1249 #endif
1250 
1251  /* Restore CR0 */
1252  __writecr0(Cr0);
1253 
1254  /* Enable interrupts */
1255  _enable();
1256 
1257  /* Return if there's an errata */
1258  return ErrataPresent != 0;
1259 }
1260 
1261 VOID
1262 NTAPI
1264 {
1265  ULONG EFlags, Cr0;
1266  PKTHREAD Thread, NpxThread;
1267  PFX_SAVE_AREA FxSaveArea;
1268 
1269  /* Save volatiles and disable interrupts */
1270  EFlags = __readeflags();
1271  _disable();
1272 
1273  /* Save the PCR and get the current thread */
1275 
1276  /* Check if we're already loaded */
1277  if (Thread->NpxState != NPX_STATE_LOADED)
1278  {
1279  /* If there's nothing to load, quit */
1280  if (!SaveArea)
1281  {
1282  /* Restore interrupt state and return */
1283  __writeeflags(EFlags);
1284  return;
1285  }
1286 
1287  /* Need FXSR support for this */
1289 
1290  /* Check for sane CR0 */
1291  Cr0 = __readcr0();
1292  if (Cr0 & (CR0_MP | CR0_TS | CR0_EM))
1293  {
1294  /* Mask out FPU flags */
1295  __writecr0(Cr0 & ~(CR0_MP | CR0_TS | CR0_EM));
1296  }
1297 
1298  /* Get the NPX thread and check its FPU state */
1299  NpxThread = KeGetCurrentPrcb()->NpxThread;
1300  if ((NpxThread) && (NpxThread->NpxState == NPX_STATE_LOADED))
1301  {
1302  /* Get the FX frame and store the state there */
1303  FxSaveArea = KiGetThreadNpxArea(NpxThread);
1304  Ke386FxSave(FxSaveArea);
1305 
1306  /* NPX thread has lost its state */
1307  NpxThread->NpxState = NPX_STATE_NOT_LOADED;
1308  }
1309 
1310  /* Now load NPX state from the NPX area */
1311  FxSaveArea = KiGetThreadNpxArea(Thread);
1312  Ke386FxStore(FxSaveArea);
1313  }
1314  else
1315  {
1316  /* Check for sane CR0 */
1317  Cr0 = __readcr0();
1318  if (Cr0 & (CR0_MP | CR0_TS | CR0_EM))
1319  {
1320  /* Mask out FPU flags */
1321  __writecr0(Cr0 & ~(CR0_MP | CR0_TS | CR0_EM));
1322  }
1323 
1324  /* Get FX frame */
1325  FxSaveArea = KiGetThreadNpxArea(Thread);
1326  Thread->NpxState = NPX_STATE_NOT_LOADED;
1327 
1328  /* Save state if supported by CPU */
1329  if (KeI386FxsrPresent) Ke386FxSave(FxSaveArea);
1330  }
1331 
1332  /* Now save the FN state wherever it was requested */
1333  if (SaveArea) Ke386FnSave(SaveArea);
1334 
1335  /* Clear NPX thread */
1336  KeGetCurrentPrcb()->NpxThread = NULL;
1337 
1338  /* Add the CR0 from the NPX frame */
1339  Cr0 |= NPX_STATE_NOT_LOADED;
1340  Cr0 |= FxSaveArea->Cr0NpxState;
1341  __writecr0(Cr0);
1342 
1343  /* Restore interrupt state */
1344  __writeeflags(EFlags);
1345 }
1346 
1347 /* PUBLIC FUNCTIONS **********************************************************/
1348 
1349 /*
1350  * @implemented
1351  */
1352 VOID
1353 NTAPI
1355 {
1356  PFX_SAVE_AREA NpxArea;
1357 
1358  /* Get the FPU area */
1360 
1361  /* Set CR0_TS */
1362  NpxArea->Cr0NpxState = CR0_TS;
1364 }
1365 
1366 /*
1367  * @implemented
1368  */
1369 NTSTATUS
1370 NTAPI
1372 {
1373  PFNSAVE_FORMAT FpState;
1376 
1377  /* check if we are doing software emulation */
1379 
1380  FpState = ExAllocatePool(NonPagedPool, sizeof (FNSAVE_FORMAT));
1381  if (!FpState) return STATUS_INSUFFICIENT_RESOURCES;
1382 
1383  *((PVOID *) Save) = FpState;
1384 #ifdef __GNUC__
1385  asm volatile("fnsave %0\n\t" : "=m" (*FpState));
1386 #else
1387  __asm
1388  {
1389  mov eax, [FpState]
1390  fnsave [eax]
1391  };
1392 #endif
1393 
1394  KeGetCurrentThread()->Header.NpxIrql = KeGetCurrentIrql();
1395  return STATUS_SUCCESS;
1396 }
1397 
1398 /*
1399  * @implemented
1400  */
1401 NTSTATUS
1402 NTAPI
1404 {
1405  PFNSAVE_FORMAT FpState = *((PVOID *) Save);
1408 
1409 #ifdef __GNUC__
1410  asm volatile("fnclex\n\t");
1411  asm volatile("frstor %0\n\t" : "=m" (*FpState));
1412 #else
1413  __asm
1414  {
1415  fnclex
1416  mov eax, [FpState]
1417  frstor [eax]
1418  };
1419 #endif
1420 
1421  ExFreePool(FpState);
1422  return STATUS_SUCCESS;
1423 }
1424 
1425 /*
1426  * @implemented
1427  */
1428 ULONG
1429 NTAPI
1431 {
1432  /* Return the global variable */
1433  return KeLargestCacheLine;
1434 }
1435 
1436 VOID
1437 NTAPI
1439  IN PVOID Ignored1,
1440  IN PVOID Ignored2,
1441  IN PVOID Ignored3)
1442 {
1443  /* Signal this packet as done */
1444  KiIpiSignalPacketDone(PacketContext);
1445 
1446  /* Flush the TB for the Current CPU */
1447  KeFlushCurrentTb();
1448 }
1449 
1450 /*
1451  * @implemented
1452  */
1453 VOID
1454 NTAPI
1456  IN BOOLEAN AllProcessors)
1457 {
1458  KIRQL OldIrql;
1459 #ifdef CONFIG_SMP
1460  KAFFINITY TargetAffinity;
1461  PKPRCB Prcb = KeGetCurrentPrcb();
1462 #endif
1463 
1464  /* Raise the IRQL for the TB Flush */
1466 
1467 #ifdef CONFIG_SMP
1468  /* FIXME: Use KiTbFlushTimeStamp to synchronize TB flush */
1469 
1470  /* Get the current processor affinity, and exclude ourselves */
1471  TargetAffinity = KeActiveProcessors;
1472  TargetAffinity &= ~Prcb->SetMember;
1473 
1474  /* Make sure this is MP */
1475  if (TargetAffinity)
1476  {
1477  /* Send an IPI TB flush to the other processors */
1478  KiIpiSendPacket(TargetAffinity,
1480  NULL,
1481  0,
1482  NULL);
1483  }
1484 #endif
1485 
1486  /* Flush the TB for the Current CPU, and update the flush stamp */
1487  KeFlushCurrentTb();
1488 
1489 #ifdef CONFIG_SMP
1490  /* If this is MP, wait for the other processors to finish */
1491  if (TargetAffinity)
1492  {
1493  /* Sanity check */
1494  ASSERT(Prcb == KeGetCurrentPrcb());
1495 
1496  /* FIXME: TODO */
1497  ASSERTMSG("Not yet implemented\n", FALSE);
1498  }
1499 #endif
1500 
1501  /* Update the flush stamp and return to original IRQL */
1504 }
1505 
1506 /*
1507  * @implemented
1508  */
1509 VOID
1510 NTAPI
1512 {
1513  /* Save the coherency globally */
1514  KiDmaIoCoherency = Coherency;
1515 }
1516 
1517 /*
1518  * @implemented
1519  */
1520 KAFFINITY
1521 NTAPI
1523 {
1524  PAGED_CODE();
1525 
1526  /* Simply return the number of active processors */
1527  return KeActiveProcessors;
1528 }
1529 
1530 /*
1531  * @implemented
1532  */
1533 VOID
1534 __cdecl
1536 {
1537  /* Capture the context */
1538  RtlCaptureContext(&State->ContextFrame);
1539 
1540  /* Capture the control state */
1542 }
#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:1263
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
union _KGDTENTRY::@2401 HighWord
__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
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
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
BOOLEAN NTAPI KiIsNpxPresent(VOID)
Definition: cpu.c:1168
static const CHAR CmpRiseID[]
Definition: cpu.c:61
#define READ_PORT_UCHAR(p)
Definition: pc98vid.h:22
struct _KGDTENTRY::@2401::@2403 Bits
#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:1354
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:799
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
union _MMPTE::@2305 u
ULONG KeFeatureBits
Definition: krnlinit.c:22
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
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:988
ULONG KeIcacheFlushCount
Definition: cpu.c:19
#define KeGetPcr()
Definition: ke.h:26
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:1011
__asm__("\t.globl GetPhys\n" "GetPhys:\t\n" "mflr 0\n\t" "stwu 0,-16(1)\n\t" "mfmsr 5\n\t" "andi. 6,5,0xffef\n\t" "mtmsr 6\n\t" "isync\n\t" "sync\n\t" "lwz 3,0(3)\n\t" "mtmsr 5\n\t" "isync\n\t" "sync\n\t" "lwz 0,0(1)\n\t" "addi 1,1,16\n\t" "mtlr 0\n\t" "blr")
__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
struct _KGDTENTRY::@2401::@2402 Bytes
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:783
NTSTATUS NTAPI KeRestoreFloatingPointState(IN PKFLOATING_SAVE Save)
Definition: cpu.c:1403
__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:745
PPC_QUAL unsigned long long __readmsr()
Definition: intrin_ppc.h:741
static WCHAR Address[46]
Definition: ping.c:68
#define NPX_STATE_LOADED
Definition: asm.h:265
Definition: ketypes.h:789
#define EFLAGS_ID
Definition: ketypes.h:136
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
ULONG Eax
Definition: ketypes.h:300
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:403
#define PtrToUlong(u)
Definition: config.h:107
ULONG_PTR NTAPI Ki386EnableXMMIExceptions(IN ULONG_PTR Context)
Definition: cpu.c:1065
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:2000
#define IO_ACCESS_MAP_NONE
Definition: ketypes.h:267
union _LOADER_PARAMETER_BLOCK::@3320 u
VOID NTAPI KiSaveProcessorState(IN PKTRAP_FRAME TrapFrame, IN PKEXCEPTION_FRAME ExceptionFrame)
Definition: cpu.c:1147
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:1045
ULONG Ebx
Definition: ketypes.h:301
struct _KIDT_ACCESS * PKIDT_ACCESS
#define KF_MTRR
Definition: ketypes.h:149
ULONG Ecx
Definition: ketypes.h:302
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: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)
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:790
#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
#define CONTEXT_DEBUG_REGISTERS
Definition: nt_native.h:1373
#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:1371
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
UINT32 AsUINT32[4]
Definition: ketypes.h:297
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:1055
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
VOID FASTCALL KeZeroPages(IN PVOID Address, IN ULONG Size)
Definition: cpu.c:56
#define CR0_TS
Definition: asm.h:248
VOID NTAPI KiSetCR0Bits(VOID)
Definition: cpu.c:728
BOOLEAN NTAPI KiIsNpxErrataPresent(VOID)
Definition: cpu.c:1209
#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:1088
#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:997
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
ULONG Edx
Definition: ketypes.h:303
CHAR CpuID
Definition: ketypes.h:585
#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:1438
#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
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