微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

调试内核 ECC 清理 ARM v7 Cyclone V SOC

如何解决调试内核 ECC 清理 ARM v7 Cyclone V SOC

我是一名硬件工程师,负责使用 Altera intel 的 Cyclone V SX SOC FPGA 开发新硬件。

我刚刚完成了我的 DDR3-800 内存时序验证(是的,它是一个旧芯片)。

我试图通过将数据位短接到地来证明 ECC 内存正常工作,这是验证硬件和软件处理位错误的常见做法。

然而,当我将 D1 短接至地时,内核恐慌了。

这是“decode_stacktrace.sh”解码输出的顶部

(注意:最上面一行来自我添加到 Altera_EDAC 驱动程序中的一个 printk)

[ 1299.870164] EDAC: [226 Correctable errors @ 0x000E33C4]
[ 1299.876892] EDAC MC0: 184 CE soc:sdramedac on mc#0csrow#0channel#0 (csrow:0 channel:0 page:0x6a3 offset:0xb9c grain:8 syndrome:0x0)
[ 1299.891822] Unable to handle kernel paging request at virtual address c06a3b9c
[ 1299.899021] pgd = b6c6b929
[ 1299.901724] [c06a3b9c] *pgd=0061940e(bad)
[ 1299.905736] Internal error: Oops: 80d [#1] SMP ARM
[ 1299.910515] Modules linked in:
[ 1299.913567] cpu: 0 PID: 0 Comm: swapper/0 Not tainted 5.11.0-wtec #5
[ 1299.919903] Hardware name: Altera SOCFPGA
[ 1299.923900] PC is at edac_raw_mc_handle_error (./arch/arm/include/asm/edac.h:26 drivers/edac/edac_mc.c:816 drivers/edac/edac_mc.c:938 drivers/edac/edac_mc.c:1010) 
[ 1299.929301] LR is at __kmap_local_page_prot (mm/highmem.c:542) 
[ 1299.934344] pc : lr : psr: 000f0193 
[ 1299.940587] sp : c0e01b70  ip : c0e01b58  fp : c0e01bd4
[ 1299.945792] r10: 00000000  r9 : c0e01c10  r8 : ef7f9000
[ 1299.950998] r7 : 00000000  r6 : 000006a3  r5 : 00000b9c  r4 : 00000008
[ 1299.957500] r3 : c06a3b9c  r2 : c06a3ba4  r1 : ebfb755f  r0 : c06a3000
[ 1299.964003] Flags: nzcv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment none
[ 1299.971201] Control: 10c5387d  Table: 02b0004a  DAC: 00000051
[ 1299.976924] Process swapper/0 (pid: 0,stack limit = 0x10d9740f)
[ 1299.982911] Stack: (0xc0e01b70 to 0xc0e02000)

我通过查看 linux 内核源代码对此进行了跟踪。这是我认为正在发生的事情:

  1. 我将 D1 短接到地。
  2. ECC 启动并修复该位,触发中断。
  3. 在这种情况下,我对 D1 信号的轻刷会导致 226 个可纠正错误
  4. Altera ECC 驱动程序处理中断、收集信息并将所述信息返回给 ECC 管理器。
  5. ECC 管理器尝试使用位于“edac.h”中的一些内联程序集来清理受影响的内存,如下所示:
static inline void edac_atomic_scrub(void *va,u32 size)
{
#if __LINUX_ARM_ARCH__ >= 6
    unsigned int *virt_addr = va;
    unsigned int temp,temp2;
    unsigned int i;

    for (i = 0; i < size / sizeof(*virt_addr); i++,virt_addr++) {
        /* Very carefully read and write to memory atomically
         * so we are interrupt,DMA and SMP safe.
         */
        __asm__ __volatile__("\n"
            "1: ldrex   %0,[%2]\n"
            "   strex   %1,%0,[%2]\n"
            "   teq %1,#0\n"
            "   bne 1b\n"
            : "=&r"(temp),"=&r"(temp2)
            : "r"(virt_addr)
            : "cc");
    }
#endif
}

#endif
  1. 代码运行并在某些时候遇到非法虚拟地址并触发错误:“无法处理虚拟地址 c06a3b9c 处的内核分页请求”

更新:我已经确定第一个地址会导致 oops 并且即使有很多错误,我捕获的示例的大小(在上面的之后)只有 8 长。

这段代码太不符合我的要求了。我希望有经验的人可以成为我的老师,告诉我如何去做。

此时我唯一的选择是尝试查看内核如何将硬件的物理地址重新映射到虚拟内存中。我想这就是问题所在。

任何帮助将不胜感激。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。