reactos操作系统实现(17)

从上面分析可以看到,主要调用函数 KiInitializeKernel 来初始化内核,这个函数传送的参数与函数 KiSetupStackAndInitializeKernel 的参数是一样的,如下:

#001  VOID

#002  NTAPI

#003  KiInitializeKernel(IN PKPROCESS InitProcess,

# 004                      IN PKTHREAD InitThread,

# 005                      IN PVOID IdleStack,

# 006                      IN PKPRCB Prcb,

# 007                      IN CCHAR Number,

# 008                      IN PLOADER_PARAMETER_BLOCK LoaderBlock)

#009  {

上面传递的参数都是基于栈式,因此在这里就可以取到在汇编代码压栈参数。

 

#010      BOOLEAN NpxPresent;

#011      ULONG FeatureBits;

#012      ULONG PageDirectory[2];

#013      PVOID DpcStack;

#014      ULONG Vendor[3];

#015 

#016      /* Detect and set the CPU Type */

#017      KiSetProcessorType();

上面调用函数KiSetProcessorType来检测当前硬件系统里的CPU类型,并且把CPU类型和特性保存到控制块PRCB里。因为不同的CPU具有不同的功能,比如INTELAMDVIA都是X86CPU,但它们是有很多浮点数指令不一样的,这样就需要针对不同的CPU作不同的处理。现在就来分析这个函数的实现,它的代码如下:

#001  VOID

#002  NTAPI

#003  KiSetProcessorType(VOID)

#004  {

#005      ULONG EFlags = 0, NewEFlags;

#006      ULONG Reg[4];

#007      ULONG Stepping, Type;

#008 

#009      /* Start by assuming no CPUID data */

#010      KeGetCurrentPrcb()->CpuID = 0;

设置CPUID指令是否支持,这里初始化为不支持。

 

#011 

#012      /* Save EFlags */

#013      Ke386SaveFlags(EFlags);

保存CPU当前的标志位,因为后面需要检测CPUID

 

#014 

#015      /* XOR out the ID bit and update EFlags */

#016      NewEFlags = EFlags ^ EFLAGS_ID;

#017      Ke386RestoreFlags(NewEFlags);

CPUID指令位清空,再把它设置回到标志寄存器。

 

#018 

#019      /* Get them back and see if they were modified */

#020      Ke386SaveFlags(NewEFlags);

获取标志寄存器的值,下面查看是否会改变这个值。

 

#021      if (NewEFlags != EFlags)

#022      {

 

如果标志位有变化,说明就是支持CPUID的指令。

#023          /* The modification worked, so CPUID exists. Set the ID Bit again. */

#024          EFlags |= EFLAGS_ID;

#025          Ke386RestoreFlags(EFlags);

#026 

#027          /* Peform CPUID 0 to see if CPUID 1 is supported */

#028          CPUID(Reg, 0);

先操作CPUID0类型的指令。

 

#029          if (Reg[0] > 0)

#030          {

#031              /* Do CPUID 1 now */

#032              CPUID(Reg, 1);

操作CPUID1类型的指令。

 

#033 

#034              /*

#035               * Get the Stepping and Type. The stepping contains both the

#036               * Model and the Step, while the Type contains the returned Type.

#037               * We ignore the family.

#038               *

#039               * For the stepping, we convert this: zzzzzzxy into this: x0y

#040               */

#041              Stepping = Reg[0] & 0xF0;

#042              Stepping <<= 4;

#043              Stepping += (Reg[0] & 0xFF);

#044              Stepping &= 0xF 0F ;

#045              Type = Reg[0] & 0xF00;

#046              Type >>= 8;

#047 

#048              /* Save them in the PRCB */

#049              KeGetCurrentPrcb()->CpuID = TRUE;

#050              KeGetCurrentPrcb()->CpuType = (UCHAR)Type;

#051              KeGetCurrentPrcb()->CpuStep = (USHORT)Stepping;

上面获取到了CPU的类型,步进信息。

 

#052          }

#053          else

#054          {

#055              DPRINT1("CPUID Support lacking/n");

#056          }

#057      }

#058      else

#059      {

#060          DPRINT1("CPUID Support lacking/n");

#061      }

#062 

#063      /* Restore EFLAGS */

#064      Ke386RestoreFlags(EFlags);

恢复原来标志寄存器值。

 

#065  }

 

其实这段代码是获取CPU类型和步进信息,不同的CPU获取的信息是不一样,下面通过其它软件获取到我的CPU信息,如下图:

reactos操作系统实现(17)_第1张图片

在这个CPU应就是获取到CPU类型为6,而步进为FB。至于其它CPU信息,还会在后面继续探测和设置到内核数据结构里。

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