Make the RTAS call to reset the debug-bus signals any time a context is
removed from the PMU. This way other contexts don't need to worry about
what state the bus is in when they get loaded onto the PMU.

For self-monitored or system-wide contexts, reset the bus during the
unload-context call. Externally monitored contexts don't need to call the
bus-reset, since they must already have been context-switched off the CPU
(or have already exited).

For self-monitored or externally-monitored contexts, reset the bus when the
monitored thread is context-switched out. System-wide contexts are not
attached to a specific process, so they never get switched out.

Signed-off-by: Kevin Corry <[EMAIL PROTECTED]>
Signed-off-by: Carl Love <[EMAIL PROTECTED]>

Index: linux-2.6.21-perfmon1/arch/powerpc/perfmon/perfmon_cell.c
===================================================================
--- linux-2.6.21-perfmon1.orig/arch/powerpc/perfmon/perfmon_cell.c
+++ linux-2.6.21-perfmon1/arch/powerpc/perfmon/perfmon_cell.c
@@ -137,9 +137,6 @@ struct cell_rtas_arg {
  *
  * Set up the RTAS arguments for a RESET command. The buffer will be only
  * the first entry in the rtas_args[cpu].signal[] array.
- *
- * FIX: When are we going to call this routine? Before each context-switch-out?
- *      After each context-switch-in?
  **/
 static int rtas_reset_signals(u32 cpu)
 {
@@ -357,6 +354,38 @@ void pfm_cell_restore_pmcs(struct pfm_ev
 }
 
 /**
+ * pfm_cell_unload_context
+ *
+ * For system-wide contexts and self-monitored contexts, make the RTAS call
+ * to reset the debug-bus signals.
+ *
+ * For non-self-monitored contexts, the monitored thread will already have
+ * been taken off the CPU and we don't need to do anything additional.
+ **/
+static int pfm_cell_unload_context(struct pfm_context *ctx,
+                                  struct task_struct *task)
+{
+       if (task == current || ctx->flags.system) {
+               rtas_reset_signals(smp_processor_id());
+       }
+       return 0;
+}
+
+/**
+ * pfm_cell_ctxswout_thread
+ *
+ * When a monitored thread is switched out (self-monitored or externally
+ * monitored) we need to reset the debug-bus signals so the next context that
+ * gets switched in can start from a clean set of signals.
+ **/
+int pfm_cell_ctxswout_thread(struct task_struct *task,
+                            struct pfm_context *ctx, struct pfm_event_set *set)
+{
+       rtas_reset_signals(smp_processor_id());
+       return 0;
+}
+
+/**
  * pfm_cell_get_ovfl_pmds
  *
  * Determine which counters in this set have overflowed and fill in the
@@ -506,6 +535,7 @@ static struct pfm_arch_pmu_info pfm_cell
        .irq_handler      = pfm_cell_irq_handler,
        .get_ovfl_pmds    = pfm_cell_get_ovfl_pmds,
        .restore_pmcs     = pfm_cell_restore_pmcs,
+       .ctxswout_thread  = pfm_cell_ctxswout_thread,
 };
 
 static struct pfm_pmu_config pfm_cell_pmu_conf = {
@@ -516,6 +546,7 @@ static struct pfm_pmu_config pfm_cell_pm
        .pmc_desc = pfm_cell_pmc_desc,
        .num_pmc_entries = PFM_PM_NUM_PMCS,
        .num_pmd_entries = PFM_PM_NUM_PMDS,
+       .unload_context = pfm_cell_unload_context,
        .probe_pmu  = pfm_cell_probe_pmu,
        .arch_info = &pfm_cell_pmu_info,
        .flags = PFM_PMU_BUILTIN_FLAG,
Index: linux-2.6.21-perfmon1/include/asm-powerpc/perfmon.h
===================================================================
--- linux-2.6.21-perfmon1.orig/include/asm-powerpc/perfmon.h
+++ linux-2.6.21-perfmon1/include/asm-powerpc/perfmon.h
@@ -57,9 +57,16 @@ struct pfm_arch_pmu_info {
        void (*get_ovfl_pmds)(struct pfm_context *ctx,
                              struct pfm_event_set *set);
 
-       /* These two are optional. */
+       /* The following routines are optional. */
        void (*restore_pmcs)(struct pfm_event_set *set);
        void (*restore_pmds)(struct pfm_event_set *set);
+
+       int  (*ctxswout_thread)(struct task_struct *task,
+                               struct pfm_context *ctx,
+                               struct pfm_event_set *set);
+       void (*ctxswin_thread)(struct task_struct *task,
+                              struct pfm_context *ctx,
+                              struct pfm_event_set *set);
 };
 
 #ifdef CONFIG_PPC32
Index: linux-2.6.21-perfmon1/arch/powerpc/perfmon/perfmon.c
===================================================================
--- linux-2.6.21-perfmon1.orig/arch/powerpc/perfmon/perfmon.c
+++ linux-2.6.21-perfmon1/arch/powerpc/perfmon/perfmon.c
@@ -54,6 +54,8 @@ static void pfm_stop_active(struct task_
 int pfm_arch_ctxswout_thread(struct task_struct *task,
                             struct pfm_context *ctx, struct pfm_event_set *set)
 {
+       struct pfm_arch_pmu_info *arch_info = pfm_pmu_conf->arch_info;
+
        /*
         * disable lazy restore of PMC registers.
         */
@@ -61,6 +63,10 @@ int pfm_arch_ctxswout_thread(struct task
 
        pfm_stop_active(task, ctx, set);
 
+       if (arch_info->ctxswout_thread) {
+               arch_info->ctxswout_thread(task, ctx, set);
+       }
+
        return 1;
 }
 
@@ -71,8 +77,13 @@ void pfm_arch_ctxswin_thread(struct task
                             struct pfm_context *ctx, struct pfm_event_set *set)
 {
        struct pfm_arch_pmu_info *arch_info = pfm_pmu_conf->arch_info;
+
        BUG_ON(!arch_info->enable_counters);
        arch_info->enable_counters(set);
+
+       if (arch_info->ctxswin_thread) {
+               arch_info->ctxswin_thread(task, ctx, set);
+       }
 }
 
 /*
Index: linux-2.6.21-perfmon1/arch/x86_64/perfmon/perfmon_k8.c
===================================================================
--- linux-2.6.21-perfmon1.orig/arch/x86_64/perfmon/perfmon_k8.c
+++ linux-2.6.21-perfmon1/arch/x86_64/perfmon/perfmon_k8.c
@@ -166,7 +166,8 @@ static int pfm_k8_pmc_write_check(struct
  * invoked on pfm_load_context().
  * context is locked, interrupts are masked
  */
-static int pfm_k8_load_context(struct pfm_context *ctx)
+static int pfm_k8_load_context(struct pfm_context *ctx,
+                              struct task_struct *task)
 {
        struct pfm_event_set *set;
        unsigned int i, n;
@@ -192,7 +193,8 @@ found:
 /*
  * invoked on pfm_unload_context()
  */
-static int pfm_k8_unload_context(struct pfm_context *ctx)
+static int pfm_k8_unload_context(struct pfm_context *ctx,
+                                struct task_struct *task)
 {
        struct pfm_context **entry, *old;
        int proc_id;
Index: linux-2.6.21-perfmon1/include/linux/perfmon_pmu.h
===================================================================
--- linux-2.6.21-perfmon1.orig/include/linux/perfmon_pmu.h
+++ linux-2.6.21-perfmon1/include/linux/perfmon_pmu.h
@@ -91,7 +91,8 @@ typedef int (*pfm_pmd_check_t)(struct pf
 typedef u64 (*pfm_pmd_sread_t)(struct pfm_context *ctx, unsigned int cnum);
 typedef void (*pfm_pmd_swrite_t)(struct pfm_context *ctx, unsigned int cnum, 
u64 val);
 
-typedef int (*pfm_check_session_t)(struct pfm_context *ctx);
+typedef int (*pfm_check_session_t)(struct pfm_context *ctx,
+                                  struct task_struct *task);
 
 /*
  * _pfm_pmu_config is for perfmon core/arch specific use only.
Index: linux-2.6.21-perfmon1/perfmon/perfmon.c
===================================================================
--- linux-2.6.21-perfmon1.orig/perfmon/perfmon.c
+++ linux-2.6.21-perfmon1/perfmon/perfmon.c
@@ -1293,7 +1293,7 @@ int __pfm_load_context(struct pfm_contex
         * invoke PMU-model specific load context handler
         */
        if (pfm_pmu_conf->load_context) {
-               ret = pfm_pmu_conf->load_context(ctx);
+               ret = pfm_pmu_conf->load_context(ctx, ctx->task);
                if (ret)
                        goto error_arch_loaded;
        }
@@ -1379,7 +1379,7 @@ int __pfm_load_context(struct pfm_contex
 
 error:
        if (pfm_pmu_conf->unload_context)
-               ret = pfm_pmu_conf->unload_context(ctx);
+               ret = pfm_pmu_conf->unload_context(ctx, ctx->task);
 error_arch_loaded:
        pfm_arch_unload_context(ctx, task);
 error_noload:
@@ -1468,7 +1468,7 @@ int __pfm_unload_context(struct pfm_cont
        *can_release = 1;
 
        if (pfm_pmu_conf->unload_context)
-               pfm_pmu_conf->unload_context(ctx);
+               pfm_pmu_conf->unload_context(ctx, task);
 
        return 0;
 }
_______________________________________________
perfmon mailing list
[email protected]
http://www.hpl.hp.com/hosted/linux/mail-archives/perfmon/

Reply via email to