proc_pmc.c

来自「是关于linux2.5.1的完全源码」· C语言 代码 · 共 791 行 · 第 1/2 页

C
791
字号
/* * proc_pmc.c * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen IBM Corporation *  * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *  * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. *  * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA *//* Change Activity: * 2001       : mikec    : Created * 2001/06/05 : engebret : Software event count support. * End Change Activity  */#include <asm/proc_fs.h>#include <asm/Paca.h>#include <asm/iSeries/ItLpPaca.h>#include <asm/iSeries/ItLpQueue.h>#include <asm/iSeries/HvCallXm.h>#include <asm/iSeries/IoHriMainStore.h>#include <asm/processor.h>#include <asm/time.h>#include <asm/iSeries/LparData.h>#include <linux/proc_fs.h>#include <linux/spinlock.h>#include <asm/pmc.h>#include <asm/uaccess.h>#include <asm/Naca.h>static int proc_pmc_control_mode = 0;static struct proc_dir_entry *proc_ppc64_root = NULL;static struct proc_dir_entry *proc_ppc64_pmc_root = NULL;static struct proc_dir_entry *proc_ppc64_pmc_system_root = NULL;static struct proc_dir_entry *proc_ppc64_pmc_cpu_root[NR_CPUS] = {NULL, };static spinlock_t proc_ppc64_lock;extern struct Naca *naca;int proc_ppc64_pmc_find_file(void *data);int proc_ppc64_pmc_read(char *page, char **start, off_t off,			int count, int *eof, char *buffer);int proc_ppc64_pmc_stab_read(char *page, char **start, off_t off,			     int count, int *eof, void *data);int proc_ppc64_pmc_htab_read(char *page, char **start, off_t off,			     int count, int *eof, void *data);int proc_ppc64_pmc_hw_read(char *page, char **start, off_t off, 			   int count, int *eof, void *data);static struct proc_dir_entry *pmc_proc_root = NULL;int proc_get_lpevents( char *page, char **start, off_t off, int count, int *eof, void *data);int proc_reset_lpevents( struct file *file, const char *buffer, unsigned long count, void *data);int proc_get_titanTod( char *page, char **start, off_t off, int count, int *eof, void *data);int proc_pmc_get_control( char *page, char **start, off_t off, int count, int *eof, void *data);int proc_pmc_set_control( struct file *file, const char *buffer, unsigned long count, void *data);int proc_pmc_set_mmcr0( struct file *file, const char *buffer, unsigned long count, void *data);int proc_pmc_set_mmcr1( struct file *file, const char *buffer, unsigned long count, void *data);int proc_pmc_set_mmcra( struct file *file, const char *buffer, unsigned long count, void *data);int proc_pmc_set_pmc1(  struct file *file, const char *buffer, unsigned long count, void *data);int proc_pmc_set_pmc2(  struct file *file, const char *buffer, unsigned long count, void *data);int proc_pmc_set_pmc3(  struct file *file, const char *buffer, unsigned long count, void *data);int proc_pmc_set_pmc4(  struct file *file, const char *buffer, unsigned long count, void *data);int proc_pmc_set_pmc5(  struct file *file, const char *buffer, unsigned long count, void *data);int proc_pmc_set_pmc6(  struct file *file, const char *buffer, unsigned long count, void *data);int proc_pmc_set_pmc7(  struct file *file, const char *buffer, unsigned long count, void *data);int proc_pmc_set_pmc8(  struct file *file, const char *buffer, unsigned long count, void *data);void proc_ppc64_init(void){	unsigned long i;	struct proc_dir_entry *ent = NULL;	char buf[256];	printk("proc_ppc64: Creating /proc/ppc64/pmc\n");	/*	 * Create the root, system, and cpu directories as follows:	 *   /proc/ppc64/pmc/system 	 *   /proc/ppc64/pmc/cpu0 	 */	spin_lock(&proc_ppc64_lock);	proc_ppc64_root = proc_mkdir("ppc64", 0);	if (!proc_ppc64_root) return;	spin_unlock(&proc_ppc64_lock);#ifdef CONFIG_PPC_EEH	eeh_init_proc(proc_ppc64_root);#endif	proc_ppc64_pmc_root = proc_mkdir("pmc", proc_ppc64_root);	proc_ppc64_pmc_system_root = proc_mkdir("system", proc_ppc64_pmc_root);	for (i = 0; i < naca->processorCount; i++) {		sprintf(buf, "cpu%ld", i); 		proc_ppc64_pmc_cpu_root[i] = proc_mkdir(buf, proc_ppc64_pmc_root);	}	/* Create directories for the software counters. */	for (i = 0; i < naca->processorCount; i++) {		ent = create_proc_entry("stab", S_IRUGO | S_IWUSR, 					proc_ppc64_pmc_cpu_root[i]);		if (ent) {			ent->nlink = 1;			ent->data = (void *)proc_ppc64_pmc_cpu_root[i];			ent->read_proc = (void *)proc_ppc64_pmc_stab_read;			ent->write_proc = (void *)proc_ppc64_pmc_stab_read;		}		ent = create_proc_entry("htab", S_IRUGO | S_IWUSR, 					proc_ppc64_pmc_cpu_root[i]);		if (ent) {			ent->nlink = 1;			ent->data = (void *)proc_ppc64_pmc_cpu_root[i];			ent->read_proc = (void *)proc_ppc64_pmc_htab_read;			ent->write_proc = (void *)proc_ppc64_pmc_htab_read;		}	}	ent = create_proc_entry("stab", S_IRUGO | S_IWUSR, 				proc_ppc64_pmc_system_root);	if (ent) {		ent->nlink = 1;		ent->data = (void *)proc_ppc64_pmc_system_root;		ent->read_proc = (void *)proc_ppc64_pmc_stab_read;		ent->write_proc = (void *)proc_ppc64_pmc_stab_read;	}	ent = create_proc_entry("htab", S_IRUGO | S_IWUSR, 				proc_ppc64_pmc_system_root);	if (ent) {		ent->nlink = 1;		ent->data = (void *)proc_ppc64_pmc_system_root;		ent->read_proc = (void *)proc_ppc64_pmc_htab_read;		ent->write_proc = (void *)proc_ppc64_pmc_htab_read;	}	/* Create directories for the hardware counters. */	for (i = 0; i < naca->processorCount; i++) {		ent = create_proc_entry("hardware", S_IRUGO | S_IWUSR, 					proc_ppc64_pmc_cpu_root[i]);		if (ent) {			ent->nlink = 1;			ent->data = (void *)proc_ppc64_pmc_cpu_root[i];			ent->read_proc = (void *)proc_ppc64_pmc_hw_read;			ent->write_proc = (void *)proc_ppc64_pmc_hw_read;		}	}	ent = create_proc_entry("hardware", S_IRUGO | S_IWUSR, 				proc_ppc64_pmc_system_root);	if (ent) {		ent->nlink = 1;		ent->data = (void *)proc_ppc64_pmc_system_root;		ent->read_proc = (void *)proc_ppc64_pmc_hw_read;		ent->write_proc = (void *)proc_ppc64_pmc_hw_read;	}}/* * Find the requested 'file' given a proc token. * * Inputs: void * data: proc token * Output: int        : (0, ..., +N) = CPU number. *                      -1           = System. */int proc_ppc64_pmc_find_file(void *data){	int i;	if ((unsigned long)data == 	   (unsigned long) proc_ppc64_pmc_system_root) {		return(-1); 	} else {		for (i = 0; i < naca->processorCount; i++) {			if ((unsigned long)data ==			   (unsigned long)proc_ppc64_pmc_cpu_root[i]) {				return(i); 			}		}	}	/* On error, just default to a type of system. */	printk("proc_ppc64_pmc_find_file: failed to find file token.\n"); 	return(-1); }int proc_ppc64_pmc_read(char *page, char **start, off_t off, 		    int count, int *eof, char *buffer){	int buffer_size, n;	if (count < 0) return 0;	if (buffer == NULL) {		*eof = 1;		return 0;	}	/* Check for read beyond EOF */	buffer_size = n = strlen(buffer);	if (off >= buffer_size) {		*eof = 1;		return 0;	}	if (n > (buffer_size - off)) n = buffer_size - off;	/* Never return more than was requested */	if (n > count) {		n = count;	} else {		*eof = 1;	}	memcpy(page, buffer + off, n);	*start = page;	return n;}int proc_ppc64_pmc_stab_read(char *page, char **start, off_t off, 			 int count, int *eof, void *data){	int n, file;	char *buffer = NULL;	if (count < 0) return 0;	spin_lock(&proc_ppc64_lock);	/* Figure out which file is being request. */	file = proc_ppc64_pmc_find_file(data);	/* Update the counters and the text buffer representation. */	buffer = ppc64_pmc_stab(file);	/* Put the data into the requestor's buffer. */	n = proc_ppc64_pmc_read(page, start, off, count, eof, buffer); 	spin_unlock(&proc_ppc64_lock);	return n;}int proc_ppc64_pmc_htab_read(char *page, char **start, off_t off, 			 int count, int *eof, void *data){	int n, file;	char *buffer = NULL;	if (count < 0) return 0;	spin_lock(&proc_ppc64_lock);	/* Figure out which file is being request. */	file = proc_ppc64_pmc_find_file(data);	/* Update the counters and the text buffer representation. */	buffer = ppc64_pmc_htab(file);	/* Put the data into the requestor's buffer. */	n = proc_ppc64_pmc_read(page, start, off, count, eof, buffer);	spin_unlock(&proc_ppc64_lock);	return n;}int proc_ppc64_pmc_hw_read(char *page, char **start, off_t off, 			     int count, int *eof, void *data){	int n, file;	char *buffer = NULL;	if (count < 0) return 0;	spin_lock(&proc_ppc64_lock);	/* Figure out which file is being request. */	file = proc_ppc64_pmc_find_file(data);	/* Update the counters and the text buffer representation. */	buffer = ppc64_pmc_hw(file);	/* Put the data into the requestor's buffer. */	n = proc_ppc64_pmc_read(page, start, off, count, eof, buffer);	spin_unlock(&proc_ppc64_lock);	return n;}/*  * DRENG the remainder of these functions still need work ... */void pmc_proc_init(struct proc_dir_entry *iSeries_proc){    struct proc_dir_entry *ent = NULL;    ent = create_proc_entry("lpevents", S_IFREG|S_IRUGO, iSeries_proc);    if (!ent) return;    ent->nlink = 1;    ent->data = (void *)0;    ent->read_proc = proc_get_lpevents;    ent->write_proc = proc_reset_lpevents;    ent = create_proc_entry("titanTod", S_IFREG|S_IRUGO, iSeries_proc);    if (!ent) return;    ent->nlink = 1;    ent->data = (void *)0;    ent->read_proc = proc_get_titanTod;    ent->write_proc = NULL;    pmc_proc_root = proc_mkdir("pmc", iSeries_proc);    if (!pmc_proc_root) return;    ent = create_proc_entry("control", S_IFREG|S_IRUSR|S_IWUSR, pmc_proc_root);    if (!ent) return;    ent->nlink = 1;    ent->data = (void *)0;    ent->read_proc = proc_pmc_get_control;    ent->write_proc = proc_pmc_set_control;}static int pmc_calc_metrics( char *page, char **start, off_t off, int count, int *eof, int len){	if ( len <= off+count)		*eof = 1;	*start = page+off;	len -= off;	if ( len > count )		len = count;	if ( len < 0 )		len = 0;	return len;}static char * lpEventTypes[9] = {	"Hypervisor\t\t",	"Machine Facilities\t",	"Session Manager\t",	"SPD I/O\t\t",	"Virtual Bus\t\t",	"PCI I/O\t\t",	"RIO I/O\t\t",	"Virtual Lan\t\t",	"Virtual I/O\t\t"	};	int proc_get_lpevents(char *page, char **start, off_t off, int count, int *eof, void *data){	unsigned i;	int len = 0;	len += sprintf( page+len, "LpEventQueue 0\n" );	len += sprintf( page+len, "  events processed:\t%lu\n",			(unsigned long)xItLpQueue.xLpIntCount );	for (i=0; i<9; ++i) {		len += sprintf( page+len, "    %s %10lu\n",			lpEventTypes[i],			(unsigned long)xItLpQueue.xLpIntCountByType[i] );	}	len += sprintf( page+len, "\n  events processed by processor:\n" );	for (i=0; i<naca->processorCount; ++i) {		len += sprintf( page+len, "    CPU%02d  %10u\n",			i, xPaca[i].lpEvent_count );	}	return pmc_calc_metrics( page, start, off, count, eof, len );}int proc_reset_lpevents( struct file *file, const char *buffer, unsigned long count, void *data ){

⌨️ 快捷键说明

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