From: Adam F. <ada...@po...> - 2003-08-26 08:13:12
|
Hello,l this is the first time i write to oprofile-list. I want to count some statistics from MSR register. So i took oprofile code and wrote my module that enables read/write MSR register. But when loaded this code causes OOPS. Even when i comment all the CTR and CTRL calls and just call CTRL_READ(l,h,msrs,0); i get OOPS... can somemone please tell me why (or have i forget about sth or so)? Underneath there is the code #include <linux/module.h> #include <linux/kernel.h> #include <linux/mm.h> #include <asm/msr.h> #include <asm/uaccess.h> #include <asm/smplock.h> /* MSRs */ #ifndef MSR_P6_PERFCTR0 #define MSR_P6_PERFCTR0 0xc1 #endif #ifndef MSR_P6_PERFCTR1 #define MSR_P6_PERFCTR1 0xc2 #endif #ifndef MSR_P6_EVNTSEL0 #define MSR_P6_EVNTSEL0 0x186 #endif #ifndef MSR_P6_EVNTSEL1 #define MSR_P6_EVNTSEL1 0x187 #endif #ifndef MSR_K7_EVNTSEL0 #define MSR_K7_EVNTSEL0 0xc0010000 #endif #ifndef MSR_K7_EVNTSEL1 #define MSR_K7_EVNTSEL1 0xc0010001 #endif #ifndef MSR_K7_PERFCTR0 #define MSR_K7_PERFCTR0 0xc0010004 #endif #ifndef MSR_K7_PERFCTR1 #define MSR_K7_PERFCTR1 0xc0010005 #endif // event:0xc0 counters:0,1 um:zero minimum:6000 name:INST_RETIRED : number of instructions retired // event:0xc2 counters:0,1 um:zero minimum:6000 name:UOPS_RETIRED : number of UOPs retired // event:0xc8 counters:0,1 um:zero minimum:500 name:HW_INT_RX : number of hardware interrupts received // event:0xd0 counters:0,1 um:zero minimum:6000 name:INST_DECODED : number of instructions decoded #define NUM_COUNTERS 2 #define NUM_CONTROLS 2 #define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters.addrs[(c)], (l), (h));} while (0) #define CTR_WRITE(l,msrs,c) do {wrmsr(msrs->counters.addrs[(c)], -(unsigned int)(l), -1);} while (0) #define CTR_OVERFLOWED(n) (!((n) & (1U<<31))) #define CTRL_READ(l,h,msrs,c) do {rdmsr((msrs->controls.addrs[(c)]), (l), (h));} while (0) #define CTRL_WRITE(l,h,msrs,c) do {wrmsr((msrs->controls.addrs[(c)]), (l), (h));} while (0) #define CTRL_SET_ACTIVE(n) (n |= (1<<22)) #define CTRL_SET_INACTIVE(n) (n &= ~(1<<22)) #define CTRL_CLEAR(x) (x &= (1<<21)) #define CTRL_SET_ENABLE(val) (val |= 1<<20) #define CTRL_SET_USR(val,u) (val |= ((u & 1) << 16)) #define CTRL_SET_KERN(val,k) (val |= ((k & 1) << 17)) #define CTRL_SET_UM(val, m) (val |= (m << 8)) #define CTRL_SET_EVENT(val, e) (val |= e) struct oprof_counter { int count; int enabled; int event; int kernel; int user; int unit_mask; }; typedef struct counter{ int addrs[2]; }counter; typedef struct control{ int addrs[2]; }control; typedef struct regs{ struct counter counters; struct control controls; }regs; struct regs *msrs; struct counter counters; struct control controls; struct oprof_counter ctr[2]; static void ppro_fill_in_addresses(struct regs *msrs) { msrs->counters.addrs[0] = MSR_P6_PERFCTR0; msrs->counters.addrs[1] = MSR_P6_PERFCTR1; msrs->controls.addrs[0] = MSR_P6_EVNTSEL0; msrs->controls.addrs[1] = MSR_P6_EVNTSEL1; } static void ppro_setup_ctrs(struct regs *msrs) { unsigned int low, high; int i; /* clear all counters */ for (i = 0 ; i < NUM_CONTROLS; ++i) { CTRL_READ(low, high, msrs, i); <<<<< take a look at here. Why it causes OOPS ??????????? // CTRL_CLEAR(low); // CTRL_WRITE(low, high, msrs, i); } } static void ppro_check_ctrs(struct regs *msrs) { unsigned int low, high; int i; for (i = 0 ; i < NUM_COUNTERS; ++i) { // CTR_READ(low, high, msrs, i); // if (CTR_OVERFLOWED(low)) { // op_do_profile(cpu, instruction_pointer(regs), IRQ_ENABLED(regs), i); // CTR_WRITE(oprof_data[cpu].ctr_count[i], msrs, i); // } } //printk("Oto zawartosc rejestru[low=%i,high=%i] = %lu\n",i,low,high); } static void ppro_start(struct regs * msrs) { unsigned int low,high; // CTRL_READ(low, high, msrs, 0); // CTRL_SET_ACTIVE(low); // CTRL_WRITE(low, high, msrs, 0); } static void ppro_stop(struct regs *msrs) { unsigned int low,high; // CTRL_READ(low, high, msrs, 0); // CTRL_SET_INACTIVE(low); // CTRL_WRITE(low, high, msrs, 0); } int init_module() { msrs = (struct regs *)kmalloc(sizeof(struct regs),GFP_ATOMIC); ppro_fill_in_addresses(msrs); ppro_start(msrs); ppro_setup_ctrs(msrs); ppro_check_ctrs(msrs); ppro_stop(msrs); return 0; } int cleanup_module() { return 0; } |
From: Adam F. <ada...@po...> - 2003-08-26 08:17:25
|
Hello, this is the first time i write to oprofile-list. I want to count some statistics from MSR register. So i took oprofile code and wrote my module that enables read/write MSR register. But when loaded this code causes OOPS. Even when i comment all the CTR and CTRL calls and just call CTRL_READ(l,h,msrs,0); i get OOPS... can somemone please tell me why (or have i forget about sth or so)? Underneath there is the code #include <linux/module.h> #include <linux/kernel.h> #include <linux/mm.h> #include <asm/msr.h> #include <asm/uaccess.h> #include <asm/smplock.h> /* MSRs */ #ifndef MSR_P6_PERFCTR0 #define MSR_P6_PERFCTR0 0xc1 #endif #ifndef MSR_P6_PERFCTR1 #define MSR_P6_PERFCTR1 0xc2 #endif #ifndef MSR_P6_EVNTSEL0 #define MSR_P6_EVNTSEL0 0x186 #endif #ifndef MSR_P6_EVNTSEL1 #define MSR_P6_EVNTSEL1 0x187 #endif #ifndef MSR_K7_EVNTSEL0 #define MSR_K7_EVNTSEL0 0xc0010000 #endif #ifndef MSR_K7_EVNTSEL1 #define MSR_K7_EVNTSEL1 0xc0010001 #endif #ifndef MSR_K7_PERFCTR0 #define MSR_K7_PERFCTR0 0xc0010004 #endif #ifndef MSR_K7_PERFCTR1 #define MSR_K7_PERFCTR1 0xc0010005 #endif // event:0xc0 counters:0,1 um:zero minimum:6000 name:INST_RETIRED : number of instructions retired // event:0xc2 counters:0,1 um:zero minimum:6000 name:UOPS_RETIRED : number of UOPs retired // event:0xc8 counters:0,1 um:zero minimum:500 name:HW_INT_RX : number of hardware interrupts received // event:0xd0 counters:0,1 um:zero minimum:6000 name:INST_DECODED : number of instructions decoded #define NUM_COUNTERS 2 #define NUM_CONTROLS 2 #define CTR_READ(l,h,msrs,c) do {rdmsr(msrs->counters.addrs[(c)], (l), (h));} while (0) #define CTR_WRITE(l,msrs,c) do {wrmsr(msrs->counters.addrs[(c)], -(unsigned int)(l), -1);} while (0) #define CTR_OVERFLOWED(n) (!((n) & (1U<<31))) #define CTRL_READ(l,h,msrs,c) do {rdmsr((msrs->controls.addrs[(c)]), (l), (h));} while (0) #define CTRL_WRITE(l,h,msrs,c) do {wrmsr((msrs->controls.addrs[(c)]), (l), (h));} while (0) #define CTRL_SET_ACTIVE(n) (n |= (1<<22)) #define CTRL_SET_INACTIVE(n) (n &= ~(1<<22)) #define CTRL_CLEAR(x) (x &= (1<<21)) #define CTRL_SET_ENABLE(val) (val |= 1<<20) #define CTRL_SET_USR(val,u) (val |= ((u & 1) << 16)) #define CTRL_SET_KERN(val,k) (val |= ((k & 1) << 17)) #define CTRL_SET_UM(val, m) (val |= (m << 8)) #define CTRL_SET_EVENT(val, e) (val |= e) struct oprof_counter { int count; int enabled; int event; int kernel; int user; int unit_mask; }; typedef struct counter{ int addrs[2]; }counter; typedef struct control{ int addrs[2]; }control; typedef struct regs{ struct counter counters; struct control controls; }regs; struct regs *msrs; struct counter counters; struct control controls; struct oprof_counter ctr[2]; static void ppro_fill_in_addresses(struct regs *msrs) { msrs->counters.addrs[0] = MSR_P6_PERFCTR0; msrs->counters.addrs[1] = MSR_P6_PERFCTR1; msrs->controls.addrs[0] = MSR_P6_EVNTSEL0; msrs->controls.addrs[1] = MSR_P6_EVNTSEL1; } static void ppro_setup_ctrs(struct regs *msrs) { unsigned int low, high; int i; /* clear all counters */ for (i = 0 ; i < NUM_CONTROLS; ++i) { CTRL_READ(low, high, msrs, i); <<<<< take a look at here. Why it causes OOPS ??????????? // CTRL_CLEAR(low); // CTRL_WRITE(low, high, msrs, i); } } static void ppro_check_ctrs(struct regs *msrs) { unsigned int low, high; int i; for (i = 0 ; i < NUM_COUNTERS; ++i) { // CTR_READ(low, high, msrs, i); // if (CTR_OVERFLOWED(low)) { // op_do_profile(cpu, instruction_pointer(regs), IRQ_ENABLED(regs), i); // CTR_WRITE(oprof_data[cpu].ctr_count[i], msrs, i); // } } //printk("Oto zawartosc rejestru[low=%i,high=%i] = %lu\n",i,low,high); } static void ppro_start(struct regs * msrs) { unsigned int low,high; // CTRL_READ(low, high, msrs, 0); // CTRL_SET_ACTIVE(low); // CTRL_WRITE(low, high, msrs, 0); } static void ppro_stop(struct regs *msrs) { unsigned int low,high; // CTRL_READ(low, high, msrs, 0); // CTRL_SET_INACTIVE(low); // CTRL_WRITE(low, high, msrs, 0); } int init_module() { msrs = (struct regs *)kmalloc(sizeof(struct regs),GFP_ATOMIC); ppro_fill_in_addresses(msrs); ppro_start(msrs); ppro_setup_ctrs(msrs); ppro_check_ctrs(msrs); ppro_stop(msrs); return 0; } int cleanup_module() { return 0; } |
From: Philippe E. <ph...@wa...> - 2003-08-26 11:23:25
|
Adam Flizikowski wrote: > Hello, > > this is the first time i write to oprofile-list. > > I want to count some statistics from MSR register. So i took oprofile code > and wrote my module that enables read/write MSR register. > > But when loaded this code causes OOPS. Even when i comment all the CTR and > CTRL calls and just call CTRL_READ(l,h,msrs,0); i get OOPS... > > can somemone please tell me why (or have i forget about sth or so)? > int init_module() { > > msrs = (struct regs *)kmalloc(sizeof(struct regs),GFP_ATOMIC); I tried with GFP_KERNEL not GFP_ATOMIC and it works fine on my box. Perhaps a previous version was faulting: on my 2.4.21 if a fault occur during init_module() subsequent load will faut in insmod even after fixing the fault cause. (look the oops to see if it's the case) reboot cure the problem. regards, Phil |
From: Adam F. <ada...@po...> - 2003-08-26 12:21:12
Attachments:
read_msr.c
|
Philippe, thanks for your answer (BTW it is pleasure to talk with author of this code underneath :) ). you were right. it works now. but... i wanted this module to read instruction count and interruptions count (on PIII processor). I send whole module to you (with change you adviced). Please take a look at lines: **************************************************************** // event:0xc0 counters:0,1 um:zero minimum:6000 name:INST_RETIRED : number of instructions retired ctr[0].event = 0xc0; ctr[0].count = 0; ctr[0].kernel = 1; ctr[0].user = 0; ctr[0].unit_mask = 0x0; ctr[0].enabled = 1; // event:0xc8 counters:0,1 um:zero minimum:500 name:HW_INT_RX : number of hardware interrupts received ctr[1].event = 0xc8; ctr[1].count = 0; ctr[1].kernel = 1; ctr[1].user = 0; ctr[1].unit_mask = 0x0; ctr[1].enabled = 1; ************************************************************ and please tell me, if you can, is this well configured to tell number of instructions executed and HW int received??? Later on in init_module(): *************************************************** ppro_fill_in_addresses(msrs); ppro_start(msrs); ppro_setup_ctrs(msrs); for(a=0; a<600000; a++){b+=a;} << does it measures instr.count for this loop??? ppro_check_ctrs(msrs); ppro_stop(msrs); *************************************************** are these function calls well in sequence to give information i want? BTW what should be (or is at your PC) outcome? should it change? I want to measure some blocks of code inside kernel with this probes.. but how can i if i dont knwo if this is right??? thanks for helping in advance regards adam |