reactos操作系统实现(19)

由于 CPU 是多种多样,具备能力也是不一样的,并且不同厂家都会创新不同的功能。下面就来了解 CPU 特征识别,如下:

/* Get the processor features for the CPU */

    FeatureBits = KiGetFeatureBits();

这里是通过函数KiGetFeatureBits来获取CPU特征位,它的代码如下:

#001  ULONG

#002  NTAPI

#003  KiGetFeatureBits(VOID)

#004  {

#005      PKPRCB Prcb = KeGetCurrentPrcb();

获取当前处理器控制块。

 

#006      ULONG Vendor;

#007      ULONG FeatureBits = KF_WORKING_PTE;

初始化为允许分页管理。

 

#008      ULONG Reg[4];

#009      BOOLEAN ExtendedCPUID = TRUE;

#010      ULONG CpuFeatures = 0;

#011 

#012      /* Get the Vendor ID */

#013      Vendor = KiGetCpuVendor();

获取厂家标识。

 

#014 

#015      /* Make sure we got a valid vendor ID at least. */

#016      if (!Vendor) return FeatureBits;

如果不认识的厂家CPU,就不用去获取特征了。

 

#017 

#018      /* Get the CPUID Info. Features are in Reg[3]. */

#019      CPUID(Reg, 1);

获取CPUID信息。

 

#020 

#021      /* Set the initial APIC ID */

#022      Prcb->InitialApicId = (UCHAR)(Reg[1] >> 24);

设置APICAdvanced Programmable Interrupt Controller)的ID

 

#023 

 

根据不同的厂家处理。

#024      switch (Vendor)

#025      {

 

下面是INTELCPU特性识别。

#026          /* Intel CPUs */

#027          case CPU_INTEL:

#028              /* Check if it's a P6 */

#029              if (Prcb->CpuType == 6)

#030              {

#031                  /* Perform the special sequence to get the MicroCode Signature */

#032                  WRMSR(0x8B, 0);

#033                  CPUID(Reg, 1);

#034                  Prcb->UpdateSignature.QuadPart = RDMSR(0x8B);

#035              }

#036              else if (Prcb->CpuType == 5)

#037              {

#038                  /* On P5, enable workaround for the LOCK errata. */

#039                  KiI386PentiumLockErrataPresent = TRUE;

#040              }

#041 

#042              /* Check for broken P6 with bad SMP PTE implementation */

#043              if (((Reg[0] & 0x0FF0) == 0x0610 && (Reg[0] & 0x 000F ) <= 0x9) ||

#044                  ((Reg[0] & 0x0FF0) == 0x0630 && (Reg[0] & 0x 000F ) <= 0x4))

#045              {

#046                  /* Remove support for correct PTE support. */

#047                  FeatureBits &= ~KF_WORKING_PTE;

#048              }

#049 

#050              /* Check if the CPU is too old to support SYSENTER */

#051              if ((Prcb->CpuType < 6) ||

#052                  ((Prcb->CpuType == 6) && (Prcb->CpuStep < 0x0303)))

#053              {

#054                  /* Disable it */

#055                  Reg[3] &= ~0x800;

#056              }

#057 

#058              /* Set the current features */

#059              CpuFeatures = Reg[3];

#060 

#061              break;

#062 

 

下面AMDCPU特性识别处理。

#063          /* AMD CPUs */

#064          case CPU_AMD:

#065 

#066              /* Check if this is a K5 or K6. (family 5) */

#067              if ((Reg[0] & 0x 0F 00) == 0x0500)

#068              {

#069                  /* Get the Model Number */

#070                  switch (Reg[0] & 0x 00F 0)

#071                  {

#072                      /* Model 1: K5 - 5k86 (initial models) */

#073                      case 0x0010:

#074 

#075                          /* Check if this is Step 0 or 1. They don't support PGE */

#076                          if ((Reg[0] & 0x 000F ) > 0x03) break;

#077 

#078                      /* Model 0: K5 - SSA5 */

#079                      case 0x0000:

#080 

#081                          /* Model 0 doesn't support PGE at all. */

#082                          Reg[3] &= ~0x2000;

#083                          break;

#084 

#085                      /* Model 8: K6-2 */

#086                      case 0x0080:

#087 

#088                          /* K6-2, Step 8 and over have support for MTRR. */

#089                          if ((Reg[0] & 0x 000F ) >= 0x8) FeatureBits |= KF_AMDK6MTRR;

#090                          break;

#091 

#092                      /* Model 9: K6-III

#093                         Model D: K6-2+, K6-III+ */

#094                      case 0x0090:

#095                      case 0x00D0:

#096 

#097                          FeatureBits |= KF_AMDK6MTRR;

#098                          break;

#099                  }

#100              }

#101              else if((Reg[0] & 0x 0F 00) < 0x0500)

#102              {

#103                  /* Families below 5 don't support PGE, PSE or CMOV at all */

#104                  Reg[3] &= ~(0x08 | 0x2000 | 0x8000);

#105 

#106                  /* They also don't support advanced CPUID functions. */

#107                  ExtendedCPUID = FALSE;

#108              }

#109 

#110              /* Set the current features */

#111              CpuFeatures = Reg[3];

#112 

#113              break;

#114 

 

其它X86CPU还没有处理。

#115          /* Cyrix CPUs */

#116          case CPU_CYRIX:

#117              break;

#118 

#119          /* Transmeta CPUs */

#120          case CPU_TRANSMETA:

#121              /* Enable CMPXCHG8B if the family (>= 5), model and stepping (>= 4.2) support it */

#122              if ((Reg[0] & 0x0FFF) >= 0x0542)

#123              {

#124                  WRMSR(0x80860004, RDMSR(0x80860004) | 0x0100);

#125                  FeatureBits |= KF_CMPXCHG8B;

#126              }

#127 

#128              break;

#129 

#130          /* Centaur, IDT, Rise and VIA CPUs */

#131          case CPU_CENTAUR:

#132          case CPU_RISE:

#133              /* These CPUs don't report the presence of CMPXCHG8B through CPUID.

#134                 However, this feature exists and operates properly without any additional steps. */

#135              FeatureBits |= KF_CMPXCHG8B;

#136 

#137              break;

#138      }

#139 

 

转换CPUID为内核使用的标识。

#140      /* Convert all CPUID Feature bits into our format */

#141      if (CpuFeatures & 0x00000002) FeatureBits |= KF_V86_VIS | KF_CR4;

#142      if (CpuFeatures & 0x00000008) FeatureBits |= KF_LARGE_PAGE | KF_CR4;

#143      if (CpuFeatures & 0x00000010) FeatureBits |= KF_RDTSC;

#144      if (CpuFeatures & 0x00000100) FeatureBits |= KF_CMPXCHG8B;

#145      if (CpuFeatures & 0x00000800) FeatureBits |= KF_FAST_SYSCALL;

#146      if (CpuFeatures & 0x00001000) FeatureBits |= KF_MTRR;

#147      if (CpuFeatures & 0x00002000) FeatureBits |= KF_GLOBAL_PAGE | KF_CR4;

#148      if (CpuFeatures & 0x00008000) FeatureBits |= KF_CMOV;

#149      if (CpuFeatures & 0x00010000) FeatureBits |= KF_PAT;

#150      if (CpuFeatures & 0x00200000) FeatureBits |= KF_DTS;

#151      if (CpuFeatures & 0x00800000) FeatureBits |= KF_MMX;

#152      if (CpuFeatures & 0x01000000) FeatureBits |= KF_FXSR;

#153      if (CpuFeatures & 0x02000000) FeatureBits |= KF_XMMI;

#154      if (CpuFeatures & 0x04000000) FeatureBits |= KF_XMMI64;

#155 

 

检查CPU是否具有超线程。

#156      /* Check if the CPU has hyper-threading */

#157      if (CpuFeatures & 0x10000000)

#158      {

#159          /* Set the number of logical CPUs */

#160          Prcb->LogicalProcessorsPerPhysicalProcessor = (UCHAR)(Reg[1] >> 16);

#161          if (Prcb->LogicalProcessorsPerPhysicalProcessor > 1)

#162          {

#163              /* We're on dual-core */

#164              KiSMTProcessorsPresent = TRUE;

#165          }

#166      }

#167      else

#168      {

#169          /* We only have a single CPU */

#170          Prcb->LogicalProcessorsPerPhysicalProcessor = 1;

#171      }

#172 

#173      /* Check if CPUID 0x80000000 is supported */

#174      if (ExtendedCPUID)

#175      {

#176          /* Do the call */

#177          CPUID(Reg, 0x80000000);

#178          if ((Reg[0] & 0xffffff00) == 0x80000000)

#179          {

#180              /* Check if CPUID 0x80000001 is supported */

#181              if (Reg[0] >= 0x80000001)

#182              {

#183                  /* Check which extended features are available. */

#184                  CPUID(Reg, 0x80000001);

#185 

#186                  /* Check if NX-bit is supported */

#187                  if (Reg[3] & 0x00100000) FeatureBits |= KF_NX_BIT;

#188 

#189                  /* Now handle each features for each CPU Vendor */

#190                  switch (Vendor)

#191                  {

#192                      case CPU_AMD:

#193                      case CPU_CENTAUR:

#194                          if (Reg[3] & 0x80000000) FeatureBits |= KF_3DNOW;

#195                          break;

#196                  }

#197              }

#198          }

#199      }

#200 

#201      /* Return the Feature Bits */

#202      return FeatureBits;

#203  }

 

现在看看什么是APICAPIC (高级可编程中断控制器)对计算机来讲有两个作用,

一是管理IRQ的分配,可以把传统的16IRQ扩展到24个(传统的管理方式叫PIC),以适应更多的设备。

二是管理多CPU

不过,如果板卡不是非常多的话,关闭 APIC对系统是没有什么影响的。

要实现SMP功能,我们使用的CPU必须具备以下要求:

CPU内部必须内置APIC单元。Intel 多处理规范的核心就是高级可编程中断控制器(Advanced Programmable Interrupt ControllersAPICs)的使用。CPU通过彼此发送中断来完成它们之间的通信。通过给中断附加动作(actions),不同的CPU可以在某种程度上彼此进行控制。每个CPU有自己的APIC(成为那个CPU的本地APIC),并且还有一个I/O APIC来处理由I/O设备引起的中断,这个I/O APIC是安装在主板上的,但每个CPU上的APIC则不可或缺,否则将无法处理多CPU之间的中断协调。

你可能感兴趣的:(reactos操作系统实现(19))