CPU 特性

Hollis Blanchard <hollis@austin.ibm.com> 2002年6月5日

本文档描述了 PPC Linux 内核中用于支持各种 PowerPC CPU 而无需在编译时进行选择的系统(包括自修改代码)。

在启动过程的早期,ppc32 内核会检测当前的 CPU 类型,并据此选择一组特性。一些示例包括 Altivec 支持、分离的指令和数据缓存,以及 CPU 是否支持 DOZE 和 NAP 睡眠模式。

特性集的检测很简单。处理器列表可在 arch/powerpc/kernel/cputable.c 中找到。PVR 寄存器会被掩码并与列表中的每个值进行比较。如果找到匹配项,cur_cpu_spec 的 cpu_features 将被分配给该处理器的特性位掩码,并调用 __setup_cpu 函数。

C 代码可以测试 ‘cur_cpu_spec[smp_processor_id()]->cpu_features’ 以查找特定的特性位。这在很多地方都有使用,例如在 ppc_setup_l2cr() 中。

在汇编中实现 cpufeatures 会稍微复杂一些。有几条路径是性能关键的,如果增加数组索引、结构体解引用和条件分支,性能将会受到影响。为了避免性能损失,同时仍然允许运行时(而非编译时)CPU 选择,未使用的代码会被 ‘nop’ 指令替换。这种 nop 替换是基于 CPU 0 的能力进行的,因此具有不同处理器的多处理器系统将无法工作(但这样的系统本身也可能存在其他问题)。

在检测到处理器类型后,内核会通过写入 nop 来覆盖不应使用的代码段,从而对其进行修补。使用 cpufeatures 只需要 2 个宏(可在 arch/powerpc/include/asm/cputable.h 中找到),如 head.S 的 transfer_to_handler 中所示。

#ifdef CONFIG_ALTIVEC
BEGIN_FTR_SECTION
        mfspr   r22,SPRN_VRSAVE         /* if G4, save vrsave register value */
        stw     r22,THREAD_VRSAVE(r23)
END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
#endif /* CONFIG_ALTIVEC */

如果 CPU 0 支持 Altivec,则代码保持不变。如果不支持,两条指令都将被 nop 替换。

END_FTR_SECTION 宏有两个更简单的变体:END_FTR_SECTION_IFSET 和 END_FTR_SECTION_IFCLR。它们分别简单地测试标志位(在 cur_cpu_spec[0]->cpu_features 中)是置位还是清零。在大多数情况下应该使用这两个宏。

END_FTR_SECTION 宏是通过将有关此代码的信息存储在 ‘__ftr_fixup’ ELF 段中来实现的。当调用 do_cpu_ftr_fixups (arch/powerpc/kernel/misc.S) 时,它会遍历 __ftr_fixup 中的记录,如果所需的特性不存在,它将循环将 nop 写入从每个 BEGIN_FTR_SECTION 到 END_FTR_SECTION 的区域。