使用 cpuid 提取缓存行大小的复制功能

Duplicating functionality for extracting cache line size with cpuid

我检查了 cpuid 文档并发现了 2 种不同的获取缓存行大小的记录方法:

  1. eax = 0x04, ecx = $cache_level

这样,$cache_level 处的缓存行大小将存储在 EBX[11:0]

  1. eax = 0x80000006

这样,缓存行大小将存储在ECX[7:0],叶子不依赖于缓存级别。

问题: 将缓存行大小信息添加到叶 0x80000006 的原因是什么,为什么不这样做取决于缓存级别?我怀疑 "the right" 获取缓存行大小的方法是 eax = 0x04, ecx = $cache_level.

英特尔和 AMD(以及威盛和...)是不同的公司;并且(可悲的是)没有涉及供应商中立的标准化机构,没有任何东西迫使供应商之间进行理智的合作,也没有任何东西可以阻止供应商制造大混乱以试图让彼此看起来很糟糕。

当 AMD 创建 "CPUID, leaf 0x80000006" 时,他们做了一件简单的事情 - 假设所有缓存的缓存行大小都相同,并将其放入一个字段中。

然而(至少在理论上)每个不同的缓存可以有不同的"line size";所以当英特尔创建 "CPUID, leaf 0x00000004" 时,他们做到了(理论上)每个不同的缓存都可以报告不同的 "line size".

正确的方法是乱七八糟的解决供应商的乱七八糟的事情。具体来说;对于 AMD CPU,如果可以的话,你会想使用 "CPUID, leaf 0x80000006";对于 Intel CPUs(我认为是 VIA CPUs),如果可以的话,你会想使用 "CPUID, leaf 0x00000004";对于所有你不能的情况(例如,因为 CPU 太旧而无法支持供应商的方法),你最终会遇到另一个大混乱(例如,使用启发式方法,and/or 使用 "vendor:family:model:stepping"在静态数据库中查找信息)。

当然,除此之外,您还必须考虑勘误表;这意味着通过大约一百个 "specification updates" 和 "BIOS and Kernel Developer Guides" 来找出需要 if/where "special case work-arounds"。

注意 1:如果您唯一关心的是缓存行大小,那么上述所有内容都不会太难;但是你想要的信息越多,情况就越糟(例如,如果你也关心每个缓存的大小,那么你应该期望大约 10 倍的麻烦和 10 倍的维护负担)。

注 2:理想情况下,OS 会提供 "pre-sanitized CPU info";使得它只需要在一个地方进行更新,使得普通软件不需要处理无意义的"vendor differences"、勘误表、缺失信息或混淆信息;并禁止直接使用 CPUID 指令(出于方便、正确和安全的原因)。不幸的是,没有现有的 OS 提供这个。