⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 op_model_p4.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 2 页
字号:
#define ESCR_CLEAR(escr) ((escr) &= ESCR_RESERVED_BITS)#define ESCR_SET_USR_0(escr, usr) ((escr) |= (((usr) & 1) << 2))#define ESCR_SET_OS_0(escr, os) ((escr) |= (((os) & 1) << 3))#define ESCR_SET_USR_1(escr, usr) ((escr) |= (((usr) & 1)))#define ESCR_SET_OS_1(escr, os) ((escr) |= (((os) & 1) << 1))#define ESCR_SET_EVENT_SELECT(escr, sel) ((escr) |= (((sel) & 0x1f) << 25))#define ESCR_SET_EVENT_MASK(escr, mask) ((escr) |= (((mask) & 0xffff) << 9))#define ESCR_READ(escr,high,ev,i) do {rdmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0);#define ESCR_WRITE(escr,high,ev,i) do {wrmsr(ev->bindings[(i)].escr_address, (escr), (high));} while (0);#define CCCR_RESERVED_BITS 0x38030FFF#define CCCR_CLEAR(cccr) ((cccr) &= CCCR_RESERVED_BITS)#define CCCR_SET_REQUIRED_BITS(cccr) ((cccr) |= 0x00030000)#define CCCR_SET_ESCR_SELECT(cccr, sel) ((cccr) |= (((sel) & 0x07) << 13))#define CCCR_SET_PMI_OVF_0(cccr) ((cccr) |= (1<<26))#define CCCR_SET_PMI_OVF_1(cccr) ((cccr) |= (1<<27))#define CCCR_SET_ENABLE(cccr) ((cccr) |= (1<<12))#define CCCR_SET_DISABLE(cccr) ((cccr) &= ~(1<<12))#define CCCR_READ(low, high, i) do {rdmsr (p4_counters[(i)].cccr_address, (low), (high));} while (0);#define CCCR_WRITE(low, high, i) do {wrmsr (p4_counters[(i)].cccr_address, (low), (high));} while (0);#define CCCR_OVF_P(cccr) ((cccr) & (1U<<31))#define CCCR_CLEAR_OVF(cccr) ((cccr) &= (~(1U<<31)))#define CTR_READ(l,h,i) do {rdmsr(p4_counters[(i)].counter_address, (l), (h));} while (0);#define CTR_WRITE(l,i) do {wrmsr(p4_counters[(i)].counter_address, -(u32)(l), -1);} while (0);#define CTR_OVERFLOW_P(ctr) (!((ctr) & 0x80000000))/* these access the underlying cccrs 1-18, not the subset of 8 bound to "virtual counters" */#define RAW_CCCR_READ(low, high, i) do {rdmsr (MSR_P4_BPU_CCCR0 + (i), (low), (high));} while (0);#define RAW_CCCR_WRITE(low, high, i) do {wrmsr (MSR_P4_BPU_CCCR0 + (i), (low), (high));} while (0);/* this assigns a "stagger" to the current CPU, which is used throughout   the code in this module as an extra array offset, to select the "even"   or "odd" part of all the divided resources. */static inline unsigned int get_stagger(void) {	#ifdef CONFIG_SMP	int cpu;	if (smp_num_siblings > 1) {		cpu = smp_processor_id();		return (cpu_sibling_map[cpu] > cpu) ? 0 : 1;	} #endif		return 0;}/* finally, mediate access to a real hardware counter   by passing a "virtual" counter numer to this macro,   along with your stagger setting. */#define VIRT_CTR(stagger, i) ((i) + ((num_counters) * (stagger)))static unsigned long reset_value[NUM_COUNTERS_NON_HT];static void p4_fill_in_addresses(struct op_msrs * const msrs){	int i; 	unsigned int addr, stag;	setup_num_counters();	stag = get_stagger();	/* the 8 counter registers we pay attention to */	for (i = 0; i < num_counters; ++i)		msrs->counters.addrs[i] = 			p4_counters[VIRT_CTR(stag, i)].counter_address;	/* 18 CCCR registers */	for (i=stag, addr = MSR_P4_BPU_CCCR0;	     addr <= MSR_P4_IQ_CCCR5; ++i, addr += (1 + stag)) 		msrs->controls.addrs[i] = addr;		/* 43 ESCR registers */	for (addr = MSR_P4_BSU_ESCR0;	     addr <= MSR_P4_SSU_ESCR0; ++i, addr += (1 + stag)){ 		msrs->controls.addrs[i] = addr;	}		for (addr = MSR_P4_MS_ESCR0;	     addr <= MSR_P4_TC_ESCR1; ++i, addr += (1 + stag)){ 		msrs->controls.addrs[i] = addr;	}		for (addr = MSR_P4_IX_ESCR0;	     addr <= MSR_P4_CRU_ESCR3; ++i, addr += (1 + stag)){ 		msrs->controls.addrs[i] = addr;	}	/* there are 2 remaining non-contiguously located ESCRs */	if (num_counters == NUM_COUNTERS_NON_HT) {				/* standard non-HT CPUs handle both remaining ESCRs*/		msrs->controls.addrs[i++] = MSR_P4_CRU_ESCR5;		msrs->controls.addrs[i++] = MSR_P4_CRU_ESCR4;	} else if (stag == 0) {		/* HT CPUs give the first remainder to the even thread, as		   the 32nd control register */		msrs->controls.addrs[i++] = MSR_P4_CRU_ESCR4;	} else {		/* and two copies of the second to the odd thread,		   for the 31st and 32nd control registers */		msrs->controls.addrs[i++] = MSR_P4_CRU_ESCR5;		msrs->controls.addrs[i++] = MSR_P4_CRU_ESCR5;	}}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 << 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_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 all cccrs (including those outside our concern) */	for (i = stag ; i < num_cccrs ; i += (1 + stag)) {		RAW_CCCR_READ(low, high, i);		CCCR_CLEAR(low);		CCCR_SET_REQUIRED_BITS(low);		RAW_CCCR_WRITE(low, high, i);	}	/* clear all escrs (including those outside out concern) */	for (addr = MSR_P4_BSU_ESCR0 + stag;	     addr <= MSR_P4_SSU_ESCR0; addr += (1 + stag)){ 		wrmsr(addr, 0, 0);	}		for (addr = MSR_P4_MS_ESCR0 + stag;	     addr <= MSR_P4_TC_ESCR1; addr += (1 + stag)){ 		wrmsr(addr, 0, 0);	}		for (addr = MSR_P4_IX_ESCR0 + stag;	     addr <= MSR_P4_CRU_ESCR3; addr += (1 + stag)){ 		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].event) {			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;		}	}}static int p4_check_ctrs(unsigned int const cpu, 			  struct op_msrs const * const msrs,			  struct pt_regs * const regs){	unsigned long ctr, low, high, stag, real;	int i;	stag = get_stagger();	for (i = 0; i < num_counters; ++i) {				if (!counter_config[i].event) 			continue;		/* 		 * there is some eccentricity in the hardware which		 * requires that we perform 2 extra corrections:		 *		 * - check both the CCCR:OVF flag for overflow and the		 *   counter high bit for un-flagged overflows.		 *		 * - write the counter back twice to ensure it gets		 *   updated properly.		 * 		 * the former seems to be related to extra NMIs happening		 * during the current NMI; the latter is reported as errata		 * N15 in intel doc 249199-029, pentium 4 specification		 * update, though their suggested work-around does not		 * appear to solve the problem.		 */				real = VIRT_CTR(stag, i);		CCCR_READ(low, high, real); 		CTR_READ(ctr, high, real);		if (CCCR_OVF_P(low) || CTR_OVERFLOW_P(ctr)) {			oprofile_add_sample(regs->eip, i, cpu); 			CTR_WRITE(reset_value[i], real);			CCCR_CLEAR_OVF(low);			CCCR_WRITE(low, high, real); 			CTR_WRITE(reset_value[i], real);			/* P4 quirk: you have to re-unmask the apic vector */			apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);			return 1;		}	}	/* P4 quirk: you have to re-unmask the apic vector */	apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);	return 0;}static void p4_start(struct op_msrs const * const msrs){	unsigned int low, high, stag;	int i;	stag = get_stagger();	for (i = 0; i < num_counters; ++i) {		if (!reset_value[i]) continue;		CCCR_READ(low, high, VIRT_CTR(stag, i));		CCCR_SET_ENABLE(low);		CCCR_WRITE(low, high, VIRT_CTR(stag, i));	}}static void p4_stop(struct op_msrs const * const msrs){	unsigned int low, high, stag;	int i;	stag = get_stagger();	for (i = 0; i < num_counters; ++i) {		CCCR_READ(low, high, VIRT_CTR(stag, i));		CCCR_SET_DISABLE(low);		CCCR_WRITE(low, high, VIRT_CTR(stag, i));	}}#ifdef CONFIG_SMPstruct op_x86_model_spec const op_p4_ht2_spec = {	.num_counters = NUM_COUNTERS_HT2,	.num_controls = NUM_CONTROLS_HT2,	.fill_in_addresses = &p4_fill_in_addresses,	.setup_ctrs = &p4_setup_ctrs,	.check_ctrs = &p4_check_ctrs,	.start = &p4_start,	.stop = &p4_stop};#endifstruct op_x86_model_spec const op_p4_spec = {	.num_counters = NUM_COUNTERS_NON_HT,	.num_controls = NUM_CONTROLS_NON_HT,	.fill_in_addresses = &p4_fill_in_addresses,	.setup_ctrs = &p4_setup_ctrs,	.check_ctrs = &p4_check_ctrs,	.start = &p4_start,	.stop = &p4_stop};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -