/* 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;
#017
#018 /* Get the cpuID Info. Features are in Reg[3]. */
#019 cpuID(Reg,1);
#020
#021 /* Set the initial APIC ID */
#022 Prcb->InitialApicId = (UCHAR)(Reg[1] >> 24);
设置APIC(Advanced Programmable Interrupt Controller)的ID。
#023
根据不同的厂家处理。
#024 switch (Vendor)
#025 {
下面是INTEL的cpu特性识别。
#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
#044 ((Reg[0] & 0x0FF0) == 0x0630 && (Reg[0] & 0x
#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
下面AMD的cpu特性识别处理。
#063 /* AMD cpus */
#064 case cpu_AMD:
#065
#066 /* Check if this is a K5 or K6. (family 5) */
#067 if ((Reg[0] & 0x
#068 {
#069 /* Get the Model Number */
#070 switch (Reg[0] & 0x
#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
#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
#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
#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
其它X86的cpu还没有处理。
#115 /* Cyrix cpus */
#116 case cpu_CYRIX:
#117 break;
#118
#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 }
现在看看什么是APIC,APIC (高级可编程中断控制器)对计算机来讲有两个作用,
一是管理IRQ的分配,可以把传统的16个IRQ扩展到24个(传统的管理方式叫PIC),以适应更多的设备。
二是管理多cpu。
不过,如果板卡不是非常多的话,关闭 APIC对系统是没有什么影响的。
cpu内部必须内置APIC单元。Intel 多处理规范的核心就是高级可编程中断控制器(Advanced Programmable Interrupt Controllers–APICs)的使用。cpu通过彼此发送中断来完成它们之间的通信。通过给中断附加动作(actions),不同的cpu可以在某种程度上彼此进行控制。每个cpu有自己的APIC(成为那个cpu的本地APIC),并且还有一个I/O APIC来处理由I/O设备引起的中断,这个I/O APIC是安装在主板上的,但每个cpu上的APIC则不可或缺,否则将无法处理多cpu之间的中断协调。