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() 中。

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

在检测到处理器类型后,内核会通过覆盖 nop 来修补不应使用的代码段。使用 cpu 特性只需要 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 中的记录,如果不存在所需的特性,它将循环写入从每个 BEGIN_FTR_SECTION 到 END_FTR_SECTION 的 nop。