• 使用SDEI上报RAS故障


    Software Delegated Exception Interface (SDEI) 软件委托异常接口的一种典型应用场景是利用APEI( ACPI Platform Error Interface)用作固件优先(firmware first)的RAS故障处理的通知机制。事实上SDEI只是在ACPI6.2版本引入的一种新的通知机制(firmware to OS),可以不受中断屏蔽的影响。
    在这里插入图片描述

    Firmware First Error Handling with SDEI

    RAS是系统鲁棒性的重要特性,重点关注由硬件产生的故障,这些故障一般有两种处理方式:firmware first 和 kernel first。其中firmware first的处理流程如下图:

    在这里插入图片描述

    1. RAS节点检测到故障
    2. Firmware收到故障事件(中断)
    3. 故障事件转发到MM驱动
    4. MM驱动从故障记录寄存器中读取RAS故障并生成CPER(Common Platform Error Record)故障记录,返回EL3
    5. EL3通过SDEI通知OS
    6. OS读CPER并处理故障

    从上面的流程可以看出,SDEI是firmware到OS的通知机制,而CPER是firmware到OS传递故障信息的载体。
    SDEI和CPER都是通过APEI中一种叫做HEST(Hardware Error Source Table)的表来承载, HEST表支持多种故障源类型,其中RAS故障通过GHES(Generic Hardware Error Source) V2结构来表示。

    在这里插入图片描述

    1. 其中GHES的Notification Structure用来通知OS,SDEI作为类型11的通知方式,并把32位事件号存储在vector字段
    2. 故障信息记录在GHES的Error Status Address,这是一个GAS(Generic Address Structure)结构体,这个结构体的Address指向记录错误数据的block( Generic Error Status Block),每个block包含一个或多个Generic Error Data Entry,CPER就是Error Data Entry的一个字段。
    3. firmware在初始化阶段检测故障源,创建GHES并填入到HEST表中发布给OS
    4. OS解析HEST( Hardware ErrorSource Table’s) 的 GHES( Generic Hardware Error Source) entry的时候,使用SDEI调用为每个event注册一个处理函数handler
    5. RAS故障发生时通过中断通知Firmware
    6. firmware从RAS扩展寄存器中读取RAS故障并记录CPER,然后通过SMC调用该故障对应的event注册的处理函数(故障与event的映射关系需要预先定义)
    7. OS执行该处理函数,从映射的内存地址中读取CPER, 进一步处理故障

    在这里插入图片描述

    SDEI初始化过程

    linux中的SDEI驱动初始化代码在 ./drivers/firmware/arm_sdei.c 的sdei_probe,
    SDEI初始化过程主要做3件事:

    1. 初始化sdei_firmware_call,明确SDEI调用是HVC还是SMC,可以通过acpi或者DTS表选择
    2. 通过SDEI_VERSION调用与firmware对齐版本号
    3. 初始化sdei_entry_point,也就是从firmware跳到OS的asm入口地址__sdei_asm_handler

    OS通过sdei_firmware_call调用到了firmware会执行sdei_smc_handler,sdei_smc_handler根据function ID执行相应的处理函数,比如SDEI_VERSION调用的function ID为 0xC400_0020,对应的处理函数为sdei_version。

    SDEI注册过程源码分析

    1. ghes_probe根据GHES的Notification Structure的通知类型ACPI_HEST_NOTIFY_SOFTWARE_DELEGATED(11)选择执行apei_sdei_register_ghes. apei_sdei_register_ghes调用sdei_register_ghes完成sdei的注册
    2. sdei_register_ghes中首先从GHES的Notification Structure的的vector字段获取到event number,调用sdei_event_register为该event注册callback函数ghes_sdei_normal_callback或ghes_sdei_critical_callback,然后通过sdei_event_enable使能该event
    3. sdei_event_register中首先通过sdei_event_create()把event添加到sdei_list,然后通过sdei_api_event_register()-> invoke_sdei_fn( SDEI_EVENT_REGISTER
      ) -> sdei_firmware_call(SDEI_EVENT_REGISTER) 注册入口地址 sdei_entry_point
    4. sdei_firmware_call通过HVC或SMC跳到firmware执行sdei_smc_handler,然后根据function ID找到对应的处理函数sdei_event_register完成事件注册

    SDEI事件分配过程源码分析

    1. RAS故障(eg: External Abort)产生时EL3会收到相应的中断,进而调用RAS驱动处理故障,接着会调用sdei_dispatch_event(event_num)把故障分发到sdei client去处理
    2. sdei_dispatch_event通过event_num找到注册好的入口地址sdei_entry_point,然后保存Non-secure上下文并通过setup_ns_dispatch填充要跳转的SDEI client的上下文,最后调用begin_sdei_synchronous_dispatch设置跳转点dispatch_jmp(从client返回的点),退出EL3
    3. setup_ns_dispatch中会设置event handler的参数,并通过sdei_set_elr_spsr设置ELR为注册事件的入口地址sdei_entry_point, 设置SPSR屏蔽中断(DISABLE_ALL_EXCEPTIONS)
    4. 退出EL3后就跳到事件的入口地址sdei_entry_point,也就是前面初始化的汇编函数__sdei_asm_handler
    5. __sdei_asm_handler调用__sdei_handler->do_sdei_event->sdei_event_handler, sdei_event_handler从参数中获取到event_num, 然后执行为该event注册的callback函数ghes_sdei_normal_callback或ghes_sdei_critical_callback
    6. 这两个callback函数都会调用__ghes_sdei_callback,这里会从GHES的里获取到Generic Error Status Block添加到ghes_estatus_llist中,清除Block故障状态并通过read_ack_register给firmware一个应答,然后添加一个irq work也就是ghes_proc_in_irq到中断队列中
    7. ghes_proc_in_irq遍历ghes_estatus_llist并调用ghes_do_proc执行具体的故障处理动作
    8. 故障处理完之后会回到__sdei_asm_handler中调用sdei_handler_exit,通过SMC或HVC跳到firmware执行sdei_smc_handler->sdei_event_complete
    9. sdei_event_complete中恢复上下文,调用end_sdei_synchronous_dispatch跳到dispatch_jmp继续执行。

    参考

    ACPI Specification

    Reliability, Availability, and Serviceability(RAS) on ARM64

    Firmware First Error Handling on ARM Neoverse Reference Design Platforms

  • 相关阅读:
    docker小技能:容器IP和宿主机IP一致( Nacos服务注册ip为内网ip,导致Fegin无法根据服务名访问 )
    uniapp使用scss仿tailwindcss进行常用样式封装便捷开发小程序或web
    【附源码】计算机毕业设计SSM水库洪水预报调度系统
    【ORM框架:Sequelize的查询】
    2022亚太C题赛题分享
    STM32单片机OLED贪吃蛇游戏记分计时
    电容笔和Apple Pencil的区别是什么?双十一值得入手的电容笔
    简述快速失败(fail-fast)和安全失败(fail-safe)的区别 ?
    宇宙最強的IDE - Visual Studio 25岁生日快乐
    【c语言】编译链接--详解
  • 原文地址:https://blog.csdn.net/jingr1/article/details/126216896