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

📄 proc_pmc.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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. * 2001/08/03 : trautman : Added PCI Flight Recorder * 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/config.h>#include <linux/proc_fs.h>#include <linux/spinlock.h>#include <asm/pmc.h>#include <asm/uaccess.h>#include <asm/naca.h>#include <asm/rtas.h>#include <asm/perfmon.h>/* pci Flight Recorder AHT */extern void proc_pciFr_init(struct proc_dir_entry *proc_ppc64_root);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;static int proc_ppc64_page_read(char *page, char **start, off_t off,				int count, int *eof, void *data);static void proc_ppc64_create_paca(int num, struct proc_dir_entry *paca_dir);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_profile_read(char *page, char **start, off_t off,				int count, int *eof, void *data);int proc_ppc64_pmc_profile_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);static loff_t  nacamap_seek( struct file *file, loff_t off, int whence);static ssize_t nacamap_read( struct file *file, char *buf, size_t nbytes, loff_t *ppos);static int     nacamap_mmap( struct file *file, struct vm_area_struct *vma );static struct file_operations nacamap_fops = {	llseek:	nacamap_seek,	read:	nacamap_read,	mmap:	nacamap_mmap};static ssize_t read_profile(struct file *file, char *buf, size_t count, loff_t *ppos);static ssize_t write_profile(struct file * file, const char * buf,			     size_t count, loff_t *ppos);static ssize_t read_trace(struct file *file, char *buf, size_t count, loff_t *ppos);static ssize_t write_trace(struct file * file, const char * buf,			     size_t count, loff_t *ppos);static ssize_t read_timeslice(struct file *file, char *buf, size_t count, loff_t *ppos);static ssize_t write_timeslice(struct file * file, const char * buf,			     size_t count, loff_t *ppos);static struct file_operations proc_profile_operations = {	read:		read_profile,	write:		write_profile,};static struct file_operations proc_trace_operations = {	read:		read_trace,	write:		write_trace,};static struct file_operations proc_timeslice_operations = {	read:		read_timeslice,	write:		write_timeslice,};extern struct perfmon_base_struct perfmon_base;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);	ent = create_proc_entry("naca", S_IFREG|S_IRUGO, proc_ppc64_root);	if ( ent ) {		ent->nlink = 1;		ent->data = naca;		ent->size = 4096;		ent->proc_fops = &nacamap_fops;	}		ent = create_proc_entry("systemcfg", S_IFREG|S_IRUGO, proc_ppc64_root);	if ( ent ) {		ent->nlink = 1;		ent->data = systemcfg;		ent->size = 4096;		ent->proc_fops = &nacamap_fops;	}	/* /proc/ppc64/paca/XX -- raw paca contents.  Only readable to root */	ent = proc_mkdir("paca", proc_ppc64_root);	if (ent) {		for (i = 0; i < systemcfg->processorCount; i++)			proc_ppc64_create_paca(i, ent);	}	/* Placeholder for rtas interfaces. */	rtas_proc_dir = proc_mkdir("rtas", proc_ppc64_root);	/* Create the /proc/ppc64/pcifr for the Pci Flight Recorder.	 */	proc_pciFr_init(proc_ppc64_root);	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 < systemcfg->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 < systemcfg->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;	}	ent = create_proc_entry("profile", S_IWUSR | S_IRUGO, proc_ppc64_pmc_system_root);	if (ent) {		ent->nlink = 1;		ent->proc_fops = &proc_profile_operations;		/* ent->size = (1+prof_len) * sizeof(unsigned int); */	}	ent = create_proc_entry("trace", S_IWUSR | S_IRUGO, proc_ppc64_pmc_system_root);	if (ent) {		ent->nlink = 1;		ent->proc_fops = &proc_trace_operations;		/* ent->size = (1+prof_len) * sizeof(unsigned int); */	}	ent = create_proc_entry("timeslice", S_IWUSR | S_IRUGO, proc_ppc64_pmc_system_root);	if (ent) {		ent->nlink = 1;		ent->proc_fops = &proc_timeslice_operations;	}	/* Create directories for the hardware counters. */	for (i = 0; i < systemcfg->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;	}}/* Read a page of raw data.  "data" points to the start addr. * Intended as a proc read function. */static int proc_ppc64_page_read(char *page, char **start, off_t off,				int count, int *eof, void *data){	int len = PAGE_SIZE - off;	char *p = (char *)data;	if (len > count)		len = count;	if (len <= 0)		return 0;	/* Rely on a "hack" in fs/proc/generic.c.	 * If we could return a ptr to our own data this would be	 * trivial (currently *start must be either an offset, or	 * point into the given page).	 */	memcpy(page, p+off, len);	*start = (char *)len;	return len;}/* NOTE: since paca data is always in flux the values will never be a consistant set. * In theory it could be made consistent if we made the corresponding cpu * copy the page for us (via an IPI).  Probably not worth it. * */static void proc_ppc64_create_paca(int num, struct proc_dir_entry *paca_dir){	struct proc_dir_entry *ent;	struct paca_struct *lpaca = paca + num;	char buf[16];	sprintf(buf, "%02x", num);	ent = create_proc_read_entry(buf, S_IRUSR, paca_dir, proc_ppc64_page_read, lpaca);}/* * 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 < systemcfg->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;}static ssize_t read_profile(struct file *file, char *buf,			    size_t count, loff_t *ppos){	unsigned long p = *ppos;	ssize_t read;	char * pnt;	unsigned int sample_step = 4;	if (p >= (perfmon_base.profile_length+1)) return 0;	if (count > (perfmon_base.profile_length+1) - p)		count = (perfmon_base.profile_length+1) - p;	read = 0;	while (p < sizeof(unsigned int) && count > 0) {		put_user(*((char *)(&sample_step)+p),buf);		buf++; p++; count--; read++;	}	pnt = (char *)(perfmon_base.profile_buffer) + p - sizeof(unsigned int);	copy_to_user(buf,(void *)pnt,count);	read += count;	*ppos += read;	return read;}static ssize_t write_profile(struct file * file, const char * buf,			     size_t count, loff_t *ppos){}static ssize_t read_trace(struct file *file, char *buf,			    size_t count, loff_t *ppos){	unsigned long p = *ppos;	ssize_t read;	char * pnt;	if (p >= (perfmon_base.trace_length)) return 0;	if (count > (perfmon_base.trace_length) - p)		count = (perfmon_base.trace_length) - p;	read = 0;	pnt = (char *)(perfmon_base.trace_buffer) + p;	copy_to_user(buf,(void *)pnt,count);	read += count;	*ppos += read;	return read;}static ssize_t write_trace(struct file * file, const char * buf,			     size_t count, loff_t *ppos){}static ssize_t read_timeslice(struct file *file, char *buf,			      size_t count, loff_t *ppos){	unsigned long p = *ppos;	ssize_t read;	char * pnt;	unsigned int sample_step = 4;	if (p >= (perfmon_base.timeslice_length)) return 0;	if (count > (perfmon_base.timeslice_length) - p)		count = (perfmon_base.timeslice_length) - p;	read = 0;	pnt = (char *)(perfmon_base.timeslice_buffer) + p;	copy_to_user(buf,(void *)pnt,count);	read += count;	*ppos += read;	return read;}static ssize_t write_timeslice(struct file * file, const char * buf,			       size_t count, loff_t *ppos){}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;

⌨️ 快捷键说明

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