【发布时间】: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 是“启动”代码,因此可能是芯片已经在使用该寄存器进行操作,这就是它切换的原因。