Blame src/perfctr-2.6.x/linux/drivers/perfctr/init.c

Packit 577717
/* $Id: init.c,v 1.68.2.5 2009/01/23 17:21:20 mikpe Exp $
Packit 577717
 * Performance-monitoring counters driver.
Packit 577717
 * Top-level initialisation code.
Packit 577717
 *
Packit 577717
 * Copyright (C) 1999-2007, 2009  Mikael Pettersson
Packit 577717
 */
Packit 577717
#include <linux/version.h>
Packit 577717
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
Packit 577717
#include <linux/config.h>
Packit 577717
#endif
Packit 577717
#include <linux/module.h>
Packit 577717
#include <linux/fs.h>
Packit 577717
#include <linux/init.h>
Packit 577717
#include <linux/miscdevice.h>
Packit 577717
#include <linux/sched.h>
Packit 577717
#include <linux/perfctr.h>
Packit 577717
Packit 577717
#include <asm/uaccess.h>
Packit 577717
Packit 577717
#include "compat.h"
Packit 577717
#include "virtual.h"
Packit 577717
#include "global.h"
Packit 577717
#include "version.h"
Packit 577717
#include "marshal.h"
Packit 577717
Packit 577717
MODULE_AUTHOR("Mikael Pettersson <mikpe@it.uu.se>");
Packit 577717
MODULE_DESCRIPTION("Performance-monitoring counters driver");
Packit 577717
MODULE_LICENSE("GPL");
Packit 577717
MODULE_ALIAS("char-major-10-182");
Packit 577717
Packit 577717
#ifdef CONFIG_PERFCTR_DEBUG
Packit 577717
#define VERSION_DEBUG " DEBUG"
Packit 577717
#else
Packit 577717
#define VERSION_DEBUG
Packit 577717
#endif
Packit 577717
Packit 577717
struct perfctr_info perfctr_info = {
Packit 577717
	.abi_version = PERFCTR_ABI_VERSION,
Packit 577717
	.driver_version = VERSION VERSION_DEBUG,
Packit 577717
};
Packit 577717
Packit 577717
char *perfctr_cpu_name __initdata;
Packit 577717
Packit 577717
int sys_perfctr_abi(unsigned int *argp)
Packit 577717
{
Packit 577717
	if( put_user(PERFCTR_ABI_VERSION, argp) )
Packit 577717
		return -EFAULT;
Packit 577717
	return 0;
Packit 577717
}
Packit 577717
Packit 577717
int sys_perfctr_info(struct perfctr_struct_buf *argp)
Packit 577717
{
Packit 577717
	return perfctr_copy_to_user(argp, &perfctr_info, &perfctr_info_sdesc);
Packit 577717
}
Packit 577717
Packit 577717
static int cpus_copy_to_user(const cpumask_t *cpus, struct perfctr_cpu_mask *argp)
Packit 577717
{
Packit 577717
	const unsigned int k_nrwords = PERFCTR_CPUMASK_NRLONGS*(sizeof(long)/sizeof(int));
Packit 577717
	unsigned int u_nrwords;
Packit 577717
	unsigned int ui, ki, j;
Packit 577717
Packit 577717
	if( get_user(u_nrwords, &argp->nrwords) )
Packit 577717
		return -EFAULT;
Packit 577717
	if( put_user(k_nrwords, &argp->nrwords) )
Packit 577717
		return -EFAULT;
Packit 577717
	if( u_nrwords < k_nrwords )
Packit 577717
		return -EOVERFLOW;
Packit 577717
	for(ui = 0, ki = 0; ki < PERFCTR_CPUMASK_NRLONGS; ++ki) {
Packit 577717
		unsigned long mask = cpus_addr(*cpus)[ki];
Packit 577717
		for(j = 0; j < sizeof(long)/sizeof(int); ++j) {
Packit 577717
			if( put_user((unsigned int)mask, &argp->mask[ui]) )
Packit 577717
				return -EFAULT;
Packit 577717
			++ui;
Packit 577717
			mask = (mask >> (8*sizeof(int)-1)) >> 1;
Packit 577717
		}
Packit 577717
	}
Packit 577717
	return 0;
Packit 577717
}
Packit 577717
Packit 577717
int sys_perfctr_cpus(struct perfctr_cpu_mask *argp)
Packit 577717
{
Packit 577717
	cpumask_t cpus = cpu_online_map;
Packit 577717
	return cpus_copy_to_user(&cpus, argp);
Packit 577717
}
Packit 577717
Packit 577717
int sys_perfctr_cpus_forbidden(struct perfctr_cpu_mask *argp)
Packit 577717
{
Packit 577717
	cpumask_t cpus = perfctr_cpus_forbidden_mask;
Packit 577717
	return cpus_copy_to_user(&cpus, argp);
Packit 577717
}
Packit 577717
Packit 577717
#if defined(CONFIG_IA32_EMULATION) && !HAVE_COMPAT_IOCTL
Packit 577717
#include <asm/ioctl32.h>
Packit 577717
Packit 577717
static void __init perfctr_register_ioctl32_conversions(void)
Packit 577717
{
Packit 577717
	int err;
Packit 577717
Packit 577717
	err  = register_ioctl32_conversion(PERFCTR_ABI, 0);
Packit 577717
	err |= register_ioctl32_conversion(PERFCTR_INFO, 0);
Packit 577717
	err |= register_ioctl32_conversion(PERFCTR_CPUS, 0);
Packit 577717
	err |= register_ioctl32_conversion(PERFCTR_CPUS_FORBIDDEN, 0);
Packit 577717
	err |= register_ioctl32_conversion(VPERFCTR_CREAT, 0);
Packit 577717
	err |= register_ioctl32_conversion(VPERFCTR_OPEN, 0);
Packit 577717
	err |= register_ioctl32_conversion(VPERFCTR_READ_SUM, 0);
Packit 577717
	err |= register_ioctl32_conversion(VPERFCTR_UNLINK, 0);
Packit 577717
	err |= register_ioctl32_conversion(VPERFCTR_CONTROL, 0);
Packit 577717
	err |= register_ioctl32_conversion(VPERFCTR_IRESUME, 0);
Packit 577717
	err |= register_ioctl32_conversion(VPERFCTR_READ_CONTROL, 0);
Packit 577717
	err |= register_ioctl32_conversion(GPERFCTR_CONTROL, 0);
Packit 577717
	err |= register_ioctl32_conversion(GPERFCTR_READ, 0);
Packit 577717
	err |= register_ioctl32_conversion(GPERFCTR_STOP, 0);
Packit 577717
	err |= register_ioctl32_conversion(GPERFCTR_START, 0);
Packit 577717
	if( err )
Packit 577717
		printk(KERN_ERR "perfctr: register_ioctl32_conversion() failed\n");
Packit 577717
}
Packit 577717
Packit 577717
static void __exit perfctr_unregister_ioctl32_conversions(void)
Packit 577717
{
Packit 577717
	unregister_ioctl32_conversion(PERFCTR_ABI);
Packit 577717
	unregister_ioctl32_conversion(PERFCTR_INFO);
Packit 577717
	unregister_ioctl32_conversion(PERFCTR_CPUS);
Packit 577717
	unregister_ioctl32_conversion(PERFCTR_CPUS_FORBIDDEN);
Packit 577717
	unregister_ioctl32_conversion(VPERFCTR_CREAT);
Packit 577717
	unregister_ioctl32_conversion(VPERFCTR_OPEN);
Packit 577717
	unregister_ioctl32_conversion(VPERFCTR_READ_SUM);
Packit 577717
	unregister_ioctl32_conversion(VPERFCTR_UNLINK);
Packit 577717
	unregister_ioctl32_conversion(VPERFCTR_CONTROL);
Packit 577717
	unregister_ioctl32_conversion(VPERFCTR_IRESUME);
Packit 577717
	unregister_ioctl32_conversion(VPERFCTR_READ_CONTROL);
Packit 577717
	unregister_ioctl32_conversion(GPERFCTR_CONTROL);
Packit 577717
	unregister_ioctl32_conversion(GPERFCTR_READ);
Packit 577717
	unregister_ioctl32_conversion(GPERFCTR_STOP);
Packit 577717
	unregister_ioctl32_conversion(GPERFCTR_START);
Packit 577717
}
Packit 577717
Packit 577717
#else
Packit 577717
#define perfctr_register_ioctl32_conversions()		do{}while(0)
Packit 577717
#define perfctr_unregister_ioctl32_conversions()	do{}while(0)
Packit 577717
#endif
Packit 577717
Packit 577717
static long dev_perfctr_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
Packit 577717
{
Packit 577717
	switch( cmd ) {
Packit 577717
	case PERFCTR_ABI:
Packit 577717
		return sys_perfctr_abi((unsigned int*)arg);
Packit 577717
	case PERFCTR_INFO:
Packit 577717
		return sys_perfctr_info((struct perfctr_struct_buf*)arg);
Packit 577717
	case PERFCTR_CPUS:
Packit 577717
		return sys_perfctr_cpus((struct perfctr_cpu_mask*)arg);
Packit 577717
	case PERFCTR_CPUS_FORBIDDEN:
Packit 577717
		return sys_perfctr_cpus_forbidden((struct perfctr_cpu_mask*)arg);
Packit 577717
	case VPERFCTR_CREAT:
Packit 577717
		return vperfctr_attach((int)arg, 1);
Packit 577717
	case VPERFCTR_OPEN:
Packit 577717
		return vperfctr_attach((int)arg, 0);
Packit 577717
	default:
Packit 577717
		return gperfctr_ioctl(filp, cmd, arg);
Packit 577717
	}
Packit 577717
	return -EINVAL;
Packit 577717
}
Packit 577717
Packit 577717
#if !HAVE_UNLOCKED_IOCTL
Packit 577717
static int dev_perfctr_ioctl_oldstyle(struct inode *inode, struct file *filp,
Packit 577717
				      unsigned int cmd, unsigned long arg)
Packit 577717
{
Packit 577717
	return dev_perfctr_ioctl(filp, cmd, arg);
Packit 577717
}
Packit 577717
#endif
Packit 577717
Packit 577717
static struct file_operations dev_perfctr_file_ops = {
Packit 577717
	.owner = THIS_MODULE,
Packit 577717
	/* 2.6.11-rc2 introduced HAVE_UNLOCKED_IOCTL and HAVE_COMPAT_IOCTL */
Packit 577717
#if HAVE_UNLOCKED_IOCTL
Packit 577717
	.unlocked_ioctl = dev_perfctr_ioctl,
Packit 577717
#else
Packit 577717
	.ioctl = dev_perfctr_ioctl_oldstyle,
Packit 577717
#endif
Packit 577717
#if defined(CONFIG_IA32_EMULATION) && HAVE_COMPAT_IOCTL
Packit 577717
	.compat_ioctl = dev_perfctr_ioctl,
Packit 577717
#endif
Packit 577717
};
Packit 577717
Packit 577717
static struct miscdevice dev_perfctr = {
Packit 577717
	.minor = 182,
Packit 577717
	.name = "perfctr",
Packit 577717
	.fops = &dev_perfctr_file_ops,
Packit 577717
};
Packit 577717
Packit 577717
int __init perfctr_init(void)
Packit 577717
{
Packit 577717
	int err;
Packit 577717
	if( (err = perfctr_cpu_init()) != 0 ) {
Packit 577717
		printk(KERN_INFO "perfctr: not supported by this processor\n");
Packit 577717
		return err;
Packit 577717
	}
Packit 577717
	if( (err = vperfctr_init()) != 0 )
Packit 577717
		return err;
Packit 577717
	gperfctr_init();
Packit 577717
	if( (err = misc_register(&dev_perfctr)) != 0 ) {
Packit 577717
		printk(KERN_ERR "/dev/perfctr: failed to register, errno %d\n",
Packit 577717
		       -err);
Packit 577717
		return err;
Packit 577717
	}
Packit 577717
	perfctr_register_ioctl32_conversions();
Packit 577717
	printk(KERN_INFO "perfctr: driver %s, cpu type %s at %u kHz\n",
Packit 577717
	       perfctr_info.driver_version,
Packit 577717
	       perfctr_cpu_name,
Packit 577717
	       perfctr_info.cpu_khz);
Packit 577717
	return 0;
Packit 577717
}
Packit 577717
Packit 577717
void __exit perfctr_exit(void)
Packit 577717
{
Packit 577717
	perfctr_unregister_ioctl32_conversions();
Packit 577717
	misc_deregister(&dev_perfctr);
Packit 577717
	vperfctr_exit();
Packit 577717
	perfctr_cpu_exit();
Packit 577717
}
Packit 577717
Packit 577717
module_init(perfctr_init)
Packit 577717
module_exit(perfctr_exit)