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

📄 perfmon.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	case PMC_SUBCMD_TIMESLICE_ENABLE:		pmc_timeslice_enable(pdata); 		break;	case PMC_SUBCMD_TIMESLICE_DISABLE:		pmc_timeslice_disable(pdata); 		break;	case PMC_SUBCMD_TIMESLICE_SET:		pmc_timeslice_set(pdata); 		break;	default:		return(-1);	}	return(0); }static long plpar_perfmon(int mode){        return plpar_hcall_norets(H_PERFMON, mode, 0); }static void pmc_configure_hardware() {	/* 	 * Debug bus enabled is required on GP for timeslice mode.	 * Flood enabled is required on GP for PMC cycle profile mode	 *   iSeries SP sets this by default.  pSeries requires the OS to enable.	 */	if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) {		/* Set up the debug bus to pmc mode - a feature of GP */		switch(systemcfg->platform) {		case PLATFORM_ISERIES_LPAR:			HvCall_setDebugBus(1);			break;		case PLATFORM_PSERIES_LPAR:			plpar_perfmon(1);			break;		case PLATFORM_PSERIES:			mtspr(HID0, mfspr(HID0) | 0x0000080000000000);		} 	} }/* * pmc_profile * * Profile the kernel based on cycle counts.  This is made a special case of the more  * general trace functions because it is high use.  Benefits of special casing this * include a buffer of sufficient size to profile the entire kernel is available, and CPI * can be collected along with the profile. */int pmc_profile(struct perfmon_struct *perfdata) {	struct pmc_struct *pdata = &(perfdata->vdata.pmc);	int i;	printk("Perfmon: NIA PMC profile\n");	pmc_timeslice_disable(NULL); // fixme	if(perfmon_base.state == PMC_STATE_INITIAL) {		printk("Perfmon: failed - no buffer was allocated.\n"); 		return -1;	}	/* Stop counters on all processors -- blocking */	pmc_stop(NULL); 	smp_call_function(pmc_stop, (void *)NULL, 0, 1);		for (i=0; i<MAX_PACAS; ++i) {		paca[i].prof_mode = PMC_STATE_PROFILE_KERN;	}	perfmon_base.state = PMC_STATE_PROFILE_KERN; 	if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) {		for(i = 0; i < 8; i++) 			pdata->pmc[i] = 0x0;		pdata->pmc[1] = 0x7f000000;		/* Freeze in problem state, exception enable, freeze on event, */		/*   enable counter negative condition, PMC1, PMC2             */		pdata->pmc[8] = 0x2600cd0e;		pdata->pmc[9] = 0x4a5675ac;		/* Freeze while in wait state */		pdata->pmc[10] = 0x00022002;	} else {		pdata->pmc[0] = 0x7f000000;		for(i = 1; i < 8; i++) 			pdata->pmc[i] = 0x0;		pdata->pmc[8] = 0x26000000 | (0x01 << (31 - 25) | (0x1));		pdata->pmc[9] = (0x3 << (31-4)); /* Instr completed */		/* Freeze while in wait state */		pdata->pmc[10] = 0x00000000 | (0x1 << (31 - 30));	}	pmc_configure_hardware();	mb();	pmc_trace_rec_type(perfdata->header.vdata.type);	pmc_configure((void *)perfdata);	smp_call_function(pmc_configure, (void *)perfdata, 0, 0);	return 0;}int pmc_set_general(struct perfmon_struct *perfdata) {	int i;	printk("Perfmon: PMC sampling - General\n");	if(perfmon_base.state == PMC_STATE_INITIAL) {		printk("Perfmon: failed - no buffer was allocated.\n"); 		return -1;	}	/* Stop counters on all processors -- blocking */	pmc_stop(NULL); 	smp_call_function(pmc_stop, (void *)NULL, 0, 1);		for (i=0; i<MAX_PACAS; ++i) {		paca[i].prof_mode = PMC_STATE_TRACE_KERN;	}	perfmon_base.state = PMC_STATE_TRACE_KERN; 	mb();	pmc_trace_rec_type(perfdata->header.vdata.type);	pmc_configure((void *)perfdata);	smp_call_function(pmc_configure, (void *)perfdata, 0, 0);	return 0;}int pmc_set_user_general(struct perfmon_struct *perfdata) {#if 0	struct pmc_struct *pdata = &(perfdata->vdata.pmc);#endif	int pid = perfdata->header.vdata.pid;	struct task_struct *task;	int i;	printk("Perfmon: PMC sampling - general user\n");	if(perfmon_base.state == PMC_STATE_INITIAL) {		printk("Perfmon: failed - no buffer was allocated.\n"); 		return -1;	}	if(pid) {		printk("Perfmon: pid = 0x%x\n", pid);		read_lock(&tasklist_lock);		task = find_task_by_pid(pid);		if (task) {			printk("Perfmon: task = 0x%lx\n", (u64) task);			task->thread.regs->msr |= 0x4;#if 0			for(i = 0; i < 11; i++)				task->thread.pmc[i] = pdata->pmc[i];#endif		} else {			printk("Perfmon: task not found\n");			read_unlock(&tasklist_lock);			return -1;		}	}	read_unlock(&tasklist_lock);	/* Stop counters on all processors -- blocking */	pmc_stop(NULL); 	smp_call_function(pmc_stop, (void *)NULL, 0, 1);		for (i=0; i<MAX_PACAS; ++i) {		paca[i].prof_mode = PMC_STATE_TRACE_USER;	}	perfmon_base.state = PMC_STATE_TRACE_USER; 	mb();	pmc_trace_rec_type(perfdata->header.vdata.type);	pmc_configure((void *)perfdata);	smp_call_function(pmc_configure, (void *)perfdata, 0, 0);	return 0;}void pmc_trace_rec_type(unsigned long type){	unsigned long cmd_rec;	cmd_rec = 0xFFUL << 56;	cmd_rec |= type;	*((unsigned long *)(perfmon_base.trace_buffer + 			    perfmon_base.trace_end)) = cmd_rec;	perfmon_base.trace_end += 8;	if(perfmon_base.trace_end >= perfmon_base.trace_length)		perfmon_base.trace_end = 0;}void pmc_configure(void *data){	struct paca_struct *lpaca = get_paca();	struct perfmon_struct *perfdata = (struct perfmon_struct *)data;	struct pmc_struct *pdata = &(perfdata->vdata.pmc);	unsigned long i;	/* Indicate to hypervisor that we are using the PMCs */	if(systemcfg->platform == PLATFORM_ISERIES_LPAR)		lpaca->xLpPacaPtr->xPMCRegsInUse = 1;	/* Freeze all counters */	mtspr(MMCR0, 0x80000000); mtspr(MMCR1, 0x00000000);	/* Clear all the PMCs */	mtspr(PMC1, 0); mtspr(PMC2, 0); mtspr(PMC3, 0); mtspr(PMC4, 0); 	mtspr(PMC5, 0); mtspr(PMC6, 0); mtspr(PMC7, 0); mtspr(PMC8, 0);	/* Set the PMCs to the new values */	for(i = 0; i < 11; i++) {		lpaca->pmc[i]  = pdata->pmc[i];		printk("pmc_configure: 0x%lx\n", pdata->pmc[i]);	}	mtspr(PMC1, lpaca->pmc[0]); mtspr(PMC2, lpaca->pmc[1]);	mtspr(PMC3, lpaca->pmc[2]); mtspr(PMC4, lpaca->pmc[3]);	mtspr(PMC5, lpaca->pmc[4]); mtspr(PMC6, lpaca->pmc[5]);	mtspr(PMC7, lpaca->pmc[6]); mtspr(PMC8, lpaca->pmc[7]);	mtspr(MMCR1, lpaca->pmc[9]); mtspr(MMCRA, lpaca->pmc[10]);	mb();		/* Start all counters - MMCR0 contains the PMC enable control bit */	mtspr(MMCR0, lpaca->pmc[8]);}/* Increment the timeslice counters for the current timeslice */ void pmc_timeslice_data_collect(void *data) {	struct paca_struct *lpaca = get_paca();	int i, cpu = smp_processor_id(); 	int slice_rec = cpu*PMC_MAX_COUNTERS*PMC_SLICES_MAX +		        pmc_timeslice[cpu]*PMC_MAX_COUNTERS;	/* First get any cumulative data that may have accrued */	for(i=0; i<8; i++) {		pmc_timeslice_data[slice_rec + i] += lpaca->pmcc[i];		lpaca->pmcc[i] = 0;		lpaca->pmc[i]  = 0;	}	/* Next get current hardware values */	pmc_timeslice_data[slice_rec + 0] += ((u32)mfspr(PMC1));	pmc_timeslice_data[slice_rec + 1] += ((u32)mfspr(PMC2));	pmc_timeslice_data[slice_rec + 2] += ((u32)mfspr(PMC3));	pmc_timeslice_data[slice_rec + 3] += ((u32)mfspr(PMC4));	pmc_timeslice_data[slice_rec + 4] += ((u32)mfspr(PMC5));	pmc_timeslice_data[slice_rec + 5] += ((u32)mfspr(PMC6));	pmc_timeslice_data[slice_rec + 6] += ((u32)mfspr(PMC7));	pmc_timeslice_data[slice_rec + 7] += ((u32)mfspr(PMC8));}/* Handle a timeslice tick.  Each processor executes independantly */int pmc_timeslice_tick() {	int i;	struct perfmon_struct perfdata;	unsigned int cpu = smp_processor_id();	/* Switch timeslice every decrementer, reduced by some factor */	pmc_tick_count[cpu]++;	if(!pmc_timeslice_enabled || pmc_tick_count[cpu] < PMC_TICK_FACTOR) 		return 0;	pmc_tick_count[cpu] = 0;	/* Stop counters and collect current state */	pmc_stop(NULL); 	pmc_timeslice_data_collect(NULL); 	/* Move on to the next timeslice */	pmc_timeslice[cpu]++; 	if(pmc_timeslice[cpu] >= pmc_timeslice_top) pmc_timeslice[cpu] = 0;	/* Set up the counters to reflect the new data to collect */	for(i = 0; i < 8; i++) {		perfdata.vdata.pmc.pmc[i] = 0;	}	for(i = 0; i < 3; i++) {		perfdata.vdata.pmc.pmc[i+8] = 			pmc_timeslice_config[pmc_timeslice[cpu]*5+i];	}	mb();	/* Configure the new counters */	pmc_configure((void *)&perfdata);	return 0;}int pmc_timeslice_set(struct perfmon_struct *perfdata) {	int slice; 	printk("Perfmon: Timeslice set\n");	slice = perfdata->header.vdata.slice;	if(slice >= PMC_SLICES_MAX) {		printk("Perfmon: invalid timeslice specified %d\n", slice);		return(-1); 	}	if(slice > pmc_timeslice_top) pmc_timeslice_top = slice;	pmc_timeslice_config[slice * 5 + 0] = perfdata->vdata.pmc.pmc[0];	pmc_timeslice_config[slice * 5 + 1] = perfdata->vdata.pmc.pmc[1];	pmc_timeslice_config[slice * 5 + 2] = perfdata->vdata.pmc.pmc[2];	pmc_timeslice_config[slice * 5 + 3] = perfdata->vdata.pmc.pmc[3];	pmc_timeslice_config[slice * 5 + 4] = perfdata->vdata.pmc.pmc[4];}int pmc_timeslice_enable(struct perfmon_struct *perfdata) {	int i, j;	printk("Perfmon: Timeslice mode\n");	if(perfmon_base.state == PMC_STATE_INITIAL) {		printk("Perfmon: failed - no buffer was allocated.\n"); 		return -1;	}	pmc_timeslice_disable(NULL); // fixme	mb();	for (i=0; i<MAX_PACAS; ++i) {		paca[i].prof_mode = PMC_STATE_TIMESLICE;	}	perfmon_base.state = PMC_STATE_TIMESLICE; 	pmc_configure_hardware(); 	for(i=0; i<PMC_MAX_CPUS; i++) {		pmc_tick_count[i] = 0;		pmc_timeslice[i]  = 0;	}	/* Stop counters on all processors -- blocking */	pmc_stop(NULL); 	smp_call_function(pmc_stop, (void *)NULL, 0, 1);	/* Clear out the PMC counters, cumulative and current */	for (i=0; i<MAX_PACAS; ++i) {		paca[i].prof_mode = PMC_STATE_TIMESLICE;		for(j=0; j<8; j++) {			paca[i].pmcc[j] = 0;		}		for(j=0; j<11; j++) {			paca[i].pmc[j] = 0;		}	}		memset((char *)perfmon_base.timeslice_buffer, 	       0, perfmon_base.timeslice_length);	pmc_trace_rec_type(PMC_TYPE_TIMESLICE);	/* Clear counters on all processors -- blocking */	pmc_clear(NULL); 	smp_call_function(pmc_clear, (void *)NULL, 0, 1);	mb();	pmc_timeslice_enabled  = 1;	/* 	 * We do not actually setup the PMC hardware here.  That occurs	 * after the first timeslice tick occurs. Close enough.	 */	return 0;}int pmc_timeslice_disable(struct perfmon_struct *perfdata) {	pmc_timeslice_enabled = 0;}void pmc_dump_timeslice(struct perfmon_struct *perfdata) {	unsigned long rec, i, j, idx;	int cpu = smp_processor_id(); 	spin_lock(&pmc_lock);	pmc_trace_rec_type(PMC_TYPE_TIMESLICE_DUMP); /* DRENG put cpu num in */	for(i=0; i<pmc_timeslice_top; i++) {		for(j=0; j<8; j++) {			idx = cpu*PMC_MAX_COUNTERS*PMC_SLICES_MAX +				i*PMC_MAX_COUNTERS + j;			rec = pmc_timeslice_data[idx];			*((unsigned long *)(perfmon_base.trace_buffer + 					    perfmon_base.trace_end)) = rec;			perfmon_base.trace_end += 8;			if(perfmon_base.trace_end >= perfmon_base.trace_length)				perfmon_base.trace_end = 0;		}	}	spin_unlock(&pmc_lock);}

⌨️ 快捷键说明

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