dr7 register enabled global but ran only once.

"Ying Chu" <[email protected]> Tue, 20 Mar 2007 18:22:35 +0800
Newsgroups gmane.linux.application
Message-ID <[email protected]>
I used the dr0 register to trigger the int 1 exception when some
instruction fetched.
Even I enabled the global option in dr7,it still only run only once.
Any suggestions?
-----
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("example DR register.");

extern void my_debug_routine(void);

unsigned long ret_from_intr_p=0xc0102fc9; // ret_from_intr ,Got it
from /proc/kallsyms.

unsigned long old_debug_routine_p;
unsigned long my_debug_routine_p=(unsigned long)&my_debug_routine;

struct dr7_bit {
       unsigned gl0:2;  unsigned gl1:2;  unsigned gl2:2;  unsigned gl3:2;
       unsigned gle:2;  unsigned rsvd:1; unsigned non1:2; unsigned
gd:1; unsigned non0:2;
       unsigned rw0:2;  unsigned len0:2; unsigned rw1:2;  unsigned len1:2;
       unsigned rw2:2;  unsigned len2:2; unsigned rw3:2;  unsigned len3:2;
};

void open_debug_register(void)
{
       unsigned long rd0,rd7 = 0UL;
       struct dr7_bit *dr7;
       rd0 = ret_from_intr_p;
       dr7 = (struct dr7_bit *)&rd7;

       dr7->gle = 3;
       dr7->rsvd=1;

       dr7->len0 = 0;
       dr7->rw0 = 0;
       dr7->gl0 = 2;        // global enable.

     __asm__("mov %0,%%ebx \n\tmov %%ebx,%%dr7\n\tmov %1,%%ebx\n\tmov
%%ebx,%%dr0" ::"m"(rd7),"m"(rd0));

}

struct descriptor_idt
{
       unsigned short offset_low,seg_selector;
       unsigned char reserved,flag;
       unsigned short offset_high;
};

unsigned long counter=0UL;
void show_counter_value(void)
{
       printk("current counter is %lu\n",counter);
}

void my_debug_routine(void)
{
       __asm__ __volatile__("\n\taddl $1,%0\n\tjmp
*%1":"=m"(counter):"m"(old_debug_routine_p));
}

void update_idt_entry (int n, unsigned long *addr, int how)
{
       unsigned char idtr[6];
       struct descriptor_idt * idt_p;
       __asm__ __volatile__ ("sidt %0": "=m" (idtr));
       idt_p= &((struct descriptor_idt*)*(unsigned long*)&idtr[2])[n];
       switch (how){
               case 0:
                       *addr= (idt_p->offset_high <<16)+ idt_p->offset_low;
                       break;
               case 1:
                       idt_p->offset_high= (unsigned short)(*addr >> 16);
                       idt_p->offset_low = (unsigned short)(*addr & 0x0000ffff);
                       break;
       }
       return ;
}

int my_module_init(void)
{
       open_debug_register();
       update_idt_entry(1,&old_debug_routine_p,0);
       update_idt_entry(1,&my_debug_routine_p,1);
       return 0;
}

void my_module_exit(void)
{
       update_idt_entry(1,&old_debug_routine_p,1);
       show_counter_value();
       return ;
}

module_init(my_module_init);
module_exit(my_module_exit);
-
To unsubscribe from this list: send the line "unsubscribe linux-apps" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html