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 类似

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/383377.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

stats 监控 macOS 系统

Stats 监控 macOS 系统 CPU 利用率GPU 利用率内存使用情况磁盘利用率网络使用情况电池电量 brew install stats参考 stats github

Ansible的脚本-----playbook剧本【上】

目录 1.playbook剧本组成 2.playbook剧本实战演练 2.1 实战演练一&#xff1a;给被管理主机安装httpd服务 2.2 实战演练二&#xff1a;定义、引用变量 2.3 实战演练三&#xff1a;指定远程主机sudo切换用户 2.4 实战演练四&#xff1a;when条件判断 2.5 实战演练五&…

ElasticSearch(六)— 全文检索

一、match系列查询 前面讲到的query中的查询&#xff0c;都是精准查询。可以理解成跟在关系型数据库中的查询类似。match系列的查询&#xff0c;是全文检索的查询。会通过分词进行评分&#xff0c;匹配&#xff0c;再返回搜索结果。 1.1 match 查询 "query": {&qu…

.Net Core 微服务之Consul(三)-KV存储分布式锁

引言: 集合上两期.Net Core 微服务之Consul(一)(.Net Core 微服务之Consul(一)-CSDN博客) 。.Net Core 微服务之Consul(二)-集群搭建)(.Net Core 微服务之Consul(二)-集群搭建-CSDN博客) 目录 一. Consul KV 存储 1. KV 存储介绍 1.1 数据模型 1.2 一致性和…

Centos安装、迁移gitlab

Centos安装迁移gitlab 一、下载安装二、配置rb修改&#xff0c;起服务。三、访问web&#xff0c;个人偏好设置。四、数据迁移1、查看当前GitLab版本2、备份旧服务器的文件3、将上述备份文件拷贝到新服务器同一目录下&#xff0c;恢复GitLab4、停止新gitlab数据连接服务5、恢复备…

Docker、containerd、CRI-O 和 runc 之间的区别

容器与 Docker 这个名称并不紧密相关。你可以使用其他工具来运行容器 您可以使用 Docker 或一堆非Docker 的其他工具来运行容器。docker只是众多选项之一&#xff0c;Docker&#xff08;公司&#xff09;在生态系统中创建了一些很棒的工具&#xff0c;但不是全部。 容器方面有…

47.简易电压表的设计与验证(2)

&#xff08;1&#xff09;Verilog 代码&#xff1a; module adc_collect(input clk ,input reset_n ,input [7:0] adc_data ,output clk_adc );wire clk_adc_a ;…

大文件分片上传(前端TS实现)

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

【Linux操作系统】:进程间通信

目录 进程间通信介绍 1、进程间通信的概念 2、进程间通信的目的 3、进程间通信的本质 4、进程间通信的分类 管道 匿名管道 匿名管道的原理 pipe函数 创建匿名管道 管道的四种情况和五种特性 命名管道 使用命令创建命名管道 创建一个命名管道 命名管道的打开规则 …

【ROS2】高级:安全-理解安全密钥库

目标&#xff1a;探索位于 ROS 2 安全密钥库中的文件。 教程级别&#xff1a;高级 时间&#xff1a;15 分钟 内容 背景安全工件位置 公钥材料 私钥材料域治理政策 安全飞地 参加测验&#xff01; 背景 在继续之前&#xff0c;请确保您已完成设置安全教程。 sros2 包可以用来创…

Qt自定义下拉列表-可为选项设置标题、可禁用选项

在Qt中,ComboBox&#xff08;组合框&#xff09;是一种常用的用户界面控件,它提供了一个下拉列表,允许用户从预定义的选项中选择一个。在项目开发中&#xff0c;如果简单的QComboBox无法满足需求&#xff0c;可以通过自定义QComboBox来实现更复杂的功能。本文介绍一个自定义的下…

Python研究生毕业设计,数据挖掘、情感分析、机器学习

最近在学校毕业了&#xff0c;其中有很多毕业论文使用到的代码&#xff0c;如数据挖掘、情感分析、机器学习、数据预测处理、划分数据集和测试集&#xff0c;绘制分类任务&#xff0c;词汇表示&#xff1a;使用TF-IDF向量化器&#xff0c;线性回归、多元线性回归、SVR回归模型&…

一文入门SpringSecurity 5

目录 提示 Apache Shiro和Spring Security 认证和授权 RBAC Demo 环境 Controller 引入Spring Security 初探Security原理 认证授权图示​编辑 图中涉及的类和接口 流程总结 提示 Spring Security源码的接口名和方法名都很长&#xff0c;看源码的时候要见名知意&am…

grafana对接zabbix数据展示

目录 1、初始化、安装grafana 2、浏览器访问 3、安装zabbix 4、zabbix数据对接grafana 5、如何导入模板&#xff1f; ① 设置键值 ② 在zabbix web端完成自定义监控项 ③ garafana里添加nginx上面的的三个监控项 6、如何自定义监控项&#xff1f; 以下实验沿用上一篇z…

二、原型模式

文章目录 1 基本介绍2 实现方式深浅拷贝目标2.1 使用 Object 的 clone() 方法2.1.1 代码2.1.2 特性2.1.3 实现深拷贝 2.2 在 clone() 方法中使用序列化2.2.1 代码 2.2.2 特性 3 实现的要点4 Spring 中的原型模式5 原型模式的类图及角色5.1 类图5.1.1 不限制语言5.1.2 在 Java 中…

免费【2024】springboot 趵突泉景区的智慧导游小程序

博主介绍&#xff1a;✌CSDN新星计划导师、Java领域优质创作者、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;SpringBoot、Vue、SSM、HTML、Jsp、PHP、Nodejs、Python、爬虫、数据可视化…

开发桌面程序-Electron入门

Electron是什么 来自官网的介绍 Electron是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。 嵌入 Chromium 和 Node.js 到 二进制的 Electron 允许您保持一个 JavaScript 代码代码库并创建 在Windows上运行的跨平台应用 macOS和Linux——不需要本地开发 经验。 总…

普中51单片机:DS1302时钟芯片讲解与应用(十)

文章目录 引言基本特性什么是RAM&#xff1f;什么是涓流充电&#xff1f; 电路图和引脚说明通信协议以及工作流程寄存器控制寄存器日历/时钟寄存器 DS1302读写时序代码演示——数码管显示时分秒 引言 DS1302 是一款广泛使用的实时时钟 (RTC) 芯片&#xff0c;具有低功耗、内置…

本地部署VMware ESXi服务实现无公网IP远程访问管理服务器

文章目录 前言1. 下载安装ESXi2. 安装Cpolar工具3. 配置ESXi公网地址4. 远程访问ESXi5. 固定ESXi公网地址 前言 在虚拟化技术日益成熟的今天&#xff0c;VMware ESXi以其卓越的性能和稳定性&#xff0c;成为了众多企业构建虚拟化环境的首选。然而&#xff0c;随着远程办公和跨…

《昇思25天学习打卡营第19天|基于MobileNetv2的垃圾分类》

基于MobileNetv2的垃圾分类 本文档主要介绍垃圾分类代码开发的方法。通过读取本地图像数据作为输入&#xff0c;对图像中的垃圾物体进行检测&#xff0c;并且将检测结果图片保存到文件中。 1、实验目的 了解熟悉垃圾分类应用代码的编写&#xff08;Python语言&#xff09;&a…