Hi Stephane,

Here's another go at the patch that fixes the problem of uninitialized interrupting pmd registers causing spurious interrupts on POWER.

This patch introduces a new arch-specific call - pfm_arch_condition_intr_pmds. It is called at the end of pfm_save_pmds in perfmon_ctxsw.c.

Since the other architectures do not need this ability, their version of the function is a static inline empty function. The x86 version of this null function actually contains comments (like the other functions in include/asm-x86/perfmon_kern.h). When in Rome.

In order that the registers be properly reloaded after being zeroed by
the above-mentioned condition function, I modified pfm_arch_ctxswout_thread to force the both the PMC and PMD registers to be re-loaded. Without this, the zeroed pmd registers caused incorrect results to be generated.

In this patch, I've also fixed the pfm_arch_restore_pmds to correctly set the upper bit of the pmd register using the corresponding povfl_mask bit. This wasn't being done before, and I believe it was an error.

Thanks for your consideration,

- Corey

--
Corey Ashford
Software Engineer
IBM Linux Technology Center, Linux Toolchain
Beaverton, OR
503-578-3507
[EMAIL PROTECTED]
Index: linux-2.6/perfmon/perfmon_ctxsw.c
===================================================================
--- linux-2.6.orig/perfmon/perfmon_ctxsw.c      2008-07-22 13:45:13.000000000 
-0500
+++ linux-2.6/perfmon/perfmon_ctxsw.c   2008-07-22 16:39:44.000000000 -0500
@@ -63,6 +63,7 @@
                        num--;
                }
        }
+       pfm_arch_condition_intr_pmds(ctx, set);
 }
 
 /*
Index: linux-2.6/arch/powerpc/perfmon/perfmon.c
===================================================================
--- linux-2.6.orig/arch/powerpc/perfmon/perfmon.c       2008-07-22 
13:44:52.000000000 -0500
+++ linux-2.6/arch/powerpc/perfmon/perfmon.c    2008-07-22 16:17:30.000000000 
-0500
@@ -42,6 +42,26 @@
 }
 
 /*
+ * Called from pfm_save_pmds(). Interrupts are masked.  Registers are
+ * already saved away.
+ */
+void pfm_arch_condition_intr_pmds(struct pfm_context *ctx,
+                                 struct pfm_event_set *set)
+{
+       int i, num;
+       u64 *used_pmds;
+
+       num = set->nused_pmds;
+       used_pmds = set->used_pmds;
+
+       for (i = 0; num; i++)
+               if (likely(test_bit(i, used_pmds))) {
+                       pfm_write_pmd(ctx, i, 0);
+                       num--;
+               }
+}
+
+/*
  * Called from pfm_ctxsw(). Task is guaranteed to be current.
  * Context is locked. Interrupts are masked. Monitoring is active.
  * PMU access is guaranteed. PMC and PMD registers are live in PMU.
@@ -58,9 +78,9 @@
 
        arch_info = pfm_pmu_info();
        /*
-        * disable lazy restore of PMC registers.
+        * disable lazy restore of the PMC/PMD registers.
         */
-       ctx->active_set->priv_flags |= PFM_SETFL_PRIV_MOD_PMCS;
+       ctx->active_set->priv_flags |= PFM_SETFL_PRIV_MOD_BOTH;
 
        if (ctx->state == PFM_CTX_MASKED)
                return 1;
@@ -160,7 +180,7 @@
 void pfm_arch_restore_pmds(struct pfm_context *ctx, struct pfm_event_set *set)
 {
        struct pfm_arch_pmu_info *arch_info;
-       u64 *used_pmds;
+       u64 *used_pmds, *povfl_pmds, ovfl_mask;
        u16 i, num;
 
        arch_info = pfm_pmu_info();
@@ -173,10 +193,16 @@
 
        num = set->nused_pmds;
        used_pmds = set->used_pmds;
+       povfl_pmds = set->povfl_pmds;
+       ovfl_mask = pfm_pmu_conf->ovfl_mask;
 
        for (i = 0; num; i++) {
                if (likely(test_bit(i, used_pmds))) {
-                       pfm_write_pmd(ctx, i, set->pmds[i].value);
+                       u64 new_value;
+                       new_value = set->pmds[i].value & ovfl_mask;
+                       if (test_bit(i, povfl_pmds))
+                               new_value += 1 + ovfl_mask;
+                       pfm_write_pmd(ctx, i, new_value);
                        num--;
                }
        }
Index: linux-2.6/include/asm-powerpc/perfmon_kern.h
===================================================================
--- linux-2.6.orig/include/asm-powerpc/perfmon_kern.h   2008-07-22 
13:45:10.000000000 -0500
+++ linux-2.6/include/asm-powerpc/perfmon_kern.h        2008-07-22 
16:25:03.000000000 -0500
@@ -191,6 +191,7 @@
 void pfm_arch_start(struct task_struct *task, struct pfm_context *ctx);
 void pfm_arch_restore_pmds(struct pfm_context *ctx, struct pfm_event_set *set);
 void pfm_arch_restore_pmcs(struct pfm_context *ctx, struct pfm_event_set *set);
+void pfm_arch_condition_intr_pmds(struct pfm_context *ctx, struct 
pfm_event_set *set);
 int  pfm_arch_get_ovfl_pmds(struct pfm_context *ctx,
                            struct pfm_event_set *set);
 char *pfm_arch_get_pmu_module_name(void);
Index: linux-2.6/include/asm-ia64/perfmon_kern.h
===================================================================
--- linux-2.6.orig/include/asm-ia64/perfmon_kern.h      2008-07-22 
13:45:10.000000000 -0500
+++ linux-2.6/include/asm-ia64/perfmon_kern.h   2008-07-22 17:23:57.000000000 
-0500
@@ -85,6 +85,10 @@
        ia64_resend_irq(IA64_PERFMON_VECTOR);
 }
 
+static inline void pfm_arch_condition_intr_pmds(struct pfm_context *ctx,
+                                               struct pfm_event_set *set)
+{}
+
 static inline void pfm_arch_serialize(void)
 {
        ia64_srlz_d();
Index: linux-2.6/include/asm-mips/perfmon_kern.h
===================================================================
--- linux-2.6.orig/include/asm-mips/perfmon_kern.h      2008-07-22 
13:45:10.000000000 -0500
+++ linux-2.6/include/asm-mips/perfmon_kern.h   2008-07-22 17:24:19.000000000 
-0500
@@ -82,6 +82,10 @@
 static inline void pfm_arch_resend_irq(struct pfm_context *ctx)
 {}
 
+static inline void pfm_arch_condition_intr_pmds(struct pfm_context *ctx,
+                                               struct pfm_event_set *set)
+{}
+
 static inline void pfm_arch_serialize(void)
 {}
 
Index: linux-2.6/include/asm-sparc64/perfmon_kern.h
===================================================================
--- linux-2.6.orig/include/asm-sparc64/perfmon_kern.h   2008-07-22 
13:45:10.000000000 -0500
+++ linux-2.6/include/asm-sparc64/perfmon_kern.h        2008-07-22 
17:24:31.000000000 -0500
@@ -19,6 +19,10 @@
 {
 }
 
+static inline void pfm_arch_condition_intr_pmds(struct pfm_context *ctx,
+                                               struct pfm_event_set *set)
+{}
+
 static inline void pfm_arch_serialize(void)
 {
 }
Index: linux-2.6/include/asm-x86/perfmon_kern.h
===================================================================
--- linux-2.6.orig/include/asm-x86/perfmon_kern.h       2008-07-22 
13:45:11.000000000 -0500
+++ linux-2.6/include/asm-x86/perfmon_kern.h    2008-07-22 17:27:02.000000000 
-0500
@@ -450,6 +450,16 @@
 }
 
 /*
+ * pfm_arch_condition_intr_pmds - alter the pmds in such a way that they
+ * will not cause cause interrupts when unused.
+ *
+ * This is a nop on x86
+ */
+static inline void pfm_arch_condition_intr_pmds(struct pfm_context *ctx,
+                                               struct pfm_event_set *set)
+{}
+
+/*
  * functions implemented in arch/x86/perfmon/perfmon.c
  */
 int  pfm_arch_init(void);
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
perfmon2-devel mailing list
perfmon2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/perfmon2-devel

Reply via email to