【ARM Coresight Debug 系列 -- ARMv8/v9 Watchpoint 软件实现地址监控详细介绍】

发布于:2024-06-16 ⋅ 阅读:(21) ⋅ 点赞:(0)


请阅读【嵌入式开发学习必备专栏 】


ARMv8/v9 Watchpoint exceptions

在ARMv8/v9架构中,可以通过配置 DBGWVR0_EL1 调试寄存器设置硬件观察点(Watchpoint)。这个寄存器是一系列观察点值寄存器(DBGWVRn_EL1,其中n代表寄存器的编号)中的第一个:

• DBGWCR0_EL1 and DBGWVR0_EL1 are for watchpoint number zero.
• DBGWCR1_EL1 and DBGWVR1_EL1 are for watchpoint number one.
• DBGWCR2_EL1 and DBGWVR2_EL1 are for watchpoint number two.
• …
• …
• DBGWCR<n-1>_EL1 and DBGWVR<n-1>_EL1 are for watchpoint number (n-1)

通过设置DBGWVR0_EL1,开发人员可以指定特定的内存地址,当处理器访问这个地址时(无论是读取还是写入),就会触发一个调试异常,从而允许开发者中断程序的执行来调查程序的当前状态。

Watchpoint 配置信息读取

在这里插入图片描述
可以通过系统寄存器 ID_AA64DFR0_EL1, AArch64 Debug Feature Register 0 来获取芯片上watch point 及其它debug 组件的实现情况:

  • WRPs, bits [23:20]: 存储watch point的个数;
  • Bits [19:16]: 存放实现breakpoint 实现的个数;
  • PMUVer, bits [11:8]: 显示 PMU的版本;
  • TraceVer, bits [7:4]: 展示trace 某块是否实现;
  • DebugVer, bits [3:0]: 显示 Debug 版本:
    • 0b0110 Armv8 debug architecture.
    • 0b0111 Armv8 debug architecture with Virtualization Host Extensions.
    • 0b1000 Armv8.2 debug architecture, FEAT_Debugv8p2.
    • 0b1001 Armv8.4 debug architecture, FEAT_Debugv8p4.
    • 0b1010 Armv8.8 debug architecture, FEAT_Debugv8p8.

DBGWVR0_EL1寄存器通常在需要密切监视程序对特定内存位置的访问时使用,这对于调试复杂的内存问题,如缓冲区溢出、意外的内存修改、追踪变量的变化等情况,都非常有用。

一个 Watchpoint 可以监控一个地址上的1到多个字节,当访问到正在监控的字节后,watchpoint 会产生一个 watchpoint debug event。watchpoint 监控的字节数可以配置为下面两种情况:

  • 监控1-8个字节,通过配置DBGWCR<n>_EL1.BAS选择要监控的字节数;
  • 监控8字节-2G地址范围,在这种情况下需要满足下面两个条件:
    • 监控的字节数是2的幂次方:2bytes
    • 要监控的起始地址要为地址size的N倍

通过配置 DBGWCR<n>_EL1.MASK 来设置要监控的8字节到2G的范围。

watchpoint debug event 可以触发 watchpoint exception 或者是让CPU进入Debug state,如果配置了EDSCR.HDE那么当产生watchpoint debug event 的时候系统将会进入 Debug state,否者是产生watchpoint exception。

Execution conditions

可以控制watchpoint在特定的条件下产生,比如只在Non-secure EL2 条件下产生。在哪种条件下可以产生watchpoint exception是通过配置DBGWCR<n>_EL1.{SSC, HMC, PAC} 决定的,如下表所示:
在这里插入图片描述

注意:本篇文章是在EL3异常等级下测试的

Watchpoint data address comparisons

我们知道ARMv8/v9 下 虚拟地址默认最大为48bit,但是也可以配置为52bit的使用场景。
在这里插入图片描述
关于ARMv8/v9 MMU 配置推荐阅读【ARM Cache 及 MMU/MPU 系列文章专栏导读】

Size of the data access

可以通过配置DBGWCR<n>_EL1.MASK 来设置监控的地址范围,需要注意的是在使用Mask 方式配置地址监控范围时需要将DBGWCR<n>_EL1.BAS全部配置为1,因为需要将地址上的所有字节都进行监控。
在这里插入图片描述

  • 如果配置监控0x80bytes的地址范围,bit[28:14] = 0b00111
  • 如果配置监控1M的地址范围,bit[28:14] = 0b10100
  • 如果配置监控1G的地址范围,bit[28:14] = 0b11110
  • 如果配置监控2G的地址范围,bit[28:14] = 0b11111

Watchpoint 软件配置流程

  1. 访问权限:首先,确保你有权限访问DBGWVR0_EL1寄存器。这通常要求你处于EL1或更高的异常级别,并且可能需要确保适当的调试权限已经被设置,本文测试代码是运行在EL3异常等级上的。
  2. 设置内存地址:将你希望监视的内存地址写入DBGWVR0_EL1。当处理器尝试访问这个地址时,就会触发调试异常。
  3. 配置观察点控制寄存器(DBGWCR0_EL1):与DBGWVR0_EL1一起使用的还有相应的控制寄存器(例如DBGWCR0_EL1),它用于配置观察点的行为,比如访问类型:读、写或执行和条件。
    • DBGWCR<n>_EL1.LSC来配置监控读写的行为;
    • DBGWCR<n>_EL1.E 来使能 watchpoint;
  4. 启用观察能力:通过适当配置相关的控制寄存器,确保观察点被启用。
  5. 运行调试会话:当程序执行过程中访问到DBGWVR0_EL1指定的地址时,将触发观察点,此时可以通过调试器查看程序状态,包括寄存器、内存和其他有用的调试信息。
  6. 处理观察点触发:一旦观察点触发,你可以使用调试器来检查程序的状态、修改变量或寄存器的值,或是单步执行程序来进一步调试。

Watchpoint Type 使用介绍

DBGWCR<n>_EL1寄存器中,DBGWCR<n>_EL1.WT字段和DBGWCR<n>_EL1.LBN分别控制观察点的类型和与其他断点的链接方式。

WT, Bit [20]: Watchpoint Type

WT位用于指定观察点的类型。这里有两种可能的值:

  • 0b0: Unlinked Data Address Match 当设置为0b0时,表示这个观察点为非链接的数据地址匹配类型。这意味着当处理器访问一个与观察点设置匹配的内存地址时,将会触发一个调试事件,不管当前的执行上下文是否与某个特定的断点相关联。
  • 0b1: Linked Data Address Match 当设置为0b1时,观察点为链接的数据地址匹配类型。这种类型的观察点将会与一个断点(Breakpoint)相关联,只有当该断点的条件(例如,特定的PC值或上下文匹配)被满足时,对于匹配的数据地址的访问才会触发调试事件。
LBN, Bits [19:16]

Linked Breakpoint Number LBN字段用于指定与观察点链接的断点的编号。这对于设置链接的数据地址匹配观察点(即WT位设置为0b1时)尤其重要。LBN字段允许你指定一个断点寄存器的索引号,只有当该断点被触发时,链接的观察点才会激活。

Watchpoint Type 使用场景

将观察点(Watchpoint)和断点(Breakpoint)链接起来使用,可以使调试过程更加精细和灵活。例如,你可以设置一个断点来监视特定函数的入口,然后通过设置链接的观察点来监视该函数中特定变量的读写操作。这样,只有当执行流达到特定函数时,对于变量的访问才会触发调试事件,从而帮助开发者更加准确地诊断和调试软件问题。

实例:
假设有一个场景,你希望监视在达到某个函数地址(由断点监视)时,某个特定全局变量(由观察点监视)的写操作。你可以这样配置:

  1. 设置一个断点(Breakpoint),指定其地址为函数的地址。
  2. 设置一个观察点(Watchpoint),指定其地址为全局变量的地址,设置WT位为0b1(Linked Data Address Match),并将LBN设置为步骤1中断点的编号。

Watchpoint 注意事项

  • 实现依赖性:不同的ARMv8实现可能支持不同数量的观察点和断点寄存器。DBGWVR0_EL1是系列中的第一个寄存器,但总体数量和具体支持的特性可能因具体的ARMv8处理器而异。
  • 安全和权限控制:对DBGWVR0_EL1寄存器的访问可能受到安全和权限控制的限制,确保在合适的安全上下文中使用这些寄存器,尤其是在多用户或安全敏感的环境中。
  • 性能影响:使用硬件观察点可能影响程序的执行性能。在性能敏感的代码区域使用时要特别注意。
    DBGWVR0_EL1等寄存器的使用是ARMv8架构提供的强大调试功能之一,使得开发者能够更有效地监控和调试软件,特别是在处理复杂的内存相关错误时。正确使用这些工具需要对ARM架构和操作系统的权限模型有深入的理解。

watchpoint 代码实现地址监控见【ARM Coresight Debug 系列 – ARMv8/v9 Watchpoint 代码实现2G地址范围监控】