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间的中断协调。

相关文章

一、前言 在组件方面react和Vue一样的,核心思想玩的就是组件...
前言: 前段时间学习完react后,刚好就接到公司一个react项目...
前言: 最近收到组长通知我们项目组后面新开的项目准备统一技...
react 中的高阶组件主要是对于 hooks 之前的类组件来说的,如...
我们上一节了解了组件的更新机制,但是只是停留在表层上,例...
我们上一节了解了 react 的虚拟 dom 的格式,如何把虚拟 dom...