2

在 linux 内核空闲循环内部,对于相当多的架构(SH、ARM、X86 等。afaik)有以下几行:

if(cpuidle_idle_call())
    pm_idle();

我的疑问:

至少对于 ARM,默认的 pm_idle 函数由 WFI(等待中断)指令组成,但令人困惑的是,中断随后被禁用并在 WFI 指令执行后启用,当中断发生时 CPU 如何从 WFI 恢复联机禁用?

我尝试在各种版本的 linux 中搜索我的答案,但相关代码自 2.6.32(我提到的最后一个版本)以来没有变化,所以我更有可能遗漏了一些东西。

4

2 回答 2

3

即使中断被禁用,WFI 也会唤醒,但 ARM 内核在再次启用中断之前不会接收到中断。

于 2012-12-06T20:52:50.350 回答
2

cpuidle_idle_call() 返回“错误”有几个原因。

  1. 没有为 CPU 安装 cpuidle 驱动程序。
  2. cpuidle 被禁用
  3. 驱动程序无法初始化

缺少驱动程序是最有可能发生的事情。但是在这种情况下,内核仍然必须以某种方式燃烧循环。所以它调用了 pm_idle,它在 arm 上默认映射到 default_idle。内核在那里检查 cpu 是否注册了 arm_pm_idle,可以将其视为轻量级 cpuidle 驱动程序。如果一切都失败了,它将回退到 cpu_idle,它必须被实现并且大部分时间会耗尽写入缓冲区并进入 WFI 模式。

整个过程中有很多冗余,但这允许开发人员编写简单的空闲驱动程序,并在必要时将它们变成完整的 cpuidle 驱动程序。

问题是不同的 SoC 提供不同的功能。例如,在 kirkwood 上,空闲驱动程序会将 DDR 设置为自刷新模式,然后再切换到 wfi 模式以保护一些电源。从理论上讲,它也可以扩展为将 cpu 切换到较慢的时钟。

对于你的另一个问题。禁用中断只会阻止 cpu 触发中断处理程序,它仍然需要注册中断发生,否则您可能会丢失数据。因此处理程序被禁用,但传入的中断仍会触发 WFI 的唤醒功能。

于 2012-12-07T12:54:03.900 回答