1 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/CREDITS
2 ===================================================================
3 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/CREDITS 2004-11-11 10:28:48.000000000 -0500
4 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/CREDITS 2004-11-18 20:59:11.000000000 -0500
7 W: http://www.csd.uu.se/~mikpe/
9 +D: Performance-monitoring counters driver
13 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/Documentation/ioctl-number.txt
14 ===================================================================
15 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/Documentation/ioctl-number.txt 2004-04-03 22:38:18.000000000 -0500
16 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/Documentation/ioctl-number.txt 2004-11-18 20:59:11.000000000 -0500
18 0xB1 00-1F PPPoX <mailto:mostrows@styx.uwaterloo.ca>
19 0xCB 00-1F CBM serial IEC bus in development:
20 <mailto:michael.klein@puffin.lb.shuttle.de>
21 +0xD0 all performance counters see drivers/perfctr/
22 + <mailto:mikpe@csd.uu.se>
23 0xDD 00-3F ZFCP device driver see drivers/s390/scsi/
24 <mailto:aherrman@de.ibm.com>
25 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/MAINTAINERS
26 ===================================================================
27 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/MAINTAINERS 2004-11-11 10:28:39.000000000 -0500
28 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/MAINTAINERS 2004-11-18 20:59:11.000000000 -0500
29 @@ -1608,6 +1608,12 @@
30 L: linux-net@vger.kernel.org
33 +PERFORMANCE-MONITORING COUNTERS DRIVER
36 +W: http://www.csd.uu.se/~mikpe/linux/perfctr/
42 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/i386/Kconfig
43 ===================================================================
44 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/arch/i386/Kconfig 2004-11-11 10:28:16.000000000 -0500
45 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/i386/Kconfig 2004-11-18 20:59:11.000000000 -0500
47 generate incorrect output with certain kernel constructs when
50 +source "drivers/perfctr/Kconfig"
54 menu "Special options"
55 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/i386/kernel/entry.S
56 ===================================================================
57 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/arch/i386/kernel/entry.S 2004-11-11 10:28:47.000000000 -0500
58 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/i386/kernel/entry.S 2004-11-18 20:59:11.000000000 -0500
60 /* The include is where all of the SMP etc. interrupts come from */
61 #include "entry_arch.h"
63 +#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_KPERFCTR)
64 +ENTRY(perfctr_interrupt)
65 + pushl $LOCAL_PERFCTR_VECTOR-256
68 + call smp_perfctr_interrupt
74 pushl $0 # no error code
75 pushl $do_divide_error
76 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/i386/kernel/i8259.c
77 ===================================================================
78 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/arch/i386/kernel/i8259.c 2004-11-11 10:27:12.000000000 -0500
79 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/i386/kernel/i8259.c 2004-11-18 20:59:11.000000000 -0500
82 #include <asm/arch_hooks.h>
83 #include <asm/i8259.h>
84 +#include <asm/perfctr.h>
86 #include <linux/irq.h>
92 + perfctr_vector_init();
95 * Set the clock to HZ Hz, we already have a valid
97 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/i386/kernel/process.c
98 ===================================================================
99 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/arch/i386/kernel/process.c 2004-11-11 10:28:16.000000000 -0500
100 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/i386/kernel/process.c 2004-11-18 20:59:11.000000000 -0500
102 #include <linux/delay.h>
103 #include <linux/reboot.h>
104 #include <linux/init.h>
105 +#include <linux/perfctr.h>
106 #include <linux/mc146818rtc.h>
107 #include <linux/module.h>
108 #include <linux/kallsyms.h>
110 tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
113 + perfctr_exit_thread(&tsk->thread);
114 if (tsk->thread.debugreg[7])
115 dr_dec_use_count(tsk->thread.debugreg[7]);
118 savesegment(fs,p->thread.fs);
119 savesegment(gs,p->thread.gs);
121 + perfctr_copy_thread(&p->thread);
124 if (unlikely(NULL != tsk->thread.io_bitmap_ptr)) {
125 p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
128 /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
130 + perfctr_suspend_thread(prev);
132 __unlazy_fpu(prev_p);
137 tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
140 + perfctr_resume_thread(next);
145 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/ppc/Kconfig
146 ===================================================================
147 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/arch/ppc/Kconfig 2004-11-11 10:28:15.000000000 -0500
148 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/ppc/Kconfig 2004-11-18 20:59:11.000000000 -0500
150 depends on 4xx || 8xx
153 +source "drivers/perfctr/Kconfig"
157 menu "Platform options"
158 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/ppc/kernel/process.c
159 ===================================================================
160 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/arch/ppc/kernel/process.c 2004-11-11 10:28:48.000000000 -0500
161 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/ppc/kernel/process.c 2004-11-18 20:59:11.000000000 -0500
163 #include <linux/module.h>
164 #include <linux/kallsyms.h>
165 #include <linux/mqueue.h>
166 +#include <linux/perfctr.h>
168 #include <asm/pgtable.h>
169 #include <asm/uaccess.h>
171 new->thread.regs->msr |= MSR_VEC;
172 new_thread = &new->thread;
173 old_thread = ¤t->thread;
174 + perfctr_suspend_thread(&prev->thread);
175 last = _switch(old_thread, new_thread);
176 + perfctr_resume_thread(¤t->thread);
177 local_irq_restore(s);
181 last_task_used_math = NULL;
182 if (last_task_used_altivec == current)
183 last_task_used_altivec = NULL;
184 + perfctr_exit_thread(¤t->thread);
187 void flush_thread(void)
190 p->thread.last_syscall = -1;
192 + perfctr_copy_thread(&p->thread);
197 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/x86_64/Kconfig
198 ===================================================================
199 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/arch/x86_64/Kconfig 2004-11-11 10:28:39.000000000 -0500
200 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/x86_64/Kconfig 2004-11-18 20:59:11.000000000 -0500
205 +source "drivers/perfctr/Kconfig"
210 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/x86_64/kernel/entry.S
211 ===================================================================
212 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/arch/x86_64/kernel/entry.S 2004-04-03 22:36:56.000000000 -0500
213 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/x86_64/kernel/entry.S 2004-11-18 20:59:11.000000000 -0500
215 apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt
218 +#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_KPERFCTR)
219 +ENTRY(perfctr_interrupt)
220 + apicinterrupt LOCAL_PERFCTR_VECTOR,smp_perfctr_interrupt
224 * Exception entry points.
226 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/x86_64/kernel/i8259.c
227 ===================================================================
228 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/arch/x86_64/kernel/i8259.c 2004-04-03 22:36:25.000000000 -0500
229 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/x86_64/kernel/i8259.c 2004-11-18 20:59:11.000000000 -0500
231 #include <asm/delay.h>
232 #include <asm/desc.h>
233 #include <asm/apic.h>
234 +#include <asm/perfctr.h>
236 #include <linux/irq.h>
239 set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
242 + perfctr_vector_init();
245 * Set the clock to HZ Hz, we already have a valid
247 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/x86_64/kernel/process.c
248 ===================================================================
249 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/arch/x86_64/kernel/process.c 2004-11-11 10:27:51.000000000 -0500
250 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/arch/x86_64/kernel/process.c 2004-11-18 20:59:11.000000000 -0500
252 #include <linux/delay.h>
253 #include <linux/irq.h>
254 #include <linux/ptrace.h>
255 +#include <linux/perfctr.h>
256 #include <linux/version.h>
258 #include <asm/uaccess.h>
260 (init_tss + smp_processor_id())->io_bitmap_base =
261 INVALID_IO_BITMAP_OFFSET;
263 + perfctr_exit_thread(&me->thread);
266 void flush_thread(void)
268 asm("movl %%es,%0" : "=m" (p->thread.es));
269 asm("movl %%ds,%0" : "=m" (p->thread.ds));
271 + perfctr_copy_thread(&p->thread);
273 if (unlikely(me->thread.io_bitmap_ptr != NULL)) {
274 p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
275 if (!p->thread.io_bitmap_ptr)
277 int cpu = smp_processor_id();
278 struct tss_struct *tss = init_tss + cpu;
280 + perfctr_suspend_thread(prev);
289 + perfctr_resume_thread(next);
294 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/Makefile
295 ===================================================================
296 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/Makefile 2004-11-18 20:59:08.000000000 -0500
297 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/Makefile 2004-11-18 20:59:11.000000000 -0500
299 obj-$(CONFIG_MCA) += mca/
300 obj-$(CONFIG_EISA) += eisa/
301 obj-$(CONFIG_CPU_FREQ) += cpufreq/
302 +obj-$(CONFIG_KPERFCTR) += perfctr/
303 obj-$(CONFIG_INFINIBAND) += infiniband/
305 obj-$(CONFIG_CRASH_DUMP) += dump/
306 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_64_compat.h
307 ===================================================================
308 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/x86_64_compat.h 1969-12-31 19:00:00.000000000 -0500
309 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_64_compat.h 2004-11-18 20:59:11.000000000 -0500
311 +/* $Id: x86_64_compat.h,v 1.1 2003/05/14 21:51:57 mikpe Exp $
312 + * Performance-monitoring counters driver.
313 + * x86_64-specific compatibility definitions for 2.4/2.5 kernels.
315 + * Copyright (C) 2003 Mikael Pettersson
317 +#include <linux/config.h>
318 +#include <linux/version.h>
320 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
322 +/* irq_enter() and irq_exit() take two parameters in 2.4. However,
323 + we only use them to disable preemption in the interrupt handler,
324 + which isn't needed in non-preemptive 2.4 kernels. */
325 +#ifdef CONFIG_PREEMPT
326 +#error "not yet ported to 2.4+PREEMPT"
330 +#define irq_enter() do{}while(0)
331 +#define irq_exit() do{}while(0)
335 +extern unsigned int perfctr_cpu_khz(void);
336 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/Makefile
337 ===================================================================
338 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/Makefile 1969-12-31 19:00:00.000000000 -0500
339 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/Makefile 2004-11-18 20:59:11.000000000 -0500
341 +# $Id: Makefile,v 1.20.2.2 2004/08/02 22:24:58 mikpe Exp $
342 +# Makefile for the Performance-monitoring counters driver.
344 +ifeq ($(VERSION)$(PATCHLEVEL),24)
348 +# We need -fno-unit-at-a-time with gcc-3.4 on x86 to avoid stack overflow.
349 +# Kernels >= 2.6.6 do that automatically but older ones do not, so we
350 +# unconditionally add that option here just in case.
351 +my_check_gcc = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
352 +EXTRA_CFLAGS_$(CONFIG_X86) := $(call my_check_gcc,-fno-unit-at-a-time,)
353 +EXTRA_CFLAGS_$(CONFIG_X86_64) :=
354 +EXTRA_CFLAGS_$(CONFIG_PPC32) :=
355 +EXTRA_CFLAGS := $(EXTRA_CFLAGS_y)
357 +# construct various object file lists:
358 +# kernel-objs-y kernel objects
359 +# m-objs-m perfctr.o if driver is module, empty otherwise
360 +# driver-objs-y objects for perfctr.o module, or empty
362 +# This also covers x86_64.
363 +driver-objs-$(CONFIG_X86) := x86.o
364 +tests-objs-$(CONFIG_X86) := x86_tests.o
365 +kernel-objs-$(CONFIG_X86) := x86_setup.o
367 +driver-objs-$(CONFIG_PPC32) := ppc.o
368 +tests-objs-$(CONFIG_PPC32) := ppc_tests.o
369 +kernel-objs-$(CONFIG_PPC32) := ppc_setup.o
371 +driver-objs-y += init.o marshal.o
372 +driver-objs-$(CONFIG_PERFCTR_INIT_TESTS) += $(tests-objs-y)
373 +driver-objs-$(CONFIG_PERFCTR_VIRTUAL) += virtual.o
374 +stub-objs-$(CONFIG_PERFCTR)-$(CONFIG_PERFCTR_VIRTUAL) := virtual_stub.o
375 +driver-objs-$(CONFIG_PERFCTR_GLOBAL) += global.o
376 +m-objs-$(CONFIG_PERFCTR) := perfctr.o
377 +kernel-objs-$(CONFIG_PERFCTR) += $(driver-objs-y)
378 +kernel-objs-y += $(stub-objs-m-y)
380 +perfctr-objs := $(driver-objs-y)
381 +obj-m += $(m-objs-m)
383 +obj-$(CONFIG_KPERFCTR) += kperfctr.o
384 +kperfctr-objs := $(kernel-objs-y)
387 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/RELEASE-NOTES
388 ===================================================================
389 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/RELEASE-NOTES 1969-12-31 19:00:00.000000000 -0500
390 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/RELEASE-NOTES 2004-11-18 20:59:11.000000000 -0500
392 +$Id: RELEASE-NOTES,v 1.234.2.28 2004/10/19 16:22:47 mikpe Exp $
397 +Version 2.6.10.2, 2004-10-19
398 +- virtual.c: replace nrctrs_lock with a mutex. Avoids illegal
399 + may-sleep-while-holding-lock, caused by mutex operations in
400 + perfctr_cpu_{reserve,release}().
401 + Backport from perfctr-2.7.6.
402 +- PPC32: Correct MMCR0 handling for FCECE/TRIGGER. Read
403 + MMCR0 at suspend and then freeze the counters. Move
404 + this code from read_counters() to suspend(). At resume,
405 + reload MMCR0 to unfreeze the counters. Clean up the
406 + cstatus checks controlling this behaviour.
407 + Backport from perfctr-2.7.6.
409 +Version 2.6.10, 2004-09-14
410 +- Fixed p4_clear_counters() to not access IQ_ESCR{0,1}
413 +Version 2.6.10-pre1, 2004-08-03
414 +- Changed x86-64 to use the x86 include file and driver.
415 + Intel's 64-bit P4 should now work in the x86-64 kernel.
416 +- Replaced PERFCTR_INTERRUPT_SUPPORT and NMI_LOCAL_APIC
417 + #if:s in x86 code by #ifdef:s on CONFIG_X86_LOCAL_APIC.
418 +- Use macros to clean up x86 per-cpu cache accesses.
419 +- Recognize model 13 Pentium-Ms.
420 +- Changed isuspend_cpu on x86 to be like x86-64's: it
421 + now stores a CPU number instead of a cache pointer.
422 +- x86: make perfctr_cpu_name more approximate.
423 +- The x86 driver records a simplified CPU type for x86_tests,
424 + but this only occurs if PERFCTR_INIT_TESTS is configured.
425 + perfctr_info.cpu_type is now unused.
426 +- Changed P4 driver to set up and check an explicit flag
427 + for EXTENDED_CASCADE availability. perfctr_info.cpu_type
428 + is now unused except for perfctr_x86_init_tests().
429 +- x86: Reformatted "if( x )" to "if (x)" and similarly for while
430 + and switch statements. Deleted #if 0 blocks.
432 +Version 2.6.9, 2004-07-27
433 +- Fix ppc_check_control() to allow 7400/7410 processors to
434 + specify MMCR2[THRESHMULT].
435 +- PPC32 cleanups: make get_cpu_cache() return pointer not lvalue,
436 + eliminate duplicated initialisation/cleanup code.
437 +- Makefile: enforce -fno-unit-at-a-time with gcc-3.4 on x86,
438 + to prevent stack overflow in 2.6 kernels < 2.6.6.
439 +- Do sync_core() before rdtsc() in x86_tests, to avoid bogus
440 + benchmarking data on K8. Add sync_core() implementation for
441 + the 32-bit kernel. Add sync_core() benchmark.
442 +- Added __perfctr_mk_cstatus() to allow x86.c:finalise_backpatching()
443 + to create a cstatus with i-mode counters marked as present, but
444 + with zero actual counters. This prevents perfctr_cpu_isuspend()
445 + from clearing the control register for counter #0 at init-time,
446 + when the hardware doesn't belong to this driver. On AMD and P6
447 + this would accidentally disable the NMI watchdog.
448 +- x86: Marked initial targets of backpatchable calls
449 + 'noinline' to prevent gcc from inlining them, which
450 + completely breaks the backpatching mechanism.
451 +- x86_tests: fix CONFIG_X86_LOCAL_APIC=n linkage error.
452 +- 2.6.8-rc1 no longer makes cpu_online_map a #define on UP,
453 + breaking modules. Reintroduce the macro.
454 +- 2.6.8-rc1 changed cpus_complement() calling convention.
455 + Replace cpus_complement();cpus_and() with cpus_andnot(),
456 + and provide cpus_andnot() compat macro.
457 +- PPC32: support generic CPUs using only the TB.
458 +- PPC32: query OF for CPU/TB frequencies, drop /proc/cpuinfo
460 +- PPC32: avoid CPU re-detection in tests code.
461 +- PPC32: clean up and sync with current perfctr-2.7 code.
463 +Version 2.6.8, 2004-05-29
464 +- Added recognition of PowerPC 750GX.
465 +- Changes for the {reserve,release}_lapic_nmi() API added in
466 + kernel 2.6.6 backported from perfctr-2.7.1:
467 + * Starting with kernel 2.6.6 we no longer need access to
468 + nmi_perfctr_msr, so removed EXPORT_SYMBOL() and <asm/apic.h>
469 + patches related to this variable (except for older kernels).
470 + * Updated x86.c to use the new API. Added simulation (without
471 + the non-conflict guarantees) for older kernels.
472 + * Moved hardware reservation to x86.c's "reserve" procedure.
473 + The init code now only does read-only hardware detection.
474 + * Added a mutex to the reserve/release procedures, eliminating
475 + * a long-standing race possibility.
476 + * Changed x86.c to reserve and release the hardware around its
477 + call to perfctr_x86_init_tests().
478 + * Similarly updated x86_64.c for the new API.
480 +Version 2.6.7, 2004-05-04
481 +- Replaced x86_64_tests.{c,h} with x86_tests.{c,h}.
482 +- sys_device_{,un}register() was renamed as sysdev_{,un}register()
483 + in 2.6.4-rc2. Updated x86.c and x86_64.c accordingly, and
484 + added a compatibility definition in compat.h.
485 +- Removed unnecessary '#include "compat.h"' from x86_tests.c.
486 +- Replaced x86_64_setup.c with x86_setup.c.
487 +- Replaced x86_64_compat.h with x86_compat.h.
488 +- Moved perfctr_interrupt entry point from x86_setup.c to patch kit,
489 + for kernels older than 2.4.21. Cleanup to facilitate future merge
490 + of x86_setup.c and x86_64_setup.c.
492 +Version 2.6.6, 2004-02-21
493 +- Fixed a bug in x86-64's perfctr interrupt entry code in 2.4 kernels,
494 + causing it to pass the wrong value for "struct pt_regs*". This
495 + was harmless since the retrieved "rip" was unused, but still wrong.
496 + Renamed do_perfctr_interrupt to smp_perfctr_interrupt to allow
497 + using the 2.4 kernel's standard BUILD_SMP_INTERRUPT macro.
498 +- Unmask LVTPC after interrupt on Pentium-M. An oprofile user
499 + reports that P-M auto-masks LVTPC just like P4. Preliminary
500 + measurements indicate a 40 to 60 cycle cost for the apic write
501 + on P4s and P6s, so the unmask is not done unconditionally.
502 +- Measure LVTPC write overhead in x86{,_64}_tests.c.
503 +- Add Pentium 4 Model 3 detection.
504 +- The 2.4.21-193 SuSE kernel does EXPORT_SYMBOL(mmu_cr4_features).
505 + Add compat24.h workaround for this.
507 +Version 2.6.5, 2004-01-26
508 +- Added perfctr_info.cpu_type constants to <asm-ppc/perfctr.h>.
509 +- Init filp->f_mapping in virtual.c for 2.6.2-rc1+ kernels.
510 +- Updated p4_check_control():
511 + * Allow ESCR.CPL_T1 to be non-zero when using global-mode
512 + counters on HT processors.
513 + * Don't require ESCR.CPL_T0 to be non-zero. CPL_T0==0b00
514 + is safe and potentially useful (global counters on HT).
515 + * Require CCCR.ACTIVE_THREAD==0b11 on non-HT processors, as
516 + documented in the IA32 Volume 3 manual. Old non-HT P4s
517 + seem to work Ok for all four values (see perfctr-2.6.0-pre3
518 + notes), but this is neither guaranteed nor useful.
519 +- x86.c now detects & records P4 HT-ness also in UP kernels.
520 +- Added 'is_global' parameter to perfctr_cpu_update_control().
521 + This flag is ignored on everything except P4 (sigh).
523 +Version 2.6.4, 2004-01-12
524 +- Added 'tsc_to_cpu_mult' field to struct perfctr_info, replacing
525 + '_reserved1'. This is needed on PowerPC to map time-base ticks
526 + to actual time. On x86/AMD64, tsc_to_cpu_mult == 1.
527 +- Added support for PowerPC 604/7xx/74xx processors. Overflow
528 + interrupts are currently not allowed due to the PMI/DECR erratum.
529 +- Replaced perfctr_cpus_mask() with cpus_addr(). Updated cpumask.h
530 + to define cpus_addr() for kernels older than 2.6.1.
532 +Version 2.6.3-pl1, 2004-01-01
533 +- Moved the x86 interrupt handler definition from x86_setup.c to
534 + the patch kit for 2.4.21 and later 2.4 kernels, like it already
535 + is done for 2.6 kernels. This change is needed due to extensive
536 + interrupt handler changes in RedHat's 2.4.21-6.EL kernel.
537 +- Simplified <asm-i386/perfctr.h>: now that early 2.4 kernels no
538 + longer are supported, LOCAL_PERFCTR_VECTOR is known to be defined,
539 + so CONFIG_X86_LOCAL_APIC implies PERFCTR_INTERRUPT_SUPPORT.
541 +Version 2.6.3, 2003-12-21
542 +- Removed gperfctr_cpu_state_only_cpu_sdesc's total_sizeof
543 + optimisation. The ABI change in 2.6.2 broke it, leading to
544 + the new fields not being cleared and later causing EOVERFLOW.
545 +- The perfctr_ioctl32_handler() workaround is now only applied
546 + to kernels older than 2.4.23, since 2.4.23 added the "NULL
547 + handler == sys_ioctl" logic.
549 +Version 2.6.2, 2003-11-23
550 +- Added 16 bytes (four fields) of reserved data to perfctr_info,
551 + perfctr_cpu_control, vperfctr_control, gperfctr_cpu_control,
552 + and gperfctr_cpu_state. Renumbered marshalling tags for
553 + generic structures. Bumped ABI versions.
554 +- Only allow use of IQ_ESCR{0,1} on P4 models <= 2. These ESCRs
555 + were removed from later models, according to a recent Intel
556 + documentation update (252046-006).
557 +- Fixes for Fedora Core 1's 2.4.22-1.2115.nptl kernel:
558 + * Work around their incomplete and broken cpumask_t backport.
559 + * Avoid name conflict due to their on_each_cpu() backport.
560 + * Handle their preempt_disable()/enable() macros.
561 +- Added new perfctr_cpu_is_forbidden() macro to fix a
562 + compilation error affecting AMD64 in SMP 2.6 kernels.
563 + SMP cpu_isset() requires that mask is an lvalue, but
564 + for AMD64 the mask is a constant.
566 +Version 2.6.1, 2003-10-05
567 +- Kernel 2.6.0-test6 changed /proc/self and the /proc/<pid>/
568 + namespace to refer to "processes" (groups of CLONE tasks)
569 + instead of actual kernel tasks. This forced the planned
570 + transition of the vperfctr API from /proc/<pid>/perfctr
571 + to /dev/perfctr to occur immediately. Changes:
572 + * Moved /dev/perfctr implementation from global.c to init.c.
573 + * Implemented VPERFCTR_{CREAT,OPEN}, vperfctr_attach(), and
574 + the vperfctrfs pseudo-fs needed to support the magic files.
575 + The fs code was ported from perfctr-1.6/3.1, but updated
576 + for 2.6 and fixed to permit module unloading in 2.4.
577 + * Fixed VPERFCTR_OPEN to accept tsk->thread.perfctr == NULL.
578 + (Needed to info querying commands.)
579 + * Removed /proc/<pid>/perfctr code. Simplified vperfctr_stub code.
580 + * Updated vperfctr_attach() to mimic the old /proc vperfctr_open().
581 + This fixes some synchronisation issues.
583 + * Removed #if checks and code for kernels older than 2.4.16.
584 + * Eliminated compat macros that are identical in 2.6 and 2.4.
585 + * Moved ptrace_check_attach EXPORT_SYMBOL from x86{,_64}_setup.c
587 + * get_task_by_proc_pid_inode() is now trivial. Eliminated it.
588 + * p4_ht_finalise() is now trivial. Eliminated it.
589 +- Added MODULE_ALIAS() declaration, eliminating the need for
590 + an alias in /etc/modprobe.conf with 2.6 kernels. Added
591 + MODULE_ALIAS() compatibility #define in compat24.h.
592 +- Added detection of AMD K8 Revision C processors.
593 +- Updated K8C detection for Revision C Athlon64s.
595 +Version 2.6.0, 2003-09-08
596 +- Handle set_cpus_allowed() when PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED:
597 + * Add bad_cpus_allowed flag to struct vperfctr.
598 + * Check bad_cpus_allowed in __vperfctr_resume: if resuming
599 + with PMCs on forbidden CPU, kill counters and SIGILL current.
600 + * __vperfctr_set_cpus_allowed() callback: set bad_cpus_allowed
601 + and print warning if mask allows forbidden CPUs.
602 + * Use task_lock/unlock instead of preempt_disable/enable to
603 + synchronise task_struct accesses.
604 + * Ensure sampling_timer and bad_cpus_allowed share cache line.
605 + * #include <linux/compiler.h> explicitly for 2.4.18 and older
606 + kernels; newer kernels include it from <linux/kernel.h>.
607 + * Hook in virtual_stub.c.
608 + * Hook and cpumask_t typedef in <linux/perfctr.h>.
609 +- Simplify #if test for set_cpus_allowed() emulation code.
610 + Also don't define it if CONFIG_PERFCTR_VIRTUAL isn't set.
611 +- cpumask.h only typedefs cpumask_t if <linux/perfctr.h> hasn't.
612 +- Don't hide #include <linux/kernel.h> in compat24.h.
613 +- Fixed compat24.h to test for MODULE not CONFIG_MODULES at the
614 + __module_get/module_put macros.
616 +Version 2.6.0-pre5, 2003-08-31
617 +- printk() is not allowed in switch_to(). Disabled debug code
618 + which could violate that rule. Changed virtual_stub.c to BUG()
619 + instead of printk() if the driver is invoked when not loaded.
620 +- Renamed vperfctr_exit2() to vperfctr_unlink() for clarity.
621 +- gcc-3.3.1 issued several "dereferencing type-punned pointer will
622 + break strict-aliasing rules" warnings for marshal.c. Used explicit
623 + unions to fix the warnings and clean up the code.
624 +- Removed compat22.h.
625 +- cpumask_t was included in standard 2.6.0-test4; replace #ifndef
626 + test in cpumask.h with normal kernel version test.
627 +- x86-64 fix: sys_ioctl() isn't exported to modules, so call
628 + filp->f_op->ioctl() instead in perfctr_ioctl32_handler().
629 +- x86-64 fix: init.c must include <asm/ioctl32.h> not <linux/ioctl32.h>
630 + for compatibility with 2.4 kernels.
632 +Version 2.6.0-pre4, 2003-08-19
633 +- Fix x86-64 register_ioctl32_conversion() usage for 2.4 kernels:
634 + * Supply dummy handler since a NULL handler oopses the kernel.
635 + * Test CONFIG_IA32_EMULATION since CONFIG_COMPAT is post-2.4.
636 +- Fixed and merged the new API struct marshalling code:
637 + * New files marshal.c and marshal.h contain the marshalling code
638 + and high-level helper functions (source shared with the library).
639 + * User-space structs are struct perfctr_struct_buf and accessed using
640 + perfctr_copy_{from,to}_user() with ptr to appropriate descriptor.
641 + The cpumask stuff isn't changed.
642 + * All ioctls registered as trivially 32-bit compatible on x86-64.
643 + * Changed perfctr_info cpu_type/cpu_features from short to int:
644 + this avoids the need for UINT16 marshalling support, and cpumask_t
645 + caused perfctr_info to change binary representation anyway.
646 +- Declared VPERFCTR_{CREAT,OPEN} ioctls, but left them unimplemented.
647 +- Fixed vperfctr_open() preemption bug. The O_CREAT check+install
648 + code could be preempted, leading to remote-control races.
649 +- Fixed perfctr_exit_thread() preemption bug. It detached the vperfctr
650 + before calling __vperfctr_exit(). If current was preempted before
651 + __vperfctr_exit() called vperfctr_suspend(), perfctr_suspend_thread()
652 + would fail to suspend the counters. The suspend+detach is now done
653 + atomically within __vperfctr_exit().
654 +- Changes to handle 2.6 kernels with the cpumask_t patch (-mm, -osdl):
655 + * Convert perfctr_cpus_forbidden_mask accesses to cpumask_t API.
656 + Based in part on a patch for the -osdl kernel by Stephen Hemminger.
657 + * Remove cpus and cpus_forbidden from struct perfctr_info,
658 + since their sizes depend on the kernel configuration.
659 + * Add struct perfctr_cpu_mask to export cpumask_t objects
660 + sanely (i.e., using ints not longs) to user-space.
661 + * Add CPUS and CPUS_FORBIDDEN commands to retrieve these sets.
662 + * Add cpumask.h to emulate cpumask_t API in cpumask_t-free kernels.
663 + * Move perfctr_cpus_forbidden_mask declaration/#define from
664 + <asm/perfctr.h> to cpumask.h -- necessary since <asm/perfctr.h>
665 + doesn't have access to the driver's compatibility definitions.
666 +- Cleaned up perfctr_cpu_ireload().
667 +- Removed struct field offset check from init.c.
668 +- 2.4.22-rc1 does EXPORT_SYMBOL(mmu_cr4_features). Added
669 + new compat #define to handle this.
670 +- Rename x86.c's rdmsrl() to rdmsr_low() to work around msr.h
671 + changes in 2.6.0-test3. Also rename rdpmcl() to rdpmc_low().
672 +- Replaced __attribute__((__aligned__(SMP_CACHE_BYTES))) usage
673 + with the official ____cacheline_aligned macro.
674 +- Detect cpuid 0x69x VIA C3s (Antaur/Nehemiah).
676 +Version 2.6.0-pre3, 2003-08-03
677 +- Changed perfctr_info.cpus and cpus_forbidden to be int instead of
678 + long, to make x86-32 and x86-64 compatible. This is a temporary
679 + solution, as there are patches for >32 CPUs on x86-32. The real
680 + solution is to make these sets variable-sized, and have user-space
681 + retrieve them with a new command.
682 +- Simplified GPERFCTR_CONTROL to update a single CPU instead of
683 + a set of CPUs. Moved cstatus clearing to release_hardware().
684 +- Moved gperfctr start to new GPERFCTR_START command.
685 +- Simplified GPERFCTR_READ to access a single CPU instead of a
687 +- Removed the requirement that CCCR.ACTIVE_THREAD == 3 on P4.
688 + HT processors define behaviour for all four possible values,
689 + and non-HT processors behave sanely for all four values.
690 +- Moved struct perfctr_low_ctrs definition from <asm/perfctr.h> to
691 + the corresponding low-level driver, since it's only used there.
692 +- Changed perfctr_info.cpu_khz and vperfctr_control.preserve to be
693 + int instead of long. This corrects x86-64 and makes it compatible
695 +- Updated x86.c to permit extended cascading on P4M2.
696 +- Fixed a bug where the perfctr module's refcount could be zero with
697 + code still running in the module (pending returns to exit_thread()).
698 + This could race with rmmod in preemptive kernels, and in theory
699 + also in SMP kernels.
700 + * module owner field added to vperfctr_stub
701 + * _vperfctr_exit() in the modular case is now a function in
702 + vperfctr_stub.c, which brackets the vperfctr_stub.exit() call
703 + with __module_get() and module_put() on vperfctr_stub.owner
704 + * updated 2.4 and 2.2 compat definitions of __module_get() and
705 + module_put() to work for modules != THIS_MODULE
706 +- Replaced uses of (void)try_module_get() with __module_get() as the
707 + latter is more appropriate for 2.6 kernels. Updated compat stuff.
709 +Version 2.6.0-pre2, 2003-07-13
710 +- vperfctr API fixes:
711 + * The new VPERFCTR_READ_CONTROL command retrieves a vperfctr's
713 + * Renamed VPERFCTR_SAMPLE to VPERFCTR_READ_SUM, and made it
714 + write the sums to a perfctr_sum_ctrs user-space buffer.
715 + * Non-write commands are now always permitted on unlinked perfctrs.
716 + The first change was needed since the control data no longer is
717 + accessible via the mmap()ed state. The other changes clean up and
718 + simplify perfex and the library's slow-path read_ctrs() operation.
719 +- sys_vperfctr_ functions now mark the tsk parameter as "const" if
720 + they don't need write access to it. Typically they only need to
721 + compare it with current to detect self-access cases.
722 +- perfctr_cpu_state no longer makes the perfctr_cpu_control part
723 + accessible to user-space (via mmap() of vperfctrs).
724 +- Simplified {set,is}_isuspend_cpu() in x86_64.c by having callers
725 + pass the CPU number instead of the cache pointer (which was only
726 + used to derive the CPU number).
727 +- Eliminated NMI_LOCAL_APIC #ifs from x86-64 code since x86-64
729 +- x86.c cleanups: the non-PERFCTR_INTERRUPT_SUPPORT case now uses
730 + dummy stub functions, eliminated six #ifdefs.
731 +- x86_64_setup.c needs <asm/fixmap.h>.
732 +- Protected cpu_has_mmx and cpu_has_ht #defines in x86_compat.h
733 + with #ifndef since 2.4.22-pre3 added those #defines.
734 +- Eliminated PERFCTR_INTERRUPT_SUPPORT #ifs from x86-64 code
735 + since x86-64 always defines CONFIG_X86_LOCAL_APIC.
736 +- Removed the P4-specific versions of isuspend() and iresume().
737 + P4 now uses p6_like_{isuspend,iresume}(), just like P6/K7/K8.
738 +- Long overdue cleanup in x86.c/x86_64.c: renamed per_cpu_cache
739 + pointer variables from 'cpu' to 'cache'.
740 +- Added inline functions in virtual.c for registering the overflow
741 + handler and for clearing iresume_cstatus. Cleaned out several
742 + #if PERFCTR_INTERRUPT_SUPPORT occurrences from the main code.
743 + (Partial backport from the abandoned perfctr-3.1 branch.)
744 +- Inlined now useless 'struct vperfctr_state' in 'struct vperfctr'.
746 +Version 2.6.0-pre1, 2003-07-02
747 +- Rearranged 'struct perfctr_cpu_state' to reduce the number of
748 + cache lines needed to be touched by key operations (suspend,
749 + resume, sample). Switched from struct-of-arrays to array-of-struct
750 + for perfctr counts, and copied pmc_map into the PMC data array.
751 + The old representation touched at least 3 cache lines at key
752 + operations, the new one only needs one cache line in most cases.
753 + The user-space mmap() view of the new representation is binary
754 + compatible between x86 and x86-64.
755 +- Changed 'isuspend_cpu' in perfctr_cpu_state on x86-64 to be a
756 + 32-bit CPU number, to maintain binary compatibility with x86.
757 +- Removed the union of p5_cesr and id; use id throughout.
758 +- Removed _filler and si_signo from 'struct vperfctr_state', making
759 + the user-space view of it identical to 'struct perfctr_cpu_state'.
761 +Version 2.5.5, 2003-06-15
762 +- Updated x86 driver for 2.5.71 local APIC driver model changes.
763 +- Updated x86-64 driver for 2.5.71 NMI watchdog enable/disable API.
764 +- x86-64 is broken in 2.5.71 since x86-64 updated to driver model
765 + for local APIC and NMI watchdog, at the same time as x86 moved
766 + to a newer version of the "system device" driver model. Updated
767 + the x86-64 driver for the new model, which is expected to be in
768 + x86-64 by 2.5.72 (patch exists for 2.5.71).
770 +Version 2.5.4, 2003-06-01
771 +- The generic-x86-with-TSC driver now uses rdpmc_read_counters
772 + and p6_write_control instead of its own procedures.
773 +- K8 docs are now available. Updated comment in x86.c accordingly.
774 +- P4 OVF_PMI+FORCE_OVF counters didn't work at all, resulting in
775 + BUG messages from the driver since identify_overflow failed to
776 + detect which counters had overflowed, and vperfctr_ihandler
777 + left the vperfctr in an inconsistent state. This works now.
778 + However, hardware quirks makes this configuration only useful
779 + for one-shot counters, since resuming generates a new interrupt
780 + and the faulting instruction again doesn't complete. The same
781 + problem can occur with regular OVF_PMI counters if ireset is
782 + a small-magnitude value, like -5.
783 + This is a user-space problem; the driver survives.
784 +- On P4, OVF_PMI+FORCE_OVF counters must have an ireset value of -1.
785 + This allows the regular overflow check to also handle FORCE_OVF
786 + counters. Not having this restriction would lead to MAJOR
787 + complications in the driver's "detect overflow counters" code.
788 + There is no loss of functionality since the ireset value doesn't
789 + affect the counter's PMI rate for FORCE_OVF counters.
790 +- Moved P4 APIC_LVTPC reinit from p4_isuspend() to identify_overflow().
791 + Reduces context-switch overheads when i-mode counters are active.
792 +- Corrected vperfctr_suspend()'s precondition.
793 +- Corrected comment in <asm/perfctr.h> to state that ireset[]
794 + values must be negative rather than non-positive.
795 +- Made 'perfctr_cpu_name' __initdata, like its predecessor.
797 +Version 2.5.3.1, 2003-05-21
798 +- Replaced 'char *perfctr_cpu_name[]' by 'char *perfctr_cpu_name'.
799 + This is needed for x86-64 and other non-x86 architectures.
800 +- Changed <asm-x86_64/perfctr.h> to use 'long long' for 64-bit sums.
801 + This doesn't change the ABI, but improves user-space source code
802 + compatibility with 32-bit x86.
803 +- Removed the !defined(set_cpus_allowed) check added to compat24.h
804 + in 2.5.3. It's wrong for SMP builds with modules and MODVERSIONS,
805 + since the set_cpus_allowed() emulation function becomes a #define
806 + from include/linux/modules/x86_setup.ver. Instead add the already
807 + used HAVE_SET_CPUS_ALLOWED #define to include/linux/config.h in
808 + the kernel patch, but make it conditional on CONFIG_X86_64.
810 +Version 2.5.3, 2003-05-16
811 +- Added detection code for Pentium M. MISC_ENABLE_PERF_AVAIL is
812 + now checked on both P4 and Pentium M.
813 +- Added x86_64 driver code. Both x86_64.c and asm-x86_64/perfctr.h
814 + are basically simplified versions of corresponding x86 files,
815 + with P5 and P4 support removed, 2.2 kernel support removed, and
816 + 'long long' for sums replaced by 'long'. The last change is
817 + painful for user-space and may be reverted.
818 +- compat24.h: don't define set_cpus_allowed() if already #defined,
819 + workaround for RawHide's 2.4.20-9.2 x86_64 kernel.
820 +- Removed list of supported CPUs from Kconfig. That information
821 + belongs elsewhere (and it's a pain to maintain for 2.2/2.4).
823 +Version 2.5.2, 2003-04-13
824 +- Minor cleanup: use PROC_I() unconditionally in virtual.c,
825 + implement trivial compat macro in compat24.h.
826 +- Updated power management code for the local APIC and NMI
827 + watchdog driver model changes in kernel 2.5.67.
828 + The suspend/resume procedures are still no-ops, however.
829 + This revealed a bug in the lapic_nmi_watchdog resume code:
830 + it resumes the lapic_nmi_watchdog even when it was disabled
831 + before suspend. Perfctr's 2.5.67 kernel patch includes a fix.
832 +- perfctr_sample_thread() is now used also on UP. Anton Ertl's
833 + 2.26GHz UP P4 managed to execute a process for more than 2^32
834 + cycles before suspending it, causing TSC inaccuracies.
835 +- RH9's 2.4.20-8 kernel changed cpu_online(), put_task_struct() and
836 + remap_page_range() to be more like in 2.5 kernels, and moved the
837 + declaration of ptrace_check_attach() from mm.h to ptrace.h, also
838 + like in 2.5 kernels, requiring fixes to compat24.h and x86_setup.c.
839 +- Added note in x86.c about the new Pentium M processor.
841 +Version 2.5.1, 2003-03-23
842 +- Fix P4 HT initialisation. I've seen several boot logs from
843 + people running MP P4 Xeons with HT disabled: this produces
844 + an ugly "restricting access for CPUs 0x0" message, and would
845 + cause P4 HT init to unnecessarily return error in older kernels
846 + lacking set_cpus_allowed(). Now only print the message or
847 + signal error if non-zero siblings actually are found.
848 +- The set_cpus_allowed() emulation doesn't compile in 2.4
849 + kernels older than 2.4.15 due to the p->cpus_running field.
850 + Updated version checks to skip it in 2.4.x when x<15.
851 +- Fix set_cpus_allowed() emulation compile error on BUG_ON()
852 + in 2.4 kernels older than 2.4.19.
853 +- Added Nehemiah note/reminder in x86.c:centaur_init().
855 +Version 2.5.0, 2003-03-10
856 +- Reverted the 2.5.0-pre2 change that replaced the PERFCTR_INFO
857 + ioctl by read(): it made the API look too weird.
858 + Added a PERFCTR_ABI ioctl which only retrieves 'abi_version'.
859 +- Cleaned up struct perfctr_info: renamed abi_magic to abi_version,
860 + and version to driver_version. Renamed PERFCTR_*_MAGIC too.
861 +- Cleaned up struct perfctr_cpu_control: moved evntsel_aux[]
862 + into the p4 sub-struct and renamed it as escr[]. Only P4 needs
863 + it anyway, and the new name clarifies its purpose.
864 +- Renumbered the vperfctr ioctls to the 8-15 range (8-11 are used)
865 + and reserved 0-7 (0-1 are used) for generic ioctls.
866 +- Added 'use_nmi' field to struct gperfctr_control, reserved for
867 + future use if/when support for i-mode gperfctrs is implemented.
868 +- Replaced some preempt/smp_call_function combinations with 2.5.64's
869 + new on_each_cpu() construct. Added compatibility definitions to
870 + compat24.h and compat22.h.
872 +Version 2.5.0-pre2, 2003-03-03
873 +- Added ABI version to perfctr_info. Replaced PERFCTR_INFO ioctl
874 + by read() on the fd, since that allows reading the ABI version
875 + even in the case of a version mismatch. Removed binary layout
876 + magic number from vperfctr_state. Rearranged perfctr_info to
877 + make the 'long' fields 8-byte aligned.
878 +- Added #ifdef CONFIG_KPERFCTR to <linux/perfctr.h> to ensure
879 + that <asm/perfctr.h> isn't included unless CONFIG_KPERFCTR=y.
880 + This allows the patched kernel source to compile cleanly also
881 + in archs not yet supported by perfctr.
882 +- Removed PERFCTR_PROC_PID_MODE #define and replaced it with
883 + /*notype*/S_IRUSR in the patch files.
884 +- Added perfctr_vector_init() to <asm-i386/perfctr.h>. Cleaned
885 + up arch/i386/kernel/i8259.c patch.
886 +- Removed apic_lvtpc_irqs[] array. Removed irq.c patch.
887 +- Updated CONFIG_PERFCTR_INIT_TESTS help text to match reality.
888 +- Kernel 2.4.21-pre5 added set_cpus_allowed(), which required
889 + fixing compat24.h and x86_setup.c.
890 +- Fixed init.c for kernel 2.5.63 removing EXPORT_NO_SYMBOLS.
891 +- Cleaned up compat.h by moving 2.2/2.4 stuff to separate files.
893 +Version 2.5.0-pre1, 2003-02-19
894 +- Repair global perfctr API: the target CPUs are now explicit
895 + in the calls to write control and read state. Global perfctrs
896 + now work on 2.5 SMP kernels (which no longer have smp_num_cpus
897 + or cpu_logical_map()), and HT P4s (asymmetric MPs).
898 +- struct perfctr_info has new bitmask fields for the set of CPUs
899 + (cpu_online_map) and forbidden CPUs; dropped the nrcpus field.
900 +- add cpu_online() compat macro to compat.h
901 +- VPERFCTR_STOP is subsumed by VPERFCTR_CONTROL. Removed it.
902 +- Detect K8 as K8 not K7. They are not identical.
903 +- Makefile cleanup: moved 2.4/2.2 kernel stuff to Makefile24.
904 +- Makefile fix: removed export-objs for 2.5 kernels.
905 +- Kconfig fix: don't mention obsolete .o module suffix.
907 +Version 2.4.5, 2003-02-09
908 +- Fixed two minor compile warnings in x86_tests.c for 2.5 kernels.
910 +Version 2.4.4, 2003-01-18
911 +- Fixed a bug in iresume() where an interrupt-mode counter could
912 + increment unexpectedly, and also miss the overflow interrupt.
913 + The following setup would cause the problem:
914 + P1 has EVNTSELn in non-interrupt mode, counting some high-
915 + frequency event (e.g. INST_RETIRED) in kernel-mode. P2 has
916 + EVNTSELn in interrupt-mode, counting some low-frequency event
917 + (e.g. MMX_ASSIST) in user-mode. P1 suspends. Since EVNTSELn is
918 + in non-interrupt mode, it is not disabled. P2 resumes. First
919 + iresume() finds that the CPU cache ID is not P2's, so it reloads
920 + PERFCTRn with P2's restart value. Then write_control() reloads
921 + EVNTSELn with P2's EVNTSEL. At this point, P2's PERFCTRn has been
922 + counting with P1's EVNTSELn since iresume(), so it will no longer
923 + equal P2's restart value. And if PERFCTRn overflowed, the overflow
924 + will go undetected since P1's EVNTSELn was in non-interrupt mode.
925 + To avoid this problem, iresume() now ensures that a counter's
926 + control register is disabled before reloading the counter.
927 +- Fixed some ugly log messages from the new HT P4 init code:
928 + * forbidden_mask would be printed as "0X<mask>" (capital X)
929 + * finalise_backpatching() could trigger a BUG! printk from
930 + p4_write_control() if the CPU the init code runs on was
931 + in the forbidden set. At init-time this is not an error.
932 + Avoided this by temporarily resetting the forbidden_mask.
933 +- Added preliminary support for AMD K8 processors with the
934 + regular 32-bit x86 kernel. The K8 performance counters appear
935 + to be identical or very similar to the K7 performance counters.
937 +Version 2.4.3, 2002-12-11
938 +- Added x86.c:perfctr_cpus_forbidden_mask. This bitmask describes
939 + the set of CPUs that must not access the perfctrs. On HT P4 MPs,
940 + only logical CPU #0 in each package is allowed access -- this
941 + avoids the resource conflict that would occur if both logical
942 + processors were to access the perfctrs. In other cases (UP or
943 + non-HT-P4 MPs) the mask is zero.
944 +- vperfctr_control() now calls set_cpus_allowed() to ensure that
945 + the task stays away from CPUs in perfctr_cpus_forbidden_mask.
946 + This is racy with sys_sched_setaffinity(), and possibly some
947 + of the kernel's internal set_cpus_allowed() calls, but the race
948 + is unlikely to occur in current 2.4 kernels.
949 +- Cleaned up the parameter passing protocol between vperfctr_ioctl()
950 + and the individual vperfctr "system call" procedures.
951 +- Added safety check in global.c to disallow global-mode perfctrs
952 + on asymmetric MPs until the API has been fixed.
953 +- Added set_cpus_allowed() implementation for 2.4 kernels, except
954 + those that already have it as indicated by HAVE_SET_CPUS_ALLOWED:
955 + this symbol is added to <linux/config.h> by the kernel patch.
956 +- 2.2 kernels can't enforce CPU affinity masks, so x86.c warns if
957 + a HT P4 MP runs a 2.2 kernel, and falls back to generic x86 mode.
958 + Added dummy set_cpus_allowed() macro for 2.2 kernels.
959 +- x86_compat.h now implements cpuid_ebx() and cpu_has_ht for old kernels.
960 +- Makefile cleanup: Rules.make is obsolete in 2.5.
961 +- Compile fixes in x86.c and virtual_stub.c: <linux/fs.h> needs to
962 + be included explicitly for the 2.5.50 kernel.
964 +Version 2.4.2, 2002-11-25
965 +- Fixed virtual.c:inc_nrctrs() to handle the -EBUSY case correctly.
966 + If the HW was busy (e.g. global running), then the first attempt
967 + to open a vperfctr would fail but further attempts would succeed.
968 + Updated error propagation to distinguish -EBUSY from -ENOMEM.
969 +- Updated global.c for preempt-safety.
970 +- Made the driver safe for preemptible kernels. This required a lot
971 + of analysis, but resulted in relatively few actual code changes.
972 + (Backport from the perfctr-3.1 branch.)
973 +- Ported to 2.5.48: Replaced MOD_INC_USE_COUNT by try_module_get()
974 + and MOD_DEC_USE_COUNT by module_put(). Updated compat.h.
975 +- Ported to 2.5.45: added Kconfig, removed Config.help.
977 +Version 2.4.1, 2002-10-12
978 +- RedHat 8.0's 2.4.18-14 kernel does EXPORT_SYMBOL(cpu_khz) while
979 + the vanilla 2.4.18 does not. This clashes with x86_setup.c's
980 + EXPORT_SYMBOL(cpu_khz). I've found no easy way to distinguish
981 + between these kernels at C preprocessing time, so I changed
982 + x86_setup.c to define a trivial perfctr_cpu_khz() function and
983 + EXPORT_SYMBOL that one instead.
985 +Version 2.4.0, 2002-09-26
986 +- Config.help updated to state that Pentium 4 is supported.
987 +- 2.5.32 moved ptrace_check_attach() declaration to <linux/ptrace.h>.
988 +- Removed redundant /proc/<pid>/perfctr access control check
989 + from vperfctr_stub_open(). Since 2.4.0-pre1 this check didn't
990 + match the real one, which prevented remote opens when the
991 + driver was built as a module.
993 +Version 2.4.0-pre2, 2002-08-27
994 +- vperfctr_control() now allows the user to specify that some PMC
995 + sums are not to be cleared when updating the control.
996 + There is a new bitmap field `preserve' in struct vperfctr_control:
997 + if bit i is set then PMC(i)'s sum is not cleared.
998 + `preserve' is a simple `unsigned long' for now, since this type
999 + fits all currently known CPU types.
1000 + This change breaks binary compatibility, but user-space code which
1001 + clears the entire control record before filling in relevant fields
1002 + will continue to work as before after a recompile.
1003 + This feature removes a limitation which some people felt was a
1004 + problem for some usage scenarios.
1006 +Version 2.4.0-pre1, 2002-08-12
1007 +- Initial implementation of a new remote-control API for virtual
1008 + per-process perfctrs. A monitor process may access a target
1009 + process' perfctrs via /proc/pid/perfctr and operations on that
1010 + file, if the monitor holds the target under ptrace ATTACH control.
1011 + Updated virtual.c to allow remote access.
1012 + Updated x86.c:perfctr_cpu_ireload() to work also in the remote
1013 + control case on SMP machines.
1015 +Version 2.3.12, 2002-08-12
1016 +- Trivial comment fixes in compat.h and x86_compat.h.
1017 +- Removed __vperfctr_sample(), vperfctr_stub.sample, and bug_sample()
1018 + from UP builds, since they are needed only on SMP.
1020 +Version 2.3.11, 2002-07-21
1021 +- Accumulated sums are now maintained for interrupt-mode perfctrs.
1022 + User-space can use the standard syscall-less algorithm for computing
1023 + these counters' current sums, should that be needed.
1025 +Version 2.3.10, 2002-07-19
1026 +- Added PERFCTR_X86_INTEL_P4M2 CPU type for Model 2 P4s, since
1027 + they have ESCR Event Mask changes in a few events.
1028 +- The driver now supports replay tagging events on P4, using the
1029 + pebs_enable and pebs_matrix_vert control fields added in 2.3.8.
1030 +- Some Pentium MMX and Pentium Pro processors have an erratum
1031 + (Pentium erratum #74, Pentium Pro erratum 26) which causes SMM
1032 + to shut down if CR4.PCE is set. intel_init() now clears the
1033 + RDPMC feature on the affected steppings, to avoid the problem.
1034 +- perfctr_cpu_release() now clears the hardware registers and
1035 + invalidates the per-cpu cache. This should allow the counter
1036 + hardware to power down when not used, especially on P4.
1037 +- Callers of update_control() have no active i-mode counters.
1038 + Documented this as a precondition, and changed update_control()
1039 + to not call isuspend(). update_control() no longer needs hardware
1040 + access, which should ease a port to CONFIG_PREEMPT=y.
1042 +Version 2.3.9, 2002-06-27
1043 +- Updated p4_escr_addr() in x86.c to match the latest revision of
1044 + Intel's IA32 Volume 3 manual, #245472-007. An error in previous
1045 + revisions of this document caused the driver to program the wrong
1046 + ESCR in some cases. (CCCRs 12/13/16 with ESCR_SELECT(2) were mapped
1047 + to SSU_ESCR0 instead of RAT_ESCR0, affecting the uop_type event.)
1049 +Version 2.3.8, 2002-06-26
1050 +- Added counter overflow interrupt support for Intel P4.
1051 +- 2.5.23 dropped smp_num_cpus and cpu_logical_map(). Added
1052 + temporary workarounds to x86.c and global.c to allow compilation
1053 + and testing under 2.5. May have to change the API (esp. global's)
1054 + to be based on the sparse cpu_online_map instead.
1055 +- RedHat's 2.4.9-34 defines cpu_relax(). Updated compat.h.
1056 +- Added pebs_enable and pebs_matrix_vert fields (currently unused)
1057 + to perfctr_cpu_control to support replay tagging events on P4.
1058 + Updated the perfctr_cpu_state binary layout magic number.
1059 +- Silenced redefinition warnings for MSR_P6_PERFCTR0 and cpu_has_mmx.
1060 +- Updated Makefile for the 2.5.19 kernel's Makefile changes.
1061 +- Merged the P6 and K7 isuspend/iresume/write_control driver code.
1062 +- Added a VC3 specific clear_counters() procedure.
1063 +- Removed pointless code from perfctr_cpu_identify_overflow().
1064 +- Removed _vperfctr_get/set_thread() wrappers and thread->perfctr
1065 + clobber checks from the DEBUG code. Removed unused "ibuf" and
1066 + obsolete si_code fields from vperfctr state and control objects.
1067 + Updated the vperfctr state magic number.
1068 +- Fixed the CONFIG_PREEMPT anti-dependency check in Config.in.
1069 +- vperfctr_control() now preserves the TSC sum on STOP;CONTROL
1070 + transitions. The failure to do this caused problems for the
1071 + PAPI P4 support being developed.
1073 +Version 2.3.7, 2002-04-14
1074 +- Kernel 2.5.8-pre3 changed the way APIC/SMP interrupt entries
1075 + are defined. Defining these with asm() in C is no longer
1076 + practical, so the kernel patch for 2.5.8-pre3 now defines
1077 + the perfctr interrupt entry in arch/i386/kernel/entry.S.
1078 +- Permit use of cascading counters on P4: in the slave counter
1079 + one sets the CASCADE flag instead of the ENABLE flag.
1080 +- Added P4 hyperthreading bit field definitions.
1081 +- Preliminary infrastructure to support a new remote-control
1082 + interface via ptrace(). Updates to compat.h, virtual.c,
1083 + virtual_stub.c, and x86_setup.c. ptrace_check_attach()
1084 + emulation for older kernels is in x86_setup.c since
1085 + virtual_stub.c isn't compiled if the driver isn't a module.
1087 +Version 2.3.6, 2002-03-21
1088 +- Rewrote sys_vperfctr_control() to do a proper suspend before
1089 + updating the control, and to skip trying to preserve the TSC
1090 + start value around the resume. This cleaned up the code and
1091 + eliminated the bogus "BUG! resuming non-suspended perfctr"
1092 + warnings that control calls to active perfctrs caused.
1093 +- Rewrote sys_vperfctr_iresume() to not preserve the TSC start
1094 + value around the resume. Since we had just done a suspend(),
1095 + this would cause double-accounting of the TSC.
1097 +Version 2.3.5, 2002-03-17
1098 +- Added detection of the VIA C3 Ezra-T processor.
1099 +- CPU detection now uses current_cpu_data instead of boot_cpu_data,
1100 + to avoid the boot_cpu_data.x86_vendor bug which is present is
1101 + all current 2.2/2.4/2.5 kernels. The bug caused the x86_vendor
1102 + field to be cleared on SMP machines, which in turn tricked the
1103 + driver to identify MP AMD K7 machines as MP Intel P6, with
1104 + disastrous results when the wrong MSRs were programmed.
1105 +- Updated compat.h for /proc/<pid>/ inode change in 2.5.4.
1106 +- Added a check to prevent building on preemptible 2.4/2.5 kernels,
1107 + since the driver isn't yet safe for those.
1108 +- Put perfctr's configuration help text in Config.help in this
1109 + directory: kernel 2.5.3-pre5 changed from a having a common
1110 + Configure.help file to having local Config.help files.
1112 +Version 2.3.4, 2002-01-23
1113 +- Updated virtual.c for remap_page_range() change in 2.5.3-pre1.
1114 + Added emulation for older kernels to compat.h.
1115 +- Permit use of tagging on P4 for at-retirement counting. This may
1116 + not yet work as expected, since up-stream (tag producing) counters
1117 + aren't disabled at context switches: a process may therefore see
1118 + more tagged uops than expected.
1119 +- Fixed uses of __FUNCTION__ to comply with changes in GCC 3.0.3.
1121 +Version 2.3.3, 2001-12-31
1122 +- Minor x86.c cleanup: reordered function definitions so that
1123 + write_control comes after isuspend/iresume: this makes it easier
1124 + to follow the runtime control flow.
1125 +- Fixed isuspend()/iresume()'s broken cache checking protocol. The
1126 + old protocol didn't handle process migration across CPUs in SMP
1127 + machines correctly, as illustrated by the following scenario:
1128 + P1 runs on CPU1 and suspends. P1 and CPU1 now have the same
1129 + cache id (->k1.id). P1 is resumed and suspended on CPU2: the state
1130 + in CPU1 is now stale. Then P1 is resumed on CPU1, and no other
1131 + process has been using CPU1's performance counters since P1's last
1132 + suspend on CPU1. The old protocol would see matching cache ids and
1133 + that P1's i-mode EVNTSELs are stopped, so it would accept the cache
1134 + and resume P1 with CPU1's stale PERFCTRS values.
1135 + In the new protocol isuspend() records the active CPU in the
1136 + state object, and iresume() checks if both the CPU and the control
1137 + id match. The new protocol is also simpler since iresume() no longer
1138 + checks if the i-mode EVNTSELs are cleared or not.
1139 +- P6 nasty i-mode to a-mode context switch bug fixed: p6_isuspend()
1140 + used to simply clear EVNTSEL0's Enable flag in order to stop all
1141 + i-mode counters. Unfortunately, that was insufficient as shown by
1142 + the following case (which actually happened).
1143 + P1 has EVNTSEL0 in a-mode and EVNTSEL1 in i-mode. P1 suspends:
1144 + PERFCTR1 is stopped but EVNTSEL1 is still in i-mode. P2 has EVNTSEL0
1145 + in a-mode and no EVNTSEL1. P2 resumes and updates EVNTSEL0. This
1146 + activates not only P2's PERFCTR0 but also the dormant PERFCTR1. If
1147 + PERFCTR1 overflows, then P2 will receive an unexpected interrupt. If
1148 + PERFCTR1 doesn't overflow, but P2 suspends and P1 resumes, then P1
1149 + will find that PERFCTR1 has a larger than expected value.
1150 + p6_isuspend() and p6_iresume() were changed to ignore the global
1151 + Enable flag and to disable/enable each i-mode EVNTSEL individually,
1152 + just like how it's done on the K7.
1153 +- x86.c cleanups: P5MMX, MII, C6, VC3, P6, K7, and P4 now all
1154 + use the same rdpmc_read_counters() method. VIA C3 now uses
1155 + p6_write_control() instead of its own method.
1156 +- Removed "pmc_map[] must be identity" restriction from P6 and K7.
1157 + The API uses the virtual counter index to distinguish a-mode
1158 + and i-mode counters, but P6 events aren't entirely symmetric:
1159 + this lead to some strange cases with the old pmc_map[] rule.
1160 + P6 and K7 isuspend() now need access to the control, so
1161 + update_control() and its callers had to be changed to allow it
1162 + to isuspend() _before_ the new control is installed.
1163 +- P4 write_control fixes: changed the ESCR cache to be indexed by
1164 + MSR offset from 0x3A0, and changed P4 write_control to index the
1165 + CCCR/ESCR cache with physical instead of virtual indices. Added
1166 + call to debug_evntsel_cache(), after updating it for pmc_map[].
1167 +- Added P4 and Generic support to x86_tests.c, and some cleanups.
1169 +Version 2.3.2, 2001-11-19
1170 +- P4 fix: the mapping from CCCR 17 to its associated ESCRs was
1171 + wrong due to an off-by-one error in x86.c:p4_escr_addr().
1172 +- P4 fix: also clear the PEBS MSRs when initialising the driver.
1173 +- Minor cleanup in x86.c: replaced the "clear MSRs" loops with
1174 + calls to a helper procedure.
1176 +Version 2.3.1, 2001-11-06
1177 +- Microscopic P4 cleanups. Testing on my new P4 box has confirmed
1178 + that the PMAVAIL flag in MSR_IA32_MISC_ENABLE is read-only.
1180 +Version 2.3, 2001-10-24
1181 +- Added support for multiple interrupt-mode virtual perfctrs
1182 + with automatic restart. Added an identify_overflow() method
1183 + to x86.c to identify and reset the overflowed counters.
1184 + Added checks to ensure that the user-specified restart values
1185 + for interrupt-mode counters are negative.
1186 + Updated virtual.c's signal delivery interface to pass a
1187 + bitmask describing which counters overflowed; the siginfo
1188 + si_code is now fixed as SI_PMC_OVF (fault-class).
1189 +- Fixed some typos in x86.c. Added a note about the C3 Ezra.
1190 +- Added EXPORT_NO_SYMBOLS to init.c, for compatibility with
1191 + announced changes in modutils 2.5.
1193 +Version 2.2, 2001-10-09
1194 +- Added preliminary support for the Pentium 4. Only basic stuff
1195 + for now: no cascading counters, overflow interrupts, tagged
1196 + micro-ops, or use of DS/PEBS. The code compiles but hasn't been
1197 + tested on an actual Pentium 4.
1199 +Version 2.1.4, 2001-09-30
1200 +- No driver-level changes.
1202 +Version 2.1.3, 2001-09-13
1203 +- Fixed a compilation problem where virtual_stub couldn't be compiled
1204 + in modular kernels older than 2.2.20pre10 if KMOD was disabled, due
1205 + to an incompatible stub definition of request_module().
1206 +- Replaced most occurrences of "VIA Cyrix III / C3" with "VIA C3".
1208 +Version 2.1.2, 2001-09-05
1209 +- Added MODULE_LICENSE() tag, for compatibility with the tainted/
1210 + non-tainted kernel stuff being put into 2.4.9-ac and modutils.
1211 +- VIA C3 support is not "preliminary" any more. Testing has revealed
1212 + that the reserved bits in the C3's EVNTSEL1 have no function and
1213 + need not be preserved. The driver now fills these bits with zeroes.
1214 + (Thanks to Dave Jones @ SuSE for running these tests.)
1215 +- Minor bug fix in the perfctr interrupt assembly code.
1216 + (Inherited from the 2.4 kernel. Fixed in 2.4.9-ac4.)
1218 +Version 2.1.1, 2001-08-28
1219 +- Preliminary recognition of Pentium 4 processors, including
1220 + checking the IA32_MISC_ENABLE MSR.
1221 +- Moved %cr4 access functions from <asm-i386/perfctr.h> to
1222 + x86_compat.h, to work around changes in 2.4.9-ac3.
1223 +- More %cr4 cleanups possible since the removal of dodgy_tsc()
1224 + in Version 2.1: moved {set,clear}_in_cr4_local() into x86.c,
1225 + and eliminated the set_in_cr4() compat macro.
1226 +- Fixed a bug in x86.c:finalise_backpatching(): the fake cstatus
1227 + mustn't include i-mode counters unless we have PCINT support.
1228 + Failure to check this cased fatal init-time oopses in some
1229 + configs (CONFIG_X86_UP_APIC set but no local APIC in the CPU).
1230 +- Minor comment updates in x86.c due to AMD #22007 Revision J.
1231 +- Removed '%' before 'cr4' in printouts from x86_tests.c, to
1232 + avoid the '%' being mutated by log-reading user-space code.
1234 +Version 2.1, 2001-08-19
1235 +- Fixed a call backpatching bug, caused by an incompatibility
1236 + between the 2.4 and 2.2 kernels' xchg() macros. The 2.2 version
1237 + lacks a "volatile" causing gcc to remove the entire statement
1238 + if xchg() is used for side-effect only. Reverted to a plain
1239 + assignment, which is safe since the 2.0.1 backpatching changes.
1240 +- Fixed a bug where an attempt to use /proc/<pid>/perfctr on an
1241 + unsupported processor would cause a (well-behaved) kernel oops,
1242 + due to calling a NULL function pointer in x86.c, vperfctr_open()
1243 + now returns -ENODEV if virtual.c hasn't been initialised.
1244 +- Removed the WinChip configuration option, the dodgy_tsc() callback,
1245 + and the clr_cap_tsc() x86_compat macro. WinChip users should configure
1246 + for generic 586 or less and use the kernel's "notsc" boot parameter.
1247 + This cleans up the driver and the 2.4 kernel patches, at the expense
1248 + of more code in the 2.2 kernel patches to implement "notsc" support.
1249 +- Minor cleanup: moved version number definition from init.c to
1250 + a separate file, version.h.
1252 +Version 2.0.1, 2001-08-14
1253 +- The unsynchronised backpatching in x86.c didn't work on SMP,
1254 + due to Pentium III erratum E49, and similar errata for other
1255 + P6 processors. (The change in 2.0-pre6 was insufficient.)
1256 + x86.c now finalises the backpatching at driver init time,
1257 + by "priming" the relevant code paths. To make this feasible,
1258 + the isuspend() and iresume() methods are now merged into
1259 + the other high-level methods; virtual.c became a bit cleaner.
1260 +- Removed obsolete "WinChip pmc_map[] must be identity" check.
1262 +Version 2.0, 2001-08-08
1263 +- Resurrected partial support for interrupt-mode virtual perfctrs.
1264 + virtual.c permits a single i-mode perfctr, in addition to TSC
1265 + and a number of a-mode perfctrs. BUG: The i-mode PMC must be last,
1266 + which constrains CPUs like the P6 where we currently restrict
1267 + the pmc_map[] to be the identity mapping. (Not a problem for
1268 + K7 since it is symmetric, or P4 since it is expected to use a
1269 + non-identity pmc_map[].)
1270 + New perfctr_cpu_ireload() procedure to force reload of i-mode
1271 + PMCs from their start values before resuming. Currently, this
1272 + just invalidates the CPU cache, which forces the following
1273 + iresume() and resume() to do the right thing.
1274 + perfctr_cpu_update_control() now calls setup_imode_start_values()
1275 + to "prime" i-mode PMCs from the control.ireset[] array.
1276 +- Bug fix in perfctr_cpu_update_control(): start by clearing cstatus.
1277 + Prevents a failed attempt to update the control from leaving the
1278 + object in a state with old cstatus != 0 but new control.
1280 +Version 2.0-pre7, 2001-08-07
1281 +- Cleaned up the driver's debugging code (virtual, x86).
1282 +- Internal driver rearrangements. The low-level driver (x86) now handles
1283 + sampling/suspending/resuming counters. Merged counter state (sums and
1284 + start values) and CPU control data to a single "CPU state" object.
1285 + This simplifies the high-level drivers, and permits some optimisations
1286 + in the low-level driver by avoiding the need to buffer tsc/pmc samples
1287 + in memory before updating the accumulated sums (not yet implemented).
1288 +- Removed the read_counters, write_control, disable_rdpmc, and enable_rdpmc
1289 + methods from <asm/perfctr.h>, since they have been obsoleted by the
1290 + new suspend/resume/sample methods.
1291 +- Rearranged the 'cstatus' encoding slightly by putting 'nractrs' in
1292 + the low 7 bits; this was done because 'nractrs' is retrieved more
1293 + often than 'nrctrs'.
1294 +- Removed the obsolete 'status' field from vperfctr_state. Exported
1295 + 'cstatus' and its access methods to user-space. (Remove the
1296 + control.tsc_on/nractrs/nrictrs fields entirely?)
1297 +- Removed WinChip "fake TSC" support. The user-space library can now
1298 + sample with slightly less overhead on sane processors.
1299 +- WinChip and VIA C3 now use p5mmx_read_counters() instead of their
1302 +Version 2.0-pre6, 2001-07-27
1303 +- New patches for kernels 2.4.6, 2.4.7, and 2.4.7-ac1.
1304 +- Sampling bug fix for SMP. Normally processes are suspended and
1305 + resumed many times per second, but on SMP machines it is possible
1306 + for a process to run for a long time without being suspended.
1307 + Since sampling is performed at the suspend and resume actions,
1308 + a performance counter may wrap around more than once between
1309 + sampling points. When this occurs, the accumulated counts will
1310 + be highly variable and much lower than expected.
1311 + A software timer is now used to ensure that sampling deadlines
1312 + aren't missed on SMP machines. (The timer is run by the same code
1313 + which runs the ITIMER_VIRTUAL interval timer.)
1314 +- Bug fix in the x86 "redirect call" backpatching routine. To be
1315 + SMP safe, a bus-locked write to the code must be used.
1316 +- Bug fix in the internal debugging code (CONFIG_PERFCTR_DEBUG).
1317 + The "shadow" data structure used to detect if a process' perfctr
1318 + pointer has been clobbered could cause lockups with SMP kernels.
1319 + Rewrote the code to be simpler and more robust.
1320 +- Minor performance tweak for the P5/P5MMX read counters procedures,
1321 + to work around the P5's cache which doesn't allocate a cache line
1323 +- To avoid undetected data layout mismatches, the user-space library
1324 + now checks the data layout version field in a virtual perfctr when
1325 + it is being mmap:ed into the user's address space.
1326 +- A few minor cleanups.
1328 +Version 2.0-pre5, 2001-06-11
1329 +- Internally use a single 'cstatus' field instead of the three
1330 + tsc_on/nractrs/nrictrs fields. Should reduce overhead slightly.
1331 +- Reorder the fields in cpu_control so that 'cstatus' and other
1332 + frequently used fields get small offsets -- avoids some disp32
1333 + addressing modes in timing-critical code.
1334 +- Fixed a bug in p6_iresume where it forgot to invalidate the
1335 + EVNTSEL cache, causing p6_write_control to fail to reload the
1336 + MSRs. (K7 had a similar bug.) Since i-mode support is disabled
1337 + at the moment, no-one was actually bitten by this.
1338 +- Fixed another iresume/write_control cache invalidation bug where a
1339 + switch to an "uninitialised" CPU would fail to initialise the MSRs.
1340 +- Added a CONFIG_PERFCTR_DEBUG option to enable internal consistency
1341 + checks. Currently, this checks that a task's vperfctr pointer
1342 + isn't clobbered behind our backs, that resume and suspend for
1343 + a vperfctr are performed on the same CPU, and that the EVNTSEL
1344 + cache is semi-consistent when reloading is optimised away.
1345 + ("semi" because it only checks that the cache agrees with the
1346 + user's control data, and not that the cache agrees with the MSRs.)
1349 +Version 2.0-pre4, 2001-04-30
1350 +- Cleanups in x86.c. #defines introduced for magic constants.
1351 + More sharing of procedures between different CPU drivers.
1352 + Fixed a bug where k7_iresume() could cause k7_write_control()
1353 + to fail to reload the correct EVNTSELs.
1354 + The WinChip C6/2/3 driver now "fakes" an incrementing TSC.
1355 +- General cleanups: s/__inline__/inline/ following Linux kernel
1356 + coding standards, and renamed the low-level control objects to
1357 + cpu_control to distinguish them from {v,g}perfctr_control objects.
1358 +- O_CREAT is now interpreted when /proc/self/perfctr is opened:
1359 + if the vperfctr does not exist, then it is created; if the
1360 + vperfctr does exist, then EEXIST is returned (unfortunately
1361 + O_EXCL doesn't work, since it's intercepted by the VFS layer).
1362 + "perfex -i" uses this to avoid having to create a vperfctr when
1363 + only an INFO command is to be issued.
1364 + libperfctr.c:vperfctr_open() uses this to decide whether to
1365 + UNLINK the newly opened vperfctr in case of errors or not.
1366 +- Cleaned up virtual.c's 2.4/2.2 VFS interface code a little,
1367 + and eliminated the OWNER_THIS_MODULE compat macro.
1368 +- Added MOD_{INC,DEC}_USE_COUNTs to virtual.c's file_operations
1369 + open and release procedures for 2.2 kernels. This should
1370 + simulate 2.4's fops_get/put at >open() and >release().
1372 +Version 2.0-pre3, 2001-04-17
1373 +- Interrupt-mode virtual perfctrs are temporarily disabled since
1374 + x86.c doesn't yet detect which PMC overflowed. The old API
1375 + could be made to work, but it was broken anyway.
1376 +- Integrated the new P4-ready data structures and APIs.
1377 + The driver compiles but the user-space stuff hasn't been
1378 + updated yet, so there may be some remaining bugs.
1380 + I have not yet committed to all details of this API. Some
1381 + things, like accumulating counters in virtual.c and global.c,
1382 + are uglier now, and going from a single "status == nrctrs"
1383 + field to three separate fields (tsc_on, nrctrs, nrictrs)
1384 + cannot be good for performance.
1386 + In the new API the control information is split in separate
1387 + arrays depending on their use, i.e. a struct-of-arrays layout
1388 + instead of an array-of-struct layout. The advantage of the
1389 + struct-of-arrays layout is that it should cause fewer cache
1390 + lines to be touched at the performance-critical operations.
1391 + The disadvantage is that the layout changes whenever the
1392 + number of array elements has to be increased -- as is the
1393 + case for the future Pentium 4 support (18 counters).
1395 +Version 2.0-pre2, 2001-04-07
1396 +- Removed automatic inheritance of per-process virtual perfctrs
1397 + across fork(). Unless wait4() is modified, it's difficult to
1398 + communicate the final values back to the parent: the now
1399 + abandoned code did this in a way which made it impossible
1400 + to distinguish one child's final counts from another's.
1401 + Inheritance can be implemented in user-space anyway, so the
1402 + loss is not great. The interface between the driver and the rest
1403 + of the kernel is now smaller and simpler than before.
1404 +- Simulating cpu_khz by a macro in very old kernels broke since
1405 + there's also a struct field with that name :-( Instead of
1406 + putting the ugly workaround back in, I decided to drop support
1407 + for kernels older than 2.2.16.
1408 +- Preliminary support for the VIA C3 processor -- the C3 is
1409 + apparently a faster version of the VIA Cyrix III.
1410 +- Added rdtsc cost deduction to the init tests code, and changed
1411 + it to output per-instruction costs as well.
1412 +- More cleanups, making 2.2 compatibility crud less visible.
1414 +Version 2.0-pre1, 2001-03-25
1415 +- First round of API and coding changes/cleanups for version 2.0:
1416 + made perfctr_info.version a string, moved some perfctr_info inits
1417 + to x86.c and eliminated some redundant variables, removed dead VFS
1418 + code from virtual.c, removed obsolete K7 tests from x86_tests.c,
1419 + removed mmu_cr4_features wrappers from x86_compat.h, minor cleanup
1420 + in virtual_stub.c.
1421 +- Fixed an include file problem which made some C compilers (not gcc)
1422 + fail when compiling user-space applications using the driver.
1423 +- Added missing EXPORT_SYMBOL declarations needed by the UP-APIC PM
1424 + code when the driver is built as a module.
1425 +- Preliminary changes in x86.c to deal with UP-APIC power management
1426 + issues in 2.4-ac kernels. The PM callback is only a stub for now.
1428 +Version 1.9, 2001-02-13
1429 +- Fixed compilation problems for 2.2 and SMP kernels.
1430 +- Found updated documentation on "VIA Cyrix III". Apparently, there
1431 + are two distinct chips: the older Joshua (a Cyrix design) and the
1432 + newer Samuel (a Centaur design). Our current code supported Joshua,
1433 + but mistook Samuel for Joshua. Corrected the identification of Samuel
1434 + and added explicit support for it. Samuel's EVNTSEL1 is not well-
1435 + documented, so there are some new Samuel-specific tests in x86_tests.c.
1436 +- Added preliminary interrupt-mode support for AMD K7.
1437 +- Small tweaks to virtual.c's interrupt handling.
1439 +Version 1.8, 2001-01-23
1440 +- Added preliminary interrupt-mode support to virtual perfctrs.
1441 + Currently for P6 only, and the local APIC must have been enabled.
1442 + Tested on 2.4.0-ac10 with CONFIG_X86_UP_APIC=y.
1443 + When an i-mode vperfctr interrupts on overflow, the counters are
1444 + suspended and a user-specified signal is sent to the process. The
1445 + user's signal handler can read the trap pc from the mmap:ed vperfctr,
1446 + and should then issue an IRESUME ioctl to restart the counters.
1447 + The next version will support buffering and automatic restart.
1448 +- Some cleanups in the x86.c init and exit code. Removed the implicit
1449 + smp_call_function() calls from x86_compat.h.
1451 +Version 1.7, 2001-01-01
1452 +- Updated Makefile for 2.4.0-test13-pre3 Rules.make changes.
1453 +- Removed PERFCTR_ATTACH ioctl from /dev/perfctr, making the
1454 + vperfctrs only accessible via /proc/self/perfctr. Removed
1455 + the "attach" code from virtual.c, and temporarily commented
1456 + out the "vperfctr fs" code. Moved /dev/perfctr initialisation
1457 + and implementation from init.c to global.c.
1458 +- Eliminated CONFIG_VPERFCTR_PROC, making /proc/pid/perfctr
1459 + mandatory if CONFIG_PERFCTR_VIRTUAL is set.
1460 +- Some 2.2/2.4 compatibility cleanups.
1461 +- VIA Cyrix III detection bug fix. Contrary to VIA's documentation,
1462 + the Cyrix III vendor field is Centaur, not Cyrix.
1464 +Version 1.6, 2000-11-21
1465 +- Preliminary implementation of /proc/pid/perfctr. Seems to work,
1466 + but virtual.c and virtual_stub.c is again filled with
1467 + #if LINUX_VERSION_CODE crap which will need to be cleaned up.
1468 + The INFO ioctl is now implemented by vperfctrs too, to avoid the
1469 + need for opening /dev/perfctr.
1470 +- virtual.c now puts the perfctr pointer in filp->private_data
1471 + instead of inode->u.generic_ip. The main reason for this change
1472 + is that proc-fs places a dentry pointer in inode->u.generic_ip.
1473 +- sys_vperfctr_control() no longer resets the virtual TSC
1474 + if it already is active. The virtual TSC therefore runs
1475 + continuously from its first activation until the process
1476 + stops or unlinks its vperfctrs.
1477 +- Updates for 2.4.0-test11pre6. Use 2.4-style cpu_has_XXX
1478 + feature testing macros. Updated x86_compat.h to implement
1479 + missing cpu_has_mmx and cpu_has_msr, and compatibility
1480 + macros for 2.2. Changed vperfctr_fs_read_super() to use
1481 + new_inode(sb) instead of get_empty_inode() + some init code.
1482 +- Updates for 2.4.0-test9. Fixed x86_compat.h for cpu_khz change.
1483 + Since drivers/Makefile was converted to the new list style,
1484 + it became more difficult to handle CONFIG_PERFCTR=m. Changed
1485 + Config.in to set CONFIG_KPERFCTR=y when CONFIG_PERFCTR != n,
1486 + resulting in a much cleaner kernel patch for 2.4.0-test9.
1487 +- Removed d_alloc_root wrapper since 2.2 doesn't need it any more.
1488 +- When building for 2.2.18pre, use some of its 2.4 compatibility
1489 + features (module_init, module_exit and DECLARE_MUTEX).
1490 +- Updates for 2.4.0-test8: repaired kernel patch for new parameter
1491 + in do_fork, and fixed CLONE_PERFCTR conflict with CLONE_THREAD.
1493 +Version 1.5, 2000-09-03
1494 +- Dropped support for intermediate 2.3 and early 2.4.0-test kernels.
1495 + The code now supports kernels 2.2.xx and 2.4.0-test7 or later only.
1496 + Cleanups in compat.h and virtual.c.
1497 +- Rewrote the Makefile to use object file lists instead of conditionals.
1498 + This gets slightly hairy since kernel extensions are needed even
1499 + when the driver proper is built as a module.
1500 +- Removed the definition of CONFIG_PERFCTR_X86 from Config.in.
1501 + Use the 2.4 standard CONFIG_X86 instead. The 2.2.xx kernel
1502 + patches now define CONFIG_X86 in arch/i386/config.in.
1503 +- Cleaned up the vperfctr inheritance filter. Instead of setting
1504 + a disable flag (CLONE_KTHREAD) when kernel-internal threads are
1505 + created, I now set CLONE_PERFCTR in sys_fork and sys_vfork.
1506 +- /dev/perfctr no longer accepts the SAMPLE and UNLINK ioctls.
1507 + All operations pertaining to a process' virtual perfctrs must
1508 + be applied to the fd returned from the ATTACH ioctl.
1509 +- Removed the remote-control features from the virtual perfctrs.
1510 + Significant simplifications in virtual.c. Removed some now
1511 + unused stuff from compat.h and virtual_stub.c.
1513 +Version 1.4, 2000-08-11
1514 +- Fixed a memory leak bug in virtual.c. An extraneous dget() in
1515 + get_vperfctr_filp() prevented reclaiming the dentry and inode
1516 + allocated for a vperfctr file.
1517 +- Major changes to the VFS interface in virtual.c. Starting with
1518 + 2.4.0-test6, inode->i_sb == NULL no longer works. Added code to
1519 + register a "vperfctr" fs and define a superblock and a mount point.
1520 + Completely rewrote the dentry init code. Most of the new code is
1521 + adapted from fs/pipe.c, with simplifications and macros to continue
1522 + supporting 2.2.x kernels. `ls -l /proc/*/fd/' now prints recognizable
1523 + names for vperfctr files.
1524 +- Cleaned up virtual.c slightly. Removed "#if 1" tests around the
1525 + vperfctr inheritance code. Rewrote vperfctr_alloc and vperfctr_free
1526 + to use the virt_to_page and {Set,Clear}PageReserved macros;
1527 + also updated compat.h to provide these for older kernels.
1528 +- Updated for 2.4.0-test3: a dummy `open' file operation is no longer
1529 + required by drivers/char/misc.c.
1530 +- Updated for `owner' field in file_operations added in 2.4.0-test2.
1531 + Removed MOD_{INC,DEC}_USE_COUNT from init.c (except when compiling
1532 + for 2.2.x) and virtual.c. Added MOD_{INC,DEC}_USE_COUNT to the
1533 + reserve/release functions in x86.c -- needed because the driver
1534 + may be active even if no open file refers to it. Using can_unload
1535 + in the module struct instead is possible but not as tidy.
1537 +Version 1.3, 2000-06-29
1538 +- Implemented inheritance for virtual perfctrs: fork() copies the
1539 + evntsel data to the child, exit() stops the child's counters but
1540 + does not detach the vperfctr object, and wait() adds the child's
1541 + counters to the parent's `children' counters.
1542 + Added a CLONE_KTHREAD flag to prevent inheritance to threads
1543 + created implicitly by request_module() and kernel_thread().
1544 +- Fixed a half-broken printk() in x86_tests.c.
1545 +- Added checks to virtual.c to prevent the remote-control interface
1546 + from trying to activate dead vperfctrs.
1547 +- Updated vperfctr_attach() for changes in 2.3.99-pre7 and 2.4.0-test2.
1548 +- Fixed a problem introduced in 1.2 which caused linker errors if
1549 + CONFIG_PERFCTR=m and CONFIG_PERFCTR_INIT_TESTS=y.
1550 +- Export CPU kHz via a new field in PERFCTR_INFO ioctl, to enable
1551 + user-space to map accumulated TSC counts to actual time.
1553 +Version 1.2, 2000-05-24
1554 +- Added support for generic x86 processors with a time-stamp counter
1555 + but no performance-monitoring counters. By using the driver to
1556 + virtualise the TSC, accurate cycle-count measurements are now
1557 + possible on PMC-less processors like the AMD K6.
1558 +- Removed some of the special-casing of the x86 time-stamp counter.
1559 + It's now "just another counter", except that no evntsel is
1560 + needed to enable it.
1561 +- WinChip bug fix: the "fake TSC" code would increment an
1562 + uninitialised counter.
1563 +- Reorganised the x86 driver. Moved the optional init-time testing
1564 + code to a separate source file.
1565 +- Miscellaneous code cleanups and naming convention changes.
1567 +Version 1.1, 2000-05-13
1568 +- vperfctr_attach() now accepts pid 0 as an alias for the current
1569 + process. This reduces the number of getpid() calls needed in
1570 + the user-space library. (Suggested by Ulrich Drepper.)
1571 +- Added support for the VIA Cyrix III processor.
1572 +- Tuned the x86 driver interface. Replaced function pointers
1573 + with stubs which rewrite callers to invoke the correct callees.
1574 +- Added ARRAY_SIZE definition to compat.h for 2.2.x builds.
1575 +- Updated for 2.3.48 inode changes.
1576 +- Moved code closer to 2.3.x coding standards. Removed init_module
1577 + and cleanup_module, added __exit, module_init, and module_exit,
1578 + and extended "compat.h" accordingly. Cleaned up <linux/perfctr.h>
1579 + and <asm-i386/perfctr.h> a little.
1581 +Version 1.0, 2000-01-31
1582 +- Prepared the driver to cope with non-x86 architectures:
1583 + - Moved generic parts of <asm-i386/perfctr.h> to <linux/perfctr.h>.
1584 + - Merged driver's private "x86.h" into <asm-i386/perfctr.h>.
1585 + - Config.in now defines CONFIG_PERFCTR_${ARCH}, and Makefile uses
1586 + it to select appropriate arch-dependent object files
1587 +- The driver now reads the low 32 bits of the counters,
1588 + instead of 40 or 48 bits zero-extended to 64 bits.
1589 + Sums are still 64 bits. This was done to reduce the number
1590 + of cache lines needed for certain data structures, to
1591 + simplify and improve the performance of the sampling
1592 + procedures, and to change 64+(64-64) arithmetic to 64+(32-32)
1593 + for the benefit of gcc on x86. This change doesn't reduce
1594 + precision, as long as no event occurs more than 2^32 times
1595 + between two sampling points.
1596 +- PERFCTR_GLOBAL_READ now forces all CPUs to be sampled, if the
1597 + sampling timer isn't running.
1599 +Version 0.11, 2000-01-30
1600 +- Added a missing EXPORT_SYMBOL which prevented the driver
1601 + from being built as a module in SMP kernels.
1602 +- Support for the CPU sampling instructions (i.e. RDPMC and
1603 + RDTSC on x86) is now announced explicitly by PERFCTR_INFO.
1604 +- The x86 hardware driver now keeps CR4.PCE globally enabled.
1605 + There are two reasons for this. First, the cost of toggling
1606 + this flag at process suspend/resume is high. Second, changes
1607 + in kernel 2.3.40 imply that any processor's %cr4 may be updated
1608 + asynchronously from the global variable mmu_cr4_features.
1610 +Version 0.10, 2000-01-23
1611 +- Added support for global-mode perfctrs (global.c).
1612 +- There is now a config option controlling whether to
1613 + perform init-time hardware tests or not.
1614 +- Added a hardware reserve/release mechanism so that multiple
1615 + high-level services don't simultaneously use the hardware.
1616 +- The driver is now officially device <char,major 10,minor 182>.
1617 +- Tuned the 64-bit tsc/msr/pmc read operations in x86.c.
1618 +- Support for virtual perfctrs can now be enabled or disabled
1619 + via CONFIG_PERFCTR_VIRTUAL.
1620 +- Added support for the WinChip 3 processor.
1621 +- Split the code into several files: x86.c (x86 drivers),
1622 + virtual.c (virtualised perfctrs), setup.c (boot-time actions),
1623 + init.c (driver top-level and init code).
1625 +Version 0.9, 2000-01-02
1626 +- The driver can now be built as a module.
1627 +- Dropped sys_perfctr() system call and went back to using a
1628 + /dev/perfctr character device. Generic operations are now
1629 + ioctl commands on /dev/perfctr, and control operations on
1630 + virtual perfctrs are ioctl commands on their file descriptors.
1631 + Initially this change was done because new system calls in 2.3.x
1632 + made maintenance and binary compatibility with 2.2.x hard, but
1633 + the new API is actually cleaner than the previous system call.
1634 +- Moved this code from arch/i386/kernel/ to drivers/perfctr/.
1636 +Version 0.8, 1999-11-14
1637 +- Made the process management callback functions inline to
1638 + reduce scheduling overhead for processes not using perfctrs.
1639 +- Changed the 'status' field to contain the number of active
1640 + counters. Changed read_counters, write_control, and accumulate
1641 + to use this information to avoid unnecessary work.
1642 +- Fixed a bug in k7_check_control() which caused it to
1643 + require all four counters to be enabled.
1644 +- Fixed sys_perfctr() to return -ENODEV instead of -ENOSYS
1645 + if the processor doesn't support perfctrs.
1646 +- Some code cleanups.
1647 +- Evntsel MSRs are updated lazily, and counters are not written to.
1649 + The following table lists the costs (in cycles) of various
1650 + instructions which access the counter or evntsel registers.
1651 + The table was derived from data collected by init-time tests
1652 + run by previous versions of this driver.
1654 + Processor P5 P5MMX PII PIII K7
1655 + Clock freq. (MHz) 133 233 266 450 500
1657 + RDPMC n/a 14 31 36 13
1658 + RDMSR (counter) 29 28 81 80 52
1659 + WRMSR (counter) 35 37 97 115 80
1660 + WRMSR (evntsel) 33 37 88 105 232
1662 + Several things are apparent from this table:
1664 + 1. It's much cheaper to use RDPMC than RDMSR to read the counters.
1665 + 2. It's much more expensive to reset a counter than to read it.
1666 + 3. It's expensive to write to an evntsel register.
1668 + As of version 0.8, this driver uses the following strategies:
1669 + * The evntsel registers are updated lazily. A per_cpu_control[]
1670 + array caches the contents of each CPU's evntsel registers,
1671 + and only when a process requires a different setup are the
1672 + evntsel registers written to. In most cases, this eliminates the
1673 + need to reprogram the evntsel registers when switching processes.
1674 + The older drivers would write to the evntsel registers both at
1675 + process suspend and resume.
1676 + * The counter registers are read both at process resume and suspend,
1677 + and the difference is added to the process' accumulated counters.
1678 + The older drivers would reset the counters at resume, read them
1679 + at suspend, and add the values read to the accumulated counters.
1680 + * Only those registers enabled by the user's control information
1681 + are manipulated, instead of blindly manipulating all of them.
1683 +Version 0.7 1999-10-25
1684 +- The init-time checks in version 0.6 of this driver showed that
1685 + RDMSR is a lot slower than RDPMC for reading the PMCs. The driver
1686 + now uses RDPMC instead of RDMSR whenever possible.
1687 +- Added an mmap() operation to perfctr files. This allows any client
1688 + to read the accumulated counter state without making a system call.
1689 + The old "sync to user-provided buffer" method has been removed,
1690 + as it entailed additional copy operations and only worked for the
1691 + "active" process. The PERFCTR_READ operation has been replaced
1692 + by a simpler PERFCTR_SAMPLE operation, for the benefit of pre-MMX
1693 + Intel P5 processors which cannot sample counters in user-mode.
1694 + This rewrite actually simplified the code.
1695 +- The AMD K7 should now be supported correctly. The init-time checks
1696 + in version 0.6 of this driver revealed that each K7 counter has
1697 + its own ENable bit. (Thanks to Nathan Slingerland for running the
1698 + test and reporting the results to me.)
1699 +- Plugged a potential memory leak in perfctr_attach_task().
1700 +- No longer piggyback on prctl(); sys_perfctr() is a real system call.
1701 +- Some code cleanups.
1703 +Version 0.6 1999-09-08
1704 +- Temporarily added some init-time code that checks the
1705 + costs of RDPMC/RDMSR/WRMSR operations applied to perfctr MSRs,
1706 + the semantics of the ENable bit on the Athlon, and gets
1707 + the boot-time value of the WinChip CESR register.
1708 + This code can be turned off by #defining INIT_DEBUG to 0.
1709 +- Preliminary support for the AMD K7 Athlon processor.
1710 +- The code will now build in both 2.3.x and 2.2.x kernels.
1712 +Version 0.5 1999-08-29
1713 +- The user-space buffer is updated whenever state.status changes,
1714 + even when a remote command triggers the change.
1715 +- Reworked and simplified the high-level code. All accesses
1716 + now require an attached file in order to implement proper
1717 + accounting and syncronisation. The only exception is UNLINK:
1718 + a process may always UNLINK its own PMCs.
1719 +- Fixed counting bug in sys_perfctr_read().
1720 +- Improved support for the Intel Pentium III.
1721 +- Another WinChip fix: fake TSC update at process resume.
1722 +- The code should now be safe for 'gcc -fstrict-aliasing'.
1724 +Version 0.4 1999-07-31
1725 +- Implemented PERFCTR_ATTACH and PERFCTR_{READ,CONTROL,STOP,UNLINK}
1726 + on attached perfctrs. An attached perfctr is represented as a file.
1727 +- Fixed an error in the WinChip-specific code.
1728 +- Perfctrs now survive exec().
1730 +Version 0.3 1999-07-22
1731 +- Interface now via sys_prctl() instead of /dev/perfctr.
1732 +- Added NYI stubs for accessing other processes' perfctrs.
1733 +- Moved to dynamic allocation of a task's perfctr state.
1734 +- Minor code cleanups.
1736 +Version 0.2 1999-06-07
1737 +- Added support for WinChip CPUs.
1738 +- Restart counters from zero, not their previous values. This
1739 + corrected a problem for Intel P6 (WRMSR writes 32 bits to a PERFCTR
1740 + MSR and then sign-extends to 40 bits), and also simplified the code.
1741 +- Added support for syncing the kernel's counter values to a user-
1742 + provided buffer each time a process is resumed. This feature, and
1743 + the fact that the driver enables RDPMC in processes using PMCs,
1744 + allows user-level computation of a process' accumulated counter
1745 + values without incurring the overhead of making a system call.
1747 +Version 0.1 1999-05-30
1748 +- First public release.
1749 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/compat24.h
1750 ===================================================================
1751 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/compat24.h 1969-12-31 19:00:00.000000000 -0500
1752 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/compat24.h 2004-11-18 20:59:11.000000000 -0500
1754 +/* $Id: compat24.h,v 1.22.2.1 2004/07/26 14:05:49 mikpe Exp $
1755 + * Performance-monitoring counters driver.
1756 + * Compatibility definitions for 2.4 kernels.
1758 + * Copyright (C) 1999-2004 Mikael Pettersson
1760 +#include <linux/mm.h> /* for remap_page_range() [redefined here] */
1762 +#include "cpumask.h"
1764 +/* 2.4.18-redhat had BUG_ON() before 2.4.19 */
1765 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19) && !defined(BUG_ON)
1766 +#define BUG_ON(condition) do { if ((condition) != 0) BUG(); } while(0)
1769 +/* 2.4.18-redhat had set_cpus_allowed() before 2.4.21-pre5 */
1770 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,21) && !defined(HAVE_SET_CPUS_ALLOWED)
1771 +#if defined(CONFIG_SMP)
1772 +extern void set_cpus_allowed(struct task_struct*, unsigned long);
1774 +#define set_cpus_allowed(tsk, mask) do{}while(0)
1778 +/* 2.4.20-8-redhat added cpu_online() */
1779 +#if !defined(cpu_online)
1780 +#define cpu_online(cpu) (cpu_online_map & (1UL << (cpu)))
1783 +/* 2.4.20-8-redhat added put_task_struct() */
1784 +#if defined(put_task_struct) /* RH 2.4.20-8 */
1785 +#define EXPORT_SYMBOL___put_task_struct EXPORT_SYMBOL(__put_task_struct)
1786 +#else /* standard 2.4 */
1787 +#define put_task_struct(tsk) free_task_struct((tsk))
1788 +#define EXPORT_SYMBOL___put_task_struct /*empty*/
1791 +/* remap_page_range() changed in 2.5.3-pre1 and 2.4.20-8-redhat */
1792 +#if !defined(HAVE_5ARG_REMAP_PAGE_RANGE)
1793 +static inline int perfctr_remap_page_range(struct vm_area_struct *vma, unsigned long from, unsigned long to, unsigned long size, pgprot_t prot)
1795 + return remap_page_range(from, to, size, prot);
1797 +#undef remap_page_range
1798 +#define remap_page_range(vma,from,to,size,prot) perfctr_remap_page_range((vma),(from),(to),(size),(prot))
1801 +/* 2.4.22-rc1 added EXPORT_SYMBOL(mmu_cr4_features) */
1802 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22) || defined(HAVE_EXPORT_mmu_cr4_features)
1803 +#define EXPORT_SYMBOL_mmu_cr4_features /*empty*/
1805 +#define EXPORT_SYMBOL_mmu_cr4_features EXPORT_SYMBOL(mmu_cr4_features)
1808 +/* not in 2.4 proper, but some people use 2.4 with preemption patches */
1809 +#ifdef CONFIG_PREEMPT
1810 +#error "not yet ported to 2.4+PREEMPT"
1812 +#ifndef preempt_disable
1813 +#define preempt_disable() do{}while(0)
1814 +#define preempt_enable() do{}while(0)
1818 +#define __module_get(module) do { if ((module)) __MOD_INC_USE_COUNT((module)); } while(0)
1819 +#define module_put(module) do { if ((module)) __MOD_DEC_USE_COUNT((module)); } while(0)
1821 +#define __module_get(module) do{}while(0)
1822 +#define module_put(module) do{}while(0)
1825 +#define MODULE_ALIAS(alias) /*empty*/
1827 +/* introduced in 2.5.64; backported to 2.4.22-1.2115.nptl (FC1) */
1829 +perfctr_on_each_cpu(void (*func) (void *info), void *info,
1830 + int retry, int wait)
1834 + preempt_disable();
1835 + ret = smp_call_function(func, info, retry, wait);
1841 +#define on_each_cpu(f,i,r,w) perfctr_on_each_cpu((f),(i),(r),(w))
1843 +/* 2.6.4 added 'noinline' */
1844 +#if !defined(noinline)
1845 +#if __GNUC__ == 3 && __GNUC_MINOR__ >= 1
1846 +#define noinline __attribute__((noinline))
1848 +#define noinline /* unimplemented */
1851 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/init.c
1852 ===================================================================
1853 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/init.c 1969-12-31 19:00:00.000000000 -0500
1854 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/init.c 2004-11-18 20:59:11.000000000 -0500
1856 +/* $Id: init.c,v 1.68 2004/01/11 22:12:09 mikpe Exp $
1857 + * Performance-monitoring counters driver.
1858 + * Top-level initialisation code.
1860 + * Copyright (C) 1999-2004 Mikael Pettersson
1862 +#include <linux/config.h>
1863 +#include <linux/module.h>
1864 +#include <linux/fs.h>
1865 +#include <linux/init.h>
1866 +#include <linux/miscdevice.h>
1867 +#include <linux/sched.h>
1868 +#include <linux/perfctr.h>
1870 +#include <asm/uaccess.h>
1872 +#include "compat.h"
1873 +#include "virtual.h"
1874 +#include "global.h"
1875 +#include "version.h"
1876 +#include "marshal.h"
1878 +MODULE_AUTHOR("Mikael Pettersson <mikpe@csd.uu.se>");
1879 +MODULE_DESCRIPTION("Performance-monitoring counters driver");
1880 +MODULE_LICENSE("GPL");
1881 +MODULE_ALIAS("char-major-10-182");
1882 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,63)
1886 +#ifdef CONFIG_PERFCTR_DEBUG
1887 +#define VERSION_DEBUG " DEBUG"
1889 +#define VERSION_DEBUG
1892 +struct perfctr_info perfctr_info = {
1893 + .abi_version = PERFCTR_ABI_VERSION,
1894 + .driver_version = VERSION VERSION_DEBUG,
1897 +char *perfctr_cpu_name __initdata;
1899 +int sys_perfctr_abi(unsigned int *argp)
1901 + if( put_user(PERFCTR_ABI_VERSION, argp) )
1906 +int sys_perfctr_info(struct perfctr_struct_buf *argp)
1908 + return perfctr_copy_to_user(argp, &perfctr_info, &perfctr_info_sdesc);
1911 +static int cpus_copy_to_user(const cpumask_t *cpus, struct perfctr_cpu_mask *argp)
1913 + const unsigned int k_nrwords = PERFCTR_CPUMASK_NRLONGS*(sizeof(long)/sizeof(int));
1914 + unsigned int u_nrwords;
1915 + unsigned int ui, ki, j;
1917 + if( get_user(u_nrwords, &argp->nrwords) )
1919 + if( put_user(k_nrwords, &argp->nrwords) )
1921 + if( u_nrwords < k_nrwords )
1922 + return -EOVERFLOW;
1923 + for(ui = 0, ki = 0; ki < PERFCTR_CPUMASK_NRLONGS; ++ki) {
1924 + unsigned long mask = cpus_addr(*cpus)[ki];
1925 + for(j = 0; j < sizeof(long)/sizeof(int); ++j) {
1926 + if( put_user((unsigned int)mask, &argp->mask[ui]) )
1929 + mask = (mask >> (8*sizeof(int)-1)) >> 1;
1935 +int sys_perfctr_cpus(struct perfctr_cpu_mask *argp)
1937 + cpumask_t cpus = cpu_online_map;
1938 + return cpus_copy_to_user(&cpus, argp);
1941 +int sys_perfctr_cpus_forbidden(struct perfctr_cpu_mask *argp)
1943 + cpumask_t cpus = perfctr_cpus_forbidden_mask;
1944 + return cpus_copy_to_user(&cpus, argp);
1947 +#ifdef CONFIG_IA32_EMULATION
1948 +#include <asm/ioctl32.h>
1949 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23)
1950 +static int perfctr_ioctl32_handler(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *filp)
1952 + /* filp->f_op->ioctl is known to exist; see sys32_ioctl() */
1953 + return filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
1956 +#define perfctr_ioctl32_handler 0
1959 +static void __init perfctr_register_ioctl32_conversions(void)
1963 + err = register_ioctl32_conversion(PERFCTR_ABI, perfctr_ioctl32_handler);
1964 + err |= register_ioctl32_conversion(PERFCTR_INFO, perfctr_ioctl32_handler);
1965 + err |= register_ioctl32_conversion(PERFCTR_CPUS, perfctr_ioctl32_handler);
1966 + err |= register_ioctl32_conversion(PERFCTR_CPUS_FORBIDDEN, perfctr_ioctl32_handler);
1967 + err |= register_ioctl32_conversion(VPERFCTR_CREAT, perfctr_ioctl32_handler);
1968 + err |= register_ioctl32_conversion(VPERFCTR_OPEN, perfctr_ioctl32_handler);
1969 + err |= register_ioctl32_conversion(VPERFCTR_READ_SUM, perfctr_ioctl32_handler);
1970 + err |= register_ioctl32_conversion(VPERFCTR_UNLINK, perfctr_ioctl32_handler);
1971 + err |= register_ioctl32_conversion(VPERFCTR_CONTROL, perfctr_ioctl32_handler);
1972 + err |= register_ioctl32_conversion(VPERFCTR_IRESUME, perfctr_ioctl32_handler);
1973 + err |= register_ioctl32_conversion(VPERFCTR_READ_CONTROL, perfctr_ioctl32_handler);
1974 + err |= register_ioctl32_conversion(GPERFCTR_CONTROL, perfctr_ioctl32_handler);
1975 + err |= register_ioctl32_conversion(GPERFCTR_READ, perfctr_ioctl32_handler);
1976 + err |= register_ioctl32_conversion(GPERFCTR_STOP, perfctr_ioctl32_handler);
1977 + err |= register_ioctl32_conversion(GPERFCTR_START, perfctr_ioctl32_handler);
1979 + printk(KERN_ERR "perfctr: register_ioctl32_conversion() failed\n");
1982 +static void __exit perfctr_unregister_ioctl32_conversions(void)
1984 + unregister_ioctl32_conversion(PERFCTR_ABI);
1985 + unregister_ioctl32_conversion(PERFCTR_INFO);
1986 + unregister_ioctl32_conversion(PERFCTR_CPUS);
1987 + unregister_ioctl32_conversion(PERFCTR_CPUS_FORBIDDEN);
1988 + unregister_ioctl32_conversion(VPERFCTR_CREAT);
1989 + unregister_ioctl32_conversion(VPERFCTR_OPEN);
1990 + unregister_ioctl32_conversion(VPERFCTR_READ_SUM);
1991 + unregister_ioctl32_conversion(VPERFCTR_UNLINK);
1992 + unregister_ioctl32_conversion(VPERFCTR_CONTROL);
1993 + unregister_ioctl32_conversion(VPERFCTR_IRESUME);
1994 + unregister_ioctl32_conversion(VPERFCTR_READ_CONTROL);
1995 + unregister_ioctl32_conversion(GPERFCTR_CONTROL);
1996 + unregister_ioctl32_conversion(GPERFCTR_READ);
1997 + unregister_ioctl32_conversion(GPERFCTR_STOP);
1998 + unregister_ioctl32_conversion(GPERFCTR_START);
2002 +#define perfctr_register_ioctl32_conversions() do{}while(0)
2003 +#define perfctr_unregister_ioctl32_conversions() do{}while(0)
2006 +static int dev_perfctr_ioctl(struct inode *inode, struct file *filp,
2007 + unsigned int cmd, unsigned long arg)
2011 + return sys_perfctr_abi((unsigned int*)arg);
2012 + case PERFCTR_INFO:
2013 + return sys_perfctr_info((struct perfctr_struct_buf*)arg);
2014 + case PERFCTR_CPUS:
2015 + return sys_perfctr_cpus((struct perfctr_cpu_mask*)arg);
2016 + case PERFCTR_CPUS_FORBIDDEN:
2017 + return sys_perfctr_cpus_forbidden((struct perfctr_cpu_mask*)arg);
2018 + case VPERFCTR_CREAT:
2019 + return vperfctr_attach((int)arg, 1);
2020 + case VPERFCTR_OPEN:
2021 + return vperfctr_attach((int)arg, 0);
2023 + return gperfctr_ioctl(inode, filp, cmd, arg);
2028 +static struct file_operations dev_perfctr_file_ops = {
2029 + .owner = THIS_MODULE,
2030 + .ioctl = dev_perfctr_ioctl,
2033 +static struct miscdevice dev_perfctr = {
2035 + .name = "perfctr",
2036 + .fops = &dev_perfctr_file_ops,
2039 +int __init perfctr_init(void)
2042 + if( (err = perfctr_cpu_init()) != 0 ) {
2043 + printk(KERN_INFO "perfctr: not supported by this processor\n");
2046 + if( (err = vperfctr_init()) != 0 )
2049 + if( (err = misc_register(&dev_perfctr)) != 0 ) {
2050 + printk(KERN_ERR "/dev/perfctr: failed to register, errno %d\n",
2054 + perfctr_register_ioctl32_conversions();
2055 + printk(KERN_INFO "perfctr: driver %s, cpu type %s at %u kHz\n",
2056 + perfctr_info.driver_version,
2058 + perfctr_info.cpu_khz);
2062 +void __exit perfctr_exit(void)
2064 + perfctr_unregister_ioctl32_conversions();
2065 + misc_deregister(&dev_perfctr);
2067 + perfctr_cpu_exit();
2070 +module_init(perfctr_init)
2071 +module_exit(perfctr_exit)
2072 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/virtual.h
2073 ===================================================================
2074 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/virtual.h 1969-12-31 19:00:00.000000000 -0500
2075 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/virtual.h 2004-11-18 20:59:11.000000000 -0500
2077 +/* $Id: virtual.h,v 1.11 2003/10/04 20:29:43 mikpe Exp $
2078 + * Virtual per-process performance counters.
2080 + * Copyright (C) 1999-2003 Mikael Pettersson
2083 +#ifdef CONFIG_PERFCTR_VIRTUAL
2084 +extern int vperfctr_attach(int, int);
2085 +extern int vperfctr_init(void);
2086 +extern void vperfctr_exit(void);
2088 +static inline int vperfctr_attach(int tid, int creat) { return -EINVAL; }
2089 +static inline int vperfctr_init(void) { return 0; }
2090 +static inline void vperfctr_exit(void) { }
2092 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/marshal.c
2093 ===================================================================
2094 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/marshal.c 1969-12-31 19:00:00.000000000 -0500
2095 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/marshal.c 2004-11-18 20:59:11.000000000 -0500
2097 +/* $Id: marshal.c,v 1.6.2.1 2004/08/02 22:24:58 mikpe Exp $
2098 + * Performance-monitoring counters driver.
2099 + * Structure marshalling support.
2101 + * Copyright (C) 2003-2004 Mikael Pettersson
2104 +#include <linux/config.h>
2106 +#include <linux/sched.h>
2107 +#include <linux/perfctr.h>
2108 +#include <linux/errno.h>
2109 +#include <linux/stddef.h>
2110 +#include <linux/string.h>
2111 +#include <asm/uaccess.h>
2112 +#else /* !__KERNEL__ */
2113 +#define CONFIG_KPERFCTR
2114 +#include <linux/perfctr.h>
2115 +#include <sys/ioctl.h>
2117 +#include <stddef.h>
2118 +#include <string.h>
2119 +#define put_user(w, p) (*(p) = (w), 0)
2120 +#define get_user(w, p) ((w) = *(p), 0)
2121 +#endif /* !__KERNEL__ */
2123 +#include "marshal.h"
2125 +/****************************************************************
2127 + * Struct encoding support. *
2129 + ****************************************************************/
2131 +static void stream_write(struct perfctr_marshal_stream *stream, unsigned int word)
2133 + if( !stream->error ) {
2134 + if( stream->pos >= stream->size )
2135 + stream->error = -EOVERFLOW;
2136 + else if( put_user(word, &stream->buffer[stream->pos]) )
2137 + stream->error = -EFAULT;
2142 +static void encode_field(const void *address,
2143 + const struct perfctr_field_desc *field,
2144 + struct perfctr_marshal_stream *stream)
2146 + unsigned int base_type = PERFCTR_TYPE_BASE(field->type);
2147 + unsigned int nr_items = PERFCTR_TYPE_NRITEMS(field->type);
2148 + unsigned int tag = field->tag;
2149 + const char *pointer = (const char*)address + field->offset;
2150 + unsigned int uint32_val;
2152 + unsigned long long ull;
2153 + unsigned int ui[2];
2155 + unsigned int i = 0;
2158 + if( base_type == PERFCTR_TYPE_UINT64 ) {
2159 + uint64_val.ull = *(unsigned long long*)pointer;
2160 + pointer += sizeof(long long);
2161 + if( !uint64_val.ull )
2163 + stream_write(stream, PERFCTR_HEADER(PERFCTR_HEADER_UINT64, tag, i));
2164 + stream_write(stream, uint64_val.ui[0]);
2165 + stream_write(stream, uint64_val.ui[1]);
2166 + } else { /* PERFCTR_TYPE_BYTES4 */
2167 + memcpy(&uint32_val, pointer, sizeof(int));
2168 + pointer += sizeof(int);
2171 + stream_write(stream, PERFCTR_HEADER(PERFCTR_HEADER_UINT32, tag, i));
2172 + stream_write(stream, uint32_val);
2174 + } while( ++i < nr_items );
2177 +void perfctr_encode_struct(const void *address,
2178 + const struct perfctr_struct_desc *sdesc,
2179 + struct perfctr_marshal_stream *stream)
2183 + for(i = 0; i < sdesc->nrfields; ++i)
2184 + encode_field(address, &sdesc->fields[i], stream);
2185 + for(i = 0; i < sdesc->nrsubs; ++i) {
2186 + const struct perfctr_sub_struct_desc *sub = &sdesc->subs[i];
2187 + perfctr_encode_struct((char*)address + sub->offset, sub->sdesc, stream);
2191 +/****************************************************************
2193 + * Struct decoding support. *
2195 + ****************************************************************/
2197 +static int stream_read(struct perfctr_marshal_stream *stream, unsigned int *word)
2199 + if( stream->pos >= stream->size )
2201 + if( get_user(*word, &stream->buffer[stream->pos]) )
2207 +static const struct perfctr_field_desc*
2208 +find_field(unsigned int *struct_offset,
2209 + const struct perfctr_struct_desc *sdesc,
2212 + unsigned int low, high, mid, i;
2213 + const struct perfctr_field_desc *field;
2214 + const struct perfctr_sub_struct_desc *sub;
2217 + high = sdesc->nrfields; /* [low,high[ */
2218 + while( low < high ) {
2219 + mid = (low + high) / 2;
2220 + field = &sdesc->fields[mid];
2221 + if( field->tag == tag )
2223 + if( field->tag < tag )
2228 + for(i = 0; i < sdesc->nrsubs; ++i) {
2229 + sub = &sdesc->subs[i];
2230 + field = find_field(struct_offset, sub->sdesc, tag);
2232 + *struct_offset += sub->offset;
2239 +int perfctr_decode_struct(void *address,
2240 + const struct perfctr_struct_desc *sdesc,
2241 + struct perfctr_marshal_stream *stream)
2243 + unsigned int header;
2245 + const struct perfctr_field_desc *field;
2246 + unsigned int struct_offset;
2248 + unsigned long long ull;
2249 + unsigned int ui[2];
2252 + unsigned int itemnr;
2255 + err = stream_read(stream, &header);
2258 + struct_offset = 0;
2259 + field = find_field(&struct_offset, sdesc, PERFCTR_HEADER_TAG(header));
2262 + /* a 64-bit datum must have a 64-bit target field */
2263 + if( PERFCTR_HEADER_TYPE(header) != PERFCTR_HEADER_UINT32 &&
2264 + PERFCTR_TYPE_BASE(field->type) != PERFCTR_TYPE_UINT64 )
2266 + err = stream_read(stream, &val.ui[0]);
2269 + target = (char*)address + struct_offset + field->offset;
2270 + itemnr = PERFCTR_HEADER_ITEMNR(header);
2271 + if( itemnr >= PERFCTR_TYPE_NRITEMS(field->type) )
2273 + if( PERFCTR_TYPE_BASE(field->type) == PERFCTR_TYPE_UINT64 ) {
2274 + /* a 64-bit field must have a 64-bit datum */
2275 + if( PERFCTR_HEADER_TYPE(header) == PERFCTR_HEADER_UINT32 )
2277 + err = stream_read(stream, &val.ui[1]);
2280 + ((unsigned long long*)target)[itemnr] = val.ull;
2282 + memcpy(&((unsigned int*)target)[itemnr], &val.ui[0], sizeof(int));
2284 + err_err: /* err ? err : -EPROTO */
2287 + err_eproto: /* saves object code over inlining it */
2291 +/****************************************************************
2293 + * Structure descriptors. *
2295 + ****************************************************************/
2297 +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
2298 +#define STRUCT_ARRAY_SIZE(TYPE, MEMBER) ARRAY_SIZE(((TYPE*)0)->MEMBER)
2300 +#if defined(__i386__) || defined(__x86_64__)
2302 +#define PERFCTR_TAG_CPU_CONTROL_TSC_ON 32
2303 +#define PERFCTR_TAG_CPU_CONTROL_NRACTRS 33
2304 +#define PERFCTR_TAG_CPU_CONTROL_NRICTRS 34
2305 +#define PERFCTR_TAG_CPU_CONTROL_PMC_MAP 35
2306 +#define PERFCTR_TAG_CPU_CONTROL_EVNTSEL 36
2307 +#define PERFCTR_TAG_CPU_CONTROL_IRESET 37
2308 +#define PERFCTR_TAG_CPU_CONTROL_P4_ESCR 38
2309 +#define PERFCTR_TAG_CPU_CONTROL_P4_PE 39
2310 +#define PERFCTR_TAG_CPU_CONTROL_P4_PMV 40
2311 +#define PERFCTR_TAG_CPU_CONTROL_RSVD1 41
2312 +#define PERFCTR_TAG_CPU_CONTROL_RSVD2 42
2313 +#define PERFCTR_TAG_CPU_CONTROL_RSVD3 43
2314 +#define PERFCTR_TAG_CPU_CONTROL_RSVD4 44
2315 +#define PERFCTR_CPU_CONTROL_NRFIELDS_0 (7 + STRUCT_ARRAY_SIZE(struct perfctr_cpu_control, pmc_map) + STRUCT_ARRAY_SIZE(struct perfctr_cpu_control, evntsel) + STRUCT_ARRAY_SIZE(struct perfctr_cpu_control, ireset))
2316 +#define PERFCTR_CPU_CONTROL_NRFIELDS_1 (2 + STRUCT_ARRAY_SIZE(struct perfctr_cpu_control, p4.escr))
2317 +#define PERFCTR_CPU_CONTROL_NRFIELDS (PERFCTR_CPU_CONTROL_NRFIELDS_0 + PERFCTR_CPU_CONTROL_NRFIELDS_1)
2319 +#define PERFCTR_TAG_SUM_CTRS_TSC 48
2320 +#define PERFCTR_TAG_SUM_CTRS_PMC 49
2321 +#define PERFCTR_SUM_CTRS_NRFIELDS (1 + STRUCT_ARRAY_SIZE(struct perfctr_sum_ctrs, pmc))
2323 +static const struct perfctr_field_desc perfctr_sum_ctrs_fields[] = {
2324 + { .offset = offsetof(struct perfctr_sum_ctrs, tsc),
2325 + .tag = PERFCTR_TAG_SUM_CTRS_TSC,
2326 + .type = PERFCTR_TYPE_UINT64 },
2327 + { .offset = offsetof(struct perfctr_sum_ctrs, pmc),
2328 + .tag = PERFCTR_TAG_SUM_CTRS_PMC,
2329 + .type = PERFCTR_TYPE_ARRAY(STRUCT_ARRAY_SIZE(struct perfctr_sum_ctrs,pmc),
2330 + PERFCTR_TYPE_UINT64) },
2333 +const struct perfctr_struct_desc perfctr_sum_ctrs_sdesc = {
2334 + .total_sizeof = sizeof(struct perfctr_sum_ctrs),
2335 + .total_nrfields = PERFCTR_SUM_CTRS_NRFIELDS,
2336 + .nrfields = ARRAY_SIZE(perfctr_sum_ctrs_fields),
2337 + .fields = perfctr_sum_ctrs_fields,
2340 +static const struct perfctr_field_desc perfctr_cpu_control_fields[] = {
2341 + { .offset = offsetof(struct perfctr_cpu_control, tsc_on),
2342 + .tag = PERFCTR_TAG_CPU_CONTROL_TSC_ON,
2343 + .type = PERFCTR_TYPE_BYTES4 },
2344 + { .offset = offsetof(struct perfctr_cpu_control, nractrs),
2345 + .tag = PERFCTR_TAG_CPU_CONTROL_NRACTRS,
2346 + .type = PERFCTR_TYPE_BYTES4 },
2347 + { .offset = offsetof(struct perfctr_cpu_control, nrictrs),
2348 + .tag = PERFCTR_TAG_CPU_CONTROL_NRICTRS,
2349 + .type = PERFCTR_TYPE_BYTES4 },
2350 + { .offset = offsetof(struct perfctr_cpu_control, pmc_map),
2351 + .tag = PERFCTR_TAG_CPU_CONTROL_PMC_MAP,
2352 + .type = PERFCTR_TYPE_ARRAY(STRUCT_ARRAY_SIZE(struct perfctr_cpu_control,pmc_map),
2353 + PERFCTR_TYPE_BYTES4) },
2354 + { .offset = offsetof(struct perfctr_cpu_control, evntsel),
2355 + .tag = PERFCTR_TAG_CPU_CONTROL_EVNTSEL,
2356 + .type = PERFCTR_TYPE_ARRAY(STRUCT_ARRAY_SIZE(struct perfctr_cpu_control,evntsel),
2357 + PERFCTR_TYPE_BYTES4) },
2358 + { .offset = offsetof(struct perfctr_cpu_control, ireset),
2359 + .tag = PERFCTR_TAG_CPU_CONTROL_IRESET,
2360 + .type = PERFCTR_TYPE_ARRAY(STRUCT_ARRAY_SIZE(struct perfctr_cpu_control,ireset),
2361 + PERFCTR_TYPE_BYTES4) },
2362 + { .offset = offsetof(struct perfctr_cpu_control, p4.escr),
2363 + .tag = PERFCTR_TAG_CPU_CONTROL_P4_ESCR,
2364 + .type = PERFCTR_TYPE_ARRAY(STRUCT_ARRAY_SIZE(struct perfctr_cpu_control,p4.escr),
2365 + PERFCTR_TYPE_BYTES4) },
2366 + { .offset = offsetof(struct perfctr_cpu_control, p4.pebs_enable),
2367 + .tag = PERFCTR_TAG_CPU_CONTROL_P4_PE,
2368 + .type = PERFCTR_TYPE_BYTES4 },
2369 + { .offset = offsetof(struct perfctr_cpu_control, p4.pebs_matrix_vert),
2370 + .tag = PERFCTR_TAG_CPU_CONTROL_P4_PMV,
2371 + .type = PERFCTR_TYPE_BYTES4 },
2372 + { .offset = offsetof(struct perfctr_cpu_control, _reserved1),
2373 + .tag = PERFCTR_TAG_CPU_CONTROL_RSVD1,
2374 + .type = PERFCTR_TYPE_BYTES4 },
2375 + { .offset = offsetof(struct perfctr_cpu_control, _reserved2),
2376 + .tag = PERFCTR_TAG_CPU_CONTROL_RSVD2,
2377 + .type = PERFCTR_TYPE_BYTES4 },
2378 + { .offset = offsetof(struct perfctr_cpu_control, _reserved3),
2379 + .tag = PERFCTR_TAG_CPU_CONTROL_RSVD3,
2380 + .type = PERFCTR_TYPE_BYTES4 },
2381 + { .offset = offsetof(struct perfctr_cpu_control, _reserved4),
2382 + .tag = PERFCTR_TAG_CPU_CONTROL_RSVD4,
2383 + .type = PERFCTR_TYPE_BYTES4 },
2386 +const struct perfctr_struct_desc perfctr_cpu_control_sdesc = {
2387 + .total_sizeof = sizeof(struct perfctr_cpu_control),
2388 + .total_nrfields = PERFCTR_CPU_CONTROL_NRFIELDS,
2389 + .nrfields = ARRAY_SIZE(perfctr_cpu_control_fields),
2390 + .fields = perfctr_cpu_control_fields,
2393 +#endif /* __i386__ || __x86_64__ */
2395 +#if defined(__powerpc__) /* XXX: can be merged with x86/amd64 */
2397 +#define PERFCTR_TAG_CPU_CONTROL_TSC_ON 32
2398 +#define PERFCTR_TAG_CPU_CONTROL_NRACTRS 33
2399 +#define PERFCTR_TAG_CPU_CONTROL_NRICTRS 34
2400 +#define PERFCTR_TAG_CPU_CONTROL_PMC_MAP 35
2401 +#define PERFCTR_TAG_CPU_CONTROL_EVNTSEL 36
2402 +#define PERFCTR_TAG_CPU_CONTROL_IRESET 37
2403 +#define PERFCTR_TAG_CPU_CONTROL_PPC_MMCR0 38
2404 +#define PERFCTR_TAG_CPU_CONTROL_PPC_MMCR2 39
2406 +#define PERFCTR_TAG_CPU_CONTROL_RSVD1 41
2407 +#define PERFCTR_TAG_CPU_CONTROL_RSVD2 42
2408 +#define PERFCTR_TAG_CPU_CONTROL_RSVD3 43
2409 +#define PERFCTR_TAG_CPU_CONTROL_RSVD4 44
2410 +#define PERFCTR_CPU_CONTROL_NRFIELDS_0 (7 + STRUCT_ARRAY_SIZE(struct perfctr_cpu_control, pmc_map) + STRUCT_ARRAY_SIZE(struct perfctr_cpu_control, evntsel) + STRUCT_ARRAY_SIZE(struct perfctr_cpu_control, ireset))
2412 +#define PERFCTR_CPU_CONTROL_NRFIELDS_1 2
2414 +#define PERFCTR_CPU_CONTROL_NRFIELDS (PERFCTR_CPU_CONTROL_NRFIELDS_0 + PERFCTR_CPU_CONTROL_NRFIELDS_1)
2416 +#define PERFCTR_TAG_SUM_CTRS_TSC 48
2417 +#define PERFCTR_TAG_SUM_CTRS_PMC 49
2418 +#define PERFCTR_SUM_CTRS_NRFIELDS (1 + STRUCT_ARRAY_SIZE(struct perfctr_sum_ctrs, pmc))
2420 +static const struct perfctr_field_desc perfctr_sum_ctrs_fields[] = {
2421 + { .offset = offsetof(struct perfctr_sum_ctrs, tsc),
2422 + .tag = PERFCTR_TAG_SUM_CTRS_TSC,
2423 + .type = PERFCTR_TYPE_UINT64 },
2424 + { .offset = offsetof(struct perfctr_sum_ctrs, pmc),
2425 + .tag = PERFCTR_TAG_SUM_CTRS_PMC,
2426 + .type = PERFCTR_TYPE_ARRAY(STRUCT_ARRAY_SIZE(struct perfctr_sum_ctrs,pmc),
2427 + PERFCTR_TYPE_UINT64) },
2430 +const struct perfctr_struct_desc perfctr_sum_ctrs_sdesc = {
2431 + .total_sizeof = sizeof(struct perfctr_sum_ctrs),
2432 + .total_nrfields = PERFCTR_SUM_CTRS_NRFIELDS,
2433 + .nrfields = ARRAY_SIZE(perfctr_sum_ctrs_fields),
2434 + .fields = perfctr_sum_ctrs_fields,
2437 +static const struct perfctr_field_desc perfctr_cpu_control_fields[] = {
2438 + { .offset = offsetof(struct perfctr_cpu_control, tsc_on),
2439 + .tag = PERFCTR_TAG_CPU_CONTROL_TSC_ON,
2440 + .type = PERFCTR_TYPE_BYTES4 },
2441 + { .offset = offsetof(struct perfctr_cpu_control, nractrs),
2442 + .tag = PERFCTR_TAG_CPU_CONTROL_NRACTRS,
2443 + .type = PERFCTR_TYPE_BYTES4 },
2444 + { .offset = offsetof(struct perfctr_cpu_control, nrictrs),
2445 + .tag = PERFCTR_TAG_CPU_CONTROL_NRICTRS,
2446 + .type = PERFCTR_TYPE_BYTES4 },
2447 + { .offset = offsetof(struct perfctr_cpu_control, pmc_map),
2448 + .tag = PERFCTR_TAG_CPU_CONTROL_PMC_MAP,
2449 + .type = PERFCTR_TYPE_ARRAY(STRUCT_ARRAY_SIZE(struct perfctr_cpu_control,pmc_map),
2450 + PERFCTR_TYPE_BYTES4) },
2451 + { .offset = offsetof(struct perfctr_cpu_control, evntsel),
2452 + .tag = PERFCTR_TAG_CPU_CONTROL_EVNTSEL,
2453 + .type = PERFCTR_TYPE_ARRAY(STRUCT_ARRAY_SIZE(struct perfctr_cpu_control,evntsel),
2454 + PERFCTR_TYPE_BYTES4) },
2455 + { .offset = offsetof(struct perfctr_cpu_control, ireset),
2456 + .tag = PERFCTR_TAG_CPU_CONTROL_IRESET,
2457 + .type = PERFCTR_TYPE_ARRAY(STRUCT_ARRAY_SIZE(struct perfctr_cpu_control,ireset),
2458 + PERFCTR_TYPE_BYTES4) },
2460 + { .offset = offsetof(struct perfctr_cpu_control, ppc.mmcr0),
2461 + .tag = PERFCTR_TAG_CPU_CONTROL_PPC_MMCR0,
2462 + .type = PERFCTR_TYPE_BYTES4 },
2463 + { .offset = offsetof(struct perfctr_cpu_control, ppc.mmcr2),
2464 + .tag = PERFCTR_TAG_CPU_CONTROL_PPC_MMCR2,
2465 + .type = PERFCTR_TYPE_BYTES4 },
2466 +#endif /* __powerpc__ */
2467 + { .offset = offsetof(struct perfctr_cpu_control, _reserved1),
2468 + .tag = PERFCTR_TAG_CPU_CONTROL_RSVD1,
2469 + .type = PERFCTR_TYPE_BYTES4 },
2470 + { .offset = offsetof(struct perfctr_cpu_control, _reserved2),
2471 + .tag = PERFCTR_TAG_CPU_CONTROL_RSVD2,
2472 + .type = PERFCTR_TYPE_BYTES4 },
2473 + { .offset = offsetof(struct perfctr_cpu_control, _reserved3),
2474 + .tag = PERFCTR_TAG_CPU_CONTROL_RSVD3,
2475 + .type = PERFCTR_TYPE_BYTES4 },
2476 + { .offset = offsetof(struct perfctr_cpu_control, _reserved4),
2477 + .tag = PERFCTR_TAG_CPU_CONTROL_RSVD4,
2478 + .type = PERFCTR_TYPE_BYTES4 },
2481 +const struct perfctr_struct_desc perfctr_cpu_control_sdesc = {
2482 + .total_sizeof = sizeof(struct perfctr_cpu_control),
2483 + .total_nrfields = PERFCTR_CPU_CONTROL_NRFIELDS,
2484 + .nrfields = ARRAY_SIZE(perfctr_cpu_control_fields),
2485 + .fields = perfctr_cpu_control_fields,
2488 +#endif /* __powerpc__ */
2490 +#define PERFCTR_TAG_INFO_ABI_VERSION 0
2491 +#define PERFCTR_TAG_INFO_DRIVER_VERSION 1
2492 +#define PERFCTR_TAG_INFO_CPU_TYPE 2
2493 +#define PERFCTR_TAG_INFO_CPU_FEATURES 3
2494 +#define PERFCTR_TAG_INFO_CPU_KHZ 4
2495 +#define PERFCTR_TAG_INFO_TSC_TO_CPU_MULT 5
2496 +#define PERFCTR_TAG_INFO_RSVD2 6
2497 +#define PERFCTR_TAG_INFO_RSVD3 7
2498 +#define PERFCTR_TAG_INFO_RSVD4 8
2499 +#define PERFCTR_INFO_NRFIELDS (8 + sizeof(((struct perfctr_info*)0)->driver_version)/sizeof(int))
2501 +#define VPERFCTR_TAG_CONTROL_SIGNO 9
2502 +#define VPERFCTR_TAG_CONTROL_PRESERVE 10
2503 +#define VPERFCTR_TAG_CONTROL_RSVD1 11
2504 +#define VPERFCTR_TAG_CONTROL_RSVD2 12
2505 +#define VPERFCTR_TAG_CONTROL_RSVD3 13
2506 +#define VPERFCTR_TAG_CONTROL_RSVD4 14
2507 +#define VPERFCTR_CONTROL_NRFIELDS (6 + PERFCTR_CPU_CONTROL_NRFIELDS)
2509 +#define GPERFCTR_TAG_CPU_CONTROL_CPU 15
2510 +#define GPERFCTR_TAG_CPU_CONTROL_RSVD1 16
2511 +#define GPERFCTR_TAG_CPU_CONTROL_RSVD2 17
2512 +#define GPERFCTR_TAG_CPU_CONTROL_RSVD3 18
2513 +#define GPERFCTR_TAG_CPU_CONTROL_RSVD4 19
2514 +#define GPERFCTR_CPU_CONTROL_NRFIELDS (5 + PERFCTR_CPU_CONTROL_NRFIELDS)
2516 +#define GPERFCTR_TAG_CPU_STATE_CPU 20
2517 +#define GPERFCTR_TAG_CPU_STATE_RSVD1 21
2518 +#define GPERFCTR_TAG_CPU_STATE_RSVD2 22
2519 +#define GPERFCTR_TAG_CPU_STATE_RSVD3 23
2520 +#define GPERFCTR_TAG_CPU_STATE_RSVD4 24
2521 +#define GPERFCTR_CPU_STATE_ONLY_CPU_NRFIELDS 5
2522 +#define GPERFCTR_CPU_STATE_NRFIELDS (GPERFCTR_CPU_STATE_ONLY_CPU_NRFIELDS + PERFCTR_CPU_CONTROL_NRFIELDS + PERFCTR_SUM_CTRS_NRFIELDS)
2524 +static const struct perfctr_field_desc perfctr_info_fields[] = {
2525 + { .offset = offsetof(struct perfctr_info, abi_version),
2526 + .tag = PERFCTR_TAG_INFO_ABI_VERSION,
2527 + .type = PERFCTR_TYPE_BYTES4 },
2528 + { .offset = offsetof(struct perfctr_info, driver_version),
2529 + .tag = PERFCTR_TAG_INFO_DRIVER_VERSION,
2530 + .type = PERFCTR_TYPE_ARRAY(sizeof(((struct perfctr_info*)0)->driver_version)/sizeof(int), PERFCTR_TYPE_BYTES4) },
2531 + { .offset = offsetof(struct perfctr_info, cpu_type),
2532 + .tag = PERFCTR_TAG_INFO_CPU_TYPE,
2533 + .type = PERFCTR_TYPE_BYTES4 },
2534 + { .offset = offsetof(struct perfctr_info, cpu_features),
2535 + .tag = PERFCTR_TAG_INFO_CPU_FEATURES,
2536 + .type = PERFCTR_TYPE_BYTES4 },
2537 + { .offset = offsetof(struct perfctr_info, cpu_khz),
2538 + .tag = PERFCTR_TAG_INFO_CPU_KHZ,
2539 + .type = PERFCTR_TYPE_BYTES4 },
2540 + { .offset = offsetof(struct perfctr_info, tsc_to_cpu_mult),
2541 + .tag = PERFCTR_TAG_INFO_TSC_TO_CPU_MULT,
2542 + .type = PERFCTR_TYPE_BYTES4 },
2543 + { .offset = offsetof(struct perfctr_info, _reserved2),
2544 + .tag = PERFCTR_TAG_INFO_RSVD2,
2545 + .type = PERFCTR_TYPE_BYTES4 },
2546 + { .offset = offsetof(struct perfctr_info, _reserved3),
2547 + .tag = PERFCTR_TAG_INFO_RSVD3,
2548 + .type = PERFCTR_TYPE_BYTES4 },
2549 + { .offset = offsetof(struct perfctr_info, _reserved4),
2550 + .tag = PERFCTR_TAG_INFO_RSVD4,
2551 + .type = PERFCTR_TYPE_BYTES4 },
2554 +const struct perfctr_struct_desc perfctr_info_sdesc = {
2555 + .total_sizeof = sizeof(struct perfctr_info),
2556 + .total_nrfields = PERFCTR_INFO_NRFIELDS,
2557 + .nrfields = ARRAY_SIZE(perfctr_info_fields),
2558 + .fields = perfctr_info_fields,
2561 +#if defined(CONFIG_PERFCTR_VIRTUAL) || !defined(__KERNEL__)
2562 +static const struct perfctr_field_desc vperfctr_control_fields[] = {
2563 + { .offset = offsetof(struct vperfctr_control, si_signo),
2564 + .tag = VPERFCTR_TAG_CONTROL_SIGNO,
2565 + .type = PERFCTR_TYPE_BYTES4 },
2566 + { .offset = offsetof(struct vperfctr_control, preserve),
2567 + .tag = VPERFCTR_TAG_CONTROL_PRESERVE,
2568 + .type = PERFCTR_TYPE_BYTES4 },
2569 + { .offset = offsetof(struct vperfctr_control, _reserved1),
2570 + .tag = VPERFCTR_TAG_CONTROL_RSVD1,
2571 + .type = PERFCTR_TYPE_BYTES4 },
2572 + { .offset = offsetof(struct vperfctr_control, _reserved2),
2573 + .tag = VPERFCTR_TAG_CONTROL_RSVD2,
2574 + .type = PERFCTR_TYPE_BYTES4 },
2575 + { .offset = offsetof(struct vperfctr_control, _reserved3),
2576 + .tag = VPERFCTR_TAG_CONTROL_RSVD3,
2577 + .type = PERFCTR_TYPE_BYTES4 },
2578 + { .offset = offsetof(struct vperfctr_control, _reserved4),
2579 + .tag = VPERFCTR_TAG_CONTROL_RSVD4,
2580 + .type = PERFCTR_TYPE_BYTES4 },
2583 +static const struct perfctr_sub_struct_desc vperfctr_control_subs[] = {
2584 + { .offset = offsetof(struct vperfctr_control, cpu_control),
2585 + .sdesc = &perfctr_cpu_control_sdesc },
2588 +const struct perfctr_struct_desc vperfctr_control_sdesc = {
2589 + .total_sizeof = sizeof(struct vperfctr_control),
2590 + .total_nrfields = VPERFCTR_CONTROL_NRFIELDS,
2591 + .nrfields = ARRAY_SIZE(vperfctr_control_fields),
2592 + .fields = vperfctr_control_fields,
2593 + .nrsubs = ARRAY_SIZE(vperfctr_control_subs),
2594 + .subs = vperfctr_control_subs,
2596 +#endif /* CONFIG_PERFCTR_VIRTUAL || !__KERNEL__ */
2598 +#if defined(CONFIG_PERFCTR_GLOBAL) || !defined(__KERNEL__)
2599 +static const struct perfctr_field_desc gperfctr_cpu_control_fields[] = {
2600 + { .offset = offsetof(struct gperfctr_cpu_control, cpu),
2601 + .tag = GPERFCTR_TAG_CPU_CONTROL_CPU,
2602 + .type = PERFCTR_TYPE_BYTES4 },
2603 + { .offset = offsetof(struct gperfctr_cpu_control, _reserved1),
2604 + .tag = GPERFCTR_TAG_CPU_CONTROL_RSVD1,
2605 + .type = PERFCTR_TYPE_BYTES4 },
2606 + { .offset = offsetof(struct gperfctr_cpu_control, _reserved2),
2607 + .tag = GPERFCTR_TAG_CPU_CONTROL_RSVD2,
2608 + .type = PERFCTR_TYPE_BYTES4 },
2609 + { .offset = offsetof(struct gperfctr_cpu_control, _reserved3),
2610 + .tag = GPERFCTR_TAG_CPU_CONTROL_RSVD3,
2611 + .type = PERFCTR_TYPE_BYTES4 },
2612 + { .offset = offsetof(struct gperfctr_cpu_control, _reserved4),
2613 + .tag = GPERFCTR_TAG_CPU_CONTROL_RSVD4,
2614 + .type = PERFCTR_TYPE_BYTES4 },
2617 +static const struct perfctr_sub_struct_desc gperfctr_cpu_control_subs[] = {
2618 + { .offset = offsetof(struct gperfctr_cpu_control, cpu_control),
2619 + .sdesc = &perfctr_cpu_control_sdesc },
2622 +const struct perfctr_struct_desc gperfctr_cpu_control_sdesc = {
2623 + .total_sizeof = sizeof(struct gperfctr_cpu_control),
2624 + .total_nrfields = GPERFCTR_CPU_CONTROL_NRFIELDS,
2625 + .nrfields = ARRAY_SIZE(gperfctr_cpu_control_fields),
2626 + .fields = gperfctr_cpu_control_fields,
2627 + .nrsubs = ARRAY_SIZE(gperfctr_cpu_control_subs),
2628 + .subs = gperfctr_cpu_control_subs,
2631 +static const struct perfctr_field_desc gperfctr_cpu_state_fields[] = {
2632 + { .offset = offsetof(struct gperfctr_cpu_state, cpu),
2633 + .tag = GPERFCTR_TAG_CPU_STATE_CPU,
2634 + .type = PERFCTR_TYPE_BYTES4 },
2635 + { .offset = offsetof(struct gperfctr_cpu_state, _reserved1),
2636 + .tag = GPERFCTR_TAG_CPU_STATE_RSVD1,
2637 + .type = PERFCTR_TYPE_BYTES4 },
2638 + { .offset = offsetof(struct gperfctr_cpu_state, _reserved2),
2639 + .tag = GPERFCTR_TAG_CPU_STATE_RSVD2,
2640 + .type = PERFCTR_TYPE_BYTES4 },
2641 + { .offset = offsetof(struct gperfctr_cpu_state, _reserved3),
2642 + .tag = GPERFCTR_TAG_CPU_STATE_RSVD3,
2643 + .type = PERFCTR_TYPE_BYTES4 },
2644 + { .offset = offsetof(struct gperfctr_cpu_state, _reserved4),
2645 + .tag = GPERFCTR_TAG_CPU_STATE_RSVD4,
2646 + .type = PERFCTR_TYPE_BYTES4 },
2649 +static const struct perfctr_sub_struct_desc gperfctr_cpu_state_subs[] = {
2650 + { .offset = offsetof(struct gperfctr_cpu_state, cpu_control),
2651 + .sdesc = &perfctr_cpu_control_sdesc },
2652 + { .offset = offsetof(struct gperfctr_cpu_state, sum),
2653 + .sdesc = &perfctr_sum_ctrs_sdesc },
2656 +const struct perfctr_struct_desc gperfctr_cpu_state_only_cpu_sdesc = {
2657 + .total_sizeof = sizeof(struct gperfctr_cpu_state),
2658 + .total_nrfields = GPERFCTR_CPU_STATE_ONLY_CPU_NRFIELDS,
2659 + .nrfields = ARRAY_SIZE(gperfctr_cpu_state_fields),
2660 + .fields = gperfctr_cpu_state_fields,
2663 +const struct perfctr_struct_desc gperfctr_cpu_state_sdesc = {
2664 + .total_sizeof = sizeof(struct gperfctr_cpu_state),
2665 + .total_nrfields = GPERFCTR_CPU_STATE_NRFIELDS,
2666 + .nrfields = ARRAY_SIZE(gperfctr_cpu_state_fields),
2667 + .fields = gperfctr_cpu_state_fields,
2668 + .nrsubs = ARRAY_SIZE(gperfctr_cpu_state_subs),
2669 + .subs = gperfctr_cpu_state_subs,
2671 +#endif /* CONFIG_PERFCTR_GLOBAL || !__KERNEL__ */
2675 +int perfctr_copy_from_user(void *struct_address,
2676 + struct perfctr_struct_buf *argp,
2677 + const struct perfctr_struct_desc *sdesc)
2679 + struct perfctr_marshal_stream stream;
2681 + if( get_user(stream.size, &argp->rdsize) )
2683 + stream.buffer = argp->buffer;
2686 + memset(struct_address, 0, sdesc->total_sizeof);
2687 + return perfctr_decode_struct(struct_address, sdesc, &stream);
2690 +int perfctr_copy_to_user(struct perfctr_struct_buf *argp,
2691 + void *struct_address,
2692 + const struct perfctr_struct_desc *sdesc)
2694 + struct perfctr_marshal_stream stream;
2696 + if( get_user(stream.size, &argp->wrsize) )
2698 + stream.buffer = argp->buffer;
2701 + perfctr_encode_struct(struct_address, sdesc, &stream);
2702 + if( stream.error )
2703 + return stream.error;
2704 + if( put_user(stream.pos, &argp->rdsize) )
2709 +#else /* !__KERNEL__ */
2711 +#define sdesc_bufsize(sdesc) ((sdesc)->total_nrfields + (sdesc)->total_sizeof/sizeof(int))
2713 +static int common_ioctl_w(const void *arg,
2714 + const struct perfctr_struct_desc *sdesc,
2715 + struct perfctr_struct_buf *buf,
2716 + unsigned int bufsize)
2718 + struct perfctr_marshal_stream stream;
2720 + stream.size = bufsize;
2721 + stream.buffer = buf->buffer;
2724 + perfctr_encode_struct(arg, sdesc, &stream);
2725 + if( stream.error ) {
2726 + errno = -stream.error;
2729 + buf->rdsize = stream.pos;
2733 +int perfctr_ioctl_w(int fd, unsigned int cmd, const void *arg,
2734 + const struct perfctr_struct_desc *sdesc)
2736 + unsigned int bufsize = sdesc_bufsize(sdesc);
2738 + struct perfctr_struct_buf buf;
2740 + unsigned int rdsize;
2741 + unsigned int wrsize;
2742 + unsigned int buffer[bufsize];
2747 + err = common_ioctl_w(arg, sdesc, &u.buf, bufsize);
2751 + return ioctl(fd, cmd, &u.buf);
2754 +static int common_ioctl_r(int fd, unsigned int cmd, void *res,
2755 + const struct perfctr_struct_desc *sdesc,
2756 + struct perfctr_struct_buf *buf)
2758 + struct perfctr_marshal_stream stream;
2761 + if( ioctl(fd, cmd, buf) < 0 )
2763 + stream.size = buf->rdsize;
2764 + stream.buffer = buf->buffer;
2767 + memset(res, 0, sdesc->total_sizeof);
2768 + err = perfctr_decode_struct(res, sdesc, &stream);
2776 +int perfctr_ioctl_r(int fd, unsigned int cmd, void *res,
2777 + const struct perfctr_struct_desc *sdesc)
2779 + unsigned int bufsize = sdesc_bufsize(sdesc);
2781 + struct perfctr_struct_buf buf;
2783 + unsigned int rdsize;
2784 + unsigned int wrsize;
2785 + unsigned int buffer[bufsize];
2790 + u.buf.wrsize = bufsize;
2791 + return common_ioctl_r(fd, cmd, res, sdesc, &u.buf);
2794 +int perfctr_ioctl_wr(int fd, unsigned int cmd, void *argres,
2795 + const struct perfctr_struct_desc *arg_sdesc,
2796 + const struct perfctr_struct_desc *res_sdesc)
2798 + unsigned int arg_bufsize = sdesc_bufsize(arg_sdesc);
2799 + unsigned int res_bufsize = sdesc_bufsize(res_sdesc);
2800 + unsigned int bufsize = arg_bufsize > res_bufsize ? arg_bufsize : res_bufsize;
2802 + struct perfctr_struct_buf buf;
2804 + unsigned int rdsize;
2805 + unsigned int wrsize;
2806 + unsigned int buffer[bufsize];
2811 + err = common_ioctl_w(argres, arg_sdesc, &u.buf, arg_bufsize);
2814 + u.buf.wrsize = res_bufsize;
2815 + return common_ioctl_r(fd, cmd, argres, res_sdesc, &u.buf);
2818 +#endif /* !__KERNEL__ */
2819 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/ppc_compat.h
2820 ===================================================================
2821 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/ppc_compat.h 1969-12-31 19:00:00.000000000 -0500
2822 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/ppc_compat.h 2004-11-18 20:59:11.000000000 -0500
2824 +/* $Id: ppc_compat.h,v 1.1.2.1 2004/06/21 22:32:14 mikpe Exp $
2825 + * Performance-monitoring counters driver.
2826 + * PPC32-specific compatibility definitions for 2.4/2.6 kernels.
2828 + * Copyright (C) 2004 Mikael Pettersson
2831 +#define SPRN_MMCR0 0x3B8 /* 604 and up */
2832 +#define SPRN_PMC1 0x3B9 /* 604 and up */
2833 +#define SPRN_PMC2 0x3BA /* 604 and up */
2834 +#define SPRN_SIA 0x3BB /* 604 and up */
2835 +#define SPRN_MMCR1 0x3BC /* 604e and up */
2836 +#define SPRN_PMC3 0x3BD /* 604e and up */
2837 +#define SPRN_PMC4 0x3BE /* 604e and up */
2838 +#define SPRN_MMCR2 0x3B0 /* 7400 and up */
2839 +#define SPRN_BAMR 0x3B7 /* 7400 and up */
2840 +#define SPRN_PMC5 0x3B1 /* 7450 and up */
2841 +#define SPRN_PMC6 0x3B2 /* 7450 and up */
2843 +/* MMCR0 layout (74xx terminology) */
2844 +#define MMCR0_FC 0x80000000 /* Freeze counters unconditionally. */
2845 +#define MMCR0_FCS 0x40000000 /* Freeze counters while MSR[PR]=0 (supervisor mode). */
2846 +#define MMCR0_FCP 0x20000000 /* Freeze counters while MSR[PR]=1 (user mode). */
2847 +#define MMCR0_FCM1 0x10000000 /* Freeze counters while MSR[PM]=1. */
2848 +#define MMCR0_FCM0 0x08000000 /* Freeze counters while MSR[PM]=0. */
2849 +#define MMCR0_PMXE 0x04000000 /* Enable performance monitor exceptions.
2850 + * Cleared by hardware when a PM exception occurs.
2851 + * 604: PMXE is not cleared by hardware.
2853 +#define MMCR0_FCECE 0x02000000 /* Freeze counters on enabled condition or event.
2854 + * FCECE is treated as 0 if TRIGGER is 1.
2855 + * 74xx: FC is set when the event occurs.
2856 + * 604/750: ineffective when PMXE=0.
2858 +#define MMCR0_TBSEL 0x01800000 /* Time base lower (TBL) bit selector.
2859 + * 00: bit 31, 01: bit 23, 10: bit 19, 11: bit 15.
2861 +#define MMCR0_TBEE 0x00400000 /* Enable event on TBL bit transition from 0 to 1. */
2862 +#define MMCR0_THRESHOLD 0x003F0000 /* Threshold value for certain events. */
2863 +#define MMCR0_PMC1CE 0x00008000 /* Enable event on PMC1 overflow. */
2864 +#define MMCR0_PMCjCE 0x00004000 /* Enable event on PMC2-PMC6 overflow.
2865 + * 604/750: Overrides FCECE (DISCOUNT).
2867 +#define MMCR0_TRIGGER 0x00002000 /* Disable PMC2-PMC6 until PMC1 overflow or other event.
2868 + * 74xx: cleared by hardware when the event occurs.
2870 +#define MMCR0_PMC1SEL 0x00001FB0 /* PMC1 event selector, 7 bits. */
2871 +#define MMCR0_PMC2SEL 0x0000003F /* PMC2 event selector, 6 bits. */
2873 +/* MMCR1 layout (604e-7457) */
2874 +#define MMCR1_PMC3SEL 0xF8000000 /* PMC3 event selector, 5 bits. */
2875 +#define MMCR1_PMC4SEL 0x07B00000 /* PMC4 event selector, 5 bits. */
2876 +#define MMCR1_PMC5SEL 0x003E0000 /* PMC5 event selector, 5 bits. (745x only) */
2877 +#define MMCR1_PMC6SEL 0x0001F800 /* PMC6 event selector, 6 bits. (745x only) */
2878 +#define MMCR1__RESERVED 0x000007FF /* should be zero */
2880 +/* MMCR2 layout (7400-7457) */
2881 +#define MMCR2_THRESHMULT 0x80000000 /* MMCR0[THRESHOLD] multiplier. */
2882 +#define MMCR2_SMCNTEN 0x40000000 /* 7400/7410 only, should be zero. */
2883 +#define MMCR2_SMINTEN 0x20000000 /* 7400/7410 only, should be zero. */
2884 +#define MMCR2__RESERVED 0x1FFFFFFF /* should be zero */
2885 +#define MMCR2_RESERVED (MMCR2_SMCNTEN | MMCR2_SMINTEN | MMCR2__RESERVED)
2886 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/compat.h
2887 ===================================================================
2888 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/compat.h 1969-12-31 19:00:00.000000000 -0500
2889 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/compat.h 2004-11-18 20:59:11.000000000 -0500
2891 +/* $Id: compat.h,v 1.42 2004/05/02 22:52:13 mikpe Exp $
2892 + * Performance-monitoring counters driver.
2893 + * Compatibility definitions for 2.6 kernels.
2895 + * Copyright (C) 1999-2004 Mikael Pettersson
2897 +#include <linux/version.h>
2899 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
2900 +#include "compat24.h"
2903 +#include "cpumask.h"
2905 +#define EXPORT_SYMBOL_mmu_cr4_features EXPORT_SYMBOL(mmu_cr4_features)
2906 +#define EXPORT_SYMBOL___put_task_struct EXPORT_SYMBOL(__put_task_struct)
2908 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) /* names changed in 2.6.4-rc2 */
2909 +#define sysdev_register(dev) sys_device_register((dev))
2910 +#define sysdev_unregister(dev) sys_device_unregister((dev))
2914 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/Config.in
2915 ===================================================================
2916 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/Config.in 1969-12-31 19:00:00.000000000 -0500
2917 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/Config.in 2004-11-18 20:59:11.000000000 -0500
2919 +# $Id: Config.in,v 1.15 2002/11/25 13:01:46 mikpe Exp $
2920 +# Performance-monitoring counters driver configuration
2923 +mainmenu_option next_comment
2924 +comment 'Performance-monitoring counters support'
2925 +tristate 'Performance-monitoring counters support' CONFIG_PERFCTR
2926 +if [ "$CONFIG_PERFCTR" != "n" ]; then
2927 + define_bool CONFIG_KPERFCTR y
2928 + bool ' Additional internal consistency checks' CONFIG_PERFCTR_DEBUG
2929 + bool ' Init-time hardware tests' CONFIG_PERFCTR_INIT_TESTS
2930 + bool ' Virtual performance counters support' CONFIG_PERFCTR_VIRTUAL $CONFIG_PERFCTR
2931 + bool ' Global performance counters support' CONFIG_PERFCTR_GLOBAL $CONFIG_PERFCTR
2934 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/global.c
2935 ===================================================================
2936 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/global.c 1969-12-31 19:00:00.000000000 -0500
2937 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/global.c 2004-11-18 20:59:11.000000000 -0500
2939 +/* $Id: global.c,v 1.38 2004/01/25 14:45:35 mikpe Exp $
2940 + * Global-mode performance-monitoring counters via /dev/perfctr.
2942 + * Copyright (C) 2000-2003 Mikael Pettersson
2944 + * XXX: Doesn't do any authentication yet. Should we limit control
2945 + * to root, or base it on having write access to /dev/perfctr?
2947 +#include <linux/config.h>
2948 +#define __NO_VERSION__
2949 +#include <linux/module.h>
2950 +#include <linux/sched.h>
2951 +#include <linux/init.h>
2952 +#include <linux/fs.h>
2953 +#include <linux/perfctr.h>
2955 +#include <asm/uaccess.h>
2957 +#include "compat.h"
2958 +#include "global.h"
2959 +#include "marshal.h"
2961 +static const char this_service[] = __FILE__;
2962 +static int hardware_is_ours = 0;
2963 +static struct timer_list sampling_timer;
2964 +static DECLARE_MUTEX(control_mutex);
2965 +static unsigned int nr_active_cpus = 0;
2968 + struct perfctr_cpu_state cpu_state;
2970 +} ____cacheline_aligned;
2972 +static struct gperfctr per_cpu_gperfctr[NR_CPUS] __cacheline_aligned;
2974 +static int reserve_hardware(void)
2976 + const char *other;
2978 + if( hardware_is_ours )
2980 + other = perfctr_cpu_reserve(this_service);
2982 + printk(KERN_ERR __FILE__ ":%s: failed because hardware is taken by '%s'\n",
2983 + __FUNCTION__, other);
2986 + hardware_is_ours = 1;
2987 + __module_get(THIS_MODULE);
2991 +static void release_hardware(void)
2995 + nr_active_cpus = 0;
2996 + if( hardware_is_ours ) {
2997 + hardware_is_ours = 0;
2998 + del_timer(&sampling_timer);
2999 + sampling_timer.data = 0;
3000 + perfctr_cpu_release(this_service);
3001 + module_put(THIS_MODULE);
3002 + for(i = 0; i < NR_CPUS; ++i)
3003 + per_cpu_gperfctr[i].cpu_state.cstatus = 0;
3007 +static void sample_this_cpu(void *unused)
3009 + /* PREEMPT note: when called via smp_call_function(),
3010 + this is in IRQ context with preemption disabled. */
3011 + struct gperfctr *perfctr;
3013 + perfctr = &per_cpu_gperfctr[smp_processor_id()];
3014 + if( !perfctr_cstatus_enabled(perfctr->cpu_state.cstatus) )
3016 + spin_lock(&perfctr->lock);
3017 + perfctr_cpu_sample(&perfctr->cpu_state);
3018 + spin_unlock(&perfctr->lock);
3021 +static void sample_all_cpus(void)
3023 + on_each_cpu(sample_this_cpu, NULL, 1, 1);
3026 +static void sampling_timer_function(unsigned long interval)
3028 + sample_all_cpus();
3029 + sampling_timer.expires = jiffies + interval;
3030 + add_timer(&sampling_timer);
3033 +static unsigned long usectojiffies(unsigned long usec)
3035 + usec += 1000000 / HZ - 1;
3036 + usec /= 1000000 / HZ;
3040 +static void start_sampling_timer(unsigned long interval_usec)
3042 + if( interval_usec > 0 ) {
3043 + unsigned long interval = usectojiffies(interval_usec);
3044 + init_timer(&sampling_timer);
3045 + sampling_timer.function = sampling_timer_function;
3046 + sampling_timer.data = interval;
3047 + sampling_timer.expires = jiffies + interval;
3048 + add_timer(&sampling_timer);
3052 +static void start_this_cpu(void *unused)
3054 + /* PREEMPT note: when called via smp_call_function(),
3055 + this is in IRQ context with preemption disabled. */
3056 + struct gperfctr *perfctr;
3058 + perfctr = &per_cpu_gperfctr[smp_processor_id()];
3059 + if( perfctr_cstatus_enabled(perfctr->cpu_state.cstatus) )
3060 + perfctr_cpu_resume(&perfctr->cpu_state);
3063 +static void start_all_cpus(void)
3065 + on_each_cpu(start_this_cpu, NULL, 1, 1);
3068 +static int gperfctr_control(struct perfctr_struct_buf *argp)
3071 + struct gperfctr *perfctr;
3072 + struct gperfctr_cpu_control cpu_control;
3074 + ret = perfctr_copy_from_user(&cpu_control, argp, &gperfctr_cpu_control_sdesc);
3077 + if( cpu_control.cpu >= NR_CPUS ||
3078 + !cpu_online(cpu_control.cpu) ||
3079 + perfctr_cpu_is_forbidden(cpu_control.cpu) )
3081 + /* we don't permit i-mode counters */
3082 + if( cpu_control.cpu_control.nrictrs != 0 )
3084 + down(&control_mutex);
3086 + if( hardware_is_ours )
3087 + goto out_up; /* you have to stop them first */
3088 + perfctr = &per_cpu_gperfctr[cpu_control.cpu];
3089 + spin_lock(&perfctr->lock);
3090 + perfctr->cpu_state.tsc_start = 0;
3091 + perfctr->cpu_state.tsc_sum = 0;
3092 + memset(&perfctr->cpu_state.pmc, 0, sizeof perfctr->cpu_state.pmc);
3093 + perfctr->cpu_state.control = cpu_control.cpu_control;
3094 + ret = perfctr_cpu_update_control(&perfctr->cpu_state, 1);
3095 + spin_unlock(&perfctr->lock);
3098 + if( perfctr_cstatus_enabled(perfctr->cpu_state.cstatus) )
3100 + ret = nr_active_cpus;
3102 + up(&control_mutex);
3106 +static int gperfctr_start(unsigned int interval_usec)
3110 + if( interval_usec < 10000 )
3112 + down(&control_mutex);
3113 + ret = nr_active_cpus;
3115 + if( reserve_hardware() < 0 ) {
3119 + start_sampling_timer(interval_usec);
3122 + up(&control_mutex);
3126 +static int gperfctr_stop(void)
3128 + down(&control_mutex);
3129 + release_hardware();
3130 + up(&control_mutex);
3134 +static int gperfctr_read(struct perfctr_struct_buf *argp)
3136 + struct gperfctr *perfctr;
3137 + struct gperfctr_cpu_state state;
3140 + // XXX: sample_all_cpus() ???
3141 + err = perfctr_copy_from_user(&state, argp, &gperfctr_cpu_state_only_cpu_sdesc);
3144 + if( state.cpu >= NR_CPUS || !cpu_online(state.cpu) )
3146 + perfctr = &per_cpu_gperfctr[state.cpu];
3147 + spin_lock(&perfctr->lock);
3148 + state.cpu_control = perfctr->cpu_state.control;
3149 + //state.sum = perfctr->cpu_state.sum;
3152 + state.sum.tsc = perfctr->cpu_state.tsc_sum;
3153 + for(j = 0; j < ARRAY_SIZE(state.sum.pmc); ++j)
3154 + state.sum.pmc[j] = perfctr->cpu_state.pmc[j].sum;
3156 + spin_unlock(&perfctr->lock);
3157 + return perfctr_copy_to_user(argp, &state, &gperfctr_cpu_state_sdesc);
3160 +int gperfctr_ioctl(struct inode *inode, struct file *filp,
3161 + unsigned int cmd, unsigned long arg)
3164 + case GPERFCTR_CONTROL:
3165 + return gperfctr_control((struct perfctr_struct_buf*)arg);
3166 + case GPERFCTR_READ:
3167 + return gperfctr_read((struct perfctr_struct_buf*)arg);
3168 + case GPERFCTR_STOP:
3169 + return gperfctr_stop();
3170 + case GPERFCTR_START:
3171 + return gperfctr_start(arg);
3176 +void __init gperfctr_init(void)
3180 + for(i = 0; i < NR_CPUS; ++i)
3181 + per_cpu_gperfctr[i].lock = SPIN_LOCK_UNLOCKED;
3183 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_64_tests.h
3184 ===================================================================
3185 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/x86_64_tests.h 1969-12-31 19:00:00.000000000 -0500
3186 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_64_tests.h 2004-11-18 20:59:11.000000000 -0500
3188 +/* $Id: x86_64_tests.h,v 1.1 2003/05/14 21:51:57 mikpe Exp $
3189 + * Performance-monitoring counters driver.
3190 + * Optional x86_64-specific init-time tests.
3192 + * Copyright (C) 2003 Mikael Pettersson
3195 +#ifdef CONFIG_PERFCTR_INIT_TESTS
3196 +extern void perfctr_k8_init_tests(void);
3197 +extern void perfctr_generic_init_tests(void);
3199 +#define perfctr_k8_init_tests()
3200 +#define perfctr_generic_init_tests()
3202 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/Kconfig
3203 ===================================================================
3204 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/Kconfig 1969-12-31 19:00:00.000000000 -0500
3205 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/Kconfig 2004-11-18 20:59:11.000000000 -0500
3207 +# $Id: Kconfig,v 1.7 2003/05/14 21:51:32 mikpe Exp $
3208 +# Performance-monitoring counters driver configuration
3211 +menu "Performance-monitoring counters support"
3214 + tristate "Performance monitoring counters support"
3216 + This driver provides access to the performance-monitoring counter
3217 + registers available in some (but not all) modern processors.
3218 + These special-purpose registers can be programmed to count low-level
3219 + performance-related events which occur during program execution,
3220 + such as cache misses, pipeline stalls, etc.
3222 + You can safely say Y here, even if you intend to run the kernel
3223 + on a processor without performance-monitoring counters.
3225 + You can also say M here to compile the driver as a module; the
3226 + module will be called `perfctr'.
3230 + depends on PERFCTR
3233 +config PERFCTR_DEBUG
3234 + bool "Additional internal consistency checks"
3235 + depends on PERFCTR
3237 + This option enables additional internal consistency checking in
3238 + the perfctr driver. The scope of these checks is unspecified and
3239 + may vary between different versions of the driver.
3241 + Enabling this option will reduce performance, so say N unless you
3242 + are debugging the driver.
3244 +config PERFCTR_INIT_TESTS
3245 + bool "Init-time hardware tests"
3246 + depends on PERFCTR
3248 + This option makes the driver perform additional hardware tests
3249 + during initialisation, and log their results in the kernel's
3250 + message buffer. For most supported processors, these tests simply
3251 + measure the runtime overheads of performance counter operations.
3253 + If you have a less well-known processor (one not listed in the
3254 + etc/costs/ directory in the user-space package), you should enable
3255 + this option and email the results to the perfctr developers.
3259 +config PERFCTR_VIRTUAL
3260 + bool "Virtual performance counters support"
3261 + depends on PERFCTR
3263 + The processor's performance-monitoring counters are special-purpose
3264 + global registers. This option adds support for virtual per-process
3265 + performance-monitoring counters which only run when the process
3266 + to which they belong is executing. This improves the accuracy of
3267 + performance measurements by reducing "noise" from other processes.
3271 +config PERFCTR_GLOBAL
3272 + bool "Global performance counters support"
3273 + depends on PERFCTR
3275 + This option adds driver support for global-mode (system-wide)
3276 + performance-monitoring counters. In this mode, the driver allows
3277 + each performance-monitoring counter on each processor to be
3278 + controlled and read. The driver provides a sampling timer to
3279 + maintain 64-bit accumulated event counts.
3281 + Global-mode performance counters cannot be used if some process
3282 + is currently using virtual-mode performance counters, and vice versa.
3286 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/marshal.h
3287 ===================================================================
3288 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/marshal.h 1969-12-31 19:00:00.000000000 -0500
3289 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/marshal.h 2004-11-18 20:59:11.000000000 -0500
3291 +/* $Id: marshal.h,v 1.1 2003/08/19 13:37:07 mikpe Exp $
3292 + * Performance-monitoring counters driver.
3293 + * Structure marshalling support.
3295 + * Copyright (C) 2003 Mikael Pettersson
3299 + * Each encoded datum starts with a 32-bit header word, containing
3300 + * the datum's type (1 bit: UINT32 or UINT64), the target's field
3301 + * tag (16 bits), and the target field's array index (15 bits).
3303 + * After the header follows the datum's value, in one (for UINT32)
3304 + * or two (for UINT64) words. Multi-word values are emitted in
3305 + * native word order.
3307 + * To encode a struct, encode each field with a non-zero value,
3308 + * and place the encodings in sequence. The field order is arbitrary.
3310 + * To decode an encoded struct, first memset() the target struct
3311 + * to zero. Then decode each encoded field in the sequence and
3312 + * update the corresponding field in the target struct.
3314 +#define PERFCTR_HEADER(TYPE,TAG,ITEMNR) (((TAG)<<16)|((ITEMNR)<<1)|(TYPE))
3315 +#define PERFCTR_HEADER_TYPE(H) ((H) & 0x1)
3316 +#define PERFCTR_HEADER_ITEMNR(H) (((H) >> 1) & 0x7FFF)
3317 +#define PERFCTR_HEADER_TAG(H) ((H) >> 16)
3319 +#define PERFCTR_HEADER_UINT32 0
3320 +#define PERFCTR_HEADER_UINT64 1
3323 + * A field descriptor describes a struct field to the
3324 + * encoding and decoding procedures.
3326 + * To keep the descriptors small, field tags and array sizes
3327 + * are currently restricted to 8 and 7 bits, respectively.
3328 + * This does not change the encoded format.
3330 +struct perfctr_field_desc {
3331 + unsigned short offset; /* offsetof() for this field */
3332 + unsigned char tag; /* identifying tag in encoded format */
3333 + unsigned char type; /* base type (1 bit), array size - 1 (7 bits) */
3336 +#define PERFCTR_TYPE_ARRAY(N,T) ((((N) - 1) << 1) | (T))
3337 +#define PERFCTR_TYPE_BASE(T) ((T) & 0x1)
3338 +#define PERFCTR_TYPE_NRITEMS(T) (((T) >> 1) + 1)
3340 +#define PERFCTR_TYPE_BYTES4 0 /* uint32 or char[4] */
3341 +#define PERFCTR_TYPE_UINT64 1 /* long long */
3343 +struct perfctr_struct_desc {
3344 + unsigned short total_sizeof; /* for buffer allocation and decode memset() */
3345 + unsigned short total_nrfields; /* for buffer allocation */
3346 + unsigned short nrfields;
3347 + unsigned short nrsubs;
3348 + /* Note: the fields must be in ascending tag order */
3349 + const struct perfctr_field_desc *fields;
3350 + const struct perfctr_sub_struct_desc {
3351 + unsigned short offset;
3352 + const struct perfctr_struct_desc *sdesc;
3356 +struct perfctr_marshal_stream {
3357 + unsigned int size;
3358 + unsigned int *buffer;
3360 + unsigned int error;
3363 +extern void perfctr_encode_struct(const void *address,
3364 + const struct perfctr_struct_desc *sdesc,
3365 + struct perfctr_marshal_stream *stream);
3367 +extern int perfctr_decode_struct(void *address,
3368 + const struct perfctr_struct_desc *sdesc,
3369 + struct perfctr_marshal_stream *stream);
3371 +extern const struct perfctr_struct_desc perfctr_sum_ctrs_sdesc;
3372 +extern const struct perfctr_struct_desc perfctr_cpu_control_sdesc;
3373 +extern const struct perfctr_struct_desc perfctr_info_sdesc;
3374 +extern const struct perfctr_struct_desc vperfctr_control_sdesc;
3375 +extern const struct perfctr_struct_desc gperfctr_cpu_control_sdesc;
3376 +extern const struct perfctr_struct_desc gperfctr_cpu_state_only_cpu_sdesc;
3377 +extern const struct perfctr_struct_desc gperfctr_cpu_state_sdesc;
3380 +extern int perfctr_copy_to_user(struct perfctr_struct_buf *argp,
3381 + void *struct_address,
3382 + const struct perfctr_struct_desc *sdesc);
3383 +extern int perfctr_copy_from_user(void *struct_address,
3384 + struct perfctr_struct_buf *argp,
3385 + const struct perfctr_struct_desc *sdesc);
3387 +extern int perfctr_ioctl_w(int fd, unsigned int cmd, const void *arg,
3388 + const struct perfctr_struct_desc *sdesc);
3389 +extern int perfctr_ioctl_r(int fd, unsigned int cmd, void *res,
3390 + const struct perfctr_struct_desc *sdesc);
3391 +extern int perfctr_ioctl_wr(int fd, unsigned int cmd, void *argres,
3392 + const struct perfctr_struct_desc *arg_sdesc,
3393 + const struct perfctr_struct_desc *res_sdesc);
3394 +#endif /* __KERNEL__ */
3395 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/virtual_stub.c
3396 ===================================================================
3397 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/virtual_stub.c 1969-12-31 19:00:00.000000000 -0500
3398 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/virtual_stub.c 2004-11-18 23:52:29.000000000 -0500
3400 +/* $Id: virtual_stub.c,v 1.26 2003/10/04 22:53:42 mikpe Exp $
3401 + * Kernel stub used to support virtual perfctrs when the
3402 + * perfctr driver is built as a module.
3404 + * Copyright (C) 2000-2003 Mikael Pettersson
3406 +#include <linux/config.h>
3407 +#include <linux/module.h>
3408 +#include <linux/kernel.h>
3409 +#include <linux/sched.h>
3410 +#include <linux/perfctr.h>
3411 +#include "compat.h"
3413 +static void bug_void_perfctr(struct vperfctr *perfctr)
3415 + current->thread.perfctr = NULL;
3419 +#if PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED
3420 +static void bug_set_cpus_allowed(struct task_struct *owner, struct vperfctr *perfctr, cpumask_t new_mask)
3422 + owner->thread.perfctr = NULL;
3427 +struct vperfctr_stub vperfctr_stub = {
3428 + .exit = bug_void_perfctr,
3429 + .suspend = bug_void_perfctr,
3430 + .resume = bug_void_perfctr,
3431 + .sample = bug_void_perfctr,
3432 +#if PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED
3433 + .set_cpus_allowed = bug_set_cpus_allowed,
3438 + * exit_thread() calls __vperfctr_exit() via vperfctr_stub.exit().
3439 + * If the process' reference was the last reference to this
3440 + * vperfctr object, and this was the last live vperfctr object,
3441 + * then the perfctr module's use count will drop to zero.
3442 + * This is Ok, except for the fact that code is still running
3443 + * in the module (pending returns back to exit_thread()). This
3444 + * could race with rmmod in a preemptive UP kernel, leading to
3445 + * code running in freed memory. The race also exists in SMP
3446 + * kernels, but the time window is extremely small.
3448 + * Since exit() isn't performance-critical, we wrap the call to
3449 + * vperfctr_stub.exit() with code to increment the module's use
3450 + * count before the call, and decrement it again afterwards. Thus,
3451 + * the final drop to zero occurs here and not in the module itself.
3452 + * (All other code paths that drop the use count do so via a file
3453 + * object, and VFS in 2.4+ kernels also refcount the module.)
3455 +void _vperfctr_exit(struct vperfctr *perfctr)
3457 + __module_get(vperfctr_stub.owner);
3458 + vperfctr_stub.exit(perfctr);
3459 + module_put(vperfctr_stub.owner);
3462 +EXPORT_SYMBOL(vperfctr_stub);
3464 +#include <linux/mm.h> /* for 2.4.15 and up, except 2.4.20-8-redhat */
3465 +#include <linux/ptrace.h> /* for 2.5.32 and up, and 2.4.20-8-redhat */
3466 +EXPORT_SYMBOL(ptrace_check_attach);
3467 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/ppc_tests.c
3468 ===================================================================
3469 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/ppc_tests.c 1969-12-31 19:00:00.000000000 -0500
3470 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/ppc_tests.c 2004-11-18 20:59:11.000000000 -0500
3472 +/* $Id: ppc_tests.c,v 1.1.2.3 2004/07/27 16:42:03 mikpe Exp $
3473 + * Performance-monitoring counters driver.
3474 + * Optional PPC32-specific init-time tests.
3476 + * Copyright (C) 2004 Mikael Pettersson
3478 +#include <linux/config.h>
3479 +#define __NO_VERSION__
3480 +#include <linux/module.h>
3481 +#include <linux/init.h>
3482 +#include <linux/sched.h>
3483 +#include <linux/fs.h>
3484 +#include <linux/perfctr.h>
3485 +#include <asm/processor.h>
3486 +#include <asm/time.h> /* for tb_ticks_per_jiffy */
3487 +#include "compat.h"
3488 +#include "ppc_compat.h"
3489 +#include "ppc_tests.h"
3492 +#define X2(S) S"; "S
3493 +#define X8(S) X2(X2(X2(S)))
3495 +static void __init do_read_tbl(unsigned int unused)
3497 + unsigned int i, dummy;
3498 + for(i = 0; i < NITER/8; ++i)
3499 + __asm__ __volatile__(X8("mftbl %0") : "=r"(dummy));
3502 +static void __init do_read_pmc1(unsigned int unused)
3504 + unsigned int i, dummy;
3505 + for(i = 0; i < NITER/8; ++i)
3506 + __asm__ __volatile__(X8("mfspr %0," __stringify(SPRN_PMC1)) : "=r"(dummy));
3509 +static void __init do_read_pmc2(unsigned int unused)
3511 + unsigned int i, dummy;
3512 + for(i = 0; i < NITER/8; ++i)
3513 + __asm__ __volatile__(X8("mfspr %0," __stringify(SPRN_PMC2)) : "=r"(dummy));
3516 +static void __init do_read_pmc3(unsigned int unused)
3518 + unsigned int i, dummy;
3519 + for(i = 0; i < NITER/8; ++i)
3520 + __asm__ __volatile__(X8("mfspr %0," __stringify(SPRN_PMC3)) : "=r"(dummy));
3523 +static void __init do_read_pmc4(unsigned int unused)
3525 + unsigned int i, dummy;
3526 + for(i = 0; i < NITER/8; ++i)
3527 + __asm__ __volatile__(X8("mfspr %0," __stringify(SPRN_PMC4)) : "=r"(dummy));
3530 +static void __init do_read_mmcr0(unsigned int unused)
3532 + unsigned int i, dummy;
3533 + for(i = 0; i < NITER/8; ++i)
3534 + __asm__ __volatile__(X8("mfspr %0," __stringify(SPRN_MMCR0)) : "=r"(dummy));
3537 +static void __init do_read_mmcr1(unsigned int unused)
3539 + unsigned int i, dummy;
3540 + for(i = 0; i < NITER/8; ++i)
3541 + __asm__ __volatile__(X8("mfspr %0," __stringify(SPRN_MMCR1)) : "=r"(dummy));
3544 +static void __init do_write_pmc2(unsigned int arg)
3547 + for(i = 0; i < NITER/8; ++i)
3548 + __asm__ __volatile__(X8("mtspr " __stringify(SPRN_PMC2) ",%0") : : "r"(arg));
3551 +static void __init do_write_pmc3(unsigned int arg)
3554 + for(i = 0; i < NITER/8; ++i)
3555 + __asm__ __volatile__(X8("mtspr " __stringify(SPRN_PMC3) ",%0") : : "r"(arg));
3558 +static void __init do_write_pmc4(unsigned int arg)
3561 + for(i = 0; i < NITER/8; ++i)
3562 + __asm__ __volatile__(X8("mtspr " __stringify(SPRN_PMC4) ",%0") : : "r"(arg));
3565 +static void __init do_write_mmcr1(unsigned int arg)
3568 + for(i = 0; i < NITER/8; ++i)
3569 + __asm__ __volatile__(X8("mtspr " __stringify(SPRN_MMCR1) ",%0") : : "r"(arg));
3572 +static void __init do_write_mmcr0(unsigned int arg)
3575 + for(i = 0; i < NITER/8; ++i)
3576 + __asm__ __volatile__(X8("mtspr " __stringify(SPRN_MMCR0) ",%0") : : "r"(arg));
3579 +static void __init do_empty_loop(unsigned int unused)
3582 + for(i = 0; i < NITER/8; ++i)
3583 + __asm__ __volatile__("" : : );
3586 +static unsigned __init run(void (*doit)(unsigned int), unsigned int arg)
3588 + unsigned int start, stop;
3589 + start = mfspr(SPRN_PMC1);
3590 + (*doit)(arg); /* should take < 2^32 cycles to complete */
3591 + stop = mfspr(SPRN_PMC1);
3592 + return stop - start;
3595 +static void __init init_tests_message(void)
3597 + unsigned int pvr = mfspr(SPRN_PVR);
3598 + printk(KERN_INFO "Please email the following PERFCTR INIT lines "
3599 + "to mikpe@csd.uu.se\n"
3600 + KERN_INFO "To remove this message, rebuild the driver "
3601 + "with CONFIG_PERFCTR_INIT_TESTS=n\n");
3602 + printk(KERN_INFO "PERFCTR INIT: PVR 0x%08x, CPU clock %u kHz, TB clock %u kHz\n",
3604 + perfctr_info.cpu_khz,
3605 + tb_ticks_per_jiffy*(HZ/10)/(1000/10));
3608 +static void __init clear(int have_mmcr1)
3610 + mtspr(SPRN_MMCR0, 0);
3611 + mtspr(SPRN_PMC1, 0);
3612 + mtspr(SPRN_PMC2, 0);
3614 + mtspr(SPRN_MMCR1, 0);
3615 + mtspr(SPRN_PMC3, 0);
3616 + mtspr(SPRN_PMC4, 0);
3620 +static void __init check_fcece(unsigned int pmc1ce)
3622 + unsigned int mmcr0;
3625 + * This test checks if MMCR0[FC] is set after PMC1 overflows
3626 + * when MMCR0[FCECE] is set.
3627 + * 74xx documentation states this behaviour, while documentation
3628 + * for 604/750 processors doesn't mention this at all.
3630 + * Also output the value of PMC1 shortly after the overflow.
3631 + * This tells us if PMC1 really was frozen. On 604/750, it may not
3632 + * freeze since we don't enable PMIs. [No freeze confirmed on 750.]
3634 + * When pmc1ce == 0, MMCR0[PMC1CE] is zero. It's unclear whether
3635 + * this masks all PMC1 overflow events or just PMC1 PMIs.
3637 + * PMC1 counts processor cycles, with 100 to go before overflowing.
3639 + * PMC1CE is clear if !pmc1ce, otherwise set.
3641 + mtspr(SPRN_PMC1, 0x80000000-100);
3642 + mmcr0 = (1<<(31-6)) | (0x01 << 6);
3644 + mmcr0 |= (1<<(31-16));
3645 + mtspr(SPRN_MMCR0, mmcr0);
3648 + } while (!(mfspr(SPRN_PMC1) & 0x80000000));
3650 + printk(KERN_INFO "PERFCTR INIT: %s(%u): MMCR0[FC] is %u, PMC1 is %#x\n",
3651 + __FUNCTION__, pmc1ce,
3652 + !!(mfspr(SPRN_MMCR0) & (1<<(31-0))), mfspr(SPRN_PMC1));
3653 + mtspr(SPRN_MMCR0, 0);
3654 + mtspr(SPRN_PMC1, 0);
3657 +static void __init check_trigger(unsigned int pmc1ce)
3659 + unsigned int mmcr0;
3662 + * This test checks if MMCR0[TRIGGER] is reset after PMC1 overflows.
3663 + * 74xx documentation states this behaviour, while documentation
3664 + * for 604/750 processors doesn't mention this at all.
3665 + * [No reset confirmed on 750.]
3667 + * Also output the values of PMC1 and PMC2 shortly after the overflow.
3668 + * PMC2 should be equal to PMC1-0x80000000.
3670 + * When pmc1ce == 0, MMCR0[PMC1CE] is zero. It's unclear whether
3671 + * this masks all PMC1 overflow events or just PMC1 PMIs.
3673 + * PMC1 counts processor cycles, with 100 to go before overflowing.
3674 + * PMC2 counts processor cycles, starting from 0.
3675 + * TRIGGER is set, so PMC2 doesn't start until PMC1 overflows.
3676 + * PMC1CE is clear if !pmc1ce, otherwise set.
3678 + mtspr(SPRN_PMC2, 0);
3679 + mtspr(SPRN_PMC1, 0x80000000-100);
3680 + mmcr0 = (1<<(31-18)) | (0x01 << 6) | (0x01 << 0);
3682 + mmcr0 |= (1<<(31-16));
3683 + mtspr(SPRN_MMCR0, mmcr0);
3686 + } while (!(mfspr(SPRN_PMC1) & 0x80000000));
3688 + printk(KERN_INFO "PERFCTR INIT: %s(%u): MMCR0[TRIGGER] is %u, PMC1 is %#x, PMC2 is %#x\n",
3689 + __FUNCTION__, pmc1ce,
3690 + !!(mfspr(SPRN_MMCR0) & (1<<(31-18))), mfspr(SPRN_PMC1), mfspr(SPRN_PMC2));
3691 + mtspr(SPRN_MMCR0, 0);
3692 + mtspr(SPRN_PMC1, 0);
3693 + mtspr(SPRN_PMC2, 0);
3697 +measure_overheads(int have_mmcr1)
3700 + unsigned int mmcr0, loop, ticks[12];
3701 + const char *name[12];
3703 + clear(have_mmcr1);
3705 + /* PMC1 = "processor cycles",
3706 + PMC2 = "completed instructions",
3707 + not disabled in any mode,
3709 + mmcr0 = (0x01 << 6) | (0x02 << 0);
3710 + mtspr(SPRN_MMCR0, mmcr0);
3712 + name[0] = "mftbl";
3713 + ticks[0] = run(do_read_tbl, 0);
3714 + name[1] = "mfspr (pmc1)";
3715 + ticks[1] = run(do_read_pmc1, 0);
3716 + name[2] = "mfspr (pmc2)";
3717 + ticks[2] = run(do_read_pmc2, 0);
3718 + name[3] = "mfspr (pmc3)";
3719 + ticks[3] = have_mmcr1 ? run(do_read_pmc3, 0) : 0;
3720 + name[4] = "mfspr (pmc4)";
3721 + ticks[4] = have_mmcr1 ? run(do_read_pmc4, 0) : 0;
3722 + name[5] = "mfspr (mmcr0)";
3723 + ticks[5] = run(do_read_mmcr0, 0);
3724 + name[6] = "mfspr (mmcr1)";
3725 + ticks[6] = have_mmcr1 ? run(do_read_mmcr1, 0) : 0;
3726 + name[7] = "mtspr (pmc2)";
3727 + ticks[7] = run(do_write_pmc2, 0);
3728 + name[8] = "mtspr (pmc3)";
3729 + ticks[8] = have_mmcr1 ? run(do_write_pmc3, 0) : 0;
3730 + name[9] = "mtspr (pmc4)";
3731 + ticks[9] = have_mmcr1 ? run(do_write_pmc4, 0) : 0;
3732 + name[10] = "mtspr (mmcr1)";
3733 + ticks[10] = have_mmcr1 ? run(do_write_mmcr1, 0) : 0;
3734 + name[11] = "mtspr (mmcr0)";
3735 + ticks[11] = run(do_write_mmcr0, mmcr0);
3737 + loop = run(do_empty_loop, 0);
3739 + clear(have_mmcr1);
3741 + init_tests_message();
3742 + printk(KERN_INFO "PERFCTR INIT: NITER == %u\n", NITER);
3743 + printk(KERN_INFO "PERFCTR INIT: loop overhead is %u cycles\n", loop);
3744 + for(i = 0; i < ARRAY_SIZE(ticks); ++i) {
3748 + x = ((ticks[i] - loop) * 10) / NITER;
3749 + printk(KERN_INFO "PERFCTR INIT: %s cost is %u.%u cycles (%u total)\n",
3750 + name[i], x/10, x%10, ticks[i]);
3758 +void __init perfctr_ppc_init_tests(int have_mmcr1)
3760 + preempt_disable();
3761 + measure_overheads(have_mmcr1);
3764 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_setup.c
3765 ===================================================================
3766 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/x86_setup.c 1969-12-31 19:00:00.000000000 -0500
3767 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_setup.c 2004-11-18 20:59:11.000000000 -0500
3769 +/* $Id: x86_setup.c,v 1.47.2.2 2004/08/02 19:38:51 mikpe Exp $
3770 + * Performance-monitoring counters driver.
3771 + * x86/x86_64-specific kernel-resident code.
3773 + * Copyright (C) 1999-2004 Mikael Pettersson
3775 +#include <linux/config.h>
3776 +#include <linux/module.h>
3777 +#include <linux/init.h>
3778 +#include <linux/kernel.h>
3779 +#include <linux/sched.h>
3780 +#include <linux/interrupt.h>
3781 +#include <asm/processor.h>
3782 +#include <asm/perfctr.h>
3783 +#include <asm/fixmap.h>
3784 +#include <asm/apic.h>
3785 +#include "x86_compat.h"
3786 +#include "compat.h"
3788 +/* XXX: belongs to a virtual_compat.c file */
3789 +#if PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED && defined(CONFIG_PERFCTR_VIRTUAL) && LINUX_VERSION_CODE < KERNEL_VERSION(2,4,21) && !defined(HAVE_SET_CPUS_ALLOWED)
3791 + * set_cpus_allowed() - change a given task's processor affinity
3792 + * @p: task to bind
3793 + * @new_mask: bitmask of allowed processors
3795 + * Upon return, the task is running on a legal processor. Note the caller
3796 + * must have a valid reference to the task: it must not exit() prematurely.
3797 + * This call can sleep; do not hold locks on call.
3799 +void set_cpus_allowed(struct task_struct *p, unsigned long new_mask)
3801 + new_mask &= cpu_online_map;
3802 + BUG_ON(!new_mask);
3804 + /* This must be our own, safe, call from sys_vperfctr_control(). */
3806 + p->cpus_allowed = new_mask;
3809 + * If the task is on a no-longer-allowed processor, we need to move
3810 + * it. If the task is not current, then set need_resched and send
3811 + * its processor an IPI to reschedule.
3813 + if (!(p->cpus_runnable & p->cpus_allowed)) {
3814 + if (p != current) {
3815 + p->need_resched = 1;
3816 + smp_send_reschedule(p->processor);
3819 + * Wait until we are on a legal processor. If the task is
3820 + * current, then we should be on a legal processor the next
3821 + * time we reschedule. Otherwise, we need to wait for the IPI.
3823 + while (!(p->cpus_runnable & p->cpus_allowed))
3827 +EXPORT_SYMBOL(set_cpus_allowed);
3830 +#ifdef CONFIG_X86_LOCAL_APIC
3831 +static void perfctr_default_ihandler(unsigned long pc)
3835 +static perfctr_ihandler_t perfctr_ihandler = perfctr_default_ihandler;
3837 +asmlinkage void smp_perfctr_interrupt(struct pt_regs *regs)
3839 + /* PREEMPT note: invoked via an interrupt gate, which
3840 + masks interrupts. We're still on the originating CPU. */
3841 + /* XXX: recursive interrupts? delay the ACK, mask LVTPC, or queue? */
3844 + (*perfctr_ihandler)(instruction_pointer(regs));
3848 +void perfctr_cpu_set_ihandler(perfctr_ihandler_t ihandler)
3850 + perfctr_ihandler = ihandler ? ihandler : perfctr_default_ihandler;
3855 +extern unsigned int cpu_khz;
3857 +extern unsigned long cpu_khz;
3860 +/* Wrapper to avoid namespace clash in RedHat 8.0's 2.4.18-14 kernel. */
3861 +unsigned int perfctr_cpu_khz(void)
3866 +#ifdef CONFIG_PERFCTR_MODULE
3867 +EXPORT_SYMBOL_mmu_cr4_features;
3868 +EXPORT_SYMBOL(perfctr_cpu_khz);
3870 +#ifdef CONFIG_X86_LOCAL_APIC
3871 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6)
3872 +EXPORT_SYMBOL(nmi_perfctr_msr);
3875 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,67) && defined(CONFIG_PM)
3876 +EXPORT_SYMBOL(apic_pm_register);
3877 +EXPORT_SYMBOL(apic_pm_unregister);
3878 +EXPORT_SYMBOL(nmi_pmdev);
3881 +EXPORT_SYMBOL(perfctr_cpu_set_ihandler);
3882 +#endif /* CONFIG_X86_LOCAL_APIC */
3884 +#endif /* MODULE */
3885 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/global.h
3886 ===================================================================
3887 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/global.h 1969-12-31 19:00:00.000000000 -0500
3888 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/global.h 2004-11-18 20:59:11.000000000 -0500
3890 +/* $Id: global.h,v 1.7 2003/10/02 20:04:35 mikpe Exp $
3891 + * Global-mode performance-monitoring counters.
3893 + * Copyright (C) 2000-2003 Mikael Pettersson
3896 +#ifdef CONFIG_PERFCTR_GLOBAL
3897 +extern int gperfctr_ioctl(struct inode*, struct file*, unsigned int, unsigned long);
3898 +extern void gperfctr_init(void);
3900 +extern int gperfctr_ioctl(struct inode *inode, struct file *filp,
3901 + unsigned int cmd, unsigned long arg)
3905 +static inline void gperfctr_init(void) { }
3907 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/cpumask.h
3908 ===================================================================
3909 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/cpumask.h 1969-12-31 19:00:00.000000000 -0500
3910 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/cpumask.h 2004-11-18 20:59:11.000000000 -0500
3912 +/* $Id: cpumask.h,v 1.6.2.1 2004/07/12 21:09:45 mikpe Exp $
3913 + * Performance-monitoring counters driver.
3914 + * Partial simulation of cpumask_t on non-cpumask_t kernels.
3915 + * Extension to allow inspecting a cpumask_t as array of ulong.
3916 + * Appropriate definition of perfctr_cpus_forbidden_mask.
3918 + * Copyright (C) 2003-2004 Mikael Pettersson
3921 +/* 2.6.0-test4 changed set-of-CPUs values from ulong to cpumask_t */
3922 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
3924 +#if !defined(PERFCTR_HAVE_CPUMASK_T) && !defined(HAVE_CPUMASK_T)
3925 +typedef unsigned long cpumask_t;
3928 +/* RH/FC1 kernel 2.4.22-1.2115.nptl added cpumask_t, but with
3929 + an incomplete API and a broken cpus_and() [misspelled parameter
3930 + in its body]. Sigh.
3931 + Assume cpumask_t is unsigned long and use our own code. */
3933 +#define cpu_set(cpu, map) atomic_set_mask((1UL << (cpu)), &(map))
3935 +#define cpu_isset(cpu, map) ((map) & (1UL << (cpu)))
3937 +#define cpus_and(dst,src1,src2) do { (dst) = (src1) & (src2); } while(0)
3939 +#define cpus_clear(map) do { (map) = 0UL; } while(0)
3940 +#undef cpus_complement
3941 +#define cpus_complement(map) do { (map) = ~(map); } while(0)
3943 +#define cpus_empty(map) ((map) == 0UL)
3945 +#define cpus_equal(map1, map2) ((map1) == (map2))
3947 +#define cpus_addr(map) (&(map))
3949 +#undef CPU_MASK_NONE
3950 +#define CPU_MASK_NONE 0UL
3952 +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,1)
3954 +/* 2.6.1-rc1 introduced cpus_addr() */
3955 +#ifdef CPU_ARRAY_SIZE
3956 +#define cpus_addr(map) ((map).mask)
3958 +#define cpus_addr(map) (&(map))
3963 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) && !defined(cpus_andnot)
3964 +#define cpus_andnot(dst, src1, src2) \
3966 + cpumask_t _tmp2; \
3968 + cpus_complement(_tmp2); \
3969 + cpus_and((dst), (src1), _tmp2); \
3973 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8) && !defined(CONFIG_SMP)
3974 +#undef cpu_online_map
3975 +#define cpu_online_map cpumask_of_cpu(0)
3978 +#ifdef CPU_ARRAY_SIZE
3979 +#define PERFCTR_CPUMASK_NRLONGS CPU_ARRAY_SIZE
3981 +#define PERFCTR_CPUMASK_NRLONGS 1
3984 +/* `perfctr_cpus_forbidden_mask' used to be defined in <asm/perfctr.h>,
3985 + but cpumask_t compatibility issues forced it to be moved here. */
3986 +#if PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED
3987 +extern cpumask_t perfctr_cpus_forbidden_mask;
3988 +#define perfctr_cpu_is_forbidden(cpu) cpu_isset((cpu), perfctr_cpus_forbidden_mask)
3990 +#define perfctr_cpus_forbidden_mask CPU_MASK_NONE
3991 +#define perfctr_cpu_is_forbidden(cpu) 0 /* cpu_isset() needs an lvalue :-( */
3993 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_compat.h
3994 ===================================================================
3995 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/x86_compat.h 1969-12-31 19:00:00.000000000 -0500
3996 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_compat.h 2004-11-18 20:59:11.000000000 -0500
3998 +/* $Id: x86_compat.h,v 1.33 2004/02/29 16:03:03 mikpe Exp $
3999 + * Performance-monitoring counters driver.
4000 + * x86/x86_64-specific compatibility definitions for 2.4/2.6 kernels.
4002 + * Copyright (C) 2000-2004 Mikael Pettersson
4004 +#include <linux/config.h>
4005 +#include <linux/version.h>
4007 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,18)
4009 +/* missing from <asm-i386/cpufeature.h> */
4010 +#define cpu_has_msr boot_cpu_has(X86_FEATURE_MSR)
4014 +/* missing from <asm-i386/processor.h> */
4015 +#ifndef cpu_has_mmx /* added in 2.4.22-pre3 */
4016 +#define cpu_has_mmx (test_bit(X86_FEATURE_MMX, boot_cpu_data.x86_capability))
4018 +#define cpu_has_msr (test_bit(X86_FEATURE_MSR, boot_cpu_data.x86_capability))
4019 +#ifndef cpu_has_ht /* added in 2.4.22-pre3 */
4020 +#define cpu_has_ht (test_bit(28, boot_cpu_data.x86_capability))
4025 +/* irq_enter() and irq_exit() take two parameters in 2.4. However,
4026 + we only use them to disable preemption in the interrupt handler,
4027 + which isn't needed in non-preemptive 2.4 kernels. */
4028 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
4029 +#ifdef CONFIG_PREEMPT
4030 +#error "not yet ported to 2.4+PREEMPT"
4034 +#define irq_enter() do{}while(0)
4035 +#define irq_exit() do{}while(0)
4038 +extern unsigned int perfctr_cpu_khz(void);
4039 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/Makefile24
4040 ===================================================================
4041 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/Makefile24 1969-12-31 19:00:00.000000000 -0500
4042 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/Makefile24 2004-11-18 20:59:11.000000000 -0500
4044 +# $Id: Makefile24,v 1.7.2.1 2004/08/02 22:24:58 mikpe Exp $
4045 +# Performance-monitoring counters driver Makefile for 2.4 kernels.
4047 +# construct various object file lists:
4048 +# kernel-objs-y kernel objects exporting symbols
4049 +# y-objs-y kernel objects not exporting symbols
4050 +# m-objs-m perfctr.o if driver is module, empty otherwise
4051 +# driver-objs-y objects for perfctr.o module, or empty
4053 +# This also covers x86_64.
4054 +driver-objs-$(CONFIG_X86) := x86.o
4055 +tests-objs-$(CONFIG_X86) := x86_tests.o
4056 +kernel-objs-$(CONFIG_X86) := x86_setup.o
4058 +driver-objs-$(CONFIG_PPC32) := ppc.o
4059 +tests-objs-$(CONFIG_PPC32) := ppc_tests.o
4060 +kernel-objs-$(CONFIG_PPC32) := ppc_setup.o
4062 +driver-objs-y += init.o marshal.o
4063 +driver-objs-$(CONFIG_PERFCTR_INIT_TESTS) += $(tests-objs-y)
4064 +driver-objs-$(CONFIG_PERFCTR_VIRTUAL) += virtual.o
4065 +stub-objs-$(CONFIG_PERFCTR)-$(CONFIG_PERFCTR_VIRTUAL) := virtual_stub.o
4066 +driver-objs-$(CONFIG_PERFCTR_GLOBAL) += global.o
4067 +m-objs-$(CONFIG_PERFCTR) := perfctr.o
4068 +y-objs-$(CONFIG_PERFCTR) := $(driver-objs-y)
4069 +kernel-objs-y += $(stub-objs-m-y)
4071 +perfctr-objs := $(driver-objs-y)
4072 +obj-m += $(m-objs-m)
4074 +export-objs := $(kernel-objs-y)
4075 +O_TARGET := kperfctr.o
4076 +obj-y := $(kernel-objs-y) $(y-objs-y)
4077 +list-multi := perfctr.o
4079 +include $(TOPDIR)/Rules.make
4081 +perfctr.o: $(perfctr-objs)
4082 + $(LD) -r -o $@ $(perfctr-objs)
4083 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_tests.c
4084 ===================================================================
4085 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/x86_tests.c 1969-12-31 19:00:00.000000000 -0500
4086 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_tests.c 2004-11-18 20:59:11.000000000 -0500
4088 +/* $Id: x86_tests.c,v 1.23.2.5 2004/08/02 22:24:58 mikpe Exp $
4089 + * Performance-monitoring counters driver.
4090 + * Optional x86/x86_64-specific init-time tests.
4092 + * Copyright (C) 1999-2004 Mikael Pettersson
4094 +#include <linux/config.h>
4095 +#define __NO_VERSION__
4096 +#include <linux/module.h>
4097 +#include <linux/init.h>
4098 +#include <linux/sched.h>
4099 +#include <linux/fs.h>
4100 +#include <linux/perfctr.h>
4101 +#include <asm/msr.h>
4102 +#undef MSR_P6_PERFCTR0
4103 +#undef MSR_P4_IQ_CCCR0
4104 +#undef MSR_P4_CRU_ESCR0
4105 +#include <asm/fixmap.h>
4106 +#include <asm/apic.h>
4107 +#include "x86_compat.h"
4108 +#include "x86_tests.h"
4110 +#define MSR_P5_CESR 0x11
4111 +#define MSR_P5_CTR0 0x12
4112 +#define P5_CESR_VAL (0x16 | (3<<6))
4113 +#define MSR_P6_PERFCTR0 0xC1
4114 +#define MSR_P6_EVNTSEL0 0x186
4115 +#define P6_EVNTSEL0_VAL (0xC0 | (3<<16) | (1<<22))
4116 +#define MSR_K7_EVNTSEL0 0xC0010000
4117 +#define MSR_K7_PERFCTR0 0xC0010004
4118 +#define K7_EVNTSEL0_VAL (0xC0 | (3<<16) | (1<<22))
4119 +#define VC3_EVNTSEL1_VAL 0xC0
4120 +#define MSR_P4_IQ_COUNTER0 0x30C
4121 +#define MSR_P4_IQ_CCCR0 0x36C
4122 +#define MSR_P4_CRU_ESCR0 0x3B8
4123 +#define P4_CRU_ESCR0_VAL ((2<<25) | (1<<9) | (0x3<<2))
4124 +#define P4_IQ_CCCR0_VAL ((0x3<<16) | (4<<13) | (1<<12))
4127 +#define X2(S) S";"S
4128 +#define X8(S) X2(X2(X2(S)))
4131 +#define CR4MOV "movq"
4133 +#define CR4MOV "movl"
4136 +#ifndef CONFIG_X86_LOCAL_APIC
4138 +#define apic_write(reg,vector) do{}while(0)
4141 +#if !defined(__x86_64__)
4142 +/* Avoid speculative execution by the CPU */
4143 +extern inline void sync_core(void)
4146 + asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
4150 +static void __init do_rdpmc(unsigned pmc, unsigned unused2)
4153 + for(i = 0; i < NITER/8; ++i)
4154 + __asm__ __volatile__(X8("rdpmc") : : "c"(pmc) : "eax", "edx");
4157 +static void __init do_rdmsr(unsigned msr, unsigned unused2)
4160 + for(i = 0; i < NITER/8; ++i)
4161 + __asm__ __volatile__(X8("rdmsr") : : "c"(msr) : "eax", "edx");
4164 +static void __init do_wrmsr(unsigned msr, unsigned data)
4167 + for(i = 0; i < NITER/8; ++i)
4168 + __asm__ __volatile__(X8("wrmsr") : : "c"(msr), "a"(data), "d"(0));
4171 +static void __init do_rdcr4(unsigned unused1, unsigned unused2)
4174 + unsigned long dummy;
4175 + for(i = 0; i < NITER/8; ++i)
4176 + __asm__ __volatile__(X8(CR4MOV" %%cr4,%0") : "=r"(dummy));
4179 +static void __init do_wrcr4(unsigned cr4, unsigned unused2)
4182 + for(i = 0; i < NITER/8; ++i)
4183 + __asm__ __volatile__(X8(CR4MOV" %0,%%cr4") : : "r"((long)cr4));
4186 +static void __init do_rdtsc(unsigned unused1, unsigned unused2)
4189 + for(i = 0; i < NITER/8; ++i)
4190 + __asm__ __volatile__(X8("rdtsc") : : : "eax", "edx");
4193 +static void __init do_wrlvtpc(unsigned val, unsigned unused2)
4196 + for(i = 0; i < NITER/8; ++i) {
4197 + apic_write(APIC_LVTPC, val);
4198 + apic_write(APIC_LVTPC, val);
4199 + apic_write(APIC_LVTPC, val);
4200 + apic_write(APIC_LVTPC, val);
4201 + apic_write(APIC_LVTPC, val);
4202 + apic_write(APIC_LVTPC, val);
4203 + apic_write(APIC_LVTPC, val);
4204 + apic_write(APIC_LVTPC, val);
4208 +static void __init do_sync_core(unsigned unused1, unsigned unused2)
4211 + for(i = 0; i < NITER/8; ++i) {
4223 +static void __init do_empty_loop(unsigned unused1, unsigned unused2)
4226 + for(i = 0; i < NITER/8; ++i)
4227 + __asm__ __volatile__("" : : "c"(0));
4230 +static unsigned __init run(void (*doit)(unsigned, unsigned),
4231 + unsigned arg1, unsigned arg2)
4233 + unsigned start, dummy, stop;
4235 + rdtsc(start, dummy);
4236 + (*doit)(arg1, arg2); /* should take < 2^32 cycles to complete */
4238 + rdtsc(stop, dummy);
4239 + return stop - start;
4242 +static void __init init_tests_message(void)
4244 + printk(KERN_INFO "Please email the following PERFCTR INIT lines "
4245 + "to mikpe@csd.uu.se\n"
4246 + KERN_INFO "To remove this message, rebuild the driver "
4247 + "with CONFIG_PERFCTR_INIT_TESTS=n\n");
4248 + printk(KERN_INFO "PERFCTR INIT: vendor %u, family %u, model %u, stepping %u, clock %u kHz\n",
4249 + current_cpu_data.x86_vendor,
4250 + current_cpu_data.x86,
4251 + current_cpu_data.x86_model,
4252 + current_cpu_data.x86_mask,
4253 + perfctr_cpu_khz());
4257 +measure_overheads(unsigned msr_evntsel0, unsigned evntsel0, unsigned msr_perfctr0,
4258 + unsigned msr_cccr, unsigned cccr_val)
4261 + unsigned int loop, ticks[13];
4262 + const char *name[13];
4265 + wrmsr(msr_evntsel0, 0, 0);
4267 + wrmsr(msr_cccr, 0, 0);
4269 + name[0] = "rdtsc";
4270 + ticks[0] = run(do_rdtsc, 0, 0);
4271 + name[1] = "rdpmc";
4272 + ticks[1] = (perfctr_info.cpu_features & PERFCTR_FEATURE_RDPMC)
4273 + ? run(do_rdpmc,1,0) : 0;
4274 + name[2] = "rdmsr (counter)";
4275 + ticks[2] = msr_perfctr0 ? run(do_rdmsr, msr_perfctr0, 0) : 0;
4276 + name[3] = msr_cccr ? "rdmsr (escr)" : "rdmsr (evntsel)";
4277 + ticks[3] = msr_evntsel0 ? run(do_rdmsr, msr_evntsel0, 0) : 0;
4278 + name[4] = "wrmsr (counter)";
4279 + ticks[4] = msr_perfctr0 ? run(do_wrmsr, msr_perfctr0, 0) : 0;
4280 + name[5] = msr_cccr ? "wrmsr (escr)" : "wrmsr (evntsel)";
4281 + ticks[5] = msr_evntsel0 ? run(do_wrmsr, msr_evntsel0, evntsel0) : 0;
4282 + name[6] = "read cr4";
4283 + ticks[6] = run(do_rdcr4, 0, 0);
4284 + name[7] = "write cr4";
4285 + ticks[7] = run(do_wrcr4, read_cr4(), 0);
4286 + name[8] = "rdpmc (fast)";
4287 + ticks[8] = msr_cccr ? run(do_rdpmc, 0x80000001, 0) : 0;
4288 + name[9] = "rdmsr (cccr)";
4289 + ticks[9] = msr_cccr ? run(do_rdmsr, msr_cccr, 0) : 0;
4290 + name[10] = "wrmsr (cccr)";
4291 + ticks[10] = msr_cccr ? run(do_wrmsr, msr_cccr, cccr_val) : 0;
4292 + name[11] = "write LVTPC";
4293 + ticks[11] = (perfctr_info.cpu_features & PERFCTR_FEATURE_PCINT)
4294 + ? run(do_wrlvtpc, APIC_DM_NMI|APIC_LVT_MASKED, 0) : 0;
4295 + name[12] = "sync_core";
4296 + ticks[12] = run(do_sync_core, 0, 0);
4298 + loop = run(do_empty_loop, 0, 0);
4301 + wrmsr(msr_evntsel0, 0, 0);
4303 + wrmsr(msr_cccr, 0, 0);
4305 + init_tests_message();
4306 + printk(KERN_INFO "PERFCTR INIT: NITER == %u\n", NITER);
4307 + printk(KERN_INFO "PERFCTR INIT: loop overhead is %u cycles\n", loop);
4308 + for(i = 0; i < ARRAY_SIZE(ticks); ++i) {
4312 + x = ((ticks[i] - loop) * 10) / NITER;
4313 + printk(KERN_INFO "PERFCTR INIT: %s cost is %u.%u cycles (%u total)\n",
4314 + name[i], x/10, x%10, ticks[i]);
4319 +static inline void perfctr_p5_init_tests(void)
4321 + measure_overheads(MSR_P5_CESR, P5_CESR_VAL, MSR_P5_CTR0, 0, 0);
4324 +static inline void perfctr_p6_init_tests(void)
4326 + measure_overheads(MSR_P6_EVNTSEL0, P6_EVNTSEL0_VAL, MSR_P6_PERFCTR0, 0, 0);
4329 +#if !defined(CONFIG_X86_TSC)
4330 +static inline void perfctr_c6_init_tests(void)
4332 + unsigned int cesr, dummy;
4334 + rdmsr(MSR_P5_CESR, cesr, dummy);
4335 + init_tests_message();
4336 + printk(KERN_INFO "PERFCTR INIT: boot CESR == %#08x\n", cesr);
4340 +static inline void perfctr_vc3_init_tests(void)
4342 + measure_overheads(MSR_P6_EVNTSEL0+1, VC3_EVNTSEL1_VAL, MSR_P6_PERFCTR0+1, 0, 0);
4344 +#endif /* !__x86_64__ */
4346 +static inline void perfctr_p4_init_tests(void)
4348 + measure_overheads(MSR_P4_CRU_ESCR0, P4_CRU_ESCR0_VAL, MSR_P4_IQ_COUNTER0,
4349 + MSR_P4_IQ_CCCR0, P4_IQ_CCCR0_VAL);
4352 +static inline void perfctr_k7_init_tests(void)
4354 + measure_overheads(MSR_K7_EVNTSEL0, K7_EVNTSEL0_VAL, MSR_K7_PERFCTR0, 0, 0);
4357 +static inline void perfctr_generic_init_tests(void)
4359 + measure_overheads(0, 0, 0, 0, 0);
4362 +enum perfctr_x86_tests_type perfctr_x86_tests_type __initdata = PTT_UNKNOWN;
4364 +void __init perfctr_x86_init_tests(void)
4366 + switch (perfctr_x86_tests_type) {
4368 + case PTT_P5: /* Intel P5, P5MMX; Cyrix 6x86MX, MII, III */
4369 + perfctr_p5_init_tests();
4371 + case PTT_P6: /* Intel PPro, PII, PIII, PENTM */
4372 + perfctr_p6_init_tests();
4374 +#if !defined(CONFIG_X86_TSC)
4375 + case PTT_WINCHIP: /* WinChip C6, 2, 3 */
4376 + perfctr_c6_init_tests();
4379 + case PTT_VC3: /* VIA C3 */
4380 + perfctr_vc3_init_tests();
4382 +#endif /* !__x86_64__ */
4383 + case PTT_P4: /* Intel P4 */
4384 + perfctr_p4_init_tests();
4386 + case PTT_AMD: /* AMD K7, K8 */
4387 + perfctr_k7_init_tests();
4390 + perfctr_generic_init_tests();
4393 + printk(KERN_INFO "%s: unknown CPU type %u\n",
4394 + __FUNCTION__, perfctr_x86_tests_type);
4398 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/ppc.c
4399 ===================================================================
4400 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/ppc.c 1969-12-31 19:00:00.000000000 -0500
4401 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/ppc.c 2004-11-18 20:59:11.000000000 -0500
4403 +/* $Id: ppc.c,v 1.3.2.8 2004/10/19 15:18:21 mikpe Exp $
4404 + * PPC32 performance-monitoring counters driver.
4406 + * Copyright (C) 2004 Mikael Pettersson
4408 +#include <linux/config.h>
4409 +#define __NO_VERSION__
4410 +#include <linux/module.h>
4411 +#include <linux/init.h>
4412 +#include <linux/sched.h>
4413 +#include <linux/fs.h>
4414 +#include <linux/perfctr.h>
4415 +#include <asm/prom.h>
4416 +#include <asm/time.h> /* tb_ticks_per_jiffy, get_tbl() */
4418 +#include "compat.h"
4419 +#include "ppc_compat.h"
4420 +#include "ppc_tests.h"
4422 +/* Support for lazy evntsel and perfctr SPR updates. */
4423 +struct per_cpu_cache { /* roughly a subset of perfctr_cpu_state */
4425 + unsigned int id; /* cache owner id */
4427 + /* Physically indexed cache of the MMCRs. */
4428 + unsigned int ppc_mmcr[3];
4429 +} ____cacheline_aligned;
4430 +static struct per_cpu_cache per_cpu_cache[NR_CPUS] __cacheline_aligned;
4431 +#define get_cpu_cache() (&per_cpu_cache[smp_processor_id()])
4433 +/* Structure for counter snapshots, as 32-bit values. */
4434 +struct perfctr_low_ctrs {
4436 + unsigned int pmc[6];
4443 + PM_750, /* XXX: Minor event set diffs between IBM and Moto. */
4447 +static enum pm_type pm_type;
4449 +/* Bits users shouldn't set in control.ppc.mmcr0:
4450 + * - PMXE because we don't yet support overflow interrupts
4451 + * - PMC1SEL/PMC2SEL because event selectors are in control.evntsel[]
4453 +#define MMCR0_RESERVED (MMCR0_PMXE | MMCR0_PMC1SEL | MMCR0_PMC2SEL)
4455 +static unsigned int new_id(void)
4457 + static spinlock_t lock = SPIN_LOCK_UNLOCKED;
4458 + static unsigned int counter;
4463 + spin_unlock(&lock);
4467 +#ifndef PERFCTR_INTERRUPT_SUPPORT
4468 +#define perfctr_cstatus_has_ictrs(cstatus) 0
4471 +#if defined(CONFIG_SMP) && defined(PERFCTR_INTERRUPT_SUPPORT)
4474 +set_isuspend_cpu(struct perfctr_cpu_state *state, int cpu)
4476 + state->k1.isuspend_cpu = cpu;
4480 +is_isuspend_cpu(const struct perfctr_cpu_state *state, int cpu)
4482 + return state->k1.isuspend_cpu == cpu;
4485 +static inline void clear_isuspend_cpu(struct perfctr_cpu_state *state)
4487 + state->k1.isuspend_cpu = NR_CPUS;
4491 +static inline void set_isuspend_cpu(struct perfctr_cpu_state *state, int cpu) { }
4492 +static inline int is_isuspend_cpu(const struct perfctr_cpu_state *state, int cpu) { return 1; }
4493 +static inline void clear_isuspend_cpu(struct perfctr_cpu_state *state) { }
4496 +/* The ppc driver internally uses cstatus & (1<<30) to record that
4497 + a context has an asynchronously changing MMCR0. */
4498 +static inline unsigned int perfctr_cstatus_set_mmcr0_quirk(unsigned int cstatus)
4500 + return cstatus | (1 << 30);
4503 +static inline int perfctr_cstatus_has_mmcr0_quirk(unsigned int cstatus)
4505 + return cstatus & (1 << 30);
4508 +/****************************************************************
4510 + * Driver procedures. *
4512 + ****************************************************************/
4515 + * The PowerPC 604/750/74xx family.
4519 + * - Per counter event selection data in subfields of control registers.
4520 + * MMCR0 contains both global control and PMC1/PMC2 event selectors.
4521 + * - Overflow interrupt support is present in all processors, but an
4522 + * erratum makes it difficult to use in 750/7400/7410 processors.
4523 + * - There is no concept of per-counter qualifiers:
4524 + * - User-mode/supervisor-mode restrictions are global.
4525 + * - Two groups of counters, PMC1 and PMC2-PMC<highest>. Each group
4526 + * has a single overflow interrupt/event enable/disable flag.
4527 + * - The instructions used to read (mfspr) and write (mtspr) the control
4528 + * and counter registers (SPRs) only support hardcoded register numbers.
4529 + * There is no support for accessing an SPR via a runtime value.
4530 + * - Each counter supports its own unique set of events. However, events
4531 + * 0-1 are common for PMC1-PMC4, and events 2-4 are common for PMC1-PMC4.
4532 + * - There is no separate high-resolution core clock counter.
4533 + * The time-base counter is available, but it typically runs an order of
4534 + * magnitude slower than the core clock.
4535 + * Any performance counter can be programmed to count core clocks, but
4536 + * doing this (a) reserves one PMC, and (b) needs indirect accesses
4537 + * since the SPR number in general isn't known at compile-time.
4541 + * - The driver currently does not support performance monitor interrupts,
4542 + * mostly because of the 750/7400/7410 erratum. Working around it would
4543 + * require disabling the decrementer interrupt, reserving a performance
4544 + * counter and setting it up for TBL bit-flip events, and having the PMI
4545 + * handler invoke the decrementer handler.
4549 + * 604 has MMCR0, PMC1, PMC2, SIA, and SDA.
4551 + * MMCR0[THRESHOLD] is not automatically multiplied.
4553 + * On the 604, software must always reset MMCR0[ENINT] after
4554 + * taking a PMI. This is not the case for the 604e.
4558 + * 604e adds MMCR1, PMC3, and PMC4.
4559 + * Bus-to-core multiplier is available via HID1[PLL_CFG].
4561 + * MMCR0[THRESHOLD] is automatically multiplied by 4.
4563 + * When the 604e vectors to the PMI handler, it automatically
4564 + * clears any pending PMIs. Unlike the 604, the 604e does not
4565 + * require MMCR0[ENINT] to be cleared (and possibly reset)
4566 + * before external interrupts can be re-enabled.
4570 + * 750 adds user-readable MMCRn/PMCn/SIA registers, and removes SDA.
4572 + * MMCR0[THRESHOLD] is not automatically multiplied.
4574 + * Motorola MPC750UM.pdf, page C-78, states: "The performance monitor
4575 + * of the MPC755 functions the same as that of the MPC750, (...), except
4576 + * that for both the MPC750 and MPC755, no combination of the thermal
4577 + * assist unit, the decrementer register, and the performance monitor
4578 + * can be used at any one time. If exceptions for any two of these
4579 + * functional blocks are enabled together, multiple exceptions caused
4580 + * by any of these three blocks cause unpredictable results."
4582 + * IBM 750CXe_Err_DD2X.pdf, Erratum #13, states that a PMI which
4583 + * occurs immediately after a delayed decrementer exception can
4584 + * corrupt SRR0, causing the processor to hang. It also states that
4585 + * PMIs via TB bit transitions can be used to simulate the decrementer.
4587 + * 750FX adds dual-PLL support and programmable core frequency switching.
4591 + * 7400 adds MMCR2 and BAMR.
4593 + * MMCR0[THRESHOLD] is multiplied by 2 or 32, as specified
4594 + * by MMCR2[THRESHMULT].
4596 + * 74xx changes the semantics of several MMCR0 control bits,
4597 + * compared to 604/750.
4599 + * PPC7410 Erratum No. 10: Like the MPC750 TAU/DECR/PMI erratum.
4600 + * Erratum No. 14 marks TAU as unsupported in 7410, but this leaves
4601 + * perfmon and decrementer interrupts as being mutually exclusive.
4602 + * Affects PPC7410 1.0-1.2 (PVR 0x800C1100-0x800C1102). 1.3 and up
4603 + * (PVR 0x800C1103 up) are Ok.
4605 + * 7450 adds PMC5 and PMC6.
4607 + * 7455/7445 V3.3 (PVR 80010303) and later use the 7457 PLL table,
4608 + * earlier revisions use the 7450 PLL table
4611 +static inline unsigned int read_pmc(unsigned int pmc)
4614 + default: /* impossible, but silences gcc warning */
4616 + return mfspr(SPRN_PMC1);
4618 + return mfspr(SPRN_PMC2);
4620 + return mfspr(SPRN_PMC3);
4622 + return mfspr(SPRN_PMC4);
4624 + return mfspr(SPRN_PMC5);
4626 + return mfspr(SPRN_PMC6);
4630 +static void ppc_read_counters(struct perfctr_cpu_state *state,
4631 + struct perfctr_low_ctrs *ctrs)
4633 + unsigned int cstatus, nrctrs, i;
4635 + cstatus = state->cstatus;
4636 + if (perfctr_cstatus_has_tsc(cstatus))
4637 + ctrs->tsc = get_tbl();
4638 + nrctrs = perfctr_cstatus_nractrs(cstatus);
4639 + for(i = 0; i < nrctrs; ++i) {
4640 + unsigned int pmc = state->pmc[i].map;
4641 + ctrs->pmc[i] = read_pmc(pmc);
4645 +static unsigned int pmc_max_event(unsigned int pmc)
4648 + default: /* impossible, but silences gcc warning */
4664 +static unsigned int get_nr_pmcs(void)
4666 + switch (pm_type) {
4675 + default: /* PM_NONE, but silences gcc warning */
4680 +static int ppc_check_control(struct perfctr_cpu_state *state)
4682 + unsigned int i, nrctrs, pmc_mask, pmc;
4683 + unsigned int nr_pmcs, evntsel[6];
4685 + nr_pmcs = get_nr_pmcs();
4686 + nrctrs = state->control.nractrs;
4687 + if (state->control.nrictrs || nrctrs > nr_pmcs)
4691 + memset(evntsel, 0, sizeof evntsel);
4692 + for(i = 0; i < nrctrs; ++i) {
4693 + pmc = state->control.pmc_map[i];
4694 + state->pmc[i].map = pmc;
4695 + if (pmc >= nr_pmcs || (pmc_mask & (1<<pmc)))
4697 + pmc_mask |= (1<<pmc);
4699 + evntsel[pmc] = state->control.evntsel[i];
4700 + if (evntsel[pmc] > pmc_max_event(pmc))
4704 + switch (pm_type) {
4707 + if (state->control.ppc.mmcr2 & MMCR2_RESERVED)
4709 + state->ppc_mmcr[2] = state->control.ppc.mmcr2;
4712 + if (state->control.ppc.mmcr2)
4714 + state->ppc_mmcr[2] = 0;
4717 + if (state->control.ppc.mmcr0 & MMCR0_RESERVED)
4719 + state->ppc_mmcr[0] = (state->control.ppc.mmcr0
4720 + | (evntsel[0] << (31-25))
4721 + | (evntsel[1] << (31-31)));
4723 + state->ppc_mmcr[1] = (( evntsel[2] << (31-4))
4724 + | (evntsel[3] << (31-9))
4725 + | (evntsel[4] << (31-14))
4726 + | (evntsel[5] << (31-20)));
4728 + state->k1.id = new_id();
4731 + * MMCR0[FC] and MMCR0[TRIGGER] may change on 74xx if FCECE or
4732 + * TRIGGER is set. At suspends we must read MMCR0 back into
4733 + * the state and the cache and then freeze the counters, and
4734 + * at resumes we must unfreeze the counters and reload MMCR0.
4736 + switch (pm_type) {
4739 + if (state->ppc_mmcr[0] & (MMCR0_FCECE | MMCR0_TRIGGER))
4740 + state->cstatus = perfctr_cstatus_set_mmcr0_quirk(state->cstatus);
4748 +#ifdef PERFCTR_INTERRUPT_SUPPORT
4749 +static void ppc_isuspend(struct perfctr_cpu_state *state)
4754 +static void ppc_iresume(const struct perfctr_cpu_state *state)
4760 +static void ppc_write_control(const struct perfctr_cpu_state *state)
4762 + struct per_cpu_cache *cache;
4763 + unsigned int value;
4765 + cache = get_cpu_cache();
4766 + if (cache->k1.id == state->k1.id)
4769 + * Order matters here: update threshmult and event
4770 + * selectors before updating global control, which
4771 + * potentially enables PMIs.
4773 + * Since mtspr doesn't accept a runtime value for the
4774 + * SPR number, unroll the loop so each mtspr targets
4777 + * For processors without MMCR2, we ensure that the
4778 + * cache and the state indicate the same value for it,
4779 + * preventing any actual mtspr to it. Ditto for MMCR1.
4781 + value = state->ppc_mmcr[2];
4782 + if (value != cache->ppc_mmcr[2]) {
4783 + cache->ppc_mmcr[2] = value;
4784 + mtspr(SPRN_MMCR2, value);
4786 + value = state->ppc_mmcr[1];
4787 + if (value != cache->ppc_mmcr[1]) {
4788 + cache->ppc_mmcr[1] = value;
4789 + mtspr(SPRN_MMCR1, value);
4791 + value = state->ppc_mmcr[0];
4792 + if (value != cache->ppc_mmcr[0]) {
4793 + cache->ppc_mmcr[0] = value;
4794 + mtspr(SPRN_MMCR0, value);
4796 + cache->k1.id = state->k1.id;
4799 +static void ppc_clear_counters(void)
4801 + switch (pm_type) {
4804 + mtspr(SPRN_MMCR2, 0);
4805 + mtspr(SPRN_BAMR, 0);
4808 + mtspr(SPRN_MMCR1, 0);
4810 + mtspr(SPRN_MMCR0, 0);
4814 + switch (pm_type) {
4816 + mtspr(SPRN_PMC6, 0);
4817 + mtspr(SPRN_PMC5, 0);
4821 + mtspr(SPRN_PMC4, 0);
4822 + mtspr(SPRN_PMC3, 0);
4824 + mtspr(SPRN_PMC2, 0);
4825 + mtspr(SPRN_PMC1, 0);
4832 + * Driver methods, internal and exported.
4835 +static void perfctr_cpu_write_control(const struct perfctr_cpu_state *state)
4837 + return ppc_write_control(state);
4840 +static void perfctr_cpu_read_counters(struct perfctr_cpu_state *state,
4841 + struct perfctr_low_ctrs *ctrs)
4843 + return ppc_read_counters(state, ctrs);
4846 +#ifdef PERFCTR_INTERRUPT_SUPPORT
4847 +static void perfctr_cpu_isuspend(struct perfctr_cpu_state *state)
4849 + return ppc_isuspend(state);
4852 +static void perfctr_cpu_iresume(const struct perfctr_cpu_state *state)
4854 + return ppc_iresume(state);
4857 +/* Call perfctr_cpu_ireload() just before perfctr_cpu_resume() to
4858 + bypass internal caching and force a reload if the I-mode PMCs. */
4859 +void perfctr_cpu_ireload(struct perfctr_cpu_state *state)
4862 + clear_isuspend_cpu(state);
4864 + get_cpu_cache()->k1.id = 0;
4868 +/* PRE: the counters have been suspended and sampled by perfctr_cpu_suspend() */
4869 +unsigned int perfctr_cpu_identify_overflow(struct perfctr_cpu_state *state)
4871 + unsigned int cstatus, nrctrs, pmc, pmc_mask;
4873 + cstatus = state->cstatus;
4874 + pmc = perfctr_cstatus_nractrs(cstatus);
4875 + nrctrs = perfctr_cstatus_nrctrs(cstatus);
4877 + for(pmc_mask = 0; pmc < nrctrs; ++pmc) {
4878 + if ((int)state->pmc[pmc].start < 0) { /* PPC-specific */
4879 + /* XXX: "+=" to correct for overshots */
4880 + state->pmc[pmc].start = state->control.ireset[pmc];
4881 + pmc_mask |= (1 << pmc);
4884 + /* XXX: if pmc_mask == 0, then it must have been a TBL bit flip */
4885 + /* XXX: HW cleared MMCR0[ENINT]. We presumably cleared the entire
4886 + MMCR0, so the re-enable occurs automatically later, no? */
4890 +static inline int check_ireset(const struct perfctr_cpu_state *state)
4892 + unsigned int nrctrs, i;
4894 + i = state->control.nractrs;
4895 + nrctrs = i + state->control.nrictrs;
4896 + for(; i < nrctrs; ++i)
4897 + if (state->control.ireset[i] < 0) /* PPC-specific */
4902 +static inline void setup_imode_start_values(struct perfctr_cpu_state *state)
4904 + unsigned int cstatus, nrctrs, i;
4906 + cstatus = state->cstatus;
4907 + nrctrs = perfctr_cstatus_nrctrs(cstatus);
4908 + for(i = perfctr_cstatus_nractrs(cstatus); i < nrctrs; ++i)
4909 + state->pmc[i].start = state->control.ireset[i];
4912 +#else /* PERFCTR_INTERRUPT_SUPPORT */
4913 +static inline void perfctr_cpu_isuspend(struct perfctr_cpu_state *state) { }
4914 +static inline void perfctr_cpu_iresume(const struct perfctr_cpu_state *state) { }
4915 +static inline int check_ireset(const struct perfctr_cpu_state *state) { return 0; }
4916 +static inline void setup_imode_start_values(struct perfctr_cpu_state *state) { }
4917 +#endif /* PERFCTR_INTERRUPT_SUPPORT */
4919 +static int check_control(struct perfctr_cpu_state *state)
4921 + return ppc_check_control(state);
4924 +int perfctr_cpu_update_control(struct perfctr_cpu_state *state, int is_global)
4928 + clear_isuspend_cpu(state);
4929 + state->cstatus = 0;
4931 + /* disallow i-mode counters if we cannot catch the interrupts */
4932 + if (!(perfctr_info.cpu_features & PERFCTR_FEATURE_PCINT)
4933 + && state->control.nrictrs)
4936 + err = check_ireset(state);
4939 + err = check_control(state); /* may initialise state->cstatus */
4942 + state->cstatus |= perfctr_mk_cstatus(state->control.tsc_on,
4943 + state->control.nractrs,
4944 + state->control.nrictrs);
4945 + setup_imode_start_values(state);
4949 +void perfctr_cpu_suspend(struct perfctr_cpu_state *state)
4951 + unsigned int i, cstatus, nractrs;
4952 + struct perfctr_low_ctrs now;
4954 + if (perfctr_cstatus_has_mmcr0_quirk(state->cstatus)) {
4955 + unsigned int mmcr0 = mfspr(SPRN_MMCR0);
4956 + mtspr(SPRN_MMCR0, mmcr0 | MMCR0_FC);
4957 + get_cpu_cache()->ppc_mmcr[0] = mmcr0 | MMCR0_FC;
4958 + state->ppc_mmcr[0] = mmcr0;
4960 + if (perfctr_cstatus_has_ictrs(state->cstatus))
4961 + perfctr_cpu_isuspend(state);
4962 + perfctr_cpu_read_counters(state, &now);
4963 + cstatus = state->cstatus;
4964 + if (perfctr_cstatus_has_tsc(cstatus))
4965 + state->tsc_sum += now.tsc - state->tsc_start;
4966 + nractrs = perfctr_cstatus_nractrs(cstatus);
4967 + for(i = 0; i < nractrs; ++i)
4968 + state->pmc[i].sum += now.pmc[i] - state->pmc[i].start;
4971 +void perfctr_cpu_resume(struct perfctr_cpu_state *state)
4973 + if (perfctr_cstatus_has_ictrs(state->cstatus))
4974 + perfctr_cpu_iresume(state);
4975 + if (perfctr_cstatus_has_mmcr0_quirk(state->cstatus))
4976 + get_cpu_cache()->k1.id = 0; /* force reload of MMCR0 */
4977 + perfctr_cpu_write_control(state);
4978 + //perfctr_cpu_read_counters(state, &state->start);
4980 + struct perfctr_low_ctrs now;
4981 + unsigned int i, cstatus, nrctrs;
4982 + perfctr_cpu_read_counters(state, &now);
4983 + cstatus = state->cstatus;
4984 + if (perfctr_cstatus_has_tsc(cstatus))
4985 + state->tsc_start = now.tsc;
4986 + nrctrs = perfctr_cstatus_nractrs(cstatus);
4987 + for(i = 0; i < nrctrs; ++i)
4988 + state->pmc[i].start = now.pmc[i];
4990 + /* XXX: if (SMP && start.tsc == now.tsc) ++now.tsc; */
4993 +void perfctr_cpu_sample(struct perfctr_cpu_state *state)
4995 + unsigned int i, cstatus, nractrs;
4996 + struct perfctr_low_ctrs now;
4998 + perfctr_cpu_read_counters(state, &now);
4999 + cstatus = state->cstatus;
5000 + if (perfctr_cstatus_has_tsc(cstatus)) {
5001 + state->tsc_sum += now.tsc - state->tsc_start;
5002 + state->tsc_start = now.tsc;
5004 + nractrs = perfctr_cstatus_nractrs(cstatus);
5005 + for(i = 0; i < nractrs; ++i) {
5006 + state->pmc[i].sum += now.pmc[i] - state->pmc[i].start;
5007 + state->pmc[i].start = now.pmc[i];
5011 +static void perfctr_cpu_clear_counters(void)
5013 + struct per_cpu_cache *cache;
5015 + cache = get_cpu_cache();
5016 + memset(cache, 0, sizeof *cache);
5017 + cache->k1.id = -1;
5019 + ppc_clear_counters();
5022 +/****************************************************************
5024 + * Processor detection and initialisation procedures. *
5026 + ****************************************************************/
5028 +/* Derive CPU core frequency from TB frequency and PLL_CFG. */
5031 + PLL_NONE, /* for e.g. 604 which has no HID1[PLL_CFG] */
5040 +/* These are the known bus-to-core ratios, indexed by PLL_CFG.
5041 + Multiplied by 2 since half-multiplier steps are present. */
5043 +static unsigned char cfg_ratio_604e[16] __initdata = { // *2
5044 + 2, 2, 14, 2, 4, 13, 5, 9,
5045 + 6, 11, 8, 10, 3, 12, 7, 0
5048 +static unsigned char cfg_ratio_750[16] __initdata = { // *2
5049 + 5, 15, 14, 2, 4, 13, 20, 9, // 0b0110 is 18 if L1_TSTCLK=0, but that is abnormal
5050 + 6, 11, 8, 10, 16, 12, 7, 0
5053 +static unsigned char cfg_ratio_750FX[32] __initdata = { // *2
5054 + 0, 0, 2, 2, 4, 5, 6, 7,
5055 + 8, 9, 10, 11, 12, 13, 14, 15,
5056 + 16, 17, 18, 19, 20, 22, 24, 26,
5057 + 28, 30, 32, 34, 36, 38, 40, 0
5060 +static unsigned char cfg_ratio_7400[16] __initdata = { // *2
5061 + 18, 15, 14, 2, 4, 13, 5, 9,
5062 + 6, 11, 8, 10, 16, 12, 7, 0
5065 +static unsigned char cfg_ratio_7450[32] __initdata = { // *2
5066 + 1, 0, 15, 30, 14, 0, 2, 0,
5067 + 4, 0, 13, 26, 5, 0, 9, 18,
5068 + 6, 0, 11, 22, 8, 20, 10, 24,
5069 + 16, 28, 12, 32, 7, 0, 0, 0
5072 +static unsigned char cfg_ratio_7457[32] __initdata = { // *2
5073 + 23, 34, 15, 30, 14, 36, 2, 40,
5074 + 4, 42, 13, 26, 17, 48, 19, 18,
5075 + 6, 21, 11, 22, 8, 20, 10, 24,
5076 + 16, 28, 12, 32, 27, 56, 0, 25
5079 +static unsigned int __init tb_to_core_ratio(enum pll_type pll_type)
5081 + unsigned char *cfg_ratio;
5082 + unsigned int shift = 28, mask = 0xF, hid1, pll_cfg, ratio;
5084 + switch (pll_type) {
5086 + cfg_ratio = cfg_ratio_604e;
5089 + cfg_ratio = cfg_ratio_750;
5092 + cfg_ratio = cfg_ratio_750FX;
5093 + hid1 = mfspr(SPRN_HID1);
5094 + switch ((hid1 >> 16) & 0x3) { /* HID1[PI0,PS] */
5095 + case 0: /* PLL0 with external config */
5096 + shift = 31-4; /* access HID1[PCE] */
5098 + case 2: /* PLL0 with internal config */
5099 + shift = 31-20; /* access HID1[PC0] */
5101 + case 1: case 3: /* PLL1 */
5102 + shift = 31-28; /* access HID1[PC1] */
5108 + cfg_ratio = cfg_ratio_7400;
5111 + cfg_ratio = cfg_ratio_7450;
5116 + cfg_ratio = cfg_ratio_7457;
5123 + hid1 = mfspr(SPRN_HID1);
5124 + pll_cfg = (hid1 >> shift) & mask;
5125 + ratio = cfg_ratio[pll_cfg];
5127 + printk(KERN_WARNING "perfctr: unknown PLL_CFG 0x%x\n", pll_cfg);
5128 + return (4/2) * ratio;
5131 +static unsigned int __init pll_to_core_khz(enum pll_type pll_type)
5133 + unsigned int tb_to_core = tb_to_core_ratio(pll_type);
5134 + perfctr_info.tsc_to_cpu_mult = tb_to_core;
5135 + return tb_ticks_per_jiffy * tb_to_core * (HZ/10) / (1000/10);
5138 +/* Extract core and timebase frequencies from Open Firmware. */
5140 +static unsigned int __init of_to_core_khz(void)
5142 + struct device_node *cpu;
5143 + unsigned int *fp, core, tb;
5145 + cpu = find_type_devices("cpu");
5148 + fp = (unsigned int*)get_property(cpu, "clock-frequency", NULL);
5149 + if (!fp || !(core = *fp))
5151 + fp = (unsigned int*)get_property(cpu, "timebase-frequency", NULL);
5152 + if (!fp || !(tb = *fp))
5154 + perfctr_info.tsc_to_cpu_mult = core / tb;
5155 + return core / 1000;
5158 +static unsigned int __init detect_cpu_khz(enum pll_type pll_type)
5162 + khz = pll_to_core_khz(pll_type);
5166 + khz = of_to_core_khz();
5170 + printk(KERN_WARNING "perfctr: unable to determine CPU speed\n");
5174 +static int __init known_init(void)
5176 + static char known_name[] __initdata = "PowerPC 60x/7xx/74xx";
5177 + unsigned int features;
5178 + enum pll_type pll_type;
5182 + features = PERFCTR_FEATURE_RDTSC | PERFCTR_FEATURE_RDPMC;
5184 + pvr = mfspr(SPRN_PVR);
5185 + switch (PVR_VER(pvr)) {
5186 + case 0x0004: /* 604 */
5188 + pll_type = PLL_NONE;
5189 + features = PERFCTR_FEATURE_RDTSC;
5192 + case 0x0009: /* 604e; */
5193 + case 0x000A: /* 604ev */
5194 + pm_type = PM_604e;
5195 + pll_type = PLL_604e;
5196 + features = PERFCTR_FEATURE_RDTSC;
5198 + case 0x0008: /* 750/740 */
5200 + pll_type = PLL_750;
5202 + case 0x7000: case 0x7001: /* IBM750FX */
5203 + case 0x7002: /* IBM750GX */
5205 + pll_type = PLL_750FX;
5207 + case 0x000C: /* 7400 */
5208 + pm_type = PM_7400;
5209 + pll_type = PLL_7400;
5211 + case 0x800C: /* 7410 */
5212 + pm_type = PM_7400;
5213 + pll_type = PLL_7400;
5215 + case 0x8000: /* 7451/7441 */
5216 + pm_type = PM_7450;
5217 + pll_type = PLL_7450;
5219 + case 0x8001: /* 7455/7445 */
5220 + pm_type = PM_7450;
5221 + pll_type = ((pvr & 0xFFFF) < 0x0303) ? PLL_7450 : PLL_7457;
5223 + case 0x8002: /* 7457/7447 */
5224 + pm_type = PM_7450;
5225 + pll_type = PLL_7457;
5230 + perfctr_info.cpu_features = features;
5231 + perfctr_info.cpu_type = 0; /* user-space should inspect PVR */
5232 + perfctr_cpu_name = known_name;
5233 + perfctr_info.cpu_khz = detect_cpu_khz(pll_type);
5234 + perfctr_ppc_init_tests(have_mmcr1);
5238 +static int __init unknown_init(void)
5240 + static char unknown_name[] __initdata = "Generic PowerPC with TB";
5243 + khz = detect_cpu_khz(PLL_NONE);
5246 + perfctr_info.cpu_features = PERFCTR_FEATURE_RDTSC;
5247 + perfctr_info.cpu_type = 0;
5248 + perfctr_cpu_name = unknown_name;
5249 + perfctr_info.cpu_khz = khz;
5250 + pm_type = PM_NONE;
5254 +static void perfctr_cpu_clear_one(void *ignore)
5256 + /* PREEMPT note: when called via on_each_cpu(),
5257 + this is in IRQ context with preemption disabled. */
5258 + perfctr_cpu_clear_counters();
5261 +static void perfctr_cpu_reset(void)
5263 + on_each_cpu(perfctr_cpu_clear_one, NULL, 1, 1);
5264 + perfctr_cpu_set_ihandler(NULL);
5267 +int __init perfctr_cpu_init(void)
5271 + perfctr_info.cpu_features = 0;
5273 + err = known_init();
5275 + err = unknown_init();
5280 + perfctr_cpu_reset();
5285 +void __exit perfctr_cpu_exit(void)
5287 + perfctr_cpu_reset();
5290 +/****************************************************************
5292 + * Hardware reservation. *
5294 + ****************************************************************/
5296 +static DECLARE_MUTEX(mutex);
5297 +static const char *current_service = 0;
5299 +const char *perfctr_cpu_reserve(const char *service)
5304 + ret = current_service;
5307 + current_service = service;
5308 + __module_get(THIS_MODULE);
5314 +void perfctr_cpu_release(const char *service)
5317 + if (service != current_service) {
5318 + printk(KERN_ERR "%s: attempt by %s to release while reserved by %s\n",
5319 + __FUNCTION__, service, current_service);
5321 + /* power down the counters */
5322 + perfctr_cpu_reset();
5323 + current_service = 0;
5324 + module_put(THIS_MODULE);
5328 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/virtual.c
5329 ===================================================================
5330 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/virtual.c 1969-12-31 19:00:00.000000000 -0500
5331 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/virtual.c 2004-11-18 20:59:11.000000000 -0500
5333 +/* $Id: virtual.c,v 1.88.2.2 2004/10/19 15:23:43 mikpe Exp $
5334 + * Virtual per-process performance counters.
5336 + * Copyright (C) 1999-2003 Mikael Pettersson
5338 +#include <linux/config.h>
5339 +#define __NO_VERSION__
5340 +#include <linux/module.h>
5341 +#include <linux/init.h>
5342 +#include <linux/compiler.h> /* for unlikely() in 2.4.18 and older */
5343 +#include <linux/kernel.h>
5344 +#include <linux/mm.h>
5345 +#include <linux/ptrace.h>
5346 +#include <linux/fs.h>
5347 +#include <linux/file.h>
5348 +#include <linux/perfctr.h>
5350 +#include <asm/io.h>
5351 +#include <asm/uaccess.h>
5353 +#include "compat.h"
5354 +#include "virtual.h"
5355 +#include "marshal.h"
5357 +/****************************************************************
5359 + * Data types and macros. *
5361 + ****************************************************************/
5364 +/* User-visible fields: (must be first for mmap()) */
5365 + struct perfctr_cpu_state cpu_state;
5366 +/* Kernel-private fields: */
5369 + spinlock_t owner_lock;
5370 + struct task_struct *owner;
5371 + /* sampling_timer and bad_cpus_allowed are frequently
5372 + accessed, so they get to share a cache line */
5373 + unsigned int sampling_timer ____cacheline_aligned;
5374 +#if PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED
5375 + atomic_t bad_cpus_allowed;
5377 +#if 0 && defined(CONFIG_PERFCTR_DEBUG)
5378 + unsigned start_smp_id;
5379 + unsigned suspended;
5381 +#if PERFCTR_INTERRUPT_SUPPORT
5382 + unsigned int iresume_cstatus;
5385 +#define IS_RUNNING(perfctr) perfctr_cstatus_enabled((perfctr)->cpu_state.cstatus)
5387 +/* XXX: disabled: called from switch_to() where printk() is disallowed */
5388 +#if 0 && defined(CONFIG_PERFCTR_DEBUG)
5389 +#define debug_free(perfctr) \
5392 + for(i = 0; i < PAGE_SIZE/sizeof(int); ++i) \
5393 + ((int*)(perfctr))[i] = 0xfedac0ed; \
5395 +#define debug_init(perfctr) do { (perfctr)->suspended = 1; } while( 0 )
5396 +#define debug_suspend(perfctr) \
5398 + if( (perfctr)->suspended ) \
5399 + printk(KERN_ERR "%s: BUG! suspending non-running perfctr (pid %d, comm %s)\n", \
5400 + __FUNCTION__, current->pid, current->comm); \
5401 + (perfctr)->suspended = 1; \
5403 +#define debug_resume(perfctr) \
5405 + if( !(perfctr)->suspended ) \
5406 + printk(KERN_ERR "%s: BUG! resuming non-suspended perfctr (pid %d, comm %s)\n", \
5407 + __FUNCTION__, current->pid, current->comm); \
5408 + (perfctr)->suspended = 0; \
5410 +#define debug_check_smp_id(perfctr) \
5412 + if( (perfctr)->start_smp_id != smp_processor_id() ) { \
5413 + printk(KERN_ERR "%s: BUG! current cpu %u differs from start cpu %u (pid %d, comm %s)\n", \
5414 + __FUNCTION__, smp_processor_id(), (perfctr)->start_smp_id, \
5415 + current->pid, current->comm); \
5419 +#define debug_set_smp_id(perfctr) \
5420 + do { (perfctr)->start_smp_id = smp_processor_id(); } while( 0 )
5421 +#else /* CONFIG_PERFCTR_DEBUG */
5422 +#define debug_free(perfctr) do{}while(0)
5423 +#define debug_init(perfctr) do{}while(0)
5424 +#define debug_suspend(perfctr) do{}while(0)
5425 +#define debug_resume(perfctr) do{}while(0)
5426 +#define debug_check_smp_id(perfctr) do{}while(0)
5427 +#define debug_set_smp_id(perfctr) do{}while(0)
5428 +#endif /* CONFIG_PERFCTR_DEBUG */
5430 +#if PERFCTR_INTERRUPT_SUPPORT
5432 +static void vperfctr_ihandler(unsigned long pc);
5434 +static inline void vperfctr_set_ihandler(void)
5436 + perfctr_cpu_set_ihandler(vperfctr_ihandler);
5439 +static inline void vperfctr_clear_iresume_cstatus(struct vperfctr *perfctr)
5441 + perfctr->iresume_cstatus = 0;
5445 +static inline void vperfctr_set_ihandler(void) { }
5446 +static inline void vperfctr_clear_iresume_cstatus(struct vperfctr *perfctr) { }
5449 +#if PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED
5451 +static inline void vperfctr_init_bad_cpus_allowed(struct vperfctr *perfctr)
5453 + atomic_set(&perfctr->bad_cpus_allowed, 0);
5456 +/* Concurrent set_cpus_allowed() is possible. The only lock it
5457 + can take is the task lock, so we have to take it as well.
5458 + task_lock/unlock also disables/enables preemption. */
5460 +static inline void vperfctr_task_lock(struct task_struct *p)
5465 +static inline void vperfctr_task_unlock(struct task_struct *p)
5470 +#else /* !PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED */
5472 +static inline void vperfctr_init_bad_cpus_allowed(struct vperfctr *perfctr) { }
5474 +/* Concurrent set_cpus_allowed() is impossible or irrelevant.
5475 + Disabling and enabling preemption suffices for an atomic region. */
5477 +static inline void vperfctr_task_lock(struct task_struct *p)
5479 + preempt_disable();
5482 +static inline void vperfctr_task_unlock(struct task_struct *p)
5487 +#endif /* !PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED */
5489 +/****************************************************************
5491 + * Resource management. *
5493 + ****************************************************************/
5495 +/* XXX: perhaps relax this to number of _live_ perfctrs */
5496 +static DECLARE_MUTEX(nrctrs_mutex);
5498 +static const char this_service[] = __FILE__;
5500 +static int inc_nrctrs(void)
5502 + const char *other;
5505 + down(&nrctrs_mutex);
5506 + if( ++nrctrs == 1 ) {
5507 + other = perfctr_cpu_reserve(this_service);
5511 + up(&nrctrs_mutex);
5513 + printk(KERN_ERR __FILE__
5514 + ": cannot operate, perfctr hardware taken by '%s'\n",
5518 + vperfctr_set_ihandler();
5522 +static void dec_nrctrs(void)
5524 + down(&nrctrs_mutex);
5525 + if( --nrctrs == 0 )
5526 + perfctr_cpu_release(this_service);
5527 + up(&nrctrs_mutex);
5530 +static struct vperfctr *vperfctr_alloc(void)
5532 + unsigned long page;
5534 + if( inc_nrctrs() != 0 )
5535 + return ERR_PTR(-EBUSY);
5536 + page = get_zeroed_page(GFP_KERNEL);
5539 + return ERR_PTR(-ENOMEM);
5541 + SetPageReserved(virt_to_page(page));
5542 + return (struct vperfctr*) page;
5545 +static void vperfctr_free(struct vperfctr *perfctr)
5547 + debug_free(perfctr);
5548 + ClearPageReserved(virt_to_page(perfctr));
5549 + free_page((unsigned long)perfctr);
5553 +static struct vperfctr *get_empty_vperfctr(void)
5555 + struct vperfctr *perfctr = vperfctr_alloc();
5556 + if( !IS_ERR(perfctr) ) {
5557 + atomic_set(&perfctr->count, 1);
5558 + vperfctr_init_bad_cpus_allowed(perfctr);
5559 + spin_lock_init(&perfctr->owner_lock);
5560 + debug_init(perfctr);
5565 +static void put_vperfctr(struct vperfctr *perfctr)
5567 + if( atomic_dec_and_test(&perfctr->count) )
5568 + vperfctr_free(perfctr);
5571 +/****************************************************************
5573 + * Basic counter operations. *
5574 + * These must all be called by the owner process only. *
5575 + * These must all be called with preemption disabled. *
5577 + ****************************************************************/
5579 +/* PRE: IS_RUNNING(perfctr)
5580 + * Suspend the counters.
5581 + * XXX: When called from switch_to(), perfctr belongs to 'prev'
5582 + * but current is 'next'. Debug messages will refer to 'next'...
5584 +static inline void vperfctr_suspend(struct vperfctr *perfctr)
5586 + debug_suspend(perfctr);
5587 + debug_check_smp_id(perfctr);
5588 + perfctr_cpu_suspend(&perfctr->cpu_state);
5591 +static inline void vperfctr_reset_sampling_timer(struct vperfctr *perfctr)
5593 + /* XXX: base the value on perfctr_info.cpu_khz instead! */
5594 + perfctr->sampling_timer = HZ/2;
5597 +/* PRE: perfctr == current->thread.perfctr && IS_RUNNING(perfctr)
5598 + * Restart the counters.
5600 +static inline void vperfctr_resume(struct vperfctr *perfctr)
5602 + debug_resume(perfctr);
5603 + perfctr_cpu_resume(&perfctr->cpu_state);
5604 + vperfctr_reset_sampling_timer(perfctr);
5605 + debug_set_smp_id(perfctr);
5608 +/* Sample the counters but do not suspend them. */
5609 +static void vperfctr_sample(struct vperfctr *perfctr)
5611 + if( IS_RUNNING(perfctr) ) {
5612 + debug_check_smp_id(perfctr);
5613 + perfctr_cpu_sample(&perfctr->cpu_state);
5614 + vperfctr_reset_sampling_timer(perfctr);
5618 +#if PERFCTR_INTERRUPT_SUPPORT
5619 +/* vperfctr interrupt handler (XXX: add buffering support) */
5620 +/* PREEMPT note: called in IRQ context with preemption disabled. */
5621 +static void vperfctr_ihandler(unsigned long pc)
5623 + struct task_struct *tsk = current;
5624 + struct vperfctr *perfctr;
5625 + unsigned int pmc_mask;
5628 + perfctr = tsk->thread.perfctr;
5630 + printk(KERN_ERR "%s: BUG! pid %d has no vperfctr\n",
5631 + __FUNCTION__, tsk->pid);
5634 + if( !perfctr_cstatus_has_ictrs(perfctr->cpu_state.cstatus) ) {
5635 + printk(KERN_ERR "%s: BUG! vperfctr has cstatus %#x (pid %d, comm %s)\n",
5636 + __FUNCTION__, perfctr->cpu_state.cstatus, tsk->pid, tsk->comm);
5639 + vperfctr_suspend(perfctr);
5640 + pmc_mask = perfctr_cpu_identify_overflow(&perfctr->cpu_state);
5642 + printk(KERN_ERR "%s: BUG! pid %d has unidentifiable overflow source\n",
5643 + __FUNCTION__, tsk->pid);
5646 + /* suspend a-mode and i-mode PMCs, leaving only TSC on */
5647 + /* XXX: some people also want to suspend the TSC */
5648 + perfctr->iresume_cstatus = perfctr->cpu_state.cstatus;
5649 + if( perfctr_cstatus_has_tsc(perfctr->iresume_cstatus) ) {
5650 + perfctr->cpu_state.cstatus = perfctr_mk_cstatus(1, 0, 0);
5651 + vperfctr_resume(perfctr);
5653 + perfctr->cpu_state.cstatus = 0;
5654 + si.si_signo = perfctr->si_signo;
5656 + si.si_code = SI_PMC_OVF;
5657 + si.si_pmc_ovf_mask = pmc_mask;
5658 + if( !send_sig_info(si.si_signo, &si, tsk) )
5659 + send_sig(si.si_signo, tsk, 1);
5663 +/****************************************************************
5665 + * Process management operations. *
5666 + * These must all, with the exception of vperfctr_unlink() *
5667 + * and __vperfctr_set_cpus_allowed(), be called by the owner *
5670 + ****************************************************************/
5672 +/* Called from exit_thread() or sys_vperfctr_unlink().
5673 + * If the counters are running, stop them and sample their final values.
5674 + * Detach the vperfctr object from its owner task.
5675 + * PREEMPT note: exit_thread() does not run with preemption disabled.
5677 +static void vperfctr_unlink(struct task_struct *owner, struct vperfctr *perfctr)
5679 + /* this synchronises with vperfctr_ioctl() */
5680 + spin_lock(&perfctr->owner_lock);
5681 + perfctr->owner = NULL;
5682 + spin_unlock(&perfctr->owner_lock);
5684 + /* perfctr suspend+detach must be atomic wrt process suspend */
5685 + /* this also synchronises with perfctr_set_cpus_allowed() */
5686 + vperfctr_task_lock(owner);
5687 + if( IS_RUNNING(perfctr) && owner == current )
5688 + vperfctr_suspend(perfctr);
5689 + owner->thread.perfctr = NULL;
5690 + vperfctr_task_unlock(owner);
5692 + perfctr->cpu_state.cstatus = 0;
5693 + vperfctr_clear_iresume_cstatus(perfctr);
5694 + put_vperfctr(perfctr);
5697 +void __vperfctr_exit(struct vperfctr *perfctr)
5699 + vperfctr_unlink(current, perfctr);
5702 +/* schedule() --> switch_to() --> .. --> __vperfctr_suspend().
5703 + * If the counters are running, suspend them.
5704 + * PREEMPT note: switch_to() runs with preemption disabled.
5706 +void __vperfctr_suspend(struct vperfctr *perfctr)
5708 + if( IS_RUNNING(perfctr) )
5709 + vperfctr_suspend(perfctr);
5712 +/* schedule() --> switch_to() --> .. --> __vperfctr_resume().
5713 + * PRE: perfctr == current->thread.perfctr
5714 + * If the counters are runnable, resume them.
5715 + * PREEMPT note: switch_to() runs with preemption disabled.
5717 +void __vperfctr_resume(struct vperfctr *perfctr)
5719 + if( IS_RUNNING(perfctr) ) {
5720 +#if PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED
5721 + if( unlikely(atomic_read(&perfctr->bad_cpus_allowed)) &&
5722 + perfctr_cstatus_nrctrs(perfctr->cpu_state.cstatus) ) {
5723 + perfctr->cpu_state.cstatus = 0;
5724 + vperfctr_clear_iresume_cstatus(perfctr);
5725 + BUG_ON(current->state != TASK_RUNNING);
5726 + send_sig(SIGILL, current, 1);
5730 + vperfctr_resume(perfctr);
5734 +/* Called from update_one_process() [triggered by timer interrupt].
5735 + * PRE: perfctr == current->thread.perfctr.
5736 + * Sample the counters but do not suspend them.
5737 + * Needed to avoid precision loss due to multiple counter
5738 + * wraparounds between resume/suspend for CPU-bound processes.
5739 + * PREEMPT note: called in IRQ context with preemption disabled.
5741 +void __vperfctr_sample(struct vperfctr *perfctr)
5743 + if( --perfctr->sampling_timer == 0 )
5744 + vperfctr_sample(perfctr);
5747 +#if PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED
5748 +/* Called from set_cpus_allowed().
5749 + * PRE: current holds task_lock(owner)
5750 + * PRE: owner->thread.perfctr == perfctr
5752 +void __vperfctr_set_cpus_allowed(struct task_struct *owner,
5753 + struct vperfctr *perfctr,
5754 + cpumask_t new_mask)
5758 + cpus_and(tmp, new_mask, perfctr_cpus_forbidden_mask);
5759 + if( !cpus_empty(tmp) ) {
5760 + atomic_set(&perfctr->bad_cpus_allowed, 1);
5761 + printk(KERN_WARNING "perfctr: process %d (comm %s) issued unsafe"
5762 + " set_cpus_allowed() on process %d (comm %s)\n",
5763 + current->pid, current->comm, owner->pid, owner->comm);
5765 + atomic_set(&perfctr->bad_cpus_allowed, 0);
5769 +/****************************************************************
5771 + * Virtual perfctr "system calls". *
5772 + * These can be called by the owner process (tsk == current), *
5773 + * a monitor process which has the owner under ptrace ATTACH *
5774 + * control (tsk && tsk != current), or anyone with a handle to *
5775 + * an unlinked perfctr (!tsk). *
5777 + ****************************************************************/
5779 +static int sys_vperfctr_control(struct vperfctr *perfctr,
5780 + struct perfctr_struct_buf *argp,
5781 + struct task_struct *tsk)
5783 + struct vperfctr_control control;
5785 + unsigned int next_cstatus;
5786 + unsigned int nrctrs, i;
5789 + return -ESRCH; /* attempt to update unlinked perfctr */
5791 + err = perfctr_copy_from_user(&control, argp, &vperfctr_control_sdesc);
5795 + if( control.cpu_control.nractrs || control.cpu_control.nrictrs ) {
5796 + cpumask_t old_mask, new_mask;
5798 + old_mask = tsk->cpus_allowed;
5799 + cpus_andnot(new_mask, old_mask, perfctr_cpus_forbidden_mask);
5801 + if( cpus_empty(new_mask) )
5803 + if( !cpus_equal(new_mask, old_mask) )
5804 + set_cpus_allowed(tsk, new_mask);
5807 + /* PREEMPT note: preemption is disabled over the entire
5808 + region since we're updating an active perfctr. */
5809 + preempt_disable();
5810 + if( IS_RUNNING(perfctr) ) {
5811 + if( tsk == current )
5812 + vperfctr_suspend(perfctr);
5813 + perfctr->cpu_state.cstatus = 0;
5814 + vperfctr_clear_iresume_cstatus(perfctr);
5816 + perfctr->cpu_state.control = control.cpu_control;
5817 + /* remote access note: perfctr_cpu_update_control() is ok */
5818 + err = perfctr_cpu_update_control(&perfctr->cpu_state, 0);
5821 + next_cstatus = perfctr->cpu_state.cstatus;
5822 + if( !perfctr_cstatus_enabled(next_cstatus) )
5825 + /* XXX: validate si_signo? */
5826 + perfctr->si_signo = control.si_signo;
5828 + if( !perfctr_cstatus_has_tsc(next_cstatus) )
5829 + perfctr->cpu_state.tsc_sum = 0;
5831 + nrctrs = perfctr_cstatus_nrctrs(next_cstatus);
5832 + for(i = 0; i < nrctrs; ++i)
5833 + if( !(control.preserve & (1<<i)) )
5834 + perfctr->cpu_state.pmc[i].sum = 0;
5836 + if( tsk == current )
5837 + vperfctr_resume(perfctr);
5844 +static int sys_vperfctr_iresume(struct vperfctr *perfctr, const struct task_struct *tsk)
5846 +#if PERFCTR_INTERRUPT_SUPPORT
5847 + unsigned int iresume_cstatus;
5850 + return -ESRCH; /* attempt to update unlinked perfctr */
5852 + iresume_cstatus = perfctr->iresume_cstatus;
5853 + if( !perfctr_cstatus_has_ictrs(iresume_cstatus) )
5856 + /* PREEMPT note: preemption is disabled over the entire
5857 + region because we're updating an active perfctr. */
5858 + preempt_disable();
5860 + if( IS_RUNNING(perfctr) && tsk == current )
5861 + vperfctr_suspend(perfctr);
5863 + perfctr->cpu_state.cstatus = iresume_cstatus;
5864 + perfctr->iresume_cstatus = 0;
5866 + /* remote access note: perfctr_cpu_ireload() is ok */
5867 + perfctr_cpu_ireload(&perfctr->cpu_state);
5869 + if( tsk == current )
5870 + vperfctr_resume(perfctr);
5880 +static int sys_vperfctr_unlink(struct vperfctr *perfctr, struct task_struct *tsk)
5883 + vperfctr_unlink(tsk, perfctr);
5887 +static int sys_vperfctr_read_sum(struct vperfctr *perfctr,
5888 + struct perfctr_struct_buf *argp,
5889 + const struct task_struct *tsk)
5891 + struct perfctr_sum_ctrs sum;
5893 + if( tsk == current ) {
5894 + preempt_disable();
5895 + vperfctr_sample(perfctr);
5897 + //sum = perfctr->cpu_state.sum;
5900 + sum.tsc = perfctr->cpu_state.tsc_sum;
5901 + for(j = 0; j < ARRAY_SIZE(sum.pmc); ++j)
5902 + sum.pmc[j] = perfctr->cpu_state.pmc[j].sum;
5904 + if( tsk == current )
5906 + return perfctr_copy_to_user(argp, &sum, &perfctr_sum_ctrs_sdesc);
5909 +static int sys_vperfctr_read_control(struct vperfctr *perfctr,
5910 + struct perfctr_struct_buf *argp,
5911 + const struct task_struct *tsk)
5913 + struct vperfctr_control control;
5915 + /* PREEMPT note: While we're reading our own control, another
5916 + process may ptrace ATTACH to us and update our control.
5917 + Disable preemption to ensure we get a consistent copy.
5918 + Not needed for other cases since the perfctr is either
5919 + unlinked or its owner is ptrace ATTACH suspended by us. */
5920 + if( tsk == current )
5921 + preempt_disable();
5922 + control.si_signo = perfctr->si_signo;
5923 + control.cpu_control = perfctr->cpu_state.control;
5924 + if( tsk == current )
5926 + control.preserve = 0;
5927 + return perfctr_copy_to_user(argp, &control, &vperfctr_control_sdesc);
5930 +/****************************************************************
5932 + * Virtual perfctr file operations. *
5934 + ****************************************************************/
5936 +static int vperfctr_mmap(struct file *filp, struct vm_area_struct *vma)
5938 + struct vperfctr *perfctr;
5940 + /* Only allow read-only mapping of first page. */
5941 + if( (vma->vm_end - vma->vm_start) != PAGE_SIZE ||
5942 + vma->vm_pgoff != 0 ||
5943 + (pgprot_val(vma->vm_page_prot) & _PAGE_RW) ||
5944 + (vma->vm_flags & (VM_WRITE | VM_MAYWRITE)) )
5946 + perfctr = filp->private_data;
5949 + return remap_page_range(vma, vma->vm_start, virt_to_phys(perfctr),
5950 + PAGE_SIZE, vma->vm_page_prot);
5953 +static int vperfctr_release(struct inode *inode, struct file *filp)
5955 + struct vperfctr *perfctr = filp->private_data;
5956 + filp->private_data = NULL;
5958 + put_vperfctr(perfctr);
5962 +static int vperfctr_ioctl(struct inode *inode, struct file *filp,
5963 + unsigned int cmd, unsigned long arg)
5965 + struct vperfctr *perfctr;
5966 + struct task_struct *tsk;
5971 + return sys_perfctr_abi((unsigned int*)arg);
5972 + case PERFCTR_INFO:
5973 + return sys_perfctr_info((struct perfctr_struct_buf*)arg);
5974 + case PERFCTR_CPUS:
5975 + return sys_perfctr_cpus((struct perfctr_cpu_mask*)arg);
5976 + case PERFCTR_CPUS_FORBIDDEN:
5977 + return sys_perfctr_cpus_forbidden((struct perfctr_cpu_mask*)arg);
5979 + perfctr = filp->private_data;
5983 + if( perfctr != current->thread.perfctr ) {
5984 + /* this synchronises with vperfctr_unlink() and itself */
5985 + spin_lock(&perfctr->owner_lock);
5986 + tsk = perfctr->owner;
5988 + get_task_struct(tsk);
5989 + spin_unlock(&perfctr->owner_lock);
5991 + ret = ptrace_check_attach(tsk, 0);
5997 + case VPERFCTR_CONTROL:
5998 + ret = sys_vperfctr_control(perfctr, (struct perfctr_struct_buf*)arg, tsk);
6000 + case VPERFCTR_UNLINK:
6001 + ret = sys_vperfctr_unlink(perfctr, tsk);
6003 + case VPERFCTR_READ_SUM:
6004 + ret = sys_vperfctr_read_sum(perfctr, (struct perfctr_struct_buf*)arg, tsk);
6006 + case VPERFCTR_IRESUME:
6007 + ret = sys_vperfctr_iresume(perfctr, tsk);
6009 + case VPERFCTR_READ_CONTROL:
6010 + ret = sys_vperfctr_read_control(perfctr, (struct perfctr_struct_buf*)arg, tsk);
6016 + if( tsk && tsk != current )
6017 + put_task_struct(tsk);
6021 +static struct file_operations vperfctr_file_ops = {
6022 + .owner = THIS_MODULE,
6023 + .mmap = vperfctr_mmap,
6024 + .release = vperfctr_release,
6025 + .ioctl = vperfctr_ioctl,
6028 +/****************************************************************
6030 + * File system for virtual perfctrs. Based on pipefs. *
6032 + ****************************************************************/
6034 +#define VPERFCTRFS_MAGIC (('V'<<24)|('P'<<16)|('M'<<8)|('C'))
6036 +/* The code to set up a `struct file_system_type' for a pseudo fs
6037 + is unfortunately not the same in 2.4 and 2.6. */
6038 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
6039 +#include <linux/mount.h> /* needed for 2.6, included by fs.h in 2.4 */
6041 +/* 2.6 doesn't EXPORT_SYMBOL() fs/libfs.c:get_sb_pseudo().
6042 + This is a verbatim copy, only renamed. */
6045 +struct super_block *
6046 +perfctr_get_sb_pseudo(struct file_system_type *fs_type, char *name,
6047 + struct super_operations *ops, unsigned long magic)
6049 + struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
6050 + static struct super_operations default_ops = {.statfs = simple_statfs};
6051 + struct dentry *dentry;
6052 + struct inode *root;
6053 + struct qstr d_name = {.name = name, .len = strlen(name)};
6058 + s->s_flags = MS_NOUSER;
6059 + s->s_maxbytes = ~0ULL;
6060 + s->s_blocksize = 1024;
6061 + s->s_blocksize_bits = 10;
6062 + s->s_magic = magic;
6063 + s->s_op = ops ? ops : &default_ops;
6064 + root = new_inode(s);
6067 + root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
6068 + root->i_uid = root->i_gid = 0;
6069 + root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
6070 + dentry = d_alloc(NULL, &d_name);
6076 + dentry->d_parent = dentry;
6077 + d_instantiate(dentry, root);
6078 + s->s_root = dentry;
6079 + s->s_flags |= MS_ACTIVE;
6083 + up_write(&s->s_umount);
6084 + deactivate_super(s);
6085 + return ERR_PTR(-ENOMEM);
6087 +#undef get_sb_pseudo
6088 +#define get_sb_pseudo perfctr_get_sb_pseudo
6089 +#endif /* MODULE */
6091 +static struct super_block *
6092 +vperfctrfs_get_sb(struct file_system_type *fs_type,
6093 + int flags, const char *dev_name, void *data)
6095 + return get_sb_pseudo(fs_type, "vperfctr:", NULL, VPERFCTRFS_MAGIC);
6098 +static struct file_system_type vperfctrfs_type = {
6099 + .name = "vperfctrfs",
6100 + .get_sb = vperfctrfs_get_sb,
6101 + .kill_sb = kill_anon_super,
6106 +static int vperfctrfs_statfs(struct super_block *sb, struct statfs *buf)
6108 + buf->f_type = VPERFCTRFS_MAGIC;
6109 + buf->f_bsize = 1024;
6110 + buf->f_namelen = 255;
6114 +static struct super_operations vperfctrfs_ops = {
6115 + .statfs = vperfctrfs_statfs,
6118 +static struct super_block*
6119 +vperfctrfs_read_super(struct super_block *sb, void *data, int silent)
6121 + static const struct qstr d_name = { "vperfctrfs:", 11, 0 };
6122 + struct dentry *dentry;
6123 + struct inode *root;
6125 + root = new_inode(sb);
6128 + root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
6129 + root->i_uid = root->i_gid = 0;
6130 + root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
6131 + sb->s_blocksize = 1024;
6132 + sb->s_blocksize_bits = 10;
6133 + sb->s_magic = VPERFCTRFS_MAGIC;
6134 + sb->s_op = &vperfctrfs_ops; /* XXX: check if 2.4 really needs this */
6135 + sb->s_root = dentry = d_alloc(NULL, &d_name);
6140 + dentry->d_sb = sb;
6141 + dentry->d_parent = dentry;
6142 + d_instantiate(dentry, root);
6146 +/* DECLARE_FSTYPE() hides 'owner: THIS_MODULE'. kern_mount() increments
6147 + owner's use count, and since we're not unmountable from user-space,
6148 + the module can't be unloaded because it's use count is >= 1.
6149 + So we declare the file_system_type manually without the owner field. */
6150 +static struct file_system_type vperfctrfs_type = {
6151 + .name = "vperfctrfs",
6152 + .read_super = vperfctrfs_read_super,
6153 + .fs_flags = FS_NOMOUNT,
6158 +/* XXX: check if s/vperfctr_mnt/vperfctrfs_type.kern_mnt/ would work */
6159 +static struct vfsmount *vperfctr_mnt;
6161 +static int __init vperfctrfs_init(void)
6163 + int err = register_filesystem(&vperfctrfs_type);
6165 + vperfctr_mnt = kern_mount(&vperfctrfs_type);
6166 + if( !IS_ERR(vperfctr_mnt) )
6168 + err = PTR_ERR(vperfctr_mnt);
6169 + unregister_filesystem(&vperfctrfs_type);
6174 +static void __exit vperfctrfs_exit(void)
6176 + unregister_filesystem(&vperfctrfs_type);
6177 + mntput(vperfctr_mnt);
6180 +static struct inode *vperfctr_get_inode(void)
6182 + struct inode *inode;
6184 + inode = new_inode(vperfctr_mnt->mnt_sb);
6187 + inode->i_fop = &vperfctr_file_ops;
6188 + inode->i_state = I_DIRTY;
6189 + inode->i_mode = S_IFCHR | S_IRUSR | S_IWUSR;
6190 + inode->i_uid = current->fsuid;
6191 + inode->i_gid = current->fsgid;
6192 + inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
6193 + inode->i_blksize = 0;
6197 +static int vperfctrfs_delete_dentry(struct dentry *dentry)
6202 +static struct dentry_operations vperfctrfs_dentry_operations = {
6203 + .d_delete = vperfctrfs_delete_dentry,
6206 +static struct dentry *vperfctr_d_alloc_root(struct inode *inode)
6210 + struct dentry *dentry;
6212 + sprintf(name, "[%lu]", inode->i_ino);
6214 + this.len = strlen(name);
6215 + this.hash = inode->i_ino; /* will go */
6216 + dentry = d_alloc(vperfctr_mnt->mnt_sb->s_root, &this);
6218 + dentry->d_op = &vperfctrfs_dentry_operations;
6219 + d_add(dentry, inode);
6224 +static struct file *vperfctr_get_filp(void)
6226 + struct file *filp;
6227 + struct inode *inode;
6228 + struct dentry *dentry;
6230 + filp = get_empty_filp();
6233 + inode = vperfctr_get_inode();
6236 + dentry = vperfctr_d_alloc_root(inode);
6240 + filp->f_vfsmnt = mntget(vperfctr_mnt);
6241 + filp->f_dentry = dentry;
6242 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,2)
6243 + filp->f_mapping = dentry->d_inode->i_mapping;
6247 + filp->f_flags = 0;
6248 + filp->f_op = fops_get(&vperfctr_file_ops); /* fops_get() for MODULE */
6249 + filp->f_mode = FMODE_READ;
6250 + filp->f_version = 0;
6257 + put_filp(filp); /* doesn't run ->release() like fput() does */
6262 +/* tid is the actual task/thread id (née pid, stored as ->pid),
6263 + pid/tgid is that 2.6 thread group id crap (stored as ->tgid) */
6264 +int vperfctr_attach(int tid, int creat)
6266 + struct file *filp;
6267 + struct task_struct *tsk;
6268 + struct vperfctr *perfctr;
6272 + filp = vperfctr_get_filp();
6275 + err = fd = get_unused_fd();
6280 + perfctr = get_empty_vperfctr(); /* may sleep */
6281 + if( IS_ERR(perfctr) ) {
6282 + err = PTR_ERR(perfctr);
6287 + if( tid != 0 && tid != tsk->pid ) { /* remote? */
6288 + read_lock(&tasklist_lock);
6289 + tsk = find_task_by_pid(tid);
6291 + get_task_struct(tsk);
6292 + read_unlock(&tasklist_lock);
6296 + err = ptrace_check_attach(tsk, 0);
6301 + /* check+install must be atomic to prevent remote-control races */
6302 + vperfctr_task_lock(tsk);
6303 + if( !tsk->thread.perfctr ) {
6304 + perfctr->owner = tsk;
6305 + tsk->thread.perfctr = perfctr;
6309 + vperfctr_task_unlock(tsk);
6313 + perfctr = tsk->thread.perfctr;
6314 + /* PERFCTR_ABI and PERFCTR_INFO don't need the perfctr.
6315 + Hence no non-NULL check here. */
6317 + filp->private_data = perfctr;
6319 + atomic_inc(&perfctr->count);
6320 + if( tsk != current )
6321 + put_task_struct(tsk);
6322 + fd_install(fd, filp);
6325 + if( tsk != current )
6326 + put_task_struct(tsk);
6328 + if( perfctr ) /* can only occur if creat != 0 */
6329 + put_vperfctr(perfctr);
6331 + put_unused_fd(fd);
6337 +/****************************************************************
6339 + * module_init/exit *
6341 + ****************************************************************/
6344 +static struct vperfctr_stub off;
6346 +static void vperfctr_stub_init(void)
6348 + off = vperfctr_stub;
6349 + vperfctr_stub.owner = THIS_MODULE;
6350 + vperfctr_stub.exit = __vperfctr_exit;
6351 + vperfctr_stub.suspend = __vperfctr_suspend;
6352 + vperfctr_stub.resume = __vperfctr_resume;
6353 + vperfctr_stub.sample = __vperfctr_sample;
6354 +#if PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED
6355 + vperfctr_stub.set_cpus_allowed = __vperfctr_set_cpus_allowed;
6359 +static void vperfctr_stub_exit(void)
6361 + vperfctr_stub = off;
6364 +static inline void vperfctr_stub_init(void) { }
6365 +static inline void vperfctr_stub_exit(void) { }
6366 +#endif /* MODULE */
6368 +int __init vperfctr_init(void)
6370 + int err = vperfctrfs_init();
6373 + vperfctr_stub_init();
6377 +void __exit vperfctr_exit(void)
6379 + vperfctrfs_exit();
6380 + vperfctr_stub_exit();
6382 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_tests.h
6383 ===================================================================
6384 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/x86_tests.h 1969-12-31 19:00:00.000000000 -0500
6385 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_tests.h 2004-11-18 20:59:11.000000000 -0500
6387 +/* $Id: x86_tests.h,v 1.8.2.2 2004/08/02 15:53:19 mikpe Exp $
6388 + * Performance-monitoring counters driver.
6389 + * Optional x86/x86_64-specific init-time tests.
6391 + * Copyright (C) 1999-2004 Mikael Pettersson
6394 +/* 'enum perfctr_x86_tests_type' classifies CPUs according
6395 + to relevance for perfctr_x86_init_tests(). */
6396 +enum perfctr_x86_tests_type {
6407 +extern enum perfctr_x86_tests_type perfctr_x86_tests_type;
6409 +static inline void perfctr_set_tests_type(enum perfctr_x86_tests_type t)
6411 +#ifdef CONFIG_PERFCTR_INIT_TESTS
6412 + perfctr_x86_tests_type = t;
6416 +extern void perfctr_x86_init_tests(void);
6417 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/ppc_setup.c
6418 ===================================================================
6419 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/ppc_setup.c 1969-12-31 19:00:00.000000000 -0500
6420 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/ppc_setup.c 2004-11-18 20:59:11.000000000 -0500
6422 +/* $Id: ppc_setup.c,v 1.1 2004/01/12 01:59:11 mikpe Exp $
6423 + * Performance-monitoring counters driver.
6424 + * PPC32-specific kernel-resident code.
6426 + * Copyright (C) 2004 Mikael Pettersson
6428 +#include <linux/config.h>
6429 +#include <linux/module.h>
6430 +#include <linux/init.h>
6431 +#include <linux/kernel.h>
6432 +#include <linux/sched.h>
6433 +#include <linux/interrupt.h>
6434 +#include <asm/processor.h>
6435 +#include <asm/perfctr.h>
6436 +#include "ppc_compat.h"
6437 +#include "compat.h"
6439 +#if PERFCTR_INTERRUPT_SUPPORT
6440 +static void perfctr_default_ihandler(unsigned long pc)
6444 +static perfctr_ihandler_t perfctr_ihandler = perfctr_default_ihandler;
6446 +void do_perfctr_interrupt(struct pt_regs *regs)
6448 + preempt_disable();
6449 + (*perfctr_ihandler)(regs->nip);
6450 + preempt_enable_no_resched();
6453 +void perfctr_cpu_set_ihandler(perfctr_ihandler_t ihandler)
6455 + perfctr_ihandler = ihandler ? ihandler : perfctr_default_ihandler;
6458 +#ifdef CONFIG_PERFCTR_MODULE
6459 +EXPORT_SYMBOL(perfctr_cpu_set_ihandler);
6460 +#endif /* MODULE */
6461 +#endif /* PERFCTR_INTERRUPT_SUPPORT */
6462 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/ppc_tests.h
6463 ===================================================================
6464 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/ppc_tests.h 1969-12-31 19:00:00.000000000 -0500
6465 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/ppc_tests.h 2004-11-18 20:59:11.000000000 -0500
6467 +/* $Id: ppc_tests.h,v 1.1.2.1 2004/06/21 22:33:35 mikpe Exp $
6468 + * Performance-monitoring counters driver.
6469 + * Optional PPC32-specific init-time tests.
6471 + * Copyright (C) 2004 Mikael Pettersson
6474 +#ifdef CONFIG_PERFCTR_INIT_TESTS
6475 +extern void perfctr_ppc_init_tests(int have_mmcr1);
6477 +static inline void perfctr_ppc_init_tests(int have_mmcr1) { }
6479 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/version.h
6480 ===================================================================
6481 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/version.h 1969-12-31 19:00:00.000000000 -0500
6482 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/version.h 2004-11-18 20:59:11.000000000 -0500
6484 +#define VERSION "2.6.10.2"
6485 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_64_tests.c
6486 ===================================================================
6487 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/x86_64_tests.c 1969-12-31 19:00:00.000000000 -0500
6488 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_64_tests.c 2004-11-18 20:59:11.000000000 -0500
6490 +/* $Id: x86_64_tests.c,v 1.3 2004/02/21 11:04:46 mikpe Exp $
6491 + * Performance-monitoring counters driver.
6492 + * Optional x86_64-specific init-time tests.
6494 + * Copyright (C) 2003-2004 Mikael Pettersson
6496 +#include <linux/config.h>
6497 +#define __NO_VERSION__
6498 +#include <linux/module.h>
6499 +#include <linux/init.h>
6500 +#include <linux/sched.h>
6501 +#include <linux/fs.h>
6502 +#include <linux/perfctr.h>
6503 +#include <asm/msr.h>
6504 +#include <asm/fixmap.h>
6505 +#include <asm/apic.h>
6506 +#include "x86_64_compat.h"
6507 +#include "x86_64_tests.h"
6509 +#define MSR_K8_EVNTSEL0 0xC0010000
6510 +#define MSR_K8_PERFCTR0 0xC0010004
6511 +#define K8_EVNTSEL0_VAL (0xC0 | (3<<16) | (1<<22))
6514 +#define X2(S) S";"S
6515 +#define X8(S) X2(X2(X2(S)))
6517 +static void __init do_rdpmc(unsigned pmc, unsigned unused2)
6520 + for(i = 0; i < NITER/8; ++i)
6521 + __asm__ __volatile__(X8("rdpmc") : : "c"(pmc) : "eax", "edx");
6524 +static void __init do_rdmsr(unsigned msr, unsigned unused2)
6527 + for(i = 0; i < NITER/8; ++i)
6528 + __asm__ __volatile__(X8("rdmsr") : : "c"(msr) : "eax", "edx");
6531 +static void __init do_wrmsr(unsigned msr, unsigned data)
6534 + for(i = 0; i < NITER/8; ++i)
6535 + __asm__ __volatile__(X8("wrmsr") : : "c"(msr), "a"(data), "d"(0));
6538 +static void __init do_rdcr4(unsigned unused1, unsigned unused2)
6541 + unsigned long dummy;
6542 + for(i = 0; i < NITER/8; ++i)
6543 + __asm__ __volatile__(X8("movq %%cr4,%0") : "=r"(dummy));
6546 +static void __init do_wrcr4(unsigned cr4, unsigned unused2)
6549 + for(i = 0; i < NITER/8; ++i)
6550 + __asm__ __volatile__(X8("movq %0,%%cr4") : : "r"((long)cr4));
6553 +static void __init do_rdtsc(unsigned unused1, unsigned unused2)
6556 + for(i = 0; i < NITER/8; ++i)
6557 + __asm__ __volatile__(X8("rdtsc") : : : "eax", "edx");
6560 +static void __init do_wrlvtpc(unsigned val, unsigned unused2)
6563 + for(i = 0; i < NITER/8; ++i) {
6564 + apic_write(APIC_LVTPC, val);
6565 + apic_write(APIC_LVTPC, val);
6566 + apic_write(APIC_LVTPC, val);
6567 + apic_write(APIC_LVTPC, val);
6568 + apic_write(APIC_LVTPC, val);
6569 + apic_write(APIC_LVTPC, val);
6570 + apic_write(APIC_LVTPC, val);
6571 + apic_write(APIC_LVTPC, val);
6575 +static void __init do_empty_loop(unsigned unused1, unsigned unused2)
6578 + for(i = 0; i < NITER/8; ++i)
6579 + __asm__ __volatile__("" : : "c"(0));
6582 +static unsigned __init run(void (*doit)(unsigned, unsigned),
6583 + unsigned arg1, unsigned arg2)
6585 + unsigned start, dummy, stop;
6586 + rdtsc(start, dummy);
6587 + (*doit)(arg1, arg2); /* should take < 2^32 cycles to complete */
6588 + rdtsc(stop, dummy);
6589 + return stop - start;
6592 +static void __init init_tests_message(void)
6594 + printk(KERN_INFO "Please email the following PERFCTR INIT lines "
6595 + "to mikpe@csd.uu.se\n"
6596 + KERN_INFO "To remove this message, rebuild the driver "
6597 + "with CONFIG_PERFCTR_INIT_TESTS=n\n");
6598 + printk(KERN_INFO "PERFCTR INIT: vendor %u, family %u, model %u, stepping %u, clock %u kHz\n",
6599 + current_cpu_data.x86_vendor,
6600 + current_cpu_data.x86,
6601 + current_cpu_data.x86_model,
6602 + current_cpu_data.x86_mask,
6603 + perfctr_cpu_khz());
6607 +measure_overheads(unsigned msr_evntsel0, unsigned evntsel0, unsigned msr_perfctr0)
6610 + unsigned int loop, ticks[9];
6611 + const char *name[9];
6613 + if( msr_evntsel0 )
6614 + wrmsr(msr_evntsel0, 0, 0);
6616 + name[0] = "rdtsc";
6617 + ticks[0] = run(do_rdtsc, 0, 0);
6618 + name[1] = "rdpmc";
6619 + ticks[1] = (perfctr_info.cpu_features & PERFCTR_FEATURE_RDPMC)
6620 + ? run(do_rdpmc,1,0) : 0;
6621 + name[2] = "rdmsr (counter)";
6622 + ticks[2] = msr_perfctr0 ? run(do_rdmsr, msr_perfctr0, 0) : 0;
6623 + name[3] = "rdmsr (evntsel)";
6624 + ticks[3] = msr_evntsel0 ? run(do_rdmsr, msr_evntsel0, 0) : 0;
6625 + name[4] = "wrmsr (counter)";
6626 + ticks[4] = msr_perfctr0 ? run(do_wrmsr, msr_perfctr0, 0) : 0;
6627 + name[5] = "wrmsr (evntsel)";
6628 + ticks[5] = msr_evntsel0 ? run(do_wrmsr, msr_evntsel0, evntsel0) : 0;
6629 + name[6] = "read cr4";
6630 + ticks[6] = run(do_rdcr4, 0, 0);
6631 + name[7] = "write cr4";
6632 + ticks[7] = run(do_wrcr4, read_cr4(), 0);
6633 + name[8] = "write LVTPC";
6634 + ticks[8] = (perfctr_info.cpu_features & PERFCTR_FEATURE_PCINT)
6635 + ? run(do_wrlvtpc, APIC_DM_NMI|APIC_LVT_MASKED, 0) : 0;
6637 + loop = run(do_empty_loop, 0, 0);
6639 + if( msr_evntsel0 )
6640 + wrmsr(msr_evntsel0, 0, 0);
6642 + init_tests_message();
6643 + printk(KERN_INFO "PERFCTR INIT: NITER == %u\n", NITER);
6644 + printk(KERN_INFO "PERFCTR INIT: loop overhead is %u cycles\n", loop);
6645 + for(i = 0; i < ARRAY_SIZE(ticks); ++i) {
6649 + x = ((ticks[i] - loop) * 10) / NITER;
6650 + printk(KERN_INFO "PERFCTR INIT: %s cost is %u.%u cycles (%u total)\n",
6651 + name[i], x/10, x%10, ticks[i]);
6655 +void __init perfctr_k8_init_tests(void)
6657 + measure_overheads(MSR_K8_EVNTSEL0, K8_EVNTSEL0_VAL, MSR_K8_PERFCTR0);
6660 +void __init perfctr_generic_init_tests(void)
6662 + measure_overheads(0, 0, 0);
6664 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_64_setup.c
6665 ===================================================================
6666 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/x86_64_setup.c 1969-12-31 19:00:00.000000000 -0500
6667 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_64_setup.c 2004-11-18 20:59:11.000000000 -0500
6669 +/* $Id: x86_64_setup.c,v 1.9 2004/02/21 11:56:53 mikpe Exp $
6670 + * Performance-monitoring counters driver.
6671 + * x86_86-specific kernel-resident code.
6673 + * Copyright (C) 2003-2004 Mikael Pettersson
6675 +#include <linux/config.h>
6676 +#include <linux/module.h>
6677 +#include <linux/init.h>
6678 +#include <linux/kernel.h>
6679 +#include <linux/sched.h>
6680 +#include <linux/interrupt.h>
6681 +#include <asm/processor.h>
6682 +#include <asm/perfctr.h>
6683 +#include <asm/fixmap.h>
6684 +#include <asm/apic.h>
6685 +#include "x86_64_compat.h"
6686 +#include "compat.h"
6688 +static void perfctr_default_ihandler(unsigned long pc)
6692 +static perfctr_ihandler_t perfctr_ihandler = perfctr_default_ihandler;
6694 +asmlinkage void smp_perfctr_interrupt(struct pt_regs *regs)
6696 + /* PREEMPT note: invoked via an interrupt gate, which
6697 + masks interrupts. We're still on the originating CPU. */
6700 + (*perfctr_ihandler)(regs->rip);
6704 +void perfctr_cpu_set_ihandler(perfctr_ihandler_t ihandler)
6706 + perfctr_ihandler = ihandler ? ihandler : perfctr_default_ihandler;
6709 +extern unsigned int cpu_khz;
6711 +/* Wrapper to avoid namespace clash in RedHat 8.0's 2.4.18-14 kernel. */
6712 +unsigned int perfctr_cpu_khz(void)
6717 +#ifdef CONFIG_PERFCTR_MODULE
6718 +EXPORT_SYMBOL_mmu_cr4_features;
6719 +EXPORT_SYMBOL(perfctr_cpu_khz);
6721 +EXPORT_SYMBOL(nmi_perfctr_msr);
6723 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,71) && defined(CONFIG_PM)
6724 +EXPORT_SYMBOL(apic_pm_register);
6725 +EXPORT_SYMBOL(apic_pm_unregister);
6726 +EXPORT_SYMBOL(nmi_pmdev);
6729 +EXPORT_SYMBOL(perfctr_cpu_set_ihandler);
6731 +#endif /* MODULE */
6732 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_64.c
6733 ===================================================================
6734 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/x86_64.c 1969-12-31 19:00:00.000000000 -0500
6735 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86_64.c 2004-11-18 20:59:11.000000000 -0500
6737 +/* $Id: x86_64.c,v 1.22.2.1 2004/05/29 22:25:22 mikpe Exp $
6738 + * x86_64 performance-monitoring counters driver.
6740 + * Copyright (C) 2003-2004 Mikael Pettersson
6742 +#include <linux/config.h>
6743 +#define __NO_VERSION__
6744 +#include <linux/module.h>
6745 +#include <linux/init.h>
6746 +#include <linux/sched.h>
6747 +#include <linux/fs.h>
6748 +#include <linux/perfctr.h>
6750 +#include <asm/msr.h>
6751 +#include <asm/fixmap.h>
6752 +#include <asm/apic.h>
6753 +struct hw_interrupt_type;
6754 +#include <asm/hw_irq.h>
6756 +#include "compat.h"
6757 +#include "x86_compat.h"
6758 +#include "x86_tests.h"
6760 +/* Support for lazy evntsel and perfctr MSR updates. */
6761 +struct per_cpu_cache { /* roughly a subset of perfctr_cpu_state */
6763 + unsigned int id; /* cache owner id */
6766 + /* NOTE: these caches have physical indices, not virtual */
6767 + unsigned int evntsel[4];
6769 +} ____cacheline_aligned;
6770 +static struct per_cpu_cache per_cpu_cache[NR_CPUS] __cacheline_aligned;
6772 +/* Structure for counter snapshots, as 32-bit values. */
6773 +struct perfctr_low_ctrs {
6775 + unsigned int pmc[4];
6779 +#define MSR_K8_EVNTSEL0 0xC0010000 /* .. 0xC0010003 */
6780 +#define MSR_K8_PERFCTR0 0xC0010004 /* .. 0xC0010007 */
6781 +#define K8_EVNTSEL_ENABLE 0x00400000
6782 +#define K8_EVNTSEL_INT 0x00100000
6783 +#define K8_EVNTSEL_CPL 0x00030000
6784 +#define K8_EVNTSEL_RESERVED 0x00280000
6786 +#define rdpmc_low(ctr,low) \
6787 + __asm__ __volatile__("rdpmc" : "=a"(low) : "c"(ctr) : "edx")
6789 +static void clear_msr_range(unsigned int base, unsigned int n)
6793 + for(i = 0; i < n; ++i)
6794 + wrmsr(base+i, 0, 0);
6797 +static inline void set_in_cr4_local(unsigned int mask)
6799 + write_cr4(read_cr4() | mask);
6802 +static inline void clear_in_cr4_local(unsigned int mask)
6804 + write_cr4(read_cr4() & ~mask);
6807 +static unsigned int new_id(void)
6809 + static spinlock_t lock = SPIN_LOCK_UNLOCKED;
6810 + static unsigned int counter;
6815 + spin_unlock(&lock);
6819 +#if defined(CONFIG_SMP)
6821 +static inline void set_isuspend_cpu(struct perfctr_cpu_state *state,
6824 + state->k1.isuspend_cpu = cpu;
6827 +static inline int is_isuspend_cpu(const struct perfctr_cpu_state *state,
6830 + return state->k1.isuspend_cpu == cpu;
6833 +static inline void clear_isuspend_cpu(struct perfctr_cpu_state *state)
6835 + state->k1.isuspend_cpu = NR_CPUS;
6839 +static inline void set_isuspend_cpu(struct perfctr_cpu_state *state,
6841 +static inline int is_isuspend_cpu(const struct perfctr_cpu_state *state,
6842 + int cpu) { return 1; }
6843 +static inline void clear_isuspend_cpu(struct perfctr_cpu_state *state) { }
6846 +/* XXX: disabled: called from switch_to() where printk() is disallowed */
6847 +#if 0 && defined(CONFIG_PERFCTR_DEBUG)
6848 +static void debug_evntsel_cache(const struct perfctr_cpu_state *state,
6849 + const struct per_cpu_cache *cache)
6851 + unsigned int nrctrs, i;
6853 + nrctrs = perfctr_cstatus_nrctrs(state->cstatus);
6854 + for(i = 0; i < nrctrs; ++i) {
6855 + unsigned int evntsel = state->control.evntsel[i];
6856 + unsigned int pmc = state->control.pmc_map[i];
6857 + if( evntsel != cache->control.evntsel[pmc] ) {
6858 + printk(KERN_ERR "perfctr: (pid %d, comm %s) "
6859 + "evntsel[%u] is %#x, should be %#x\n",
6860 + current->pid, current->comm,
6861 + i, cache->control.evntsel[pmc], evntsel);
6867 +static inline void debug_evntsel_cache(const struct perfctr_cpu_state *s,
6868 + const struct per_cpu_cache *c)
6872 +/****************************************************************
6874 + * Driver procedures. *
6876 + ****************************************************************/
6878 +static void perfctr_cpu_read_counters(const struct perfctr_cpu_state *state,
6879 + struct perfctr_low_ctrs *ctrs)
6881 + unsigned int cstatus, nrctrs, i;
6883 + cstatus = state->cstatus;
6884 + if( perfctr_cstatus_has_tsc(cstatus) )
6885 + rdtscl(ctrs->tsc);
6886 + nrctrs = perfctr_cstatus_nractrs(cstatus);
6887 + for(i = 0; i < nrctrs; ++i) {
6888 + unsigned int pmc = state->pmc[i].map;
6889 + rdpmc_low(pmc, ctrs->pmc[i]);
6893 +static int k8_check_control(struct perfctr_cpu_state *state)
6895 + unsigned int evntsel, i, nractrs, nrctrs, pmc_mask, pmc;
6897 + nractrs = state->control.nractrs;
6898 + nrctrs = nractrs + state->control.nrictrs;
6899 + if( nrctrs < nractrs || nrctrs > 4 )
6903 + for(i = 0; i < nrctrs; ++i) {
6904 + pmc = state->control.pmc_map[i];
6905 + state->pmc[i].map = pmc;
6906 + if( pmc >= 4 || (pmc_mask & (1<<pmc)) )
6908 + pmc_mask |= (1<<pmc);
6909 + evntsel = state->control.evntsel[i];
6910 + /* protect reserved bits */
6911 + if( evntsel & K8_EVNTSEL_RESERVED )
6913 + /* ENable bit must be set in each evntsel */
6914 + if( !(evntsel & K8_EVNTSEL_ENABLE) )
6916 + /* the CPL field must be non-zero */
6917 + if( !(evntsel & K8_EVNTSEL_CPL) )
6919 + /* INT bit must be off for a-mode and on for i-mode counters */
6920 + if( evntsel & K8_EVNTSEL_INT ) {
6924 + if( i >= nractrs )
6928 + state->k1.id = new_id();
6932 +static void perfctr_cpu_isuspend(struct perfctr_cpu_state *state)
6934 + struct per_cpu_cache *cache;
6935 + unsigned int cstatus, nrctrs, i;
6938 + cpu = smp_processor_id();
6939 + cache = &per_cpu_cache[cpu];
6940 + cstatus = state->cstatus;
6941 + nrctrs = perfctr_cstatus_nrctrs(cstatus);
6942 + for(i = perfctr_cstatus_nractrs(cstatus); i < nrctrs; ++i) {
6943 + unsigned int pmc, now;
6944 + pmc = state->pmc[i].map;
6945 + cache->control.evntsel[pmc] = 0;
6946 + wrmsr(MSR_K8_EVNTSEL0+pmc, 0, 0);
6947 + rdpmc_low(pmc, now);
6948 + state->pmc[i].sum += now - state->pmc[i].start;
6949 + state->pmc[i].start = now;
6951 + /* cache->k1.id is still == state->k1.id */
6952 + set_isuspend_cpu(state, cpu);
6955 +static void perfctr_cpu_iresume(const struct perfctr_cpu_state *state)
6957 + struct per_cpu_cache *cache;
6958 + unsigned int cstatus, nrctrs, i;
6961 + cpu = smp_processor_id();
6962 + cache = &per_cpu_cache[cpu];
6963 + if( cache->k1.id == state->k1.id ) {
6964 + cache->k1.id = 0; /* force reload of cleared EVNTSELs */
6965 + if( is_isuspend_cpu(state, cpu) )
6966 + return; /* skip reload of PERFCTRs */
6968 + cstatus = state->cstatus;
6969 + nrctrs = perfctr_cstatus_nrctrs(cstatus);
6970 + for(i = perfctr_cstatus_nractrs(cstatus); i < nrctrs; ++i) {
6971 + unsigned int pmc = state->pmc[i].map;
6972 + /* If the control wasn't ours we must disable the evntsels
6973 + before reinitialising the counters, to prevent unexpected
6974 + counter increments and missed overflow interrupts. */
6975 + if( cache->control.evntsel[pmc] ) {
6976 + cache->control.evntsel[pmc] = 0;
6977 + wrmsr(MSR_K8_EVNTSEL0+pmc, 0, 0);
6979 + wrmsr(MSR_K8_PERFCTR0+pmc, state->pmc[i].start, -1);
6981 + /* cache->k1.id remains != state->k1.id */
6984 +static void perfctr_cpu_write_control(const struct perfctr_cpu_state *state)
6986 + struct per_cpu_cache *cache;
6987 + unsigned int nrctrs, i;
6989 + cache = &per_cpu_cache[smp_processor_id()];
6990 + if( cache->k1.id == state->k1.id ) {
6991 + debug_evntsel_cache(state, cache);
6994 + nrctrs = perfctr_cstatus_nrctrs(state->cstatus);
6995 + for(i = 0; i < nrctrs; ++i) {
6996 + unsigned int evntsel = state->control.evntsel[i];
6997 + unsigned int pmc = state->pmc[i].map;
6998 + if( evntsel != cache->control.evntsel[pmc] ) {
6999 + cache->control.evntsel[pmc] = evntsel;
7000 + wrmsr(MSR_K8_EVNTSEL0+pmc, evntsel, 0);
7003 + cache->k1.id = state->k1.id;
7006 +static void k8_clear_counters(void)
7008 + clear_msr_range(MSR_K8_EVNTSEL0, 4+4);
7012 + * Generic driver for any x86-64 with a working TSC.
7013 + * (Mainly for testing with Screwdriver.)
7016 +static int generic_check_control(struct perfctr_cpu_state *state)
7018 + if( state->control.nractrs || state->control.nrictrs )
7023 +static void generic_clear_counters(void)
7028 + * Driver methods, internal and exported.
7031 +/* Call perfctr_cpu_ireload() just before perfctr_cpu_resume() to
7032 + bypass internal caching and force a reload if the I-mode PMCs. */
7033 +void perfctr_cpu_ireload(struct perfctr_cpu_state *state)
7036 + clear_isuspend_cpu(state);
7038 + per_cpu_cache[smp_processor_id()].k1.id = 0;
7042 +/* PRE: the counters have been suspended and sampled by perfctr_cpu_suspend() */
7043 +unsigned int perfctr_cpu_identify_overflow(struct perfctr_cpu_state *state)
7045 + unsigned int cstatus, nrctrs, pmc, pmc_mask;
7047 + cstatus = state->cstatus;
7048 + pmc = perfctr_cstatus_nractrs(cstatus);
7049 + nrctrs = perfctr_cstatus_nrctrs(cstatus);
7051 + for(pmc_mask = 0; pmc < nrctrs; ++pmc) {
7052 + if( (int)state->pmc[pmc].start >= 0 ) { /* XXX: ">" ? */
7053 + /* XXX: "+=" to correct for overshots */
7054 + state->pmc[pmc].start = state->control.ireset[pmc];
7055 + pmc_mask |= (1 << pmc);
7061 +static inline int check_ireset(const struct perfctr_cpu_state *state)
7063 + unsigned int nrctrs, i;
7065 + i = state->control.nractrs;
7066 + nrctrs = i + state->control.nrictrs;
7067 + for(; i < nrctrs; ++i)
7068 + if( state->control.ireset[i] >= 0 )
7073 +static inline void setup_imode_start_values(struct perfctr_cpu_state *state)
7075 + unsigned int cstatus, nrctrs, i;
7077 + cstatus = state->cstatus;
7078 + nrctrs = perfctr_cstatus_nrctrs(cstatus);
7079 + for(i = perfctr_cstatus_nractrs(cstatus); i < nrctrs; ++i)
7080 + state->pmc[i].start = state->control.ireset[i];
7083 +static inline void debug_no_imode(const struct perfctr_cpu_state *state)
7085 +#ifdef CONFIG_PERFCTR_DEBUG
7086 + if( perfctr_cstatus_has_ictrs(state->cstatus) )
7087 + printk(KERN_ERR "perfctr: BUG! updating control in"
7088 + " perfctr %p on cpu %u while it has cstatus %x"
7089 + " (pid %d, comm %s)\n",
7090 + state, smp_processor_id(), state->cstatus,
7091 + current->pid, current->comm);
7095 +static int (*check_control)(struct perfctr_cpu_state*);
7096 +int perfctr_cpu_update_control(struct perfctr_cpu_state *state, int is_global)
7100 + debug_no_imode(state);
7101 + clear_isuspend_cpu(state);
7102 + state->cstatus = 0;
7104 + /* disallow i-mode counters if we cannot catch the interrupts */
7105 + if( !(perfctr_info.cpu_features & PERFCTR_FEATURE_PCINT)
7106 + && state->control.nrictrs )
7109 + err = check_control(state);
7112 + err = check_ireset(state);
7115 + state->cstatus = perfctr_mk_cstatus(state->control.tsc_on,
7116 + state->control.nractrs,
7117 + state->control.nrictrs);
7118 + setup_imode_start_values(state);
7122 +void perfctr_cpu_suspend(struct perfctr_cpu_state *state)
7124 + unsigned int i, cstatus, nractrs;
7125 + struct perfctr_low_ctrs now;
7127 + if( perfctr_cstatus_has_ictrs(state->cstatus) )
7128 + perfctr_cpu_isuspend(state);
7129 + perfctr_cpu_read_counters(state, &now);
7130 + cstatus = state->cstatus;
7131 + if( perfctr_cstatus_has_tsc(cstatus) )
7132 + state->tsc_sum += now.tsc - state->tsc_start;
7133 + nractrs = perfctr_cstatus_nractrs(cstatus);
7134 + for(i = 0; i < nractrs; ++i)
7135 + state->pmc[i].sum += now.pmc[i] - state->pmc[i].start;
7138 +void perfctr_cpu_resume(struct perfctr_cpu_state *state)
7140 + if( perfctr_cstatus_has_ictrs(state->cstatus) )
7141 + perfctr_cpu_iresume(state);
7142 + perfctr_cpu_write_control(state);
7143 + //perfctr_cpu_read_counters(state, &state->start);
7145 + struct perfctr_low_ctrs now;
7146 + unsigned int i, cstatus, nrctrs;
7147 + perfctr_cpu_read_counters(state, &now);
7148 + cstatus = state->cstatus;
7149 + if( perfctr_cstatus_has_tsc(cstatus) )
7150 + state->tsc_start = now.tsc;
7151 + nrctrs = perfctr_cstatus_nractrs(cstatus);
7152 + for(i = 0; i < nrctrs; ++i)
7153 + state->pmc[i].start = now.pmc[i];
7155 + /* XXX: if (SMP && start.tsc == now.tsc) ++now.tsc; */
7158 +void perfctr_cpu_sample(struct perfctr_cpu_state *state)
7160 + unsigned int i, cstatus, nractrs;
7161 + struct perfctr_low_ctrs now;
7163 + perfctr_cpu_read_counters(state, &now);
7164 + cstatus = state->cstatus;
7165 + if( perfctr_cstatus_has_tsc(cstatus) ) {
7166 + state->tsc_sum += now.tsc - state->tsc_start;
7167 + state->tsc_start = now.tsc;
7169 + nractrs = perfctr_cstatus_nractrs(cstatus);
7170 + for(i = 0; i < nractrs; ++i) {
7171 + state->pmc[i].sum += now.pmc[i] - state->pmc[i].start;
7172 + state->pmc[i].start = now.pmc[i];
7176 +static void (*clear_counters)(void);
7177 +static void perfctr_cpu_clear_counters(void)
7179 + return clear_counters();
7182 +/****************************************************************
7184 + * Processor detection and initialisation procedures. *
7186 + ****************************************************************/
7188 +static int __init amd_init(void)
7190 + static char k8_name[] __initdata = "AMD K8";
7191 + static char k8c_name[] __initdata = "AMD K8C";
7193 + if( !cpu_has_tsc )
7195 + if( boot_cpu_data.x86 != 15 )
7197 + if( (boot_cpu_data.x86_model > 5) ||
7198 + (boot_cpu_data.x86_model >= 4 && boot_cpu_data.x86_mask >= 8) ) {
7199 + perfctr_info.cpu_type = PERFCTR_X86_AMD_K8C;
7200 + perfctr_cpu_name = k8c_name;
7202 + perfctr_info.cpu_type = PERFCTR_X86_AMD_K8;
7203 + perfctr_cpu_name = k8_name;
7205 + check_control = k8_check_control;
7206 + clear_counters = k8_clear_counters;
7207 + if( cpu_has_apic )
7208 + perfctr_info.cpu_features |= PERFCTR_FEATURE_PCINT;
7212 +/* For testing on Screwdriver. */
7213 +static int __init generic_init(void)
7215 + static char generic_name[] __initdata = "Generic x86-64 with TSC";
7216 + if( !cpu_has_tsc )
7218 + perfctr_info.cpu_features &= ~PERFCTR_FEATURE_RDPMC;
7219 + perfctr_info.cpu_type = PERFCTR_X86_GENERIC;
7220 + perfctr_cpu_name = generic_name;
7221 + check_control = generic_check_control;
7222 + clear_counters = generic_clear_counters;
7226 +static void perfctr_cpu_init_one(void *ignore)
7228 + /* PREEMPT note: when called via smp_call_function(),
7229 + this is in IRQ context with preemption disabled. */
7230 + perfctr_cpu_clear_counters();
7231 + if( cpu_has_apic )
7232 + apic_write(APIC_LVTPC, LOCAL_PERFCTR_VECTOR);
7233 + if( perfctr_info.cpu_features & PERFCTR_FEATURE_RDPMC )
7234 + set_in_cr4_local(X86_CR4_PCE);
7237 +static void perfctr_cpu_exit_one(void *ignore)
7239 + /* PREEMPT note: when called via smp_call_function(),
7240 + this is in IRQ context with preemption disabled. */
7241 + perfctr_cpu_clear_counters();
7242 + if( cpu_has_apic )
7243 + apic_write(APIC_LVTPC, APIC_DM_NMI | APIC_LVT_MASKED);
7244 + if( perfctr_info.cpu_features & PERFCTR_FEATURE_RDPMC )
7245 + clear_in_cr4_local(X86_CR4_PCE);
7248 +#if defined(CONFIG_PM)
7250 +static void perfctr_pm_suspend(void)
7252 + /* XXX: clear control registers */
7253 + printk("perfctr: PM suspend\n");
7256 +static void perfctr_pm_resume(void)
7258 + /* XXX: reload control registers */
7259 + printk("perfctr: PM resume\n");
7262 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,71)
7264 +#include <linux/sysdev.h>
7266 +static int perfctr_device_suspend(struct sys_device *dev, u32 state)
7268 + perfctr_pm_suspend();
7272 +static int perfctr_device_resume(struct sys_device *dev)
7274 + perfctr_pm_resume();
7278 +static struct sysdev_class perfctr_sysclass = {
7279 + set_kset_name("perfctr"),
7280 + .resume = perfctr_device_resume,
7281 + .suspend = perfctr_device_suspend,
7284 +static struct sys_device device_perfctr = {
7286 + .cls = &perfctr_sysclass,
7289 +static void x86_pm_init(void)
7291 + if( sysdev_class_register(&perfctr_sysclass) == 0 )
7292 + sysdev_register(&device_perfctr);
7295 +static void x86_pm_exit(void)
7297 + sysdev_unregister(&device_perfctr);
7298 + sysdev_class_unregister(&perfctr_sysclass);
7301 +#else /* 2.4 kernel */
7303 +static int x86_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
7307 + perfctr_pm_suspend();
7310 + perfctr_pm_resume();
7316 +static struct pm_dev *x86_pmdev;
7318 +static void x86_pm_init(void)
7320 + x86_pmdev = apic_pm_register(PM_SYS_DEV, 0, x86_pm_callback);
7323 +static void x86_pm_exit(void)
7326 + apic_pm_unregister(x86_pmdev);
7331 +#endif /* 2.4 kernel */
7335 +static inline void x86_pm_init(void) { }
7336 +static inline void x86_pm_exit(void) { }
7338 +#endif /* CONFIG_PM */
7340 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,71)
7341 +static void disable_lapic_nmi_watchdog(void)
7345 + apic_pm_unregister(nmi_pmdev);
7352 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6)
7353 +static int reserve_lapic_nmi(void)
7356 + if( nmi_perfctr_msr ) {
7357 + nmi_perfctr_msr = 0;
7358 + disable_lapic_nmi_watchdog();
7364 +static inline void release_lapic_nmi(void) { }
7367 +static void do_init_tests(void)
7369 +#ifdef CONFIG_PERFCTR_INIT_TESTS
7370 + if( reserve_lapic_nmi() >= 0 ) {
7371 + perfctr_x86_init_tests();
7372 + release_lapic_nmi();
7377 +static void invalidate_per_cpu_cache(void)
7380 + * per_cpu_cache[] is initialised to contain "impossible"
7381 + * evntsel values guaranteed to differ from anything accepted
7382 + * by perfctr_cpu_update_control(). This way, initialisation of
7383 + * a CPU's evntsel MSRs will happen automatically the first time
7384 + * perfctr_cpu_write_control() executes on it.
7385 + * All-bits-one works for all currently supported processors.
7386 + * The memset also sets the ids to -1, which is intentional.
7388 + memset(per_cpu_cache, ~0, sizeof per_cpu_cache);
7391 +int __init perfctr_cpu_init(void)
7393 + int err = -ENODEV;
7395 + preempt_disable();
7397 + /* RDPMC and RDTSC are on by default. They will be disabled
7398 + by the init procedures if necessary. */
7399 + perfctr_info.cpu_features = PERFCTR_FEATURE_RDPMC | PERFCTR_FEATURE_RDTSC;
7401 + switch( boot_cpu_data.x86_vendor ) {
7402 + case X86_VENDOR_AMD:
7407 + err = generic_init(); /* last resort */
7414 + * Put the hardware in a sane state:
7415 + * - clear perfctr MSRs
7416 + * - set up APIC_LVTPC
7417 + * - set CR4.PCE [on permanently due to __flush_tlb_global()]
7418 + * - install our default interrupt handler
7420 + if( perfctr_info.cpu_features & PERFCTR_FEATURE_RDPMC )
7421 + mmu_cr4_features |= X86_CR4_PCE;
7422 + perfctr_cpu_init_one(NULL);
7423 + smp_call_function(perfctr_cpu_init_one, NULL, 1, 1);
7424 + perfctr_cpu_set_ihandler(NULL);
7426 + * Fix up the connection to the local APIC:
7427 + * - disable and disconnect the NMI watchdog
7428 + * - register our PM callback
7430 + disable_nmi_watchdog();
7434 + invalidate_per_cpu_cache();
7436 + perfctr_info.cpu_khz = perfctr_cpu_khz();
7437 + perfctr_info.tsc_to_cpu_mult = 1;
7444 +void __exit perfctr_cpu_exit(void)
7447 + preempt_disable();
7448 + if( perfctr_info.cpu_features & PERFCTR_FEATURE_RDPMC )
7449 + mmu_cr4_features &= ~X86_CR4_PCE;
7450 + perfctr_cpu_exit_one(NULL);
7451 + smp_call_function(perfctr_cpu_exit_one, NULL, 1, 1);
7452 + perfctr_cpu_set_ihandler(NULL);
7454 + /* XXX: restart nmi watchdog? */
7459 +/****************************************************************
7461 + * Hardware reservation. *
7463 + ****************************************************************/
7465 +static DECLARE_MUTEX(mutex);
7466 +static const char *current_service = 0;
7468 +const char *perfctr_cpu_reserve(const char *service)
7473 + ret = current_service;
7476 + ret = "unknown driver (oprofile?)";
7477 + if( reserve_lapic_nmi() < 0 )
7479 + current_service = service;
7480 + __module_get(THIS_MODULE);
7481 + if( perfctr_info.cpu_features & PERFCTR_FEATURE_RDPMC )
7482 + mmu_cr4_features |= X86_CR4_PCE;
7483 + on_each_cpu(perfctr_cpu_init_one, NULL, 1, 1);
7484 + perfctr_cpu_set_ihandler(NULL);
7492 +void perfctr_cpu_release(const char *service)
7495 + if( service != current_service ) {
7496 + printk(KERN_ERR "%s: attempt by %s to release while reserved by %s\n",
7497 + __FUNCTION__, service, current_service);
7500 + /* power down the counters */
7501 + invalidate_per_cpu_cache();
7502 + if( perfctr_info.cpu_features & PERFCTR_FEATURE_RDPMC )
7503 + mmu_cr4_features &= ~X86_CR4_PCE;
7504 + on_each_cpu(perfctr_cpu_exit_one, NULL, 1, 1);
7505 + perfctr_cpu_set_ihandler(NULL);
7507 + current_service = 0;
7508 + release_lapic_nmi();
7509 + module_put(THIS_MODULE);
7513 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86.c
7514 ===================================================================
7515 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/drivers/perfctr/x86.c 1969-12-31 19:00:00.000000000 -0500
7516 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/drivers/perfctr/x86.c 2004-11-18 20:59:11.000000000 -0500
7518 +/* $Id: x86.c,v 1.127.2.13 2004/09/14 17:56:42 mikpe Exp $
7519 + * x86/x86_64 performance-monitoring counters driver.
7521 + * Copyright (C) 1999-2004 Mikael Pettersson
7523 +#include <linux/config.h>
7524 +#define __NO_VERSION__
7525 +#include <linux/module.h>
7526 +#include <linux/init.h>
7527 +#include <linux/sched.h>
7528 +#include <linux/fs.h>
7529 +#include <linux/perfctr.h>
7531 +#include <asm/msr.h>
7532 +#undef MSR_P6_PERFCTR0
7533 +#undef MSR_IA32_MISC_ENABLE
7534 +#include <asm/fixmap.h>
7535 +#include <asm/apic.h>
7536 +struct hw_interrupt_type;
7537 +#include <asm/hw_irq.h>
7539 +#include "compat.h"
7540 +#include "x86_compat.h"
7541 +#include "x86_tests.h"
7543 +/* Support for lazy evntsel and perfctr MSR updates. */
7544 +struct per_cpu_cache { /* roughly a subset of perfctr_cpu_state */
7546 + unsigned int p5_cesr;
7547 + unsigned int id; /* cache owner id */
7550 + /* NOTE: these caches have physical indices, not virtual */
7551 + unsigned int evntsel[18];
7552 + unsigned int escr[0x3E2-0x3A0];
7553 + unsigned int pebs_enable;
7554 + unsigned int pebs_matrix_vert;
7556 +} ____cacheline_aligned;
7557 +static struct per_cpu_cache per_cpu_cache[NR_CPUS] __cacheline_aligned;
7558 +#define __get_cpu_cache(cpu) (&per_cpu_cache[cpu])
7559 +#define get_cpu_cache() __get_cpu_cache(smp_processor_id())
7561 +/* Structure for counter snapshots, as 32-bit values. */
7562 +struct perfctr_low_ctrs {
7564 + unsigned int pmc[18];
7567 +/* Intel P5, Cyrix 6x86MX/MII/III, Centaur WinChip C6/2/3 */
7568 +#define MSR_P5_CESR 0x11
7569 +#define MSR_P5_CTR0 0x12 /* .. 0x13 */
7570 +#define P5_CESR_CPL 0x00C0
7571 +#define P5_CESR_RESERVED (~0x01FF)
7572 +#define MII_CESR_RESERVED (~0x05FF)
7573 +#define C6_CESR_RESERVED (~0x00FF)
7575 +/* Intel P6, VIA C3 */
7576 +#define MSR_P6_PERFCTR0 0xC1 /* .. 0xC2 */
7577 +#define MSR_P6_EVNTSEL0 0x186 /* .. 0x187 */
7578 +#define P6_EVNTSEL_ENABLE 0x00400000
7579 +#define P6_EVNTSEL_INT 0x00100000
7580 +#define P6_EVNTSEL_CPL 0x00030000
7581 +#define P6_EVNTSEL_RESERVED 0x00280000
7582 +#define VC3_EVNTSEL1_RESERVED (~0x1FF)
7585 +#define MSR_K7_EVNTSEL0 0xC0010000 /* .. 0xC0010003 */
7586 +#define MSR_K7_PERFCTR0 0xC0010004 /* .. 0xC0010007 */
7588 +/* Intel P4, Intel Pentium M */
7589 +#define MSR_IA32_MISC_ENABLE 0x1A0
7590 +#define MSR_IA32_MISC_ENABLE_PERF_AVAIL (1<<7) /* read-only status bit */
7591 +#define MSR_IA32_MISC_ENABLE_PEBS_UNAVAIL (1<<12) /* read-only status bit */
7594 +#define MSR_P4_PERFCTR0 0x300 /* .. 0x311 */
7595 +#define MSR_P4_CCCR0 0x360 /* .. 0x371 */
7596 +#define MSR_P4_ESCR0 0x3A0 /* .. 0x3E1, with some gaps */
7598 +#define MSR_P4_PEBS_ENABLE 0x3F1
7599 +#define P4_PE_REPLAY_TAG_BITS 0x00000607
7600 +#define P4_PE_UOP_TAG 0x01000000
7601 +#define P4_PE_RESERVED 0xFEFFF9F8 /* only allow ReplayTagging */
7603 +#define MSR_P4_PEBS_MATRIX_VERT 0x3F2
7604 +#define P4_PMV_REPLAY_TAG_BITS 0x00000003
7605 +#define P4_PMV_RESERVED 0xFFFFFFFC
7607 +#define P4_CCCR_OVF 0x80000000
7608 +#define P4_CCCR_CASCADE 0x40000000
7609 +#define P4_CCCR_OVF_PMI_T1 0x08000000
7610 +#define P4_CCCR_OVF_PMI_T0 0x04000000
7611 +#define P4_CCCR_FORCE_OVF 0x02000000
7612 +#define P4_CCCR_ACTIVE_THREAD 0x00030000
7613 +#define P4_CCCR_ENABLE 0x00001000
7614 +#define P4_CCCR_ESCR_SELECT(X) (((X) >> 13) & 0x7)
7615 +#define P4_CCCR_EXTENDED_CASCADE 0x00000800
7616 +#define P4_CCCR_RESERVED (0x300007FF|P4_CCCR_OVF|P4_CCCR_OVF_PMI_T1)
7618 +#define P4_ESCR_CPL_T1 0x00000003
7619 +#define P4_ESCR_CPL_T0 0x0000000C
7620 +#define P4_ESCR_TAG_ENABLE 0x00000010
7621 +#define P4_ESCR_RESERVED (0x80000000)
7623 +#define P4_FAST_RDPMC 0x80000000
7624 +#define P4_MASK_FAST_RDPMC 0x0000001F /* we only need low 5 bits */
7626 +#define rdmsr_low(msr,low) \
7627 + __asm__ __volatile__("rdmsr" : "=a"(low) : "c"(msr) : "edx")
7628 +#define rdpmc_low(ctr,low) \
7629 + __asm__ __volatile__("rdpmc" : "=a"(low) : "c"(ctr) : "edx")
7631 +static void clear_msr_range(unsigned int base, unsigned int n)
7635 + for(i = 0; i < n; ++i)
7636 + wrmsr(base+i, 0, 0);
7639 +static inline void set_in_cr4_local(unsigned int mask)
7641 + write_cr4(read_cr4() | mask);
7644 +static inline void clear_in_cr4_local(unsigned int mask)
7646 + write_cr4(read_cr4() & ~mask);
7649 +static unsigned int new_id(void)
7651 + static spinlock_t lock = SPIN_LOCK_UNLOCKED;
7652 + static unsigned int counter;
7657 + spin_unlock(&lock);
7661 +#if !defined(CONFIG_X86_LOCAL_APIC)
7662 +#define perfctr_cstatus_has_ictrs(cstatus) 0
7663 +#undef cpu_has_apic
7664 +#define cpu_has_apic 0
7666 +#define apic_write(reg,vector) do{}while(0)
7669 +#if defined(CONFIG_SMP)
7672 +set_isuspend_cpu(struct perfctr_cpu_state *state, int cpu)
7674 + state->k1.isuspend_cpu = cpu;
7678 +is_isuspend_cpu(const struct perfctr_cpu_state *state, int cpu)
7680 + return state->k1.isuspend_cpu == cpu;
7683 +static inline void clear_isuspend_cpu(struct perfctr_cpu_state *state)
7685 + state->k1.isuspend_cpu = NR_CPUS;
7689 +static inline void set_isuspend_cpu(struct perfctr_cpu_state *state, int cpu) { }
7690 +static inline int is_isuspend_cpu(const struct perfctr_cpu_state *state, int cpu) { return 1; }
7691 +static inline void clear_isuspend_cpu(struct perfctr_cpu_state *state) { }
7694 +/****************************************************************
7696 + * Driver procedures. *
7698 + ****************************************************************/
7701 + * Intel P5 family (Pentium, family code 5).
7702 + * - One TSC and two 40-bit PMCs.
7703 + * - A single 32-bit CESR (MSR 0x11) controls both PMCs.
7704 + * CESR has two halves, each controlling one PMC.
7705 + * To keep the API reasonably clean, the user puts 16 bits of
7706 + * control data in each counter's evntsel; the driver combines
7707 + * these to a single 32-bit CESR value.
7708 + * - Overflow interrupts are not available.
7709 + * - Pentium MMX added the RDPMC instruction. RDPMC has lower
7710 + * overhead than RDMSR and it can be used in user-mode code.
7711 + * - The MMX events are not symmetric: some events are only available
7712 + * for some PMC, and some event codes denote different events
7713 + * depending on which PMCs they control.
7716 +/* shared with MII and C6 */
7717 +static int p5_like_check_control(struct perfctr_cpu_state *state,
7718 + unsigned int reserved_bits, int is_c6)
7720 + unsigned short cesr_half[2];
7721 + unsigned int pmc, evntsel, i;
7723 + if (state->control.nrictrs != 0 || state->control.nractrs > 2)
7727 + for(i = 0; i < state->control.nractrs; ++i) {
7728 + pmc = state->control.pmc_map[i];
7729 + state->pmc[i].map = pmc;
7730 + if (pmc > 1 || cesr_half[pmc] != 0)
7732 + evntsel = state->control.evntsel[i];
7733 + /* protect reserved bits */
7734 + if ((evntsel & reserved_bits) != 0)
7736 + /* the CPL field (if defined) must be non-zero */
7737 + if (!is_c6 && !(evntsel & P5_CESR_CPL))
7739 + cesr_half[pmc] = evntsel;
7741 + state->k1.id = (cesr_half[1] << 16) | cesr_half[0];
7745 +static int p5_check_control(struct perfctr_cpu_state *state, int is_global)
7747 + return p5_like_check_control(state, P5_CESR_RESERVED, 0);
7750 +/* shared with MII but not C6 */
7751 +static void p5_write_control(const struct perfctr_cpu_state *state)
7753 + struct per_cpu_cache *cache;
7754 + unsigned int cesr;
7756 + cesr = state->k1.id;
7757 + if (!cesr) /* no PMC is on (this test doesn't work on C6) */
7759 + cache = get_cpu_cache();
7760 + if (cache->k1.p5_cesr != cesr) {
7761 + cache->k1.p5_cesr = cesr;
7762 + wrmsr(MSR_P5_CESR, cesr, 0);
7766 +static void p5_read_counters(const struct perfctr_cpu_state *state,
7767 + struct perfctr_low_ctrs *ctrs)
7769 + unsigned int cstatus, nrctrs, i;
7771 + /* The P5 doesn't allocate a cache line on a write miss, so do
7772 + a dummy read to avoid a write miss here _and_ a read miss
7773 + later in our caller. */
7774 + asm("" : : "r"(ctrs->tsc));
7776 + cstatus = state->cstatus;
7777 + if (perfctr_cstatus_has_tsc(cstatus))
7778 + rdtscl(ctrs->tsc);
7779 + nrctrs = perfctr_cstatus_nractrs(cstatus);
7780 + for(i = 0; i < nrctrs; ++i) {
7781 + unsigned int pmc = state->pmc[i].map;
7782 + rdmsr_low(MSR_P5_CTR0+pmc, ctrs->pmc[i]);
7786 +/* used by all except pre-MMX P5 */
7787 +static void rdpmc_read_counters(const struct perfctr_cpu_state *state,
7788 + struct perfctr_low_ctrs *ctrs)
7790 + unsigned int cstatus, nrctrs, i;
7792 + cstatus = state->cstatus;
7793 + if (perfctr_cstatus_has_tsc(cstatus))
7794 + rdtscl(ctrs->tsc);
7795 + nrctrs = perfctr_cstatus_nractrs(cstatus);
7796 + for(i = 0; i < nrctrs; ++i) {
7797 + unsigned int pmc = state->pmc[i].map;
7798 + rdpmc_low(pmc, ctrs->pmc[i]);
7802 +/* shared with MII and C6 */
7803 +static void p5_clear_counters(void)
7805 + clear_msr_range(MSR_P5_CESR, 1+2);
7809 + * Cyrix 6x86/MII/III.
7810 + * - Same MSR assignments as P5 MMX. Has RDPMC and two 48-bit PMCs.
7811 + * - Event codes and CESR formatting as in the plain P5 subset.
7812 + * - Many but not all P5 MMX event codes are implemented.
7813 + * - Cyrix adds a few more event codes. The event code is widened
7814 + * to 7 bits, and Cyrix puts the high bit in CESR bit 10
7815 + * (and CESR bit 26 for PMC1).
7818 +static int mii_check_control(struct perfctr_cpu_state *state, int is_global)
7820 + return p5_like_check_control(state, MII_CESR_RESERVED, 0);
7824 + * Centaur WinChip C6/2/3.
7825 + * - Same MSR assignments as P5 MMX. Has RDPMC and two 40-bit PMCs.
7826 + * - CESR is formatted with two halves, like P5. However, there
7827 + * are no defined control fields for e.g. CPL selection, and
7828 + * there is no defined method for stopping the counters.
7829 + * - Only a few event codes are defined.
7830 + * - The 64-bit TSC is synthesised from the low 32 bits of the
7831 + * two PMCs, and CESR has to be set up appropriately.
7832 + * Reprogramming CESR causes RDTSC to yield invalid results.
7833 + * (The C6 may also hang in this case, due to C6 erratum I-13.)
7834 + * Therefore, using the PMCs on any of these processors requires
7835 + * that the TSC is not accessed at all:
7836 + * 1. The kernel must be configured or a TSC-less processor, i.e.
7837 + * generic 586 or less.
7838 + * 2. The "notsc" boot parameter must be passed to the kernel.
7839 + * 3. User-space libraries and code must also be configured and
7840 + * compiled for a generic 586 or less.
7843 +#if !defined(CONFIG_X86_TSC)
7844 +static int c6_check_control(struct perfctr_cpu_state *state, int is_global)
7846 + if (state->control.tsc_on)
7848 + return p5_like_check_control(state, C6_CESR_RESERVED, 1);
7851 +static void c6_write_control(const struct perfctr_cpu_state *state)
7853 + struct per_cpu_cache *cache;
7854 + unsigned int cesr;
7856 + if (perfctr_cstatus_nractrs(state->cstatus) == 0) /* no PMC is on */
7858 + cache = get_cpu_cache();
7859 + cesr = state->k1.id;
7860 + if (cache->k1.p5_cesr != cesr) {
7861 + cache->k1.p5_cesr = cesr;
7862 + wrmsr(MSR_P5_CESR, cesr, 0);
7868 + * Intel P6 family (Pentium Pro, Pentium II, and Pentium III cores,
7869 + * and Xeon and Celeron versions of Pentium II and III cores).
7870 + * - One TSC and two 40-bit PMCs.
7871 + * - One 32-bit EVNTSEL MSR for each PMC.
7872 + * - EVNTSEL0 contains a global enable/disable bit.
7873 + * That bit is reserved in EVNTSEL1.
7874 + * - Each EVNTSEL contains a CPL field.
7875 + * - Overflow interrupts are possible, but requires that the
7876 + * local APIC is available. Some Mobile P6s have no local APIC.
7877 + * - The PMCs cannot be initialised with arbitrary values, since
7878 + * wrmsr fills the high bits by sign-extending from bit 31.
7879 + * - Most events are symmetric, but a few are not.
7882 +/* shared with K7 */
7883 +static int p6_like_check_control(struct perfctr_cpu_state *state, int is_k7)
7885 + unsigned int evntsel, i, nractrs, nrctrs, pmc_mask, pmc;
7887 + nractrs = state->control.nractrs;
7888 + nrctrs = nractrs + state->control.nrictrs;
7889 + if (nrctrs < nractrs || nrctrs > (is_k7 ? 4 : 2))
7893 + for(i = 0; i < nrctrs; ++i) {
7894 + pmc = state->control.pmc_map[i];
7895 + state->pmc[i].map = pmc;
7896 + if (pmc >= (is_k7 ? 4 : 2) || (pmc_mask & (1<<pmc)))
7898 + pmc_mask |= (1<<pmc);
7899 + evntsel = state->control.evntsel[i];
7900 + /* protect reserved bits */
7901 + if (evntsel & P6_EVNTSEL_RESERVED)
7903 + /* check ENable bit */
7905 + /* ENable bit must be set in each evntsel */
7906 + if (!(evntsel & P6_EVNTSEL_ENABLE))
7909 + /* only evntsel[0] has the ENable bit */
7910 + if (evntsel & P6_EVNTSEL_ENABLE) {
7918 + /* the CPL field must be non-zero */
7919 + if (!(evntsel & P6_EVNTSEL_CPL))
7921 + /* INT bit must be off for a-mode and on for i-mode counters */
7922 + if (evntsel & P6_EVNTSEL_INT) {
7930 + state->k1.id = new_id();
7934 +static int p6_check_control(struct perfctr_cpu_state *state, int is_global)
7936 + return p6_like_check_control(state, 0);
7939 +#ifdef CONFIG_X86_LOCAL_APIC
7940 +/* PRE: perfctr_cstatus_has_ictrs(state->cstatus) != 0 */
7941 +/* shared with K7 and P4 */
7942 +static void p6_like_isuspend(struct perfctr_cpu_state *state,
7943 + unsigned int msr_evntsel0)
7945 + struct per_cpu_cache *cache;
7946 + unsigned int cstatus, nrctrs, i;
7949 + cpu = smp_processor_id();
7950 + set_isuspend_cpu(state, cpu); /* early to limit cpu's live range */
7951 + cache = __get_cpu_cache(cpu);
7952 + cstatus = state->cstatus;
7953 + nrctrs = perfctr_cstatus_nrctrs(cstatus);
7954 + for(i = perfctr_cstatus_nractrs(cstatus); i < nrctrs; ++i) {
7955 + unsigned int pmc_raw, pmc_idx, now;
7956 + pmc_raw = state->pmc[i].map;
7957 + /* Note: P4_MASK_FAST_RDPMC is a no-op for P6 and K7.
7958 + We don't need to make it into a parameter. */
7959 + pmc_idx = pmc_raw & P4_MASK_FAST_RDPMC;
7960 + cache->control.evntsel[pmc_idx] = 0;
7961 + /* On P4 this intensionally also clears the CCCR.OVF flag. */
7962 + wrmsr(msr_evntsel0+pmc_idx, 0, 0);
7963 + /* P4 erratum N17 does not apply since we read only low 32 bits. */
7964 + rdpmc_low(pmc_raw, now);
7965 + state->pmc[i].sum += now - state->pmc[i].start;
7966 + state->pmc[i].start = now;
7968 + /* cache->k1.id is still == state->k1.id */
7971 +/* PRE: perfctr_cstatus_has_ictrs(state->cstatus) != 0 */
7972 +/* shared with K7 and P4 */
7973 +static void p6_like_iresume(const struct perfctr_cpu_state *state,
7974 + unsigned int msr_evntsel0,
7975 + unsigned int msr_perfctr0)
7977 + struct per_cpu_cache *cache;
7978 + unsigned int cstatus, nrctrs, i;
7981 + cpu = smp_processor_id();
7982 + cache = __get_cpu_cache(cpu);
7983 + if (cache->k1.id == state->k1.id) {
7984 + cache->k1.id = 0; /* force reload of cleared EVNTSELs */
7985 + if (is_isuspend_cpu(state, cpu))
7986 + return; /* skip reload of PERFCTRs */
7988 + cstatus = state->cstatus;
7989 + nrctrs = perfctr_cstatus_nrctrs(cstatus);
7990 + for(i = perfctr_cstatus_nractrs(cstatus); i < nrctrs; ++i) {
7991 + /* Note: P4_MASK_FAST_RDPMC is a no-op for P6 and K7.
7992 + We don't need to make it into a parameter. */
7993 + unsigned int pmc = state->pmc[i].map & P4_MASK_FAST_RDPMC;
7994 + /* If the control wasn't ours we must disable the evntsels
7995 + before reinitialising the counters, to prevent unexpected
7996 + counter increments and missed overflow interrupts. */
7997 + if (cache->control.evntsel[pmc]) {
7998 + cache->control.evntsel[pmc] = 0;
7999 + wrmsr(msr_evntsel0+pmc, 0, 0);
8001 + /* P4 erratum N15 does not apply since the CCCR is disabled. */
8002 + wrmsr(msr_perfctr0+pmc, state->pmc[i].start, -1);
8004 + /* cache->k1.id remains != state->k1.id */
8007 +static void p6_isuspend(struct perfctr_cpu_state *state)
8009 + p6_like_isuspend(state, MSR_P6_EVNTSEL0);
8012 +static void p6_iresume(const struct perfctr_cpu_state *state)
8014 + p6_like_iresume(state, MSR_P6_EVNTSEL0, MSR_P6_PERFCTR0);
8016 +#endif /* CONFIG_X86_LOCAL_APIC */
8018 +/* shared with K7 and VC3 */
8019 +static void p6_like_write_control(const struct perfctr_cpu_state *state,
8020 + unsigned int msr_evntsel0)
8022 + struct per_cpu_cache *cache;
8023 + unsigned int nrctrs, i;
8025 + cache = get_cpu_cache();
8026 + if (cache->k1.id == state->k1.id)
8028 + nrctrs = perfctr_cstatus_nrctrs(state->cstatus);
8029 + for(i = 0; i < nrctrs; ++i) {
8030 + unsigned int evntsel = state->control.evntsel[i];
8031 + unsigned int pmc = state->pmc[i].map;
8032 + if (evntsel != cache->control.evntsel[pmc]) {
8033 + cache->control.evntsel[pmc] = evntsel;
8034 + wrmsr(msr_evntsel0+pmc, evntsel, 0);
8037 + cache->k1.id = state->k1.id;
8040 +/* shared with VC3, Generic*/
8041 +static void p6_write_control(const struct perfctr_cpu_state *state)
8043 + p6_like_write_control(state, MSR_P6_EVNTSEL0);
8046 +static void p6_clear_counters(void)
8048 + clear_msr_range(MSR_P6_EVNTSEL0, 2);
8049 + clear_msr_range(MSR_P6_PERFCTR0, 2);
8053 + * AMD K7 family (Athlon, Duron).
8054 + * - Somewhat similar to the Intel P6 family.
8055 + * - Four 48-bit PMCs.
8056 + * - Four 32-bit EVNTSEL MSRs with similar layout as in P6.
8057 + * - Completely different MSR assignments :-(
8058 + * - Fewer countable events defined :-(
8059 + * - The events appear to be completely symmetric.
8060 + * - The EVNTSEL MSRs are symmetric since each has its own enable bit.
8061 + * - Publicly available documentation is incomplete.
8062 + * - K7 model 1 does not have a local APIC. AMD Document #22007
8063 + * Revision J hints that it may use debug interrupts instead.
8065 + * The K8 has the same hardware layout as the K7. It also has
8066 + * better documentation and a different set of available events.
8069 +static int k7_check_control(struct perfctr_cpu_state *state, int is_global)
8071 + return p6_like_check_control(state, 1);
8074 +#ifdef CONFIG_X86_LOCAL_APIC
8075 +static void k7_isuspend(struct perfctr_cpu_state *state)
8077 + p6_like_isuspend(state, MSR_K7_EVNTSEL0);
8080 +static void k7_iresume(const struct perfctr_cpu_state *state)
8082 + p6_like_iresume(state, MSR_K7_EVNTSEL0, MSR_K7_PERFCTR0);
8084 +#endif /* CONFIG_X86_LOCAL_APIC */
8086 +static void k7_write_control(const struct perfctr_cpu_state *state)
8088 + p6_like_write_control(state, MSR_K7_EVNTSEL0);
8091 +static void k7_clear_counters(void)
8093 + clear_msr_range(MSR_K7_EVNTSEL0, 4+4);
8098 + * - A Centaur design somewhat similar to the P6/Celeron.
8099 + * - PERFCTR0 is an alias for the TSC, and EVNTSEL0 is read-only.
8100 + * - PERFCTR1 is 32 bits wide.
8101 + * - EVNTSEL1 has no defined control fields, and there is no
8102 + * defined method for stopping the counter.
8103 + * - According to testing, the reserved fields in EVNTSEL1 have
8104 + * no function. We always fill them with zeroes.
8105 + * - Only a few event codes are defined.
8106 + * - No local APIC or interrupt-mode support.
8107 + * - pmc_map[0] must be 1, if nractrs == 1.
8109 +static int vc3_check_control(struct perfctr_cpu_state *state, int is_global)
8111 + if (state->control.nrictrs || state->control.nractrs > 1)
8113 + if (state->control.nractrs == 1) {
8114 + if (state->control.pmc_map[0] != 1)
8116 + state->pmc[0].map = 1;
8117 + if (state->control.evntsel[0] & VC3_EVNTSEL1_RESERVED)
8119 + state->k1.id = state->control.evntsel[0];
8125 +static void vc3_clear_counters(void)
8127 + /* Not documented, but seems to be default after boot. */
8128 + wrmsr(MSR_P6_EVNTSEL0+1, 0x00070079, 0);
8132 + * Intel Pentium 4.
8133 + * Current implementation restrictions:
8134 + * - No DS/PEBS support.
8137 + * - OVF_PMI+FORCE_OVF counters must have an ireset value of -1.
8138 + * This allows the regular overflow check to also handle FORCE_OVF
8139 + * counters. Not having this restriction would lead to MAJOR
8140 + * complications in the driver's "detect overflow counters" code.
8141 + * There is no loss of functionality since the ireset value doesn't
8142 + * affect the counter's PMI rate for FORCE_OVF counters.
8143 + * - In experiments with FORCE_OVF counters, and regular OVF_PMI
8144 + * counters with small ireset values between -8 and -1, it appears
8145 + * that the faulting instruction is subjected to a new PMI before
8146 + * it can complete, ad infinitum. This occurs even though the driver
8147 + * clears the CCCR (and in testing also the ESCR) and invokes a
8148 + * user-space signal handler before restoring the CCCR and resuming
8149 + * the instruction.
8153 + * Table 15-4 in the IA32 Volume 3 manual contains a 18x8 entry mapping
8154 + * from counter/CCCR number (0-17) and ESCR SELECT value (0-7) to the
8155 + * actual ESCR MSR number. This mapping contains some repeated patterns,
8156 + * so we can compact it to a 4x8 table of MSR offsets:
8158 + * 1. CCCRs 16 and 17 are mapped just like CCCRs 13 and 14, respectively.
8159 + * Thus, we only consider the 16 CCCRs 0-15.
8160 + * 2. The CCCRs are organised in pairs, and both CCCRs in a pair use the
8161 + * same mapping. Thus, we only consider the 8 pairs 0-7.
8162 + * 3. In each pair of pairs, the second odd-numbered pair has the same domain
8163 + * as the first even-numbered pair, and the range is 1+ the range of the
8164 + * the first even-numbered pair. For example, CCCR(0) and (1) map ESCR
8165 + * SELECT(7) to 0x3A0, and CCCR(2) and (3) map it to 0x3A1.
8166 + * The only exception is that pair (7) [CCCRs 14 and 15] does not have
8167 + * ESCR SELECT(3) in its domain, like pair (6) [CCCRs 12 and 13] has.
8168 + * NOTE: Revisions of IA32 Volume 3 older than #245472-007 had an error
8169 + * in this table: CCCRs 12, 13, and 16 had their mappings for ESCR SELECT
8170 + * values 2 and 3 swapped.
8171 + * 4. All MSR numbers are on the form 0x3??. Instead of storing these as
8172 + * 16-bit numbers, the table only stores the 8-bit offsets from 0x300.
8175 +static const unsigned char p4_cccr_escr_map[4][8] = {
8176 + /* 0x00 and 0x01 as is, 0x02 and 0x03 are +1 */
8177 + [0x00/4] { [7] 0xA0,
8185 + /* 0x04 and 0x05 as is, 0x06 and 0x07 are +1 */
8186 + [0x04/4] { [0] 0xC0,
8189 + /* 0x08 and 0x09 as is, 0x0A and 0x0B are +1 */
8190 + [0x08/4] { [1] 0xA4,
8195 + /* 0x0C, 0x0D, and 0x10 as is,
8196 + 0x0E, 0x0F, and 0x11 are +1 except [3] is not in the domain */
8197 + [0x0C/4] { [4] 0xB8,
8206 +static unsigned int p4_escr_addr(unsigned int pmc, unsigned int cccr_val)
8208 + unsigned int escr_select, pair, escr_offset;
8210 + escr_select = P4_CCCR_ESCR_SELECT(cccr_val);
8212 + return 0; /* pmc range error */
8214 + pmc -= 3; /* 0 <= pmc <= 0x0F */
8215 + pair = pmc / 2; /* 0 <= pair <= 7 */
8216 + escr_offset = p4_cccr_escr_map[pair / 2][escr_select];
8217 + if (!escr_offset || (pair == 7 && escr_select == 3))
8218 + return 0; /* ESCR SELECT range error */
8219 + return escr_offset + (pair & 1) + 0x300;
8222 +static int p4_IQ_ESCR_ok; /* only models <= 2 can use IQ_ESCR{0,1} */
8223 +static int p4_is_ht; /* affects several CCCR & ESCR fields */
8224 +static int p4_extended_cascade_ok; /* only models >= 2 can use extended cascading */
8226 +static int p4_check_control(struct perfctr_cpu_state *state, int is_global)
8228 + unsigned int i, nractrs, nrctrs, pmc_mask;
8230 + nractrs = state->control.nractrs;
8231 + nrctrs = nractrs + state->control.nrictrs;
8232 + if (nrctrs < nractrs || nrctrs > 18)
8236 + for(i = 0; i < nrctrs; ++i) {
8237 + unsigned int pmc, cccr_val, escr_val, escr_addr;
8238 + /* check that pmc_map[] is well-defined;
8239 + pmc_map[i] is what we pass to RDPMC, the PMC itself
8240 + is extracted by masking off the FAST_RDPMC flag */
8241 + pmc = state->control.pmc_map[i] & ~P4_FAST_RDPMC;
8242 + state->pmc[i].map = state->control.pmc_map[i];
8243 + if (pmc >= 18 || (pmc_mask & (1<<pmc)))
8245 + pmc_mask |= (1<<pmc);
8246 + /* check CCCR contents */
8247 + cccr_val = state->control.evntsel[i];
8248 + if (cccr_val & P4_CCCR_RESERVED)
8250 + if (cccr_val & P4_CCCR_EXTENDED_CASCADE) {
8251 + if (!p4_extended_cascade_ok)
8253 + if (!(pmc == 12 || pmc >= 15))
8256 + if ((cccr_val & P4_CCCR_ACTIVE_THREAD) != P4_CCCR_ACTIVE_THREAD && !p4_is_ht)
8258 + if (!(cccr_val & (P4_CCCR_ENABLE | P4_CCCR_CASCADE | P4_CCCR_EXTENDED_CASCADE)))
8260 + if (cccr_val & P4_CCCR_OVF_PMI_T0) {
8263 + if ((cccr_val & P4_CCCR_FORCE_OVF) &&
8264 + state->control.ireset[i] != -1)
8270 + /* check ESCR contents */
8271 + escr_val = state->control.p4.escr[i];
8272 + if (escr_val & P4_ESCR_RESERVED)
8274 + if ((escr_val & P4_ESCR_CPL_T1) && (!p4_is_ht || !is_global))
8276 + /* compute and cache ESCR address */
8277 + escr_addr = p4_escr_addr(pmc, cccr_val);
8279 + return -EINVAL; /* ESCR SELECT range error */
8280 + /* IQ_ESCR0 and IQ_ESCR1 only exist in models <= 2 */
8281 + if ((escr_addr & ~0x001) == 0x3BA && !p4_IQ_ESCR_ok)
8283 + /* XXX: Two counters could map to the same ESCR. Should we
8284 + check that they use the same ESCR value? */
8285 + state->p4_escr_map[i] = escr_addr - MSR_P4_ESCR0;
8287 + /* check ReplayTagging control (PEBS_ENABLE and PEBS_MATRIX_VERT) */
8288 + if (state->control.p4.pebs_enable) {
8291 + if (state->control.p4.pebs_enable & P4_PE_RESERVED)
8293 + if (!(state->control.p4.pebs_enable & P4_PE_UOP_TAG))
8295 + if (!(state->control.p4.pebs_enable & P4_PE_REPLAY_TAG_BITS))
8297 + if (state->control.p4.pebs_matrix_vert & P4_PMV_RESERVED)
8299 + if (!(state->control.p4.pebs_matrix_vert & P4_PMV_REPLAY_TAG_BITS))
8301 + } else if (state->control.p4.pebs_matrix_vert)
8303 + state->k1.id = new_id();
8307 +#ifdef CONFIG_X86_LOCAL_APIC
8308 +static void p4_isuspend(struct perfctr_cpu_state *state)
8310 + return p6_like_isuspend(state, MSR_P4_CCCR0);
8313 +static void p4_iresume(const struct perfctr_cpu_state *state)
8315 + return p6_like_iresume(state, MSR_P4_CCCR0, MSR_P4_PERFCTR0);
8317 +#endif /* CONFIG_X86_LOCAL_APIC */
8319 +static void p4_write_control(const struct perfctr_cpu_state *state)
8321 + struct per_cpu_cache *cache;
8322 + unsigned int nrctrs, i;
8324 + /* XXX: temporary debug check */
8325 + if (cpu_isset(smp_processor_id(), perfctr_cpus_forbidden_mask) &&
8326 + perfctr_cstatus_nrctrs(state->cstatus))
8327 + printk(KERN_ERR "%s: BUG! CPU %u is in the forbidden set\n",
8328 + __FUNCTION__, smp_processor_id());
8329 + cache = get_cpu_cache();
8330 + if (cache->k1.id == state->k1.id)
8332 + nrctrs = perfctr_cstatus_nrctrs(state->cstatus);
8333 + for(i = 0; i < nrctrs; ++i) {
8334 + unsigned int escr_val, escr_off, cccr_val, pmc;
8335 + escr_val = state->control.p4.escr[i];
8336 + escr_off = state->p4_escr_map[i];
8337 + if (escr_val != cache->control.escr[escr_off]) {
8338 + cache->control.escr[escr_off] = escr_val;
8339 + wrmsr(MSR_P4_ESCR0+escr_off, escr_val, 0);
8341 + cccr_val = state->control.evntsel[i];
8342 + pmc = state->pmc[i].map & P4_MASK_FAST_RDPMC;
8343 + if (cccr_val != cache->control.evntsel[pmc]) {
8344 + cache->control.evntsel[pmc] = cccr_val;
8345 + wrmsr(MSR_P4_CCCR0+pmc, cccr_val, 0);
8348 + if (state->control.p4.pebs_enable != cache->control.pebs_enable) {
8349 + cache->control.pebs_enable = state->control.p4.pebs_enable;
8350 + wrmsr(MSR_P4_PEBS_ENABLE, state->control.p4.pebs_enable, 0);
8352 + if (state->control.p4.pebs_matrix_vert != cache->control.pebs_matrix_vert) {
8353 + cache->control.pebs_matrix_vert = state->control.p4.pebs_matrix_vert;
8354 + wrmsr(MSR_P4_PEBS_MATRIX_VERT, state->control.p4.pebs_matrix_vert, 0);
8356 + cache->k1.id = state->k1.id;
8359 +static void p4_clear_counters(void)
8361 + /* MSR 0x3F0 seems to have a default value of 0xFC00, but current
8362 + docs doesn't fully define it, so leave it alone for now. */
8363 + /* clear PEBS_ENABLE and PEBS_MATRIX_VERT; they handle both PEBS
8364 + and ReplayTagging, and should exist even if PEBS is disabled */
8365 + clear_msr_range(0x3F1, 2);
8366 + clear_msr_range(0x3A0, 26);
8367 + if (p4_IQ_ESCR_ok)
8368 + clear_msr_range(0x3BA, 2);
8369 + clear_msr_range(0x3BC, 3);
8370 + clear_msr_range(0x3C0, 6);
8371 + clear_msr_range(0x3C8, 6);
8372 + clear_msr_range(0x3E0, 2);
8373 + clear_msr_range(MSR_P4_CCCR0, 18);
8374 + clear_msr_range(MSR_P4_PERFCTR0, 18);
8378 + * Generic driver for any x86 with a working TSC.
8381 +static int generic_check_control(struct perfctr_cpu_state *state, int is_global)
8383 + if (state->control.nractrs || state->control.nrictrs)
8388 +static void generic_clear_counters(void)
8393 + * Driver methods, internal and exported.
8395 + * Frequently called functions (write_control, read_counters,
8396 + * isuspend and iresume) are back-patched to invoke the correct
8397 + * processor-specific methods directly, thereby saving the
8398 + * overheads of indirect function calls.
8400 + * Backpatchable call sites must have been "finalised" after
8401 + * initialisation. The reason for this is that unsynchronised code
8402 + * modification doesn't work in multiprocessor systems, due to
8403 + * Intel P6 errata. Consequently, all backpatchable call sites
8404 + * must be known and local to this file.
8406 + * Backpatchable calls must initially be to 'noinline' stubs.
8407 + * Otherwise the compiler may inline the stubs, which breaks
8408 + * redirect_call() and finalise_backpatching().
8411 +static int redirect_call_disable;
8413 +static noinline void redirect_call(void *ra, void *to)
8415 + /* XXX: make this function __init later */
8416 + if (redirect_call_disable)
8417 + printk(KERN_ERR __FILE__ ":%s: unresolved call to %p at %p\n",
8418 + __FUNCTION__, to, ra);
8419 + /* we can only redirect `call near relative' instructions */
8420 + if (*((unsigned char*)ra - 5) != 0xE8) {
8421 + printk(KERN_WARNING __FILE__ ":%s: unable to redirect caller %p to %p\n",
8422 + __FUNCTION__, ra, to);
8425 + *(int*)((char*)ra - 4) = (char*)to - (char*)ra;
8428 +static void (*write_control)(const struct perfctr_cpu_state*);
8429 +static noinline void perfctr_cpu_write_control(const struct perfctr_cpu_state *state)
8431 + redirect_call(__builtin_return_address(0), write_control);
8432 + return write_control(state);
8435 +static void (*read_counters)(const struct perfctr_cpu_state*,
8436 + struct perfctr_low_ctrs*);
8437 +static noinline void perfctr_cpu_read_counters(const struct perfctr_cpu_state *state,
8438 + struct perfctr_low_ctrs *ctrs)
8440 + redirect_call(__builtin_return_address(0), read_counters);
8441 + return read_counters(state, ctrs);
8444 +#ifdef CONFIG_X86_LOCAL_APIC
8445 +static void (*cpu_isuspend)(struct perfctr_cpu_state*);
8446 +static noinline void perfctr_cpu_isuspend(struct perfctr_cpu_state *state)
8448 + redirect_call(__builtin_return_address(0), cpu_isuspend);
8449 + return cpu_isuspend(state);
8452 +static void (*cpu_iresume)(const struct perfctr_cpu_state*);
8453 +static noinline void perfctr_cpu_iresume(const struct perfctr_cpu_state *state)
8455 + redirect_call(__builtin_return_address(0), cpu_iresume);
8456 + return cpu_iresume(state);
8459 +/* Call perfctr_cpu_ireload() just before perfctr_cpu_resume() to
8460 + bypass internal caching and force a reload if the I-mode PMCs. */
8461 +void perfctr_cpu_ireload(struct perfctr_cpu_state *state)
8464 + clear_isuspend_cpu(state);
8466 + get_cpu_cache()->k1.id = 0;
8470 +/* PRE: the counters have been suspended and sampled by perfctr_cpu_suspend() */
8471 +static int lvtpc_reinit_needed;
8472 +unsigned int perfctr_cpu_identify_overflow(struct perfctr_cpu_state *state)
8474 + unsigned int cstatus, nrctrs, pmc, pmc_mask;
8476 + cstatus = state->cstatus;
8477 + pmc = perfctr_cstatus_nractrs(cstatus);
8478 + nrctrs = perfctr_cstatus_nrctrs(cstatus);
8480 + for(pmc_mask = 0; pmc < nrctrs; ++pmc) {
8481 + if ((int)state->pmc[pmc].start >= 0) { /* XXX: ">" ? */
8482 + /* XXX: "+=" to correct for overshots */
8483 + state->pmc[pmc].start = state->control.ireset[pmc];
8484 + pmc_mask |= (1 << pmc);
8485 + /* On a P4 we should now clear the OVF flag in the
8486 + counter's CCCR. However, p4_isuspend() already
8487 + did that as a side-effect of clearing the CCCR
8488 + in order to stop the i-mode counters. */
8491 + if (lvtpc_reinit_needed)
8492 + apic_write(APIC_LVTPC, LOCAL_PERFCTR_VECTOR);
8496 +static inline int check_ireset(const struct perfctr_cpu_state *state)
8498 + unsigned int nrctrs, i;
8500 + i = state->control.nractrs;
8501 + nrctrs = i + state->control.nrictrs;
8502 + for(; i < nrctrs; ++i)
8503 + if (state->control.ireset[i] >= 0)
8508 +static inline void setup_imode_start_values(struct perfctr_cpu_state *state)
8510 + unsigned int cstatus, nrctrs, i;
8512 + cstatus = state->cstatus;
8513 + nrctrs = perfctr_cstatus_nrctrs(cstatus);
8514 + for(i = perfctr_cstatus_nractrs(cstatus); i < nrctrs; ++i)
8515 + state->pmc[i].start = state->control.ireset[i];
8518 +static inline void debug_no_imode(const struct perfctr_cpu_state *state)
8520 +#ifdef CONFIG_PERFCTR_DEBUG
8521 + if (perfctr_cstatus_has_ictrs(state->cstatus))
8522 + printk(KERN_ERR "perfctr/x86.c: BUG! updating control in"
8523 + " perfctr %p on cpu %u while it has cstatus %x"
8524 + " (pid %d, comm %s)\n",
8525 + state, smp_processor_id(), state->cstatus,
8526 + current->pid, current->comm);
8530 +#else /* CONFIG_X86_LOCAL_APIC */
8531 +static inline void perfctr_cpu_isuspend(struct perfctr_cpu_state *state) { }
8532 +static inline void perfctr_cpu_iresume(const struct perfctr_cpu_state *state) { }
8533 +static inline int check_ireset(const struct perfctr_cpu_state *state) { return 0; }
8534 +static inline void setup_imode_start_values(struct perfctr_cpu_state *state) { }
8535 +static inline void debug_no_imode(const struct perfctr_cpu_state *state) { }
8536 +#endif /* CONFIG_X86_LOCAL_APIC */
8538 +static int (*check_control)(struct perfctr_cpu_state*, int);
8539 +int perfctr_cpu_update_control(struct perfctr_cpu_state *state, int is_global)
8543 + debug_no_imode(state);
8544 + clear_isuspend_cpu(state);
8545 + state->cstatus = 0;
8547 + /* disallow i-mode counters if we cannot catch the interrupts */
8548 + if (!(perfctr_info.cpu_features & PERFCTR_FEATURE_PCINT)
8549 + && state->control.nrictrs)
8552 + err = check_control(state, is_global);
8555 + err = check_ireset(state);
8558 + state->cstatus = perfctr_mk_cstatus(state->control.tsc_on,
8559 + state->control.nractrs,
8560 + state->control.nrictrs);
8561 + setup_imode_start_values(state);
8565 +void perfctr_cpu_suspend(struct perfctr_cpu_state *state)
8567 + unsigned int i, cstatus, nractrs;
8568 + struct perfctr_low_ctrs now;
8570 + if (perfctr_cstatus_has_ictrs(state->cstatus))
8571 + perfctr_cpu_isuspend(state);
8572 + perfctr_cpu_read_counters(state, &now);
8573 + cstatus = state->cstatus;
8574 + if (perfctr_cstatus_has_tsc(cstatus))
8575 + state->tsc_sum += now.tsc - state->tsc_start;
8576 + nractrs = perfctr_cstatus_nractrs(cstatus);
8577 + for(i = 0; i < nractrs; ++i)
8578 + state->pmc[i].sum += now.pmc[i] - state->pmc[i].start;
8579 + /* perfctr_cpu_disable_rdpmc(); */ /* not for x86 */
8582 +void perfctr_cpu_resume(struct perfctr_cpu_state *state)
8584 + if (perfctr_cstatus_has_ictrs(state->cstatus))
8585 + perfctr_cpu_iresume(state);
8586 + /* perfctr_cpu_enable_rdpmc(); */ /* not for x86 or global-mode */
8587 + perfctr_cpu_write_control(state);
8588 + //perfctr_cpu_read_counters(state, &state->start);
8590 + struct perfctr_low_ctrs now;
8591 + unsigned int i, cstatus, nrctrs;
8592 + perfctr_cpu_read_counters(state, &now);
8593 + cstatus = state->cstatus;
8594 + if (perfctr_cstatus_has_tsc(cstatus))
8595 + state->tsc_start = now.tsc;
8596 + nrctrs = perfctr_cstatus_nractrs(cstatus);
8597 + for(i = 0; i < nrctrs; ++i)
8598 + state->pmc[i].start = now.pmc[i];
8600 + /* XXX: if (SMP && start.tsc == now.tsc) ++now.tsc; */
8603 +void perfctr_cpu_sample(struct perfctr_cpu_state *state)
8605 + unsigned int i, cstatus, nractrs;
8606 + struct perfctr_low_ctrs now;
8608 + perfctr_cpu_read_counters(state, &now);
8609 + cstatus = state->cstatus;
8610 + if (perfctr_cstatus_has_tsc(cstatus)) {
8611 + state->tsc_sum += now.tsc - state->tsc_start;
8612 + state->tsc_start = now.tsc;
8614 + nractrs = perfctr_cstatus_nractrs(cstatus);
8615 + for(i = 0; i < nractrs; ++i) {
8616 + state->pmc[i].sum += now.pmc[i] - state->pmc[i].start;
8617 + state->pmc[i].start = now.pmc[i];
8621 +static void (*clear_counters)(void);
8622 +static void perfctr_cpu_clear_counters(void)
8624 + return clear_counters();
8627 +/****************************************************************
8629 + * Processor detection and initialisation procedures. *
8631 + ****************************************************************/
8633 +static inline void clear_perfctr_cpus_forbidden_mask(void)
8635 +#if !defined(perfctr_cpus_forbidden_mask)
8636 + cpus_clear(perfctr_cpus_forbidden_mask);
8640 +static inline void set_perfctr_cpus_forbidden_mask(cpumask_t mask)
8642 +#if !defined(perfctr_cpus_forbidden_mask)
8643 + perfctr_cpus_forbidden_mask = mask;
8647 +/* see comment above at redirect_call() */
8648 +static void __init finalise_backpatching(void)
8650 + struct per_cpu_cache *cache;
8651 + struct perfctr_cpu_state state;
8652 + cpumask_t old_mask;
8654 + old_mask = perfctr_cpus_forbidden_mask;
8655 + clear_perfctr_cpus_forbidden_mask();
8657 + cache = get_cpu_cache();
8658 + memset(cache, 0, sizeof *cache);
8659 + memset(&state, 0, sizeof state);
8661 + (perfctr_info.cpu_features & PERFCTR_FEATURE_PCINT)
8662 + ? __perfctr_mk_cstatus(0, 1, 0, 0)
8664 + perfctr_cpu_sample(&state);
8665 + perfctr_cpu_resume(&state);
8666 + perfctr_cpu_suspend(&state);
8668 + set_perfctr_cpus_forbidden_mask(old_mask);
8670 + redirect_call_disable = 1;
8675 +cpumask_t perfctr_cpus_forbidden_mask;
8677 +static void __init p4_ht_mask_setup_cpu(void *forbidden)
8679 + unsigned int local_apic_physical_id = cpuid_ebx(1) >> 24;
8680 + unsigned int logical_processor_id = local_apic_physical_id & 1;
8681 + if (logical_processor_id != 0)
8682 + /* We rely on cpu_set() being atomic! */
8683 + cpu_set(smp_processor_id(), *(cpumask_t*)forbidden);
8686 +static int __init p4_ht_smp_init(void)
8688 + cpumask_t forbidden;
8691 + cpus_clear(forbidden);
8692 + smp_call_function(p4_ht_mask_setup_cpu, &forbidden, 1, 1);
8693 + p4_ht_mask_setup_cpu(&forbidden);
8694 + if (cpus_empty(forbidden))
8696 + perfctr_cpus_forbidden_mask = forbidden;
8697 + printk(KERN_INFO "perfctr/x86.c: hyper-threaded P4s detected:"
8698 + " restricting access for CPUs");
8699 + for(cpu = 0; cpu < NR_CPUS; ++cpu)
8700 + if (cpu_isset(cpu, forbidden))
8701 + printk(" %u", cpu);
8706 +#define p4_ht_smp_init() (0)
8709 +static int __init p4_ht_init(void)
8711 + unsigned int nr_siblings;
8715 + nr_siblings = (cpuid_ebx(1) >> 16) & 0xFF;
8716 + if (nr_siblings > 2) {
8717 + printk(KERN_WARNING "perfctr/x86.c: hyper-threaded P4s detected:"
8718 + " unsupported number of siblings: %u -- bailing out\n",
8722 + if (nr_siblings < 2)
8724 + p4_is_ht = 1; /* needed even in a UP kernel */
8725 + return p4_ht_smp_init();
8728 +static int __init intel_init(void)
8730 + static char p5_name[] __initdata = "Intel P5";
8731 + static char p6_name[] __initdata = "Intel P6";
8732 + static char p4_name[] __initdata = "Intel P4";
8733 + unsigned int misc_enable;
8737 + switch (current_cpu_data.x86) {
8739 + if (cpu_has_mmx) {
8740 + perfctr_info.cpu_type = PERFCTR_X86_INTEL_P5MMX;
8741 + read_counters = rdpmc_read_counters;
8743 + /* Avoid Pentium Erratum 74. */
8744 + if (current_cpu_data.x86_model == 4 &&
8745 + (current_cpu_data.x86_mask == 4 ||
8746 + (current_cpu_data.x86_mask == 3 &&
8747 + ((cpuid_eax(1) >> 12) & 0x3) == 1)))
8748 + perfctr_info.cpu_features &= ~PERFCTR_FEATURE_RDPMC;
8750 + perfctr_info.cpu_type = PERFCTR_X86_INTEL_P5;
8751 + perfctr_info.cpu_features &= ~PERFCTR_FEATURE_RDPMC;
8752 + read_counters = p5_read_counters;
8754 + perfctr_set_tests_type(PTT_P5);
8755 + perfctr_cpu_name = p5_name;
8756 + write_control = p5_write_control;
8757 + check_control = p5_check_control;
8758 + clear_counters = p5_clear_counters;
8761 + if (current_cpu_data.x86_model == 9 ||
8762 + current_cpu_data.x86_model == 13) { /* Pentium M */
8763 + /* Pentium M added the MISC_ENABLE MSR from P4. */
8764 + rdmsr_low(MSR_IA32_MISC_ENABLE, misc_enable);
8765 + if (!(misc_enable & MSR_IA32_MISC_ENABLE_PERF_AVAIL))
8767 + /* Erratum Y3 probably does not apply since we
8768 + read only the low 32 bits. */
8769 + perfctr_info.cpu_type = PERFCTR_X86_INTEL_PENTM;
8770 + } else if (current_cpu_data.x86_model >= 7) { /* PIII */
8771 + perfctr_info.cpu_type = PERFCTR_X86_INTEL_PIII;
8772 + } else if (current_cpu_data.x86_model >= 3) { /* PII or Celeron */
8773 + perfctr_info.cpu_type = PERFCTR_X86_INTEL_PII;
8775 + perfctr_info.cpu_type = PERFCTR_X86_INTEL_P6;
8777 + /* Avoid Pentium Pro Erratum 26. */
8778 + if (current_cpu_data.x86_mask < 9)
8779 + perfctr_info.cpu_features &= ~PERFCTR_FEATURE_RDPMC;
8781 + perfctr_set_tests_type(PTT_P6);
8782 + perfctr_cpu_name = p6_name;
8783 + read_counters = rdpmc_read_counters;
8784 + write_control = p6_write_control;
8785 + check_control = p6_check_control;
8786 + clear_counters = p6_clear_counters;
8787 +#ifdef CONFIG_X86_LOCAL_APIC
8788 + if (cpu_has_apic) {
8789 + perfctr_info.cpu_features |= PERFCTR_FEATURE_PCINT;
8790 + cpu_isuspend = p6_isuspend;
8791 + cpu_iresume = p6_iresume;
8792 + /* P-M apparently inherited P4's LVTPC auto-masking :-( */
8793 + if (current_cpu_data.x86_model == 9 ||
8794 + current_cpu_data.x86_model == 13)
8795 + lvtpc_reinit_needed = 1;
8799 + case 15: /* Pentium 4 */
8800 + rdmsr_low(MSR_IA32_MISC_ENABLE, misc_enable);
8801 + if (!(misc_enable & MSR_IA32_MISC_ENABLE_PERF_AVAIL))
8803 + if (p4_ht_init() != 0)
8805 + if (current_cpu_data.x86_model <= 2)
8806 + p4_IQ_ESCR_ok = 1;
8807 + if (current_cpu_data.x86_model >= 2)
8808 + p4_extended_cascade_ok = 1;
8809 + if (current_cpu_data.x86_model >= 3) {
8810 + /* Model 3 removes IQ_ESCR{0,1} and adds one event. */
8811 + perfctr_info.cpu_type = PERFCTR_X86_INTEL_P4M3;
8812 + } else if (current_cpu_data.x86_model >= 2) {
8813 + /* Model 2 changed the ESCR Event Mask programming
8814 + details for several events. */
8815 + perfctr_info.cpu_type = PERFCTR_X86_INTEL_P4M2;
8817 + perfctr_info.cpu_type = PERFCTR_X86_INTEL_P4;
8819 + perfctr_set_tests_type(PTT_P4);
8820 + perfctr_cpu_name = p4_name;
8821 + read_counters = rdpmc_read_counters;
8822 + write_control = p4_write_control;
8823 + check_control = p4_check_control;
8824 + clear_counters = p4_clear_counters;
8825 +#ifdef CONFIG_X86_LOCAL_APIC
8826 + if (cpu_has_apic) {
8827 + perfctr_info.cpu_features |= PERFCTR_FEATURE_PCINT;
8828 + cpu_isuspend = p4_isuspend;
8829 + cpu_iresume = p4_iresume;
8830 + lvtpc_reinit_needed = 1;
8838 +static int __init amd_init(void)
8840 + static char amd_name[] __initdata = "AMD K7/K8";
8844 + switch (current_cpu_data.x86) {
8846 + perfctr_info.cpu_type = PERFCTR_X86_AMD_K7;
8848 + case 15: /* K8. Like a K7 with a different event set. */
8849 + if ((current_cpu_data.x86_model > 5) ||
8850 + (current_cpu_data.x86_model >= 4 && current_cpu_data.x86_mask >= 8)) {
8851 + perfctr_info.cpu_type = PERFCTR_X86_AMD_K8C;
8853 + perfctr_info.cpu_type = PERFCTR_X86_AMD_K8;
8859 + perfctr_set_tests_type(PTT_AMD);
8860 + perfctr_cpu_name = amd_name;
8861 + read_counters = rdpmc_read_counters;
8862 + write_control = k7_write_control;
8863 + check_control = k7_check_control;
8864 + clear_counters = k7_clear_counters;
8865 +#ifdef CONFIG_X86_LOCAL_APIC
8866 + if (cpu_has_apic) {
8867 + perfctr_info.cpu_features |= PERFCTR_FEATURE_PCINT;
8868 + cpu_isuspend = k7_isuspend;
8869 + cpu_iresume = k7_iresume;
8875 +static int __init cyrix_init(void)
8877 + static char mii_name[] __initdata = "Cyrix 6x86MX/MII/III";
8880 + switch (current_cpu_data.x86) {
8881 + case 6: /* 6x86MX, MII, or III */
8882 + perfctr_info.cpu_type = PERFCTR_X86_CYRIX_MII;
8883 + perfctr_set_tests_type(PTT_P5);
8884 + perfctr_cpu_name = mii_name;
8885 + read_counters = rdpmc_read_counters;
8886 + write_control = p5_write_control;
8887 + check_control = mii_check_control;
8888 + clear_counters = p5_clear_counters;
8894 +static int __init centaur_init(void)
8896 +#if !defined(CONFIG_X86_TSC)
8897 + static char winchip_name[] __initdata = "WinChip C6/2/3";
8899 + static char vc3_name[] __initdata = "VIA C3";
8900 + switch (current_cpu_data.x86) {
8901 +#if !defined(CONFIG_X86_TSC)
8903 + switch (current_cpu_data.x86_model) {
8904 + case 4: /* WinChip C6 */
8905 + perfctr_info.cpu_type = PERFCTR_X86_WINCHIP_C6;
8907 + case 8: /* WinChip 2, 2A, or 2B */
8908 + case 9: /* WinChip 3, a 2A with larger cache and lower voltage */
8909 + perfctr_info.cpu_type = PERFCTR_X86_WINCHIP_2;
8914 + perfctr_set_tests_type(PTT_WINCHIP);
8915 + perfctr_cpu_name = winchip_name;
8917 + * TSC must be inaccessible for perfctrs to work.
8919 + if (!(read_cr4() & X86_CR4_TSD) || cpu_has_tsc)
8921 + perfctr_info.cpu_features &= ~PERFCTR_FEATURE_RDTSC;
8922 + read_counters = rdpmc_read_counters;
8923 + write_control = c6_write_control;
8924 + check_control = c6_check_control;
8925 + clear_counters = p5_clear_counters;
8928 + case 6: /* VIA C3 */
8931 + switch (current_cpu_data.x86_model) {
8932 + case 6: /* Cyrix III */
8933 + case 7: /* Samuel 2, Ezra (steppings >= 8) */
8934 + case 8: /* Ezra-T */
8935 + case 9: /* Antaur/Nehemiah */
8940 + perfctr_info.cpu_type = PERFCTR_X86_VIA_C3;
8941 + perfctr_set_tests_type(PTT_VC3);
8942 + perfctr_cpu_name = vc3_name;
8943 + read_counters = rdpmc_read_counters;
8944 + write_control = p6_write_control;
8945 + check_control = vc3_check_control;
8946 + clear_counters = vc3_clear_counters;
8952 +static int __init generic_init(void)
8954 + static char generic_name[] __initdata = "Generic x86 with TSC";
8957 + perfctr_info.cpu_features &= ~PERFCTR_FEATURE_RDPMC;
8958 + perfctr_info.cpu_type = PERFCTR_X86_GENERIC;
8959 + perfctr_set_tests_type(PTT_GENERIC);
8960 + perfctr_cpu_name = generic_name;
8961 + check_control = generic_check_control;
8962 + write_control = p6_write_control;
8963 + read_counters = rdpmc_read_counters;
8964 + clear_counters = generic_clear_counters;
8968 +static void perfctr_cpu_invalidate_cache(void)
8971 + * per_cpu_cache[] is initialised to contain "impossible"
8972 + * evntsel values guaranteed to differ from anything accepted
8973 + * by perfctr_cpu_update_control().
8974 + * All-bits-one works for all currently supported processors.
8975 + * The memset also sets the ids to -1, which is intentional.
8977 + memset(get_cpu_cache(), ~0, sizeof(struct per_cpu_cache));
8980 +static void perfctr_cpu_init_one(void *ignore)
8982 + /* PREEMPT note: when called via smp_call_function(),
8983 + this is in IRQ context with preemption disabled. */
8984 + perfctr_cpu_clear_counters();
8985 + perfctr_cpu_invalidate_cache();
8987 + apic_write(APIC_LVTPC, LOCAL_PERFCTR_VECTOR);
8988 + if (perfctr_info.cpu_features & PERFCTR_FEATURE_RDPMC)
8989 + set_in_cr4_local(X86_CR4_PCE);
8992 +static void perfctr_cpu_exit_one(void *ignore)
8994 + /* PREEMPT note: when called via smp_call_function(),
8995 + this is in IRQ context with preemption disabled. */
8996 + perfctr_cpu_clear_counters();
8997 + perfctr_cpu_invalidate_cache();
8999 + apic_write(APIC_LVTPC, APIC_DM_NMI | APIC_LVT_MASKED);
9000 + if (perfctr_info.cpu_features & PERFCTR_FEATURE_RDPMC)
9001 + clear_in_cr4_local(X86_CR4_PCE);
9004 +#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PM)
9006 +static void perfctr_pm_suspend(void)
9008 + /* XXX: clear control registers */
9009 + printk("perfctr/x86: PM suspend\n");
9012 +static void perfctr_pm_resume(void)
9014 + /* XXX: reload control registers */
9015 + printk("perfctr/x86: PM resume\n");
9018 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,71)
9020 +#include <linux/sysdev.h>
9022 +static int perfctr_device_suspend(struct sys_device *dev, u32 state)
9024 + perfctr_pm_suspend();
9028 +static int perfctr_device_resume(struct sys_device *dev)
9030 + perfctr_pm_resume();
9034 +static struct sysdev_class perfctr_sysclass = {
9035 + set_kset_name("perfctr"),
9036 + .resume = perfctr_device_resume,
9037 + .suspend = perfctr_device_suspend,
9040 +static struct sys_device device_perfctr = {
9042 + .cls = &perfctr_sysclass,
9045 +static void x86_pm_init(void)
9047 + if (sysdev_class_register(&perfctr_sysclass) == 0)
9048 + sysdev_register(&device_perfctr);
9051 +static void x86_pm_exit(void)
9053 + sysdev_unregister(&device_perfctr);
9054 + sysdev_class_unregister(&perfctr_sysclass);
9057 +#else /* 2.4 kernel */
9059 +static int x86_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
9063 + perfctr_pm_suspend();
9066 + perfctr_pm_resume();
9072 +static struct pm_dev *x86_pmdev;
9074 +static void x86_pm_init(void)
9076 + x86_pmdev = apic_pm_register(PM_SYS_DEV, 0, x86_pm_callback);
9079 +static void x86_pm_exit(void)
9082 + apic_pm_unregister(x86_pmdev);
9087 +#endif /* 2.4 kernel */
9091 +static inline void x86_pm_init(void) { }
9092 +static inline void x86_pm_exit(void) { }
9094 +#endif /* CONFIG_X86_LOCAL_APIC && CONFIG_PM */
9096 +#ifdef CONFIG_X86_LOCAL_APIC
9098 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,67)
9099 +static void disable_lapic_nmi_watchdog(void)
9103 + apic_pm_unregister(nmi_pmdev);
9110 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6)
9111 +static int reserve_lapic_nmi(void)
9114 + if (nmi_perfctr_msr) {
9115 + nmi_perfctr_msr = 0;
9116 + disable_lapic_nmi_watchdog();
9122 +static inline void release_lapic_nmi(void) { }
9126 +static inline int reserve_lapic_nmi(void) { return 0; }
9127 +static inline void release_lapic_nmi(void) { }
9130 +static void do_init_tests(void)
9132 +#ifdef CONFIG_PERFCTR_INIT_TESTS
9133 + if (reserve_lapic_nmi() >= 0) {
9134 + perfctr_x86_init_tests();
9135 + release_lapic_nmi();
9140 +int __init perfctr_cpu_init(void)
9142 + int err = -ENODEV;
9144 + preempt_disable();
9146 + /* RDPMC and RDTSC are on by default. They will be disabled
9147 + by the init procedures if necessary. */
9148 + perfctr_info.cpu_features = PERFCTR_FEATURE_RDPMC | PERFCTR_FEATURE_RDTSC;
9150 + if (cpu_has_msr) {
9151 + switch (current_cpu_data.x86_vendor) {
9152 + case X86_VENDOR_INTEL:
9153 + err = intel_init();
9155 + case X86_VENDOR_AMD:
9158 + case X86_VENDOR_CYRIX:
9159 + err = cyrix_init();
9161 + case X86_VENDOR_CENTAUR:
9162 + err = centaur_init();
9166 + err = generic_init(); /* last resort */
9171 + finalise_backpatching();
9173 + perfctr_info.cpu_khz = perfctr_cpu_khz();
9174 + perfctr_info.tsc_to_cpu_mult = 1;
9181 +void __exit perfctr_cpu_exit(void)
9185 +/****************************************************************
9187 + * Hardware reservation. *
9189 + ****************************************************************/
9191 +static DECLARE_MUTEX(mutex);
9192 +static const char *current_service = 0;
9194 +const char *perfctr_cpu_reserve(const char *service)
9199 + ret = current_service;
9202 + ret = "unknown driver (oprofile?)";
9203 + if (reserve_lapic_nmi() < 0)
9205 + current_service = service;
9206 + __module_get(THIS_MODULE);
9207 + if (perfctr_info.cpu_features & PERFCTR_FEATURE_RDPMC)
9208 + mmu_cr4_features |= X86_CR4_PCE;
9209 + on_each_cpu(perfctr_cpu_init_one, NULL, 1, 1);
9210 + perfctr_cpu_set_ihandler(NULL);
9218 +void perfctr_cpu_release(const char *service)
9221 + if (service != current_service) {
9222 + printk(KERN_ERR "%s: attempt by %s to release while reserved by %s\n",
9223 + __FUNCTION__, service, current_service);
9226 + /* power down the counters */
9227 + if (perfctr_info.cpu_features & PERFCTR_FEATURE_RDPMC)
9228 + mmu_cr4_features &= ~X86_CR4_PCE;
9229 + on_each_cpu(perfctr_cpu_exit_one, NULL, 1, 1);
9230 + perfctr_cpu_set_ihandler(NULL);
9232 + current_service = 0;
9233 + release_lapic_nmi();
9234 + module_put(THIS_MODULE);
9238 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-i386/apic.h
9239 ===================================================================
9240 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/include/asm-i386/apic.h 2004-04-03 22:38:23.000000000 -0500
9241 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-i386/apic.h 2004-11-18 20:59:11.000000000 -0500
9243 #define NMI_LOCAL_APIC 2
9244 #define NMI_INVALID 3
9246 +extern unsigned int nmi_perfctr_msr;
9248 #endif /* CONFIG_X86_LOCAL_APIC */
9250 #endif /* __ASM_APIC_H */
9251 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-i386/mach-default/irq_vectors.h
9252 ===================================================================
9253 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/include/asm-i386/mach-default/irq_vectors.h 2004-11-11 10:27:51.000000000 -0500
9254 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-i386/mach-default/irq_vectors.h 2004-11-18 20:59:11.000000000 -0500
9256 * sources per level' errata.
9258 #define LOCAL_TIMER_VECTOR 0xef
9259 +#define LOCAL_PERFCTR_VECTOR 0xee
9262 - * First APIC vector available to drivers: (vectors 0x30-0xee)
9263 + * First APIC vector available to drivers: (vectors 0x30-0xed)
9264 * we start at 0x31 to spread out vectors evenly between priority
9265 * levels. (0x80 is the syscall vector)
9267 #define FIRST_DEVICE_VECTOR 0x31
9268 -#define FIRST_SYSTEM_VECTOR 0xef
9269 +#define FIRST_SYSTEM_VECTOR 0xee
9273 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-i386/mach-pc9800/irq_vectors.h
9274 ===================================================================
9275 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/include/asm-i386/mach-pc9800/irq_vectors.h 2004-04-03 22:36:16.000000000 -0500
9276 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-i386/mach-pc9800/irq_vectors.h 2004-11-18 20:59:11.000000000 -0500
9278 * sources per level' errata.
9280 #define LOCAL_TIMER_VECTOR 0xef
9281 +#define LOCAL_PERFCTR_VECTOR 0xee
9284 - * First APIC vector available to drivers: (vectors 0x30-0xee)
9285 + * First APIC vector available to drivers: (vectors 0x30-0xed)
9286 * we start at 0x31 to spread out vectors evenly between priority
9287 * levels. (0x80 is the syscall vector)
9289 #define FIRST_DEVICE_VECTOR 0x31
9290 -#define FIRST_SYSTEM_VECTOR 0xef
9291 +#define FIRST_SYSTEM_VECTOR 0xee
9295 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-i386/mach-visws/irq_vectors.h
9296 ===================================================================
9297 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/include/asm-i386/mach-visws/irq_vectors.h 2004-04-03 22:36:18.000000000 -0500
9298 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-i386/mach-visws/irq_vectors.h 2004-11-18 20:59:11.000000000 -0500
9300 * sources per level' errata.
9302 #define LOCAL_TIMER_VECTOR 0xef
9303 +#define LOCAL_PERFCTR_VECTOR 0xee
9306 - * First APIC vector available to drivers: (vectors 0x30-0xee)
9307 + * First APIC vector available to drivers: (vectors 0x30-0xed)
9308 * we start at 0x31 to spread out vectors evenly between priority
9309 * levels. (0x80 is the syscall vector)
9311 #define FIRST_DEVICE_VECTOR 0x31
9312 -#define FIRST_SYSTEM_VECTOR 0xef
9313 +#define FIRST_SYSTEM_VECTOR 0xee
9317 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-i386/processor.h
9318 ===================================================================
9319 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/include/asm-i386/processor.h 2004-11-11 10:27:40.000000000 -0500
9320 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-i386/processor.h 2004-11-18 20:59:11.000000000 -0500
9322 unsigned int saved_fs, saved_gs;
9323 /* IO permissions */
9324 unsigned long *io_bitmap_ptr;
9325 +/* performance counters */
9326 + struct vperfctr *perfctr;
9329 #define INIT_THREAD { \
9330 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-i386/perfctr.h
9331 ===================================================================
9332 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/include/asm-i386/perfctr.h 1969-12-31 19:00:00.000000000 -0500
9333 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-i386/perfctr.h 2004-11-18 20:59:11.000000000 -0500
9335 +/* $Id: perfctr.h,v 1.48.2.4 2004/08/02 22:24:58 mikpe Exp $
9336 + * x86/x86_64 Performance-Monitoring Counters driver
9338 + * Copyright (C) 1999-2004 Mikael Pettersson
9340 +#ifndef _ASM_I386_PERFCTR_H
9341 +#define _ASM_I386_PERFCTR_H
9343 +struct perfctr_sum_ctrs {
9344 + unsigned long long tsc;
9345 + unsigned long long pmc[18];
9348 +struct perfctr_cpu_control {
9349 + unsigned int tsc_on;
9350 + unsigned int nractrs; /* # of a-mode counters */
9351 + unsigned int nrictrs; /* # of i-mode counters */
9352 + unsigned int pmc_map[18];
9353 + unsigned int evntsel[18]; /* one per counter, even on P5 */
9355 + unsigned int escr[18];
9356 + unsigned int pebs_enable; /* for replay tagging */
9357 + unsigned int pebs_matrix_vert; /* for replay tagging */
9359 + int ireset[18]; /* < 0, for i-mode counters */
9360 + unsigned int _reserved1;
9361 + unsigned int _reserved2;
9362 + unsigned int _reserved3;
9363 + unsigned int _reserved4;
9366 +struct perfctr_cpu_state {
9367 + unsigned int cstatus;
9368 + struct { /* k1 is opaque in the user ABI */
9372 + /* The two tsc fields must be inlined. Placing them in a
9373 + sub-struct causes unwanted internal padding on x86-64. */
9374 + unsigned int tsc_start;
9375 + unsigned long long tsc_sum;
9378 + unsigned int start;
9379 + unsigned long long sum;
9380 + } pmc[18]; /* the size is not part of the user ABI */
9382 + struct perfctr_cpu_control control;
9383 + unsigned int p4_escr_map[18];
9387 +/* cstatus is a re-encoding of control.tsc_on/nractrs/nrictrs
9388 + which should have less overhead in most cases */
9391 +unsigned int __perfctr_mk_cstatus(unsigned int tsc_on, unsigned int have_ictrs,
9392 + unsigned int nrictrs, unsigned int nractrs)
9394 + return (tsc_on<<31) | (have_ictrs<<16) | ((nractrs+nrictrs)<<8) | nractrs;
9398 +unsigned int perfctr_mk_cstatus(unsigned int tsc_on, unsigned int nractrs,
9399 + unsigned int nrictrs)
9401 + return __perfctr_mk_cstatus(tsc_on, nrictrs, nrictrs, nractrs);
9404 +static inline unsigned int perfctr_cstatus_enabled(unsigned int cstatus)
9409 +static inline int perfctr_cstatus_has_tsc(unsigned int cstatus)
9411 + return (int)cstatus < 0; /* test and jump on sign */
9414 +static inline unsigned int perfctr_cstatus_nractrs(unsigned int cstatus)
9416 + return cstatus & 0x7F; /* and with imm8 */
9419 +static inline unsigned int perfctr_cstatus_nrctrs(unsigned int cstatus)
9421 + return (cstatus >> 8) & 0x7F;
9424 +static inline unsigned int perfctr_cstatus_has_ictrs(unsigned int cstatus)
9426 + return cstatus & (0x7F << 16);
9430 + * 'struct siginfo' support for perfctr overflow signals.
9431 + * In unbuffered mode, si_code is set to SI_PMC_OVF and a bitmask
9432 + * describing which perfctrs overflowed is put in si_pmc_ovf_mask.
9433 + * A bitmask is used since more than one perfctr can have overflowed
9434 + * by the time the interrupt handler runs.
9436 + * glibc's <signal.h> doesn't seem to define __SI_FAULT or __SI_CODE(),
9437 + * and including <asm/siginfo.h> as well may cause redefinition errors,
9438 + * so the user and kernel values are different #defines here.
9441 +#define SI_PMC_OVF (__SI_FAULT|'P')
9443 +#define SI_PMC_OVF ('P')
9445 +#define si_pmc_ovf_mask _sifields._pad[0] /* XXX: use an unsigned field later */
9447 +/* version number for user-visible CPU-specific data */
9448 +#define PERFCTR_CPU_VERSION 0x0501 /* 5.1 */
9452 +#if defined(CONFIG_PERFCTR) || defined(CONFIG_PERFCTR_MODULE)
9454 +/* Driver init/exit. */
9455 +extern int perfctr_cpu_init(void);
9456 +extern void perfctr_cpu_exit(void);
9458 +/* CPU type name. */
9459 +extern char *perfctr_cpu_name;
9461 +/* Hardware reservation. */
9462 +extern const char *perfctr_cpu_reserve(const char *service);
9463 +extern void perfctr_cpu_release(const char *service);
9465 +/* PRE: state has no running interrupt-mode counters.
9466 + Check that the new control data is valid.
9467 + Update the driver's private control data.
9468 + is_global should be zero for per-process counters and non-zero
9469 + for global-mode counters. This matters for HT P4s, alas.
9470 + Returns a negative error code if the control data is invalid. */
9471 +extern int perfctr_cpu_update_control(struct perfctr_cpu_state *state, int is_global);
9473 +/* Read a-mode counters. Subtract from start and accumulate into sums.
9474 + Must be called with preemption disabled. */
9475 +extern void perfctr_cpu_suspend(struct perfctr_cpu_state *state);
9477 +/* Write control registers. Read a-mode counters into start.
9478 + Must be called with preemption disabled. */
9479 +extern void perfctr_cpu_resume(struct perfctr_cpu_state *state);
9481 +/* Perform an efficient combined suspend/resume operation.
9482 + Must be called with preemption disabled. */
9483 +extern void perfctr_cpu_sample(struct perfctr_cpu_state *state);
9485 +/* The type of a perfctr overflow interrupt handler.
9486 + It will be called in IRQ context, with preemption disabled. */
9487 +typedef void (*perfctr_ihandler_t)(unsigned long pc);
9489 +#if defined(CONFIG_X86_LOCAL_APIC)
9490 +#define PERFCTR_INTERRUPT_SUPPORT 1
9493 +/* Operations related to overflow interrupt handling. */
9494 +#ifdef CONFIG_X86_LOCAL_APIC
9495 +extern void perfctr_cpu_set_ihandler(perfctr_ihandler_t);
9496 +extern void perfctr_cpu_ireload(struct perfctr_cpu_state*);
9497 +extern unsigned int perfctr_cpu_identify_overflow(struct perfctr_cpu_state*);
9499 +static inline void perfctr_cpu_set_ihandler(perfctr_ihandler_t x) { }
9502 +#if defined(CONFIG_SMP)
9503 +/* CPUs in `perfctr_cpus_forbidden_mask' must not use the
9504 + performance-monitoring counters. TSC use is unrestricted.
9505 + This is needed to prevent resource conflicts on hyper-threaded P4s.
9506 + The declaration of `perfctr_cpus_forbidden_mask' is in the driver's
9507 + private compat.h, since it needs to handle cpumask_t incompatibilities. */
9508 +#define PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED 1
9511 +#endif /* CONFIG_PERFCTR */
9513 +#if defined(CONFIG_KPERFCTR) && defined(CONFIG_X86_LOCAL_APIC)
9514 +asmlinkage void perfctr_interrupt(struct pt_regs*);
9515 +#define perfctr_vector_init() \
9516 + set_intr_gate(LOCAL_PERFCTR_VECTOR, perfctr_interrupt)
9518 +#define perfctr_vector_init() do{}while(0)
9521 +#endif /* __KERNEL__ */
9523 +#endif /* _ASM_I386_PERFCTR_H */
9524 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-ppc/processor.h
9525 ===================================================================
9526 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/include/asm-ppc/processor.h 2004-11-11 10:27:19.000000000 -0500
9527 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-ppc/processor.h 2004-11-18 20:59:11.000000000 -0500
9529 unsigned long vrsave;
9530 int used_vr; /* set if process has used altivec */
9531 #endif /* CONFIG_ALTIVEC */
9532 + struct vperfctr *perfctr; /* performance counters */
9535 #define ARCH_MIN_TASKALIGN 16
9536 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-ppc/perfctr.h
9537 ===================================================================
9538 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/include/asm-ppc/perfctr.h 1969-12-31 19:00:00.000000000 -0500
9539 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-ppc/perfctr.h 2004-11-18 20:59:11.000000000 -0500
9541 +/* $Id: perfctr.h,v 1.3.2.2 2004/06/21 22:38:30 mikpe Exp $
9542 + * PPC32 Performance-Monitoring Counters driver
9544 + * Copyright (C) 2004 Mikael Pettersson
9546 +#ifndef _ASM_PPC_PERFCTR_H
9547 +#define _ASM_PPC_PERFCTR_H
9549 +/* perfctr_info.cpu_type values */
9550 +#define PERFCTR_PPC_GENERIC 0
9551 +#define PERFCTR_PPC_604 1
9552 +#define PERFCTR_PPC_604e 2
9553 +#define PERFCTR_PPC_750 3
9554 +#define PERFCTR_PPC_7400 4
9555 +#define PERFCTR_PPC_7450 5
9557 +struct perfctr_sum_ctrs {
9558 + unsigned long long tsc;
9559 + unsigned long long pmc[6];
9562 +struct perfctr_cpu_control {
9563 + unsigned int tsc_on;
9564 + unsigned int nractrs; /* # of a-mode counters */
9565 + unsigned int nrictrs; /* # of i-mode counters */
9566 + unsigned int pmc_map[6];
9567 + unsigned int evntsel[6]; /* one per counter, even on P5 */
9568 + int ireset[6]; /* [0,0x7fffffff], for i-mode counters */
9570 + unsigned int mmcr0; /* sans PMC{1,2}SEL */
9571 + unsigned int mmcr2; /* only THRESHMULT */
9572 + /* IABR/DABR/BAMR not supported */
9574 + unsigned int _reserved1;
9575 + unsigned int _reserved2;
9576 + unsigned int _reserved3;
9577 + unsigned int _reserved4;
9580 +struct perfctr_cpu_state {
9581 + unsigned int cstatus;
9582 + struct { /* k1 is opaque in the user ABI */
9586 + /* The two tsc fields must be inlined. Placing them in a
9587 + sub-struct causes unwanted internal padding on x86-64. */
9588 + unsigned int tsc_start;
9589 + unsigned long long tsc_sum;
9592 + unsigned int start;
9593 + unsigned long long sum;
9594 + } pmc[6]; /* the size is not part of the user ABI */
9596 + unsigned int ppc_mmcr[3];
9597 + struct perfctr_cpu_control control;
9601 +/* cstatus is a re-encoding of control.tsc_on/nractrs/nrictrs
9602 + which should have less overhead in most cases */
9603 +/* XXX: ppc driver internally also uses cstatus&(1<<30) */
9606 +unsigned int perfctr_mk_cstatus(unsigned int tsc_on, unsigned int nractrs,
9607 + unsigned int nrictrs)
9609 + return (tsc_on<<31) | (nrictrs<<16) | ((nractrs+nrictrs)<<8) | nractrs;
9612 +static inline unsigned int perfctr_cstatus_enabled(unsigned int cstatus)
9617 +static inline int perfctr_cstatus_has_tsc(unsigned int cstatus)
9619 + return (int)cstatus < 0; /* test and jump on sign */
9622 +static inline unsigned int perfctr_cstatus_nractrs(unsigned int cstatus)
9624 + return cstatus & 0x7F; /* and with imm8 */
9627 +static inline unsigned int perfctr_cstatus_nrctrs(unsigned int cstatus)
9629 + return (cstatus >> 8) & 0x7F;
9632 +static inline unsigned int perfctr_cstatus_has_ictrs(unsigned int cstatus)
9634 + return cstatus & (0x7F << 16);
9638 + * 'struct siginfo' support for perfctr overflow signals.
9639 + * In unbuffered mode, si_code is set to SI_PMC_OVF and a bitmask
9640 + * describing which perfctrs overflowed is put in si_pmc_ovf_mask.
9641 + * A bitmask is used since more than one perfctr can have overflowed
9642 + * by the time the interrupt handler runs.
9644 + * glibc's <signal.h> doesn't seem to define __SI_FAULT or __SI_CODE(),
9645 + * and including <asm/siginfo.h> as well may cause redefinition errors,
9646 + * so the user and kernel values are different #defines here.
9649 +#define SI_PMC_OVF (__SI_FAULT|'P')
9651 +#define SI_PMC_OVF ('P')
9653 +#define si_pmc_ovf_mask _sifields._pad[0] /* XXX: use an unsigned field later */
9655 +/* version number for user-visible CPU-specific data */
9656 +#define PERFCTR_CPU_VERSION 0 /* XXX: not yet cast in stone */
9660 +#if defined(CONFIG_PERFCTR) || defined(CONFIG_PERFCTR_MODULE)
9662 +/* Driver init/exit. */
9663 +extern int perfctr_cpu_init(void);
9664 +extern void perfctr_cpu_exit(void);
9666 +/* CPU type name. */
9667 +extern char *perfctr_cpu_name;
9669 +/* Hardware reservation. */
9670 +extern const char *perfctr_cpu_reserve(const char *service);
9671 +extern void perfctr_cpu_release(const char *service);
9673 +/* PRE: state has no running interrupt-mode counters.
9674 + Check that the new control data is valid.
9675 + Update the driver's private control data.
9676 + Returns a negative error code if the control data is invalid. */
9677 +extern int perfctr_cpu_update_control(struct perfctr_cpu_state *state, int is_global);
9679 +/* Read a-mode counters. Subtract from start and accumulate into sums.
9680 + Must be called with preemption disabled. */
9681 +extern void perfctr_cpu_suspend(struct perfctr_cpu_state *state);
9683 +/* Write control registers. Read a-mode counters into start.
9684 + Must be called with preemption disabled. */
9685 +extern void perfctr_cpu_resume(struct perfctr_cpu_state *state);
9687 +/* Perform an efficient combined suspend/resume operation.
9688 + Must be called with preemption disabled. */
9689 +extern void perfctr_cpu_sample(struct perfctr_cpu_state *state);
9691 +/* The type of a perfctr overflow interrupt handler.
9692 + It will be called in IRQ context, with preemption disabled. */
9693 +typedef void (*perfctr_ihandler_t)(unsigned long pc);
9695 +/* XXX: The hardware supports overflow interrupts, but the driver
9696 + does not yet enable this due to an erratum in 750/7400/7410. */
9697 +//#define PERFCTR_INTERRUPT_SUPPORT 1
9699 +#ifdef PERFCTR_INTERRUPT_SUPPORT
9700 +extern void perfctr_cpu_set_ihandler(perfctr_ihandler_t);
9701 +extern void perfctr_cpu_ireload(struct perfctr_cpu_state*);
9702 +extern unsigned int perfctr_cpu_identify_overflow(struct perfctr_cpu_state*);
9704 +static inline void perfctr_cpu_set_ihandler(perfctr_ihandler_t x) { }
9707 +#endif /* CONFIG_PERFCTR */
9709 +#endif /* __KERNEL__ */
9711 +#endif /* _ASM_PPC_PERFCTR_H */
9712 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-x86_64/apic.h
9713 ===================================================================
9714 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/include/asm-x86_64/apic.h 2004-11-11 10:28:46.000000000 -0500
9715 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-x86_64/apic.h 2004-11-18 20:59:11.000000000 -0500
9717 #define NMI_LOCAL_APIC 2
9718 #define NMI_INVALID 3
9720 +extern unsigned int nmi_perfctr_msr;
9722 #endif /* CONFIG_X86_LOCAL_APIC */
9724 #define esr_disable 0
9725 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-x86_64/hw_irq.h
9726 ===================================================================
9727 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/include/asm-x86_64/hw_irq.h 2004-11-11 10:28:31.000000000 -0500
9728 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-x86_64/hw_irq.h 2004-11-18 20:59:11.000000000 -0500
9730 * sources per level' errata.
9732 #define LOCAL_TIMER_VECTOR 0xef
9733 +#define LOCAL_PERFCTR_VECTOR 0xee
9736 - * First APIC vector available to drivers: (vectors 0x30-0xee)
9737 + * First APIC vector available to drivers: (vectors 0x30-0xed)
9738 * we start at 0x31 to spread out vectors evenly between priority
9739 * levels. (0x80 is the syscall vector)
9741 #define FIRST_DEVICE_VECTOR 0x31
9742 -#define FIRST_SYSTEM_VECTOR 0xef /* duplicated in irq.h */
9743 +#define FIRST_SYSTEM_VECTOR 0xee /* duplicated in irq.h */
9746 #ifndef __ASSEMBLY__
9747 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-x86_64/irq.h
9748 ===================================================================
9749 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/include/asm-x86_64/irq.h 2004-11-11 10:28:46.000000000 -0500
9750 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-x86_64/irq.h 2004-11-18 20:59:11.000000000 -0500
9753 #define NR_VECTORS 256
9755 -#define FIRST_SYSTEM_VECTOR 0xef /* duplicated in hw_irq.h */
9756 +#define FIRST_SYSTEM_VECTOR 0xee /* duplicated in hw_irq.h */
9758 #ifdef CONFIG_PCI_USE_VECTOR
9759 #define NR_IRQS FIRST_SYSTEM_VECTOR
9760 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-x86_64/processor.h
9761 ===================================================================
9762 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/include/asm-x86_64/processor.h 2004-11-11 10:27:40.000000000 -0500
9763 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-x86_64/processor.h 2004-11-18 20:59:11.000000000 -0500
9765 unsigned long *io_bitmap_ptr;
9766 /* cached TLS descriptors. */
9767 u64 tls_array[GDT_ENTRY_TLS_ENTRIES];
9768 +/* performance counters */
9769 + struct vperfctr *perfctr;
9772 #define INIT_THREAD {}
9773 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-x86_64/perfctr.h
9774 ===================================================================
9775 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/include/asm-x86_64/perfctr.h 1969-12-31 19:00:00.000000000 -0500
9776 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/asm-x86_64/perfctr.h 2004-11-18 20:59:11.000000000 -0500
9778 +#include <asm-i386/perfctr.h>
9779 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/linux/perfctr.h
9780 ===================================================================
9781 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/include/linux/perfctr.h 1969-12-31 19:00:00.000000000 -0500
9782 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/include/linux/perfctr.h 2004-11-18 20:59:11.000000000 -0500
9784 +/* $Id: perfctr.h,v 1.69 2004/02/20 21:31:02 mikpe Exp $
9785 + * Performance-Monitoring Counters driver
9787 + * Copyright (C) 1999-2004 Mikael Pettersson
9789 +#ifndef _LINUX_PERFCTR_H
9790 +#define _LINUX_PERFCTR_H
9792 +#ifdef CONFIG_KPERFCTR /* don't break archs without <asm/perfctr.h> */
9794 +#include <asm/perfctr.h>
9796 +struct perfctr_info {
9797 + unsigned int abi_version;
9798 + char driver_version[32];
9799 + unsigned int cpu_type;
9800 + unsigned int cpu_features;
9801 + unsigned int cpu_khz;
9802 + unsigned int tsc_to_cpu_mult;
9803 + unsigned int _reserved2;
9804 + unsigned int _reserved3;
9805 + unsigned int _reserved4;
9808 +struct perfctr_cpu_mask {
9809 + unsigned int nrwords;
9810 + unsigned int mask[1]; /* actually 'nrwords' */
9813 +/* abi_version values: Lower 16 bits contain the CPU data version, upper
9814 + 16 bits contain the API version. Each half has a major version in its
9815 + upper 8 bits, and a minor version in its lower 8 bits. */
9816 +#define PERFCTR_API_VERSION 0x0501 /* 5.1 */
9817 +#define PERFCTR_ABI_VERSION ((PERFCTR_API_VERSION<<16)|PERFCTR_CPU_VERSION)
9819 +/* cpu_type values */
9820 +#define PERFCTR_X86_GENERIC 0 /* any x86 with rdtsc */
9821 +#define PERFCTR_X86_INTEL_P5 1 /* no rdpmc */
9822 +#define PERFCTR_X86_INTEL_P5MMX 2
9823 +#define PERFCTR_X86_INTEL_P6 3
9824 +#define PERFCTR_X86_INTEL_PII 4
9825 +#define PERFCTR_X86_INTEL_PIII 5
9826 +#define PERFCTR_X86_CYRIX_MII 6
9827 +#define PERFCTR_X86_WINCHIP_C6 7 /* no rdtsc */
9828 +#define PERFCTR_X86_WINCHIP_2 8 /* no rdtsc */
9829 +#define PERFCTR_X86_AMD_K7 9
9830 +#define PERFCTR_X86_VIA_C3 10 /* no pmc0 */
9831 +#define PERFCTR_X86_INTEL_P4 11 /* model 0 and 1 */
9832 +#define PERFCTR_X86_INTEL_P4M2 12 /* model 2 */
9833 +#define PERFCTR_X86_AMD_K8 13
9834 +#define PERFCTR_X86_INTEL_PENTM 14 /* Pentium M */
9835 +#define PERFCTR_X86_AMD_K8C 15 /* Revision C */
9836 +#define PERFCTR_X86_INTEL_P4M3 16 /* model 3 and above */
9838 +/* cpu_features flag bits */
9839 +#define PERFCTR_FEATURE_RDPMC 0x01
9840 +#define PERFCTR_FEATURE_RDTSC 0x02
9841 +#define PERFCTR_FEATURE_PCINT 0x04
9843 +/* user's view of mmap:ed virtual perfctr */
9844 +struct vperfctr_state {
9845 + struct perfctr_cpu_state cpu_state;
9848 +/* parameter in VPERFCTR_CONTROL command */
9849 +struct vperfctr_control {
9851 + struct perfctr_cpu_control cpu_control;
9852 + unsigned int preserve;
9853 + unsigned int _reserved1;
9854 + unsigned int _reserved2;
9855 + unsigned int _reserved3;
9856 + unsigned int _reserved4;
9859 +/* parameter in GPERFCTR_CONTROL command */
9860 +struct gperfctr_cpu_control {
9862 + struct perfctr_cpu_control cpu_control;
9863 + unsigned int _reserved1;
9864 + unsigned int _reserved2;
9865 + unsigned int _reserved3;
9866 + unsigned int _reserved4;
9869 +/* returned by GPERFCTR_READ command */
9870 +struct gperfctr_cpu_state {
9872 + struct perfctr_cpu_control cpu_control;
9873 + struct perfctr_sum_ctrs sum;
9874 + unsigned int _reserved1;
9875 + unsigned int _reserved2;
9876 + unsigned int _reserved3;
9877 + unsigned int _reserved4;
9880 +/* buffer for encodings of most of the above structs */
9881 +struct perfctr_struct_buf {
9882 + unsigned int rdsize;
9883 + unsigned int wrsize;
9884 + unsigned int buffer[1]; /* actually 'max(rdsize,wrsize)' */
9887 +#include <linux/ioctl.h>
9888 +#define _PERFCTR_IOCTL 0xD0 /* 'P'+128, currently unassigned */
9890 +#define PERFCTR_ABI _IOR(_PERFCTR_IOCTL,0,unsigned int)
9891 +#define PERFCTR_INFO _IOR(_PERFCTR_IOCTL,1,struct perfctr_struct_buf)
9892 +#define PERFCTR_CPUS _IOWR(_PERFCTR_IOCTL,2,struct perfctr_cpu_mask)
9893 +#define PERFCTR_CPUS_FORBIDDEN _IOWR(_PERFCTR_IOCTL,3,struct perfctr_cpu_mask)
9894 +#define VPERFCTR_CREAT _IO(_PERFCTR_IOCTL,6)/*int tid*/
9895 +#define VPERFCTR_OPEN _IO(_PERFCTR_IOCTL,7)/*int tid*/
9897 +#define VPERFCTR_READ_SUM _IOR(_PERFCTR_IOCTL,8,struct perfctr_struct_buf)
9898 +#define VPERFCTR_UNLINK _IO(_PERFCTR_IOCTL,9)
9899 +#define VPERFCTR_CONTROL _IOW(_PERFCTR_IOCTL,10,struct perfctr_struct_buf)
9900 +#define VPERFCTR_IRESUME _IO(_PERFCTR_IOCTL,11)
9901 +#define VPERFCTR_READ_CONTROL _IOR(_PERFCTR_IOCTL,12,struct perfctr_struct_buf)
9903 +#define GPERFCTR_CONTROL _IOWR(_PERFCTR_IOCTL,16,struct perfctr_struct_buf)
9904 +#define GPERFCTR_READ _IOWR(_PERFCTR_IOCTL,17,struct perfctr_struct_buf)
9905 +#define GPERFCTR_STOP _IO(_PERFCTR_IOCTL,18)
9906 +#define GPERFCTR_START _IO(_PERFCTR_IOCTL,19)/*unsigned int*/
9909 +extern struct perfctr_info perfctr_info;
9910 +extern int sys_perfctr_abi(unsigned int*);
9911 +extern int sys_perfctr_info(struct perfctr_struct_buf*);
9912 +extern int sys_perfctr_cpus(struct perfctr_cpu_mask*);
9913 +extern int sys_perfctr_cpus_forbidden(struct perfctr_cpu_mask*);
9914 +#endif /* __KERNEL__ */
9916 +#endif /* CONFIG_KPERFCTR */
9920 +/* Needed for perfctr_set_cpus_allowed() prototype. */
9921 +#include <linux/version.h>
9922 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) && !defined(HAVE_CPUMASK_T)
9923 +typedef unsigned long cpumask_t;
9924 +#define PERFCTR_HAVE_CPUMASK_T
9927 +#ifdef CONFIG_PERFCTR_VIRTUAL
9930 + * Virtual per-process performance-monitoring counters.
9932 +struct vperfctr; /* opaque */
9934 +/* process management operations */
9935 +extern struct vperfctr *__vperfctr_copy(struct vperfctr*);
9936 +extern void __vperfctr_exit(struct vperfctr*);
9937 +extern void __vperfctr_suspend(struct vperfctr*);
9938 +extern void __vperfctr_resume(struct vperfctr*);
9939 +extern void __vperfctr_sample(struct vperfctr*);
9940 +extern void __vperfctr_set_cpus_allowed(struct task_struct*, struct vperfctr*, cpumask_t);
9942 +#ifdef CONFIG_PERFCTR_MODULE
9943 +extern struct vperfctr_stub {
9944 + struct module *owner;
9945 + void (*exit)(struct vperfctr*);
9946 + void (*suspend)(struct vperfctr*);
9947 + void (*resume)(struct vperfctr*);
9948 + void (*sample)(struct vperfctr*);
9949 +#if PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED
9950 + void (*set_cpus_allowed)(struct task_struct*, struct vperfctr*, cpumask_t);
9953 +extern void _vperfctr_exit(struct vperfctr*);
9954 +#define _vperfctr_suspend(x) vperfctr_stub.suspend((x))
9955 +#define _vperfctr_resume(x) vperfctr_stub.resume((x))
9956 +#define _vperfctr_sample(x) vperfctr_stub.sample((x))
9957 +#define _vperfctr_set_cpus_allowed(x,y,z) (*vperfctr_stub.set_cpus_allowed)((x),(y),(z))
9958 +#else /* !CONFIG_PERFCTR_MODULE */
9959 +#define _vperfctr_exit(x) __vperfctr_exit((x))
9960 +#define _vperfctr_suspend(x) __vperfctr_suspend((x))
9961 +#define _vperfctr_resume(x) __vperfctr_resume((x))
9962 +#define _vperfctr_sample(x) __vperfctr_sample((x))
9963 +#define _vperfctr_set_cpus_allowed(x,y,z) __vperfctr_set_cpus_allowed((x),(y),(z))
9964 +#endif /* CONFIG_PERFCTR_MODULE */
9966 +static inline void perfctr_copy_thread(struct thread_struct *thread)
9968 + thread->perfctr = NULL;
9971 +static inline void perfctr_exit_thread(struct thread_struct *thread)
9973 + struct vperfctr *perfctr;
9974 + perfctr = thread->perfctr;
9976 + _vperfctr_exit(perfctr);
9979 +static inline void perfctr_suspend_thread(struct thread_struct *prev)
9981 + struct vperfctr *perfctr;
9982 + perfctr = prev->perfctr;
9984 + _vperfctr_suspend(perfctr);
9987 +static inline void perfctr_resume_thread(struct thread_struct *next)
9989 + struct vperfctr *perfctr;
9990 + perfctr = next->perfctr;
9992 + _vperfctr_resume(perfctr);
9995 +static inline void perfctr_sample_thread(struct thread_struct *thread)
9997 + struct vperfctr *perfctr;
9998 + perfctr = thread->perfctr;
10000 + _vperfctr_sample(perfctr);
10003 +static inline void perfctr_set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
10005 +#if PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED
10006 + struct vperfctr *perfctr;
10009 + perfctr = p->thread.perfctr;
10011 + _vperfctr_set_cpus_allowed(p, perfctr, new_mask);
10016 +#else /* !CONFIG_PERFCTR_VIRTUAL */
10018 +static inline void perfctr_copy_thread(struct thread_struct *t) { }
10019 +static inline void perfctr_exit_thread(struct thread_struct *t) { }
10020 +static inline void perfctr_suspend_thread(struct thread_struct *t) { }
10021 +static inline void perfctr_resume_thread(struct thread_struct *t) { }
10022 +static inline void perfctr_sample_thread(struct thread_struct *t) { }
10023 +static inline void perfctr_set_cpus_allowed(struct task_struct *p, cpumask_t m) { }
10025 +#endif /* CONFIG_PERFCTR_VIRTUAL */
10027 +#endif /* __KERNEL__ */
10029 +#endif /* _LINUX_PERFCTR_H */
10030 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/kernel/sched.c
10031 ===================================================================
10032 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/kernel/sched.c 2004-11-11 10:28:49.000000000 -0500
10033 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/kernel/sched.c 2004-11-18 20:59:11.000000000 -0500
10035 #include <linux/rcupdate.h>
10036 #include <linux/cpu.h>
10037 #include <linux/percpu.h>
10038 +#include <linux/perfctr.h>
10039 #include <linux/kthread.h>
10040 #include <linux/cpuset.h>
10041 #include <linux/stop_machine.h>
10042 @@ -3304,6 +3305,8 @@
10043 migration_req_t req;
10046 + perfctr_set_cpus_allowed(p, new_mask);
10048 rq = task_rq_lock(p, &flags);
10049 if (any_online_cpu(new_mask) == NR_CPUS) {
10051 Index: linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/kernel/timer.c
10052 ===================================================================
10053 --- linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891.orig/kernel/timer.c 2004-11-11 10:28:46.000000000 -0500
10054 +++ linux-2.6.5-SLES9_SP1_BRANCH_2004111114454891/kernel/timer.c 2004-11-18 20:59:11.000000000 -0500
10056 #include <linux/time.h>
10057 #include <linux/jiffies.h>
10058 #include <linux/cpu.h>
10059 +#include <linux/perfctr.h>
10060 #include <linux/trigevent_hooks.h>
10062 #include <asm/uaccess.h>
10063 @@ -844,6 +845,7 @@
10064 do_process_times(p, user, system);
10065 do_it_virt(p, user);
10067 + perfctr_sample_thread(&p->thread);