在MIPS标准的协处理器0(CP0)中定义一组硬件watchpoints接口,由于某些原因,龙芯3系列处理器并未实现,这就导致了在该架构Linux系统中用gdb watch只能使用软件断点,真心非常、非常慢。:(
好消息是龙芯3系列处理器是实现了MIPS EJTAG的,兼容2.61标准,那么能否利用MIPS EJTAG的硬件断点功能部件实现Linux ptrace的watchpoints功能呢?答案是肯定的。让我们一起看看具体的方法吧。
首先,我们需要更改BIOS中的异常处理函数,将EJTAG调试异常重新路由至Linux内核中处理,因为MIPS EJTAG异常处理程序的入口地址固定为0xbfc00480。
/* Debug exception */ .align 7 /* bfc00480 */ .set push .set noreorder .set arch=mips64r2 dmtc0 k0, CP0_DESAVE mfc0 k0, CP0_DEBUG andi k0, 0x2 beqz k0, 1f mfc0 k0, CP0_STATUS andi k0, 0x18 bnez k0, 2f nop 1: mfc0 k0, CP0_EBASE ins k0, zero, 0, 12 addiu k0, 0x480 jr k0 dmfc0 k0, CP0_DESAVE 2: la k0, 0xdeadbeef dmtc0 k0, CP0_DEPC dmfc0 k0, CP0_DESAVE deret .set pop |
这段处理程序实现了两个功能:
1. 将来自用户态的sdbbp指令触发的异常路由至地址 0xdeadbeef。
2. 将来自内核态的sdbbp指令触发的异常或是任意态的非sdbbp触发的异常路由至 ebase+0x480。
接着,我们还需要修改内核,实现下列功能:
1. 实现 EJTAG watch 相关的 probe、install、read、clear 等操作,及合适的调试异常处理程序。
2. 实现 Linux ptrace watch 接口与 EJTAG watch 的对接。
See: https://github.com/heiher/linux-stable/commits/ejtag-watch-4.9
Over!