基于 ARM 的设备上 Prefetch Abort 错误的常见原因是啥?

Posted

技术标签:

【中文标题】基于 ARM 的设备上 Prefetch Abort 错误的常见原因是啥?【英文标题】:What are the common causes of Prefetch Abort errors on ARM-based devices?基于 ARM 的设备上 Prefetch Abort 错误的常见原因是什么? 【发布时间】:2018-10-09 12:08:28 【问题描述】:

我的 C 程序在裸机 Raspberry Pi 3B+ 上运行。它工作正常,除了我得到 CPU 本身报告为 Prefetch Abort 的随机冻结。该设备可能会正常工作数小时,然后突然崩溃。它在崩溃之前没有做任何特别的事情,所以它是不可预测的。

发生此错误时,FS 寄存器 (FSR) 设置为 0xD,这表明这是一个权限错误:http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0087e/Cihhhged.html

其他寄存器:FAR 为 0xE80000B6,LR 为 0xFFFFFFFF,PC 为 0xE80000B6,PSR 为 0x200001F1

我的程序使用 FIQ 和 IRQ 中断,并使用所有四个 cpu 内核。

我在这里不要求具体调试,因为深入了解细节太复杂了,但是您知道发生预取错误的常见原因吗?

【问题讨论】:

FARPC 是 ARM 指令(不是真实地址),而 LR 是一个疯狂的值。这表明堆栈溢出(或至少是问题),以及您似乎处于FIQ 模式?您是否为FIQ 设置了堆栈?这可能再次与内核堆栈溢出有关,FSR 寄存器也是如此。例如,Linux 通过 8k 页面堆栈/TCB 将“任务控制块”作为掩码,如果这种溢出/不足流动,代码将获取垃圾 MMU (mm) 结构和错误的返回值,例如模式和 PC 值等. 有趣,我记得我的程序在早期的开发阶段根本不工作,它只有在我降低一些缓冲区的大小时才有效——这些缓冲区是在堆栈上分配的。直到你的消息我才想到。只需执行“char *buffer=new char[SIZE]”而不是“char *buffer[SIZE]”就足以释放一些堆栈空间并使用堆代替吗? IRQ 用于与 I2S 设备交互,FIQ 用于处理串行输入。我没有尝试将它与 IRQ 一起使用。我没有为 FIQ 设置任何特殊堆栈,因为我使用了一个裸机框架,它为我做了一些抽象工作 当然,char *buffer=new char[SIZE],但这可能会泄漏。尺寸是固定的吗?某些库函数(如new)不能在中断中可靠地使用。您必须在其他地方执行此操作。 new 和所有堆管理都需要“原子”运行。如果您的主线执行new 而中断执行new,您可能会偶尔崩溃; new 管理的列表/存储桶会混淆。您应该在中断中限制 C/C++ 库调用。 memset() strncat() 等都可以,但其他的不多。 我已经根据这些 cmets 和我的答案下方的一个扩展了我的答案 - 希望它会有所帮助。 【参考方案1】:

鉴于您的代码是多线程的(实际上是多核的)并且崩溃是不可预测的,我想说预取中止几乎肯定是由于比赛导致的内存损坏。

如果您能找出生成中止的位置,这可能会有所帮助。但是,像这样的错误可能非常难以追踪;如果代码总是在同一个地方崩溃,那么这可能会有所帮助,但即使它确实如此,您也可以找出哪个地址正在遭受损坏,监控该地址是否存在恶意写入,而不会影响程序的时序(以及因此bug) 基本上是不可能的。

很可能根本原因是缓冲区溢出,尤其是考虑到上面的 cmets。实际上,您应该事先知道缓冲区需要多大,然后将它们设置为该大小。如果您使用的任何算法都不能保证它使用的缓冲区数量的限制,您应该添加对缓冲区执行运行时检查并做出适当响应的代码(可能是一个很好报告的错误,以便您知道哪个缓冲区溢出) .使用堆是可以的,但将大缓冲区声明为 static 更快且无泄漏,前提是包含缓冲区的函数是不可重入的。

如果混合中也存在数据访问竞争,请注意,您需要的不仅仅是数据屏障指令来解决这些问题。数据屏障指令仅解决与未决内存事务相关的一致性问题。它们不会阻止共享数据的寄存器缓存(您需要 volatile 关键字)或同时读取-修改-写入竞争(您需要互斥机制,由您使用的任何框架或家庭提供- 使用 armv7 上的 STREXLDREX 指令酿造)。

【讨论】:

当内核使用数据内存屏障完成工作时,我确保读/写区域是正确的(它是指令“mcr p15, 0, %0, c7, c10, 5” )。一些缓冲区由核心 #0 设置,它告诉其他核心它们可以开始工作,然后等待它们完成后再获取结果。我看到还有其他类型的障碍:数据同步障碍,指令同步障碍......(infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/…)也许需要它们来确保完全一致?

以上是关于基于 ARM 的设备上 Prefetch Abort 错误的常见原因是啥?的主要内容,如果未能解决你的问题,请参考以下文章

在 Windows 上使用自定义交叉编译器为 arm 编译 v8

ios touchesBegan 未在 arm64 设备上调用

WinCE: prefetch abort

基于ARM的智能灯光控制系统设备管理

arm设备上的k8s仪表板(v2.0.0-betaX)

一个基于Qt的截屏程序