为什么 intel_idle 不支持某些 Intel 系列 6 CPU 型号(Core 2、Pentium M)?

为什么 intel_idle 不支持某些 Intel 系列 6 CPU 型号(Core 2、Pentium M)?

我一直在调整我的 Linux 内核英特尔酷睿 2 四核(约克菲尔德)处理器,我注意到以下消息dmesg

[    0.019526] cpuidle: using governor menu
[    0.531691] clocksource: acpi_pm: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 2085701024 ns
[    0.550918] intel_idle: does not run on family 6 model 23
[    0.554415] tsc: Marking TSC unstable due to TSC halts in idle

PowerTop 仅显示用于封装和各个内核的状态 C1、C2 和 C3:

          Package   |            CPU 0
POLL        0.0%    | POLL        0.0%    0.1 ms
C1          0.0%    | C1          0.0%    0.0 ms
C2          8.2%    | C2          9.9%    0.4 ms
C3         84.9%    | C3         82.5%    0.9 ms

                    |            CPU 1
                    | POLL        0.1%    1.6 ms
                    | C1          0.0%    1.5 ms
                    | C2          9.6%    0.4 ms
                    | C3         82.7%    1.0 ms

                    |            CPU 2
                    | POLL        0.0%    0.1 ms
                    | C1          0.0%    0.0 ms
                    | C2          7.2%    0.3 ms
                    | C3         86.5%    1.0 ms

                    |            CPU 3
                    | POLL        0.0%    0.1 ms
                    | C1          0.0%    0.0 ms
                    | C2          5.9%    0.3 ms
                    | C3         87.7%    1.0 ms

出于好奇,我查询sysfs并发现旧版acpi_idle驱动程序正在使用中(我希望看到该intel_idle驱动程序):

cat /sys/devices/system/cpu/cpuidle/current_driver

acpi_空闲

查看内核源码,当前英特尔空闲驱动程序包含一条调试消息,特别指出该驱动程序不支持某些 Intel 系列 6 型号:

if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && boot_cpu_data.x86 == 6)
    pr_debug("does not run on family %d model %d\n", boot_cpu_data.x86, boot_cpu_data.x86_model);

较早的分叉(2010 年 11 月 22 日)intel_idle.c显示了对 Core 2 处理器的预期支持(型号 23 实际上涵盖了 Core 2 Duo 和 Quad):

#ifdef FUTURE_USE
    case 0x17:  /* 23 - Core 2 Duo */
        lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */
#endif

上述代码已于2010年12月删除犯罪

不幸的是,源代码中几乎没有文档,因此没有关于这些 CPU 中缺乏对空闲功能的支持的解释。

我当前的内核配置如下:

CONFIG_SMP=y
CONFIG_MCORE2=y
CONFIG_GENERIC_SMP_IDLE_THREAD=y
CONFIG_ACPI_PROCESSOR_IDLE=y
CONFIG_CPU_IDLE=y
# CONFIG_CPU_IDLE_GOV_LADDER is not set
CONFIG_CPU_IDLE_GOV_MENU=y
# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
CONFIG_INTEL_IDLE=y

我的问题如下:

  • 是否存在不支持 Core 2 处理器的特定硬件原因intel_idle
  • 是否有更合适的方法来配置内核以获得该系列处理器的最佳 CPU 空闲支持(除了禁用对 的支持之外intel_idle)?

答案1

研究 Core 2 时CPU 电源状态(“C状态”),我实际上设法实现了对大多数旧版 Intel Core/Core 2 处理器的支持。完整的实现(Linux 补丁)以及所有背景信息都记录在此处。

随着我积累了有关这些处理器的更多信息,我开始发现 Core 2 模型中支持的 C 状态比早期和后续处理器中的 C 状态复杂得多。这些被称为增强型 C 状态(或者 ”CXE”),其中涉及封装、各个核心和芯片组上的其他组件(例如内存)。在驱动程序发布时intel_idle,代码还不是特别成熟,并且已经发布了多个具有冲突 C 状态的 Core 2 处理器支持。

有关 Core 2 Solo/Duo C 状态支持的一些令人信服的信息可在这篇文章来自2006年。这与 Windows 上的支持有关,但它确实表明了这些处理器上强大的硬件 C 状态支持。有关 Kentsfield 的信息与实际型号相冲突,所以我相信他们实际上指的是下面的 Yorkfield:

...四核 Intel Core 2 Extreme (Kentsfield) 处理器支持所有五种性能和节能技术 — 增强型 Intel SpeedStep (EIST)、Thermal Monitor 1 (TM1) 和 Thermal Monitor 2 (TM2)、旧版按需时钟调制 (ODCM) 以及增强型 C 状态 (CxE)。与仅具有增强型暂停 (C1) 状态特征的 Intel Pentium 4 和 Pentium D 600、800 和 900 处理器相比,该功能在 Intel Core 2 处理器(以及 Intel Core Solo/Duo 处理器)中得到了扩展,可用于处理器的所有可能的空闲状态,包括停止授予 (C2)、深度睡眠 (C3) 和深度睡眠 (C4)。

这篇文章来自2008年概述了多核 Intel 处理器上对每核 C 状态的支持,包括 Core 2 Duo 和 Core 2 Quad(其他有用的背景阅读可在戴尔的这份白皮书):

核心 C 状态是硬件 C 状态。有几种核心空闲状态,例如CC1和CC3。众所周知,现代最先进的处理器具有多个核心,例如最近发布的Core Duo T5000/T7000移动处理器,在某些圈子里被称为Penryn。我们过去认为的 CPU/处理器,实际上里面有多个通用 CPU。 Intel Core Duo 处理器芯片中有 2 个核心。 Intel Core-2 Quad 在每个处理器芯片上有 4 个这样的内核。每个核心都有自己的空闲状态。这是有道理的,因为一个核心可能处于空闲状态,而另一个核心正在线程上努力工作。因此,核心 C 状态是这些核心之一的空闲状态。

我找到了一个英特尔 2010 年演讲它提供了一些有关驱动程序的额外背景信息intel_idle,但不幸的是没有解释缺乏对 Core 2 的支持:

此实验驱动程序取代 Intel Atom 处理器、Intel Core i3/i5/i7 处理器和相关 Intel Xeon 处理器上的 acpi_idle。它不支持 Intel Core2 或更早版本的处理器。

上面的介绍确实表明该intel_idle驱动程序是“菜单”CPU 调控器的实现,这对 Linux 内核配置有影响(即CONFIG_CPU_IDLE_GOV_LADDERvs. CONFIG_CPU_IDLE_GOV_MENU)。梯形调节器和菜单调节器之间的差异在这个答案

戴尔有一个有用的文章列出了 C 状态 C0 到 C6 兼容性:

模式C1至C3基本上通过切断CPU内部使用的时钟信号来工作,而模式C4至C6通过降低CPU电压来工作。 “增强”模式可以同时执行这两项操作。

Mode   Name                   CPUs
C0     Operating State        All CPUs
C1     Halt                   486DX4 and above
C1E    Enhanced Halt          All socket LGA775 CPUs
C1E    —                      Turion 64, 65-nm Athlon X2 and Phenom CPUs
C2     Stop Grant             486DX4 and above
C2     Stop Clock             Only 486DX4, Pentium, Pentium MMX, K5, K6, K6-2, K6-III
C2E    Extended Stop Grant    Core 2 Duo and above (Intel only)
C3     Sleep                  Pentium II, Athlon and above, but not on Core 2 Duo E4000 and E6000
C3     Deep Sleep             Pentium II and above, but not on Core 2 Duo E4000 and E6000; Turion 64
C3     AltVID                 AMD Turion 64
C4     Deeper Sleep           Pentium M and above, but not on Core 2 Duo E4000 and E6000 series; AMD Turion 64
C4E/C5 Enhanced Deeper Sleep  Core Solo, Core Duo and 45-nm mobile Core 2 Duo only
C6     Deep Power Down        45-nm mobile Core 2 Duo only

从这个表(我后来发现在某些情况下不正确)来看,Core 2 处理器的 C 状态支持似乎存在各种差异(请注意,几乎所有 Core 2 处理器都是 Socket LGA775,除了 Core 2 处理器) 2 Solo SU3500,即 Socket BGA956 和 Merom/Penryn 处理器,“Intel Core”Solo/Duo 处理器是 Socket PBGA479 或 PPGA478 之一。

该表的另一个例外是在本文:

Intel的Core 2 Duo E8500支持C状态C2和C4,而Core 2 Extreme QX9650则不支持。

有趣的是,QX9650 是一款 Yorkfield 处理器(Intel 系列 6,型号 23,步进 6)。作为参考,我的 Q9550S 是 Intel family 6,型号 23 (0x17),步进 10,据说支持 C 状态 C4(通过实验确认)。此外,Core 2 Solo U3500 具有与 Q9550S 相同的 CPUID(系列、型号、步进),但可用于非 LGA775 插槽,这会混淆上表的解释。

显然,必须至少使用 CPUID 来确定该处理器模型的 C 状态支持,并且在某些情况下这可能不够(目前尚未确定)。

分配CPU空闲信息的方法签名是:

#define ICPU(model, cpu) \
{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&cpu }

model列举在哪里asm/intel-family.h。检查此头文件,我发现 Intel CPU 被分配了 8 位标识符,这些标识符似乎与 Intel 系列 6 型号相匹配:

#define INTEL_FAM6_CORE2_PENRYN 0x17

从上面,我们将 Intel Family 6, Model 23 (0x17) 定义为INTEL_FAM6_CORE2_PENRYN.这应该足以定义大多数 Model 23 处理器的空闲状态,但可能会导致如上所述的 QX9650 问题。

因此,至少需要在此列表中定义具有不同 C 状态集的每组处理器。

扎加基和波纳拉,英特尔技术杂志 12(3):219-227, 2008表明 Yorkfield 处理器确实支持 C2 和 C4。它们似乎还表明 ACPI 3.0a 规范仅支持 C 状态 C0、C1、C2 和 C3 之间的转换,我认为这也可能限制 Linuxacpi_idle驱动程序只能在有限的 C 状态集之间进行转换。然而,本文表明情况可能并不总是如此:

请记住,这是 ACPI C 状态,而不是处理器状态,因此 ACPI C3 可能是 HW C6 等。

另外值得注意的是:

除了处理器本身之外,由于 C4 是平台中主要硅组件之间的同步工作,英特尔 Q45 高速芯片组实现了 28% 的功耗改进。

我使用的芯片组确实是 Intel Q45 Express 芯片组。

有关 MWAIT 的英特尔文档说明很简洁,但确认了 BIOS 特定的 ACPI 行为:

MWAIT 扩展中定义的特定于处理器的 C 状态可以映射到 ACPI 定义的 C 状态类型(C0、C1、C2、C3)。映射关系取决于处理器实现对 C 状态的定义,并由 BIOS 使用 ACPI 定义的 _CST 表向 OSPM 公开。

我对上表的解释(结合来自维基百科的表格,asm/intel-family.h以及上述文章)是:

型号 9 0x09 (奔腾M赛扬M):

  • 巴尼亚斯:C0、C1、C2、C3、C4

型号 13 0x0D (奔腾M赛扬M):

  • 多森·斯蒂利:C0、C1、C2、C3、C4

型号 14 0x0E INTEL_FAM6_CORE_YONAH(增强型奔腾M,增强型赛扬M或者英特尔酷睿):

  • 尤纳(核心独奏,核心双核):C0、C1、C2、C3、C4、C4E/C5

型号 15 0x0F INTEL_FAM6_CORE2_MEROM(一些核心2奔腾双核):

  • 肯茨菲尔德、梅罗姆、康罗、艾伦代尔 (E2xxx/E4xxx酷睿 2 双核 E6xxx、T7xxxx/T8xxxx,酷睿2至尊QX6xxx,酷睿 2 四核 Q6xxx):C0、C1、C1E、C2、C2E

模型 23 0x17 INTEL_FAM6_CORE2_PENRYN (核心2):

  • 梅罗姆-L/彭林-L:?
  • 彭林(酷睿 2 双核 45 纳米移动处理器):C0、C1、C1E、C2、C2E、C3、C4、C4E/C5、C6
  • 约克菲尔德(酷睿2至尊QX9650): C0, C1, C1E, C2E?, C3
  • 沃尔夫代尔/约克菲尔德(酷睿 2 四核,C2Q至强,酷睿 2 双核 E5xxx/E7xxx/E8xxx,奔腾双核 E6xxx,赛扬双核):C0、C1、C1E、C2、C2E、C3、C4

从 Core 2 系列处理器中 C 状态支持的多样性来看,缺乏对 C 状态的一致支持可能是不尝试通过驱动程序完全支持它们的原因intel_idle。我想完整完成上述整个 Core 2 系列的列表。

这并不是一个真正令人满意的答案,因为它让我想知道由于没有充分利用强大的节能功能而使用了多少不必要的电力以及(并且仍然)产生了多余的热量MWAIT C 状态在这些处理器上。

查托帕德耶等人。2018年,高能效高性能处理器:设计绿色高性能计算的最新方法值得注意的是我在 Q45 Express 芯片组中寻找的特定行为:

封装 C 状态 (PC0-PC10) - 当计算域、核心和显卡 (GPU) 空闲时,处理器有机会在非核心和平台级别实现额外的节能,例如刷新 LLC 和电源门控内存控制器和 DRAM IO,并且在某种状态下,整个处理器可以关闭,同时其状态保留在始终开启的电源域中。

作为测试,我在以下位置插入了以下内容linux/驱动程序/idle/intel_idle.c第 127 行:

static struct cpuidle_state conroe_cstates[] = {
    {
        .name = "C1",
        .desc = "MWAIT 0x00",
        .flags = MWAIT2flg(0x00),
        .exit_latency = 3,
        .target_residency = 6,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C1E",
        .desc = "MWAIT 0x01",
        .flags = MWAIT2flg(0x01),
        .exit_latency = 10,
        .target_residency = 20,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
//  {
//      .name = "C2",
//      .desc = "MWAIT 0x10",
//      .flags = MWAIT2flg(0x10),
//      .exit_latency = 20,
//      .target_residency = 40,
//      .enter = &intel_idle,
//      .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C2E",
        .desc = "MWAIT 0x11",
        .flags = MWAIT2flg(0x11),
        .exit_latency = 40,
        .target_residency = 100,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .enter = NULL }
};

static struct cpuidle_state core2_cstates[] = {
    {
        .name = "C1",
        .desc = "MWAIT 0x00",
        .flags = MWAIT2flg(0x00),
        .exit_latency = 3,
        .target_residency = 6,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C1E",
        .desc = "MWAIT 0x01",
        .flags = MWAIT2flg(0x01),
        .exit_latency = 10,
        .target_residency = 20,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C2",
        .desc = "MWAIT 0x10",
        .flags = MWAIT2flg(0x10),
        .exit_latency = 20,
        .target_residency = 40,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C2E",
        .desc = "MWAIT 0x11",
        .flags = MWAIT2flg(0x11),
        .exit_latency = 40,
        .target_residency = 100,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C3",
        .desc = "MWAIT 0x20",
        .flags = MWAIT2flg(0x20) | CPUIDLE_FLAG_TLB_FLUSHED,
        .exit_latency = 85,
        .target_residency = 200,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C4",
        .desc = "MWAIT 0x30",
        .flags = MWAIT2flg(0x30) | CPUIDLE_FLAG_TLB_FLUSHED,
        .exit_latency = 100,
        .target_residency = 400,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C4E",
        .desc = "MWAIT 0x31",
        .flags = MWAIT2flg(0x31) | CPUIDLE_FLAG_TLB_FLUSHED,
        .exit_latency = 100,
        .target_residency = 400,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .name = "C6",
        .desc = "MWAIT 0x40",
        .flags = MWAIT2flg(0x40) | CPUIDLE_FLAG_TLB_FLUSHED,
        .exit_latency = 200,
        .target_residency = 800,
        .enter = &intel_idle,
        .enter_s2idle = intel_idle_s2idle, },
    {
        .enter = NULL }
};

intel_idle.c983 行:

static const struct idle_cpu idle_cpu_conroe = {
    .state_table = conroe_cstates,
    .disable_promotion_to_c1e = false,
};

static const struct idle_cpu idle_cpu_core2 = {
    .state_table = core2_cstates,
    .disable_promotion_to_c1e = false,
};

intel_idle.c1073 行:

ICPU(INTEL_FAM6_CORE2_MEROM,  idle_cpu_conroe),
ICPU(INTEL_FAM6_CORE2_PENRYN, idle_cpu_core2),

快速编译并重新启动 PXE 节点后,dmesg现在显示:

[    0.019845] cpuidle: using governor menu
[    0.515785] clocksource: acpi_pm: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 2085701024 ns
[    0.543404] intel_idle: MWAIT substates: 0x22220
[    0.543405] intel_idle: v0.4.1 model 0x17
[    0.543413] tsc: Marking TSC unstable due to TSC halts in idle states deeper than C2
[    0.543680] intel_idle: lapic_timer_reliable_states 0x2

现在 PowerTOP 显示:

          Package   |            CPU 0
POLL        2.5%    | POLL        0.0%    0.0 ms
C1E         2.9%    | C1E         5.0%   22.4 ms
C2          0.4%    | C2          0.2%    0.2 ms
C3          2.1%    | C3          1.9%    0.5 ms
C4E        89.9%    | C4E        92.6%   66.5 ms

                    |            CPU 1
                    | POLL       10.0%  400.8 ms
                    | C1E         5.1%    6.4 ms
                    | C2          0.3%    0.1 ms
                    | C3          1.4%    0.6 ms
                    | C4E        76.8%   73.6 ms

                    |            CPU 2
                    | POLL        0.0%    0.2 ms
                    | C1E         1.1%    3.7 ms
                    | C2          0.2%    0.2 ms
                    | C3          3.9%    1.3 ms
                    | C4E        93.1%   26.4 ms

                    |            CPU 3
                    | POLL        0.0%    0.7 ms
                    | C1E         0.3%    0.3 ms
                    | C2          1.1%    0.4 ms
                    | C3          1.1%    0.5 ms
                    | C4E        97.0%   45.2 ms

我终于访问了增强型核心 2 C 状态,看起来功耗明显下降 - 我在 8 个节点上的仪表似乎平均至少降低了 5%(其中一个节点仍在运行旧内核) ,但我会尝试再次更换内核作为测试。

关于 C4E 支持的有趣说明 - 我的 Yorktown Q9550S 处理器似乎支持它(或 C4 的其他一些子状态),如上所示!这让我很困惑,因为Intel Core 2 Q9000 处理器数据表(第 6.2 节)仅提到 C 状态正常 (C0)、HALT (C1 = 0x00)、扩展 HALT (C1E = 0x01)、停止授予 (C2 = 0x10)、扩展停止授予 (C2E = 0x11)、睡眠/深度睡眠(C3 = 0x20) 和深度睡眠 (C4 = 0x30)。这个额外的 0x31 状态是什么?如果我启用状态 C2,则使用 C4E 而不是 C4。如果我禁用状态 C2(强制状态 C2E),则使用 C4 而不是 C4E。我怀疑这可能与 MWAIT 标志有关,但我尚未找到有关此行为的文档。

我不确定如何理解:C1E 状态似乎用于代替 C1,C2 用于代替 C2E,C4E 用于代替 C4。我不确定C1/C1E、C2/C2E和C4/C4E是否可以一起使用intel_idle或者它们是否是多余的。我发现了一个注释英特尔匹兹堡实验室 2010 年的演示表示转换为 C0 - C1 - C0 - C1E - C0,并进一步说明:

仅当所有核心都在 C1E 中时才使用 C1E

我认为这可以解释为只有当所有内核都处于 C1E 状态时,其他组件(例如内存)才会进入 C1E 状态。我也认为这同样适用于 C2/C2E 和 C4/C4E 状态(尽管 C4E 被称为“C4E/C5”,所以我不确定 C4E 是否是 C4 的子状态,或者 C5 是否是子状态) C4E 的状态。测试似乎表明 C4/C4E 是正确的)。我可以通过注释掉 C2 状态来强制使用 C2E - 但是,这会导致使用 C4 状态而不是 C4E(此处可能需要更多工作)。希望没有任何型号 15 或型号 23 处理器缺少状态 C2E,因为使用上述代码这些处理器将仅限于 C1/C1E。

此外,标志、延迟和驻留值可能需要进行微调,但仅根据 Nehalem 空闲值进行有根据的猜测似乎效果很好。需要更多的阅读才能做出任何改进。

我在一个上测试了这个酷睿2双核E2220艾伦代尔), A双核奔腾E5300沃尔夫代尔),酷睿2双核E7400,酷睿2双核E8400沃尔夫代尔),酷睿 2 四核 Q9550S约克菲尔德) 和酷睿2至尊QX9650,除了上述对状态 C2/C2E 和 C4/C4E 的偏好之外,我没有发现任何问题。

此驱动程序修改不包括:

  • 原本的核心独奏/核心双核尤纳,非核心 2)是系列 6,型号 14。这很好,因为它们支持 C4E/C5(增强型深度睡眠)C 状态,但不支持 C1E/C2E 状态,并且需要自己的空闲定义。

我能想到的唯一问题是:

  • 核心 2 独奏 SU3300/SU3500(Penryn-L) 是系列 6,型号 23,将被该驱动程序检测到。但是,它们不是 LGA775 插槽,因此可能不支持 C1E 增强型停止 C 状态。对于 Core 2 Solo ULV U2100/U2200 也是如此(梅罗姆-L)。但是,intel_idle驱动程序似乎会根据子状态的硬件支持来选择适当的 C1/C1E。
  • 据报道,Core 2 Extreme QX9650 (Yorkfield) 不支持 C 状态 C2 或 C4。我通过在 eBay 上购买二手 Optiplex 780 和 QX9650 Extreme 处理器证实了这一点。该处理器支持 C 状态 C1 和 C1E。通过此驱动程序修改,CPU 在状态 C1E 而不是 C1 下空闲,因此可能会节省一些电量。我预计会看到 C 状态 C3,但使用此驱动程序时它不存在,因此我可能需要进一步研究这一点。

我设法从 2009 年 Intel 演示文稿中找到了一张有关 C 状态(即深度断电)之间转换的幻灯片:

深度掉电技术进入/退出

总之,事实证明intel_idle驱动程序中缺乏 Core 2 支持并没有真正的原因。现在很清楚,“Core 2 Duo”的原始存根代码仅处理 C 状态 C1 和 C2,这acpi_idle比同时处理 C 状态 C3 的函数效率要低得多。一旦我知道去哪里寻找,实施支持就很容易了。非常感谢有用的评论和其他答案,如果亚马逊正在倾听,您就知道将支票发送到哪里。

本次更新已致力于github。我很快就会通过电子邮件将补丁发送到 LKML。

更新: 我还挖到了一个Socket T/LGA775艾伦代尔康罗) Core 2 Duo E2220,属于系列 6,型号 15,因此我也添加了对此的支持。该模型缺乏对C状态C4的支持,但支持C1/C1E和C2/C2E。这也适用于其他基于 Conroe 的芯片(E4xxx/E6xxx)以及可能所有 Kentsfield 和 Merom(非 Merom-L)处理器。

更新:我终于找到了一些MWAIT调优资源。这功率与性能写和这个更深的 C 状态和增加的延迟博客文章都包含一些有关识别 CPU 空闲延迟的有用信息。不幸的是,这仅报告那些编码到内核中的退出延迟(但有趣的是,仅报告处理器支持的那些硬件状态):

# cd /sys/devices/system/cpu/cpu0/cpuidle
# for state in `ls -d state*` ; do echo c-$state `cat $state/name` `cat $state/latency` ; done

c-state0/ POLL 0
c-state1/ C1 3
c-state2/ C1E 10
c-state3/ C2 20
c-state4/ C2E 40
c-state5/ C3 20
c-state6/ C4 60
c-state7/ C4E 100

更新:一位英特尔员工最近发表了一篇文章详细说明intel_idleMWAIT 状态。

答案2

我怀疑这可能只是一个机会和成本的例子。当intel_idle添加时,似乎已经计划支持 Core 2 Duo,但它从未完全实现——也许当英特尔工程师开始考虑它时,它已经不再值得了。这个等式相对复杂:intel_idle需要提供足够的好处acpi_idle以使其值得在这里支持,在CPU上将看到足够数量的“改进”内核......

作为来源绝地回答说,驱动程序不排除所有系列 6。intel_idle初始化检查 CPUCPU型号列表,基本上涵盖了从 Nehalem 到 Kaby Lake 的所有微架构。约克菲尔德比那更古老(而且显着不同——尼黑勒姆与它之前的建筑有很大不同)。 family 6测试仅影响是否打印错误信息;它的作用只是错误消息只会显示在 Intel CPU 上,而不是 AMD CPU 上(Intel 系列 6 包括自 Pentium Pro 以来的所有非 NetBurst Intel CPU)。

要回答您的配置问题,您可以完全禁用intel_idle,但保留它也可以(只要您不介意警告)。

答案3

是否有更合适的方法来配置内核以获得该系列处理器的最佳 CPU 空闲支持(除了禁用对 intel_idle 的支持之外)

您已启用 ACPI,并且已检查 acpi_idle 是否正在使用。我真诚地怀疑您是否错过了任何有用的内核配置选项。您可以随时检查powertop可能的建议,但您可能已经知道了。


这不是答案,但我想格式化它:-(。

查看内核源代码,当前的 intel_idle 驱动程序包含一个测试,专门从驱动程序中排除 Intel 家族 6。

不,它没有:-)。

id = x86_match_cpu(intel_idle_ids);
if (!id) {
    if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
        boot_cpu_data.x86 == 6)
        pr_debug(PREFIX "does not run on family %d model %d\n",
            boot_cpu_data.x86, boot_cpu_data.x86_model);
    return -ENODEV;
}

if语句不排除 Family 6。相反,该if语句在启用调试时提供一条消息,表明 . 不支持此特定的现代 Intel CPU intel_idle。事实上,我当前的 i5-5300U CPU 是 Family 6,它使用intel_idle.

排除你的CPU的是表中没有匹配项intel_idle_ids

我注意到这个实现了该表的提交。它删除的代码有一个switch语句。这使得很容易看出最早的模型 intel_idle 已经实现/成功测试/无论是 0x1A = 26。 https://github.com/torvalds/linux/commit/b66b8b9a4a79087dde1b358a016e5c8739ccf186

答案4

又一年了,这些旧机器越来越少,但仍然没有内核对空闲状态的支持。我以与上面类似的方式定制了一个内核,并在核心温度和功耗方面得到了有用的下降。以前,空闲时核心温度约为 60°C,自定义 intel_idle 时核心温度约为 45°C。

我在 intel_idle.c 中使用了稍微不同的配置。我设置了禁用 C1E 提升标志:C1E 是每当处理器进入 C1 时通常会自动达到的状态(如果在 BIOS 中配置)。 intel_idle 在所有情况下都会禁用此功能,并将 C1E 视为单独的 C 状态,主要是为了避免处理器意外陷入可能导致 QoS 问题的延迟状态(请注意,这意味着 max_cstate 比您预期的高 1,因为 2 是C1E)。 C2E 状态类似,但没有在 intel_idle 中禁用或单独处理,因此我将其完全排除在配置之外。 BIOS 通常有一个选项可以启用或禁用自动升级到此状态,因此您可以在 BIOS 中禁用它,在 intel_idle 中启用它,并且可能会获得更好的结果,但我没有尝试过。

这是在 E2180 上进行的,因此没有高于 C2/C2E 的状态,但主要收益似乎来自第一个空闲状态。我有一台更旧的 Pentium 4,Linux 仅支持 C1,这使得核心温度降低了 10-15C。使用 Core i7 进行的实验显示,启用 C3 或 C6 时,温度仅略有额外下降,尽管您可能认为节省电池仍然值得。我还没有发现如上所示配置的延迟有任何明显的性能问题,但无论如何它并不完全是一台硬核游戏机。

相关内容