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