RAS--APEI 报错解析流程(2)
RAS--APEI 报错解析流程(1)
除了APEI 中除了GHES会记录错误,在Post过程中的错误通常是通过BERT Table汇报
1.BERT
Boot Error Record Table is used to report unhandled errors that occurred in a previous boot,it is reported as a ‘one-time polled’type error source.
Bert 用于记录post 过程中产生的 error 以及UCE hang 重启 BIOS 错误状态未进行清除在下次重启扫描出的error
具体结构如图所示:
使用BERT 的header 通过section type 区分错误类型 对应到不同的错误结构 都是通过block error status addrss 链接
内存 pcie cpu的错误汇报信息结构体
使用IASL 解析BERT table:
BIOS 在Post 过程中去扫描pcie error 内存 error CPU error
NBIOErrorDetection 检测到错误 addbert ->GENERIC_PCIE_AER_ERR_ENTRY
MCAErrorDetection 检测到MCA Bank UMC 错误 addbert ->GENERIC_MEM_ERR_ENTRY
MCAErrorDetection 检测到MCA Bank PIE 错误 addbert ->GENERIC_PRO_ERR_ENTRY
CPU BERT OS 解析
内存OS 解析
PCIE OS 解析
Post过程中检测到多个BERT :有内存和CPU bank 的错误状态
BIOS 日志:两个MCA Bank 读取到错误MCA_Status
BERT Table: BIOS 汇报和OS 解析通过Boot Error Region Address 联系
Boot Error Region Address 对应到结构体
///
/// Generic Error Status Definition
///
typedef struct {
EFI_ACPI_6_2_ERROR_BLOCK_STATUS BlockStatus;
UINT32 RawDataOffset;
UINT32 RawDataLength;
UINT32 DataLength;
UINT32 ErrorSeverity;
} EFI_ACPI_6_2_GENERIC_ERROR_STATUS_STRUCTURE;
对于OS去打印HardWare error 只需要参考GHES 中的Error Block status 就会去打印 错误的GHES Table中的错误信息
typedef struct {
UINT32 UncorrectableErrorValid : 1;
UINT32 CorrectableErrorValid : 1;
UINT32 MultipleUncorrectableErrors : 1;
UINT32 MultipleCorrectableErrors : 1;
UINT32 ErrorDataEntryCount : 10;
UINT32 Reserved : 18;
} EFI_ACPI_6_2_ERROR_BLOCK_STATUS;
也就是当扫描到BlockStatus 存在错误状态 OS就会上报Hardware error 然后清除错误状态
后面接着结构体,后面的结构体会根据SectionType 接着内存/CPU/PCIE 的结构体
typedef struct {
UINT8 SectionType[16];
UINT32 ErrorSeverity;
UINT16 Revision;
UINT8 ValidationBits;
UINT8 Flags;
UINT32 ErrorDataLength;
UINT8 FruId[16];
UINT8 FruText[20];
UINT8 Timestamp[8];
} EFI_ACPI_6_2_GENERIC_ERROR_DATA_ENTRY_STRUCTURE;
/*
* Section type definitions, used in section_type field in struct
* cper_section_descriptor
*
* Processor Generic
*/
#define CPER_SEC_PROC_GENERIC \
GUID_INIT(0x9876CCAD, 0x47B4, 0x4bdb, 0xB6, 0x5E, 0x16, 0xF1, \
0x93, 0xC4, 0xF3, 0xDB)
/* Processor Specific: X86/X86_64 */
#define CPER_SEC_PROC_IA \
GUID_INIT(0xDC3EA0B0, 0xA144, 0x4797, 0xB9, 0x5B, 0x53, 0xFA, \
0x24, 0x2B, 0x6E, 0x1D)
/* Processor Specific: IA64 */
#define CPER_SEC_PROC_IPF \
GUID_INIT(0xE429FAF1, 0x3CB7, 0x11D4, 0x0B, 0xCA, 0x07, 0x00, \
0x80, 0xC7, 0x3C, 0x88, 0x81)
/* Processor Specific: ARM */
#define CPER_SEC_PROC_ARM \
GUID_INIT(0xE19E3D16, 0xBC11, 0x11E4, 0x9C, 0xAA, 0xC2, 0x05, \
0x1D, 0x5D, 0x46, 0xB0)
/* Platform Memory */
#define CPER_SEC_PLATFORM_MEM \
GUID_INIT(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \
0xED, 0x7C, 0x83, 0xB1)
#define CPER_SEC_PCIE \
GUID_INIT(0xD995E954, 0xBBC1, 0x430F, 0xAD, 0x91, 0xB4, 0x4D, \
0xCB, 0x3C, 0x6F, 0x35)
/* Firmware Error Record Reference */
Section Type=CPER_SEC_PROC_GENERIC 对应到 CPU 的错误结构体
对于GHES 的错误OS需要使用定时器,BERT 只需要在Kernel 加载时跑一边即可。
OS 下错误解析 ghes.c bert.c cper.c
GHES 驱动:
static struct platform_driver ghes_platform_driver = {
.driver = {
.name = "GHES",
},
.probe = ghes_probe,
.remove = ghes_remove,
};
ghes_init 加载GHES的驱动 ,系统下的解析策略和Notify 的结构体相关联,BIOS中会设置Notify Type ,Pollinterval
系统下扫描GHES 的驱动 是通过定时器周期性去扫描错误状态,Pollinterval 是定时器的参考时间
switch (generic->notify.type) {
case ACPI_HEST_NOTIFY_POLLED:
case ACPI_HEST_NOTIFY_EXTERNAL:
case ACPI_HEST_NOTIFY_SCI:
case ACPI_HEST_NOTIFY_GSIV:
case ACPI_HEST_NOTIFY_GPIO:
break;
case ACPI_HEST_NOTIFY_SEA:
if (!IS_ENABLED(CONFIG_ACPI_APEI_SEA)) {
pr_warn(GHES_PFX "Generic hardware error source: %d notified via SEA is not supported\n",
generic->header.source_id);
rc = -ENOTSUPP;
goto err;
}
break;
case ACPI_HEST_NOTIFY_NMI:
if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_NMI)) {
pr_warn(GHES_PFX "Generic hardware error source: %d notified via NMI interrupt is not supported!\n",
generic->header.source_id);
goto err;
}
break;
case ACPI_HEST_NOTIFY_LOCAL:
pr_warning(GHES_PFX "Generic hardware error source: %d notified via local interrupt is not supported!\n",
generic->header.source_id);
goto err;
timer_setup(&ghes->timer, ghes_poll_func, TIMER_DEFERRABLE);
ghes_proc(ghes);
ghes_read_estatus(ghes, 0);//-->apei_read(&buf_paddr, &g->error_status_address);
ghes_print_estatus
cper_estatus_print(pfx_seq, estatus);
这就对应到Dmesg 中的HardWare error 错误,就可以识别到错误的source id ,既可以大致定位错误信息来源 Source id = 512 对应到PCIE 错误
后续通过Section error type 定位到更加详细的信息
前面的信息都是来自于固定结构体
///
/// Generic Error Data Entry Definition
///
typedef struct {
UINT8 SectionType[16];
UINT32 ErrorSeverity;
UINT16 Revision;
UINT8 ValidationBits;
UINT8 Flags;
UINT32 ErrorDataLength;
UINT8 FruId[16];
UINT8 FruText[20];
UINT8 Timestamp[8];
} EFI_ACPI_6_2_GENERIC_ERROR_DATA_ENTRY_STRUCTURE;
static void
cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata,
int sec_no)
{
guid_t *sec_type = (guid_t *)gdata->section_type;
__u16 severity;
char newpfx[64];
if (acpi_hest_get_version(gdata) >= 3)
cper_print_tstamp(pfx, (struct acpi_hest_generic_data_v300 *)gdata);
severity = gdata->error_severity;
printk("%s""Error %d, type: %s\n", pfx, sec_no,
cper_severity_str(severity));
if (gdata->validation_bits & CPER_SEC_VALID_FRU_ID)
printk("%s""fru_id: %pUl\n", pfx, gdata->fru_id);
if (gdata->validation_bits & CPER_SEC_VALID_FRU_TEXT)
printk("%s""fru_text: %.20s\n", pfx, gdata->fru_text);
}
对于后续的结构体包括内存PCIE CPU 有着不同的结构体主要包括三个函数打印错误信息,通过匹配Section type Guid 判断
cper_print_proc_generic(); cper_print_mem(); cper_print_pcie()
if (guid_equal(sec_type, &CPER_SEC_PROC_GENERIC)) {
struct cper_sec_proc_generic *proc_err = acpi_hest_get_payload(gdata);
printk("%s""section_type: general processor error\n", newpfx);
if (gdata->error_data_length >= sizeof(*proc_err))
cper_print_proc_generic(newpfx, proc_err);
else
goto err_section_too_small;
} else if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) {
struct cper_sec_mem_err *mem_err = acpi_hest_get_payload(gdata);
printk("%s""section_type: memory error\n", newpfx);
if (gdata->error_data_length >=
sizeof(struct cper_sec_mem_err_old))
cper_print_mem(newpfx, mem_err,
gdata->error_data_length);
else
goto err_section_too_small;
} else if (guid_equal(sec_type, &CPER_SEC_PCIE)) {
struct cper_sec_pcie *pcie = acpi_hest_get_payload(gdata);
printk("%s""section_type: PCIe error\n", newpfx);
if (gdata->error_data_length >= sizeof(*pcie))
cper_print_pcie(newpfx, pcie, gdata);
else
goto err_section_too_small;
#if defined(CONFIG_ARM64) || defined(CONFIG_ARM)
} else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) {
struct cper_sec_proc_arm *arm_err = acpi_hest_get_payload(gdata);
printk("%ssection_type: ARM processor error\n", newpfx);
if (gdata->error_data_length >= sizeof(*arm_err))
cper_print_proc_arm(newpfx, arm_err);
else
goto err_section_too_small;
CPU错误信息结构体:
typedef struct _PLATFORM_PROC_ERR_SEC {
PROC_ERR_VALID_BIT ValidBits; ///< Validation Bits
UINT64 LocalApicID; ///< Processor APIC ID
UINT64 CpuIdInfo_EAX; ///< CPUID Information output value from EAX
UINT64 CpuIdInfo_EBX; ///< CPUID Information output value from EBX
UINT64 CpuIdInfo_ECX; ///< CPUID Information output value from ECX
UINT64 CpuIdInfo_EDX; ///< CPUID Information output value from EDX
UINT64 CpuIdInfo_PD1; ///< CPUID Information Padding 1
UINT64 CpuIdInfo_PD2; ///< CPUID Information Padding 2
} PLATFORM_PROC_ERR_SEC;
内存错误信息结构体:
typedef struct _PLATFORM_MEM_ERR_SEC {
MEM_ERR_VALID_BIT ValidBits; ///< Valid bits Bitmp
UINT64 ErrStatus; ///< Error Status
UINT64 PhyAddr; ///< Physical memory address of detected error
UINT64 PhyAddrMask; ///< Physical Error Address mask
UINT16 Node; ///< Node Number
UINT16 Card; ///< Card Number
UINT16 Module; ///< Module Number
UINT16 Bank; ///< Bank Number
UINT16 Device; ///< Device Number
UINT16 Row; ///< Row Number
UINT16 Column; ///< Column Number
UINT16 BitPosition; ///< Bit Position
UINT64 RequestorID; ///< Requestor ID
UINT64 ResponderID; ///< Responder ID
UINT64 TargetID; ///< Target ID
UINT8 MemErrType; ///< Memory Error Type
UINT8 Extend; ///< Extened
UINT16 RankNumber; ///< Rank Number
UINT16 CardHandle; ///< Card Number
UINT16 ModuleHandle;///< Module Number
} PLATFORM_MEM_ERR_SEC;
PCIE 错误信息结构体:
///
/// PCIE Error Section
///
typedef struct {
PCIE_ERR_VALID_BIT Validation; ///< Validation Bits
UINT32 PortType; ///< Port Type
UINT32 Revision; ///< Revision
UINT32 CommandStatus; ///< Command Status
UINT32 Reserved; ///< Reserved
DEVICE_ID DeviceId; ///< Device Id
UINT8 SerialNum[8]; ///< Serial Num
UINT32 BridgeCtrlStatus; ///< Bridge Control Status
CAP_STRUCTURE CapabilityStructure; ///< Capability Structure
AER_INFO AerInfo; ///< AER Info
} PCIE_ERROR_SECTION;
对于BERT 错误不需要使用定时器在Kernel 加载的时候会去初始化一遍BERT
BERT \drivers\acpi\apei\bert.c
bert_init -->
pr_info_once("Error records from previous boot:\n");
bert_print_all(boot_error_region, region_len);
cper_estatus_print(KERN_INFO HW_ERR, estatus);
错误解析和HEST GHES 类似
相关文章:

RAS--APEI 报错解析流程(2)
RAS--APEI 报错解析流程(1) 除了APEI 中除了GHES会记录错误,在Post过程中的错误通常是通过BERT Table汇报 1.BERT Boot Error Record Table is used to report unhandled errors that occurred in a previous boot,it is reported as a ‘one-time polle…...

微软蓝屏事件对企业数字化转型有什么影响?
引言:从北京时间2024年7月19日(周五)下午2点多开始,全球大量Windows用户出现电脑崩溃、蓝屏死机、无法重启等情况。事发后,网络安全公司CrowdStrike称,收到大量关于Windows电脑出现蓝屏报告,公司…...

【Gin】精准应用:Gin框架中工厂模式的现代软件开发策略与实施技巧(上)
【Gin】精准应用:Gin框架中工厂模式的现代软件开发策略与实施技巧(上) 大家好 我是寸铁👊 【Gin】精准应用:Gin框架中工厂模式的现代软件开发策略与实施技巧(上)✨ 喜欢的小伙伴可以点点关注 💝 前言 本次文章分为上下两部分&…...

浅谈Devops
1.什么是Devops DevopsDev(Development)Ops(Operation) DevOps(Development和Operations的混合词)是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”…...

大文件分片上传(前端TS实现)
大文件分片上传 内容 一般情况下,前端上传文件就是new FormData,然后把文件 append 进去,然后post发送给后端就完事了,但是文件越大,上传的文件也就越长,如果在上传过程中,突然网络故障,又或者…...

unity2D游戏开发02添加组件移动玩家
添加组件 给PlayGame和EnemyObject添加组件BoxCollider 2D碰撞器,不用修改参数 给PlayGame添加组件Rigibody 2D 设置数据 添加EnemyObject,属性如下 Edit->project setting->Physics 2D 将 y的值改为0 给playerObject添加标签 新建层 将PlayerObj…...

设计模式 之 —— 单例模式
目录 什么是单例模式? 定义 单例模式的主要特点 单例模式的几种设计模式 1.懒汉式:线程不安全 2.懒汉式:线程安全 3.饿汉式 4.双重校验锁 单例模式的优缺点 优点: 缺点: 适用场景: 什么是单例模…...

深入浅出WebRTC—ULPFEC
FEC 通过在发送端添加额外的冗余信息,使接收端即使在部分数据包丢失的情况下也能恢复原始数据,从而减轻网络丢包的影响。在 WebRTC 中,FEC 主要有两种实现方式:ULPFEC 和 FlexFEC,FlexFEC 是 ULPFEC 的扩展和升级&…...

Python从0到100(四十三):数据库与Django ORM 精讲
前言: 零基础学Python:Python从0到100最新最全教程。 想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…...

Redis-主从模式
目录 前言 一.主从节点介绍 二.配置redis主从结构 二.主从复制 四.拓扑结构 五.数据同步 全量复制(Full Sync Replication) 局部复制(Partial Replication) Redis的学习专栏:http://t.csdnimg.cn/a8cvV 前言 …...

加速决策过程:企业级爬虫平台的实时数据分析
摘要 在当今数据驱动的商业环境中,企业如何才能在海量信息中迅速做出精准决策?本文将探讨企业级爬虫平台如何通过实时数据分析加速决策过程,实现数据到决策的无缝衔接。我们聚焦于技术如何赋能企业,提升数据处理效率,…...

字典树(前缀树)数组实现(只能查26个单词)
这段代码实现了一个基于 Trie 树的字典树(Trie)数据结构,用于存储和检索字符串。其中包含以下几个方法. insert(String word): 向 Trie 树中插入一个单词。首先将单词转换为字符数组,然后遍历字符数组,逐个字符在 Trie…...

CTF-pwn-虚拟化-vmmware 前置
文章目录 参考vmware逃逸简介虚拟机和主机通信机制(guest to host)共享内存(弃用)backdoor机制Message_Send和Message_RecvGuestRPC实例RpcOutSendOneRawWork实例 vmware-rpctool info-get guestinfo.ip各个步骤对应的backdoor操作Open RPC channelSend …...

thinkphp8结合layui2.9 图片上传验证
<?php declare (strict_types 1);namespace app\index\validate;use think\Validate;class Upload extends Validate {/*** 定义验证规则* 格式:字段名 > [规则1,规则2...]** var array*/protected $rule [image > fileExt:jpg,png|fileSize:204800|fi…...

农村污水处理难题:探索低成本高效解决方案
农村污水处理难题:探索低成本高效解决方案 农村污水处理作为国家生态文明建设的重要一环,面临着诸多挑战,尤其是技术落后、管理分散、资源匮乏等问题。物联网技术的引入,为解决这些痛点提供了创新途径,实现了对污水处…...

lightningcss介绍及使用
lightningcss介绍及使用 一款使用 rust 编写的 css 解析器,转换器、及压缩器。 特性 特别快:可以在毫秒级别解析、压缩大量的 css 文件,而且比其他工具的打包结果更小给值添加类型:许多其他css解析器会将值解析成一个无类型的 …...

HTTP服务的应用
1、编辑json请求参数; 2、把json发送到服务url,接收服务的返回参数; 3、解析返回参数。 procedure TfrmCustomQuery.btnFullUpdateClick(Sender: TObject); varfrm: TfrmInputQueryConditionEX;b_OK: Boolean;sBeginDate, sEndDate, sJSON…...

uni-app:踩坑路---scroll-view内使用fixed定位,无效的问题
前言: emmm,说起来这个问题整得还挺好笑的,本人在公司内,奋笔疾书写代码,愉快的提交测试的时候,测试跟我说,在苹果手机上你这个样式有bug,我倒是要看看,是什么bug。 安卓…...

MySQL4.索引及视图
1.建库 create database mydb15_indexstu; use mydb15_indexstu;2.建表 2.1 student表学(sno)号为主键,姓名(sname)不能重名,性别(ssex)仅能输入男或女,默认所在系别&a…...

MongoDB - 聚合阶段 $match、$sort、$limit
文章目录 1. $match 聚合阶段1. 构造测试数据2. $match 示例3. $match 示例 2. $sort 聚合阶段1. 排序一致性问题2. $sort 示例 3. $limit 聚合阶段 1. $match 聚合阶段 $match 接受一个指定查询条件的文档。 $match 阶段语法: { $match: { <query> } }$ma…...

ModuleNotFoundError: No module named ‘scrapy.utils.reqser‘
在scrapy中使用scrapy-rabbitmq-scheduler会出现报错 ModuleNotFoundError: No module named scrapy.utils.reqser原因是新的版本的scrapy已经摒弃了该方法,但是scrapy-rabbitmq-scheduler 没有及时的更新,所以此时有两种解决方法 方法一.将scrapy回退至旧版本,找到对应的旧版…...

vue3+ts+vite+electron+electron-packager打包成exe文件
目录 1、创建vite项目 2、添加需求文件 3、根据package.json文件安装依赖 4、打包 5、electron命令运行 6、electron-packager打包成exe文件 Build cross-platform desktop apps with JavaScript, HTML, and CSS | Electron 1、创建vite项目 npm create vitelatest 2、添…...

使用脚本搭建MySQL数据库基础环境
数据库的基本概念 数据(Data) 描述事物的符号记录 包括数字,文字,图形。图像,声音,档案记录等。 以记录形式按统一格式进行存储 表 将不同的记录组织在一起 用来储存具体数据 数据库 表的集合,是…...

Parameter index out of range (2 > number of parameters, which is 1【已解决】
文章目录 1、SysLogMapper.xml添加注释导致的2、解决方法3、总结 1、SysLogMapper.xml添加注释导致的 <!--定义一个查询方法,用于获取日志列表--><!--方法ID为getLogList,返回类型com.main.server.api.model.SysLogModel,参数类型为com.main.se…...

rk3588s 定制版 USB adb , USB2.0与USB3.0 区别,adb 由typeC 转换到USB3.0(第二部分)
硬件资源: rk3588s 核心板定制的地板 软件资源: 网盘上的 android12 源码 1 硬件上 客户只想使用 type c 接口中的 usb2.0 OTG 。在硬件上,甚至连 CC芯片都没有连接。 关于一些前置的知识。 1 USB2.0 与 USB3.0 的区别。 usb3.0 兼容2.0 …...

Cookie与Session 实现登录操作
Cookie Cookie 是网络编程中使用最广泛的一项技术,主要用于辨识用户身份。 客户端(浏览器)与网站服务端通讯的过程如下图所示: 从图中看,服务端既要返回 Cookie 给客户端,也要读取客户端提交的 Cookie。所…...

通过IEC104转MQTT网关轻松接入阿里云平台
随着智能电网和物联网技术的飞速发展,电力系统中的传统IEC 104协议设备正面临向现代化、智能化转型的迫切需求。阿里云作为全球领先的云计算服务提供商,其强大的物联网平台为IEC 104设备的接入与数据处理提供了强大的支持。本文将深入探讨钡铼网关在MQTT…...
lua 游戏架构 之 游戏 AI (五)ai_autofight_find_way
这段Lua脚本定义了一个名为 ai_autofight_find_way 的类,继承自 ai_base 类。 lua 游戏架构 之 游戏 AI (一)ai_base-CSDN博客文章浏览阅读238次。定义了一套接口和属性,可以基于这个基础类派生出具有特定行为的AI组件。例如&…...

vue3+openLayers点击标记事件
<template><!--地图--><div class"distributeMap" id"distributeMap"></div> </template> <script lang"ts" setup> import { onMounted, reactive } from "vue"; import { Feature, Map, View }…...

深入分析 Android ContentProvider (三)
文章目录 深入分析 Android ContentProvider (三)ContentProvider 的高级使用和性能优化1. 高级使用场景1.1. 数据分页加载示例:分页加载 1.2. 使用 Loader 实现异步加载示例:使用 CursorLoader 加载数据 1.3. ContentProvider 与权限管理示例࿱…...