请阅读【嵌入式开发学习必备专栏 】
文章目录
- ARMv8/v9 Watchpoint exceptions
- Watchpoint 配置信息读取
- Execution conditions
- Watchpoint data address comparisons
- Size of the data access
- Watchpoint 软件配置流程
- Watchpoint Type 使用介绍
- WT, Bit [20]: Watchpoint Type
- LBN, Bits [19:16]
- Watchpoint Type 使用场景
- Watchpoint 注意事项
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
,因为需要将地址上的所有字节都进行监控。
- 如果配置监控
0x80
bytes的地址范围,bit[28:14]
=0b00111
- 如果配置监控1M的地址范围,
bit[28:14]
=0b10100
- 如果配置监控1G的地址范围,
bit[28:14]
=0b11110
- 如果配置监控2G的地址范围,
bit[28:14]
=0b11111
Watchpoint 软件配置流程
- 访问权限:首先,确保你有权限访问
DBGWVR0_EL1
寄存器。这通常要求你处于EL1或更高的异常级别,并且可能需要确保适当的调试权限已经被设置,本文测试代码是运行在EL3异常等级上的。 - 设置内存地址:将你希望监视的内存地址写入
DBGWVR0_EL1
。当处理器尝试访问这个地址时,就会触发调试异常。 - 配置观察点控制寄存器(DBGWCR0_EL1):与
DBGWVR0_EL1
一起使用的还有相应的控制寄存器(例如DBGWCR0_EL1
),它用于配置观察点的行为,比如访问类型:读、写或执行和条件。DBGWCR<n>_EL1.LSC
来配置监控读写的行为;DBGWCR<n>_EL1.E
来使能 watchpoint;
- 启用观察能力:通过适当配置相关的控制寄存器,确保观察点被启用。
- 运行调试会话:当程序执行过程中访问到
DBGWVR0_EL1
指定的地址时,将触发观察点,此时可以通过调试器查看程序状态,包括寄存器、内存和其他有用的调试信息。 - 处理观察点触发:一旦观察点触发,你可以使用调试器来检查程序的状态、修改变量或寄存器的值,或是单步执行程序来进一步调试。
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)链接起来使用,可以使调试过程更加精细和灵活。例如,你可以设置一个断点来监视特定函数的入口,然后通过设置链接的观察点来监视该函数中特定变量的读写操作。这样,只有当执行流达到特定函数时,对于变量的访问才会触发调试事件,从而帮助开发者更加准确地诊断和调试软件问题。
实例:
假设有一个场景,你希望监视在达到某个函数地址(由断点监视)时,某个特定全局变量(由观察点监视)的写操作。你可以这样配置:
- 设置一个断点(Breakpoint),指定其地址为函数的地址。
- 设置一个观察点(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地址范围监控】