RAS--APEI 报错解析流程(2)

news2024/9/20 8:54:05

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.coloradmin.cn/o/1945648.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一文弄懂JVM类加载器与双亲委派机制

类的加载器完成类的加载环节中的装载阶段的工作&#xff08;通过一个类的全限定名来获取该类的二进制字节流&#xff0c;且这个动作在虚拟机**外部实现**&#xff0c;即开发者可以决定如何去获取所需的类&#xff09;&#xff0c;且**不会影响后续的链接和初始化阶段&#xff0…

《算法笔记》总结No.10——链表

从第10期破例插叙一期单链表的实现&#xff0c;这个东东相当重要&#xff01;考研的同学也可以看&#xff1a;相较于王道考研的伪码不太相同&#xff0c;专注于可以运行。如果是笔试中的伪码&#xff0c;意思正确即可~ 注&#xff1a;博主之前写过一个版本的顺序表和单链表的C实…

谷粒商城实战笔记-56~57-商品服务-API-三级分类-修改-拖拽功能完成

文章目录 一&#xff0c;56-商品服务-API-三级分类-修改-拖拽功能完成二&#xff0c;57-商品服务-API-三级分类-修改-批量拖拽效果1&#xff0c;增加按钮2&#xff0c;多次拖拽一次保存完整代码 在构建商品服务API中的三级分类修改功能时&#xff0c;拖拽排序是一个直观且高效的…

Linux:Linux权限

目录 1. Linux权限的概念 2. Linux权限管理 2.1 文件访问者的分类 2.2 文件类型和访问权限 2.2.1 文件类型 2.2.2 基本权限 2.3 文件权限值的表示方法 2.4 文件访问权限的相关设置方法 2.4.1 chmod 2.4.2 chown 2.4.3 chgrp 2.4.4 umask 3. file指令 4. Linux目…

如何学习EMR:糙快猛的大数据之路(建立整体框架)

目录 初学EMREMR是什么&#xff1f;我的EMR学习故事糙快猛学习法则代码示例: 你的第一个EMR任务学习EMR的深入步骤EMR进阶技巧实用资源推荐常见挑战和解决方案 EMR生态EMR生态系统深度探索1. EMR上的Hadoop生态系统2. EMR Studio3. EMR on EKS 高级EMR配置和优化1. EMR实例集策…

音视频入门基础:PCM专题(3)——使用Audacity工具分析PCM音频文件

音视频入门基础&#xff1a;PCM专题系列文章&#xff1a; 音视频入门基础&#xff1a;PCM专题&#xff08;1&#xff09;——使用FFmpeg命令生成PCM音频文件并播放 音视频入门基础&#xff1a;PCM专题&#xff08;2&#xff09;——使用Qt播放PCM音频文件 音视频入门基础&am…

ICML 2024最佳论文开奖了!今年的热门投稿方向有这些

ICML 2024最近也放榜啦&#xff01;今年共有10篇论文夺得最佳论文奖&#xff0c;包括火爆的Stable Diffusion 3、谷歌VideoPoet以及世界模型Genie。 ICML是国际机器学习顶会&#xff0c;也是CCF-A类学术会议。今年这届顶会一共收到了9473篇论文&#xff0c;其中2610篇被录用&am…

昇思25天学习打卡营第22天|基于MindNLP+MusicGen生成自己的个性化音乐

文章目录 昇思MindSpore应用实践1、MusicGen模型简介残差矢量量化&#xff08;RVQ&#xff09;SoundStreamEncodec 2、生成音乐无提示生成文本提示生成音频提示生成 Reference 昇思MindSpore应用实践 本系列文章主要用于记录昇思25天学习打卡营的学习心得。 1、MusicGen模型简…

Qt基础 | Qt SQL模块介绍 | Qt SQL模块常用类及其常用函数介绍

文章目录 一、Qt SQL模块概述1.Qt sql 支持的数据库2.SQLite 数据库3.Qt SQL 模块的主要类 一、Qt SQL模块概述 Qt SQL 模块提供数据库编程的支持&#xff0c;Qt 支持多种常见的数据库&#xff0c;如MySQL、Oracle、MS SQL Server、SQLite 等。Qt SQL 模块包括多个类&#xff0…

phpstorm配置xdebug3

查看php路径相关信息 php --ini安装xdebug https://www.jetbrains.com/help/phpstorm/2024.1/configuring-xdebug.html?php.debugging.xdebug.configure php.ini 配置 在最后添加&#xff0c;以下是我的配置 [xdebug] zend_extension/opt/homebrew/Cellar/php8.1/8.1.29/p…

安装NVIDIA驱动

一、不升级内核安装NVIDIA驱动 说明: 1、安装NVIDIA驱动,是用来提升AI、图片等算法 2、本人是在centos7.9操作系统安装英伟达T4板卡驱动 操作系统Centos 7.9驱动版本NVIDIA-Linux-x86_64-525.89.02.run操作账号root1.1 关闭nouveau 1、查看nouveau是否关闭 lsmod |grep nouv…

Android 常用调试工具/方法解析

一、内存相关 参考Android内存分析命令_dumpsys meminfo 算出rss-CSDN博客 1、基本概念 1&#xff09;PSS & RSS & USS & VSS a、PSS 概念&#xff1a;全称Proportional Set Size&#xff0c;根据进程实际使用的内存量按照共享比例分配给进程的一种内存度量方…

MySql性能调优05-[sql实战演练]

sql实战演练 行列转换行列式转换第一题【列转行】第二题【列转行】 having的使用找到表中&#xff0c;名字重复的项有数据表employee&#xff0c;包含如下字段id、name、department、age&#xff0c;编写SQL&#xff0c;找到不与其他人同龄的年纪最大的员工的年龄有数据表emplo…

Nacos-2.4.0最新版本docker镜像,本人亲自制作,部署十分方便,兼容postgresql最新版本17和16,奉献给大家了

基于Postgresql数据库存储的nacos最新版本2.4.0,采用docker镜像安装方式 因业务需要,为了让nacos支持postgresql,特意花了两天时间修改了源码,然后制作了docker镜像,如果你也在找支持postgresql的nacos最新版本,恭喜你,你来的正好~ nacos-2.4.0 postgresql的数据库脚本…

C++学习笔记-C++11中的智能指针

1.智能指针介绍 智能指针是C的特性用法&#xff0c;是一个类似指针功能的类对象&#xff0c;其目的是为了更好的管理动态分配的内存&#xff0c;避免出现内存泄漏、悬空指针等问题。C11的标准库里提供了三种智能指针模板类&#xff0c;分别是std::unique_ptr、std::shared_ptr…

vue 两个页面切换, 再回到当前页,还是离开前的数据

1、要保证页面的name 和 建路由的大小写一致 2、页面不用生命周期--activated 调接口刷新

计算机网络八股文(三)

目录 41.为什么每次建立TCP连接时&#xff0c;初始化的序列号都不一样&#xff1f; 42.初始序列号ISN如何随机产生&#xff1f; 43.既然IP层会分片&#xff0c;为什么TCP层需要根据MSS分片呢&#xff1f; 44.TCP第一次握手丢失&#xff0c;会发生什么&#xff1f; 45.TCP第…

一个python脚本解决新版剪映导出字幕收费问题

如果你是希望我能完全解决剪映收费问题&#xff0c;我无法帮你&#xff1b; 两个文件&#xff0c;可生成不带时间线的纯文案&#xff0c;MD 格式&#xff0c;也可以生成带时间线的 SRT 文件。 因为剪映国内版对 JSON 文件进行了加密&#xff0c;所以请选择国际版 Cutcap&#x…

《javaEE篇》--阻塞队列详解

阻塞队列 阻塞队列概述 阻塞队列也是一种队列&#xff0c;和普通队列一样遵循先进先出的原则&#xff0c;但是阻塞队列相较于普通队列多了两项功能阻塞添加和阻塞移除&#xff0c;使得阻塞队列成为一种线程安全的数据结构 阻塞添加&#xff1a;当队列满的时候继续入队就会阻…

电脑虚拟摄像头软件分享|用手机打破电脑摄像头的极限

随着手机摄像头的不断更新迭代&#xff0c;手机已经接近专业电脑摄像头的画质。这让我们可以花费更低的成本获取优质的电脑录像画面。今天小编给大家详细讲解电脑虚拟摄像头的在我们日常生活中的妙用&#xff0c;以及分享几款口碑不错的电脑虚拟摄像头软件。有需要的小伙伴可以…