Hardware breakpoints on MIPS

Bruce Korb bruce.korb@gmail.com
Thu Jan 29 23:01:00 GMT 2015


    FSF's Position regarding SCO's attacks on Free Software

This comes from gdb's GNU.org web page.
I think SCO has stopped attacking now. :)

Anyway, I need to set a hardware breakpoint on a Mips CPU on a "Cavium" platform
in a kernel module.  As I read the data sheet, I should need to write
to CP0 registers
18 and 19, with 18 containing a kernel virtual address plus three bits
for indicating
an instruction, write access or read access; then I need to write 0x40000007 to
register 19.  Except the interrupt doesn't fire and I've been unable
to figure out
what I've got wrong.  Code follows, for folks that can follow it and know how it
ought to work.  I surely do thank you for any hints you can give:


#define WW_W_BIT 0
#define WW_R_BIT 1
#define WW_I_BIT 2

#define WW_W_MASK (1UL << WW_W_BIT)
#define WW_R_MASK (1UL << WW_R_BIT)
#define WW_I_MASK (1UL << WW_I_BIT)

#define WW_IRW_MASK (WW_I_MASK | WW_R_MASK | WW_W_MASK)

static inline void watch_word(void * addr, unsigned int mask)
{
    typedef struct {
        unsigned is_inst_watch : 1; // true --> instruction watch
        unsigned do_exception  : 1;
        unsigned unused_29_24  : 6;
        unsigned asid          : 8; // IFF "do_exception" is false
        unsigned unused_15_12  : 4;
        unsigned mask          : 9;
        unsigned found_ins     : 1;
        unsigned found_read    : 1;
        unsigned found_write   : 1;
    } watch_lo_bits_t;

    U64 watchlo;
    union {
        watch_lo_bits_t bits;
        U32 word;
    } watchhi;

    watchlo = (U64)addr;
    watchlo = (watchlo & ~WW_IRW_MASK) | mask;  // watch for write access

    watchhi.bits = (watch_lo_bits_t) {
        .do_exception  = 1,
        .found_ins     = 1,
        .found_read    = 1,
        .found_write   = 1
    };
    assert(watchhi.word == 0x40000007);

    if ((mask & WW_I_MASK) != 0) {
        write_c0_watchlo0(watchlo);  // macro from asm/mipsregs.h
        write_c0_watchhi0(watchhi.word);
    } else {
        write_c0_watchlo1(watchlo);
        write_c0_watchhi1(watchhi.word);
    }
}



More information about the Gdb mailing list