static void pmc_setup_one_p4_counter(unsigned int ctr) { int i; int const maxbind = 2; unsigned int cccr = 0; unsigned int escr = 0; unsigned int high = 0; unsigned int counter_bit; struct p4_event_binding * ev = 0; unsigned int stag; stag = get_stagger(); /* convert from counter *number* to counter *bit* */ counter_bit = 1 << VIRT_CTR(stag, ctr); /* find our event binding structure. */ if (counter_config[ctr].event <= 0 || counter_config[ctr].event > NUM_EVENTS) { printk(KERN_ERR "oprofile: P4 event code 0x%lx out of range\n", counter_config[ctr].event); return; } ev = &(p4_events[counter_config[ctr].event - 1]); for (i = 0; i < maxbind; i++) { if (ev->bindings[i].virt_counter & counter_bit) { /* modify ESCR */ ESCR_READ(escr, high, ev, i); ESCR_CLEAR(escr); if (stag == 0) { ESCR_SET_USR_0(escr, counter_config[ctr].user); ESCR_SET_OS_0(escr, counter_config[ctr].kernel); } else { ESCR_SET_USR_1(escr, counter_config[ctr].user); ESCR_SET_OS_1(escr, counter_config[ctr].kernel); } ESCR_SET_EVENT_SELECT(escr, ev->event_select); ESCR_SET_EVENT_MASK(escr, counter_config[ctr].unit_mask); ESCR_WRITE(escr, high, ev, i); /* modify CCCR */ CCCR_READ(cccr, high, VIRT_CTR(stag, ctr)); CCCR_CLEAR(cccr); CCCR_SET_REQUIRED_BITS(cccr); CCCR_SET_ESCR_SELECT(cccr, ev->escr_select); if (stag == 0) { CCCR_SET_PMI_OVF_0(cccr); } else { CCCR_SET_PMI_OVF_1(cccr); } CCCR_WRITE(cccr, high, VIRT_CTR(stag, ctr)); return; } } }
static void p4_setup_ctrs(struct op_x86_model_spec const *model, struct op_msrs const * const msrs) { unsigned int i; unsigned int low, high; unsigned int stag; stag = get_stagger(); rdmsr(MSR_IA32_MISC_ENABLE, low, high); if (!MISC_PMC_ENABLED_P(low)) { printk(KERN_ERR "oprofile: P4 PMC not available\n"); return; } /* clear the cccrs we will use */ for (i = 0; i < num_counters; i++) { if (unlikely(!msrs->controls[i].addr)) continue; rdmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high); CCCR_CLEAR(low); CCCR_SET_REQUIRED_BITS(low); wrmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high); } /* clear all escrs (including those outside our concern) */ for (i = num_counters; i < num_controls; i++) { if (unlikely(!msrs->controls[i].addr)) continue; wrmsr(msrs->controls[i].addr, 0, 0); } /* setup all counters */ for (i = 0; i < num_counters; ++i) { if (counter_config[i].enabled && msrs->controls[i].addr) { reset_value[i] = counter_config[i].count; pmc_setup_one_p4_counter(i); wrmsrl(p4_counters[VIRT_CTR(stag, i)].counter_address, -(u64)counter_config[i].count); } else { reset_value[i] = 0; } } }
static void p4_setup_ctrs(struct op_msrs const * const msrs) { unsigned int i; unsigned int low, high; unsigned int addr; unsigned int stag; stag = get_stagger(); rdmsr(MSR_IA32_MISC_ENABLE, low, high); if (!MISC_PMC_ENABLED_P(low)) { printk(KERN_ERR "oprofile: P4 PMC not available\n"); return; } for (i = 0 ; i < num_counters ; i++) { rdmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high); CCCR_CLEAR(low); CCCR_SET_REQUIRED_BITS(low); wrmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high); } for (i = stag ; i < NUM_UNUSED_CCCRS ; i += addr_increment()) { rdmsr(p4_unused_cccr[i], low, high); CCCR_CLEAR(low); CCCR_SET_REQUIRED_BITS(low); wrmsr(p4_unused_cccr[i], low, high); } for (addr = MSR_P4_BSU_ESCR0 + stag; addr < MSR_P4_IQ_ESCR0; addr += addr_increment()) { wrmsr(addr, 0, 0); } if (boot_cpu_data.x86_model < 0x3) { wrmsr(MSR_P4_IQ_ESCR0, 0, 0); wrmsr(MSR_P4_IQ_ESCR1, 0, 0); } for (addr = MSR_P4_RAT_ESCR0 + stag; addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) { wrmsr(addr, 0, 0); } for (addr = MSR_P4_MS_ESCR0 + stag; addr <= MSR_P4_TC_ESCR1; addr += addr_increment()) { wrmsr(addr, 0, 0); } for (addr = MSR_P4_IX_ESCR0 + stag; addr <= MSR_P4_CRU_ESCR3; addr += addr_increment()) { wrmsr(addr, 0, 0); } if (num_counters == NUM_COUNTERS_NON_HT) { wrmsr(MSR_P4_CRU_ESCR4, 0, 0); wrmsr(MSR_P4_CRU_ESCR5, 0, 0); } else if (stag == 0) { wrmsr(MSR_P4_CRU_ESCR4, 0, 0); } else { wrmsr(MSR_P4_CRU_ESCR5, 0, 0); } for (i = 0 ; i < num_counters ; ++i) { if (sysctl.ctr[i].event) { pmc_setup_one_p4_counter(i); CTR_WRITE(sysctl.ctr[i].count, VIRT_CTR(stag, i)); } } }
static void pmc_setup_one_p4_counter(unsigned int ctr) { int i; int const maxbind = 2; unsigned int cccr = 0; unsigned int escr = 0; unsigned int high = 0; unsigned int counter_bit; struct p4_event_binding * ev = NULL; unsigned int stag; stag = get_stagger(); counter_bit = 1 << VIRT_CTR(stag, ctr); if (sysctl.ctr[ctr].event <= 0 || sysctl.ctr[ctr].event > NUM_EVENTS) { printk(KERN_ERR "oprofile: P4 event code 0x%x out of range\n", sysctl.ctr[ctr].event); return; } ev = &(p4_events[sysctl.ctr[ctr].event - 1]); for (i = 0; i < maxbind; i++) { if (ev->bindings[i].virt_counter & counter_bit) { ESCR_READ(escr, high, ev, i); ESCR_CLEAR(escr); if (stag == 0) { ESCR_SET_USR_0(escr, sysctl.ctr[ctr].user); ESCR_SET_OS_0(escr, sysctl.ctr[ctr].kernel); } else { ESCR_SET_USR_1(escr, sysctl.ctr[ctr].user); ESCR_SET_OS_1(escr, sysctl.ctr[ctr].kernel); } ESCR_SET_EVENT_SELECT(escr, ev->event_select); ESCR_SET_EVENT_MASK(escr, sysctl.ctr[ctr].unit_mask); ESCR_WRITE(escr, high, ev, i); CCCR_READ(cccr, high, VIRT_CTR(stag, ctr)); CCCR_CLEAR(cccr); CCCR_SET_REQUIRED_BITS(cccr); CCCR_SET_ESCR_SELECT(cccr, ev->escr_select); if (stag == 0) { CCCR_SET_PMI_OVF_0(cccr); } else { CCCR_SET_PMI_OVF_1(cccr); } CCCR_WRITE(cccr, high, VIRT_CTR(stag, ctr)); return; } } printk(KERN_ERR "oprofile: P4 event code 0x%x no binding, ctr %d\n", sysctl.ctr[ctr].event, ctr); }
static void p4_setup_ctrs(struct op_msrs const * const msrs) { unsigned int i; unsigned int low, high; unsigned int addr; unsigned int stag; stag = get_stagger(); rdmsr(MSR_IA32_MISC_ENABLE, low, high); if (! MISC_PMC_ENABLED_P(low)) { printk(KERN_ERR "oprofile: P4 PMC not available\n"); return; } /* clear the cccrs we will use */ for (i = 0 ; i < num_counters ; i++) { rdmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high); CCCR_CLEAR(low); CCCR_SET_REQUIRED_BITS(low); wrmsr(p4_counters[VIRT_CTR(stag, i)].cccr_address, low, high); } /* clear cccrs outside our concern */ for (i = stag ; i < NUM_UNUSED_CCCRS ; i += addr_increment()) { rdmsr(p4_unused_cccr[i], low, high); CCCR_CLEAR(low); CCCR_SET_REQUIRED_BITS(low); wrmsr(p4_unused_cccr[i], low, high); } /* clear all escrs (including those outside our concern) */ for (addr = MSR_P4_BSU_ESCR0 + stag; addr < MSR_P4_IQ_ESCR0; addr += addr_increment()) { wrmsr(addr, 0, 0); } /* On older models clear also MSR_P4_IQ_ESCR0/1 */ if (boot_cpu_data.x86_model < 0x3) { wrmsr(MSR_P4_IQ_ESCR0, 0, 0); wrmsr(MSR_P4_IQ_ESCR1, 0, 0); } for (addr = MSR_P4_RAT_ESCR0 + stag; addr <= MSR_P4_SSU_ESCR0; ++i, addr += addr_increment()) { wrmsr(addr, 0, 0); } for (addr = MSR_P4_MS_ESCR0 + stag; addr <= MSR_P4_TC_ESCR1; addr += addr_increment()){ wrmsr(addr, 0, 0); } for (addr = MSR_P4_IX_ESCR0 + stag; addr <= MSR_P4_CRU_ESCR3; addr += addr_increment()){ wrmsr(addr, 0, 0); } if (num_counters == NUM_COUNTERS_NON_HT) { wrmsr(MSR_P4_CRU_ESCR4, 0, 0); wrmsr(MSR_P4_CRU_ESCR5, 0, 0); } else if (stag == 0) { wrmsr(MSR_P4_CRU_ESCR4, 0, 0); } else { wrmsr(MSR_P4_CRU_ESCR5, 0, 0); } /* setup all counters */ for (i = 0 ; i < num_counters ; ++i) { if (counter_config[i].enabled) { reset_value[i] = counter_config[i].count; pmc_setup_one_p4_counter(i); CTR_WRITE(counter_config[i].count, VIRT_CTR(stag, i)); } else { reset_value[i] = 0; } } }