2

在 Linux 内核中,更准确地说是 3.9- rc6上的 /arch/arm/mach-exynos/cpuidle.c,这些行读取

static unsigned int g_pwr_ctrl, g_diag_reg;

static void save_cpu_arch_register(void)
{
    /*read power control register*/
    asm("mrc p15, 0, %0, c15, c0, 0" : "=r"(g_pwr_ctrl) : : "cc");
    /*read diagnostic register*/
    asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");
    return;
}

在研究了这个问题之后,这似乎是gcc 内联汇编。考虑到它是一个关键组件,因此asm正在阅读它,因为它要么

  1. 更快,因此更高效
  2. 在 C 中不可用

我在学习汇编时查看了ARM 手册,但由于它的三个字母长度MCR,我可以判断它是协处理器。MCR内联汇编似乎访问电源控制寄存器并将结果(来自寄存器)保存到第一行的无符号整数中(我希望在某个时候调用)。

关于电源控制寄存器,arm手册列出,

  • 实现 Cortex-A9 处理器的时钟延迟
  • 动态时钟门控。

我无法理解为什么需要这样做,这可以在函数中动态访问。

最后,ARM 手册列出了 32 位宽寄存器的设计。基本时钟似乎设置在那里,我们是在从空闲上下文进程启动时读取这个吗?

我也发现了一个类似的问题——这也可能对你有所帮助。

4

1 回答 1

4

您的问题确实缺乏重点,请考虑更新它。我假设您正在尝试了解 Linux 内核中的exynos挂起/恢复机制。

为什么选择内联汇编

...这似乎是gcc 内联汇编。考虑到它是一个关键组件,asm 正在读取它,因为它要么
a) 更快,因此更高效;
b) 在 C 中不可用

我们选择选项b,没有办法在Cmcr中表达/ 。mrc

内联破坏者列表

第二, ...: : "cc");

这是一个gcc破坏列表。它表示条件代码将被指令更改。这可能只是为了确保gcc决定不丢弃该指令。您可以在gcc 手册中阅读更多内容。

这是在做什么

我无法理解为什么需要这样做,这可以在函数中动态访问。

您需要查看的部分是exynos4_enter_core0_aftr(). 这同时使用save_cpu_arch_register()restore_cpu_arch_register()。因此,有一组双重函数,我们注意到这些值存储在globals中。另一个需要注意的是cpu_suspend(0, idle_finisher);. 这个函数告诉 Linux cpu被挂起,然后调用cpu_do_idle();通常是 ARM WFI等待中断)指令。这会使 CPU在该指令处冻结,直到触发启用的中断。全速暂停 CPU 时钟的问题是,这会浪费一些电流/功率。通常,在此模式下,SDRAM 和平台时钟可能会自动进入低功耗状态。

您必须查阅 CPU/SOC 上的数据表以了解更多信息。然而,回到问题。这种低功耗模式很可能会破坏/更改这些协处理器寄存器,因此save_cpu_arch_register()需要restore_cpu_arch_register()确保它们保持调用前的状态。该代码可能会在exynos4_enter_core0_aftr(). 它们确实需要保存和恢复,否则 CPU 可能会以奇怪的电源/电压/时钟恢复。也可能cpu_do_idle()是您的机器覆盖了它,并且它正在更改这些寄存器。

简单地说,这个函数是保存一些状态,当 CPU 进入挂起等待中断模式时会被破坏。

于 2013-04-15T01:05:12.280 回答