Memory 调试内核ECC清理。臂v7旋风分离器V SOC

Memory 调试内核ECC清理。臂v7旋风分离器V SOC,memory,kernel,armv7,intel-fpga,soc,Memory,Kernel,Armv7,Intel Fpga,Soc,我是一名硬件工程师,使用Altera intel的Cyclone V SX SOC FPGA开发新硬件 我刚刚完成验证我的DDR3-800内存计时(是的,它是一个旧芯片) 我试图通过将数据位接地短路来证明ECC内存正常工作,这是验证硬件和软件处理位错误的常见做法 然而,当我将D1短路到地上时,内核惊慌失措 下面是“decode_stacktrace.sh”解码输出的顶部部分 (注:顶行来自添加到Altera_EDAC驱动程序的printk I) 我通过查看linux内核源代码跟踪了这一点。以下是

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

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

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

然而,当我将D1短路到地上时,内核惊慌失措

下面是“decode_stacktrace.sh”解码输出的顶部部分

(注:顶行来自添加到Altera_EDAC驱动程序的printk I)

我通过查看linux内核源代码跟踪了这一点。以下是我认为正在发生的事情:

  • 我对地短路
  • ECC启动并修复位,触发中断
  • 在这种情况下,针对D1信号的光刷会导致226个可纠正错误
  • Altera ECC驱动程序处理中断,收集信息并将所述信息返回给ECC管理器
  • ECC管理器尝试使用位于“edac.h”中的某些内联程序集清除受影响的内存,如下所示:
  • static inline void edac_atomic_scrub(void*va,u32大小)
    {
    #如果=6
    无符号整数*virt\u addr=va;
    未签名的int-temp,temp2;
    无符号整数i;
    对于(i=0;i
  • 此代码运行并在某个点命中非法虚拟地址并触发错误:“无法处理虚拟地址c06a3b9c处的内核分页请求”
  • 更新:我已经确定第一个地址导致了oops,并且即使有很多错误,我捕获的示例(在上面的一个之后)的大小也只有8个长

    这段代码太离谱了。我希望有一个有经验的人能成为我的老师,告诉我该怎么做

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

    任何帮助都将不胜感激

    [ 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)
    
    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