PCIe控制器错误处理与配置访问机制详解:从原理到实战

发布时间:2026/6/16 0:28:00
PCIe控制器错误处理与配置访问机制详解:从原理到实战
1. 项目概述深入PCIe控制器的“黑匣子”与“寻址地图”在嵌入式系统尤其是通信处理器和网络设备的设计与调试中PCI ExpressPCIe总线的稳定性和可观测性是决定系统可靠性的关键一环。当一块高速网卡在满负荷下突然丢包或者一个数据采集卡间歇性“失联”时问题可能并不在应用层而是深埋在PCIe链路的物理层或事务层。这时如果控制器只告诉你“出错了”却不说“错在哪”、“谁干的”调试工作就会像大海捞针。我手边这份来自Freescale现NXPMSC8251处理器的参考手册片段恰好揭示了PCIe控制器内部两个至关重要的“诊断工具箱”错误处理机制与配置空间访问机制。这不仅仅是寄存器列表的罗列它实际上定义了一套完整的硬件级“故障记录仪”和“设备寻址协议”。理解它们意味着你不仅能配置设备更能“听懂”设备的告警精准定位从配置访问越界到数据包超时的各类问题。无论是进行BSP板级支持包开发、撰写稳健的设备驱动程序还是进行深度的硬件故障根因分析这套机制都是你必须掌握的底层语言。本文将以MSC8251为蓝本拆解这些寄存器的每一个比特位并分享在实际开发中如何运用它们来构建更可靠的系统。2. 核心原理PCIe错误处理与配置访问的顶层设计在深入寄存器细节前我们必须建立两个核心机制的宏观视图。这有助于理解为什么设计者要如此安排这些寄存器而不是孤立地记忆每个比特位的含义。2.1 错误处理的三层架构检测、屏蔽与捕获PCIe的错误处理并非一个单一功能而是一个精密的流水线其设计哲学是及时发现、灵活控制、完整记录。在MSC8251中这套流水线主要由三类寄存器协同工作构成了一个三层架构。第一层错误检测寄存器PEX_ERR_DR这是整个流程的源头。虽然输入资料中未详细列出该寄存器但通过“错误禁用寄存器”的描述反向推断PEX_ERR_DR的各个比特位对应着具体的错误类型。例如PEX_ERR_DR[PET]位会在发生PCIe完成超时Completion Timeout时被置位。这个寄存器就像一个布满传感器的仪表盘实时反映链路状态。第二层错误禁用寄存器PEX_ERR_DISR这是控制层也是输入资料详细描述的部分。它的作用不是清除错误而是屏蔽错误的检测。例如将PCTD位PCI Express Completion Time-out Disable写1那么即使链路真的发生了完成超时PEX_ERR_DR[PET]位也不会被置位后续的错误报告流程如触发系统错误也就不会启动。这个设计给了软件极大的灵活性在初始化阶段你可能希望屏蔽所有非关键错误以避免干扰在稳定运行阶段则打开关键错误检测在调试阶段又可以单独启用某一类错误进行观察。第三层错误捕获寄存器组PEX_ERR_CAP_STAT/R0-R3这是记录层堪称“黑匣子”。当错误发生且未被禁用时控制器会瞬间将错误发生瞬间的关键上下文信息如出错的数据包头、事务来源等快照到这一组寄存器中。PEX_ERR_CAP_STAT[ECV]位变为有效锁定当前数据直到软件读取并清除它才会开始记录下一次错误。这避免了错误信息的覆盖为事后分析提供了不可替代的第一现场数据。实操心得错误处理的配置顺序在驱动初始化时一个常见的误区是先配置捕获寄存器。正确的顺序应该是1) 首先根据当前阶段初始化、运行、调试的需求配置PEX_ERR_DISR决定要监控哪些错误。2) 然后清除PEX_ERR_CAP_STAT[ECV]位确保捕获寄存器就绪。3) 最后再使能PCIe控制器的正常运行。这个顺序能确保从运行伊始错误监控就在可控状态下进行。2.2 配置空间访问的两种路径直接映射与地址转换配置空间是PCIe设备的“身份证”和“控制面板”操作系统通过读写其中的寄存器来识别、配置和管理设备。MSC8251的PCIe控制器工作在RC模式时提供了两种访问外部设备配置空间的方法这反映了硬件设计中对灵活性和效率的权衡。方法一配置访问寄存器机制PEX_CONFIG_ADDR/DATA这是最经典、最直接的方式仿效了PCI的CF8h/CFCh端口机制。软件需要向PEX_CONFIG_ADDR寄存器写入一个格式化的地址包含总线号、设备号、功能号和寄存器号然后通过对PEX_CONFIG_DATA寄存器的读写操作间接触发一次对目标配置空间的访问。优点逻辑简单与标准PCI配置访问模型兼容性好易于理解和实现。缺点每次访问都需要至少两次寄存器操作设置地址、读写数据在需要频繁或批量访问配置空间时效率较低。方法二出站ATMU窗口机制这是一种更高效、更“像内存访问”的方式。ATMU地址转换与映射单元通常用于将处理器的本地地址空间映射到PCIe总线地址空间。通过将一个出站ATMU窗口的ReadTType或WriteTType字段编程为0x2表示配置事务软件就可以像访问普通内存地址一样直接读写PCIe配置空间。访问的地址会被硬件自动解码为总线、设备、功能和寄存器号。优点效率高。一旦窗口设置好后续的配置访问就像内存加载/存储指令一样快特别适合驱动程序中需要扫描多个设备或频繁访问配置寄存器的场景。缺点设置相对复杂需要正确编程ATMU的基地址、大小和事务类型。并且手册明确警告此方法不能用于访问控制器自身的内部配置寄存器即RC的本地配置空间。注意事项链接训练完成前勿操作手册在17.4.1.6.1节特别强调在链路成功训练Link Training完成之前不应尝试发起外部配置事务。软件可以通过轮询链路训练与状态机状态寄存器PEX_LTSSM_STAT来检查链路状态。在未训练成功时访问配置空间可能导致访问超时或得到全1的无效数据甚至在某些硬件上引发不可预知的行为。这是很多新手容易忽略的硬件初始化依赖条件。3. 核心细节解析与实操要点3.1 错误禁用寄存器PEX_ERR_DISR详解与配置策略PEX_ERR_DISR是一个32位寄存器其每一位都对应着PEX_ERR_DR中一个错误检测位的使能控制。理解每个错误类型的含义是制定合理屏蔽策略的基础。下表对关键错误类型进行了归纳位域名称 (缩写)描述典型场景与配置建议31MED多错误禁用当多个错误几乎同时发生时此位控制是否记录“多错误”标志。调试初期建议禁用(1)以简化问题稳定运行时可开启(0)以监控异常风暴。23PCTDPCIe完成超时禁用禁用对TLP事务响应超时的检测。在已知存在慢速端点设备或调试超时问题时可临时禁用(1)但长期运行务必开启(0)这是检测设备无响应的重要指标。21PCACDCA状态完成禁用禁用对带有“Completer Abort”状态完成包的检测。CA表示目标设备无法处理该请求。通常保持开启(0)以捕获设备异常。19CDNSCD带数据非成功完成禁用禁用对“Non-Successful Completion with Data”的检测。这类错误指示请求部分失败。建议保持开启(0)用于诊断数传输问题。17ICCAD无效配置访问禁用禁用对通过PEX_CONFIG_ADDR/DATA进行非法配置访问的检测。**在软件调试阶段可临时禁用(1)**以避免频繁触发错误软件稳定后应开启(0)。16IACAD无效ATMU配置访问禁用禁用对通过ATMU窗口进行非法配置访问的检测。建议与ICCAD位采取相同策略。14MISD消息无效大小禁用禁用对出站消息TLP大小无效的检测。通常保持开启(0)防止软件错误构造消息包。13IOISDI/O无效大小禁用禁用对出站I/O事务大小无效的检测PCIe中I/O事务通常限制为1、2、4字节。必须保持开启(0)因为非对齐或超大小的I/O访问是明确的错误。12CISD配置无效大小禁用禁用对出站配置事务大小无效的检测配置访问必须为1、2、4字节且不能跨边界。必须保持开启(0)这是PCIe规范强制要求。8IOIADI/O无效地址禁用禁用对大于4GB的I/O地址访问的检测在32位地址空间中无效。**在64位系统中可酌情考虑但一般保持开启(0)**以保持兼容性。配置示例与解析 假设在驱动初始化阶段我们希望仅启用最关键的链路级和协议级错误检测暂时屏蔽可能由未就绪的端点设备引发的访问类错误。我们可以这样计算PEX_ERR_DISR的值// 假设我们需要配置的位禁用 ICCAD(17), IACAD(16), 启用其他关键错误检测 // 位17 (ICCAD) 1 位16 (IACAD) 1 // 其他需要关注的位如PCTD, PCACD等我们设为0启用 // 注意寄存器复位后全为0所有检测启用。我们现在要设置第17和16位为1。 // 构建要写入的值bit17和bit16为1 uint32_t pex_err_disr_value 0; pex_err_disr_value | (1 17); // 设置ICCAD位 pex_err_disr_value | (1 16); // 设置IACAD位 // 在实际操作中我们通常采用读-修改-写的方式避免影响其他位 uint32_t current_val readl(PEX_ERR_DISR_ADDR); current_val | ( (1 17) | (1 16) ); // 将第17和16位置1 writel(current_val, PEX_ERR_DISR_ADDR);这段代码执行后控制器将忽略通过两种配置访问机制进行的非法访问错误但依然会监控完成超时、CA错误等更严重的链路问题。3.2 错误捕获寄存器组事故现场的“黑匣子”数据分析当错误发生且被捕获后PEX_ERR_CAP_STAT和PEX_ERR_CAP_R0-R3寄存器就构成了分析问题的核心。关键在于PEX_ERR_CAP_STAT[GSID]和TO位它们指明了错误来源从而决定了R0-R3寄存器中数据的格式。场景一内部源出站事务错误例如处理器发起的访问出错当GSID不等于0x02且TO0时错误源于内部如CPU发起的出站事务。PEX_ERR_CAP_R0包含出错的TLP包的FMT格式和TYPE类型字段。这能立刻告诉你出错的事务是内存读、内存写、配置读还是消息等。PEX_ERR_CAP_R1/R2标记为OD0/OD1手册注明“Reserved for factory debug”。这意味着这些信息是平台相关的可能包含内部总线ID、线程ID等对芯片原厂调试更有用对驱动开发者通常意义不大。PEX_ERR_CAP_R3OD2同样为工厂调试保留。场景二外部源入站事务错误例如端点设备发来的数据包出错当GSID等于0x02时错误源于外部设备发起的入站事务。这是最常见也最需要关注的调试场景。PEX_ERR_CAP_R0(GH0)包含错误TLP的第一个双字DW的包头。你需要根据PCIe协议解析这个32位值获取Fmt,Type,TC流量类别,Attr属性,Length长度等关键信息。PEX_ERR_CAP_R1(GH1)包含TLP的第二个DW的包头主要包含Requester ID请求者ID即总线/设备/功能号和Tag标签。这是定位“罪魁祸首”设备的关键通过Requester ID你可以追溯到是哪个PCIe设备发起了这个出错的事务。PEX_ERR_CAP_R2(GH2)包含TLP的第三个DW的包头对于带地址的请求这里包含地址的低位部分。PEX_ERR_CAP_R3(GH3)第四个DW包头手册标注为“don‘t care”通常不包含有效信息。排查技巧利用捕获信息定位故障设备当系统报告PCIe错误如AER日志时首先读取PEX_ERR_CAP_STAT检查ECV和TO位确认错误已被捕获且来源是外部设备GSID 0x02。读取PEX_ERR_CAP_R1提取Requester ID位24-31为Bus Number位16-23为Device Number位13-15的低3位为Function Number。在操作系统中使用lspci -s BB:DD.F命令Linux或通过内核PCI子系统即可定位到具体的硬件设备。结合PEX_ERR_CAP_R0中的TLP类型和长度可以判断该设备试图进行何种操作如DMA读、写从而进一步分析是设备驱动bug、硬件故障还是内存映射问题。3.3 配置空间访问机制实战两种方法的代码实现对比我们以读取总线1、设备0、功能0的配置空间中偏移0x00处的Vendor ID为例展示两种方法的实现。方法一使用PEX_CONFIG_ADDR/DATA寄存器// 假设 PEX_CONFIG_ADDR 和 PEX_CONFIG_DATA 的物理地址已映射到虚拟地址 pex_config_addr 和 pex_config_data void read_vendor_id_cfg_reg(uint8_t bus, uint8_t dev, uint8_t func, uint16_t offset, uint32_t *value) { // 1. 构建配置地址。格式遵循PCI规范31位为Enable位[30:24]为总线号[23:19]为设备号[18:16]为功能号[15:8]为寄存器号高8位[7:2]为寄存器号低6位[1:0]为0。 uint32_t addr 0x80000000; // 使能位(31)置1 addr | (bus 16); addr | (dev 11); addr | (func 8); addr | (offset 0xFC); // 确保偏移是4字节对齐的低2位为0 // 2. 将地址写入PEX_CONFIG_ADDR writel(addr, pex_config_addr); // 3. 从PEX_CONFIG_DATA读取数据 // 注意对于32位读取直接读取即可。对于8/16位读取需要处理字节使能这里不展开。 *value readl(pex_config_data); } // 调用示例读取Bus 1, Dev 0, Func 0的Vendor ID (offset 0x00) uint32_t vid; read_vendor_id_cfg_reg(1, 0, 0, 0x00, vid); printf(Vendor ID: 0x%04X\n, vid 0xFFFF);方法二使用出站ATMU窗口首先需要在系统初始化时设置一个ATMU窗口。假设我们使用窗口n。// 1. 编程ATMU窗口属性寄存器 (PEXOWARn) // 设置事务类型为配置读写 (0x2)窗口大小等属性 uint32_t pexowar 0; pexowar | (0x2 24); // WriteTType 0x2 配置写 pexowar | (0x2 16); // ReadTType 0x2 配置读 // ... 设置其他属性如窗口大小、目标区域等 writel(pexowar, PEXOWARn_ADDR); // 2. 编程ATMU窗口翻译寄存器 (PEXOWTRn) // 将本地处理器地址空间的一段区域映射到PCIe配置空间。 // 关键构造映射的基地址。PCIe配置空间的地址格式为 // [27:20] Bus Number, [19:15] Device Number, [14:12] Function Number, [11:8] Extended Reg, [7:2] Register Number // 假设我们将本地地址 0xF000_0000 映射到 Bus 0 的配置空间。 uint32_t pexowtr 0xF0000000; // 本地基地址 // 注意ATMU窗口的基地址需要根据具体系统内存布局对齐。 writel(pexowtr, PEXOWTRn_ADDR); // 启用口等操作...设置完成后访问配置空间就变成了直接的内存访问// 定义一个指向ATMU窗口本地基地址的指针 volatile uint32_t *config_mem_base (volatile uint32_t *)0xF0000000; // 计算目标配置寄存器的“内存”地址 // 目标Bus 1, Dev 0, Func 0, Offset 0x00 // 根据手册公式PCIe地址 (bus 20) | (dev 15) | (func 12) | (ext_reg 8) | (reg_num 2) // 其中 ext_reg 通常为0 reg_num offset / 4 uint32_t pcie_config_addr (1 20) | (0 15) | (0 12) | (0 8) | (0x00); // offset 0x00, reg_num0 // 转换为在ATMU窗口内的本地地址 uint32_t local_offset pcie_config_addr; // 这里假设ATMU窗口的本地基地址直接映射到PCIe地址0。 // 更通用的做法是local_addr config_mem_base (pcie_config_addr 2) 因为我们是32位指针访问。 // 直接读取 uint32_t vid config_mem_base[pcie_config_addr 2]; // 右移2位是因为以4字节为单位索引 printf(Vendor ID via ATMU: 0x%04X\n, vid 0xFFFF);显然ATMU方法在需要大量扫描或频繁访问时代码更简洁性能更高。4. 配置空间头部关键寄存器解析配置空间的前256字节是PCI兼容区域前64字节是标准头部。MSC8251手册详细描述了其中关键寄存器的功能理解它们对驱动开发至关重要。4.1 命令寄存器Command Register, Offset 0x04控制器的“总开关”这个寄存器控制着PCIe控制器的基本行为。几个关键位需要特别注意Bit 2 - Bus Master Enable这是最重要的位之一。在EP模式下清除此位会阻止设备发起任何内存或I/O请求包括MSI中断。在RC模式下清除此位会阻止控制器将内存事务转发到上游。在设备驱动加载初期通常先保持此位为0待所有资源BAR、中断等配置妥当后再置1启用设备主控功能。Bit 10 - Interrupt Disable此位仅控制传统的INTx中断线模拟消息不影响MSI或MSI-X中断。在现代PCIe设备中通常使用MSI/MSI-X因此此位常被忽略。Bit 6 - Parity Error Response控制是否响应奇偶校验错误。在调试涉及数据完整性的问题时可以临时关闭此响应但生产环境建议开启。4.2 状态寄存器Status Register, Offset 0x06错误历史的“记录本”这个寄存器记录了各种错误状态。需要注意的是这些位是“写1清除”w1c的。这意味着要清除一个状态位必须向该位写入1写入0无效。Bit 15 - Detected Parity Error只要收到“中毒”Poisoned的TLP就会被置位与命令寄存器的Bit 6设置无关。这是检测数据损坏的直接标志。Bit 13 - Received Master-Abort当请求者收到“不支持的请求”Unsupported Request完成状态时置位。这通常意味着访问了一个不存在的地址或设备。Bit 4 - Capabilities List必须为1表示该设备支持PCIe能力链表Capabilities List。操作系统依赖此标志来发现PCIe高级功能如AER、MSI等。4.3 基地址寄存器BARs设备资源的“门户”BAR是设备与系统交换数据的核心窗口。MSC8251在EP模式下支持多种BARBAR0 (PEXCSRBAR)这是一个特殊的、固定的1MB窗口专用于入站配置访问。系统软件通过这个窗口来访问EP设备自身的配置空间。它不可通过ATMU修改。BAR132位内存空间BAR。其可写的高位比特数量由入站窗口属性寄存器PEXIWAR1中的窗口大小字段决定。这决定了该BAR可以映射多大的内存区域。BAR2 BAR4用于组成64位内存空间BAR。当设备需要申请4GB以上的地址空间时就需要使用64位BAR。BAR2存放低32位地址BAR4存放高32位地址。在编程时需要先写BAR4高地址再写BAR2低地址并注意其类型标识。实操心得BAR的探测与分配操作系统或Bootloader通过向BAR写入全1再读回来探测BAR所需的大小。例如向一个32位非预取内存BAR写入0xFFFFFFFF读回的值可能是0xFFFFF000。低12位比特11-4保留3-0为类型和指示位为0表示该BAR需要2^12 4KB对齐的空间。驱动开发者在手动配置BAR时必须确保分配的内存区域满足其大小和对齐要求否则会导致设备无法正常工作或系统不稳定。5. 常见问题与排查技巧实录在实际开发和调试中围绕PCIe错误和配置访问我遇到过不少典型问题。以下是一些实录和解决思路。5.1 问题一系统启动时频繁报告PCIe Completion Timeout错误现象在Linux内核启动日志dmesg中持续看到pcieport或特定设备报告Completion Timeout错误但设备似乎还能被识别。排查步骤确认错误来源首先检查PEX_ERR_CAP_STAT寄存器确认ECV1且TO位指示错误来源。如果是外部设备GSID0x02通过PEX_ERR_CAP_R1的Requester ID定位设备。分析错误类型检查PEX_ERR_DR寄存器确认是PET完成超时位被置位。检查链路状态读取PEX_LTSSM_STAT寄存器确认链路是否处于L0正常工作状态。有时链路训练不彻底或信号质量差会导致设备间歇性无响应。检查配置确认对端设备的BAR空间是否被正确分配和映射。一个常见的错误是BAR所需空间大于实际分配的空间导致设备对部分地址范围的访问无响应。检查电源管理确认PCIe设备的电源状态。如果设备处于低功耗状态如L1、L2唤醒可能需要时间导致临时超时。可以尝试在BIOS或内核启动参数中禁用设备的ASPM主动状态电源管理。临时屏蔽如果确认是特定设备在初始化阶段暂时性超时可能其固件启动较慢可以在驱动初始化早期通过设置PEX_ERR_DISR寄存器的PCTD位来临时屏蔽此类超时错误待设备稳定后再开启。5.2 问题二通过ATMU窗口访问配置空间失败返回全1或全0现象使用ATMU窗口方法访问外部设备配置空间时读回的数据全是0xFFFFFFFF或0x00000000。排查思路验证ATMU窗口配置这是最常见的原因。仔细检查PEXOWARn寄存器ReadTType/WriteTType是否设置为0x2配置事务窗口大小SZ字段是否足够大以覆盖要访问的配置空间地址范围窗口是否已启用V位验证地址计算确保根据手册公式正确构造了PCIe配置地址[27:20]Bus, [19:15]Dev, [14:12]Func, [11:8]ExtReg, [7:2]RegNum并且这个地址落在了已编程的ATMU窗口的本地地址范围内。检查链路再次强调确保PCIe链路已训练成功PEX_LTSSM_STAT显示L0。ATMU访问同样依赖物理链路。检查访问权限确认当前处理器上下文如Bootloader或内核驱动有权限访问该ATMU窗口映射的物理内存区域。回退到寄存器方法作为对比测试使用PEX_CONFIG_ADDR/DATA方法访问同一个配置寄存器。如果这种方法成功而ATMU失败问题几乎肯定出在ATMU的配置或地址计算上。5.3 问题三设备驱动加载后系统不稳定或发生数据损坏现象设备驱动可以加载并识别设备但一旦开始数据传输如DMA系统就容易崩溃或数据出现错误。排查技巧检查BAR映射使用lspci -vvvLinux或类似工具确认设备的BAR被分配到了正确的、且与其他设备不冲突的物理地址上。特别检查64位BAR的高位部分是否正确。检查DMA寻址能力确认设备支持的DMA地址宽度通过PCIe能力结构中的Address Translation Cache或ATS相关寄存器并与系统IOMMU如SMMU或DMA掩码设置进行比对。如果设备只能进行32位DMA寻址却试图访问64位高地址会导致错误。启用并检查高级错误报告AER现代PCIe设备都支持AER能力结构。在操作系统中启用AER通常需要内核配置和驱动支持它能提供比标准状态寄存器更详细的错误信息如错误的TLP前缀、错误源ID等对于诊断数据链路层错误如ECRC错误、Flow Control Credit溢出至关重要。审查错误捕获寄存器在发生数据损坏时立即读取PEX_ERR_CAP_STAT和R0-R3寄存器。分析捕获的TLP包头看是否是预期的请求/完成包长度和地址是否正确。PEX_ERR_DR中的CDNSC带数据非成功完成或PCACCA完成位可能被置位指示了传输失败的具体类型。5.4 速查表关键寄存器访问与错误分析流程步骤目标操作/寄存器关键点1. 初始化配置错误处理PEX_ERR_DISR根据阶段初始化/调试/运行设置错误屏蔽位。先屏蔽后使能。准备错误捕获PEX_ERR_CAP_STAT写1清除ECV位确保捕获寄存器可用。检查链路PEX_LTSSM_STAT确认链路处于L0状态再进行任何配置访问。2. 运行时监控轮询错误状态PEX_ERR_DR定期或中断服务中检查定位错误类型。错误发生PEX_ERR_CAP_STAT检查ECV和TO判断错误是否被捕获及来源。3. 事后分析定位出错设备PEX_ERR_CAP_R1(GH1)提取Requester ID(Bus/Dev/Func)。分析出错事务PEX_ERR_CAP_R0(GH0)解析TLP的Fmt和Type判断操作类型内存读/写、配置等。获取详细地址PEX_ERR_CAP_R2(GH2)获取出错TLP的地址低32位如果是带地址的请求。4. 配置访问直接访问PEX_CONFIG_ADDR/DATA确保地址格式正确Enable位Bus/Dev/Func/Reg访问前链路已就绪。高效/批量访问出站ATMU窗口正确设置PEXOWARnTType0x2和PEXOWTRn确保地址映射计算正确。掌握MSC8251 PCIe控制器的错误处理和配置访问机制相当于为你的系统装上了高精度的诊断仪器和高效的设备管理工具。在看似复杂的寄存器描述背后是一套逻辑清晰、层次分明的硬件设计哲学。从错误检测的开关PEX_ERR_DISR到事故瞬间的黑匣子PEX_ERR_CAP_Rx再到灵活多样的设备寻址方式配置寄存器与ATMU每一个环节都为构建高可靠、易调试的嵌入式系统提供了坚实的基础。在实际项目中我习惯于在BSP中封装好这些寄存器的访问接口并实现一个简单的错误日志转储函数一旦系统出现PCIe相关异常就能第一时间将这套“黑匣子”数据保存下来为后续分析提供最直接的证据。记住硬件不会说谎这些寄存器里的数据就是它最真实的“证词”。