我有兴趣在arm64(aarch64)中生成断点异常,使用LiteOS作为工作操作系统。为了不不清楚,每当处理器元素尝试从特定地址执行指令时,就会生成断点异常(这不应与“断点指令异常”混淆,即指令
bkpt
或 int
,如 中所示)这个问题)。
AARCH64手册的断点异常部分处理了我想要实现的目标(以及这个问题,但它没有解决我的问题)。
在解释我的问题之前,让我说我验证了我的CPU支持硬件断点:寄存器ID_AA64DFR0_EL1
(手册这里)的位[15:12]是
0b1010
= 5-1 =
4
断点支持.在我的用户空间中,我有一个简单的功能:
void justAFunction()
{
printf("justAFunction has been called, did you block?\n");
}
在调用该函数之前,用户态进程“设置断点”:
[...]
setBreakpoint((void *)justAFunction); /* this is a system call to the kernel */
[...]
justAFunction();
[...]
setBreakpoint
是一个系统调用,我实现的内核代码如下(如kvm代码,我在这方面找到的唯一参考,这里):
void setBreakpoint(void *addr)
{
AARCH64_SYSREG_WRITE(DBGBVR0_EL1, addr);
AARCH64_SYSREG_WRITE(DBGBCR0_EL1, (AARCH64_SYSREG_READ(DBGBCR0_EL1) | DBGBCR_E | DBGBCR_LEN8 | DBGBCR_EXEC | DBGBCR_EL1));
isb();
asm volatile("msr daifclr, #8");
AARCH64_SYSREG_WRITE(mdscr_el1, (AARCH64_SYSREG_READ(mdscr_el1) | MDSCR_KDE | MDSCR_MDE));
isb();
}
DBGBCR0_EL1
和
DBGBVR0_EL1
的说明:这里。 具体:
#define DBGBCR_LEN8 (0xff << 5)
#define DBGBCR_EXEC (0x0 << 3)
#define DBGBCR_EL1 (0x1 << 1)
#define DBGBCR_E (0x1 << 0)
#define MDSCR_KDE (1 << 13)
#define MDSCR_MDE (1 << 15)
尝试将addr
(即
justAFunction
虚拟地址)写入
DBGBVR0_EL1
后,我尝试重新读取相同的寄存器,内容是正确的。我期望的是一旦用户态进程尝试执行
bkpt
,就会引发调试异常(在我的内核中启用,因为我能够引发像
justAFunction
这样的断点指令或单步执行我的应用程序)。不幸的是,什么也没发生。
justAFunction
被执行并且异常向量没有被触发(我已经用gdb验证过)。我的感觉是我错过了一些东西,但我找不到什么。
DBGBCR_EL1
旗帜。此外,您可能不想读取
DBGBCR0_EL1
的当前内容,而是完全覆盖它们。替换这个:
AARCH64_SYSREG_WRITE(DBGBCR0_EL1, (AARCH64_SYSREG_READ(DBGBCR0_EL1) | DBGBCR_E | DBGBCR_LEN8 | DBGBCR_EXEC | DBGBCR_EL1));
这样:
AARCH64_SYSREG_WRITE(DBGBCR0_EL1, (DBGBCR_E | DBGBCR_LEN8 | DBGBCR_EXEC));
0b10
而不是
0b01
(而不是
0b00
,因为这些位符合 Siguza 的建议)。因此,再加一个定义,
#define DBGBCR_EL0 (0x2 << 1)
对控制寄存器的正确写入是
AARCH64_SYSREG_WRITE(DBGBCR0_EL1, (DBGBCR_E | DBGBCR_LEN8 | DBGBCR_EL0));
注意,我放弃了 DBGBCR_EXEC
,因为它是 0。在
架构参考手册中,它指出HMC、SSCE、SSC和PMC位都需要一起考虑,但我认为对于这种情况,我们可以在其他字段中保留零。
HMC | SSCE | SSC | PMC || EL3 | EL2 | EL1 | EL0
-----------------------------------------------
0 | 0 | 00 | 01 || - | - | Y | -
0 | 0 | 00 | 10 || - | - | - | Y
0 | 0 | 00 | 11 || - | - | Y | Y
...
完整表格请参见D2.8.4 断点生成断点异常的执行条件。