0

I am interested in generating a breakpoint exception in arm64 (aarch64), using LiteOS as working OS. To not be unclear, a Breakpoint exception is generated whenever the processor element tries to execute an instruction from a particular address (this shouldn't be confused with "breakpoint instruction exceptions", i.e. instruction bkpt or int, like in this question).

The section BREAKPOINT EXCEPTION of AARCH64 manual treats what I want to achieve (and this question as well, but it didn't solve my problem).

Before explaining my problem, let me say that I verified that my CPU supports hardware breakpoints: bits [15:12] of register ID_AA64DFR0_EL1 (manual here) are 0b1010 = 5-1 = 4 breakpoint supported.

In my userspace, I have a simple function:

void justAFunction()
{
    printf("justAFunction has been called, did you block?\n");
}

Before calling this function, the userland process "set a breakpoint":

[...]
setBreakpoint((void *)justAFunction); /* this is a system call to the kernel */
[...]
justAFunction();
[...]

setBreakpoint is a system call, and I implemented the kernel code as follow (like kvm code, the only reference I found in this respect, here):

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();
}

Description for DBGBCR0_EL1 and DBGBVR0_EL1: here.

Specifically:

#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)

After trying to write addr (namely justAFunction virtual address) to DBGBVR0_EL1, I tried to re-read the same register, and the content was correct.

What I expected is to raise a debug exception (which are enabled in my kernel because I am able to raise a breakpoint instruction like bkpt or to single-step my application) once the userland process tried to execute justAFunction.

Unfortunately, nothing happens. justAFunction is executed and the exception vector is not triggered (I have verified with gdb).

My feeling is that I missed something, but I can't find what.

1 Answers1

1

You want your breakpoint to hit at EL0, but you configure it for EL1. Drop the DBGBCR_EL1 flag.

Also, you probably don't want to read the current contents of DBGBCR0_EL1, but rather overwrite them completely.

Replace this:

AARCH64_SYSREG_WRITE(DBGBCR0_EL1, (AARCH64_SYSREG_READ(DBGBCR0_EL1) | DBGBCR_E | DBGBCR_LEN8 | DBGBCR_EXEC | DBGBCR_EL1));

with this:

AARCH64_SYSREG_WRITE(DBGBCR0_EL1, (DBGBCR_E | DBGBCR_LEN8 | DBGBCR_EXEC));
Siguza
  • 21,155
  • 6
  • 52
  • 89
  • Hello @Siguza, thanks for your answer. What you say it's always pertinent. I still have doubts, sorry. I don't think registers `DBGBCR_EL0` and `DBGBVR_EL0` exist. How can I target EL0? Thanks – ParisHilton Feb 24 '22 at 17:24
  • That's not what I meant. I clarified my answer. – Siguza Feb 24 '22 at 17:27
  • Thanks for the clarification. Unfortunately, I still can't get the exception ... – ParisHilton Feb 24 '22 at 17:30