This is the mail archive of the
gdb@sourceware.org
mailing list for the GDB project.
Re: Hardware breakpoints on MIPS
- From: David Daney <ddaney dot cavm at gmail dot com>
- To: Bruce Korb <bruce dot korb at gmail dot com>
- Cc: gdb at sourceware dot org, linux-mips <linux-mips at linux-mips dot org>
- Date: Thu, 29 Jan 2015 15:01:23 -0800
- Subject: Re: Hardware breakpoints on MIPS
- Authentication-results: sourceware.org; auth=none
- References: <CAKRnqN+Js_zDn==T0+-EGzyTSW4P-dpvB7jKsLmFJEbKhxifJw at mail dot gmail dot com>
On 01/29/2015 02:05 PM, Bruce Korb wrote:
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:
This would appear to be for the most part, completely independent of
GDB, and thus perhaps not a good candidate for the gdb@mailing list.
What happens inside of the Linux kernel running on a MIPS{,64} CPU is
often discussed on linux-mips@linux-mips.org.
Since many years ago, WatchLo and WatchHi have been under the control of
the Linux kernel. If you set these registers and a Watch Exception is
triggered, it will cause the registers to be cleared and the exception
will be ignored, unless they were configured via ptrace(2) for userspace
addresses.
For debugging kernel space with watchpoint registers on OCTEON it is
probably best to use the facilities in the EJTAG unit.
David Daney
#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);
}
}