perfctr-2.7.3 for 2.6.7-rc1-mm1, part 1/6: - core driver files and kernel changes drivers/Makefile | 1 drivers/perfctr/version.h | 1 kernel/sched.c | 3 kernel/timer.c | 2 DESC CONFIG_PERFCTR=n build fix EDESC From: Mikael Pettersson CONFIG_PERFCTR=n leads to compile-time warnings from the syscall prototypes in . I'm not sure if providing dummy struct declarations is cleaner than bracketing the offending code inside #ifdef CONFIG_PERFCTR, but this patch should fix the warnings for now. DESC From: Mikael Pettersson Subject: [PATCH][6/6] perfctr-2.7.3 for 2.6.7-rc1-mm1: misc EDESC perfctr-2.7.3 for 2.6.7-rc1-mm1, part 6/6: - remaining small changes Signed-off-by: Andrew Morton --- 25-akpm/CREDITS | 1 25-akpm/MAINTAINERS | 6 + 25-akpm/drivers/Makefile | 1 25-akpm/drivers/perfctr/Kconfig | 45 ++++++++++ 25-akpm/drivers/perfctr/Makefile | 16 +++ 25-akpm/drivers/perfctr/cpumask.h | 24 +++++ 25-akpm/drivers/perfctr/init.c | 97 +++++++++++++++++++++++ 25-akpm/drivers/perfctr/version.h | 1 25-akpm/include/linux/perfctr.h | 158 ++++++++++++++++++++++++++++++++++++++ 25-akpm/kernel/sched.c | 3 25-akpm/kernel/sys.c | 6 + 25-akpm/kernel/timer.c | 2 12 files changed, 360 insertions(+) diff -puN CREDITS~perfctr-core CREDITS --- 25/CREDITS~perfctr-core 2004-10-21 14:54:23.850297696 -0700 +++ 25-akpm/CREDITS 2004-10-21 14:54:23.865295416 -0700 @@ -2586,6 +2586,7 @@ N: Mikael Pettersson E: mikpe@csd.uu.se W: http://www.csd.uu.se/~mikpe/ D: Miscellaneous fixes +D: Performance-monitoring counters driver N: Reed H. Petty E: rhp@draper.net diff -puN drivers/Makefile~perfctr-core drivers/Makefile --- 25/drivers/Makefile~perfctr-core 2004-10-21 14:54:23.852297392 -0700 +++ 25-akpm/drivers/Makefile 2004-10-21 14:54:23.865295416 -0700 @@ -58,4 +58,5 @@ obj-$(CONFIG_MCA) += mca/ obj-$(CONFIG_EISA) += eisa/ obj-$(CONFIG_CPU_FREQ) += cpufreq/ obj-$(CONFIG_MMC) += mmc/ +obj-$(CONFIG_PERFCTR) += perfctr/ obj-y += firmware/ diff -puN /dev/null drivers/perfctr/cpumask.h --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25-akpm/drivers/perfctr/cpumask.h 2004-10-21 14:54:23.866295264 -0700 @@ -0,0 +1,24 @@ +/* $Id: cpumask.h,v 1.7 2004/05/12 19:59:01 mikpe Exp $ + * Performance-monitoring counters driver. + * Partial simulation of cpumask_t on non-cpumask_t kernels. + * Extension to allow inspecting a cpumask_t as array of ulong. + * Appropriate definition of perfctr_cpus_forbidden_mask. + * + * Copyright (C) 2003-2004 Mikael Pettersson + */ + +#ifdef CPU_ARRAY_SIZE +#define PERFCTR_CPUMASK_NRLONGS CPU_ARRAY_SIZE +#else +#define PERFCTR_CPUMASK_NRLONGS 1 +#endif + +/* `perfctr_cpus_forbidden_mask' used to be defined in , + but cpumask_t compatibility issues forced it to be moved here. */ +#if PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED +extern cpumask_t perfctr_cpus_forbidden_mask; +#define perfctr_cpu_is_forbidden(cpu) cpu_isset((cpu), perfctr_cpus_forbidden_mask) +#else +#define perfctr_cpus_forbidden_mask CPU_MASK_NONE +#define perfctr_cpu_is_forbidden(cpu) 0 /* cpu_isset() needs an lvalue :-( */ +#endif diff -puN /dev/null drivers/perfctr/init.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25-akpm/drivers/perfctr/init.c 2004-10-21 14:54:23.866295264 -0700 @@ -0,0 +1,97 @@ +/* $Id: init.c,v 1.76 2004/05/31 18:18:55 mikpe Exp $ + * Performance-monitoring counters driver. + * Top-level initialisation code. + * + * Copyright (C) 1999-2004 Mikael Pettersson + */ +#include +#include +#include +#include +#include + +#include + +#include "cpumask.h" +#include "virtual.h" +#include "version.h" + +struct perfctr_info perfctr_info = { + .abi_version = PERFCTR_ABI_VERSION, + .driver_version = VERSION, +}; + +char *perfctr_cpu_name __initdata; + +static int cpus_copy_to_user(const cpumask_t *cpus, struct perfctr_cpu_mask *argp) +{ + const unsigned int k_nrwords = PERFCTR_CPUMASK_NRLONGS*(sizeof(long)/sizeof(int)); + unsigned int u_nrwords; + unsigned int ui, ki, j; + + if (get_user(u_nrwords, &argp->nrwords)) + return -EFAULT; + if (put_user(k_nrwords, &argp->nrwords)) + return -EFAULT; + if (u_nrwords < k_nrwords) + return -EOVERFLOW; + for(ui = 0, ki = 0; ki < PERFCTR_CPUMASK_NRLONGS; ++ki) { + unsigned long mask = cpus_addr(*cpus)[ki]; + for(j = 0; j < sizeof(long)/sizeof(int); ++j) { + if (put_user((unsigned int)mask, &argp->mask[ui])) + return -EFAULT; + ++ui; + mask = (mask >> (8*sizeof(int)-1)) >> 1; + } + } + return 0; +} + +asmlinkage long sys_perfctr_info(struct perfctr_info *infop, + struct perfctr_cpu_mask *cpusp, + struct perfctr_cpu_mask *forbiddenp) +{ + if (infop && copy_to_user(infop, &perfctr_info, sizeof perfctr_info)) + return -EFAULT; + if (cpusp) { + cpumask_t cpus = cpu_online_map; + int err = cpus_copy_to_user(&cpus, cpusp); + if (err) + return err; + } + if (forbiddenp) { + cpumask_t cpus = perfctr_cpus_forbidden_mask; + int err = cpus_copy_to_user(&cpus, forbiddenp); + if (err) + return err; + } + return 0; +} + +int __init perfctr_init(void) +{ + int err; + + err = perfctr_cpu_init(); + if (err) { + printk(KERN_INFO "perfctr: not supported by this processor\n"); + return err; + } + err = vperfctr_init(); + if (err) + return err; + printk(KERN_INFO "perfctr: driver %s, cpu type %s at %u kHz\n", + perfctr_info.driver_version, + perfctr_cpu_name, + perfctr_info.cpu_khz); + return 0; +} + +void __exit perfctr_exit(void) +{ + vperfctr_exit(); + perfctr_cpu_exit(); +} + +module_init(perfctr_init) +module_exit(perfctr_exit) diff -puN /dev/null drivers/perfctr/Kconfig --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25-akpm/drivers/perfctr/Kconfig 2004-10-21 14:54:23.867295112 -0700 @@ -0,0 +1,45 @@ +# $Id: Kconfig,v 1.10 2004/05/24 11:00:55 mikpe Exp $ +# Performance-monitoring counters driver configuration +# + +menu "Performance-monitoring counters support" + +config PERFCTR + bool "Performance monitoring counters support" + help + This driver provides access to the performance-monitoring counter + registers available in some (but not all) modern processors. + These special-purpose registers can be programmed to count low-level + performance-related events which occur during program execution, + such as cache misses, pipeline stalls, etc. + + You can safely say Y here, even if you intend to run the kernel + on a processor without performance-monitoring counters. + +config PERFCTR_INIT_TESTS + bool "Init-time hardware tests" + depends on PERFCTR + help + This option makes the driver perform additional hardware tests + during initialisation, and log their results in the kernel's + message buffer. For most supported processors, these tests simply + measure the runtime overheads of performance counter operations. + + If you have a less well-known processor (one not listed in the + etc/costs/ directory in the user-space package), you should enable + this option and email the results to the perfctr developers. + + If unsure, say N. + +config PERFCTR_VIRTUAL + bool "Virtual performance counters support" + depends on PERFCTR + help + The processor's performance-monitoring counters are special-purpose + global registers. This option adds support for virtual per-process + performance-monitoring counters which only run when the process + to which they belong is executing. This improves the accuracy of + performance measurements by reducing "noise" from other processes. + + Say Y. +endmenu diff -puN /dev/null drivers/perfctr/Makefile --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25-akpm/drivers/perfctr/Makefile 2004-10-21 14:54:23.867295112 -0700 @@ -0,0 +1,16 @@ +# $Id: Makefile,v 1.26 2004/05/30 23:02:14 mikpe Exp $ +# Makefile for the Performance-monitoring counters driver. + +# This also covers x86_64. +perfctr-objs-$(CONFIG_X86) := x86.o +tests-objs-$(CONFIG_X86) := x86_tests.o + +perfctr-objs-$(CONFIG_PPC32) := ppc.o +tests-objs-$(CONFIG_PPC32) := ppc_tests.o + +perfctr-objs-y += init.o +perfctr-objs-$(CONFIG_PERFCTR_INIT_TESTS) += $(tests-objs-y) +perfctr-objs-$(CONFIG_PERFCTR_VIRTUAL) += virtual.o + +perfctr-objs := $(perfctr-objs-y) +obj-$(CONFIG_PERFCTR) := perfctr.o diff -puN /dev/null drivers/perfctr/version.h --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25-akpm/drivers/perfctr/version.h 2004-10-21 14:54:23.867295112 -0700 @@ -0,0 +1 @@ +#define VERSION "2.7.3" diff -puN /dev/null include/linux/perfctr.h --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25-akpm/include/linux/perfctr.h 2004-10-21 14:54:23.868294960 -0700 @@ -0,0 +1,158 @@ +/* $Id: perfctr.h,v 1.78 2004/05/31 20:45:51 mikpe Exp $ + * Performance-Monitoring Counters driver + * + * Copyright (C) 1999-2004 Mikael Pettersson + */ +#ifndef _LINUX_PERFCTR_H +#define _LINUX_PERFCTR_H + +#ifdef CONFIG_PERFCTR /* don't break archs without */ + +#include + +struct perfctr_info { + unsigned int abi_version; + char driver_version[32]; + unsigned int cpu_type; + unsigned int cpu_features; + unsigned int cpu_khz; + unsigned int tsc_to_cpu_mult; + unsigned int _reserved2; + unsigned int _reserved3; + unsigned int _reserved4; +}; + +struct perfctr_cpu_mask { + unsigned int nrwords; + unsigned int mask[1]; /* actually 'nrwords' */ +}; + +/* abi_version values: Lower 16 bits contain the CPU data version, upper + 16 bits contain the API version. Each half has a major version in its + upper 8 bits, and a minor version in its lower 8 bits. */ +#define PERFCTR_API_VERSION 0x0600 /* 6.0 */ +#define PERFCTR_ABI_VERSION ((PERFCTR_API_VERSION<<16)|PERFCTR_CPU_VERSION) + +/* cpu_features flag bits */ +#define PERFCTR_FEATURE_RDPMC 0x01 +#define PERFCTR_FEATURE_RDTSC 0x02 +#define PERFCTR_FEATURE_PCINT 0x04 + +/* user's view of mmap:ed virtual perfctr */ +struct vperfctr_state { + struct perfctr_cpu_state cpu_state; +}; + +/* virtual perfctr control object */ +struct vperfctr_control { + int si_signo; + struct perfctr_cpu_control cpu_control; + unsigned int preserve; + unsigned int _reserved1; + unsigned int _reserved2; + unsigned int _reserved3; + unsigned int _reserved4; +}; + +#else +struct perfctr_info; +struct perfctr_cpu_mask; +struct perfctr_sum_ctrs; +struct vperfctr_control; +#endif /* CONFIG_PERFCTR */ + +#ifdef __KERNEL__ + +/* + * The perfctr system calls. + */ +asmlinkage long sys_perfctr_info(struct perfctr_info*, struct perfctr_cpu_mask*, struct perfctr_cpu_mask*); +asmlinkage long sys_vperfctr_open(int tid, int creat); +asmlinkage long sys_vperfctr_control(int fd, const struct vperfctr_control*); +asmlinkage long sys_vperfctr_unlink(int fd); +asmlinkage long sys_vperfctr_iresume(int fd); +asmlinkage long sys_vperfctr_read(int fd, + struct perfctr_sum_ctrs*, + struct vperfctr_control*); + +extern struct perfctr_info perfctr_info; + +#ifdef CONFIG_PERFCTR_VIRTUAL + +/* + * Virtual per-process performance-monitoring counters. + */ +struct vperfctr; /* opaque */ + +/* process management operations */ +extern struct vperfctr *__vperfctr_copy(struct vperfctr*); +extern void __vperfctr_exit(struct vperfctr*); +extern void __vperfctr_suspend(struct vperfctr*); +extern void __vperfctr_resume(struct vperfctr*); +extern void __vperfctr_sample(struct vperfctr*); +extern void __vperfctr_set_cpus_allowed(struct task_struct*, struct vperfctr*, cpumask_t); + +static inline void perfctr_copy_thread(struct thread_struct *thread) +{ + thread->perfctr = NULL; +} + +static inline void perfctr_exit_thread(struct thread_struct *thread) +{ + struct vperfctr *perfctr; + perfctr = thread->perfctr; + if (perfctr) + __vperfctr_exit(perfctr); +} + +static inline void perfctr_suspend_thread(struct thread_struct *prev) +{ + struct vperfctr *perfctr; + perfctr = prev->perfctr; + if (perfctr) + __vperfctr_suspend(perfctr); +} + +static inline void perfctr_resume_thread(struct thread_struct *next) +{ + struct vperfctr *perfctr; + perfctr = next->perfctr; + if (perfctr) + __vperfctr_resume(perfctr); +} + +static inline void perfctr_sample_thread(struct thread_struct *thread) +{ + struct vperfctr *perfctr; + perfctr = thread->perfctr; + if (perfctr) + __vperfctr_sample(perfctr); +} + +static inline void perfctr_set_cpus_allowed(struct task_struct *p, cpumask_t new_mask) +{ +#if PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED + struct vperfctr *perfctr; + + task_lock(p); + perfctr = p->thread.perfctr; + if (perfctr) + __vperfctr_set_cpus_allowed(p, perfctr, new_mask); + task_unlock(p); +#endif +} + +#else /* !CONFIG_PERFCTR_VIRTUAL */ + +static inline void perfctr_copy_thread(struct thread_struct *t) { } +static inline void perfctr_exit_thread(struct thread_struct *t) { } +static inline void perfctr_suspend_thread(struct thread_struct *t) { } +static inline void perfctr_resume_thread(struct thread_struct *t) { } +static inline void perfctr_sample_thread(struct thread_struct *t) { } +static inline void perfctr_set_cpus_allowed(struct task_struct *p, cpumask_t m) { } + +#endif /* CONFIG_PERFCTR_VIRTUAL */ + +#endif /* __KERNEL__ */ + +#endif /* _LINUX_PERFCTR_H */ diff -puN kernel/sched.c~perfctr-core kernel/sched.c --- 25/kernel/sched.c~perfctr-core 2004-10-21 14:54:23.855296936 -0700 +++ 25-akpm/kernel/sched.c 2004-10-21 14:54:23.871294504 -0700 @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -3700,6 +3701,8 @@ int set_cpus_allowed(task_t *p, cpumask_ migration_req_t req; runqueue_t *rq; + perfctr_set_cpus_allowed(p, new_mask); + rq = task_rq_lock(p, &flags); if (!cpus_intersects(new_mask, cpu_online_map)) { ret = -EINVAL; diff -puN kernel/sys.c~perfctr-core kernel/sys.c --- 25/kernel/sys.c~perfctr-core 2004-10-21 14:54:23.856296784 -0700 +++ 25-akpm/kernel/sys.c 2004-10-21 14:54:23.873294200 -0700 @@ -292,6 +292,12 @@ cond_syscall(compat_sys_socketcall) cond_syscall(sys_pciconfig_read) cond_syscall(sys_pciconfig_write) cond_syscall(sys_pciconfig_iobase) +cond_syscall(sys_perfctr_info) +cond_syscall(sys_vperfctr_open) +cond_syscall(sys_vperfctr_control) +cond_syscall(sys_vperfctr_unlink) +cond_syscall(sys_vperfctr_iresume) +cond_syscall(sys_vperfctr_read) static int set_one_prio(struct task_struct *p, int niceval, int error) { diff -puN kernel/timer.c~perfctr-core kernel/timer.c --- 25/kernel/timer.c~perfctr-core 2004-10-21 14:54:23.858296480 -0700 +++ 25-akpm/kernel/timer.c 2004-10-21 14:54:23.874294048 -0700 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -849,6 +850,7 @@ static void update_one_process(struct ta do_process_times(p, user, system); do_it_virt(p, user); do_it_prof(p); + perfctr_sample_thread(&p->thread); } /* diff -puN MAINTAINERS~perfctr-core MAINTAINERS --- 25/MAINTAINERS~perfctr-core 2004-10-21 14:54:23.860296176 -0700 +++ 25-akpm/MAINTAINERS 2004-10-21 14:54:23.876293744 -0700 @@ -1737,6 +1737,12 @@ M: george@mvista.com L: linux-net@vger.kernel.org S: Supported +PERFORMANCE-MONITORING COUNTERS DRIVER +P: Mikael Pettersson +M: mikpe@csd.uu.se +W: http://www.csd.uu.se/~mikpe/linux/perfctr/ +S: Maintained + PNP SUPPORT P: Adam Belay M: ambx1@neo.rr.com _