当前位置:网站首页>【Note17】PECI(Platform Environment Control Interface)

【Note17】PECI(Platform Environment Control Interface)

2022-07-05 22:42:00 码农编程录


1.模式和命令介绍

peci是 intel提供的私有协议,openbmc是由intel授权的,其他不授权是不能用的。硬件上是由一根线,不像i2c是有2根线。peci1.1只支持CPU温度,2.0增加支持MSR相关寄存器,3.0增加支持读intel的PCI配置。PCI主要根据intel的BDF【Bus/Device/Function (PCI technology)】确定读pcie设备里的寄存器地址。如下peci有两个请求方式:AMIbmc是A,obmc用的B。
在这里插入图片描述
1.PCH模式:cpu一般有一个ME地址挂在smlink上,-b就是挂的bus号(简单理解就是i2c的bus号),-t是挂的地址,一般都是0x2c。BMC通过IPMI给ME发一个raw date命令,ME再发pcie命令到cpu。实际是ME不停给cpu发一些peci命令来获取它需要的数据,它把这些数据做一个缓存在它自己内部,bmc向它访问数据的话,me会直接把缓存的数据回到bmc上,如下raw 6 1 是读ME的版本号。
在这里插入图片描述
2.PECI模式:obmc上有一个peci-util命令,通过这命令直接访问到cpu内部,peci-util虽说是二进制命令,但是底层调用libpeci库(https://github.com/openbmc/libpeci.git),通过libpeci 访问 /dev/peci-0节点进行IO操作即那根数据线发peci指令。Openbmc中使能PECI需要同时修改kernel.cfg和image.bb文件:在image.bb IMAGE_INSTALL 变量中追加”peci-util-v2”来安装peci-util 命令,在kernel.cfg中增加CONFIG_PECI相关宏来使能PECI驱动,如下图:
在这里插入图片描述
如下peci3.0支持的方式,如下10个命令也不是所有cpu平台都支持,具体还要看cpu手册,因为cpu平台功能划分比较细,不是所有平台都支持所有功能,前5个全平台支持。
在这里插入图片描述

2.通过peci读cpu温度

cpu温度使用RdPkgconfig()命令(read page config),通过peci读到cpu的最大值(tjmax)和一个偏移量(Tcontrol)(距离当前设定的最大值还差多少值),这两个的差值作为cpu实际温度。如下在intel芯片手册中:
在这里插入图片描述
如下6,7是两个字节。
在这里插入图片描述
在这里插入图片描述
0x10(十六进制) = 16(十进制)。info是偏移量。如下0x30是cpu的id,第一个cpu就是0x30,cpu2的话就是0x31,第一个05写长度,oxa1表示现在是read config操作(固定的)。
在这里插入图片描述

3.通过peci读DIMM温度

DIMM温度不涉及偏差多少,直接读实时温度,也是用RdPkgconfig()命令。DIMM每个channel可以插两个DIMM即DIMM0和DIMM1。14对应0x0E,$1对应传入0或者1,后面就是十六进制换算。
在这里插入图片描述
在这里插入图片描述

4.通过peci读MSR

客户给的不止msr,还有pcie寄存器一些读法,lerrLoggingReg通过查cpu手册,发现是pcie寄存器,BDFO四个变量才能确定一个地址,带外方式用RdPCIConfigLocal()读PCIE寄存器。如下地址换算值就是三个字节地址(根据BDF获得)。
在这里插入图片描述
在这里插入图片描述
如下就是读cpu上pcie寄存器都能用带外方式读了,临终遗言需要读lerrLoggingReg和MCerrLoggingReg寄存器都是一样这样读取。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如上四个值或(有1为1)一下得到三个字节值。
在这里插入图片描述
PTSTS(Power And Reset)是cpu内部寄存器,带外方式读不了。如下C语言也可以发送PECI命令,参数用数组传入。
在这里插入图片描述
MSR(Model Specific Register)是x86架构中的概念,指的是在x86架构处理器中,一系列用于控制CPU运行、功能开关、调试、跟踪程序执行、监测CPU性能等方面的寄存器。MSR使用RdIAMSR()命令

如下是所有msr寄存器,0-15个物理核,项目是0-4个物理核相当于5个cpu,逻辑核心是0-7,现在项目只读物理核。我们一般只负责读出寄存器值,具体解析bios做,我们数据给他,他们自己去查。
在这里插入图片描述
在这里插入图片描述

# dumplwt.sh
. /usr/local/bin/openbmc-utils.sh
renice -20 -p $$ >/dev/null 2>&1

do_msr_deal()
{
    
echo
echo CPU MSR DUMP:
echo ==============
echo
echo "MCA_ERR_SRC_LOG"
peci-util 0x30 0x05 0x05 0xA1 0x00 0x00 0x05 0x00  
echo
echo "IerrLoggingReg"
peci-util 0x30 0x05 0x05 0xE1 0x00 0xA4 0x50 0x18
echo
echo "MCerrLoggingReg"
peci-util 0x30 0x05 0x05 0xE1 0x00 0xA8 0x50 0x18
echo
echo "********************************************************"
echo "* MC index 00 *"
echo "********************************************************"
echo " IA32_MC0_CTL, ProcessorID from 0 to 4 "
peci-util 0x30 0x05 0x09 0xB1 0x00 0x00 0x00 0x04   # 倒数第三个是ProcessorID 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x01 0x00 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x02 0x00 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x03 0x00 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x04 0x00 0x04 

echo " IA32_MC0_CTL2, ProcessorID from 0 to 4 "
peci-util 0x30 0x05 0x09 0xB1 0x00 0x00 0x80 0x02 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x01 0x80 0x02 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x02 0x80 0x02 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x03 0x80 0x02 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x04 0x80 0x02 

echo " IA32_MC0_STATUS, ProcessorID from 0 to 4 "
peci-util 0x30 0x05 0x09 0xB1 0x00 0x00 0x01 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x01 0x01 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x02 0x01 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x03 0x01 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x04 0x01 0x04 

echo " IA32_MC0_ADDR, ProcessorID from 0 to 4 "
peci-util 0x30 0x05 0x09 0xB1 0x00 0x00 0x02 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x01 0x02 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x02 0x02 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x03 0x02 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x04 0x02 0x04 

echo " IA32_MC0_MISC, ProcessorID from 0 to 4 "
peci-util 0x30 0x05 0x09 0xB1 0x00 0x00 0x03 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x01 0x03 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x02 0x03 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x03 0x03 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x04 0x03 0x04 

echo "********************************************************"
echo "* MC index 01 *"
echo "********************************************************"
echo " IA32_MC1_CTL, ProcessorID from 0 to 4 "
peci-util 0x30 0x05 0x09 0xB1 0x00 0x00 0x04 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x01 0x04 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x02 0x04 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x03 0x04 0x04 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x04 0x04 0x04 

echo " IA32_MC1_CTL2, ProcessorID from 0 to 4 "
peci-util 0x30 0x05 0x09 0xB1 0x00 0x00 0x81 0x02 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x01 0x81 0x02 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x02 0x81 0x02 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x03 0x81 0x02 
peci-util 0x30 0x05 0x09 0xB1 0x00 0x04 0x81 0x02 

do_peci_select 7 #peci通道提前手动选择,在openbmc-utils.sh里source了一些borad.sh一些共用的脚本接口
do_msr_deal
do_peci_select 8
do_msr_deal
# 如下0x400是MC0,0x404是MC1....
IA32_MCi_CTL=(0x400 0x404 0x408 0x40c 0x410 0x414 0x418 0x41c 0x420 0x424 0x428)

mce_log(){
    
    modprobe msr
    mcelog --daemon  # 手动启动mcelog。查看mcelog日志:vim /var/log/mcelog
    i=${
    #IA32_MCi_CTL[@]}
    echo "read IA32_MCi_CTL register begin ${IA32_MCi_CTL[*]}"
    for ((cpu=0;cpu<8;cpu++));do
    echo "cpu $cpu read IA32_MCi_CTL register"
        for ((row=0;row<i;row++));do
            rdmsr -p   $cpu  ${IA32_MCi_CTL[row]}   -x
        done
    done
    echo "read IA32_MCi_CTL register end"
}
mce_log

5.rdmsr读CPU温度

原方案从 /sys/class/hwmon/下读取CPU温度,该目录下有hwmon0、hwmon1、hwmon2三个文件,其中hwmon2目录下有记录CPU温度的文件temp_input,从该文件能直接读CPU温度。后发现temp_input文件有时在hwmon1下,有时在hwmon2下,不同环境位置不一样。不想再用直接读文件获取温度的方法,查看CPU手册找到了读寄存器获取温度的方法,该方案比较稳定。

rdmsr方案:intel cpu有以下两个寄存器可供实现读CPU温度。CPU温度 = TCC_ACTIVATION_TEMP - TEMPERATURE。
0x1A2:寄存器的bit23-16记录了TCC_ACTIVATION_TEMP值,改值可理解为CPU触发调温手段的阈值,该阈值出厂时设置;
0x19C:寄存器的bit22-16记录了 TEMPERATURE值,这个值是CPU温度相对于TCC_ACTIVATION_TEMP的温度值;

#define TEMP_TARGET_MSR_REG (0x1a2)
#define TEMP_STATUS_MSR_REG (0x19c)
static int get_cpu_msr_temp_info(void)  //接口直接返回CPU实际温度
{
    
    int ucTempOffset;
    int ucTempActivation;
    int dwValh=0,dwVall=0;

    rdmsr(TEMP_TARGET_MSR_REG, dwVall, dwValh);
    /*bit23-16*/
    dwVall &= 0x00FF0000;
    ucTempActivation = (dwVall>>16)&0xff;

    dwVall=0;
    dwValh=0;
    rdmsr(TEMP_STATUS_MSR_REG, dwVall, dwValh);
    /*bit22-16*/
    dwVall &= 0x007F0000;
    ucTempOffset = (dwVall>>16)&0xff;

    return (ucTempActivation-ucTempOffset);
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

原网站

版权声明
本文为[码农编程录]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_43435675/article/details/124772814