Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / kernel_patches / patches / perfctr-2.6-suse-lnxi.patch
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
5 @@ -2522,6 +2522,7 @@
6  E: mikpe@csd.uu.se
7  W: http://www.csd.uu.se/~mikpe/
8  D: Miscellaneous fixes
9 +D: Performance-monitoring counters driver
10  
11  N: Reed H. Petty
12  E: rhp@draper.net
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
17 @@ -187,5 +187,7 @@
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
31  S:     Supported
32  
33 +PERFORMANCE-MONITORING COUNTERS DRIVER
34 +P:     Mikael Pettersson
35 +M:     mikpe@csd.uu.se
36 +W:     http://www.csd.uu.se/~mikpe/linux/perfctr/
37 +S:     Maintained
38 +
39  PNP SUPPORT
40  P:     Adam Belay
41  M:     ambx1@neo.rr.com
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
46 @@ -857,6 +857,8 @@
47         generate incorrect output with certain kernel constructs when
48         -mregparm=3 is used.
49  
50 +source "drivers/perfctr/Kconfig"
51 +
52  endmenu
53  
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
59 @@ -444,6 +444,16 @@
60  /* The include is where all of the SMP etc. interrupts come from */
61  #include "entry_arch.h"
62  
63 +#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_KPERFCTR)
64 +ENTRY(perfctr_interrupt)
65 +       pushl $LOCAL_PERFCTR_VECTOR-256
66 +       SAVE_ALL
67 +       pushl %esp
68 +       call smp_perfctr_interrupt
69 +       addl $4, %esp
70 +       jmp ret_from_intr
71 +#endif
72 +
73  ENTRY(divide_error)
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
80 @@ -23,6 +23,7 @@
81  #include <asm/apic.h>
82  #include <asm/arch_hooks.h>
83  #include <asm/i8259.h>
84 +#include <asm/perfctr.h>
85  
86  #include <linux/irq.h>
87  
88 @@ -436,6 +437,8 @@
89          */
90         intr_init_hook();
91  
92 +       perfctr_vector_init();
93 +
94         /*
95          * Set the clock to HZ Hz, we already have a valid
96          * vector now:
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
101 @@ -32,6 +32,7 @@
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>
109 @@ -305,6 +306,7 @@
110                 tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
111                 put_cpu();
112         }
113 +       perfctr_exit_thread(&tsk->thread);
114         if (tsk->thread.debugreg[7])
115                 dr_dec_use_count(tsk->thread.debugreg[7]);
116  }
117 @@ -371,6 +373,8 @@
118         savesegment(fs,p->thread.fs);
119         savesegment(gs,p->thread.gs);
120  
121 +       perfctr_copy_thread(&p->thread);
122 +
123         tsk = current;
124         if (unlikely(NULL != tsk->thread.io_bitmap_ptr)) {
125                 p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
126 @@ -519,6 +523,8 @@
127  
128         /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
129  
130 +       perfctr_suspend_thread(prev);
131 +
132         __unlazy_fpu(prev_p);
133  
134         /*
135 @@ -599,6 +605,9 @@
136                          */
137                         tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
138         }
139 +
140 +       perfctr_resume_thread(next);
141 +
142         return prev_p;
143  }
144  
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
149 @@ -214,6 +214,8 @@
150         depends on 4xx || 8xx
151         default y
152  
153 +source "drivers/perfctr/Kconfig"
154 +
155  endmenu
156  
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
162 @@ -37,6 +37,7 @@
163  #include <linux/module.h>
164  #include <linux/kallsyms.h>
165  #include <linux/mqueue.h>
166 +#include <linux/perfctr.h>
167  
168  #include <asm/pgtable.h>
169  #include <asm/uaccess.h>
170 @@ -255,7 +256,9 @@
171                 new->thread.regs->msr |= MSR_VEC;
172         new_thread = &new->thread;
173         old_thread = &current->thread;
174 +       perfctr_suspend_thread(&prev->thread);
175         last = _switch(old_thread, new_thread);
176 +       perfctr_resume_thread(&current->thread);
177         local_irq_restore(s);
178         return last;
179  }
180 @@ -314,6 +317,7 @@
181                 last_task_used_math = NULL;
182         if (last_task_used_altivec == current)
183                 last_task_used_altivec = NULL;
184 +       perfctr_exit_thread(&current->thread);
185  }
186  
187  void flush_thread(void)
188 @@ -400,6 +404,8 @@
189  
190         p->thread.last_syscall = -1;
191  
192 +       perfctr_copy_thread(&p->thread);
193 +
194         return 0;
195  }
196  
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
201 @@ -319,6 +319,8 @@
202         bool
203         default y
204  
205 +source "drivers/perfctr/Kconfig"
206 +
207  endmenu
208  
209  
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
214 @@ -556,6 +556,11 @@
215         apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt
216  #endif
217                                 
218 +#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_KPERFCTR)
219 +ENTRY(perfctr_interrupt)
220 +       apicinterrupt LOCAL_PERFCTR_VECTOR,smp_perfctr_interrupt
221 +#endif
222 +               
223  /*
224   * Exception entry points.
225   */            
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
230 @@ -23,6 +23,7 @@
231  #include <asm/delay.h>
232  #include <asm/desc.h>
233  #include <asm/apic.h>
234 +#include <asm/perfctr.h>
235  
236  #include <linux/irq.h>
237  
238 @@ -484,6 +485,8 @@
239         set_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
240  #endif
241  
242 +       perfctr_vector_init();
243 +
244         /*
245          * Set the clock to HZ Hz, we already have a valid
246          * vector now:
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
251 @@ -32,6 +32,7 @@
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>
257  
258  #include <asm/uaccess.h>
259 @@ -258,6 +259,7 @@
260                 (init_tss + smp_processor_id())->io_bitmap_base = 
261                         INVALID_IO_BITMAP_OFFSET;
262         }
263 +       perfctr_exit_thread(&me->thread);
264  }
265  
266  void flush_thread(void)
267 @@ -361,6 +363,8 @@
268         asm("movl %%es,%0" : "=m" (p->thread.es));
269         asm("movl %%ds,%0" : "=m" (p->thread.ds));
270  
271 +       perfctr_copy_thread(&p->thread);
272 +
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) 
276 @@ -407,6 +411,8 @@
277         int cpu = smp_processor_id();  
278         struct tss_struct *tss = init_tss + cpu;
279  
280 +       perfctr_suspend_thread(prev);
281 +
282         unlazy_fpu(prev_p);
283  
284         /*
285 @@ -510,6 +516,8 @@
286                 }
287         }
288  
289 +       perfctr_resume_thread(next);
290 +
291         return prev_p;
292  }
293  
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
298 @@ -51,6 +51,7 @@
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/
304  obj-y                          += firmware/
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
310 @@ -0,0 +1,25 @@
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.
314 + *
315 + * Copyright (C) 2003  Mikael Pettersson
316 + */
317 +#include <linux/config.h>
318 +#include <linux/version.h>
319 +
320 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
321 +
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"
327 +#endif
328 +#undef irq_enter
329 +#undef irq_exit
330 +#define irq_enter()    do{}while(0)
331 +#define irq_exit()     do{}while(0)
332 +
333 +#endif
334 +
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
340 @@ -0,0 +1,46 @@
341 +# $Id: Makefile,v 1.20.2.2 2004/08/02 22:24:58 mikpe Exp $
342 +# Makefile for the Performance-monitoring counters driver.
343 +
344 +ifeq ($(VERSION)$(PATCHLEVEL),24)
345 +include Makefile24
346 +else
347 +
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)
356 +
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
361 +
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
366 +
367 +driver-objs-$(CONFIG_PPC32) := ppc.o
368 +tests-objs-$(CONFIG_PPC32) := ppc_tests.o
369 +kernel-objs-$(CONFIG_PPC32) := ppc_setup.o
370 +
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)
379 +
380 +perfctr-objs           := $(driver-objs-y)
381 +obj-m                  += $(m-objs-m)
382 +
383 +obj-$(CONFIG_KPERFCTR) += kperfctr.o
384 +kperfctr-objs          := $(kernel-objs-y)
385 +
386 +endif  # ifeq 24
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
391 @@ -0,0 +1,1357 @@
392 +$Id: RELEASE-NOTES,v 1.234.2.28 2004/10/19 16:22:47 mikpe Exp $
393 +
394 +RELEASE NOTES
395 +=============
396 +
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.
408 +
409 +Version 2.6.10, 2004-09-14
410 +- Fixed p4_clear_counters() to not access IQ_ESCR{0,1}
411 +  on P4 models >= 3.
412 +
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.
431 +
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
459 +  parsing code.
460 +- PPC32: avoid CPU re-detection in tests code.
461 +- PPC32: clean up and sync with current perfctr-2.7 code.
462 +
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.
479 +
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.
491 +
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.
506 +
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).
522 +
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.
531 +
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.
540 +
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.
548 +
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.
565 +
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.
582 +- Cleanups:
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
586 +    to virtual_stub.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.
594 +
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.
615 +
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.
631 +
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).
675 +
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
686 +  set of CPUs.
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
694 +  with x86-32.
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.
708 +
709 +Version 2.6.0-pre2, 2003-07-13
710 +- vperfctr API fixes:
711 +  * The new VPERFCTR_READ_CONTROL command retrieves a vperfctr's
712 +    control data.
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
728 +  always defines it.
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'.
745 +
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'.
760 +
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).
769 +
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.
796 +
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.
809 +
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).
822 +
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.
840 +
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().
854 +
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.
871 +
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.
892 +
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.
906 +
907 +Version 2.4.5, 2003-02-09
908 +- Fixed two minor compile warnings in x86_tests.c for 2.5 kernels.
909 +
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.
936 +
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.
963 +
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.
976 +
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.
984 +
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.
992 +
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.
1005 +
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.
1014 +
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.
1019 +
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.
1024 +
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.
1041 +
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.)
1048 +
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.
1072 +
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.
1086 +
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.
1096 +
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.
1111 +
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.
1120 +
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.
1168 +
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.
1175 +
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.
1179 +
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.
1192 +
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.
1198 +
1199 +Version 2.1.4, 2001-09-30
1200 +- No driver-level changes.
1201 +
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".
1207 +
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.)
1217 +
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.
1233 +
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.
1251 +
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.
1261 +
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.
1279 +
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
1300 +  own versions.
1301 +
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
1322 +  on a write miss.
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.  
1327 +
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.)
1347 +- Minor cleanups.
1348 +
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().
1371 +
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.
1379 +
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.
1385 +
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).
1394 +
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.
1413 +
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.
1427 +
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.
1438 +
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.
1450 +
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.
1463 +
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.
1492 +
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.
1512 +
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.
1536 +
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.
1552 +
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.
1566 +
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.
1580 +
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.
1598 +
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.
1609 +
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).
1624 +
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/.
1635 +
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.
1648 +
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.
1653 +
1654 +  Processor            P5      P5MMX   PII     PIII    K7
1655 +  Clock freq. (MHz)    133     233     266     450     500
1656 +
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
1661 +
1662 +  Several things are apparent from this table:
1663 +
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.
1667 +
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.
1682 +
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.
1702 +
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.
1711 +
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'.
1723 +
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().
1729 +
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.
1735 +
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.
1746 +
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
1753 @@ -0,0 +1,97 @@
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.
1757 + *
1758 + * Copyright (C) 1999-2004  Mikael Pettersson
1759 + */
1760 +#include <linux/mm.h>  /* for remap_page_range() [redefined here] */
1761 +
1762 +#include "cpumask.h"
1763 +
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)
1767 +#endif
1768 +
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);
1773 +#else
1774 +#define set_cpus_allowed(tsk, mask)    do{}while(0)
1775 +#endif
1776 +#endif
1777 +
1778 +/* 2.4.20-8-redhat added cpu_online() */
1779 +#if !defined(cpu_online)
1780 +#define cpu_online(cpu)                (cpu_online_map & (1UL << (cpu)))
1781 +#endif
1782 +
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*/
1789 +#endif
1790 +
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)
1794 +{
1795 +       return remap_page_range(from, to, size, prot);
1796 +}
1797 +#undef remap_page_range
1798 +#define remap_page_range(vma,from,to,size,prot) perfctr_remap_page_range((vma),(from),(to),(size),(prot))
1799 +#endif
1800 +
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*/
1804 +#else
1805 +#define EXPORT_SYMBOL_mmu_cr4_features EXPORT_SYMBOL(mmu_cr4_features)
1806 +#endif
1807 +
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"
1811 +#endif
1812 +#ifndef preempt_disable
1813 +#define preempt_disable()      do{}while(0)
1814 +#define preempt_enable()       do{}while(0)
1815 +#endif
1816 +
1817 +#ifdef MODULE
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)
1820 +#else
1821 +#define __module_get(module)   do{}while(0)
1822 +#define module_put(module)     do{}while(0)
1823 +#endif
1824 +
1825 +#define MODULE_ALIAS(alias)    /*empty*/
1826 +
1827 +/* introduced in 2.5.64; backported to 2.4.22-1.2115.nptl (FC1) */
1828 +static inline int
1829 +perfctr_on_each_cpu(void (*func) (void *info), void *info,
1830 +                   int retry, int wait)
1831 +{
1832 +        int ret = 0;
1833 +
1834 +        preempt_disable();
1835 +        ret = smp_call_function(func, info, retry, wait);
1836 +        func(info);
1837 +        preempt_enable();
1838 +        return ret;
1839 +}
1840 +#undef on_each_cpu
1841 +#define on_each_cpu(f,i,r,w)   perfctr_on_each_cpu((f),(i),(r),(w))
1842 +
1843 +/* 2.6.4 added 'noinline' */
1844 +#if !defined(noinline)
1845 +#if __GNUC__ == 3 && __GNUC_MINOR__ >= 1
1846 +#define noinline       __attribute__((noinline))
1847 +#else
1848 +#define noinline       /* unimplemented */
1849 +#endif
1850 +#endif
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
1855 @@ -0,0 +1,216 @@
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.
1859 + *
1860 + * Copyright (C) 1999-2004  Mikael Pettersson
1861 + */
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>
1869 +
1870 +#include <asm/uaccess.h>
1871 +
1872 +#include "compat.h"
1873 +#include "virtual.h"
1874 +#include "global.h"
1875 +#include "version.h"
1876 +#include "marshal.h"
1877 +
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)
1883 +EXPORT_NO_SYMBOLS;
1884 +#endif
1885 +
1886 +#ifdef CONFIG_PERFCTR_DEBUG
1887 +#define VERSION_DEBUG " DEBUG"
1888 +#else
1889 +#define VERSION_DEBUG
1890 +#endif
1891 +
1892 +struct perfctr_info perfctr_info = {
1893 +       .abi_version = PERFCTR_ABI_VERSION,
1894 +       .driver_version = VERSION VERSION_DEBUG,
1895 +};
1896 +
1897 +char *perfctr_cpu_name __initdata;
1898 +
1899 +int sys_perfctr_abi(unsigned int *argp)
1900 +{
1901 +       if( put_user(PERFCTR_ABI_VERSION, argp) )
1902 +               return -EFAULT;
1903 +       return 0;
1904 +}
1905 +
1906 +int sys_perfctr_info(struct perfctr_struct_buf *argp)
1907 +{
1908 +       return perfctr_copy_to_user(argp, &perfctr_info, &perfctr_info_sdesc);
1909 +}
1910 +
1911 +static int cpus_copy_to_user(const cpumask_t *cpus, struct perfctr_cpu_mask *argp)
1912 +{
1913 +       const unsigned int k_nrwords = PERFCTR_CPUMASK_NRLONGS*(sizeof(long)/sizeof(int));
1914 +       unsigned int u_nrwords;
1915 +       unsigned int ui, ki, j;
1916 +
1917 +       if( get_user(u_nrwords, &argp->nrwords) )
1918 +               return -EFAULT;
1919 +       if( put_user(k_nrwords, &argp->nrwords) )
1920 +               return -EFAULT;
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]) )
1927 +                               return -EFAULT;
1928 +                       ++ui;
1929 +                       mask = (mask >> (8*sizeof(int)-1)) >> 1;
1930 +               }
1931 +       }
1932 +       return 0;
1933 +}
1934 +
1935 +int sys_perfctr_cpus(struct perfctr_cpu_mask *argp)
1936 +{
1937 +       cpumask_t cpus = cpu_online_map;
1938 +       return cpus_copy_to_user(&cpus, argp);
1939 +}
1940 +
1941 +int sys_perfctr_cpus_forbidden(struct perfctr_cpu_mask *argp)
1942 +{
1943 +       cpumask_t cpus = perfctr_cpus_forbidden_mask;
1944 +       return cpus_copy_to_user(&cpus, argp);
1945 +}
1946 +
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)
1951 +{
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);
1954 +}
1955 +#else
1956 +#define perfctr_ioctl32_handler        0
1957 +#endif
1958 +
1959 +static void __init perfctr_register_ioctl32_conversions(void)
1960 +{
1961 +       int err;
1962 +
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);
1978 +       if( err )
1979 +               printk(KERN_ERR "perfctr: register_ioctl32_conversion() failed\n");
1980 +}
1981 +
1982 +static void __exit perfctr_unregister_ioctl32_conversions(void)
1983 +{
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);
1999 +}
2000 +
2001 +#else
2002 +#define perfctr_register_ioctl32_conversions()         do{}while(0)
2003 +#define perfctr_unregister_ioctl32_conversions()       do{}while(0)
2004 +#endif
2005 +
2006 +static int dev_perfctr_ioctl(struct inode *inode, struct file *filp,
2007 +                            unsigned int cmd, unsigned long arg)
2008 +{
2009 +       switch( cmd ) {
2010 +       case PERFCTR_ABI:
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);
2022 +       default:
2023 +               return gperfctr_ioctl(inode, filp, cmd, arg);
2024 +       }
2025 +       return -EINVAL;
2026 +}
2027 +
2028 +static struct file_operations dev_perfctr_file_ops = {
2029 +       .owner = THIS_MODULE,
2030 +       .ioctl = dev_perfctr_ioctl,
2031 +};
2032 +
2033 +static struct miscdevice dev_perfctr = {
2034 +       .minor = 182,
2035 +       .name = "perfctr",
2036 +       .fops = &dev_perfctr_file_ops,
2037 +};
2038 +
2039 +int __init perfctr_init(void)
2040 +{
2041 +       int err;
2042 +       if( (err = perfctr_cpu_init()) != 0 ) {
2043 +               printk(KERN_INFO "perfctr: not supported by this processor\n");
2044 +               return err;
2045 +       }
2046 +       if( (err = vperfctr_init()) != 0 )
2047 +               return err;
2048 +       gperfctr_init();
2049 +       if( (err = misc_register(&dev_perfctr)) != 0 ) {
2050 +               printk(KERN_ERR "/dev/perfctr: failed to register, errno %d\n",
2051 +                      -err);
2052 +               return err;
2053 +       }
2054 +       perfctr_register_ioctl32_conversions();
2055 +       printk(KERN_INFO "perfctr: driver %s, cpu type %s at %u kHz\n",
2056 +              perfctr_info.driver_version,
2057 +              perfctr_cpu_name,
2058 +              perfctr_info.cpu_khz);
2059 +       return 0;
2060 +}
2061 +
2062 +void __exit perfctr_exit(void)
2063 +{
2064 +       perfctr_unregister_ioctl32_conversions();
2065 +       misc_deregister(&dev_perfctr);
2066 +       vperfctr_exit();
2067 +       perfctr_cpu_exit();
2068 +}
2069 +
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
2076 @@ -0,0 +1,15 @@
2077 +/* $Id: virtual.h,v 1.11 2003/10/04 20:29:43 mikpe Exp $
2078 + * Virtual per-process performance counters.
2079 + *
2080 + * Copyright (C) 1999-2003  Mikael Pettersson
2081 + */
2082 +
2083 +#ifdef CONFIG_PERFCTR_VIRTUAL
2084 +extern int vperfctr_attach(int, int);
2085 +extern int vperfctr_init(void);
2086 +extern void vperfctr_exit(void);
2087 +#else
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) { }
2091 +#endif
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
2096 @@ -0,0 +1,722 @@
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.
2100 + *
2101 + * Copyright (C) 2003-2004  Mikael Pettersson
2102 + */
2103 +#ifdef __KERNEL__
2104 +#include <linux/config.h>
2105 +struct inode;
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>
2116 +#include <errno.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__ */
2122 +
2123 +#include "marshal.h"
2124 +
2125 +/****************************************************************
2126 + *                                                             *
2127 + * Struct encoding support.                                    *
2128 + *                                                             *
2129 + ****************************************************************/
2130 +
2131 +static void stream_write(struct perfctr_marshal_stream *stream, unsigned int word)
2132 +{
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;
2138 +       }
2139 +       ++stream->pos;
2140 +}
2141 +
2142 +static void encode_field(const void *address,
2143 +                        const struct perfctr_field_desc *field,
2144 +                        struct perfctr_marshal_stream *stream)
2145 +{
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;
2151 +       union {
2152 +               unsigned long long ull;
2153 +               unsigned int ui[2];
2154 +       } uint64_val;
2155 +       unsigned int i = 0;
2156 +
2157 +       do {
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 )
2162 +                               continue;
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); 
2169 +                       if( !uint32_val )
2170 +                               continue;
2171 +                       stream_write(stream, PERFCTR_HEADER(PERFCTR_HEADER_UINT32, tag, i));
2172 +                       stream_write(stream, uint32_val);
2173 +               }
2174 +       } while( ++i < nr_items );
2175 +}
2176 +
2177 +void perfctr_encode_struct(const void *address,
2178 +                          const struct perfctr_struct_desc *sdesc,
2179 +                          struct perfctr_marshal_stream *stream)
2180 +{
2181 +       unsigned int i;
2182 +
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);
2188 +       }
2189 +}
2190 +
2191 +/****************************************************************
2192 + *                                                             *
2193 + * Struct decoding support.                                    *
2194 + *                                                             *
2195 + ****************************************************************/
2196 +
2197 +static int stream_read(struct perfctr_marshal_stream *stream, unsigned int *word)
2198 +{
2199 +       if( stream->pos >= stream->size )
2200 +               return 0;
2201 +       if( get_user(*word, &stream->buffer[stream->pos]) )
2202 +               return -EFAULT;
2203 +       ++stream->pos;
2204 +       return 1;
2205 +}
2206 +
2207 +static const struct perfctr_field_desc*
2208 +find_field(unsigned int *struct_offset,
2209 +          const struct perfctr_struct_desc *sdesc,
2210 +          unsigned int tag)
2211 +{
2212 +       unsigned int low, high, mid, i;
2213 +       const struct perfctr_field_desc *field;
2214 +       const struct perfctr_sub_struct_desc *sub;
2215 +
2216 +       low = 0;
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 )
2222 +                       return field;
2223 +               if( field->tag < tag )
2224 +                       low = mid + 1;
2225 +               else
2226 +                       high = mid;
2227 +       }
2228 +       for(i = 0; i < sdesc->nrsubs; ++i) {
2229 +               sub = &sdesc->subs[i];
2230 +               field = find_field(struct_offset, sub->sdesc, tag);
2231 +               if( field ) {
2232 +                       *struct_offset += sub->offset;
2233 +                       return field;
2234 +               }
2235 +       }
2236 +       return 0;
2237 +}
2238 +
2239 +int perfctr_decode_struct(void *address,
2240 +                         const struct perfctr_struct_desc *sdesc,
2241 +                         struct perfctr_marshal_stream *stream)
2242 +{
2243 +       unsigned int header;
2244 +       int err;
2245 +       const struct perfctr_field_desc *field;
2246 +       unsigned int struct_offset;
2247 +       union {
2248 +               unsigned long long ull;
2249 +               unsigned int ui[2];
2250 +       } val;
2251 +       char *target;
2252 +       unsigned int itemnr;
2253 +
2254 +       for(;;) {
2255 +               err = stream_read(stream, &header);
2256 +               if( err <= 0 )
2257 +                       return err;
2258 +               struct_offset = 0;
2259 +               field = find_field(&struct_offset, sdesc, PERFCTR_HEADER_TAG(header));
2260 +               if( !field )
2261 +                       goto err_eproto;
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 )
2265 +                       goto err_eproto;
2266 +               err = stream_read(stream, &val.ui[0]);
2267 +               if( err <= 0 )
2268 +                       goto err_err;
2269 +               target = (char*)address + struct_offset + field->offset;
2270 +               itemnr = PERFCTR_HEADER_ITEMNR(header);
2271 +               if( itemnr >= PERFCTR_TYPE_NRITEMS(field->type) )
2272 +                       goto err_eproto;
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 )
2276 +                               goto err_eproto;
2277 +                       err = stream_read(stream, &val.ui[1]);
2278 +                       if( err <= 0 )
2279 +                               goto err_err;
2280 +                       ((unsigned long long*)target)[itemnr] = val.ull;
2281 +               } else
2282 +                       memcpy(&((unsigned int*)target)[itemnr], &val.ui[0], sizeof(int));
2283 +       }
2284 + err_err:      /* err ? err : -EPROTO */
2285 +       if( err )
2286 +               return err;
2287 + err_eproto:   /* saves object code over inlining it */
2288 +       return -EPROTO;
2289 +}
2290 +
2291 +/****************************************************************
2292 + *                                                             *
2293 + * Structure descriptors.                                      *
2294 + *                                                             *
2295 + ****************************************************************/
2296 +
2297 +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
2298 +#define STRUCT_ARRAY_SIZE(TYPE, MEMBER) ARRAY_SIZE(((TYPE*)0)->MEMBER)
2299 +
2300 +#if defined(__i386__) || defined(__x86_64__)
2301 +
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)
2318 +
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))
2322 +
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) },
2331 +};
2332 +
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,
2338 +};
2339 +
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 },
2384 +};
2385 +
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,
2391 +};
2392 +
2393 +#endif /* __i386__ || __x86_64__ */
2394 +
2395 +#if defined(__powerpc__)       /* XXX: can be merged with x86/amd64 */
2396 +
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
2405 +/* 40: unused */
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))
2411 +#ifdef __powerpc__
2412 +#define PERFCTR_CPU_CONTROL_NRFIELDS_1 2
2413 +#endif
2414 +#define PERFCTR_CPU_CONTROL_NRFIELDS   (PERFCTR_CPU_CONTROL_NRFIELDS_0 + PERFCTR_CPU_CONTROL_NRFIELDS_1)
2415 +
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))
2419 +
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) },
2428 +};
2429 +
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,
2435 +};
2436 +
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) },
2459 +#ifdef __powerpc__
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 },
2479 +};
2480 +
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,
2486 +};
2487 +
2488 +#endif /* __powerpc__ */
2489 +
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))
2500 +
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)
2508 +
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)
2515 +
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)
2523 +
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 },
2552 +};
2553 +
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,
2559 +};
2560 +
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 },
2581 +};
2582 +
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 },
2586 +};
2587 +
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,
2595 +};
2596 +#endif /* CONFIG_PERFCTR_VIRTUAL || !__KERNEL__ */
2597 +
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 },
2615 +};
2616 +
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 },
2620 +};
2621 +
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,
2629 +};
2630 +
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 },
2647 +};
2648 +
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 },
2654 +};
2655 +
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,
2661 +};
2662 +
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,
2670 +};
2671 +#endif /* CONFIG_PERFCTR_GLOBAL || !__KERNEL__ */
2672 +
2673 +#ifdef __KERNEL__
2674 +
2675 +int perfctr_copy_from_user(void *struct_address,
2676 +                          struct perfctr_struct_buf *argp,
2677 +                          const struct perfctr_struct_desc *sdesc)
2678 +{
2679 +       struct perfctr_marshal_stream stream;
2680 +
2681 +       if( get_user(stream.size, &argp->rdsize) )
2682 +               return -EFAULT;
2683 +       stream.buffer = argp->buffer;
2684 +       stream.pos = 0;
2685 +       stream.error = 0;
2686 +       memset(struct_address, 0, sdesc->total_sizeof);
2687 +       return perfctr_decode_struct(struct_address, sdesc, &stream);
2688 +}
2689 +
2690 +int perfctr_copy_to_user(struct perfctr_struct_buf *argp,
2691 +                        void *struct_address,
2692 +                        const struct perfctr_struct_desc *sdesc)
2693 +{
2694 +       struct perfctr_marshal_stream stream;
2695 +
2696 +       if( get_user(stream.size, &argp->wrsize) )
2697 +               return -EFAULT;
2698 +       stream.buffer = argp->buffer;
2699 +       stream.pos = 0;
2700 +       stream.error = 0;
2701 +       perfctr_encode_struct(struct_address, sdesc, &stream);
2702 +       if( stream.error )
2703 +               return stream.error;
2704 +       if( put_user(stream.pos, &argp->rdsize) )
2705 +               return -EFAULT;
2706 +       return 0;
2707 +}
2708 +
2709 +#else  /* !__KERNEL__ */
2710 +
2711 +#define sdesc_bufsize(sdesc)   ((sdesc)->total_nrfields + (sdesc)->total_sizeof/sizeof(int))
2712 +
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)
2717 +{
2718 +       struct perfctr_marshal_stream stream;
2719 +
2720 +       stream.size = bufsize;
2721 +       stream.buffer = buf->buffer;
2722 +       stream.pos = 0;
2723 +       stream.error = 0;
2724 +       perfctr_encode_struct(arg, sdesc, &stream);
2725 +       if( stream.error ) {
2726 +               errno = -stream.error;
2727 +               return -1;
2728 +       }
2729 +       buf->rdsize = stream.pos;
2730 +       return 0;
2731 +}
2732 +
2733 +int perfctr_ioctl_w(int fd, unsigned int cmd, const void *arg,
2734 +                   const struct perfctr_struct_desc *sdesc)
2735 +{
2736 +       unsigned int bufsize = sdesc_bufsize(sdesc);
2737 +       union {
2738 +               struct perfctr_struct_buf buf;
2739 +               struct {
2740 +                       unsigned int rdsize;
2741 +                       unsigned int wrsize;
2742 +                       unsigned int buffer[bufsize];
2743 +               } buf_bufsize;
2744 +       } u;
2745 +       int err;
2746 +
2747 +       err = common_ioctl_w(arg, sdesc, &u.buf, bufsize);
2748 +       if( err < 0 )
2749 +               return err;
2750 +       u.buf.wrsize = 0;
2751 +       return ioctl(fd, cmd, &u.buf);
2752 +}
2753 +
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)
2757 +{
2758 +       struct perfctr_marshal_stream stream;
2759 +       int err;
2760 +
2761 +       if( ioctl(fd, cmd, buf) < 0 )
2762 +               return -1;
2763 +       stream.size = buf->rdsize;
2764 +       stream.buffer = buf->buffer;
2765 +       stream.pos = 0;
2766 +       stream.error = 0;
2767 +       memset(res, 0, sdesc->total_sizeof);
2768 +       err = perfctr_decode_struct(res, sdesc, &stream);
2769 +       if( err < 0 ) {
2770 +               errno = -err;
2771 +               return -1;
2772 +       }
2773 +       return 0;
2774 +}
2775 +
2776 +int perfctr_ioctl_r(int fd, unsigned int cmd, void *res,
2777 +                   const struct perfctr_struct_desc *sdesc)
2778 +{
2779 +       unsigned int bufsize = sdesc_bufsize(sdesc);
2780 +       union {
2781 +               struct perfctr_struct_buf buf;
2782 +               struct {
2783 +                       unsigned int rdsize;
2784 +                       unsigned int wrsize;
2785 +                       unsigned int buffer[bufsize];
2786 +               } buf_bufsize;
2787 +       } u;
2788 +
2789 +       u.buf.rdsize = 0;
2790 +       u.buf.wrsize = bufsize;
2791 +       return common_ioctl_r(fd, cmd, res, sdesc, &u.buf);
2792 +}
2793 +
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)
2797 +{
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;
2801 +       union {
2802 +               struct perfctr_struct_buf buf;
2803 +               struct {
2804 +                       unsigned int rdsize;
2805 +                       unsigned int wrsize;
2806 +                       unsigned int buffer[bufsize];
2807 +               } buf_bufsize;
2808 +       } u;
2809 +       int err;
2810 +
2811 +       err = common_ioctl_w(argres, arg_sdesc, &u.buf, arg_bufsize);
2812 +       if( err < 0 )
2813 +               return err;
2814 +       u.buf.wrsize = res_bufsize;
2815 +       return common_ioctl_r(fd, cmd, argres, res_sdesc, &u.buf);
2816 +}
2817 +
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
2823 @@ -0,0 +1,62 @@
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.
2827 + *
2828 + * Copyright (C) 2004  Mikael Pettersson
2829 + */
2830 +
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 */
2842 +
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.
2852 +                                           */
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.
2857 +                                           */
2858 +#define MMCR0_TBSEL            0x01800000 /* Time base lower (TBL) bit selector.
2859 +                                           * 00: bit 31, 01: bit 23, 10: bit 19, 11: bit 15.
2860 +                                           */
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).
2866 +                                           */
2867 +#define MMCR0_TRIGGER          0x00002000 /* Disable PMC2-PMC6 until PMC1 overflow or other event.
2868 +                                           * 74xx: cleared by hardware when the event occurs.
2869 +                                           */
2870 +#define MMCR0_PMC1SEL          0x00001FB0 /* PMC1 event selector, 7 bits. */
2871 +#define MMCR0_PMC2SEL          0x0000003F /* PMC2 event selector, 6 bits. */
2872 +
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 */
2879 +
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
2890 @@ -0,0 +1,23 @@
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.
2894 + *
2895 + * Copyright (C) 1999-2004  Mikael Pettersson
2896 + */
2897 +#include <linux/version.h>
2898 +
2899 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
2900 +#include "compat24.h"
2901 +#else
2902 +
2903 +#include "cpumask.h"
2904 +
2905 +#define EXPORT_SYMBOL_mmu_cr4_features EXPORT_SYMBOL(mmu_cr4_features)
2906 +#define EXPORT_SYMBOL___put_task_struct        EXPORT_SYMBOL(__put_task_struct)
2907 +
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))
2911 +#endif
2912 +
2913 +#endif
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
2918 @@ -0,0 +1,15 @@
2919 +# $Id: Config.in,v 1.15 2002/11/25 13:01:46 mikpe Exp $
2920 +# Performance-monitoring counters driver configuration
2921 +#
2922 +
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
2932 +fi
2933 +endmenu
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
2938 @@ -0,0 +1,244 @@
2939 +/* $Id: global.c,v 1.38 2004/01/25 14:45:35 mikpe Exp $
2940 + * Global-mode performance-monitoring counters via /dev/perfctr.
2941 + *
2942 + * Copyright (C) 2000-2003  Mikael Pettersson
2943 + *
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?
2946 + */
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>
2954 +
2955 +#include <asm/uaccess.h>
2956 +
2957 +#include "compat.h"
2958 +#include "global.h"
2959 +#include "marshal.h"
2960 +
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;
2966 +
2967 +struct gperfctr {
2968 +       struct perfctr_cpu_state cpu_state;
2969 +       spinlock_t lock;
2970 +} ____cacheline_aligned;
2971 +
2972 +static struct gperfctr per_cpu_gperfctr[NR_CPUS] __cacheline_aligned;
2973 +
2974 +static int reserve_hardware(void)
2975 +{
2976 +       const char *other;
2977 +
2978 +       if( hardware_is_ours )
2979 +               return 0;
2980 +       other = perfctr_cpu_reserve(this_service);
2981 +       if( other ) {
2982 +               printk(KERN_ERR __FILE__ ":%s: failed because hardware is taken by '%s'\n",
2983 +                      __FUNCTION__, other);
2984 +               return -EBUSY;
2985 +       }
2986 +       hardware_is_ours = 1;
2987 +       __module_get(THIS_MODULE);
2988 +       return 0;
2989 +}
2990 +
2991 +static void release_hardware(void)
2992 +{
2993 +       int i;
2994 +
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;
3004 +       }
3005 +}
3006 +
3007 +static void sample_this_cpu(void *unused)
3008 +{
3009 +       /* PREEMPT note: when called via smp_call_function(),
3010 +          this is in IRQ context with preemption disabled. */
3011 +       struct gperfctr *perfctr;
3012 +
3013 +       perfctr = &per_cpu_gperfctr[smp_processor_id()];
3014 +       if( !perfctr_cstatus_enabled(perfctr->cpu_state.cstatus) )
3015 +               return;
3016 +       spin_lock(&perfctr->lock);
3017 +       perfctr_cpu_sample(&perfctr->cpu_state);
3018 +       spin_unlock(&perfctr->lock);
3019 +}
3020 +
3021 +static void sample_all_cpus(void)
3022 +{
3023 +       on_each_cpu(sample_this_cpu, NULL, 1, 1);
3024 +}
3025 +
3026 +static void sampling_timer_function(unsigned long interval)
3027 +{      
3028 +       sample_all_cpus();
3029 +       sampling_timer.expires = jiffies + interval;
3030 +       add_timer(&sampling_timer);
3031 +}
3032 +
3033 +static unsigned long usectojiffies(unsigned long usec)
3034 +{
3035 +       usec += 1000000 / HZ - 1;
3036 +       usec /= 1000000 / HZ;
3037 +       return usec;
3038 +}
3039 +
3040 +static void start_sampling_timer(unsigned long interval_usec)
3041 +{
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);
3049 +       }
3050 +}
3051 +
3052 +static void start_this_cpu(void *unused)
3053 +{
3054 +       /* PREEMPT note: when called via smp_call_function(),
3055 +          this is in IRQ context with preemption disabled. */
3056 +       struct gperfctr *perfctr;
3057 +
3058 +       perfctr = &per_cpu_gperfctr[smp_processor_id()];
3059 +       if( perfctr_cstatus_enabled(perfctr->cpu_state.cstatus) )
3060 +               perfctr_cpu_resume(&perfctr->cpu_state);
3061 +}
3062 +
3063 +static void start_all_cpus(void)
3064 +{
3065 +       on_each_cpu(start_this_cpu, NULL, 1, 1);
3066 +}
3067 +
3068 +static int gperfctr_control(struct perfctr_struct_buf *argp)
3069 +{
3070 +       int ret;
3071 +       struct gperfctr *perfctr;
3072 +       struct gperfctr_cpu_control cpu_control;
3073 +
3074 +       ret = perfctr_copy_from_user(&cpu_control, argp, &gperfctr_cpu_control_sdesc);
3075 +       if( ret )
3076 +               return ret;
3077 +       if( cpu_control.cpu >= NR_CPUS ||
3078 +           !cpu_online(cpu_control.cpu) ||
3079 +           perfctr_cpu_is_forbidden(cpu_control.cpu) )
3080 +               return -EINVAL;
3081 +       /* we don't permit i-mode counters */
3082 +       if( cpu_control.cpu_control.nrictrs != 0 )
3083 +               return -EPERM;
3084 +       down(&control_mutex);
3085 +       ret = -EBUSY;
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);
3096 +       if( ret < 0 )
3097 +               goto out_up;
3098 +       if( perfctr_cstatus_enabled(perfctr->cpu_state.cstatus) )
3099 +               ++nr_active_cpus;
3100 +       ret = nr_active_cpus;
3101 + out_up:
3102 +       up(&control_mutex);
3103 +       return ret;
3104 +}
3105 +
3106 +static int gperfctr_start(unsigned int interval_usec)
3107 +{
3108 +       int ret;
3109 +
3110 +       if( interval_usec < 10000 )
3111 +               return -EINVAL;
3112 +       down(&control_mutex);
3113 +       ret = nr_active_cpus;
3114 +       if( ret > 0 ) {
3115 +               if( reserve_hardware() < 0 ) {
3116 +                       ret = -EBUSY;
3117 +               } else {
3118 +                       start_all_cpus();
3119 +                       start_sampling_timer(interval_usec);
3120 +               }
3121 +       }
3122 +       up(&control_mutex);
3123 +       return ret;
3124 +}
3125 +
3126 +static int gperfctr_stop(void)
3127 +{
3128 +       down(&control_mutex);
3129 +       release_hardware();
3130 +       up(&control_mutex);
3131 +       return 0;
3132 +}
3133 +
3134 +static int gperfctr_read(struct perfctr_struct_buf *argp)
3135 +{
3136 +       struct gperfctr *perfctr;
3137 +       struct gperfctr_cpu_state state;
3138 +       int err;
3139 +
3140 +       // XXX: sample_all_cpus() ???
3141 +       err = perfctr_copy_from_user(&state, argp, &gperfctr_cpu_state_only_cpu_sdesc);
3142 +       if( err )
3143 +               return err;
3144 +       if( state.cpu >= NR_CPUS || !cpu_online(state.cpu) )
3145 +               return -EINVAL;
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;
3150 +       {
3151 +               int j;
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;
3155 +       }
3156 +       spin_unlock(&perfctr->lock);
3157 +       return perfctr_copy_to_user(argp, &state, &gperfctr_cpu_state_sdesc);
3158 +}
3159 +
3160 +int gperfctr_ioctl(struct inode *inode, struct file *filp,
3161 +                  unsigned int cmd, unsigned long arg)
3162 +{
3163 +       switch( cmd ) {
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);
3172 +       }
3173 +       return -EINVAL;
3174 +}
3175 +
3176 +void __init gperfctr_init(void)
3177 +{
3178 +       int i;
3179 +
3180 +       for(i = 0; i < NR_CPUS; ++i)
3181 +               per_cpu_gperfctr[i].lock = SPIN_LOCK_UNLOCKED;
3182 +}
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
3187 @@ -0,0 +1,14 @@
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.
3191 + *
3192 + * Copyright (C) 2003  Mikael Pettersson
3193 + */
3194 +
3195 +#ifdef CONFIG_PERFCTR_INIT_TESTS
3196 +extern void perfctr_k8_init_tests(void);
3197 +extern void perfctr_generic_init_tests(void);
3198 +#else
3199 +#define perfctr_k8_init_tests()
3200 +#define perfctr_generic_init_tests()
3201 +#endif
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
3206 @@ -0,0 +1,79 @@
3207 +# $Id: Kconfig,v 1.7 2003/05/14 21:51:32 mikpe Exp $
3208 +# Performance-monitoring counters driver configuration
3209 +#
3210 +
3211 +menu "Performance-monitoring counters support"
3212 +
3213 +config PERFCTR
3214 +       tristate "Performance monitoring counters support"
3215 +       help
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.
3221 +
3222 +         You can safely say Y here, even if you intend to run the kernel
3223 +         on a processor without performance-monitoring counters.
3224 +
3225 +         You can also say M here to compile the driver as a module; the
3226 +         module will be called `perfctr'.
3227 +
3228 +config KPERFCTR
3229 +       bool
3230 +       depends on PERFCTR
3231 +       default y
3232 +
3233 +config PERFCTR_DEBUG
3234 +       bool "Additional internal consistency checks"
3235 +       depends on PERFCTR
3236 +       help
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.
3240 +
3241 +         Enabling this option will reduce performance, so say N unless you
3242 +         are debugging the driver.
3243 +
3244 +config PERFCTR_INIT_TESTS
3245 +       bool "Init-time hardware tests"
3246 +       depends on PERFCTR
3247 +       help
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.
3252 +
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.
3256 +
3257 +         If unsure, say N.
3258 +
3259 +config PERFCTR_VIRTUAL
3260 +       bool "Virtual performance counters support"
3261 +       depends on PERFCTR
3262 +       help
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.
3268 +
3269 +         Say Y.
3270 +
3271 +config PERFCTR_GLOBAL
3272 +       bool "Global performance counters support"
3273 +       depends on PERFCTR
3274 +       help
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.
3280 +
3281 +         Global-mode performance counters cannot be used if some process
3282 +         is currently using virtual-mode performance counters, and vice versa.
3283 +
3284 +         Say Y.
3285 +endmenu
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
3290 @@ -0,0 +1,104 @@
3291 +/* $Id: marshal.h,v 1.1 2003/08/19 13:37:07 mikpe Exp $
3292 + * Performance-monitoring counters driver.
3293 + * Structure marshalling support.
3294 + *
3295 + * Copyright (C) 2003  Mikael Pettersson
3296 + */
3297 +
3298 +/*
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).
3302 + *
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.
3306 + *
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.
3309 + *
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.
3313 + */
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)
3318 +
3319 +#define PERFCTR_HEADER_UINT32          0
3320 +#define PERFCTR_HEADER_UINT64          1
3321 +
3322 +/*
3323 + * A field descriptor describes a struct field to the
3324 + * encoding and decoding procedures.
3325 + *
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.
3329 + */
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) */
3334 +};
3335 +
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)
3339 +
3340 +#define PERFCTR_TYPE_BYTES4    0       /* uint32 or char[4] */
3341 +#define PERFCTR_TYPE_UINT64    1       /* long long */
3342 +
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;
3353 +       } *subs;
3354 +};
3355 +
3356 +struct perfctr_marshal_stream {
3357 +       unsigned int size;
3358 +       unsigned int *buffer;
3359 +       unsigned int pos;
3360 +       unsigned int error;
3361 +};
3362 +
3363 +extern void perfctr_encode_struct(const void *address,
3364 +                                 const struct perfctr_struct_desc *sdesc,
3365 +                                 struct perfctr_marshal_stream *stream);
3366 +
3367 +extern int perfctr_decode_struct(void *address,
3368 +                                const struct perfctr_struct_desc *sdesc,
3369 +                                struct perfctr_marshal_stream *stream);
3370 +
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;
3378 +
3379 +#ifdef __KERNEL__
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);
3386 +#else
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
3399 @@ -0,0 +1,67 @@
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.
3403 + *
3404 + * Copyright (C) 2000-2003  Mikael Pettersson
3405 + */
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"
3412 +
3413 +static void bug_void_perfctr(struct vperfctr *perfctr)
3414 +{
3415 +       current->thread.perfctr = NULL;
3416 +       BUG();
3417 +}
3418 +
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)
3421 +{
3422 +       owner->thread.perfctr = NULL;
3423 +       BUG();
3424 +}
3425 +#endif
3426 +
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,
3434 +#endif
3435 +};
3436 +
3437 +/*
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.
3447 + *
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.)
3454 + */
3455 +void _vperfctr_exit(struct vperfctr *perfctr)
3456 +{
3457 +       __module_get(vperfctr_stub.owner);
3458 +       vperfctr_stub.exit(perfctr);
3459 +       module_put(vperfctr_stub.owner);
3460 +}
3461 +
3462 +EXPORT_SYMBOL(vperfctr_stub);
3463 +
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
3471 @@ -0,0 +1,292 @@
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.
3475 + *
3476 + * Copyright (C) 2004  Mikael Pettersson
3477 + */
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"
3490 +
3491 +#define NITER  256
3492 +#define X2(S)  S"; "S
3493 +#define X8(S)  X2(X2(X2(S)))
3494 +
3495 +static void __init do_read_tbl(unsigned int unused)
3496 +{
3497 +       unsigned int i, dummy;
3498 +       for(i = 0; i < NITER/8; ++i)
3499 +               __asm__ __volatile__(X8("mftbl %0") : "=r"(dummy));
3500 +}
3501 +
3502 +static void __init do_read_pmc1(unsigned int unused)
3503 +{
3504 +       unsigned int i, dummy;
3505 +       for(i = 0; i < NITER/8; ++i)
3506 +               __asm__ __volatile__(X8("mfspr %0," __stringify(SPRN_PMC1)) : "=r"(dummy));
3507 +}
3508 +
3509 +static void __init do_read_pmc2(unsigned int unused)
3510 +{
3511 +       unsigned int i, dummy;
3512 +       for(i = 0; i < NITER/8; ++i)
3513 +               __asm__ __volatile__(X8("mfspr %0," __stringify(SPRN_PMC2)) : "=r"(dummy));
3514 +}
3515 +
3516 +static void __init do_read_pmc3(unsigned int unused)
3517 +{
3518 +       unsigned int i, dummy;
3519 +       for(i = 0; i < NITER/8; ++i)
3520 +               __asm__ __volatile__(X8("mfspr %0," __stringify(SPRN_PMC3)) : "=r"(dummy));
3521 +}
3522 +
3523 +static void __init do_read_pmc4(unsigned int unused)
3524 +{
3525 +       unsigned int i, dummy;
3526 +       for(i = 0; i < NITER/8; ++i)
3527 +               __asm__ __volatile__(X8("mfspr %0," __stringify(SPRN_PMC4)) : "=r"(dummy));
3528 +}
3529 +
3530 +static void __init do_read_mmcr0(unsigned int unused)
3531 +{
3532 +       unsigned int i, dummy;
3533 +       for(i = 0; i < NITER/8; ++i)
3534 +               __asm__ __volatile__(X8("mfspr %0," __stringify(SPRN_MMCR0)) : "=r"(dummy));
3535 +}
3536 +
3537 +static void __init do_read_mmcr1(unsigned int unused)
3538 +{
3539 +       unsigned int i, dummy;
3540 +       for(i = 0; i < NITER/8; ++i)
3541 +               __asm__ __volatile__(X8("mfspr %0," __stringify(SPRN_MMCR1)) : "=r"(dummy));
3542 +}
3543 +
3544 +static void __init do_write_pmc2(unsigned int arg)
3545 +{
3546 +       unsigned int i;
3547 +       for(i = 0; i < NITER/8; ++i)
3548 +               __asm__ __volatile__(X8("mtspr " __stringify(SPRN_PMC2) ",%0") : : "r"(arg));
3549 +}
3550 +
3551 +static void __init do_write_pmc3(unsigned int arg)
3552 +{
3553 +       unsigned int i;
3554 +       for(i = 0; i < NITER/8; ++i)
3555 +               __asm__ __volatile__(X8("mtspr " __stringify(SPRN_PMC3) ",%0") : : "r"(arg));
3556 +}
3557 +
3558 +static void __init do_write_pmc4(unsigned int arg)
3559 +{
3560 +       unsigned int i;
3561 +       for(i = 0; i < NITER/8; ++i)
3562 +               __asm__ __volatile__(X8("mtspr " __stringify(SPRN_PMC4) ",%0") : : "r"(arg));
3563 +}
3564 +
3565 +static void __init do_write_mmcr1(unsigned int arg)
3566 +{
3567 +       unsigned int i;
3568 +       for(i = 0; i < NITER/8; ++i)
3569 +               __asm__ __volatile__(X8("mtspr " __stringify(SPRN_MMCR1) ",%0") : : "r"(arg));
3570 +}
3571 +
3572 +static void __init do_write_mmcr0(unsigned int arg)
3573 +{
3574 +       unsigned int i;
3575 +       for(i = 0; i < NITER/8; ++i)
3576 +               __asm__ __volatile__(X8("mtspr " __stringify(SPRN_MMCR0) ",%0") : : "r"(arg));
3577 +}
3578 +
3579 +static void __init do_empty_loop(unsigned int unused)
3580 +{
3581 +       unsigned i;
3582 +       for(i = 0; i < NITER/8; ++i)
3583 +               __asm__ __volatile__("" : : );
3584 +}
3585 +
3586 +static unsigned __init run(void (*doit)(unsigned int), unsigned int arg)
3587 +{
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;
3593 +}
3594 +
3595 +static void __init init_tests_message(void)
3596 +{
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",
3603 +              pvr,
3604 +              perfctr_info.cpu_khz,
3605 +              tb_ticks_per_jiffy*(HZ/10)/(1000/10));
3606 +}
3607 +
3608 +static void __init clear(int have_mmcr1)
3609 +{
3610 +       mtspr(SPRN_MMCR0, 0);
3611 +       mtspr(SPRN_PMC1, 0);
3612 +       mtspr(SPRN_PMC2, 0);
3613 +       if (have_mmcr1) {
3614 +               mtspr(SPRN_MMCR1, 0);
3615 +               mtspr(SPRN_PMC3, 0);
3616 +               mtspr(SPRN_PMC4, 0);
3617 +       }
3618 +}
3619 +
3620 +static void __init check_fcece(unsigned int pmc1ce)
3621 +{
3622 +       unsigned int mmcr0;
3623 +
3624 +       /*
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.
3629 +        *
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.]
3633 +        *
3634 +        * When pmc1ce == 0, MMCR0[PMC1CE] is zero. It's unclear whether
3635 +        * this masks all PMC1 overflow events or just PMC1 PMIs.
3636 +        *
3637 +        * PMC1 counts processor cycles, with 100 to go before overflowing.
3638 +        * FCECE is set.
3639 +        * PMC1CE is clear if !pmc1ce, otherwise set.
3640 +        */
3641 +       mtspr(SPRN_PMC1, 0x80000000-100);
3642 +       mmcr0 = (1<<(31-6)) | (0x01 << 6);
3643 +       if (pmc1ce)
3644 +               mmcr0 |= (1<<(31-16));
3645 +       mtspr(SPRN_MMCR0, mmcr0);
3646 +       do {
3647 +               do_empty_loop(0);
3648 +       } while (!(mfspr(SPRN_PMC1) & 0x80000000));
3649 +       do_empty_loop(0);
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);
3655 +}
3656 +
3657 +static void __init check_trigger(unsigned int pmc1ce)
3658 +{
3659 +       unsigned int mmcr0;
3660 +
3661 +       /*
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.]
3666 +        *
3667 +        * Also output the values of PMC1 and PMC2 shortly after the overflow.
3668 +        * PMC2 should be equal to PMC1-0x80000000.
3669 +        *
3670 +        * When pmc1ce == 0, MMCR0[PMC1CE] is zero. It's unclear whether
3671 +        * this masks all PMC1 overflow events or just PMC1 PMIs.
3672 +        *
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.
3677 +        */
3678 +       mtspr(SPRN_PMC2, 0);
3679 +       mtspr(SPRN_PMC1, 0x80000000-100);
3680 +       mmcr0 = (1<<(31-18)) | (0x01 << 6) | (0x01 << 0);
3681 +       if (pmc1ce)
3682 +               mmcr0 |= (1<<(31-16));
3683 +       mtspr(SPRN_MMCR0, mmcr0);
3684 +       do {
3685 +               do_empty_loop(0);
3686 +       } while (!(mfspr(SPRN_PMC1) & 0x80000000));
3687 +       do_empty_loop(0);
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);
3694 +}
3695 +
3696 +static void __init
3697 +measure_overheads(int have_mmcr1)
3698 +{
3699 +       int i;
3700 +       unsigned int mmcr0, loop, ticks[12];
3701 +       const char *name[12];
3702 +
3703 +       clear(have_mmcr1);
3704 +
3705 +       /* PMC1 = "processor cycles",
3706 +          PMC2 = "completed instructions",
3707 +          not disabled in any mode,
3708 +          no interrupts */
3709 +       mmcr0 = (0x01 << 6) | (0x02 << 0);
3710 +       mtspr(SPRN_MMCR0, mmcr0);
3711 +
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);
3736 +
3737 +       loop = run(do_empty_loop, 0);
3738 +
3739 +       clear(have_mmcr1);
3740 +
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) {
3745 +               unsigned int x;
3746 +               if (!ticks[i])
3747 +                       continue;
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]);
3751 +       }
3752 +       check_fcece(0);
3753 +       check_fcece(1);
3754 +       check_trigger(0);
3755 +       check_trigger(1);
3756 +}
3757 +
3758 +void __init perfctr_ppc_init_tests(int have_mmcr1)
3759 +{
3760 +       preempt_disable();
3761 +       measure_overheads(have_mmcr1);
3762 +       preempt_enable();
3763 +}
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
3768 @@ -0,0 +1,116 @@
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.
3772 + *
3773 + * Copyright (C) 1999-2004  Mikael Pettersson
3774 + */
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"
3787 +
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)
3790 +/**
3791 + * set_cpus_allowed() - change a given task's processor affinity
3792 + * @p: task to bind
3793 + * @new_mask: bitmask of allowed processors
3794 + *
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.
3798 + */
3799 +void set_cpus_allowed(struct task_struct *p, unsigned long new_mask)
3800 +{
3801 +       new_mask &= cpu_online_map;
3802 +       BUG_ON(!new_mask);
3803 +
3804 +       /* This must be our own, safe, call from sys_vperfctr_control(). */
3805 +
3806 +       p->cpus_allowed = new_mask;
3807 +
3808 +       /*
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.
3812 +        */
3813 +       if (!(p->cpus_runnable & p->cpus_allowed)) {
3814 +               if (p != current) {
3815 +                       p->need_resched = 1;
3816 +                       smp_send_reschedule(p->processor);
3817 +               }
3818 +               /*
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.
3822 +                */
3823 +               while (!(p->cpus_runnable & p->cpus_allowed))
3824 +                       schedule();
3825 +       }
3826 +}
3827 +EXPORT_SYMBOL(set_cpus_allowed);
3828 +#endif
3829 +
3830 +#ifdef CONFIG_X86_LOCAL_APIC
3831 +static void perfctr_default_ihandler(unsigned long pc)
3832 +{
3833 +}
3834 +
3835 +static perfctr_ihandler_t perfctr_ihandler = perfctr_default_ihandler;
3836 +
3837 +asmlinkage void smp_perfctr_interrupt(struct pt_regs *regs)
3838 +{
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? */
3842 +       ack_APIC_irq();
3843 +       irq_enter();
3844 +       (*perfctr_ihandler)(instruction_pointer(regs));
3845 +       irq_exit();
3846 +}
3847 +
3848 +void perfctr_cpu_set_ihandler(perfctr_ihandler_t ihandler)
3849 +{
3850 +       perfctr_ihandler = ihandler ? ihandler : perfctr_default_ihandler;
3851 +}
3852 +#endif
3853 +
3854 +#ifdef __x86_64__
3855 +extern unsigned int cpu_khz;
3856 +#else
3857 +extern unsigned long cpu_khz;
3858 +#endif
3859 +
3860 +/* Wrapper to avoid namespace clash in RedHat 8.0's 2.4.18-14 kernel. */
3861 +unsigned int perfctr_cpu_khz(void)
3862 +{
3863 +       return cpu_khz;
3864 +}
3865 +
3866 +#ifdef CONFIG_PERFCTR_MODULE
3867 +EXPORT_SYMBOL_mmu_cr4_features;
3868 +EXPORT_SYMBOL(perfctr_cpu_khz);
3869 +
3870 +#ifdef CONFIG_X86_LOCAL_APIC
3871 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6)
3872 +EXPORT_SYMBOL(nmi_perfctr_msr);
3873 +#endif
3874 +
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);
3879 +#endif
3880 +
3881 +EXPORT_SYMBOL(perfctr_cpu_set_ihandler);
3882 +#endif /* CONFIG_X86_LOCAL_APIC */
3883 +
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
3889 @@ -0,0 +1,17 @@
3890 +/* $Id: global.h,v 1.7 2003/10/02 20:04:35 mikpe Exp $
3891 + * Global-mode performance-monitoring counters.
3892 + *
3893 + * Copyright (C) 2000-2003  Mikael Pettersson
3894 + */
3895 +
3896 +#ifdef CONFIG_PERFCTR_GLOBAL
3897 +extern int gperfctr_ioctl(struct inode*, struct file*, unsigned int, unsigned long);
3898 +extern void gperfctr_init(void);
3899 +#else
3900 +extern int gperfctr_ioctl(struct inode *inode, struct file *filp,
3901 +                         unsigned int cmd, unsigned long arg)
3902 +{
3903 +       return -EINVAL;
3904 +}
3905 +static inline void gperfctr_init(void) { }
3906 +#endif
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
3911 @@ -0,0 +1,81 @@
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.
3917 + *
3918 + * Copyright (C) 2003-2004  Mikael Pettersson
3919 + */
3920 +
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)
3923 +
3924 +#if !defined(PERFCTR_HAVE_CPUMASK_T) && !defined(HAVE_CPUMASK_T)
3925 +typedef unsigned long cpumask_t;
3926 +#endif
3927 +
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. */
3932 +#undef cpu_set
3933 +#define cpu_set(cpu, map)      atomic_set_mask((1UL << (cpu)), &(map))
3934 +#undef cpu_isset
3935 +#define cpu_isset(cpu, map)    ((map) & (1UL << (cpu)))
3936 +#undef cpus_and
3937 +#define cpus_and(dst,src1,src2)        do { (dst) = (src1) & (src2); } while(0)
3938 +#undef cpus_clear
3939 +#define cpus_clear(map)                do { (map) = 0UL; } while(0)
3940 +#undef cpus_complement
3941 +#define cpus_complement(map)   do { (map) = ~(map); } while(0)
3942 +#undef cpus_empty
3943 +#define cpus_empty(map)                ((map) == 0UL)
3944 +#undef cpus_equal
3945 +#define cpus_equal(map1, map2) ((map1) == (map2))
3946 +#undef cpus_addr
3947 +#define cpus_addr(map)         (&(map))
3948 +
3949 +#undef CPU_MASK_NONE
3950 +#define CPU_MASK_NONE          0UL
3951 +
3952 +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,1)
3953 +
3954 +/* 2.6.1-rc1 introduced cpus_addr() */
3955 +#ifdef CPU_ARRAY_SIZE
3956 +#define cpus_addr(map)         ((map).mask)
3957 +#else
3958 +#define cpus_addr(map)         (&(map))
3959 +#endif
3960 +
3961 +#endif
3962 +
3963 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) && !defined(cpus_andnot)
3964 +#define cpus_andnot(dst, src1, src2) \
3965 +do { \
3966 +    cpumask_t _tmp2; \
3967 +    _tmp2 = (src2); \
3968 +    cpus_complement(_tmp2); \
3969 +    cpus_and((dst), (src1), _tmp2); \
3970 +} while(0)
3971 +#endif
3972 +
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)
3976 +#endif
3977 +
3978 +#ifdef CPU_ARRAY_SIZE
3979 +#define PERFCTR_CPUMASK_NRLONGS        CPU_ARRAY_SIZE
3980 +#else
3981 +#define PERFCTR_CPUMASK_NRLONGS        1
3982 +#endif
3983 +
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)
3989 +#else
3990 +#define perfctr_cpus_forbidden_mask    CPU_MASK_NONE
3991 +#define perfctr_cpu_is_forbidden(cpu)  0 /* cpu_isset() needs an lvalue :-( */
3992 +#endif
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
3997 @@ -0,0 +1,41 @@
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.
4001 + *
4002 + * Copyright (C) 2000-2004  Mikael Pettersson
4003 + */
4004 +#include <linux/config.h>
4005 +#include <linux/version.h>
4006 +
4007 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,18)
4008 +
4009 +/* missing from <asm-i386/cpufeature.h> */
4010 +#define cpu_has_msr    boot_cpu_has(X86_FEATURE_MSR)
4011 +
4012 +#else  /* 2.4 */
4013 +
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))
4017 +#endif
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))
4021 +#endif
4022 +
4023 +#endif /* 2.4 */
4024 +
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"
4031 +#endif
4032 +#undef irq_enter
4033 +#undef irq_exit
4034 +#define irq_enter()    do{}while(0)
4035 +#define irq_exit()     do{}while(0)
4036 +#endif
4037 +
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
4043 @@ -0,0 +1,39 @@
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.
4046 +
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
4052 +
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
4057 +
4058 +driver-objs-$(CONFIG_PPC32) := ppc.o
4059 +tests-objs-$(CONFIG_PPC32) := ppc_tests.o
4060 +kernel-objs-$(CONFIG_PPC32) := ppc_setup.o
4061 +
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)
4070 +
4071 +perfctr-objs           := $(driver-objs-y)
4072 +obj-m                  += $(m-objs-m)
4073 +
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
4078 +
4079 +include $(TOPDIR)/Rules.make
4080 +
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
4087 @@ -0,0 +1,310 @@
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.
4091 + *
4092 + * Copyright (C) 1999-2004  Mikael Pettersson
4093 + */
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"
4109 +
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))
4125 +
4126 +#define NITER  64
4127 +#define X2(S)  S";"S
4128 +#define X8(S)  X2(X2(X2(S)))
4129 +
4130 +#ifdef __x86_64__
4131 +#define CR4MOV "movq"
4132 +#else
4133 +#define CR4MOV "movl"
4134 +#endif
4135 +
4136 +#ifndef CONFIG_X86_LOCAL_APIC
4137 +#undef apic_write
4138 +#define apic_write(reg,vector)                 do{}while(0)
4139 +#endif
4140 +
4141 +#if !defined(__x86_64__)
4142 +/* Avoid speculative execution by the CPU */
4143 +extern inline void sync_core(void)
4144 +{
4145 +       int tmp;
4146 +       asm volatile("cpuid" : "=a" (tmp) : "0" (1) : "ebx","ecx","edx","memory");
4147 +}
4148 +#endif
4149 +
4150 +static void __init do_rdpmc(unsigned pmc, unsigned unused2)
4151 +{
4152 +       unsigned i;
4153 +       for(i = 0; i < NITER/8; ++i)
4154 +               __asm__ __volatile__(X8("rdpmc") : : "c"(pmc) : "eax", "edx");
4155 +}
4156 +
4157 +static void __init do_rdmsr(unsigned msr, unsigned unused2)
4158 +{
4159 +       unsigned i;
4160 +       for(i = 0; i < NITER/8; ++i)
4161 +               __asm__ __volatile__(X8("rdmsr") : : "c"(msr) : "eax", "edx");
4162 +}
4163 +
4164 +static void __init do_wrmsr(unsigned msr, unsigned data)
4165 +{
4166 +       unsigned i;
4167 +       for(i = 0; i < NITER/8; ++i)
4168 +               __asm__ __volatile__(X8("wrmsr") : : "c"(msr), "a"(data), "d"(0));
4169 +}
4170 +
4171 +static void __init do_rdcr4(unsigned unused1, unsigned unused2)
4172 +{
4173 +       unsigned i;
4174 +       unsigned long dummy;
4175 +       for(i = 0; i < NITER/8; ++i)
4176 +               __asm__ __volatile__(X8(CR4MOV" %%cr4,%0") : "=r"(dummy));
4177 +}
4178 +
4179 +static void __init do_wrcr4(unsigned cr4, unsigned unused2)
4180 +{
4181 +       unsigned i;
4182 +       for(i = 0; i < NITER/8; ++i)
4183 +               __asm__ __volatile__(X8(CR4MOV" %0,%%cr4") : : "r"((long)cr4));
4184 +}
4185 +
4186 +static void __init do_rdtsc(unsigned unused1, unsigned unused2)
4187 +{
4188 +       unsigned i;
4189 +       for(i = 0; i < NITER/8; ++i)
4190 +               __asm__ __volatile__(X8("rdtsc") : : : "eax", "edx");
4191 +}
4192 +
4193 +static void __init do_wrlvtpc(unsigned val, unsigned unused2)
4194 +{
4195 +       unsigned i;
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);
4205 +       }
4206 +}
4207 +
4208 +static void __init do_sync_core(unsigned unused1, unsigned unused2)
4209 +{
4210 +       unsigned i;
4211 +       for(i = 0; i < NITER/8; ++i) {
4212 +               sync_core();
4213 +               sync_core();
4214 +               sync_core();
4215 +               sync_core();
4216 +               sync_core();
4217 +               sync_core();
4218 +               sync_core();
4219 +               sync_core();
4220 +       }
4221 +}
4222 +
4223 +static void __init do_empty_loop(unsigned unused1, unsigned unused2)
4224 +{
4225 +       unsigned i;
4226 +       for(i = 0; i < NITER/8; ++i)
4227 +               __asm__ __volatile__("" : : "c"(0));
4228 +}
4229 +
4230 +static unsigned __init run(void (*doit)(unsigned, unsigned),
4231 +                          unsigned arg1, unsigned arg2)
4232 +{
4233 +       unsigned start, dummy, stop;
4234 +       sync_core();
4235 +       rdtsc(start, dummy);
4236 +       (*doit)(arg1, arg2);    /* should take < 2^32 cycles to complete */
4237 +       sync_core();
4238 +       rdtsc(stop, dummy);
4239 +       return stop - start;
4240 +}
4241 +
4242 +static void __init init_tests_message(void)
4243 +{
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());
4254 +}
4255 +
4256 +static void __init
4257 +measure_overheads(unsigned msr_evntsel0, unsigned evntsel0, unsigned msr_perfctr0,
4258 +                 unsigned msr_cccr, unsigned cccr_val)
4259 +{
4260 +       int i;
4261 +       unsigned int loop, ticks[13];
4262 +       const char *name[13];
4263 +
4264 +       if (msr_evntsel0)
4265 +               wrmsr(msr_evntsel0, 0, 0);
4266 +       if (msr_cccr)
4267 +               wrmsr(msr_cccr, 0, 0);
4268 +
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);
4297 +
4298 +       loop = run(do_empty_loop, 0, 0);
4299 +
4300 +       if (msr_evntsel0)
4301 +               wrmsr(msr_evntsel0, 0, 0);
4302 +       if (msr_cccr)
4303 +               wrmsr(msr_cccr, 0, 0);
4304 +
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) {
4309 +               unsigned int x;
4310 +               if (!ticks[i])
4311 +                       continue;
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]);
4315 +       }
4316 +}
4317 +
4318 +#ifndef __x86_64__
4319 +static inline void perfctr_p5_init_tests(void)
4320 +{
4321 +       measure_overheads(MSR_P5_CESR, P5_CESR_VAL, MSR_P5_CTR0, 0, 0);
4322 +}
4323 +
4324 +static inline void perfctr_p6_init_tests(void)
4325 +{
4326 +       measure_overheads(MSR_P6_EVNTSEL0, P6_EVNTSEL0_VAL, MSR_P6_PERFCTR0, 0, 0);
4327 +}
4328 +
4329 +#if !defined(CONFIG_X86_TSC)
4330 +static inline void perfctr_c6_init_tests(void)
4331 +{
4332 +       unsigned int cesr, dummy;
4333 +
4334 +       rdmsr(MSR_P5_CESR, cesr, dummy);
4335 +       init_tests_message();
4336 +       printk(KERN_INFO "PERFCTR INIT: boot CESR == %#08x\n", cesr);
4337 +}
4338 +#endif
4339 +
4340 +static inline void perfctr_vc3_init_tests(void)
4341 +{
4342 +       measure_overheads(MSR_P6_EVNTSEL0+1, VC3_EVNTSEL1_VAL, MSR_P6_PERFCTR0+1, 0, 0);
4343 +}
4344 +#endif /* !__x86_64__ */
4345 +
4346 +static inline void perfctr_p4_init_tests(void)
4347 +{
4348 +       measure_overheads(MSR_P4_CRU_ESCR0, P4_CRU_ESCR0_VAL, MSR_P4_IQ_COUNTER0,
4349 +                         MSR_P4_IQ_CCCR0, P4_IQ_CCCR0_VAL);
4350 +}
4351 +
4352 +static inline void perfctr_k7_init_tests(void)
4353 +{
4354 +       measure_overheads(MSR_K7_EVNTSEL0, K7_EVNTSEL0_VAL, MSR_K7_PERFCTR0, 0, 0);
4355 +}
4356 +
4357 +static inline void perfctr_generic_init_tests(void)
4358 +{
4359 +       measure_overheads(0, 0, 0, 0, 0);
4360 +}
4361 +
4362 +enum perfctr_x86_tests_type perfctr_x86_tests_type __initdata = PTT_UNKNOWN;
4363 +
4364 +void __init perfctr_x86_init_tests(void)
4365 +{
4366 +       switch (perfctr_x86_tests_type) {
4367 +#ifndef __x86_64__
4368 +       case PTT_P5: /* Intel P5, P5MMX; Cyrix 6x86MX, MII, III */
4369 +               perfctr_p5_init_tests();
4370 +               break;
4371 +       case PTT_P6: /* Intel PPro, PII, PIII, PENTM */
4372 +               perfctr_p6_init_tests();
4373 +               break;
4374 +#if !defined(CONFIG_X86_TSC)
4375 +       case PTT_WINCHIP: /* WinChip C6, 2, 3 */
4376 +               perfctr_c6_init_tests();
4377 +               break;
4378 +#endif
4379 +       case PTT_VC3: /* VIA C3 */
4380 +               perfctr_vc3_init_tests();
4381 +               break;
4382 +#endif /* !__x86_64__ */
4383 +       case PTT_P4: /* Intel P4 */
4384 +               perfctr_p4_init_tests();
4385 +               break;
4386 +       case PTT_AMD: /* AMD K7, K8 */
4387 +               perfctr_k7_init_tests();
4388 +               break;
4389 +       case PTT_GENERIC:
4390 +               perfctr_generic_init_tests();
4391 +               break;
4392 +       default:
4393 +               printk(KERN_INFO "%s: unknown CPU type %u\n",
4394 +                      __FUNCTION__, perfctr_x86_tests_type);
4395 +               break;
4396 +       }
4397 +}
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
4402 @@ -0,0 +1,925 @@
4403 +/* $Id: ppc.c,v 1.3.2.8 2004/10/19 15:18:21 mikpe Exp $
4404 + * PPC32 performance-monitoring counters driver.
4405 + *
4406 + * Copyright (C) 2004  Mikael Pettersson
4407 + */
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() */
4417 +
4418 +#include "compat.h"
4419 +#include "ppc_compat.h"
4420 +#include "ppc_tests.h"
4421 +
4422 +/* Support for lazy evntsel and perfctr SPR updates. */
4423 +struct per_cpu_cache { /* roughly a subset of perfctr_cpu_state */
4424 +       union {
4425 +               unsigned int id;        /* cache owner id */
4426 +       } k1;
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()])
4432 +
4433 +/* Structure for counter snapshots, as 32-bit values. */
4434 +struct perfctr_low_ctrs {
4435 +       unsigned int tsc;
4436 +       unsigned int pmc[6];
4437 +};
4438 +
4439 +enum pm_type {
4440 +       PM_NONE,
4441 +       PM_604,
4442 +       PM_604e,
4443 +       PM_750, /* XXX: Minor event set diffs between IBM and Moto. */
4444 +       PM_7400,
4445 +       PM_7450,
4446 +};
4447 +static enum pm_type pm_type;
4448 +
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[]
4452 + */
4453 +#define MMCR0_RESERVED         (MMCR0_PMXE | MMCR0_PMC1SEL | MMCR0_PMC2SEL)
4454 +
4455 +static unsigned int new_id(void)
4456 +{
4457 +       static spinlock_t lock = SPIN_LOCK_UNLOCKED;
4458 +       static unsigned int counter;
4459 +       int id;
4460 +
4461 +       spin_lock(&lock);
4462 +       id = ++counter;
4463 +       spin_unlock(&lock);
4464 +       return id;
4465 +}
4466 +
4467 +#ifndef PERFCTR_INTERRUPT_SUPPORT
4468 +#define perfctr_cstatus_has_ictrs(cstatus)     0
4469 +#endif
4470 +
4471 +#if defined(CONFIG_SMP) && defined(PERFCTR_INTERRUPT_SUPPORT)
4472 +
4473 +static inline void
4474 +set_isuspend_cpu(struct perfctr_cpu_state *state, int cpu)
4475 +{
4476 +       state->k1.isuspend_cpu = cpu;
4477 +}
4478 +
4479 +static inline int
4480 +is_isuspend_cpu(const struct perfctr_cpu_state *state, int cpu)
4481 +{
4482 +       return state->k1.isuspend_cpu == cpu;
4483 +}
4484 +
4485 +static inline void clear_isuspend_cpu(struct perfctr_cpu_state *state)
4486 +{
4487 +       state->k1.isuspend_cpu = NR_CPUS;
4488 +}
4489 +
4490 +#else
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) { }
4494 +#endif
4495 +
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)
4499 +{
4500 +       return cstatus | (1 << 30);
4501 +}
4502 +
4503 +static inline int perfctr_cstatus_has_mmcr0_quirk(unsigned int cstatus)
4504 +{
4505 +       return cstatus & (1 << 30);
4506 +}
4507 +
4508 +/****************************************************************
4509 + *                                                             *
4510 + * Driver procedures.                                          *
4511 + *                                                             *
4512 + ****************************************************************/
4513 +
4514 +/*
4515 + * The PowerPC 604/750/74xx family.
4516 + *
4517 + * Common features
4518 + * ---------------
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.
4538 + *
4539 + * Driver notes
4540 + * ------------
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.
4546 + *
4547 + * 604
4548 + * ---
4549 + * 604 has MMCR0, PMC1, PMC2, SIA, and SDA.
4550 + *
4551 + * MMCR0[THRESHOLD] is not automatically multiplied.
4552 + *
4553 + * On the 604, software must always reset MMCR0[ENINT] after
4554 + * taking a PMI. This is not the case for the 604e.
4555 + *
4556 + * 604e
4557 + * ----
4558 + * 604e adds MMCR1, PMC3, and PMC4.
4559 + * Bus-to-core multiplier is available via HID1[PLL_CFG].
4560 + *
4561 + * MMCR0[THRESHOLD] is automatically multiplied by 4.
4562 + *
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.
4567 + *
4568 + * 750
4569 + * ---
4570 + * 750 adds user-readable MMCRn/PMCn/SIA registers, and removes SDA.
4571 + *
4572 + * MMCR0[THRESHOLD] is not automatically multiplied.
4573 + *
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."
4581 + *
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.
4586 + *
4587 + * 750FX adds dual-PLL support and programmable core frequency switching.
4588 + *
4589 + * 74xx
4590 + * ----
4591 + * 7400 adds MMCR2 and BAMR.
4592 + *
4593 + * MMCR0[THRESHOLD] is multiplied by 2 or 32, as specified
4594 + * by MMCR2[THRESHMULT].
4595 + *
4596 + * 74xx changes the semantics of several MMCR0 control bits,
4597 + * compared to 604/750.
4598 + *
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.
4604 + *
4605 + * 7450 adds PMC5 and PMC6.
4606 + *
4607 + * 7455/7445 V3.3 (PVR 80010303) and later use the 7457 PLL table,
4608 + * earlier revisions use the 7450 PLL table
4609 + */
4610 +
4611 +static inline unsigned int read_pmc(unsigned int pmc)
4612 +{
4613 +       switch (pmc) {
4614 +       default: /* impossible, but silences gcc warning */
4615 +       case 0:
4616 +               return mfspr(SPRN_PMC1);
4617 +       case 1:
4618 +               return mfspr(SPRN_PMC2);
4619 +       case 2:
4620 +               return mfspr(SPRN_PMC3);
4621 +       case 3:
4622 +               return mfspr(SPRN_PMC4);
4623 +       case 4:
4624 +               return mfspr(SPRN_PMC5);
4625 +       case 5:
4626 +               return mfspr(SPRN_PMC6);
4627 +       }
4628 +}
4629 +
4630 +static void ppc_read_counters(struct perfctr_cpu_state *state,
4631 +                             struct perfctr_low_ctrs *ctrs)
4632 +{
4633 +       unsigned int cstatus, nrctrs, i;
4634 +
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);
4642 +       }
4643 +}
4644 +
4645 +static unsigned int pmc_max_event(unsigned int pmc)
4646 +{
4647 +       switch (pmc) {
4648 +       default: /* impossible, but silences gcc warning */
4649 +       case 0:
4650 +               return 127;
4651 +       case 1:
4652 +               return 63;
4653 +       case 2:
4654 +               return 31;
4655 +       case 3:
4656 +               return 31;
4657 +       case 4:
4658 +               return 31;
4659 +       case 5:
4660 +               return 63;
4661 +       }
4662 +}
4663 +
4664 +static unsigned int get_nr_pmcs(void)
4665 +{
4666 +       switch (pm_type) {
4667 +       case PM_7450:
4668 +               return 6;
4669 +       case PM_7400:
4670 +       case PM_750:
4671 +       case PM_604e:
4672 +               return 4;
4673 +       case PM_604:
4674 +               return 2;
4675 +       default: /* PM_NONE, but silences gcc warning */
4676 +               return 0;
4677 +       }
4678 +}
4679 +
4680 +static int ppc_check_control(struct perfctr_cpu_state *state)
4681 +{
4682 +       unsigned int i, nrctrs, pmc_mask, pmc;
4683 +       unsigned int nr_pmcs, evntsel[6];
4684 +
4685 +       nr_pmcs = get_nr_pmcs();
4686 +       nrctrs = state->control.nractrs;
4687 +       if (state->control.nrictrs || nrctrs > nr_pmcs)
4688 +               return -EINVAL;
4689 +
4690 +       pmc_mask = 0;
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)))
4696 +                       return -EINVAL;
4697 +               pmc_mask |= (1<<pmc);
4698 +
4699 +               evntsel[pmc] = state->control.evntsel[i];
4700 +               if (evntsel[pmc] > pmc_max_event(pmc))
4701 +                       return -EINVAL;
4702 +       }
4703 +
4704 +       switch (pm_type) {
4705 +       case PM_7450:
4706 +       case PM_7400:
4707 +               if (state->control.ppc.mmcr2 & MMCR2_RESERVED)
4708 +                       return -EINVAL;
4709 +               state->ppc_mmcr[2] = state->control.ppc.mmcr2;
4710 +               break;
4711 +       default:
4712 +               if (state->control.ppc.mmcr2)
4713 +                       return -EINVAL;
4714 +               state->ppc_mmcr[2] = 0;
4715 +       }
4716 +
4717 +       if (state->control.ppc.mmcr0 & MMCR0_RESERVED)
4718 +               return -EINVAL;
4719 +       state->ppc_mmcr[0] = (state->control.ppc.mmcr0
4720 +                             | (evntsel[0] << (31-25))
4721 +                             | (evntsel[1] << (31-31)));
4722 +
4723 +       state->ppc_mmcr[1] = ((  evntsel[2] << (31-4))
4724 +                             | (evntsel[3] << (31-9))
4725 +                             | (evntsel[4] << (31-14))
4726 +                             | (evntsel[5] << (31-20)));
4727 +
4728 +       state->k1.id = new_id();
4729 +
4730 +       /*
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.
4735 +        */
4736 +       switch (pm_type) {
4737 +       case PM_7450:
4738 +       case PM_7400:
4739 +               if (state->ppc_mmcr[0] & (MMCR0_FCECE | MMCR0_TRIGGER))
4740 +                       state->cstatus = perfctr_cstatus_set_mmcr0_quirk(state->cstatus);
4741 +       default:
4742 +               ;
4743 +       }
4744 +
4745 +       return 0;
4746 +}
4747 +
4748 +#ifdef PERFCTR_INTERRUPT_SUPPORT
4749 +static void ppc_isuspend(struct perfctr_cpu_state *state)
4750 +{
4751 +       // XXX
4752 +}
4753 +
4754 +static void ppc_iresume(const struct perfctr_cpu_state *state)
4755 +{
4756 +       // XXX
4757 +}
4758 +#endif
4759 +
4760 +static void ppc_write_control(const struct perfctr_cpu_state *state)
4761 +{
4762 +       struct per_cpu_cache *cache;
4763 +       unsigned int value;
4764 +
4765 +       cache = get_cpu_cache();
4766 +       if (cache->k1.id == state->k1.id)
4767 +               return;
4768 +       /*
4769 +        * Order matters here: update threshmult and event
4770 +        * selectors before updating global control, which
4771 +        * potentially enables PMIs.
4772 +        *
4773 +        * Since mtspr doesn't accept a runtime value for the
4774 +        * SPR number, unroll the loop so each mtspr targets
4775 +        * a constant SPR.
4776 +        *
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.
4780 +        */
4781 +       value = state->ppc_mmcr[2];
4782 +       if (value != cache->ppc_mmcr[2]) {
4783 +               cache->ppc_mmcr[2] = value;
4784 +               mtspr(SPRN_MMCR2, value);
4785 +       }
4786 +       value = state->ppc_mmcr[1];
4787 +       if (value != cache->ppc_mmcr[1]) {
4788 +               cache->ppc_mmcr[1] = value;
4789 +               mtspr(SPRN_MMCR1, value);
4790 +       }
4791 +       value = state->ppc_mmcr[0];
4792 +       if (value != cache->ppc_mmcr[0]) {
4793 +               cache->ppc_mmcr[0] = value;
4794 +               mtspr(SPRN_MMCR0, value);
4795 +       }
4796 +       cache->k1.id = state->k1.id;
4797 +}
4798 +
4799 +static void ppc_clear_counters(void)
4800 +{
4801 +       switch (pm_type) {
4802 +       case PM_7450:
4803 +       case PM_7400:
4804 +               mtspr(SPRN_MMCR2, 0);
4805 +               mtspr(SPRN_BAMR, 0);
4806 +       case PM_750:
4807 +       case PM_604e:
4808 +               mtspr(SPRN_MMCR1, 0);
4809 +       case PM_604:
4810 +               mtspr(SPRN_MMCR0, 0);
4811 +       case PM_NONE:
4812 +               ;
4813 +       }
4814 +       switch (pm_type) {
4815 +       case PM_7450:
4816 +               mtspr(SPRN_PMC6, 0);
4817 +               mtspr(SPRN_PMC5, 0);
4818 +       case PM_7400:
4819 +       case PM_750:
4820 +       case PM_604e:
4821 +               mtspr(SPRN_PMC4, 0);
4822 +               mtspr(SPRN_PMC3, 0);
4823 +       case PM_604:
4824 +               mtspr(SPRN_PMC2, 0);
4825 +               mtspr(SPRN_PMC1, 0);
4826 +       case PM_NONE:
4827 +               ;
4828 +       }
4829 +}
4830 +
4831 +/*
4832 + * Driver methods, internal and exported.
4833 + */
4834 +
4835 +static void perfctr_cpu_write_control(const struct perfctr_cpu_state *state)
4836 +{
4837 +       return ppc_write_control(state);
4838 +}
4839 +
4840 +static void perfctr_cpu_read_counters(struct perfctr_cpu_state *state,
4841 +                                     struct perfctr_low_ctrs *ctrs)
4842 +{
4843 +       return ppc_read_counters(state, ctrs);
4844 +}
4845 +
4846 +#ifdef PERFCTR_INTERRUPT_SUPPORT
4847 +static void perfctr_cpu_isuspend(struct perfctr_cpu_state *state)
4848 +{
4849 +       return ppc_isuspend(state);
4850 +}
4851 +
4852 +static void perfctr_cpu_iresume(const struct perfctr_cpu_state *state)
4853 +{
4854 +       return ppc_iresume(state);
4855 +}
4856 +
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)
4860 +{
4861 +#ifdef CONFIG_SMP
4862 +       clear_isuspend_cpu(state);
4863 +#else
4864 +       get_cpu_cache()->k1.id = 0;
4865 +#endif
4866 +}
4867 +
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)
4870 +{
4871 +       unsigned int cstatus, nrctrs, pmc, pmc_mask;
4872 +
4873 +       cstatus = state->cstatus;
4874 +       pmc = perfctr_cstatus_nractrs(cstatus);
4875 +       nrctrs = perfctr_cstatus_nrctrs(cstatus);
4876 +
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);
4882 +               }
4883 +       }
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? */
4887 +       return pmc_mask;
4888 +}
4889 +
4890 +static inline int check_ireset(const struct perfctr_cpu_state *state)
4891 +{
4892 +       unsigned int nrctrs, i;
4893 +
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 */
4898 +                       return -EINVAL;
4899 +       return 0;
4900 +}
4901 +
4902 +static inline void setup_imode_start_values(struct perfctr_cpu_state *state)
4903 +{
4904 +       unsigned int cstatus, nrctrs, i;
4905 +
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];
4910 +}
4911 +
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 */
4918 +
4919 +static int check_control(struct perfctr_cpu_state *state)
4920 +{
4921 +       return ppc_check_control(state);
4922 +}
4923 +
4924 +int perfctr_cpu_update_control(struct perfctr_cpu_state *state, int is_global)
4925 +{
4926 +       int err;
4927 +
4928 +       clear_isuspend_cpu(state);
4929 +       state->cstatus = 0;
4930 +
4931 +       /* disallow i-mode counters if we cannot catch the interrupts */
4932 +       if (!(perfctr_info.cpu_features & PERFCTR_FEATURE_PCINT)
4933 +           && state->control.nrictrs)
4934 +               return -EPERM;
4935 +
4936 +       err = check_ireset(state);
4937 +       if (err < 0)
4938 +               return err;
4939 +       err = check_control(state); /* may initialise state->cstatus */
4940 +       if (err < 0)
4941 +               return err;
4942 +       state->cstatus |= perfctr_mk_cstatus(state->control.tsc_on,
4943 +                                            state->control.nractrs,
4944 +                                            state->control.nrictrs);
4945 +       setup_imode_start_values(state);
4946 +       return 0;
4947 +}
4948 +
4949 +void perfctr_cpu_suspend(struct perfctr_cpu_state *state)
4950 +{
4951 +       unsigned int i, cstatus, nractrs;
4952 +       struct perfctr_low_ctrs now;
4953 +
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;
4959 +       }
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;
4969 +}
4970 +
4971 +void perfctr_cpu_resume(struct perfctr_cpu_state *state)
4972 +{
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);
4979 +       {
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];
4989 +       }
4990 +       /* XXX: if (SMP && start.tsc == now.tsc) ++now.tsc; */
4991 +}
4992 +
4993 +void perfctr_cpu_sample(struct perfctr_cpu_state *state)
4994 +{
4995 +       unsigned int i, cstatus, nractrs;
4996 +       struct perfctr_low_ctrs now;
4997 +
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;
5003 +       }
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];
5008 +       }
5009 +}
5010 +
5011 +static void perfctr_cpu_clear_counters(void)
5012 +{
5013 +       struct per_cpu_cache *cache;
5014 +
5015 +       cache = get_cpu_cache();
5016 +       memset(cache, 0, sizeof *cache);
5017 +       cache->k1.id = -1;
5018 +
5019 +       ppc_clear_counters();
5020 +}
5021 +
5022 +/****************************************************************
5023 + *                                                             *
5024 + * Processor detection and initialisation procedures.          *
5025 + *                                                             *
5026 + ****************************************************************/
5027 +
5028 +/* Derive CPU core frequency from TB frequency and PLL_CFG. */
5029 +
5030 +enum pll_type {
5031 +       PLL_NONE,       /* for e.g. 604 which has no HID1[PLL_CFG] */
5032 +       PLL_604e,
5033 +       PLL_750,
5034 +       PLL_750FX,
5035 +       PLL_7400,
5036 +       PLL_7450,
5037 +       PLL_7457,
5038 +};
5039 +
5040 +/* These are the known bus-to-core ratios, indexed by PLL_CFG.
5041 +   Multiplied by 2 since half-multiplier steps are present. */
5042 +
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
5046 +};
5047 +
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
5051 +};
5052 +
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
5058 +};
5059 +
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
5063 +};
5064 +
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
5070 +};
5071 +
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
5077 +};
5078 +
5079 +static unsigned int __init tb_to_core_ratio(enum pll_type pll_type)
5080 +{
5081 +       unsigned char *cfg_ratio;
5082 +       unsigned int shift = 28, mask = 0xF, hid1, pll_cfg, ratio;
5083 +
5084 +       switch (pll_type) {
5085 +       case PLL_604e:
5086 +               cfg_ratio = cfg_ratio_604e;
5087 +               break;
5088 +       case PLL_750:
5089 +               cfg_ratio = cfg_ratio_750;
5090 +               break;
5091 +       case PLL_750FX:
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] */
5097 +                       break;
5098 +               case 2:         /* PLL0 with internal config */
5099 +                       shift = 31-20;  /* access HID1[PC0] */
5100 +                       break;
5101 +               case 1: case 3: /* PLL1 */
5102 +                       shift = 31-28;  /* access HID1[PC1] */
5103 +                       break;
5104 +               }
5105 +               mask = 0x1F;
5106 +               break;
5107 +       case PLL_7400:
5108 +               cfg_ratio = cfg_ratio_7400;
5109 +               break;
5110 +       case PLL_7450:
5111 +               cfg_ratio = cfg_ratio_7450;
5112 +               shift = 12;
5113 +               mask = 0x1F;
5114 +               break;
5115 +       case PLL_7457:
5116 +               cfg_ratio = cfg_ratio_7457;
5117 +               shift = 12;
5118 +               mask = 0x1F;
5119 +               break;
5120 +       default:
5121 +               return 0;
5122 +       }
5123 +       hid1 = mfspr(SPRN_HID1);
5124 +       pll_cfg = (hid1 >> shift) & mask;
5125 +       ratio = cfg_ratio[pll_cfg];
5126 +       if (!ratio)
5127 +               printk(KERN_WARNING "perfctr: unknown PLL_CFG 0x%x\n", pll_cfg);
5128 +       return (4/2) * ratio;
5129 +}
5130 +
5131 +static unsigned int __init pll_to_core_khz(enum pll_type pll_type)
5132 +{
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);
5136 +}
5137 +
5138 +/* Extract core and timebase frequencies from Open Firmware. */
5139 +
5140 +static unsigned int __init of_to_core_khz(void)
5141 +{
5142 +       struct device_node *cpu;
5143 +       unsigned int *fp, core, tb;
5144 +
5145 +       cpu = find_type_devices("cpu");
5146 +       if (!cpu)
5147 +               return 0;
5148 +       fp = (unsigned int*)get_property(cpu, "clock-frequency", NULL);
5149 +       if (!fp || !(core = *fp))
5150 +               return 0;
5151 +       fp = (unsigned int*)get_property(cpu, "timebase-frequency", NULL);
5152 +       if (!fp || !(tb = *fp))
5153 +               return 0;
5154 +       perfctr_info.tsc_to_cpu_mult = core / tb;
5155 +       return core / 1000;
5156 +}
5157 +
5158 +static unsigned int __init detect_cpu_khz(enum pll_type pll_type)
5159 +{
5160 +       unsigned int khz;
5161 +
5162 +       khz = pll_to_core_khz(pll_type);
5163 +       if (khz)
5164 +               return khz;
5165 +
5166 +       khz = of_to_core_khz();
5167 +       if (khz)
5168 +               return khz;
5169 +
5170 +       printk(KERN_WARNING "perfctr: unable to determine CPU speed\n");
5171 +       return 0;
5172 +}
5173 +
5174 +static int __init known_init(void)
5175 +{
5176 +       static char known_name[] __initdata = "PowerPC 60x/7xx/74xx";
5177 +       unsigned int features;
5178 +       enum pll_type pll_type;
5179 +       unsigned int pvr;
5180 +       int have_mmcr1;
5181 +
5182 +       features = PERFCTR_FEATURE_RDTSC | PERFCTR_FEATURE_RDPMC;
5183 +       have_mmcr1 = 1;
5184 +       pvr = mfspr(SPRN_PVR);
5185 +       switch (PVR_VER(pvr)) {
5186 +       case 0x0004: /* 604 */
5187 +               pm_type = PM_604;
5188 +               pll_type = PLL_NONE;
5189 +               features = PERFCTR_FEATURE_RDTSC;
5190 +               have_mmcr1 = 0;
5191 +               break;
5192 +       case 0x0009: /* 604e;  */
5193 +       case 0x000A: /* 604ev */
5194 +               pm_type = PM_604e;
5195 +               pll_type = PLL_604e;
5196 +               features = PERFCTR_FEATURE_RDTSC;
5197 +               break;
5198 +       case 0x0008: /* 750/740 */
5199 +               pm_type = PM_750;
5200 +               pll_type = PLL_750;
5201 +               break;
5202 +       case 0x7000: case 0x7001: /* IBM750FX */
5203 +       case 0x7002: /* IBM750GX */
5204 +               pm_type = PM_750;
5205 +               pll_type = PLL_750FX;
5206 +               break;
5207 +       case 0x000C: /* 7400 */
5208 +               pm_type = PM_7400;
5209 +               pll_type = PLL_7400;
5210 +               break;
5211 +       case 0x800C: /* 7410 */
5212 +               pm_type = PM_7400;
5213 +               pll_type = PLL_7400;
5214 +               break;
5215 +       case 0x8000: /* 7451/7441 */
5216 +               pm_type = PM_7450;
5217 +               pll_type = PLL_7450;
5218 +               break;
5219 +       case 0x8001: /* 7455/7445 */
5220 +               pm_type = PM_7450;
5221 +               pll_type = ((pvr & 0xFFFF) < 0x0303) ? PLL_7450 : PLL_7457;
5222 +               break;
5223 +       case 0x8002: /* 7457/7447 */
5224 +               pm_type = PM_7450;
5225 +               pll_type = PLL_7457;
5226 +               break;
5227 +       default:
5228 +               return -ENODEV;
5229 +       }
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);
5235 +       return 0;
5236 +}
5237 +
5238 +static int __init unknown_init(void)
5239 +{
5240 +       static char unknown_name[] __initdata = "Generic PowerPC with TB";
5241 +       unsigned int khz;
5242 +
5243 +       khz = detect_cpu_khz(PLL_NONE);
5244 +       if (!khz)
5245 +               return -ENODEV;
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;
5251 +       return 0;
5252 +}
5253 +
5254 +static void perfctr_cpu_clear_one(void *ignore)
5255 +{
5256 +       /* PREEMPT note: when called via on_each_cpu(),
5257 +          this is in IRQ context with preemption disabled. */
5258 +       perfctr_cpu_clear_counters();
5259 +}
5260 +
5261 +static void perfctr_cpu_reset(void)
5262 +{
5263 +       on_each_cpu(perfctr_cpu_clear_one, NULL, 1, 1);
5264 +       perfctr_cpu_set_ihandler(NULL);
5265 +}
5266 +
5267 +int __init perfctr_cpu_init(void)
5268 +{
5269 +       int err;
5270 +
5271 +       perfctr_info.cpu_features = 0;
5272 +
5273 +       err = known_init();
5274 +       if (err) {
5275 +               err = unknown_init();
5276 +               if (err)
5277 +                       goto out;
5278 +       }
5279 +
5280 +       perfctr_cpu_reset();
5281 + out:
5282 +       return err;
5283 +}
5284 +
5285 +void __exit perfctr_cpu_exit(void)
5286 +{
5287 +       perfctr_cpu_reset();
5288 +}
5289 +
5290 +/****************************************************************
5291 + *                                                             *
5292 + * Hardware reservation.                                       *
5293 + *                                                             *
5294 + ****************************************************************/
5295 +
5296 +static DECLARE_MUTEX(mutex);
5297 +static const char *current_service = 0;
5298 +
5299 +const char *perfctr_cpu_reserve(const char *service)
5300 +{
5301 +       const char *ret;
5302 +
5303 +       down(&mutex);
5304 +       ret = current_service;
5305 +       if (!ret)
5306 +       {
5307 +               current_service = service;
5308 +               __module_get(THIS_MODULE);
5309 +       }
5310 +       up(&mutex);
5311 +       return ret;
5312 +}
5313 +
5314 +void perfctr_cpu_release(const char *service)
5315 +{
5316 +       down(&mutex);
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);
5320 +       } else {
5321 +               /* power down the counters */
5322 +               perfctr_cpu_reset();
5323 +               current_service = 0;
5324 +               module_put(THIS_MODULE);
5325 +       }
5326 +       up(&mutex);
5327 +}
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
5332 @@ -0,0 +1,1049 @@
5333 +/* $Id: virtual.c,v 1.88.2.2 2004/10/19 15:23:43 mikpe Exp $
5334 + * Virtual per-process performance counters.
5335 + *
5336 + * Copyright (C) 1999-2003  Mikael Pettersson
5337 + */
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>
5349 +
5350 +#include <asm/io.h>
5351 +#include <asm/uaccess.h>
5352 +
5353 +#include "compat.h"
5354 +#include "virtual.h"
5355 +#include "marshal.h"
5356 +
5357 +/****************************************************************
5358 + *                                                             *
5359 + * Data types and macros.                                      *
5360 + *                                                             *
5361 + ****************************************************************/
5362 +
5363 +struct vperfctr {
5364 +/* User-visible fields: (must be first for mmap()) */
5365 +       struct perfctr_cpu_state cpu_state;
5366 +/* Kernel-private fields: */
5367 +       int si_signo;
5368 +       atomic_t count;
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;
5376 +#endif
5377 +#if 0 && defined(CONFIG_PERFCTR_DEBUG)
5378 +       unsigned start_smp_id;
5379 +       unsigned suspended;
5380 +#endif
5381 +#if PERFCTR_INTERRUPT_SUPPORT
5382 +       unsigned int iresume_cstatus;
5383 +#endif
5384 +};
5385 +#define IS_RUNNING(perfctr)    perfctr_cstatus_enabled((perfctr)->cpu_state.cstatus)
5386 +
5387 +/* XXX: disabled: called from switch_to() where printk() is disallowed */
5388 +#if 0 && defined(CONFIG_PERFCTR_DEBUG)
5389 +#define debug_free(perfctr) \
5390 +do { \
5391 +       int i; \
5392 +       for(i = 0; i < PAGE_SIZE/sizeof(int); ++i) \
5393 +               ((int*)(perfctr))[i] = 0xfedac0ed; \
5394 +} while( 0 )
5395 +#define debug_init(perfctr)    do { (perfctr)->suspended = 1; } while( 0 )
5396 +#define debug_suspend(perfctr) \
5397 +do { \
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; \
5402 +} while( 0 )
5403 +#define debug_resume(perfctr) \
5404 +do { \
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; \
5409 +} while( 0 )
5410 +#define debug_check_smp_id(perfctr) \
5411 +do { \
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); \
5416 +               return; \
5417 +       } \
5418 +} while( 0 )
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 */
5429 +
5430 +#if PERFCTR_INTERRUPT_SUPPORT
5431 +
5432 +static void vperfctr_ihandler(unsigned long pc);
5433 +
5434 +static inline void vperfctr_set_ihandler(void)
5435 +{
5436 +       perfctr_cpu_set_ihandler(vperfctr_ihandler);
5437 +}
5438 +
5439 +static inline void vperfctr_clear_iresume_cstatus(struct vperfctr *perfctr)
5440 +{
5441 +       perfctr->iresume_cstatus = 0;
5442 +}
5443 +
5444 +#else
5445 +static inline void vperfctr_set_ihandler(void) { }
5446 +static inline void vperfctr_clear_iresume_cstatus(struct vperfctr *perfctr) { }
5447 +#endif
5448 +
5449 +#if PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED
5450 +
5451 +static inline void vperfctr_init_bad_cpus_allowed(struct vperfctr *perfctr)
5452 +{
5453 +       atomic_set(&perfctr->bad_cpus_allowed, 0);
5454 +}
5455 +
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. */
5459 +
5460 +static inline void vperfctr_task_lock(struct task_struct *p)
5461 +{
5462 +       task_lock(p);
5463 +}
5464 +
5465 +static inline void vperfctr_task_unlock(struct task_struct *p)
5466 +{
5467 +       task_unlock(p);
5468 +}
5469 +
5470 +#else  /* !PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED */
5471 +
5472 +static inline void vperfctr_init_bad_cpus_allowed(struct vperfctr *perfctr) { }
5473 +
5474 +/* Concurrent set_cpus_allowed() is impossible or irrelevant.
5475 +   Disabling and enabling preemption suffices for an atomic region. */
5476 +
5477 +static inline void vperfctr_task_lock(struct task_struct *p)
5478 +{
5479 +       preempt_disable();
5480 +}
5481 +
5482 +static inline void vperfctr_task_unlock(struct task_struct *p)
5483 +{
5484 +       preempt_enable();
5485 +}
5486 +
5487 +#endif /* !PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED */
5488 +
5489 +/****************************************************************
5490 + *                                                             *
5491 + * Resource management.                                                *
5492 + *                                                             *
5493 + ****************************************************************/
5494 +
5495 +/* XXX: perhaps relax this to number of _live_ perfctrs */
5496 +static DECLARE_MUTEX(nrctrs_mutex);
5497 +static int nrctrs;
5498 +static const char this_service[] = __FILE__;
5499 +
5500 +static int inc_nrctrs(void)
5501 +{
5502 +       const char *other;
5503 +
5504 +       other = NULL;
5505 +       down(&nrctrs_mutex);
5506 +       if( ++nrctrs == 1 ) {
5507 +               other = perfctr_cpu_reserve(this_service);
5508 +               if( other )
5509 +                       nrctrs = 0;
5510 +       }
5511 +       up(&nrctrs_mutex);
5512 +       if( other ) {
5513 +               printk(KERN_ERR __FILE__
5514 +                      ": cannot operate, perfctr hardware taken by '%s'\n",
5515 +                      other);
5516 +               return -EBUSY;
5517 +       }
5518 +       vperfctr_set_ihandler();
5519 +       return 0;
5520 +}
5521 +
5522 +static void dec_nrctrs(void)
5523 +{
5524 +       down(&nrctrs_mutex);
5525 +       if( --nrctrs == 0 )
5526 +               perfctr_cpu_release(this_service);
5527 +       up(&nrctrs_mutex);
5528 +}
5529 +
5530 +static struct vperfctr *vperfctr_alloc(void)
5531 +{
5532 +       unsigned long page;
5533 +
5534 +       if( inc_nrctrs() != 0 )
5535 +               return ERR_PTR(-EBUSY);
5536 +       page = get_zeroed_page(GFP_KERNEL);
5537 +       if( !page ) {
5538 +               dec_nrctrs();
5539 +               return ERR_PTR(-ENOMEM);
5540 +       }
5541 +       SetPageReserved(virt_to_page(page));
5542 +       return (struct vperfctr*) page;
5543 +}
5544 +
5545 +static void vperfctr_free(struct vperfctr *perfctr)
5546 +{
5547 +       debug_free(perfctr);
5548 +       ClearPageReserved(virt_to_page(perfctr));
5549 +       free_page((unsigned long)perfctr);
5550 +       dec_nrctrs();
5551 +}
5552 +
5553 +static struct vperfctr *get_empty_vperfctr(void)
5554 +{
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);
5561 +       }
5562 +       return perfctr;
5563 +}
5564 +
5565 +static void put_vperfctr(struct vperfctr *perfctr)
5566 +{
5567 +       if( atomic_dec_and_test(&perfctr->count) )
5568 +               vperfctr_free(perfctr);
5569 +}
5570 +
5571 +/****************************************************************
5572 + *                                                             *
5573 + * Basic counter operations.                                   *
5574 + * These must all be called by the owner process only.         *
5575 + * These must all be called with preemption disabled.          *
5576 + *                                                             *
5577 + ****************************************************************/
5578 +
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'...
5583 + */
5584 +static inline void vperfctr_suspend(struct vperfctr *perfctr)
5585 +{
5586 +       debug_suspend(perfctr);
5587 +       debug_check_smp_id(perfctr);
5588 +       perfctr_cpu_suspend(&perfctr->cpu_state);
5589 +}
5590 +
5591 +static inline void vperfctr_reset_sampling_timer(struct vperfctr *perfctr)
5592 +{
5593 +       /* XXX: base the value on perfctr_info.cpu_khz instead! */
5594 +       perfctr->sampling_timer = HZ/2;
5595 +}
5596 +
5597 +/* PRE: perfctr == current->thread.perfctr && IS_RUNNING(perfctr)
5598 + * Restart the counters.
5599 + */
5600 +static inline void vperfctr_resume(struct vperfctr *perfctr)
5601 +{
5602 +       debug_resume(perfctr);
5603 +       perfctr_cpu_resume(&perfctr->cpu_state);
5604 +       vperfctr_reset_sampling_timer(perfctr);
5605 +       debug_set_smp_id(perfctr);
5606 +}
5607 +
5608 +/* Sample the counters but do not suspend them. */
5609 +static void vperfctr_sample(struct vperfctr *perfctr)
5610 +{
5611 +       if( IS_RUNNING(perfctr) ) {
5612 +               debug_check_smp_id(perfctr);
5613 +               perfctr_cpu_sample(&perfctr->cpu_state);
5614 +               vperfctr_reset_sampling_timer(perfctr);
5615 +       }
5616 +}
5617 +
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)
5622 +{
5623 +       struct task_struct *tsk = current;
5624 +       struct vperfctr *perfctr;
5625 +       unsigned int pmc_mask;
5626 +       siginfo_t si;
5627 +
5628 +       perfctr = tsk->thread.perfctr;
5629 +       if( !perfctr ) {
5630 +               printk(KERN_ERR "%s: BUG! pid %d has no vperfctr\n",
5631 +                      __FUNCTION__, tsk->pid);
5632 +               return;
5633 +       }
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);
5637 +               return;
5638 +       }
5639 +       vperfctr_suspend(perfctr);
5640 +       pmc_mask = perfctr_cpu_identify_overflow(&perfctr->cpu_state);
5641 +       if( !pmc_mask ) {
5642 +               printk(KERN_ERR "%s: BUG! pid %d has unidentifiable overflow source\n",
5643 +                      __FUNCTION__, tsk->pid);
5644 +               return;
5645 +       }
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);
5652 +       } else
5653 +               perfctr->cpu_state.cstatus = 0;
5654 +       si.si_signo = perfctr->si_signo;
5655 +       si.si_errno = 0;
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);
5660 +}
5661 +#endif
5662 +
5663 +/****************************************************************
5664 + *                                                             *
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   *
5668 + * process only.                                               *
5669 + *                                                             *
5670 + ****************************************************************/
5671 +
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.
5676 + */
5677 +static void vperfctr_unlink(struct task_struct *owner, struct vperfctr *perfctr)
5678 +{
5679 +       /* this synchronises with vperfctr_ioctl() */
5680 +       spin_lock(&perfctr->owner_lock);
5681 +       perfctr->owner = NULL;
5682 +       spin_unlock(&perfctr->owner_lock);
5683 +
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);
5691 +
5692 +       perfctr->cpu_state.cstatus = 0;
5693 +       vperfctr_clear_iresume_cstatus(perfctr);
5694 +       put_vperfctr(perfctr);
5695 +}
5696 +
5697 +void __vperfctr_exit(struct vperfctr *perfctr)
5698 +{
5699 +       vperfctr_unlink(current, perfctr);
5700 +}
5701 +
5702 +/* schedule() --> switch_to() --> .. --> __vperfctr_suspend().
5703 + * If the counters are running, suspend them.
5704 + * PREEMPT note: switch_to() runs with preemption disabled.
5705 + */
5706 +void __vperfctr_suspend(struct vperfctr *perfctr)
5707 +{
5708 +       if( IS_RUNNING(perfctr) )
5709 +               vperfctr_suspend(perfctr);
5710 +}
5711 +
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.
5716 + */
5717 +void __vperfctr_resume(struct vperfctr *perfctr)
5718 +{
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);
5727 +                       return;
5728 +               }
5729 +#endif
5730 +               vperfctr_resume(perfctr);
5731 +       }
5732 +}
5733 +
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.
5740 + */
5741 +void __vperfctr_sample(struct vperfctr *perfctr)
5742 +{
5743 +       if( --perfctr->sampling_timer == 0 )
5744 +               vperfctr_sample(perfctr);
5745 +}
5746 +
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
5751 + */
5752 +void __vperfctr_set_cpus_allowed(struct task_struct *owner,
5753 +                                struct vperfctr *perfctr,
5754 +                                cpumask_t new_mask)
5755 +{
5756 +       cpumask_t tmp;
5757 +
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);
5764 +       } else
5765 +               atomic_set(&perfctr->bad_cpus_allowed, 0);
5766 +}
5767 +#endif
5768 +
5769 +/****************************************************************
5770 + *                                                             *
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).                                 *
5776 + *                                                             *
5777 + ****************************************************************/
5778 +
5779 +static int sys_vperfctr_control(struct vperfctr *perfctr,
5780 +                               struct perfctr_struct_buf *argp,
5781 +                               struct task_struct *tsk)
5782 +{
5783 +       struct vperfctr_control control;
5784 +       int err;
5785 +       unsigned int next_cstatus;
5786 +       unsigned int nrctrs, i;
5787 +
5788 +       if( !tsk )
5789 +               return -ESRCH;  /* attempt to update unlinked perfctr */
5790 +
5791 +       err = perfctr_copy_from_user(&control, argp, &vperfctr_control_sdesc);
5792 +       if( err )
5793 +               return err;
5794 +
5795 +       if( control.cpu_control.nractrs || control.cpu_control.nrictrs ) {
5796 +               cpumask_t old_mask, new_mask;
5797 +
5798 +               old_mask = tsk->cpus_allowed;
5799 +               cpus_andnot(new_mask, old_mask, perfctr_cpus_forbidden_mask);
5800 +
5801 +               if( cpus_empty(new_mask) )
5802 +                       return -EINVAL;
5803 +               if( !cpus_equal(new_mask, old_mask) )
5804 +                       set_cpus_allowed(tsk, new_mask);
5805 +       }
5806 +
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);
5815 +       }
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);
5819 +       if( err < 0 )
5820 +               goto out;
5821 +       next_cstatus = perfctr->cpu_state.cstatus;
5822 +       if( !perfctr_cstatus_enabled(next_cstatus) )
5823 +               goto out;
5824 +
5825 +       /* XXX: validate si_signo? */
5826 +       perfctr->si_signo = control.si_signo;
5827 +
5828 +       if( !perfctr_cstatus_has_tsc(next_cstatus) )
5829 +               perfctr->cpu_state.tsc_sum = 0;
5830 +
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;
5835 +
5836 +       if( tsk == current )
5837 +               vperfctr_resume(perfctr);
5838 +
5839 + out:
5840 +       preempt_enable();
5841 +       return err;
5842 +}
5843 +
5844 +static int sys_vperfctr_iresume(struct vperfctr *perfctr, const struct task_struct *tsk)
5845 +{
5846 +#if PERFCTR_INTERRUPT_SUPPORT
5847 +       unsigned int iresume_cstatus;
5848 +
5849 +       if( !tsk )
5850 +               return -ESRCH;  /* attempt to update unlinked perfctr */
5851 +
5852 +       iresume_cstatus = perfctr->iresume_cstatus;
5853 +       if( !perfctr_cstatus_has_ictrs(iresume_cstatus) )
5854 +               return -EPERM;
5855 +
5856 +       /* PREEMPT note: preemption is disabled over the entire
5857 +          region because we're updating an active perfctr. */
5858 +       preempt_disable();
5859 +
5860 +       if( IS_RUNNING(perfctr) && tsk == current )
5861 +               vperfctr_suspend(perfctr);
5862 +
5863 +       perfctr->cpu_state.cstatus = iresume_cstatus;
5864 +       perfctr->iresume_cstatus = 0;
5865 +
5866 +       /* remote access note: perfctr_cpu_ireload() is ok */
5867 +       perfctr_cpu_ireload(&perfctr->cpu_state);
5868 +
5869 +       if( tsk == current )
5870 +               vperfctr_resume(perfctr);
5871 +
5872 +       preempt_enable();
5873 +
5874 +       return 0;
5875 +#else
5876 +       return -ENOSYS;
5877 +#endif
5878 +}
5879 +
5880 +static int sys_vperfctr_unlink(struct vperfctr *perfctr, struct task_struct *tsk)
5881 +{
5882 +       if( tsk )
5883 +               vperfctr_unlink(tsk, perfctr);
5884 +       return 0;
5885 +}
5886 +
5887 +static int sys_vperfctr_read_sum(struct vperfctr *perfctr,
5888 +                                struct perfctr_struct_buf *argp,
5889 +                                const struct task_struct *tsk)
5890 +{
5891 +       struct perfctr_sum_ctrs sum;
5892 +
5893 +       if( tsk == current ) {
5894 +               preempt_disable();
5895 +               vperfctr_sample(perfctr);
5896 +       }
5897 +       //sum = perfctr->cpu_state.sum;
5898 +       {
5899 +               int j;
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;
5903 +       }
5904 +       if( tsk == current )
5905 +               preempt_enable();
5906 +       return perfctr_copy_to_user(argp, &sum, &perfctr_sum_ctrs_sdesc);
5907 +}
5908 +
5909 +static int sys_vperfctr_read_control(struct vperfctr *perfctr,
5910 +                                    struct perfctr_struct_buf *argp,
5911 +                                    const struct task_struct *tsk)
5912 +{
5913 +       struct vperfctr_control control;
5914 +
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 )
5925 +               preempt_enable();
5926 +       control.preserve = 0;
5927 +       return perfctr_copy_to_user(argp, &control, &vperfctr_control_sdesc);
5928 +}
5929 +
5930 +/****************************************************************
5931 + *                                                             *
5932 + * Virtual perfctr file operations.                            *
5933 + *                                                             *
5934 + ****************************************************************/
5935 +
5936 +static int vperfctr_mmap(struct file *filp, struct vm_area_struct *vma)
5937 +{
5938 +       struct vperfctr *perfctr;
5939 +
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)) )
5945 +               return -EPERM;
5946 +       perfctr = filp->private_data;
5947 +       if( !perfctr )
5948 +               return -EPERM;
5949 +       return remap_page_range(vma, vma->vm_start, virt_to_phys(perfctr),
5950 +                               PAGE_SIZE, vma->vm_page_prot);
5951 +}
5952 +
5953 +static int vperfctr_release(struct inode *inode, struct file *filp)
5954 +{
5955 +       struct vperfctr *perfctr = filp->private_data;
5956 +       filp->private_data = NULL;
5957 +       if( perfctr )
5958 +               put_vperfctr(perfctr);
5959 +       return 0;
5960 +}
5961 +
5962 +static int vperfctr_ioctl(struct inode *inode, struct file *filp,
5963 +                         unsigned int cmd, unsigned long arg)
5964 +{
5965 +       struct vperfctr *perfctr;
5966 +       struct task_struct *tsk;
5967 +       int ret;
5968 +
5969 +       switch( cmd ) {
5970 +       case PERFCTR_ABI:
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);
5978 +       }
5979 +       perfctr = filp->private_data;
5980 +       if( !perfctr )
5981 +               return -EINVAL;
5982 +       tsk = current;
5983 +       if( perfctr != current->thread.perfctr ) {
5984 +               /* this synchronises with vperfctr_unlink() and itself */
5985 +               spin_lock(&perfctr->owner_lock);
5986 +               tsk = perfctr->owner;
5987 +               if( tsk )
5988 +                       get_task_struct(tsk);
5989 +               spin_unlock(&perfctr->owner_lock);
5990 +               if( tsk ) {
5991 +                       ret = ptrace_check_attach(tsk, 0);
5992 +                       if( ret < 0 )
5993 +                               goto out;
5994 +               }
5995 +       }
5996 +       switch( cmd ) {
5997 +       case VPERFCTR_CONTROL:
5998 +               ret = sys_vperfctr_control(perfctr, (struct perfctr_struct_buf*)arg, tsk);
5999 +               break;
6000 +       case VPERFCTR_UNLINK:
6001 +               ret = sys_vperfctr_unlink(perfctr, tsk);
6002 +               break;
6003 +       case VPERFCTR_READ_SUM:
6004 +               ret = sys_vperfctr_read_sum(perfctr, (struct perfctr_struct_buf*)arg, tsk);
6005 +               break;
6006 +       case VPERFCTR_IRESUME:
6007 +               ret = sys_vperfctr_iresume(perfctr, tsk);
6008 +               break;
6009 +       case VPERFCTR_READ_CONTROL:
6010 +               ret = sys_vperfctr_read_control(perfctr, (struct perfctr_struct_buf*)arg, tsk);
6011 +               break;
6012 +       default:
6013 +               ret = -EINVAL;
6014 +       }
6015 + out:
6016 +       if( tsk && tsk != current )
6017 +               put_task_struct(tsk);
6018 +       return ret;
6019 +}
6020 +
6021 +static struct file_operations vperfctr_file_ops = {
6022 +       .owner = THIS_MODULE,
6023 +       .mmap = vperfctr_mmap,
6024 +       .release = vperfctr_release,
6025 +       .ioctl = vperfctr_ioctl,
6026 +};
6027 +
6028 +/****************************************************************
6029 + *                                                             *
6030 + * File system for virtual perfctrs. Based on pipefs.          *
6031 + *                                                             *
6032 + ****************************************************************/
6033 +
6034 +#define VPERFCTRFS_MAGIC (('V'<<24)|('P'<<16)|('M'<<8)|('C'))
6035 +
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 */
6040 +
6041 +/* 2.6 doesn't EXPORT_SYMBOL() fs/libfs.c:get_sb_pseudo().
6042 +   This is a verbatim copy, only renamed. */
6043 +#ifdef MODULE
6044 +static
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)
6048 +{
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)};
6054 +
6055 +       if (IS_ERR(s))
6056 +               return s;
6057 +
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);
6065 +       if (!root)
6066 +               goto Enomem;
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);
6071 +       if (!dentry) {
6072 +               iput(root);
6073 +               goto Enomem;
6074 +       }
6075 +       dentry->d_sb = s;
6076 +       dentry->d_parent = dentry;
6077 +       d_instantiate(dentry, root);
6078 +       s->s_root = dentry;
6079 +       s->s_flags |= MS_ACTIVE;
6080 +       return s;
6081 +
6082 +Enomem:
6083 +       up_write(&s->s_umount);
6084 +       deactivate_super(s);
6085 +       return ERR_PTR(-ENOMEM);
6086 +}
6087 +#undef get_sb_pseudo
6088 +#define get_sb_pseudo perfctr_get_sb_pseudo
6089 +#endif /* MODULE */
6090 +
6091 +static struct super_block *
6092 +vperfctrfs_get_sb(struct file_system_type *fs_type,
6093 +                 int flags, const char *dev_name, void *data)
6094 +{
6095 +       return get_sb_pseudo(fs_type, "vperfctr:", NULL, VPERFCTRFS_MAGIC);
6096 +}
6097 +
6098 +static struct file_system_type vperfctrfs_type = {
6099 +       .name           = "vperfctrfs",
6100 +       .get_sb         = vperfctrfs_get_sb,
6101 +       .kill_sb        = kill_anon_super,
6102 +};
6103 +
6104 +#else  /* 2.4 */
6105 +
6106 +static int vperfctrfs_statfs(struct super_block *sb, struct statfs *buf)
6107 +{
6108 +       buf->f_type = VPERFCTRFS_MAGIC;
6109 +       buf->f_bsize = 1024;
6110 +       buf->f_namelen = 255;
6111 +       return 0;
6112 +}
6113 +
6114 +static struct super_operations vperfctrfs_ops = {
6115 +       .statfs = vperfctrfs_statfs,
6116 +};
6117 +
6118 +static struct super_block*
6119 +vperfctrfs_read_super(struct super_block *sb, void *data, int silent)
6120 +{
6121 +       static const struct qstr d_name = { "vperfctrfs:", 11, 0 };
6122 +       struct dentry *dentry;
6123 +       struct inode *root;
6124 +
6125 +       root = new_inode(sb);
6126 +       if( !root )
6127 +               return NULL;
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);
6136 +       if( !dentry ) {
6137 +               iput(root);
6138 +               return NULL;
6139 +       }
6140 +       dentry->d_sb = sb;
6141 +       dentry->d_parent = dentry;
6142 +       d_instantiate(dentry, root);
6143 +       return sb;
6144 +}
6145 +
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,
6154 +};
6155 +
6156 +#endif /* 2.4 */
6157 +
6158 +/* XXX: check if s/vperfctr_mnt/vperfctrfs_type.kern_mnt/ would work */
6159 +static struct vfsmount *vperfctr_mnt;
6160 +
6161 +static int __init vperfctrfs_init(void)
6162 +{
6163 +       int err = register_filesystem(&vperfctrfs_type);
6164 +       if( !err ) {
6165 +               vperfctr_mnt = kern_mount(&vperfctrfs_type);
6166 +               if( !IS_ERR(vperfctr_mnt) )
6167 +                       return 0;
6168 +               err = PTR_ERR(vperfctr_mnt);
6169 +               unregister_filesystem(&vperfctrfs_type);
6170 +       }
6171 +       return err;
6172 +}
6173 +
6174 +static void __exit vperfctrfs_exit(void)
6175 +{
6176 +       unregister_filesystem(&vperfctrfs_type);
6177 +       mntput(vperfctr_mnt);
6178 +}
6179 +
6180 +static struct inode *vperfctr_get_inode(void)
6181 +{
6182 +       struct inode *inode;
6183 +
6184 +       inode = new_inode(vperfctr_mnt->mnt_sb);
6185 +       if( !inode )
6186 +               return NULL;
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;
6194 +       return inode;
6195 +}
6196 +
6197 +static int vperfctrfs_delete_dentry(struct dentry *dentry)
6198 +{
6199 +       return 1;
6200 +}
6201 +
6202 +static struct dentry_operations vperfctrfs_dentry_operations = {
6203 +       .d_delete       = vperfctrfs_delete_dentry,
6204 +};
6205 +
6206 +static struct dentry *vperfctr_d_alloc_root(struct inode *inode)
6207 +{
6208 +       struct qstr this;
6209 +       char name[32];
6210 +       struct dentry *dentry;
6211 +
6212 +       sprintf(name, "[%lu]", inode->i_ino);
6213 +       this.name = name;
6214 +       this.len = strlen(name);
6215 +       this.hash = inode->i_ino; /* will go */
6216 +       dentry = d_alloc(vperfctr_mnt->mnt_sb->s_root, &this);
6217 +       if( dentry ) {
6218 +               dentry->d_op = &vperfctrfs_dentry_operations;
6219 +               d_add(dentry, inode);
6220 +       }
6221 +       return dentry;
6222 +}
6223 +
6224 +static struct file *vperfctr_get_filp(void)
6225 +{
6226 +       struct file *filp;
6227 +       struct inode *inode;
6228 +       struct dentry *dentry;
6229 +
6230 +       filp = get_empty_filp();
6231 +       if( !filp )
6232 +               goto out;
6233 +       inode = vperfctr_get_inode();
6234 +       if( !inode )
6235 +               goto out_filp;
6236 +       dentry = vperfctr_d_alloc_root(inode);
6237 +       if( !dentry )
6238 +               goto out_inode;
6239 +
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;
6244 +#endif
6245 +
6246 +       filp->f_pos = 0;
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;
6251 +
6252 +       return filp;
6253 +
6254 + out_inode:
6255 +       iput(inode);
6256 + out_filp:
6257 +       put_filp(filp); /* doesn't run ->release() like fput() does */
6258 + out:
6259 +       return NULL;
6260 +}
6261 +
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)
6265 +{
6266 +       struct file *filp;
6267 +       struct task_struct *tsk;
6268 +       struct vperfctr *perfctr;
6269 +       int err;
6270 +       int fd;
6271 +
6272 +       filp = vperfctr_get_filp();
6273 +       if( !filp )
6274 +               return -ENOMEM;
6275 +       err = fd = get_unused_fd();
6276 +       if( err < 0 )
6277 +               goto err_filp;
6278 +       perfctr = NULL;
6279 +       if( creat ) {
6280 +               perfctr = get_empty_vperfctr(); /* may sleep */
6281 +               if( IS_ERR(perfctr) ) {
6282 +                       err = PTR_ERR(perfctr);
6283 +                       goto err_fd;
6284 +               }
6285 +       }
6286 +       tsk = current;
6287 +       if( tid != 0 && tid != tsk->pid ) { /* remote? */
6288 +               read_lock(&tasklist_lock);
6289 +               tsk = find_task_by_pid(tid);
6290 +               if( tsk )
6291 +                       get_task_struct(tsk);
6292 +               read_unlock(&tasklist_lock);
6293 +               err = -ESRCH;
6294 +               if( !tsk )
6295 +                       goto err_perfctr;
6296 +               err = ptrace_check_attach(tsk, 0);
6297 +               if( err < 0 )
6298 +                       goto err_tsk;
6299 +       }
6300 +       if( creat ) {
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;
6306 +                       err = 0;
6307 +               } else
6308 +                       err = -EEXIST;
6309 +               vperfctr_task_unlock(tsk);
6310 +               if( err )
6311 +                       goto err_tsk;
6312 +       } else {
6313 +               perfctr = tsk->thread.perfctr;
6314 +               /* PERFCTR_ABI and PERFCTR_INFO don't need the perfctr.
6315 +                  Hence no non-NULL check here. */
6316 +       }
6317 +       filp->private_data = perfctr;
6318 +       if( perfctr )
6319 +               atomic_inc(&perfctr->count);
6320 +       if( tsk != current )
6321 +               put_task_struct(tsk);
6322 +       fd_install(fd, filp);
6323 +       return fd;
6324 + err_tsk:
6325 +       if( tsk != current )
6326 +               put_task_struct(tsk);
6327 + err_perfctr:
6328 +       if( perfctr )   /* can only occur if creat != 0 */
6329 +               put_vperfctr(perfctr);
6330 + err_fd:
6331 +       put_unused_fd(fd);
6332 + err_filp:
6333 +       fput(filp);
6334 +       return err;
6335 +}
6336 +
6337 +/****************************************************************
6338 + *                                                             *
6339 + * module_init/exit                                            *
6340 + *                                                             *
6341 + ****************************************************************/
6342 +
6343 +#ifdef MODULE
6344 +static struct vperfctr_stub off;
6345 +
6346 +static void vperfctr_stub_init(void)
6347 +{
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;
6356 +#endif
6357 +}
6358 +
6359 +static void vperfctr_stub_exit(void)
6360 +{
6361 +       vperfctr_stub = off;
6362 +}
6363 +#else
6364 +static inline void vperfctr_stub_init(void) { }
6365 +static inline void vperfctr_stub_exit(void) { }
6366 +#endif /* MODULE */
6367 +
6368 +int __init vperfctr_init(void)
6369 +{
6370 +       int err = vperfctrfs_init();
6371 +       if( err )
6372 +               return err;
6373 +       vperfctr_stub_init();
6374 +       return 0;
6375 +}
6376 +
6377 +void __exit vperfctr_exit(void)
6378 +{
6379 +       vperfctrfs_exit();
6380 +       vperfctr_stub_exit();
6381 +}
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
6386 @@ -0,0 +1,30 @@
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.
6390 + *
6391 + * Copyright (C) 1999-2004  Mikael Pettersson
6392 + */
6393 +
6394 +/* 'enum perfctr_x86_tests_type' classifies CPUs according
6395 +   to relevance for perfctr_x86_init_tests(). */
6396 +enum perfctr_x86_tests_type {
6397 +       PTT_UNKNOWN,
6398 +       PTT_GENERIC,
6399 +       PTT_P5,
6400 +       PTT_P6,
6401 +       PTT_P4,
6402 +       PTT_AMD,
6403 +       PTT_WINCHIP,
6404 +       PTT_VC3,
6405 +};
6406 +
6407 +extern enum perfctr_x86_tests_type perfctr_x86_tests_type;
6408 +
6409 +static inline void perfctr_set_tests_type(enum perfctr_x86_tests_type t)
6410 +{
6411 +#ifdef CONFIG_PERFCTR_INIT_TESTS
6412 +       perfctr_x86_tests_type = t;
6413 +#endif
6414 +}
6415 +
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
6421 @@ -0,0 +1,40 @@
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.
6425 + *
6426 + * Copyright (C) 2004  Mikael Pettersson
6427 + */
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"
6438 +
6439 +#if PERFCTR_INTERRUPT_SUPPORT
6440 +static void perfctr_default_ihandler(unsigned long pc)
6441 +{
6442 +}
6443 +
6444 +static perfctr_ihandler_t perfctr_ihandler = perfctr_default_ihandler;
6445 +
6446 +void do_perfctr_interrupt(struct pt_regs *regs)
6447 +{
6448 +       preempt_disable();
6449 +       (*perfctr_ihandler)(regs->nip);
6450 +       preempt_enable_no_resched();
6451 +}
6452 +
6453 +void perfctr_cpu_set_ihandler(perfctr_ihandler_t ihandler)
6454 +{
6455 +       perfctr_ihandler = ihandler ? ihandler : perfctr_default_ihandler;
6456 +}
6457 +
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
6466 @@ -0,0 +1,12 @@
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.
6470 + *
6471 + * Copyright (C) 2004  Mikael Pettersson
6472 + */
6473 +
6474 +#ifdef CONFIG_PERFCTR_INIT_TESTS
6475 +extern void perfctr_ppc_init_tests(int have_mmcr1);
6476 +#else
6477 +static inline void perfctr_ppc_init_tests(int have_mmcr1) { }
6478 +#endif
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
6483 @@ -0,0 +1 @@
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
6489 @@ -0,0 +1,174 @@
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.
6493 + *
6494 + * Copyright (C) 2003-2004  Mikael Pettersson
6495 + */
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"
6508 +
6509 +#define MSR_K8_EVNTSEL0                0xC0010000
6510 +#define MSR_K8_PERFCTR0                0xC0010004
6511 +#define K8_EVNTSEL0_VAL                (0xC0 | (3<<16) | (1<<22))
6512 +
6513 +#define NITER  64
6514 +#define X2(S)  S";"S
6515 +#define X8(S)  X2(X2(X2(S)))
6516 +
6517 +static void __init do_rdpmc(unsigned pmc, unsigned unused2)
6518 +{
6519 +       unsigned i;
6520 +       for(i = 0; i < NITER/8; ++i)
6521 +               __asm__ __volatile__(X8("rdpmc") : : "c"(pmc) : "eax", "edx");
6522 +}
6523 +
6524 +static void __init do_rdmsr(unsigned msr, unsigned unused2)
6525 +{
6526 +       unsigned i;
6527 +       for(i = 0; i < NITER/8; ++i)
6528 +               __asm__ __volatile__(X8("rdmsr") : : "c"(msr) : "eax", "edx");
6529 +}
6530 +
6531 +static void __init do_wrmsr(unsigned msr, unsigned data)
6532 +{
6533 +       unsigned i;
6534 +       for(i = 0; i < NITER/8; ++i)
6535 +               __asm__ __volatile__(X8("wrmsr") : : "c"(msr), "a"(data), "d"(0));
6536 +}
6537 +
6538 +static void __init do_rdcr4(unsigned unused1, unsigned unused2)
6539 +{
6540 +       unsigned i;
6541 +       unsigned long dummy;
6542 +       for(i = 0; i < NITER/8; ++i)
6543 +               __asm__ __volatile__(X8("movq %%cr4,%0") : "=r"(dummy));
6544 +}
6545 +
6546 +static void __init do_wrcr4(unsigned cr4, unsigned unused2)
6547 +{
6548 +       unsigned i;
6549 +       for(i = 0; i < NITER/8; ++i)
6550 +               __asm__ __volatile__(X8("movq %0,%%cr4") : : "r"((long)cr4));
6551 +}
6552 +
6553 +static void __init do_rdtsc(unsigned unused1, unsigned unused2)
6554 +{
6555 +       unsigned i;
6556 +       for(i = 0; i < NITER/8; ++i)
6557 +               __asm__ __volatile__(X8("rdtsc") : : : "eax", "edx");
6558 +}
6559 +
6560 +static void __init do_wrlvtpc(unsigned val, unsigned unused2)
6561 +{
6562 +       unsigned i;
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);
6572 +       }
6573 +}
6574 +
6575 +static void __init do_empty_loop(unsigned unused1, unsigned unused2)
6576 +{
6577 +       unsigned i;
6578 +       for(i = 0; i < NITER/8; ++i)
6579 +               __asm__ __volatile__("" : : "c"(0));
6580 +}
6581 +
6582 +static unsigned __init run(void (*doit)(unsigned, unsigned),
6583 +                          unsigned arg1, unsigned arg2)
6584 +{
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;
6590 +}
6591 +
6592 +static void __init init_tests_message(void)
6593 +{
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());
6604 +}
6605 +
6606 +static void __init
6607 +measure_overheads(unsigned msr_evntsel0, unsigned evntsel0, unsigned msr_perfctr0)
6608 +{
6609 +       int i;
6610 +       unsigned int loop, ticks[9];
6611 +       const char *name[9];
6612 +
6613 +       if( msr_evntsel0 )
6614 +               wrmsr(msr_evntsel0, 0, 0);
6615 +
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;
6636 +
6637 +       loop = run(do_empty_loop, 0, 0);
6638 +
6639 +       if( msr_evntsel0 )
6640 +               wrmsr(msr_evntsel0, 0, 0);
6641 +
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) {
6646 +               unsigned int x;
6647 +               if( !ticks[i] )
6648 +                       continue;
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]);
6652 +       }
6653 +}
6654 +
6655 +void __init perfctr_k8_init_tests(void)
6656 +{
6657 +       measure_overheads(MSR_K8_EVNTSEL0, K8_EVNTSEL0_VAL, MSR_K8_PERFCTR0);
6658 +}
6659 +
6660 +void __init perfctr_generic_init_tests(void)
6661 +{
6662 +       measure_overheads(0, 0, 0);
6663 +}
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
6668 @@ -0,0 +1,63 @@
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.
6672 + *
6673 + * Copyright (C) 2003-2004  Mikael Pettersson
6674 + */
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"
6687 +
6688 +static void perfctr_default_ihandler(unsigned long pc)
6689 +{
6690 +}
6691 +
6692 +static perfctr_ihandler_t perfctr_ihandler = perfctr_default_ihandler;
6693 +
6694 +asmlinkage void smp_perfctr_interrupt(struct pt_regs *regs)
6695 +{
6696 +       /* PREEMPT note: invoked via an interrupt gate, which
6697 +          masks interrupts. We're still on the originating CPU. */
6698 +       ack_APIC_irq();
6699 +       irq_enter();
6700 +       (*perfctr_ihandler)(regs->rip);
6701 +       irq_exit();
6702 +}
6703 +
6704 +void perfctr_cpu_set_ihandler(perfctr_ihandler_t ihandler)
6705 +{
6706 +       perfctr_ihandler = ihandler ? ihandler : perfctr_default_ihandler;
6707 +}
6708 +
6709 +extern unsigned int cpu_khz;
6710 +
6711 +/* Wrapper to avoid namespace clash in RedHat 8.0's 2.4.18-14 kernel. */
6712 +unsigned int perfctr_cpu_khz(void)
6713 +{
6714 +       return cpu_khz;
6715 +}
6716 +
6717 +#ifdef CONFIG_PERFCTR_MODULE
6718 +EXPORT_SYMBOL_mmu_cr4_features;
6719 +EXPORT_SYMBOL(perfctr_cpu_khz);
6720 +
6721 +EXPORT_SYMBOL(nmi_perfctr_msr);
6722 +
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);
6727 +#endif
6728 +
6729 +EXPORT_SYMBOL(perfctr_cpu_set_ihandler);
6730 +
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
6736 @@ -0,0 +1,776 @@
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.
6739 + *
6740 + * Copyright (C) 2003-2004  Mikael Pettersson
6741 + */
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>
6749 +
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>
6755 +
6756 +#include "compat.h"
6757 +#include "x86_compat.h"
6758 +#include "x86_tests.h"
6759 +
6760 +/* Support for lazy evntsel and perfctr MSR updates. */
6761 +struct per_cpu_cache { /* roughly a subset of perfctr_cpu_state */
6762 +       union {
6763 +               unsigned int id;        /* cache owner id */
6764 +       } k1;
6765 +       struct {
6766 +               /* NOTE: these caches have physical indices, not virtual */
6767 +               unsigned int evntsel[4];
6768 +       } control;
6769 +} ____cacheline_aligned;
6770 +static struct per_cpu_cache per_cpu_cache[NR_CPUS] __cacheline_aligned;
6771 +
6772 +/* Structure for counter snapshots, as 32-bit values. */
6773 +struct perfctr_low_ctrs {
6774 +       unsigned int tsc;
6775 +       unsigned int pmc[4];
6776 +};
6777 +
6778 +/* AMD K8 */
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
6785 +
6786 +#define rdpmc_low(ctr,low) \
6787 +       __asm__ __volatile__("rdpmc" : "=a"(low) : "c"(ctr) : "edx")
6788 +
6789 +static void clear_msr_range(unsigned int base, unsigned int n)
6790 +{
6791 +       unsigned int i;
6792 +
6793 +       for(i = 0; i < n; ++i)
6794 +               wrmsr(base+i, 0, 0);
6795 +}
6796 +
6797 +static inline void set_in_cr4_local(unsigned int mask)
6798 +{
6799 +       write_cr4(read_cr4() | mask);
6800 +}
6801 +
6802 +static inline void clear_in_cr4_local(unsigned int mask)
6803 +{
6804 +       write_cr4(read_cr4() & ~mask);
6805 +}
6806 +
6807 +static unsigned int new_id(void)
6808 +{
6809 +       static spinlock_t lock = SPIN_LOCK_UNLOCKED;
6810 +       static unsigned int counter;
6811 +       int id;
6812 +
6813 +       spin_lock(&lock);
6814 +       id = ++counter;
6815 +       spin_unlock(&lock);
6816 +       return id;
6817 +}
6818 +
6819 +#if defined(CONFIG_SMP)
6820 +
6821 +static inline void set_isuspend_cpu(struct perfctr_cpu_state *state,
6822 +                                   int cpu)
6823 +{
6824 +       state->k1.isuspend_cpu = cpu;
6825 +}
6826 +
6827 +static inline int is_isuspend_cpu(const struct perfctr_cpu_state *state,
6828 +                                 int cpu)
6829 +{
6830 +       return state->k1.isuspend_cpu == cpu;
6831 +}
6832 +
6833 +static inline void clear_isuspend_cpu(struct perfctr_cpu_state *state)
6834 +{
6835 +       state->k1.isuspend_cpu = NR_CPUS;
6836 +}
6837 +
6838 +#else
6839 +static inline void set_isuspend_cpu(struct perfctr_cpu_state *state,
6840 +                                   int cpu) { }
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) { }
6844 +#endif
6845 +
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)
6850 +{
6851 +       unsigned int nrctrs, i;
6852 +
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);
6862 +                       return;
6863 +               }
6864 +       }
6865 +}
6866 +#else
6867 +static inline void debug_evntsel_cache(const struct perfctr_cpu_state *s,
6868 +                                      const struct per_cpu_cache *c)
6869 +{ }
6870 +#endif
6871 +
6872 +/****************************************************************
6873 + *                                                             *
6874 + * Driver procedures.                                          *
6875 + *                                                             *
6876 + ****************************************************************/
6877 +
6878 +static void perfctr_cpu_read_counters(const struct perfctr_cpu_state *state,
6879 +                                     struct perfctr_low_ctrs *ctrs)
6880 +{
6881 +       unsigned int cstatus, nrctrs, i;
6882 +
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]);
6890 +       }
6891 +}
6892 +
6893 +static int k8_check_control(struct perfctr_cpu_state *state)
6894 +{
6895 +       unsigned int evntsel, i, nractrs, nrctrs, pmc_mask, pmc;
6896 +
6897 +       nractrs = state->control.nractrs;
6898 +       nrctrs = nractrs + state->control.nrictrs;
6899 +       if( nrctrs < nractrs || nrctrs > 4 )
6900 +               return -EINVAL;
6901 +
6902 +       pmc_mask = 0;
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)) )
6907 +                       return -EINVAL;
6908 +               pmc_mask |= (1<<pmc);
6909 +               evntsel = state->control.evntsel[i];
6910 +               /* protect reserved bits */
6911 +               if( evntsel & K8_EVNTSEL_RESERVED )
6912 +                       return -EPERM;
6913 +               /* ENable bit must be set in each evntsel */
6914 +               if( !(evntsel & K8_EVNTSEL_ENABLE) )
6915 +                       return -EINVAL;
6916 +               /* the CPL field must be non-zero */
6917 +               if( !(evntsel & K8_EVNTSEL_CPL) )
6918 +                       return -EINVAL;
6919 +               /* INT bit must be off for a-mode and on for i-mode counters */
6920 +               if( evntsel & K8_EVNTSEL_INT ) {
6921 +                       if( i < nractrs )
6922 +                               return -EINVAL;
6923 +               } else {
6924 +                       if( i >= nractrs )
6925 +                               return -EINVAL;
6926 +               }
6927 +       }
6928 +       state->k1.id = new_id();
6929 +       return 0;
6930 +}
6931 +
6932 +static void perfctr_cpu_isuspend(struct perfctr_cpu_state *state)
6933 +{
6934 +       struct per_cpu_cache *cache;
6935 +       unsigned int cstatus, nrctrs, i;
6936 +       int cpu;
6937 +
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;
6950 +       }
6951 +       /* cache->k1.id is still == state->k1.id */
6952 +       set_isuspend_cpu(state, cpu);
6953 +}
6954 +
6955 +static void perfctr_cpu_iresume(const struct perfctr_cpu_state *state)
6956 +{
6957 +       struct per_cpu_cache *cache;
6958 +       unsigned int cstatus, nrctrs, i;
6959 +       int cpu;
6960 +
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 */
6967 +       }
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);
6978 +               }
6979 +               wrmsr(MSR_K8_PERFCTR0+pmc, state->pmc[i].start, -1);
6980 +       }
6981 +       /* cache->k1.id remains != state->k1.id */
6982 +}
6983 +
6984 +static void perfctr_cpu_write_control(const struct perfctr_cpu_state *state)
6985 +{
6986 +       struct per_cpu_cache *cache;
6987 +       unsigned int nrctrs, i;
6988 +
6989 +       cache = &per_cpu_cache[smp_processor_id()];
6990 +       if( cache->k1.id == state->k1.id ) {
6991 +               debug_evntsel_cache(state, cache);
6992 +               return;
6993 +       }
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);
7001 +               }
7002 +       }
7003 +       cache->k1.id = state->k1.id;
7004 +}
7005 +
7006 +static void k8_clear_counters(void)
7007 +{
7008 +       clear_msr_range(MSR_K8_EVNTSEL0, 4+4);
7009 +}
7010 +
7011 +/*
7012 + * Generic driver for any x86-64 with a working TSC.
7013 + * (Mainly for testing with Screwdriver.)
7014 + */
7015 +
7016 +static int generic_check_control(struct perfctr_cpu_state *state)
7017 +{
7018 +       if( state->control.nractrs || state->control.nrictrs )
7019 +               return -EINVAL;
7020 +       return 0;
7021 +}
7022 +
7023 +static void generic_clear_counters(void)
7024 +{
7025 +}
7026 +
7027 +/*
7028 + * Driver methods, internal and exported.
7029 + */
7030 +
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)
7034 +{
7035 +#ifdef CONFIG_SMP
7036 +       clear_isuspend_cpu(state);
7037 +#else
7038 +       per_cpu_cache[smp_processor_id()].k1.id = 0;
7039 +#endif
7040 +}
7041 +
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)
7044 +{
7045 +       unsigned int cstatus, nrctrs, pmc, pmc_mask;
7046 +
7047 +       cstatus = state->cstatus;
7048 +       pmc = perfctr_cstatus_nractrs(cstatus);
7049 +       nrctrs = perfctr_cstatus_nrctrs(cstatus);
7050 +
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);
7056 +               }
7057 +       }
7058 +       return pmc_mask;
7059 +}
7060 +
7061 +static inline int check_ireset(const struct perfctr_cpu_state *state)
7062 +{
7063 +       unsigned int nrctrs, i;
7064 +
7065 +       i = state->control.nractrs;
7066 +       nrctrs = i + state->control.nrictrs;
7067 +       for(; i < nrctrs; ++i)
7068 +               if( state->control.ireset[i] >= 0 )
7069 +                       return -EINVAL;
7070 +       return 0;
7071 +}
7072 +
7073 +static inline void setup_imode_start_values(struct perfctr_cpu_state *state)
7074 +{
7075 +       unsigned int cstatus, nrctrs, i;
7076 +
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];
7081 +}
7082 +
7083 +static inline void debug_no_imode(const struct perfctr_cpu_state *state)
7084 +{
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);
7092 +#endif
7093 +}
7094 +
7095 +static int (*check_control)(struct perfctr_cpu_state*);
7096 +int perfctr_cpu_update_control(struct perfctr_cpu_state *state, int is_global)
7097 +{
7098 +       int err;
7099 +
7100 +       debug_no_imode(state);
7101 +       clear_isuspend_cpu(state);
7102 +       state->cstatus = 0;
7103 +
7104 +       /* disallow i-mode counters if we cannot catch the interrupts */
7105 +       if( !(perfctr_info.cpu_features & PERFCTR_FEATURE_PCINT)
7106 +           && state->control.nrictrs )
7107 +               return -EPERM;
7108 +
7109 +       err = check_control(state);
7110 +       if( err < 0 )
7111 +               return err;
7112 +       err = check_ireset(state);
7113 +       if( err < 0 )
7114 +               return err;
7115 +       state->cstatus = perfctr_mk_cstatus(state->control.tsc_on,
7116 +                                           state->control.nractrs,
7117 +                                           state->control.nrictrs);
7118 +       setup_imode_start_values(state);
7119 +       return 0;
7120 +}
7121 +
7122 +void perfctr_cpu_suspend(struct perfctr_cpu_state *state)
7123 +{
7124 +       unsigned int i, cstatus, nractrs;
7125 +       struct perfctr_low_ctrs now;
7126 +
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;
7136 +}
7137 +
7138 +void perfctr_cpu_resume(struct perfctr_cpu_state *state)
7139 +{
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);
7144 +       {
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];
7154 +       }
7155 +       /* XXX: if (SMP && start.tsc == now.tsc) ++now.tsc; */
7156 +}
7157 +
7158 +void perfctr_cpu_sample(struct perfctr_cpu_state *state)
7159 +{
7160 +       unsigned int i, cstatus, nractrs;
7161 +       struct perfctr_low_ctrs now;
7162 +
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;
7168 +       }
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];
7173 +       }
7174 +}
7175 +
7176 +static void (*clear_counters)(void);
7177 +static void perfctr_cpu_clear_counters(void)
7178 +{
7179 +       return clear_counters();
7180 +}
7181 +
7182 +/****************************************************************
7183 + *                                                             *
7184 + * Processor detection and initialisation procedures.          *
7185 + *                                                             *
7186 + ****************************************************************/
7187 +
7188 +static int __init amd_init(void)
7189 +{
7190 +       static char k8_name[] __initdata = "AMD K8";
7191 +       static char k8c_name[] __initdata = "AMD K8C";
7192 +
7193 +       if( !cpu_has_tsc )
7194 +               return -ENODEV;
7195 +       if( boot_cpu_data.x86 != 15 )
7196 +               return -ENODEV;
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;
7201 +       } else {
7202 +               perfctr_info.cpu_type = PERFCTR_X86_AMD_K8;
7203 +               perfctr_cpu_name = k8_name;
7204 +       }
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;
7209 +       return 0;
7210 +}
7211 +
7212 +/* For testing on Screwdriver. */
7213 +static int __init generic_init(void)
7214 +{
7215 +       static char generic_name[] __initdata = "Generic x86-64 with TSC";
7216 +       if( !cpu_has_tsc )
7217 +               return -ENODEV;
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;
7223 +       return 0;
7224 +}
7225 +
7226 +static void perfctr_cpu_init_one(void *ignore)
7227 +{
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);
7235 +}
7236 +
7237 +static void perfctr_cpu_exit_one(void *ignore)
7238 +{
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);
7246 +}
7247 +
7248 +#if defined(CONFIG_PM)
7249 +
7250 +static void perfctr_pm_suspend(void)
7251 +{
7252 +       /* XXX: clear control registers */
7253 +       printk("perfctr: PM suspend\n");
7254 +}
7255 +
7256 +static void perfctr_pm_resume(void)
7257 +{
7258 +       /* XXX: reload control registers */
7259 +       printk("perfctr: PM resume\n");
7260 +}
7261 +
7262 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,71)
7263 +
7264 +#include <linux/sysdev.h>
7265 +
7266 +static int perfctr_device_suspend(struct sys_device *dev, u32 state)
7267 +{
7268 +       perfctr_pm_suspend();
7269 +       return 0;
7270 +}
7271 +
7272 +static int perfctr_device_resume(struct sys_device *dev)
7273 +{
7274 +       perfctr_pm_resume();
7275 +       return 0;
7276 +}
7277 +
7278 +static struct sysdev_class perfctr_sysclass = {
7279 +       set_kset_name("perfctr"),
7280 +       .resume         = perfctr_device_resume,
7281 +       .suspend        = perfctr_device_suspend,
7282 +};
7283 +
7284 +static struct sys_device device_perfctr = {
7285 +       .id     = 0,
7286 +       .cls    = &perfctr_sysclass,
7287 +};
7288 +
7289 +static void x86_pm_init(void)
7290 +{
7291 +       if( sysdev_class_register(&perfctr_sysclass) == 0 )
7292 +               sysdev_register(&device_perfctr);
7293 +}
7294 +
7295 +static void x86_pm_exit(void)
7296 +{
7297 +       sysdev_unregister(&device_perfctr);
7298 +       sysdev_class_unregister(&perfctr_sysclass);
7299 +}
7300 +
7301 +#else  /* 2.4 kernel */
7302 +
7303 +static int x86_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
7304 +{
7305 +       switch( rqst ) {
7306 +       case PM_SUSPEND:
7307 +               perfctr_pm_suspend();
7308 +               break;
7309 +       case PM_RESUME:
7310 +               perfctr_pm_resume();
7311 +               break;
7312 +       }
7313 +       return 0;
7314 +}
7315 +
7316 +static struct pm_dev *x86_pmdev;
7317 +
7318 +static void x86_pm_init(void)
7319 +{
7320 +       x86_pmdev = apic_pm_register(PM_SYS_DEV, 0, x86_pm_callback);
7321 +}
7322 +
7323 +static void x86_pm_exit(void)
7324 +{
7325 +       if( x86_pmdev ) {
7326 +               apic_pm_unregister(x86_pmdev);
7327 +               x86_pmdev = NULL;
7328 +       }
7329 +}
7330 +
7331 +#endif /* 2.4 kernel */
7332 +
7333 +#else
7334 +
7335 +static inline void x86_pm_init(void) { }
7336 +static inline void x86_pm_exit(void) { }
7337 +
7338 +#endif /* CONFIG_PM */
7339 +
7340 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,71)
7341 +static void disable_lapic_nmi_watchdog(void)
7342 +{
7343 +#ifdef CONFIG_PM
7344 +       if( nmi_pmdev ) {
7345 +               apic_pm_unregister(nmi_pmdev);
7346 +               nmi_pmdev = 0;
7347 +       }
7348 +#endif
7349 +}
7350 +#endif
7351 +
7352 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6)
7353 +static int reserve_lapic_nmi(void)
7354 +{
7355 +       int ret = 0;
7356 +       if( nmi_perfctr_msr ) {
7357 +               nmi_perfctr_msr = 0;
7358 +               disable_lapic_nmi_watchdog();
7359 +               ret = 1;
7360 +       }
7361 +       return ret;
7362 +}
7363 +
7364 +static inline void release_lapic_nmi(void) { }
7365 +#endif
7366 +
7367 +static void do_init_tests(void)
7368 +{
7369 +#ifdef CONFIG_PERFCTR_INIT_TESTS
7370 +       if( reserve_lapic_nmi() >= 0 ) {
7371 +               perfctr_x86_init_tests();
7372 +               release_lapic_nmi();
7373 +       }
7374 +#endif
7375 +}
7376 +
7377 +static void invalidate_per_cpu_cache(void)
7378 +{
7379 +       /*
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.
7387 +        */
7388 +       memset(per_cpu_cache, ~0, sizeof per_cpu_cache);
7389 +}
7390 +
7391 +int __init perfctr_cpu_init(void)
7392 +{
7393 +       int err = -ENODEV;
7394 +
7395 +       preempt_disable();
7396 +
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;
7400 +
7401 +       switch( boot_cpu_data.x86_vendor ) {
7402 +       case X86_VENDOR_AMD:
7403 +               err = amd_init();
7404 +               break;
7405 +       }
7406 +       if( err ) {
7407 +               err = generic_init();   /* last resort */
7408 +               if( err )
7409 +                       goto out;
7410 +       }
7411 +       do_init_tests();
7412 +#if 0
7413 +       /*
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
7419 +        */
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);
7425 +       /*
7426 +        * Fix up the connection to the local APIC:
7427 +        * - disable and disconnect the NMI watchdog
7428 +        * - register our PM callback
7429 +        */
7430 +       disable_nmi_watchdog();
7431 +       x86_pm_init();
7432 +#endif
7433 +
7434 +       invalidate_per_cpu_cache();
7435 +
7436 +       perfctr_info.cpu_khz = perfctr_cpu_khz();
7437 +       perfctr_info.tsc_to_cpu_mult = 1;
7438 +
7439 + out:
7440 +       preempt_enable();
7441 +       return err;
7442 +}
7443 +
7444 +void __exit perfctr_cpu_exit(void)
7445 +{
7446 +#if 0
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);
7453 +       x86_pm_exit();
7454 +       /* XXX: restart nmi watchdog? */
7455 +       preempt_enable();
7456 +#endif
7457 +}
7458 +
7459 +/****************************************************************
7460 + *                                                             *
7461 + * Hardware reservation.                                       *
7462 + *                                                             *
7463 + ****************************************************************/
7464 +
7465 +static DECLARE_MUTEX(mutex);
7466 +static const char *current_service = 0;
7467 +
7468 +const char *perfctr_cpu_reserve(const char *service)
7469 +{
7470 +       const char *ret;
7471 +
7472 +       down(&mutex);
7473 +       ret = current_service;
7474 +       if( ret )
7475 +               goto out_up;
7476 +       ret = "unknown driver (oprofile?)";
7477 +       if( reserve_lapic_nmi() < 0 )
7478 +               goto out_up;
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);
7485 +       x86_pm_init();
7486 +       ret = NULL;
7487 + out_up:
7488 +       up(&mutex);
7489 +       return ret;
7490 +}
7491 +
7492 +void perfctr_cpu_release(const char *service)
7493 +{
7494 +       down(&mutex);
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);
7498 +               goto out_up;
7499 +       }
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);
7506 +       x86_pm_exit();
7507 +       current_service = 0;
7508 +       release_lapic_nmi();
7509 +       module_put(THIS_MODULE);
7510 + out_up:
7511 +       up(&mutex);
7512 +}
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
7517 @@ -0,0 +1,1720 @@
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.
7520 + *
7521 + * Copyright (C) 1999-2004  Mikael Pettersson
7522 + */
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>
7530 +
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>
7538 +
7539 +#include "compat.h"
7540 +#include "x86_compat.h"
7541 +#include "x86_tests.h"
7542 +
7543 +/* Support for lazy evntsel and perfctr MSR updates. */
7544 +struct per_cpu_cache { /* roughly a subset of perfctr_cpu_state */
7545 +       union {
7546 +               unsigned int p5_cesr;
7547 +               unsigned int id;        /* cache owner id */
7548 +       } k1;
7549 +       struct {
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;
7555 +       } control;
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())
7560 +
7561 +/* Structure for counter snapshots, as 32-bit values. */
7562 +struct perfctr_low_ctrs {
7563 +       unsigned int tsc;
7564 +       unsigned int pmc[18];
7565 +};
7566 +
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)
7574 +
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)
7583 +
7584 +/* AMD K7 */
7585 +#define MSR_K7_EVNTSEL0                0xC0010000      /* .. 0xC0010003 */
7586 +#define MSR_K7_PERFCTR0                0xC0010004      /* .. 0xC0010007 */
7587 +
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 */
7592 +
7593 +/* Intel P4 */
7594 +#define MSR_P4_PERFCTR0                0x300           /* .. 0x311 */
7595 +#define MSR_P4_CCCR0           0x360           /* .. 0x371 */
7596 +#define MSR_P4_ESCR0           0x3A0           /* .. 0x3E1, with some gaps */
7597 +
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 */
7602 +
7603 +#define MSR_P4_PEBS_MATRIX_VERT        0x3F2
7604 +#define P4_PMV_REPLAY_TAG_BITS 0x00000003
7605 +#define P4_PMV_RESERVED                0xFFFFFFFC
7606 +
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)
7617 +
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)
7622 +
7623 +#define P4_FAST_RDPMC          0x80000000
7624 +#define P4_MASK_FAST_RDPMC     0x0000001F      /* we only need low 5 bits */
7625 +
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")
7630 +
7631 +static void clear_msr_range(unsigned int base, unsigned int n)
7632 +{
7633 +       unsigned int i;
7634 +
7635 +       for(i = 0; i < n; ++i)
7636 +               wrmsr(base+i, 0, 0);
7637 +}
7638 +
7639 +static inline void set_in_cr4_local(unsigned int mask)
7640 +{
7641 +       write_cr4(read_cr4() | mask);
7642 +}
7643 +
7644 +static inline void clear_in_cr4_local(unsigned int mask)
7645 +{
7646 +       write_cr4(read_cr4() & ~mask);
7647 +}
7648 +
7649 +static unsigned int new_id(void)
7650 +{
7651 +       static spinlock_t lock = SPIN_LOCK_UNLOCKED;
7652 +       static unsigned int counter;
7653 +       int id;
7654 +
7655 +       spin_lock(&lock);
7656 +       id = ++counter;
7657 +       spin_unlock(&lock);
7658 +       return id;
7659 +}
7660 +
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
7665 +#undef apic_write
7666 +#define apic_write(reg,vector)                 do{}while(0)
7667 +#endif
7668 +
7669 +#if defined(CONFIG_SMP)
7670 +
7671 +static inline void
7672 +set_isuspend_cpu(struct perfctr_cpu_state *state, int cpu)
7673 +{
7674 +       state->k1.isuspend_cpu = cpu;
7675 +}
7676 +
7677 +static inline int
7678 +is_isuspend_cpu(const struct perfctr_cpu_state *state, int cpu)
7679 +{
7680 +       return state->k1.isuspend_cpu == cpu;
7681 +}
7682 +
7683 +static inline void clear_isuspend_cpu(struct perfctr_cpu_state *state)
7684 +{
7685 +       state->k1.isuspend_cpu = NR_CPUS;
7686 +}
7687 +
7688 +#else
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) { }
7692 +#endif
7693 +
7694 +/****************************************************************
7695 + *                                                             *
7696 + * Driver procedures.                                          *
7697 + *                                                             *
7698 + ****************************************************************/
7699 +
7700 +/*
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.
7714 + */
7715 +
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)
7719 +{
7720 +       unsigned short cesr_half[2];
7721 +       unsigned int pmc, evntsel, i;
7722 +
7723 +       if (state->control.nrictrs != 0 || state->control.nractrs > 2)
7724 +               return -EINVAL;
7725 +       cesr_half[0] = 0;
7726 +       cesr_half[1] = 0;
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)
7731 +                       return -EINVAL;
7732 +               evntsel = state->control.evntsel[i];
7733 +               /* protect reserved bits */
7734 +               if ((evntsel & reserved_bits) != 0)
7735 +                       return -EPERM;
7736 +               /* the CPL field (if defined) must be non-zero */
7737 +               if (!is_c6 && !(evntsel & P5_CESR_CPL))
7738 +                       return -EINVAL;
7739 +               cesr_half[pmc] = evntsel;
7740 +       }
7741 +       state->k1.id = (cesr_half[1] << 16) | cesr_half[0];
7742 +       return 0;
7743 +}
7744 +
7745 +static int p5_check_control(struct perfctr_cpu_state *state, int is_global)
7746 +{
7747 +       return p5_like_check_control(state, P5_CESR_RESERVED, 0);
7748 +}
7749 +
7750 +/* shared with MII but not C6 */
7751 +static void p5_write_control(const struct perfctr_cpu_state *state)
7752 +{
7753 +       struct per_cpu_cache *cache;
7754 +       unsigned int cesr;
7755 +
7756 +       cesr = state->k1.id;
7757 +       if (!cesr)      /* no PMC is on (this test doesn't work on C6) */
7758 +               return;
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);
7763 +       }
7764 +}
7765 +
7766 +static void p5_read_counters(const struct perfctr_cpu_state *state,
7767 +                            struct perfctr_low_ctrs *ctrs)
7768 +{
7769 +       unsigned int cstatus, nrctrs, i;
7770 +
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));
7775 +
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]);
7783 +       }
7784 +}
7785 +
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)
7789 +{
7790 +       unsigned int cstatus, nrctrs, i;
7791 +
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]);
7799 +       }
7800 +}
7801 +
7802 +/* shared with MII and C6 */
7803 +static void p5_clear_counters(void)
7804 +{
7805 +       clear_msr_range(MSR_P5_CESR, 1+2);
7806 +}
7807 +
7808 +/*
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).
7816 + */
7817 +
7818 +static int mii_check_control(struct perfctr_cpu_state *state, int is_global)
7819 +{
7820 +       return p5_like_check_control(state, MII_CESR_RESERVED, 0);
7821 +}
7822 +
7823 +/*
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.
7841 + */
7842 +
7843 +#if !defined(CONFIG_X86_TSC)
7844 +static int c6_check_control(struct perfctr_cpu_state *state, int is_global)
7845 +{
7846 +       if (state->control.tsc_on)
7847 +               return -EINVAL;
7848 +       return p5_like_check_control(state, C6_CESR_RESERVED, 1);
7849 +}
7850 +
7851 +static void c6_write_control(const struct perfctr_cpu_state *state)
7852 +{
7853 +       struct per_cpu_cache *cache;
7854 +       unsigned int cesr;
7855 +
7856 +       if (perfctr_cstatus_nractrs(state->cstatus) == 0) /* no PMC is on */
7857 +               return;
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);
7863 +       }
7864 +}
7865 +#endif
7866 +
7867 +/*
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.
7880 + */
7881 +
7882 +/* shared with K7 */
7883 +static int p6_like_check_control(struct perfctr_cpu_state *state, int is_k7)
7884 +{
7885 +       unsigned int evntsel, i, nractrs, nrctrs, pmc_mask, pmc;
7886 +
7887 +       nractrs = state->control.nractrs;
7888 +       nrctrs = nractrs + state->control.nrictrs;
7889 +       if (nrctrs < nractrs || nrctrs > (is_k7 ? 4 : 2))
7890 +               return -EINVAL;
7891 +
7892 +       pmc_mask = 0;
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)))
7897 +                       return -EINVAL;
7898 +               pmc_mask |= (1<<pmc);
7899 +               evntsel = state->control.evntsel[i];
7900 +               /* protect reserved bits */
7901 +               if (evntsel & P6_EVNTSEL_RESERVED)
7902 +                       return -EPERM;
7903 +               /* check ENable bit */
7904 +               if (is_k7) {
7905 +                       /* ENable bit must be set in each evntsel */
7906 +                       if (!(evntsel & P6_EVNTSEL_ENABLE))
7907 +                               return -EINVAL;
7908 +               } else {
7909 +                       /* only evntsel[0] has the ENable bit */
7910 +                       if (evntsel & P6_EVNTSEL_ENABLE) {
7911 +                               if (pmc > 0)
7912 +                                       return -EPERM;
7913 +                       } else {
7914 +                               if (pmc == 0)
7915 +                                       return -EINVAL;
7916 +                       }
7917 +               }
7918 +               /* the CPL field must be non-zero */
7919 +               if (!(evntsel & P6_EVNTSEL_CPL))
7920 +                       return -EINVAL;
7921 +               /* INT bit must be off for a-mode and on for i-mode counters */
7922 +               if (evntsel & P6_EVNTSEL_INT) {
7923 +                       if (i < nractrs)
7924 +                               return -EINVAL;
7925 +               } else {
7926 +                       if (i >= nractrs)
7927 +                               return -EINVAL;
7928 +               }
7929 +       }
7930 +       state->k1.id = new_id();
7931 +       return 0;
7932 +}
7933 +
7934 +static int p6_check_control(struct perfctr_cpu_state *state, int is_global)
7935 +{
7936 +       return p6_like_check_control(state, 0);
7937 +}
7938 +
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)
7944 +{
7945 +       struct per_cpu_cache *cache;
7946 +       unsigned int cstatus, nrctrs, i;
7947 +       int cpu;
7948 +
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;
7967 +       }
7968 +       /* cache->k1.id is still == state->k1.id */
7969 +}
7970 +
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)
7976 +{
7977 +       struct per_cpu_cache *cache;
7978 +       unsigned int cstatus, nrctrs, i;
7979 +       int cpu;
7980 +
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 */
7987 +       }
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);
8000 +               }
8001 +               /* P4 erratum N15 does not apply since the CCCR is disabled. */
8002 +               wrmsr(msr_perfctr0+pmc, state->pmc[i].start, -1);
8003 +       }
8004 +       /* cache->k1.id remains != state->k1.id */
8005 +}
8006 +
8007 +static void p6_isuspend(struct perfctr_cpu_state *state)
8008 +{
8009 +       p6_like_isuspend(state, MSR_P6_EVNTSEL0);
8010 +}
8011 +
8012 +static void p6_iresume(const struct perfctr_cpu_state *state)
8013 +{
8014 +       p6_like_iresume(state, MSR_P6_EVNTSEL0, MSR_P6_PERFCTR0);
8015 +}
8016 +#endif /* CONFIG_X86_LOCAL_APIC */
8017 +
8018 +/* shared with K7 and VC3 */
8019 +static void p6_like_write_control(const struct perfctr_cpu_state *state,
8020 +                                 unsigned int msr_evntsel0)
8021 +{
8022 +       struct per_cpu_cache *cache;
8023 +       unsigned int nrctrs, i;
8024 +
8025 +       cache = get_cpu_cache();
8026 +       if (cache->k1.id == state->k1.id)
8027 +               return;
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);
8035 +               }
8036 +       }
8037 +       cache->k1.id = state->k1.id;
8038 +}
8039 +
8040 +/* shared with VC3, Generic*/
8041 +static void p6_write_control(const struct perfctr_cpu_state *state)
8042 +{
8043 +       p6_like_write_control(state, MSR_P6_EVNTSEL0);
8044 +}
8045 +
8046 +static void p6_clear_counters(void)
8047 +{
8048 +       clear_msr_range(MSR_P6_EVNTSEL0, 2);
8049 +       clear_msr_range(MSR_P6_PERFCTR0, 2);
8050 +}
8051 +
8052 +/*
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.
8064 + *
8065 + * The K8 has the same hardware layout as the K7. It also has
8066 + * better documentation and a different set of available events.
8067 + */
8068 +
8069 +static int k7_check_control(struct perfctr_cpu_state *state, int is_global)
8070 +{
8071 +       return p6_like_check_control(state, 1);
8072 +}
8073 +
8074 +#ifdef CONFIG_X86_LOCAL_APIC
8075 +static void k7_isuspend(struct perfctr_cpu_state *state)
8076 +{
8077 +       p6_like_isuspend(state, MSR_K7_EVNTSEL0);
8078 +}
8079 +
8080 +static void k7_iresume(const struct perfctr_cpu_state *state)
8081 +{
8082 +       p6_like_iresume(state, MSR_K7_EVNTSEL0, MSR_K7_PERFCTR0);
8083 +}
8084 +#endif /* CONFIG_X86_LOCAL_APIC */
8085 +
8086 +static void k7_write_control(const struct perfctr_cpu_state *state)
8087 +{
8088 +       p6_like_write_control(state, MSR_K7_EVNTSEL0);
8089 +}
8090 +
8091 +static void k7_clear_counters(void)
8092 +{
8093 +       clear_msr_range(MSR_K7_EVNTSEL0, 4+4);
8094 +}
8095 +
8096 +/*
8097 + * VIA C3 family.
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.
8108 + */
8109 +static int vc3_check_control(struct perfctr_cpu_state *state, int is_global)
8110 +{
8111 +       if (state->control.nrictrs || state->control.nractrs > 1)
8112 +               return -EINVAL;
8113 +       if (state->control.nractrs == 1) {
8114 +               if (state->control.pmc_map[0] != 1)
8115 +                       return -EINVAL;
8116 +               state->pmc[0].map = 1;
8117 +               if (state->control.evntsel[0] & VC3_EVNTSEL1_RESERVED)
8118 +                       return -EPERM;
8119 +               state->k1.id = state->control.evntsel[0];
8120 +       } else
8121 +               state->k1.id = 0;
8122 +       return 0;
8123 +}
8124 +
8125 +static void vc3_clear_counters(void)
8126 +{
8127 +       /* Not documented, but seems to be default after boot. */
8128 +       wrmsr(MSR_P6_EVNTSEL0+1, 0x00070079, 0);
8129 +}
8130 +
8131 +/*
8132 + * Intel Pentium 4.
8133 + * Current implementation restrictions:
8134 + * - No DS/PEBS support.
8135 + *
8136 + * Known quirks:
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.
8150 + */
8151 +
8152 +/*
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:
8157 + *
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.
8173 + */
8174 +
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,
8178 +                       [6] 0xA2,
8179 +                       [2] 0xAA,
8180 +                       [4] 0xAC,
8181 +                       [0] 0xB2,
8182 +                       [1] 0xB4,
8183 +                       [3] 0xB6,
8184 +                       [5] 0xC8, },
8185 +       /* 0x04 and 0x05 as is, 0x06 and 0x07 are +1 */
8186 +       [0x04/4] {      [0] 0xC0,
8187 +                       [2] 0xC2,
8188 +                       [1] 0xC4, },
8189 +       /* 0x08 and 0x09 as is, 0x0A and 0x0B are +1 */
8190 +       [0x08/4] {      [1] 0xA4,
8191 +                       [0] 0xA6,
8192 +                       [5] 0xA8,
8193 +                       [2] 0xAE,
8194 +                       [3] 0xB0, },
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,
8198 +                       [5] 0xCC,
8199 +                       [6] 0xE0,
8200 +                       [0] 0xBA,
8201 +                       [2] 0xBC,
8202 +                       [3] 0xBE,
8203 +                       [1] 0xCA, },
8204 +};
8205 +
8206 +static unsigned int p4_escr_addr(unsigned int pmc, unsigned int cccr_val)
8207 +{
8208 +       unsigned int escr_select, pair, escr_offset;
8209 +
8210 +       escr_select = P4_CCCR_ESCR_SELECT(cccr_val);
8211 +       if (pmc > 0x11)
8212 +               return 0;       /* pmc range error */
8213 +       if (pmc > 0x0F)
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;
8220 +};
8221 +
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 */
8225 +
8226 +static int p4_check_control(struct perfctr_cpu_state *state, int is_global)
8227 +{
8228 +       unsigned int i, nractrs, nrctrs, pmc_mask;
8229 +
8230 +       nractrs = state->control.nractrs;
8231 +       nrctrs = nractrs + state->control.nrictrs;
8232 +       if (nrctrs < nractrs || nrctrs > 18)
8233 +               return -EINVAL;
8234 +
8235 +       pmc_mask = 0;
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)))
8244 +                       return -EINVAL;
8245 +               pmc_mask |= (1<<pmc);
8246 +               /* check CCCR contents */
8247 +               cccr_val = state->control.evntsel[i];
8248 +               if (cccr_val & P4_CCCR_RESERVED)
8249 +                       return -EPERM;
8250 +               if (cccr_val & P4_CCCR_EXTENDED_CASCADE) {
8251 +                       if (!p4_extended_cascade_ok)
8252 +                               return -EPERM;
8253 +                       if (!(pmc == 12 || pmc >= 15))
8254 +                               return -EPERM;
8255 +               }
8256 +               if ((cccr_val & P4_CCCR_ACTIVE_THREAD) != P4_CCCR_ACTIVE_THREAD && !p4_is_ht)
8257 +                       return -EINVAL;
8258 +               if (!(cccr_val & (P4_CCCR_ENABLE | P4_CCCR_CASCADE | P4_CCCR_EXTENDED_CASCADE)))
8259 +                       return -EINVAL;
8260 +               if (cccr_val & P4_CCCR_OVF_PMI_T0) {
8261 +                       if (i < nractrs)
8262 +                               return -EINVAL;
8263 +                       if ((cccr_val & P4_CCCR_FORCE_OVF) &&
8264 +                           state->control.ireset[i] != -1)
8265 +                               return -EINVAL;
8266 +               } else {
8267 +                       if (i >= nractrs)
8268 +                               return -EINVAL;
8269 +               }
8270 +               /* check ESCR contents */
8271 +               escr_val = state->control.p4.escr[i];
8272 +               if (escr_val & P4_ESCR_RESERVED)
8273 +                       return -EPERM;
8274 +               if ((escr_val & P4_ESCR_CPL_T1) && (!p4_is_ht || !is_global))
8275 +                       return -EINVAL;
8276 +               /* compute and cache ESCR address */
8277 +               escr_addr = p4_escr_addr(pmc, cccr_val);
8278 +               if (!escr_addr)
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)
8282 +                       return -EINVAL;
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;
8286 +       }
8287 +       /* check ReplayTagging control (PEBS_ENABLE and PEBS_MATRIX_VERT) */
8288 +       if (state->control.p4.pebs_enable) {
8289 +               if (!nrctrs)
8290 +                       return -EPERM;
8291 +               if (state->control.p4.pebs_enable & P4_PE_RESERVED)
8292 +                       return -EPERM;
8293 +               if (!(state->control.p4.pebs_enable & P4_PE_UOP_TAG))
8294 +                       return -EINVAL;
8295 +               if (!(state->control.p4.pebs_enable & P4_PE_REPLAY_TAG_BITS))
8296 +                       return -EINVAL;
8297 +               if (state->control.p4.pebs_matrix_vert & P4_PMV_RESERVED)
8298 +                       return -EPERM;
8299 +               if (!(state->control.p4.pebs_matrix_vert & P4_PMV_REPLAY_TAG_BITS))
8300 +                       return -EINVAL;
8301 +       } else if (state->control.p4.pebs_matrix_vert)
8302 +               return -EPERM;
8303 +       state->k1.id = new_id();
8304 +       return 0;
8305 +}
8306 +
8307 +#ifdef CONFIG_X86_LOCAL_APIC
8308 +static void p4_isuspend(struct perfctr_cpu_state *state)
8309 +{
8310 +       return p6_like_isuspend(state, MSR_P4_CCCR0);
8311 +}
8312 +
8313 +static void p4_iresume(const struct perfctr_cpu_state *state)
8314 +{
8315 +       return p6_like_iresume(state, MSR_P4_CCCR0, MSR_P4_PERFCTR0);
8316 +}
8317 +#endif /* CONFIG_X86_LOCAL_APIC */
8318 +
8319 +static void p4_write_control(const struct perfctr_cpu_state *state)
8320 +{
8321 +       struct per_cpu_cache *cache;
8322 +       unsigned int nrctrs, i;
8323 +
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)
8331 +               return;
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);
8340 +               }
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);
8346 +               }
8347 +       }
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);
8351 +       }
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);
8355 +       }
8356 +       cache->k1.id = state->k1.id;
8357 +}
8358 +
8359 +static void p4_clear_counters(void)
8360 +{
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);
8375 +}
8376 +
8377 +/*
8378 + * Generic driver for any x86 with a working TSC.
8379 + */
8380 +
8381 +static int generic_check_control(struct perfctr_cpu_state *state, int is_global)
8382 +{
8383 +       if (state->control.nractrs || state->control.nrictrs)
8384 +               return -EINVAL;
8385 +       return 0;
8386 +}
8387 +
8388 +static void generic_clear_counters(void)
8389 +{
8390 +}
8391 +
8392 +/*
8393 + * Driver methods, internal and exported.
8394 + *
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.
8399 + *
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.
8405 + *
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().
8409 + */
8410 +
8411 +static int redirect_call_disable;
8412 +
8413 +static noinline void redirect_call(void *ra, void *to)
8414 +{
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);
8423 +               return;
8424 +       }
8425 +       *(int*)((char*)ra - 4) = (char*)to - (char*)ra;
8426 +}
8427 +
8428 +static void (*write_control)(const struct perfctr_cpu_state*);
8429 +static noinline void perfctr_cpu_write_control(const struct perfctr_cpu_state *state)
8430 +{
8431 +       redirect_call(__builtin_return_address(0), write_control);
8432 +       return write_control(state);
8433 +}
8434 +
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)
8439 +{
8440 +       redirect_call(__builtin_return_address(0), read_counters);
8441 +       return read_counters(state, ctrs);
8442 +}
8443 +
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)
8447 +{
8448 +       redirect_call(__builtin_return_address(0), cpu_isuspend);
8449 +       return cpu_isuspend(state);
8450 +}
8451 +
8452 +static void (*cpu_iresume)(const struct perfctr_cpu_state*);
8453 +static noinline void perfctr_cpu_iresume(const struct perfctr_cpu_state *state)
8454 +{
8455 +       redirect_call(__builtin_return_address(0), cpu_iresume);
8456 +       return cpu_iresume(state);
8457 +}
8458 +
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)
8462 +{
8463 +#ifdef CONFIG_SMP
8464 +       clear_isuspend_cpu(state);
8465 +#else
8466 +       get_cpu_cache()->k1.id = 0;
8467 +#endif
8468 +}
8469 +
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)
8473 +{
8474 +       unsigned int cstatus, nrctrs, pmc, pmc_mask;
8475 +
8476 +       cstatus = state->cstatus;
8477 +       pmc = perfctr_cstatus_nractrs(cstatus);
8478 +       nrctrs = perfctr_cstatus_nrctrs(cstatus);
8479 +
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. */
8489 +               }
8490 +       }
8491 +       if (lvtpc_reinit_needed)
8492 +               apic_write(APIC_LVTPC, LOCAL_PERFCTR_VECTOR);
8493 +       return pmc_mask;
8494 +}
8495 +
8496 +static inline int check_ireset(const struct perfctr_cpu_state *state)
8497 +{
8498 +       unsigned int nrctrs, i;
8499 +
8500 +       i = state->control.nractrs;
8501 +       nrctrs = i + state->control.nrictrs;
8502 +       for(; i < nrctrs; ++i)
8503 +               if (state->control.ireset[i] >= 0)
8504 +                       return -EINVAL;
8505 +       return 0;
8506 +}
8507 +
8508 +static inline void setup_imode_start_values(struct perfctr_cpu_state *state)
8509 +{
8510 +       unsigned int cstatus, nrctrs, i;
8511 +
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];
8516 +}
8517 +
8518 +static inline void debug_no_imode(const struct perfctr_cpu_state *state)
8519 +{
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);
8527 +#endif
8528 +}
8529 +
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 */
8537 +
8538 +static int (*check_control)(struct perfctr_cpu_state*, int);
8539 +int perfctr_cpu_update_control(struct perfctr_cpu_state *state, int is_global)
8540 +{
8541 +       int err;
8542 +
8543 +       debug_no_imode(state);
8544 +       clear_isuspend_cpu(state);
8545 +       state->cstatus = 0;
8546 +
8547 +       /* disallow i-mode counters if we cannot catch the interrupts */
8548 +       if (!(perfctr_info.cpu_features & PERFCTR_FEATURE_PCINT)
8549 +           && state->control.nrictrs)
8550 +               return -EPERM;
8551 +
8552 +       err = check_control(state, is_global);
8553 +       if (err < 0)
8554 +               return err;
8555 +       err = check_ireset(state);
8556 +       if (err < 0)
8557 +               return err;
8558 +       state->cstatus = perfctr_mk_cstatus(state->control.tsc_on,
8559 +                                           state->control.nractrs,
8560 +                                           state->control.nrictrs);
8561 +       setup_imode_start_values(state);
8562 +       return 0;
8563 +}
8564 +
8565 +void perfctr_cpu_suspend(struct perfctr_cpu_state *state)
8566 +{
8567 +       unsigned int i, cstatus, nractrs;
8568 +       struct perfctr_low_ctrs now;
8569 +
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 */
8580 +}
8581 +
8582 +void perfctr_cpu_resume(struct perfctr_cpu_state *state)
8583 +{
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);
8589 +       {
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];
8599 +       }
8600 +       /* XXX: if (SMP && start.tsc == now.tsc) ++now.tsc; */
8601 +}
8602 +
8603 +void perfctr_cpu_sample(struct perfctr_cpu_state *state)
8604 +{
8605 +       unsigned int i, cstatus, nractrs;
8606 +       struct perfctr_low_ctrs now;
8607 +
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;
8613 +       }
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];
8618 +       }
8619 +}
8620 +
8621 +static void (*clear_counters)(void);
8622 +static void perfctr_cpu_clear_counters(void)
8623 +{
8624 +       return clear_counters();
8625 +}
8626 +
8627 +/****************************************************************
8628 + *                                                             *
8629 + * Processor detection and initialisation procedures.          *
8630 + *                                                             *
8631 + ****************************************************************/
8632 +
8633 +static inline void clear_perfctr_cpus_forbidden_mask(void)
8634 +{
8635 +#if !defined(perfctr_cpus_forbidden_mask)
8636 +       cpus_clear(perfctr_cpus_forbidden_mask);
8637 +#endif
8638 +}
8639 +
8640 +static inline void set_perfctr_cpus_forbidden_mask(cpumask_t mask)
8641 +{
8642 +#if !defined(perfctr_cpus_forbidden_mask)
8643 +       perfctr_cpus_forbidden_mask = mask;
8644 +#endif
8645 +}
8646 +
8647 +/* see comment above at redirect_call() */
8648 +static void __init finalise_backpatching(void)
8649 +{
8650 +       struct per_cpu_cache *cache;
8651 +       struct perfctr_cpu_state state;
8652 +       cpumask_t old_mask;
8653 +
8654 +       old_mask = perfctr_cpus_forbidden_mask;
8655 +       clear_perfctr_cpus_forbidden_mask();
8656 +
8657 +       cache = get_cpu_cache();
8658 +       memset(cache, 0, sizeof *cache);
8659 +       memset(&state, 0, sizeof state);
8660 +       state.cstatus =
8661 +               (perfctr_info.cpu_features & PERFCTR_FEATURE_PCINT)
8662 +               ? __perfctr_mk_cstatus(0, 1, 0, 0)
8663 +               : 0;
8664 +       perfctr_cpu_sample(&state);
8665 +       perfctr_cpu_resume(&state);
8666 +       perfctr_cpu_suspend(&state);
8667 +
8668 +       set_perfctr_cpus_forbidden_mask(old_mask);
8669 +
8670 +       redirect_call_disable = 1;
8671 +}
8672 +
8673 +#ifdef CONFIG_SMP
8674 +
8675 +cpumask_t perfctr_cpus_forbidden_mask;
8676 +
8677 +static void __init p4_ht_mask_setup_cpu(void *forbidden)
8678 +{
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);
8684 +}
8685 +
8686 +static int __init p4_ht_smp_init(void)
8687 +{
8688 +       cpumask_t forbidden;
8689 +       unsigned int cpu;
8690 +
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))
8695 +               return 0;
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);
8702 +       printk("\n");
8703 +       return 0;
8704 +}
8705 +#else /* SMP */
8706 +#define p4_ht_smp_init()       (0)
8707 +#endif /* SMP */
8708 +
8709 +static int __init p4_ht_init(void)
8710 +{
8711 +       unsigned int nr_siblings;
8712 +
8713 +       if (!cpu_has_ht)
8714 +               return 0;
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",
8719 +                      nr_siblings);
8720 +               return -ENODEV;
8721 +       }
8722 +       if (nr_siblings < 2)
8723 +               return 0;
8724 +       p4_is_ht = 1;   /* needed even in a UP kernel */
8725 +       return p4_ht_smp_init();
8726 +}
8727 +
8728 +static int __init intel_init(void)
8729 +{
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;
8734 +
8735 +       if (!cpu_has_tsc)
8736 +               return -ENODEV;
8737 +       switch (current_cpu_data.x86) {
8738 +       case 5:
8739 +               if (cpu_has_mmx) {
8740 +                       perfctr_info.cpu_type = PERFCTR_X86_INTEL_P5MMX;
8741 +                       read_counters = rdpmc_read_counters;
8742 +
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;
8749 +               } else {
8750 +                       perfctr_info.cpu_type = PERFCTR_X86_INTEL_P5;
8751 +                       perfctr_info.cpu_features &= ~PERFCTR_FEATURE_RDPMC;
8752 +                       read_counters = p5_read_counters;
8753 +               }
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;
8759 +               return 0;
8760 +       case 6:
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))
8766 +                               break;
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;
8774 +               } else {
8775 +                       perfctr_info.cpu_type = PERFCTR_X86_INTEL_P6;
8776 +
8777 +                       /* Avoid Pentium Pro Erratum 26. */
8778 +                       if (current_cpu_data.x86_mask < 9)
8779 +                               perfctr_info.cpu_features &= ~PERFCTR_FEATURE_RDPMC;
8780 +               }
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;
8796 +               }
8797 +#endif
8798 +               return 0;
8799 +       case 15:        /* Pentium 4 */
8800 +               rdmsr_low(MSR_IA32_MISC_ENABLE, misc_enable);
8801 +               if (!(misc_enable & MSR_IA32_MISC_ENABLE_PERF_AVAIL))
8802 +                       break;
8803 +               if (p4_ht_init() != 0)
8804 +                       break;
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;
8816 +               } else {
8817 +                       perfctr_info.cpu_type = PERFCTR_X86_INTEL_P4;
8818 +               }
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;
8831 +               }
8832 +#endif
8833 +               return 0;
8834 +       }
8835 +       return -ENODEV;
8836 +}
8837 +
8838 +static int __init amd_init(void)
8839 +{
8840 +       static char amd_name[] __initdata = "AMD K7/K8";
8841 +
8842 +       if (!cpu_has_tsc)
8843 +               return -ENODEV;
8844 +       switch (current_cpu_data.x86) {
8845 +       case 6: /* K7 */
8846 +               perfctr_info.cpu_type = PERFCTR_X86_AMD_K7;
8847 +               break;
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;
8852 +               } else {
8853 +                       perfctr_info.cpu_type = PERFCTR_X86_AMD_K8;
8854 +               }
8855 +               break;
8856 +       default:
8857 +               return -ENODEV;
8858 +       }
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;
8870 +       }
8871 +#endif
8872 +       return 0;
8873 +}
8874 +
8875 +static int __init cyrix_init(void)
8876 +{
8877 +       static char mii_name[] __initdata = "Cyrix 6x86MX/MII/III";
8878 +       if (!cpu_has_tsc)
8879 +               return -ENODEV;
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;
8889 +               return 0;
8890 +       }
8891 +       return -ENODEV;
8892 +}
8893 +
8894 +static int __init centaur_init(void)
8895 +{
8896 +#if !defined(CONFIG_X86_TSC)
8897 +       static char winchip_name[] __initdata = "WinChip C6/2/3";
8898 +#endif
8899 +       static char vc3_name[] __initdata = "VIA C3";
8900 +       switch (current_cpu_data.x86) {
8901 +#if !defined(CONFIG_X86_TSC)
8902 +       case 5:
8903 +               switch (current_cpu_data.x86_model) {
8904 +               case 4: /* WinChip C6 */
8905 +                       perfctr_info.cpu_type = PERFCTR_X86_WINCHIP_C6;
8906 +                       break;
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;
8910 +                       break;
8911 +               default:
8912 +                       return -ENODEV;
8913 +               }
8914 +               perfctr_set_tests_type(PTT_WINCHIP);
8915 +               perfctr_cpu_name = winchip_name;
8916 +               /*
8917 +                * TSC must be inaccessible for perfctrs to work.
8918 +                */
8919 +               if (!(read_cr4() & X86_CR4_TSD) || cpu_has_tsc)
8920 +                       return -ENODEV;
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;
8926 +               return 0;
8927 +#endif
8928 +       case 6: /* VIA C3 */
8929 +               if (!cpu_has_tsc)
8930 +                       return -ENODEV;
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 */
8936 +                       break;
8937 +               default:
8938 +                       return -ENODEV;
8939 +               }
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;
8947 +               return 0;
8948 +       }
8949 +       return -ENODEV;
8950 +}
8951 +
8952 +static int __init generic_init(void)
8953 +{
8954 +       static char generic_name[] __initdata = "Generic x86 with TSC";
8955 +       if (!cpu_has_tsc)
8956 +               return -ENODEV;
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;
8965 +       return 0;
8966 +}
8967 +
8968 +static void perfctr_cpu_invalidate_cache(void)
8969 +{
8970 +       /*
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.
8976 +        */
8977 +       memset(get_cpu_cache(), ~0, sizeof(struct per_cpu_cache));
8978 +}
8979 +
8980 +static void perfctr_cpu_init_one(void *ignore)
8981 +{
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();
8986 +       if (cpu_has_apic)
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);
8990 +}
8991 +
8992 +static void perfctr_cpu_exit_one(void *ignore)
8993 +{
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();
8998 +       if (cpu_has_apic)
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);
9002 +}
9003 +
9004 +#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PM)
9005 +
9006 +static void perfctr_pm_suspend(void)
9007 +{
9008 +       /* XXX: clear control registers */
9009 +       printk("perfctr/x86: PM suspend\n");
9010 +}
9011 +
9012 +static void perfctr_pm_resume(void)
9013 +{
9014 +       /* XXX: reload control registers */
9015 +       printk("perfctr/x86: PM resume\n");
9016 +}
9017 +
9018 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,71)
9019 +
9020 +#include <linux/sysdev.h>
9021 +
9022 +static int perfctr_device_suspend(struct sys_device *dev, u32 state)
9023 +{
9024 +       perfctr_pm_suspend();
9025 +       return 0;
9026 +}
9027 +
9028 +static int perfctr_device_resume(struct sys_device *dev)
9029 +{
9030 +       perfctr_pm_resume();
9031 +       return 0;
9032 +}
9033 +
9034 +static struct sysdev_class perfctr_sysclass = {
9035 +       set_kset_name("perfctr"),
9036 +       .resume         = perfctr_device_resume,
9037 +       .suspend        = perfctr_device_suspend,
9038 +};
9039 +
9040 +static struct sys_device device_perfctr = {
9041 +       .id     = 0,
9042 +       .cls    = &perfctr_sysclass,
9043 +};
9044 +
9045 +static void x86_pm_init(void)
9046 +{
9047 +       if (sysdev_class_register(&perfctr_sysclass) == 0)
9048 +               sysdev_register(&device_perfctr);
9049 +}
9050 +
9051 +static void x86_pm_exit(void)
9052 +{
9053 +       sysdev_unregister(&device_perfctr);
9054 +       sysdev_class_unregister(&perfctr_sysclass);
9055 +}
9056 +
9057 +#else  /* 2.4 kernel */
9058 +
9059 +static int x86_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
9060 +{
9061 +       switch (rqst) {
9062 +       case PM_SUSPEND:
9063 +               perfctr_pm_suspend();
9064 +               break;
9065 +       case PM_RESUME:
9066 +               perfctr_pm_resume();
9067 +               break;
9068 +       }
9069 +       return 0;
9070 +}
9071 +
9072 +static struct pm_dev *x86_pmdev;
9073 +
9074 +static void x86_pm_init(void)
9075 +{
9076 +       x86_pmdev = apic_pm_register(PM_SYS_DEV, 0, x86_pm_callback);
9077 +}
9078 +
9079 +static void x86_pm_exit(void)
9080 +{
9081 +       if (x86_pmdev) {
9082 +               apic_pm_unregister(x86_pmdev);
9083 +               x86_pmdev = NULL;
9084 +       }
9085 +}
9086 +
9087 +#endif /* 2.4 kernel */
9088 +
9089 +#else
9090 +
9091 +static inline void x86_pm_init(void) { }
9092 +static inline void x86_pm_exit(void) { }
9093 +
9094 +#endif /* CONFIG_X86_LOCAL_APIC && CONFIG_PM */
9095 +
9096 +#ifdef CONFIG_X86_LOCAL_APIC
9097 +
9098 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,67)
9099 +static void disable_lapic_nmi_watchdog(void)
9100 +{
9101 +#ifdef CONFIG_PM
9102 +       if (nmi_pmdev) {
9103 +               apic_pm_unregister(nmi_pmdev);
9104 +               nmi_pmdev = 0;
9105 +       }
9106 +#endif
9107 +}
9108 +#endif
9109 +
9110 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,6)
9111 +static int reserve_lapic_nmi(void)
9112 +{
9113 +       int ret = 0;
9114 +       if (nmi_perfctr_msr) {
9115 +               nmi_perfctr_msr = 0;
9116 +               disable_lapic_nmi_watchdog();
9117 +               ret = 1;
9118 +       }
9119 +       return ret;
9120 +}
9121 +
9122 +static inline void release_lapic_nmi(void) { }
9123 +#endif
9124 +
9125 +#else
9126 +static inline int reserve_lapic_nmi(void) { return 0; }
9127 +static inline void release_lapic_nmi(void) { }
9128 +#endif
9129 +
9130 +static void do_init_tests(void)
9131 +{
9132 +#ifdef CONFIG_PERFCTR_INIT_TESTS
9133 +       if (reserve_lapic_nmi() >= 0) {
9134 +               perfctr_x86_init_tests();
9135 +               release_lapic_nmi();
9136 +       }
9137 +#endif
9138 +}
9139 +
9140 +int __init perfctr_cpu_init(void)
9141 +{
9142 +       int err = -ENODEV;
9143 +
9144 +       preempt_disable();
9145 +
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;
9149 +
9150 +       if (cpu_has_msr) {
9151 +               switch (current_cpu_data.x86_vendor) {
9152 +               case X86_VENDOR_INTEL:
9153 +                       err = intel_init();
9154 +                       break;
9155 +               case X86_VENDOR_AMD:
9156 +                       err = amd_init();
9157 +                       break;
9158 +               case X86_VENDOR_CYRIX:
9159 +                       err = cyrix_init();
9160 +                       break;
9161 +               case X86_VENDOR_CENTAUR:
9162 +                       err = centaur_init();
9163 +               }
9164 +       }
9165 +       if (err) {
9166 +               err = generic_init();   /* last resort */
9167 +               if (err)
9168 +                       goto out;
9169 +       }
9170 +       do_init_tests();
9171 +       finalise_backpatching();
9172 +
9173 +       perfctr_info.cpu_khz = perfctr_cpu_khz();
9174 +       perfctr_info.tsc_to_cpu_mult = 1;
9175 +
9176 + out:
9177 +       preempt_enable();
9178 +       return err;
9179 +}
9180 +
9181 +void __exit perfctr_cpu_exit(void)
9182 +{
9183 +}
9184 +
9185 +/****************************************************************
9186 + *                                                             *
9187 + * Hardware reservation.                                       *
9188 + *                                                             *
9189 + ****************************************************************/
9190 +
9191 +static DECLARE_MUTEX(mutex);
9192 +static const char *current_service = 0;
9193 +
9194 +const char *perfctr_cpu_reserve(const char *service)
9195 +{
9196 +       const char *ret;
9197 +
9198 +       down(&mutex);
9199 +       ret = current_service;
9200 +       if (ret)
9201 +               goto out_up;
9202 +       ret = "unknown driver (oprofile?)";
9203 +       if (reserve_lapic_nmi() < 0)
9204 +               goto out_up;
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);
9211 +       x86_pm_init();
9212 +       ret = NULL;
9213 + out_up:
9214 +       up(&mutex);
9215 +       return ret;
9216 +}
9217 +
9218 +void perfctr_cpu_release(const char *service)
9219 +{
9220 +       down(&mutex);
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);
9224 +               goto out_up;
9225 +       }
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);
9231 +       x86_pm_exit();
9232 +       current_service = 0;
9233 +       release_lapic_nmi();
9234 +       module_put(THIS_MODULE);
9235 + out_up:
9236 +       up(&mutex);
9237 +}
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
9242 @@ -99,6 +99,8 @@
9243  #define NMI_LOCAL_APIC 2
9244  #define NMI_INVALID    3
9245  
9246 +extern unsigned int nmi_perfctr_msr;
9247 +
9248  #endif /* CONFIG_X86_LOCAL_APIC */
9249  
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
9255 @@ -59,14 +59,15 @@
9256   * sources per level' errata.
9257   */
9258  #define LOCAL_TIMER_VECTOR     0xef
9259 +#define LOCAL_PERFCTR_VECTOR   0xee
9260  
9261  /*
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)
9266   */
9267  #define FIRST_DEVICE_VECTOR    0x31
9268 -#define FIRST_SYSTEM_VECTOR    0xef
9269 +#define FIRST_SYSTEM_VECTOR    0xee
9270  
9271  #define TIMER_IRQ 0
9272  
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
9277 @@ -59,14 +59,15 @@
9278   * sources per level' errata.
9279   */
9280  #define LOCAL_TIMER_VECTOR     0xef
9281 +#define LOCAL_PERFCTR_VECTOR   0xee
9282  
9283  /*
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)
9288   */
9289  #define FIRST_DEVICE_VECTOR    0x31
9290 -#define FIRST_SYSTEM_VECTOR    0xef
9291 +#define FIRST_SYSTEM_VECTOR    0xee
9292  
9293  #define TIMER_IRQ 0
9294  
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
9299 @@ -35,14 +35,15 @@
9300   * sources per level' errata.
9301   */
9302  #define LOCAL_TIMER_VECTOR     0xef
9303 +#define LOCAL_PERFCTR_VECTOR   0xee
9304  
9305  /*
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)
9310   */
9311  #define FIRST_DEVICE_VECTOR    0x31
9312 -#define FIRST_SYSTEM_VECTOR    0xef
9313 +#define FIRST_SYSTEM_VECTOR    0xee
9314  
9315  #define TIMER_IRQ 0
9316  
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
9321 @@ -427,6 +427,8 @@
9322         unsigned int            saved_fs, saved_gs;
9323  /* IO permissions */
9324         unsigned long   *io_bitmap_ptr;
9325 +/* performance counters */
9326 +       struct vperfctr *perfctr;
9327  };
9328  
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
9334 @@ -0,0 +1,189 @@
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
9337 + *
9338 + * Copyright (C) 1999-2004  Mikael Pettersson
9339 + */
9340 +#ifndef _ASM_I386_PERFCTR_H
9341 +#define _ASM_I386_PERFCTR_H
9342 +
9343 +struct perfctr_sum_ctrs {
9344 +       unsigned long long tsc;
9345 +       unsigned long long pmc[18];
9346 +};
9347 +
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 */
9354 +       struct {
9355 +               unsigned int escr[18];
9356 +               unsigned int pebs_enable;       /* for replay tagging */
9357 +               unsigned int pebs_matrix_vert;  /* for replay tagging */
9358 +       } p4;
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;
9364 +};
9365 +
9366 +struct perfctr_cpu_state {
9367 +       unsigned int cstatus;
9368 +       struct {        /* k1 is opaque in the user ABI */
9369 +               unsigned int id;
9370 +               int isuspend_cpu;
9371 +       } k1;
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;
9376 +       struct {
9377 +               unsigned int map;
9378 +               unsigned int start;
9379 +               unsigned long long sum;
9380 +       } pmc[18];      /* the size is not part of the user ABI */
9381 +#ifdef __KERNEL__
9382 +       struct perfctr_cpu_control control;
9383 +       unsigned int p4_escr_map[18];
9384 +#endif
9385 +};
9386 +
9387 +/* cstatus is a re-encoding of control.tsc_on/nractrs/nrictrs
9388 +   which should have less overhead in most cases */
9389 +
9390 +static inline
9391 +unsigned int __perfctr_mk_cstatus(unsigned int tsc_on, unsigned int have_ictrs,
9392 +                                 unsigned int nrictrs, unsigned int nractrs)
9393 +{
9394 +       return (tsc_on<<31) | (have_ictrs<<16) | ((nractrs+nrictrs)<<8) | nractrs;
9395 +}
9396 +
9397 +static inline
9398 +unsigned int perfctr_mk_cstatus(unsigned int tsc_on, unsigned int nractrs,
9399 +                               unsigned int nrictrs)
9400 +{
9401 +       return __perfctr_mk_cstatus(tsc_on, nrictrs, nrictrs, nractrs);
9402 +}
9403 +
9404 +static inline unsigned int perfctr_cstatus_enabled(unsigned int cstatus)
9405 +{
9406 +       return cstatus;
9407 +}
9408 +
9409 +static inline int perfctr_cstatus_has_tsc(unsigned int cstatus)
9410 +{
9411 +       return (int)cstatus < 0;        /* test and jump on sign */
9412 +}
9413 +
9414 +static inline unsigned int perfctr_cstatus_nractrs(unsigned int cstatus)
9415 +{
9416 +       return cstatus & 0x7F;          /* and with imm8 */
9417 +}
9418 +
9419 +static inline unsigned int perfctr_cstatus_nrctrs(unsigned int cstatus)
9420 +{
9421 +       return (cstatus >> 8) & 0x7F;
9422 +}
9423 +
9424 +static inline unsigned int perfctr_cstatus_has_ictrs(unsigned int cstatus)
9425 +{
9426 +       return cstatus & (0x7F << 16);
9427 +}
9428 +
9429 +/*
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.
9435 + *
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.
9439 + */
9440 +#ifdef __KERNEL__
9441 +#define SI_PMC_OVF     (__SI_FAULT|'P')
9442 +#else
9443 +#define SI_PMC_OVF     ('P')
9444 +#endif
9445 +#define si_pmc_ovf_mask        _sifields._pad[0] /* XXX: use an unsigned field later */
9446 +
9447 +/* version number for user-visible CPU-specific data */
9448 +#define PERFCTR_CPU_VERSION    0x0501  /* 5.1 */
9449 +
9450 +#ifdef __KERNEL__
9451 +
9452 +#if defined(CONFIG_PERFCTR) || defined(CONFIG_PERFCTR_MODULE)
9453 +
9454 +/* Driver init/exit. */
9455 +extern int perfctr_cpu_init(void);
9456 +extern void perfctr_cpu_exit(void);
9457 +
9458 +/* CPU type name. */
9459 +extern char *perfctr_cpu_name;
9460 +
9461 +/* Hardware reservation. */
9462 +extern const char *perfctr_cpu_reserve(const char *service);
9463 +extern void perfctr_cpu_release(const char *service);
9464 +
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);
9472 +
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);
9476 +
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);
9480 +
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);
9484 +
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);
9488 +
9489 +#if defined(CONFIG_X86_LOCAL_APIC)
9490 +#define PERFCTR_INTERRUPT_SUPPORT 1
9491 +#endif
9492 +
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*);
9498 +#else
9499 +static inline void perfctr_cpu_set_ihandler(perfctr_ihandler_t x) { }
9500 +#endif
9501 +
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
9509 +#endif
9510 +
9511 +#endif /* CONFIG_PERFCTR */
9512 +
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)
9517 +#else
9518 +#define perfctr_vector_init()  do{}while(0)
9519 +#endif
9520 +
9521 +#endif /* __KERNEL__ */
9522 +
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
9528 @@ -119,6 +119,7 @@
9529         unsigned long   vrsave;
9530         int             used_vr;        /* set if process has used altivec */
9531  #endif /* CONFIG_ALTIVEC */
9532 +       struct vperfctr *perfctr;       /* performance counters */
9533  };
9534  
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
9540 @@ -0,0 +1,171 @@
9541 +/* $Id: perfctr.h,v 1.3.2.2 2004/06/21 22:38:30 mikpe Exp $
9542 + * PPC32 Performance-Monitoring Counters driver
9543 + *
9544 + * Copyright (C) 2004  Mikael Pettersson
9545 + */
9546 +#ifndef _ASM_PPC_PERFCTR_H
9547 +#define _ASM_PPC_PERFCTR_H
9548 +
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
9556 +
9557 +struct perfctr_sum_ctrs {
9558 +       unsigned long long tsc;
9559 +       unsigned long long pmc[6];
9560 +};
9561 +
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 */
9569 +       struct {
9570 +               unsigned int mmcr0;     /* sans PMC{1,2}SEL */
9571 +               unsigned int mmcr2;     /* only THRESHMULT */
9572 +               /* IABR/DABR/BAMR not supported */
9573 +       } ppc;
9574 +       unsigned int _reserved1;
9575 +       unsigned int _reserved2;
9576 +       unsigned int _reserved3;
9577 +       unsigned int _reserved4;
9578 +};
9579 +
9580 +struct perfctr_cpu_state {
9581 +       unsigned int cstatus;
9582 +       struct {        /* k1 is opaque in the user ABI */
9583 +               unsigned int id;
9584 +               int isuspend_cpu;
9585 +       } k1;
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;
9590 +       struct {
9591 +               unsigned int map;
9592 +               unsigned int start;
9593 +               unsigned long long sum;
9594 +       } pmc[6];       /* the size is not part of the user ABI */
9595 +#ifdef __KERNEL__
9596 +       unsigned int ppc_mmcr[3];
9597 +       struct perfctr_cpu_control control;
9598 +#endif
9599 +};
9600 +
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) */
9604 +
9605 +static inline
9606 +unsigned int perfctr_mk_cstatus(unsigned int tsc_on, unsigned int nractrs,
9607 +                               unsigned int nrictrs)
9608 +{
9609 +       return (tsc_on<<31) | (nrictrs<<16) | ((nractrs+nrictrs)<<8) | nractrs;
9610 +}
9611 +
9612 +static inline unsigned int perfctr_cstatus_enabled(unsigned int cstatus)
9613 +{
9614 +       return cstatus;
9615 +}
9616 +
9617 +static inline int perfctr_cstatus_has_tsc(unsigned int cstatus)
9618 +{
9619 +       return (int)cstatus < 0;        /* test and jump on sign */
9620 +}
9621 +
9622 +static inline unsigned int perfctr_cstatus_nractrs(unsigned int cstatus)
9623 +{
9624 +       return cstatus & 0x7F;          /* and with imm8 */
9625 +}
9626 +
9627 +static inline unsigned int perfctr_cstatus_nrctrs(unsigned int cstatus)
9628 +{
9629 +       return (cstatus >> 8) & 0x7F;
9630 +}
9631 +
9632 +static inline unsigned int perfctr_cstatus_has_ictrs(unsigned int cstatus)
9633 +{
9634 +       return cstatus & (0x7F << 16);
9635 +}
9636 +
9637 +/*
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.
9643 + *
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.
9647 + */
9648 +#ifdef __KERNEL__
9649 +#define SI_PMC_OVF     (__SI_FAULT|'P')
9650 +#else
9651 +#define SI_PMC_OVF     ('P')
9652 +#endif
9653 +#define si_pmc_ovf_mask        _sifields._pad[0] /* XXX: use an unsigned field later */
9654 +
9655 +/* version number for user-visible CPU-specific data */
9656 +#define PERFCTR_CPU_VERSION    0       /* XXX: not yet cast in stone */
9657 +
9658 +#ifdef __KERNEL__
9659 +
9660 +#if defined(CONFIG_PERFCTR) || defined(CONFIG_PERFCTR_MODULE)
9661 +
9662 +/* Driver init/exit. */
9663 +extern int perfctr_cpu_init(void);
9664 +extern void perfctr_cpu_exit(void);
9665 +
9666 +/* CPU type name. */
9667 +extern char *perfctr_cpu_name;
9668 +
9669 +/* Hardware reservation. */
9670 +extern const char *perfctr_cpu_reserve(const char *service);
9671 +extern void perfctr_cpu_release(const char *service);
9672 +
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);
9678 +
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);
9682 +
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);
9686 +
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);
9690 +
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);
9694 +
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
9698 +
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*);
9703 +#else
9704 +static inline void perfctr_cpu_set_ihandler(perfctr_ihandler_t x) { }
9705 +#endif
9706 +
9707 +#endif /* CONFIG_PERFCTR */
9708 +
9709 +#endif /* __KERNEL__ */
9710 +
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
9716 @@ -96,6 +96,8 @@
9717  #define NMI_LOCAL_APIC 2
9718  #define NMI_INVALID    3
9719  
9720 +extern unsigned int nmi_perfctr_msr;
9721 +
9722  #endif /* CONFIG_X86_LOCAL_APIC */
9723  
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
9729 @@ -65,14 +65,15 @@
9730   * sources per level' errata.
9731   */
9732  #define LOCAL_TIMER_VECTOR     0xef
9733 +#define LOCAL_PERFCTR_VECTOR   0xee
9734  
9735  /*
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)
9740   */
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 */
9744  
9745  
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
9751 @@ -29,7 +29,7 @@
9752   */
9753  #define NR_VECTORS 256
9754  
9755 -#define FIRST_SYSTEM_VECTOR    0xef   /* duplicated in hw_irq.h */
9756 +#define FIRST_SYSTEM_VECTOR    0xee   /* duplicated in hw_irq.h */
9757  
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
9764 @@ -258,6 +258,8 @@
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;
9770  };
9771  
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
9777 @@ -0,0 +1 @@
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
9783 @@ -0,0 +1,246 @@
9784 +/* $Id: perfctr.h,v 1.69 2004/02/20 21:31:02 mikpe Exp $
9785 + * Performance-Monitoring Counters driver
9786 + *
9787 + * Copyright (C) 1999-2004  Mikael Pettersson
9788 + */
9789 +#ifndef _LINUX_PERFCTR_H
9790 +#define _LINUX_PERFCTR_H
9791 +
9792 +#ifdef CONFIG_KPERFCTR /* don't break archs without <asm/perfctr.h> */
9793 +
9794 +#include <asm/perfctr.h>
9795 +
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;
9806 +};
9807 +
9808 +struct perfctr_cpu_mask {
9809 +       unsigned int nrwords;
9810 +       unsigned int mask[1];   /* actually 'nrwords' */
9811 +};
9812 +
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)
9818 +
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 */
9837 +
9838 +/* cpu_features flag bits */
9839 +#define PERFCTR_FEATURE_RDPMC  0x01
9840 +#define PERFCTR_FEATURE_RDTSC  0x02
9841 +#define PERFCTR_FEATURE_PCINT  0x04
9842 +
9843 +/* user's view of mmap:ed virtual perfctr */
9844 +struct vperfctr_state {
9845 +       struct perfctr_cpu_state cpu_state;
9846 +};
9847 +
9848 +/* parameter in VPERFCTR_CONTROL command */
9849 +struct vperfctr_control {
9850 +       int si_signo;
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;
9857 +};
9858 +
9859 +/* parameter in GPERFCTR_CONTROL command */
9860 +struct gperfctr_cpu_control {
9861 +       unsigned int cpu;
9862 +       struct perfctr_cpu_control cpu_control;
9863 +       unsigned int _reserved1;
9864 +       unsigned int _reserved2;
9865 +       unsigned int _reserved3;
9866 +       unsigned int _reserved4;
9867 +};
9868 +
9869 +/* returned by GPERFCTR_READ command */
9870 +struct gperfctr_cpu_state {
9871 +       unsigned int cpu;
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;
9878 +};
9879 +
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)' */
9885 +};
9886 +
9887 +#include <linux/ioctl.h>
9888 +#define _PERFCTR_IOCTL 0xD0    /* 'P'+128, currently unassigned */
9889 +
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*/
9896 +
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)
9902 +
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*/
9907 +
9908 +#ifdef __KERNEL__
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__ */
9915 +
9916 +#endif /* CONFIG_KPERFCTR */
9917 +
9918 +#ifdef __KERNEL__
9919 +
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
9925 +#endif
9926 +
9927 +#ifdef CONFIG_PERFCTR_VIRTUAL
9928 +
9929 +/*
9930 + * Virtual per-process performance-monitoring counters.
9931 + */
9932 +struct vperfctr;       /* opaque */
9933 +
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);
9941 +
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);
9951 +#endif
9952 +} vperfctr_stub;
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 */
9965 +
9966 +static inline void perfctr_copy_thread(struct thread_struct *thread)
9967 +{
9968 +       thread->perfctr = NULL;
9969 +}
9970 +
9971 +static inline void perfctr_exit_thread(struct thread_struct *thread)
9972 +{
9973 +       struct vperfctr *perfctr;
9974 +       perfctr = thread->perfctr;
9975 +       if( perfctr )
9976 +               _vperfctr_exit(perfctr);
9977 +}
9978 +
9979 +static inline void perfctr_suspend_thread(struct thread_struct *prev)
9980 +{
9981 +       struct vperfctr *perfctr;
9982 +       perfctr = prev->perfctr;
9983 +       if( perfctr )
9984 +               _vperfctr_suspend(perfctr);
9985 +}
9986 +
9987 +static inline void perfctr_resume_thread(struct thread_struct *next)
9988 +{
9989 +       struct vperfctr *perfctr;
9990 +       perfctr = next->perfctr;
9991 +       if( perfctr )
9992 +               _vperfctr_resume(perfctr);
9993 +}
9994 +
9995 +static inline void perfctr_sample_thread(struct thread_struct *thread)
9996 +{
9997 +       struct vperfctr *perfctr;
9998 +       perfctr = thread->perfctr;
9999 +       if( perfctr )
10000 +               _vperfctr_sample(perfctr);
10001 +}
10002 +
10003 +static inline void perfctr_set_cpus_allowed(struct task_struct *p, cpumask_t new_mask)
10004 +{
10005 +#if PERFCTR_CPUS_FORBIDDEN_MASK_NEEDED
10006 +       struct vperfctr *perfctr;
10007 +
10008 +       task_lock(p);
10009 +       perfctr = p->thread.perfctr;
10010 +       if( perfctr )
10011 +               _vperfctr_set_cpus_allowed(p, perfctr, new_mask);
10012 +       task_unlock(p);
10013 +#endif
10014 +}
10015 +
10016 +#else  /* !CONFIG_PERFCTR_VIRTUAL */
10017 +
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) { }
10024 +
10025 +#endif /* CONFIG_PERFCTR_VIRTUAL */
10026 +
10027 +#endif /* __KERNEL__ */
10028 +
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
10034 @@ -39,6 +39,7 @@
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;
10044         runqueue_t *rq;
10045  
10046 +       perfctr_set_cpus_allowed(p, new_mask);
10047 +
10048         rq = task_rq_lock(p, &flags);
10049         if (any_online_cpu(new_mask) == NR_CPUS) {
10050                 ret = -EINVAL;
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
10055 @@ -31,6 +31,7 @@
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>
10061  
10062  #include <asm/uaccess.h>
10063 @@ -844,6 +845,7 @@
10064         do_process_times(p, user, system);
10065         do_it_virt(p, user);
10066         do_it_prof(p);
10067 +       perfctr_sample_thread(&p->thread);
10068  }      
10069  
10070  /*