A correct method to use the x86 breakpoint registers (DR0-7)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I'm trying to set the x86 breakpoint registers to trip on write data.

After they are set, nothing seems to happen when I trigger them.

It's possible I'm not setting them correctly, I tried putting the
virt_to_phys() value in them. And, I tried looking at what KPROBE puts
in them, but it looks like kprobe doesn't use them at all.

In 2.6.11, arch/i386/ has 5 places where it modifies the db regs:
	do_debug()              in traps.c    (??)
	do_signal()             in signal.c   (re-enable them)
	fix_processor_context() in cpu.c      (reload them)
	__switch_to()		in process.c  (reload them)
	cpu_init()		in common.c   (clears them)

Just FYI: sometime after 2.6.11, the macros get_debugreg() and
set_debugreg() were defined in include/asm-i386/processor.h and set to
be used in the 5 places above. In any case, the functionality seems the
same the above routines. (And the registers names corrected s/db/dr/g )

In any case, setting these registers never seems to do anything. No INT3
or INT1 (is it really supposed to generate an interrupt?) Perhaps I need
to have kgdb setup.

The closest I can get to making anything happen is if I set bit 13 of
DR7 (triggers on the next access of the breakpoint registers) then when
I insmod I get:

root@foxtrot:~/dbregtest# insmod ./dbregtest.ko
Trace/breakpoint trap
root@foxtrot:~/dbregtest#

If I set BR0 with the value from virt_to_phys() I don't get this
trace/breakpoint trap.

Enjoy,
Jeff

// Current documentation for these registers is in Vol 3 Section 15.2:
// Also note: EFLAGS BIT 16 (Resume) section 2.3 disables #DB exceptions
// http://developer.intel.com/design/pentium4/manuals/index_new.htm

static int __init db_reg_test(void)
{
        u32 *i;
        unsigned int phys_addr;

        i = kmalloc( 0x1000, GFP_DMA );
        printk("i == 0x%08X\n", (int) i);
        phys_addr = virt_to_phys(i);

        printk("virt_to_phys(i)  == 0x%08X\n", (int) phys_addr);
        __asm__ __volatile__( "movl %0, %%dr0\n" : : "r" (phys_addr) );

        // clear out the DR6 status register
        __asm__ __volatile__( "movl %0, %%dr6\n" : : "r" (0xFFFF0FF0) );

        // Enable DR0 as a global breakpoint
        __asm__ __volatile__( "movl %0, %%dr7\n" : : "r" (0x00030002) );

        // Enables all four BR registers as global breakpoints
        __asm__ __volatile__( "movl %0, %%dr7\n" : : "r" (0x333300AA) );

        // shouldn't this trigger a breakpoint exception?
        i[0] = 0xDEADBEEF;

        kfree(i);

	// this will correctly trigger a breakpoint
	// __asm__ ( "movl %0, %%dr7\n" : : "r" (0x333320AA) );
        // __asm__ ( "movl %0, %%dr7\n" : : "r" (0x333300AA) );
        return 0;
}

module_init(db_reg_test);

root@foxtrot:~/dbregtest# tail /var/log/kern.log
Jul  5 09:01:16 localhost kernel: i == 0xC046E000
Jul  5 09:01:16 localhost kernel: virt_to_phys(i)  == 0x0046E000



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]
  Powered by Linux