예제 #1
0
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;
		}
	}
}
예제 #2
0
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;
		}
	}
}
예제 #3
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));
		}
	}
}
예제 #4
0
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);
}
예제 #5
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;
	}

	/* 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;
		}
	}
}