1、背景介绍
为了排查全国产飞腾计算模块的一个外场问题,需要验证飞腾2000+/64核这个处理器的DDR控制器是否支持ECC功能,即在异常情况下能纠错。ECC纠错原理如下,目前飞腾2000+/64 DDR控制器就是纠一检二:
2、寄存器说明
目前飞腾提供了2000+/64这款处理器的关于ECC的寄存器信息,如下:
通过读取错误计数器寄存器能够知道到底ECC纠了多少错误,该寄存器详细描述如下:
3、测试脚本说明
可以使用测试脚本读取ECC寄存器状态,该脚本内容如下:
#!/bin/bash
#FT-2000+64 寄存器读取
#错误寄存器读取
#间接地址寄存器 Size:32位 复位值:0x0 Offset: 0x000
LMU_ADDR_REG=0x80028780000
#间接数据寄存器 复位值:0x0 Offset: 0x008 Size:32位
LMU_DATA_REG=$LMU_ADDR_REG+8
LMU_REG_SEG_USR_BIT=0x0
LMU_REG_SEG_CTL_BIT=0x10000000
LMU_REG_SEG_PHY_BIT=0x20000000
#注:LMU_ADDR_REG的bit[29:28]为REG_SEG位,区别MUC内不同部件的寄存器:00:USR寄存器 01:CTL寄存器 10:PHY寄存器
#错误状态寄存器 Size:32位 复位值:0x0 Offset: 0x1a0
LMU_MCU_ERR_STA_REG=0x1a0
#描述: 错误记录使能寄存器 Size:32位 复位值:0xffffffff Offset: 0x1b0
LMU_MCU_LOG_ENA_REG=0x1b0
#错误使能寄存器 Size:32位 复位值:0x0 Offset: 0x1c0
LMU_MCU_ERR_ENA_REG=0x1c0
#中断使能寄存器 Size:32位 复位值:0x0 Offset: 0x1d0
LMU_MCU_INT_ENA_REG=0x1d0
#描述: 错误设置寄存器 Size:32位 复位值:0x0 Offset: 0x1e0
LMU_MCU_ERR_SET_REG=0x1e0
# 错误清除寄存器 Size:32位 复位值:0x0 Offset: 0x1f0
LMU_MCU_ERR_CLR_REG=0x1f0
#ECC 配置寄存器0 0x70
LMU_ECCCFG0=0X70
#ECC 配置寄存器1 0x74
LMU_ECCCFG1=0X74
#ECC 状态寄存器 0X78
LMU_ECCSTAT=0X78
#ECC 清除寄存器 0X7C
LMU_ECCCLR=0X7C
#错误计数器寄存器 0X80
LMU_ECCERRCNT=0X80
core_mask=`lscpu | awk NR==5 | cut -f 2 -d '-'`
#类型选择
function CHOSE_TYPE()
{
if [ $core_mask == 63 ];then
peu=2
echo "FT-2000+/64 64核版本"
elif [ $core_mask == 31 ]
then
peu=1
echo "FT-2000+/64 32核版本"
fi
}
#内存ecc错误寄存器获取
function MCU_ECC_ERROR_TEST()
{
let i=0
while [ $i -lt 8 ]
do
let "addr_base=LMU_ADDR_REG + i*0x10000"
let "data_base=$addr_base+8"
let "register=LMU_ECCCFG0|LMU_REG_SEG_CTL_BIT"
./mem write 4 $addr_base $register
./mem read 4 $data_base
LMU_ECCCFG0_NUM=`./mem read 4 $data_base | cut -f 6 -d ' '`
let "register=LMU_ECCCFG1|LMU_REG_SEG_CTL_BIT"
./mem write 4 $addr_base $register > /dev/null
./mem read 4 $data_base
LMU_ECCCFG1_NUM=`./mem read 4 $data_base | cut -f 6 -d ' '`
let "register=LMU_ECCSTAT|LMU_REG_SEG_CTL_BIT"
./mem write 4 $addr_base $register > /dev/null
./mem read 4 $data_base
LMU_ECCSTAT_NUM=`./mem read 4 $data_base | cut -f 6 -d ' '`
let "register=LMU_ECCCLR|LMU_REG_SEG_CTL_BIT"
./mem write 4 $addr_base $register > /dev/null
./mem read 4 $data_base
LMU_ECCCLR_NUM=`./mem read 4 $data_base | cut -f 6 -d ' '`
let "register=LMU_ECCERRCNT|LMU_REG_SEG_CTL_BIT"
./mem write 4 $addr_base $register > /dev/null
./mem read 4 $data_base
LMU_ECCERRCNT_NUM=`./mem read 4 $data_base | cut -f 6 -d ' '`
sleep 2
if [ $LMU_ECCERRCNT_NUM == 0x0 ]
then
echo "内存通道" $i "ECC 校验 状态正常"
echo " "
else
echo "内存通道" $i "ECC 校验 状态异常"
echo "*** ERROR ****"
fi
let i=i+1
echo " "
done
}
function TEST()
{
date
CHOSE_TYPE
echo "FT-2000+/64服务器错误寄存器"
date
#循环间隔时间读所有寄存器
for ((NUM=0;NUM<1000000;NUM++))
do
date
echo "*******间隔时间"$NUM*1 s"读错误相关寄存器*******"
echo " "
echo " "
#首次读所有寄存器
echo "******MCU_ECC_ERROR_TEST(内存ecc错误寄存器) *******"
MCU_ECC_ERROR_TEST
sleep 1
echo "等待中..."
sleep 1
done
}
TEST
echo "====Test Finished===="
脚本中会循环读取ECC各个寄存器状态信息,其中的mem为飞腾提供的底层可执行程序。
4、测试步骤
首先运行脚本,此时会打印ECC状态信息,无异常
8个通道的ECC错误寄存器校验正常,如下打印
******MCU_ECC_ERROR_TEST(内存ecc错误寄存器) *******
Write word 0x10000070 to 0x80028780000
Read word from 0x80028780008 result 0x4
Read word from 0x80028780008 result 0x2
Read word from 0x80028780008 result 0x0
Read word from 0x80028780008 result 0x0
Read word from 0x80028780008 result 0x0
内存通道 0 ECC 校验 状态正常
Write word 0x10000070 to 0x80028790000
Read word from 0x80028790008 result 0x4
Read word from 0x80028790008 result 0x2
Read word from 0x80028790008 result 0x0
Read word from 0x80028790008 result 0x0
Read word from 0x80028790008 result 0x0
内存通道 1 ECC 校验 状态正常
Write word 0x10000070 to 0x800287a0000
Read word from 0x800287a0008 result 0x4
Read word from 0x800287a0008 result 0x2
Read word from 0x800287a0008 result 0x0
Read word from 0x800287a0008 result 0x0
Read word from 0x800287a0008 result 0x0
内存通道 2 ECC 校验 状态正常
Write word 0x10000070 to 0x800287b0000
Read word from 0x800287b0008 result 0x4
Read word from 0x800287b0008 result 0x2
Read word from 0x800287b0008 result 0x0
Read word from 0x800287b0008 result 0x0
Read word from 0x800287b0008 result 0x0
内存通道 3 ECC 校验 状态正常
Write word 0x10000070 to 0x800287c0000
Read word from 0x800287c0008 result 0x4
Read word from 0x800287c0008 result 0x2
Read word from 0x800287c0008 result 0x0
Read word from 0x800287c0008 result 0x0
Read word from 0x800287c0008 result 0x0
内存通道 4 ECC 校验 状态正常
Write word 0x10000070 to 0x800287d0000
Read word from 0x800287d0008 result 0x4
Read word from 0x800287d0008 result 0x2
Read word from 0x800287d0008 result 0x0
Read word from 0x800287d0008 result 0x0
Read word from 0x800287d0008 result 0x0
内存通道 5 ECC 校验 状态正常
Write word 0x10000070 to 0x800287e0000
Read word from 0x800287e0008 result 0x4
Read word from 0x800287e0008 result 0x2
Read word from 0x800287e0008 result 0x0
Read word from 0x800287e0008 result 0x0
Read word from 0x800287e0008 result 0x0
内存通道 6 ECC 校验 状态正常
Write word 0x10000070 to 0x800287f0000
Read word from 0x800287f0008 result 0x4
Read word from 0x800287f0008 result 0x2
Read word from 0x800287f0008 result 0x0
Read word from 0x800287f0008 result 0x0
Read word from 0x800287f0008 result 0x0
内存通道 7 ECC 校验 状态正常
此时在硬件上短接某个通道DDR控制器的DQ信号,会报该通道ECC状态异常
比如这里短接了通道0的DDR控制器DQ7信号(MEM0_S4_DQ7),报通道0 ECC检验状态异常,能够看到错误计数在不停累加。
这个时候在系统下面跑memtester是不会报错的,因为只有一位错误,ECC能够纠正。
但此时又短接了通道0的DDR控制器另一路DQ信号(注意:必须要同一个通道,因为8个DDR控制器相互独立,每个通道都能独立进行单bitECC纠错,如果同时短接两路不同的通道DQ,也能进行正确纠错),导致这个该通道DDR控制器出现了两位错误,运行memtester将会导致系统崩溃重启,重启后能在crash日志中发现是因为内存错误导致。
5、结论
经过以上试验,可以表明飞腾2000+/64核处理器具备ECC校验能力,不过每个通道的DDR控制器只能纠正一位错误,如果同一个通道DDR控制器上出现两bit错误,那将导致系统异常。
在飞腾PBF内可以针对ECC功能进行打开或者关闭,可以通过读取ECC配置寄存器(0x70)最后两位进行判断,如下:
如果读出来为0x4那就是有ECC,如果读出来为0代表无ECC。