What's wrong when watchpoint doesn't watch?

I've been trying to get a watchpoint to trigger, but no luck.

There should be 4 watchpoints accordíng to DBGDIDR, DBGDSCR=0x0204000e, so there shouldn't be any problems there?

I use (just in case) the cp14 interface - write DBGWVR0 and DBGWCR0 and read them back to see that the values went there.

Then I access the memory location, but nothing happens. Oh, and there are no masks in the CPSR set.

The program runs in non-secure SVC-mode.

Here's the watchpoint setting code:

void rpi2_set_watchpoint(unsigned int num, unsigned int addr, unsigned int control)
{
    char scratchpad[9];
    SYNC;

    volatile uint32_t *pval;
    pval = (volatile uint32_t *)(dbg_reg_base + 0x088);

#if 0
    // if memory-mapped interface works
    //  96-111 0x180-0x1BC DBGWVRm 4 watchpoint values
    // 112-127 0x1C0-0x1FC DBGWCRm 4 watchpoint controls
    uint32_t *pval, *pctrl;
    pval = (volatile uint32_t *)(dbg_reg_base + 0x180);
    pctrl = (volatile uint32_t *)(dbg_reg_base + 0x1c0);
    pval[num] = (uint32_t)addr;
    pctrl[num] = control;
#else
    // have to use cp14
    switch (num)
    {
    case 0:
        serial_raw_puts("\r\nwatch0!\r\n");
        // write to DBGWVR0
        asm volatile ("mcr p14, 0, %[val], c0, c0, 6\n\t" ::[val] "r" (addr) :);
        // write to DBGWCR0
        asm volatile ("mcr p14, 0, %[ctl], c0, c0, 7\n\t" ::[ctl] "r" (control) :);
        // debug
        asm volatile ("mrc p14, 0, %[val], c0, c0, 6\n\t" :[val] "=r" (addr) ::);
        asm volatile ("mrc p14, 0, %[ctl], c0, c0, 7\n\t" :[ctl] "=r" (control) ::);
        serial_raw_puts("DBGWVR0: ");
        util_word_to_hex(scratchpad, addr);
        serial_raw_puts(scratchpad);
        serial_raw_puts(" DBGWCR0: ");
        util_word_to_hex(scratchpad, control);
        serial_raw_puts(scratchpad);
        serial_raw_puts(" DBGDSCR: ");
        util_word_to_hex(scratchpad, *pval);
        serial_raw_puts(scratchpad);
        serial_raw_puts("\r\n");
        break;
    case 1:
        serial_raw_puts("\r\nwatch1!\r\n");
        // write to DBGWVR1
        asm volatile ("mcr p14, 0, %[val], c0, c1, 6\n\t" ::[val] "r" (addr) :);
        // write to DBGWCR1
        asm volatile ("mcr p14, 0, %[ctl], c0, c1, 7\n\t" ::[ctl] "r" (control) :);
        break;
    case 2:
        serial_raw_puts("\r\nwatch2!\r\n");
        // write to DBGWVR2
        asm volatile ("mcr p14, 0, %[val], c0, c2, 6\n\t" ::[val] "r" (addr) :);
        // write to DBGWCR2
        asm volatile ("mcr p14, 0, %[ctl], c0, c2, 7\n\t" ::[ctl] "r" (control) :);
        break;
    case 3:
        serial_raw_puts("\r\nwatch3!\r\n");
        // write to DBGWVR3
        asm volatile ("mcr p14, 0, %[val], c0, c3, 6\n\t" ::[val] "r" (addr) :);
        // write to DBGWCR3
        asm volatile ("mcr p14, 0, %[ctl], c0, c3, 7\n\t" ::[ctl] "r" (control) :);
        break;
    default:
        serial_raw_puts("\r\nwatch?!\r\n");
        // do nothing;
        break;
    }
#endif
    SYNC;
}

The machine is Raspberry Pi 2B if that helps.

The output from the function (through dgb):

w \x00](gdb) watch g_testloc

Sending packet: $m8360,4#9e...[\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][

r +]Ack

[$][7][0][8][3][0][0][0][0][#][9][2]Packet received: 70830000

[

w \x00]Sending packet: $m8360,4#9e...[\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][

r +]Ack

[$][7][0][8][3][0][0][0][0][#][9][2]Packet received: 70830000

[

w \x00]Hardware watchpoint 1: g_testloc

(gdb) cont

Continuing.

Sending packet: $m8360,4#9e...[\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][

r +]Ack

[$][7][0][8][3][0][0][0][0][#][9][2]Packet received: 70830000

[

w \x00]Sending packet: $Z2,8360,4#e9...[\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][

r +]Ack

[\r][\n][w][a][t][c][h][ ][n][u][m][=][ ][0][0][0][0][0][0][0][0][ ][v][a][l][=][0][0][0][0][8][3][6][0][ ][c][t][r][l][0][0][0][0][2][1][f][7][\r][\n][\r][\n][w][a][t][c][h][0][!][\r][\n][D][B][G][W][V][R][0][:][ ][0][0][0][0][8][3][6][0][ ][D][B][G][W][C][R][0][:][ ][0][0][0][0][2][1][f][7][ ][D][B][G][D][S][C][R][:][ ][0][2][0][4][0][0][0][e][\r][\n][$][O][K][#][9][a]Packet received: OK

[

w \x00]Packet Z2 (write-watchpoint) is supported

Sending packet: $vCont?#49...[\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][\x00][

r +]Ack

[$][#][0][0]Packet received:

The address of g_testloc is indeed 0x8360

Disassembly of section .bss:

00008360 <g_testloc>:

    8360:    00000000     andeq    r0, r0, r0

Parents
  • I started reading about debug modes instead of debug events, and...

    Is it so that HW breakpoints and watchpoints generate debug events, and (invasive) debug mode must be enabled to 'catch' the debug events? And bkpts have worked without any debug mode because bkpt causes both debug event and PABT exception, and it's the 'PABT exception part' that has been working?

    And if so, what kind of restrictions does invasive debug monitor mode introduce (if any) compared to the situation with both debug modes disabled?

Reply
  • I started reading about debug modes instead of debug events, and...

    Is it so that HW breakpoints and watchpoints generate debug events, and (invasive) debug mode must be enabled to 'catch' the debug events? And bkpts have worked without any debug mode because bkpt causes both debug event and PABT exception, and it's the 'PABT exception part' that has been working?

    And if so, what kind of restrictions does invasive debug monitor mode introduce (if any) compared to the situation with both debug modes disabled?

Children