update PAPI support.
This commit is contained in:
@ -14,6 +14,7 @@
|
||||
#include <registers.h>
|
||||
|
||||
extern unsigned int *x86_march_perfmap;
|
||||
static unsigned long pmc_status = 0x0;
|
||||
|
||||
#define X86_CR4_PCE 0x00000100
|
||||
|
||||
@ -33,20 +34,51 @@ static int set_perfctr_x86_direct(int counter, int mode, unsigned int value)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (mode & PERFCTR_USER_MODE) {
|
||||
// clear mode flags
|
||||
value &= ~(3 << 16);
|
||||
|
||||
// set mode flags
|
||||
if(mode & PERFCTR_USER_MODE) {
|
||||
value |= 1 << 16;
|
||||
}
|
||||
if (mode & PERFCTR_KERNEL_MODE) {
|
||||
}
|
||||
if(mode & PERFCTR_KERNEL_MODE) {
|
||||
value |= 1 << 17;
|
||||
}
|
||||
}
|
||||
|
||||
// wrmsr(MSR_PERF_GLOBAL_CTRL, 0);
|
||||
|
||||
value |= (1 << 22) | (1 << 18); /* EN */
|
||||
value |= (1 << 20); /* Enable overflow interrupt */
|
||||
|
||||
wrmsr(MSR_IA32_PERFEVTSEL0 + counter, value);
|
||||
|
||||
kprintf("wrmsr: %d <= %x\n", MSR_PERF_GLOBAL_CTRL, 0);
|
||||
//kprintf("wrmsr: %d <= %x\n", MSR_PERF_GLOBAL_CTRL, 0);
|
||||
kprintf("wrmsr: %d <= %x\n", MSR_IA32_PERFEVTSEL0 + counter, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_pmc_x86_direct(int counter, unsigned long val)
|
||||
{
|
||||
unsigned long cnt_bit = 0;
|
||||
|
||||
if (counter < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cnt_bit = 1UL << counter;
|
||||
if ( cnt_bit & X86_IA32_PERF_COUNTERS_MASK ) {
|
||||
// set generic pmc
|
||||
wrmsr(MSR_IA32_PMC0 + counter, val);
|
||||
}
|
||||
else if ( cnt_bit & X86_IA32_FIXED_PERF_COUNTERS_MASK ) {
|
||||
// set fixed pmc
|
||||
wrmsr(MSR_IA32_FIXED_CTR0 + counter - X86_IA32_BASE_FIXED_PERF_COUNTERS, val);
|
||||
}
|
||||
else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -57,6 +89,37 @@ static int set_perfctr_x86(int counter, int event, int mask, int inv, int count,
|
||||
CVAL2(event, mask, inv, count));
|
||||
}
|
||||
|
||||
static int set_fixed_counter(int counter, int mode)
|
||||
{
|
||||
unsigned long value = 0;
|
||||
unsigned int ctr_mask = 0x7;
|
||||
int counter_idx = counter - X86_IA32_BASE_FIXED_PERF_COUNTERS ;
|
||||
unsigned int set_val = 0;
|
||||
|
||||
if (counter_idx < 0 || counter_idx >= X86_IA32_NUM_FIXED_PERF_COUNTERS) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// clear specified fixed counter info
|
||||
value = rdmsr(MSR_PERF_FIXED_CTRL);
|
||||
ctr_mask <<= counter_idx * 4;
|
||||
value &= ~ctr_mask;
|
||||
|
||||
if (mode & PERFCTR_USER_MODE) {
|
||||
set_val |= 1 << 1;
|
||||
}
|
||||
if (mode & PERFCTR_KERNEL_MODE) {
|
||||
set_val |= 1;
|
||||
}
|
||||
|
||||
set_val <<= counter_idx * 4;
|
||||
value |= set_val;
|
||||
|
||||
wrmsr(MSR_PERF_FIXED_CTRL, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ihk_mc_perfctr_init_raw(int counter, unsigned int code, int mode)
|
||||
{
|
||||
if (counter < 0 || counter >= X86_IA32_NUM_PERF_COUNTERS) {
|
||||
@ -86,14 +149,15 @@ extern void x86_march_perfctr_start(unsigned long counter_mask);
|
||||
|
||||
int ihk_mc_perfctr_start(unsigned long counter_mask)
|
||||
{
|
||||
unsigned int value = 0;
|
||||
unsigned long value = 0;
|
||||
unsigned long mask = X86_IA32_PERF_COUNTERS_MASK | X86_IA32_FIXED_PERF_COUNTERS_MASK;
|
||||
|
||||
#ifdef HAVE_MARCH_PERFCTR_START
|
||||
x86_march_perfctr_start(counter_mask);
|
||||
#endif
|
||||
counter_mask &= ((1 << X86_IA32_NUM_PERF_COUNTERS) - 1);
|
||||
counter_mask &= mask;
|
||||
value = rdmsr(MSR_PERF_GLOBAL_CTRL);
|
||||
value |= counter_mask;
|
||||
value |= counter_mask;
|
||||
wrmsr(MSR_PERF_GLOBAL_CTRL, value);
|
||||
|
||||
return 0;
|
||||
@ -101,9 +165,10 @@ int ihk_mc_perfctr_start(unsigned long counter_mask)
|
||||
|
||||
int ihk_mc_perfctr_stop(unsigned long counter_mask)
|
||||
{
|
||||
unsigned int value;
|
||||
unsigned long value;
|
||||
unsigned long mask = X86_IA32_PERF_COUNTERS_MASK | X86_IA32_FIXED_PERF_COUNTERS_MASK;
|
||||
|
||||
counter_mask &= ((1 << X86_IA32_NUM_PERF_COUNTERS) - 1);
|
||||
counter_mask &= mask;
|
||||
value = rdmsr(MSR_PERF_GLOBAL_CTRL);
|
||||
value &= ~counter_mask;
|
||||
wrmsr(MSR_PERF_GLOBAL_CTRL, value);
|
||||
@ -111,17 +176,48 @@ int ihk_mc_perfctr_stop(unsigned long counter_mask)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ihk_mc_perfctr_reset(int counter)
|
||||
// init for fixed counter
|
||||
int ihk_mc_perfctr_fixed_init(int counter, int mode)
|
||||
{
|
||||
if (counter < 0 || counter >= X86_IA32_NUM_PERF_COUNTERS) {
|
||||
unsigned long value = 0;
|
||||
unsigned int ctr_mask = 0x7;
|
||||
int counter_idx = counter - X86_IA32_BASE_FIXED_PERF_COUNTERS ;
|
||||
unsigned int set_val = 0;
|
||||
|
||||
if (counter_idx < 0 || counter_idx >= X86_IA32_NUM_FIXED_PERF_COUNTERS) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
wrmsr(MSR_IA32_PMC0 + counter, 0);
|
||||
// clear specified fixed counter info
|
||||
value = rdmsr(MSR_PERF_FIXED_CTRL);
|
||||
ctr_mask <<= counter_idx * 4;
|
||||
value &= ~ctr_mask;
|
||||
|
||||
if (mode & PERFCTR_USER_MODE) {
|
||||
set_val |= 1 << 1;
|
||||
}
|
||||
if (mode & PERFCTR_KERNEL_MODE) {
|
||||
set_val |= 1;
|
||||
}
|
||||
|
||||
set_val <<= counter_idx * 4;
|
||||
value |= set_val;
|
||||
|
||||
wrmsr(MSR_PERF_FIXED_CTRL, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ihk_mc_perfctr_reset(int counter)
|
||||
{
|
||||
return set_pmc_x86_direct(counter, 0);
|
||||
}
|
||||
|
||||
int ihk_mc_perfctr_set(int counter, unsigned long val)
|
||||
{
|
||||
return set_pmc_x86_direct(counter, val);
|
||||
}
|
||||
|
||||
int ihk_mc_perfctr_read_mask(unsigned long counter_mask, unsigned long *value)
|
||||
{
|
||||
int i, j;
|
||||
@ -137,10 +233,89 @@ int ihk_mc_perfctr_read_mask(unsigned long counter_mask, unsigned long *value)
|
||||
|
||||
unsigned long ihk_mc_perfctr_read(int counter)
|
||||
{
|
||||
if (counter < 0 || counter >= X86_IA32_NUM_PERF_COUNTERS) {
|
||||
unsigned long retval = 0;
|
||||
unsigned long cnt_bit = 0;
|
||||
|
||||
if (counter < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rdpmc(counter);
|
||||
cnt_bit = 1UL << counter;
|
||||
|
||||
if ( cnt_bit & X86_IA32_PERF_COUNTERS_MASK ) {
|
||||
// read generic pmc
|
||||
retval = rdpmc(counter);
|
||||
}
|
||||
else if ( cnt_bit & X86_IA32_FIXED_PERF_COUNTERS_MASK ) {
|
||||
// read fixed pmc
|
||||
retval = rdpmc((1 << 30) + (counter - X86_IA32_BASE_FIXED_PERF_COUNTERS));
|
||||
}
|
||||
else {
|
||||
retval = -EINVAL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
// read by rdmsr
|
||||
unsigned long ihk_mc_perfctr_read_msr(int counter)
|
||||
{
|
||||
unsigned int idx = 0;
|
||||
unsigned long retval = 0;
|
||||
unsigned long cnt_bit = 0;
|
||||
|
||||
if (counter < 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cnt_bit = 1UL << counter;
|
||||
|
||||
if ( cnt_bit & X86_IA32_PERF_COUNTERS_MASK ) {
|
||||
// read generic pmc
|
||||
idx = MSR_IA32_PMC0 + counter;
|
||||
retval = (unsigned long) rdmsr(idx);
|
||||
}
|
||||
else if ( cnt_bit & X86_IA32_FIXED_PERF_COUNTERS_MASK ) {
|
||||
// read fixed pmc
|
||||
idx = MSR_IA32_FIXED_CTR0 + counter;
|
||||
retval = (unsigned long) rdmsr(idx);
|
||||
}
|
||||
else {
|
||||
retval = -EINVAL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
int ihk_mc_perfctr_alloc_counter()
|
||||
{
|
||||
int i = 0;
|
||||
int ret = -1;
|
||||
|
||||
// find avail generic counter
|
||||
for(i = 0; i < X86_IA32_NUM_PERF_COUNTERS; i++) {
|
||||
if(!(pmc_status & (1 << i))) {
|
||||
ret = i;
|
||||
pmc_status |= (1 << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(ret < 0){
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ihk_mc_perfctr_release_counter(int counter)
|
||||
{
|
||||
unsigned long value = 0;
|
||||
|
||||
value = rdmsr(MSR_PERF_GLOBAL_CTRL);
|
||||
value &= ~(1UL << counter);
|
||||
pmc_status &= ~(1UL << counter);
|
||||
|
||||
wrmsr(MSR_PERF_GLOBAL_CTRL, 0);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user