【问题标题】:Enable ARM errata in inline assembly在内联汇编中启用 ARM 勘误表
【发布时间】:2020-10-16 10:19:48
【问题描述】:

我正在尝试通过在驱动程序中启用勘误表的解决方法来了解 asm。这应该是可能的,因为内核代码是在特权世界中执行的。 (简约)代码如下所示。

unsigned int cp15c15 = 0, result = 0;
__asm__ volatile("mrc p15, 0, %0, c15, c0, 1" : "=r" (cp15c15));
cp15c15 |= (1<<22); /* Errata 845369 */
__asm__ volatile("mcr p15, 0, %0, c15, c0, 1" : "+r" (cp15c15));

这似乎有效,但是当我多次读取寄存器时,有时会得到一个未启用第 22 位的值。 (例如0x000001 而不是0x400001)。

char buf[10];
__asm__ volatile("mrc p15, 0, %0, c15, c0, 1" : "=r" (cp15c15));
sprintf(buf, "0x%.8x", cp15c15);
copy_to_user(buffer, buf, 10);

我认为我在 asm 通话中做错了什么。如果有人能告诉我为什么这只在 10% 的时间里有效,我真的很感激。 (Asm 有点酷)。

编辑:
来自原始 NXP 勘误说明的汇编代码:

MRC p15,0,rt,c15,c0,1
ORR rt,rt,#0x00400000
MCR p15,0,rt,c15,c0,1

编辑 2:
如果我在 ./linux/arch/arm/mm/proc-v7.S 中启用它,当我从我的驱动程序中读取它时,该位仍然设置。但是,如果我禁用它,似乎该位会不规则地关闭和打开。它似乎证实了该位何时设置。

【问题讨论】:

  • 您没有在第二个 asm 模板中引用 %1。您是否假设它将为"r" (cp15c15) 选择与"=r"(result) 相同的寄存器?因为这不能保证。使用类似"0"(cp15c15) 的匹配约束,或使用单个"+r" (cp15c15) 读/写操作数。
  • 顺便说一句,我认为这实际上是在启用 workaround 或缓解错误。勘误是硬件设计错误,您不想启用错误。
  • 感谢@PeterCordes 指出这一点。 +r 比我以前的干净得多,但它不能解决问题(我认为我犯了这个错误是因为试图让它工作)。另外,事实上,我并不想引入更多错误:-)
  • 好的,现在你的 asm 是理智的,应该可靠地做它想做的事情。也许勘误表本身解释了为什么如果不是手动设置,IDK 的位读取会发生变化。将其写为 1 具有导致行为改变的副作用当然是合理的。
  • 我认为它与内核完全启动后写入它有关。 proc-v4.S 中的 asm 是“启动”代码,因此可能是芯片已经在使用该寄存器进行操作,这就是它切换的原因。

标签: c assembly arm imx6


【解决方案1】:

如果计算机有多个处理器内核(如某些 i.MX 6 芯片),那么除非您安排运行所有处理器内核,否则它运行的处理器将由 Linux 调度程序随心所欲。

因此可能会在一个 CPU 上设置寄存器,然后如果在该 CPU 上运行检查,则会显示修改,但如果在不同 CPU 上运行检查,则会读取原始值。

【讨论】:

  • 处理器确实有多个核心。在接受您的答案之前,我想验证是否可以在所有内核上运行它,但我认为您提出了一个很好的论点。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多