Hi Evan,
For now, I did the following (which feels a bit hacked but seems to work):
- After memory write access: Executing a fence.i and fence instruction. In my implementation, fence.i invalidates the instruction cache and fence flushes the data cache. This is mainly required to ensure that software breakpoints are visible to the CPU.
- Before memory read access: Executing a fence instruction to ensure that the debugger reads fresh data from memory when looking at memory content. I added a check to see if the CPU is halted or not because it seems the hook is also called when doing background memory reads using the SBA.
C
int HandleAfterMemAccessWrite(U32 Addr, U32 NumBytes, U32 Flags)
{
int ret;
JLINK_SYS_Report("Executing fence.i & fence instructions");
JLINK_RISCV_DMI_AutodetectDMISettings();
// Write fence.i instruction to progbuf0
ret = JLINK_RISCV_DMI_WriteReg(0x20, 0x0000100f);
// Write fence instruction to progbuf1
ret = JLINK_RISCV_DMI_WriteReg(0x21, 0x0000000f);
// Write to command register
// regno: 0x1000
// write: 0
// transfer: 0
// postexec: 1
// aarpostincrement: 0
// -> 0x00241000
ret = JLINK_RISCV_DMI_WriteReg(0x17, 0x00241000);
return 0;
}
int HandleBeforeMemAccessRead(U32 Addr, U32 NumBytes, U32 Flags)
{
int is_halted;
int ret;
is_halted = JLINK_TARGET_IsHalted();
if (is_halted == 1)
{
JLINK_SYS_Report("Executing fence instruction");
JLINK_RISCV_DMI_AutodetectDMISettings();
// Write fence instruction to progbuf0
ret = JLINK_RISCV_DMI_WriteReg(0x20, 0x0000000f);
// Write ebreak instruction to progbuf1
ret = JLINK_RISCV_DMI_WriteReg(0x21, 0x00100073);
// Write to command register
// regno: 0x1000
// write: 0
// transfer: 0
// postexec: 1
// aarpostincrement: 0
// -> 0x00241000
ret = JLINK_RISCV_DMI_WriteReg(0x17, 0x00241000);
}
return 0;
}
Display More