Takashi,

This patch does not apply cleanly on my perfmon_cell.c.
Could you check against the one in the GIT tree?

Also, is you mailer somehow formatting to 80-columns?
Some lines of the patch are malformed due to insertion
of carriage return.

On Thu, Nov 01, 2007 at 04:42:26PM +0900, TakashiYamamoto wrote:
> Hello,
> 
> Here is the Cell PPU HW thread depended event support.
> Kevin-san, Azuma-san, please review it!
> 
> Takashi Yamamoto.
> 
> -----------------------------------------------------------------
> Cell PPU IU(Instruction Unit)/XU(Execution Unit) event support in 
> per-thread(task) mode.
> 
> In per-thread mode, the PPU IU/XU events should be measured 
> while the target SW thread(task) runs on the target HW thread. 
> To realize that, the counter enable bit of the pmX_control PMC is
> manipulated in pfm_cell_restore_pmcs().
> 
> Signed-off-by: Takashi Yamamoto <TakashiA.Yamamoto at jp.sony.com>
> ---
>  arch/powerpc/perfmon/perfmon_cell.c |  204
> +++++++++++++++++++++++++++++-------
>  1 file changed, 165 insertions(+), 39 deletions(-)
> 
> Index: linux-2.6/arch/powerpc/perfmon/perfmon_cell.c
> ===================================================================
> --- linux-2.6.orig/arch/powerpc/perfmon/perfmon_cell.c
> +++ linux-2.6/arch/powerpc/perfmon/perfmon_cell.c
> @@ -18,7 +18,7 @@
>   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>   * General Public License for more details.
>   *
> - * You should have received a copy of the GNU General Public License
> + * You should have received a copy of the GNU XSGeneral Public License
>   * along with this program; if not, write to the Free Software
>   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
>   * 02111-1307 USA
> @@ -96,7 +96,9 @@ static struct pfm_regmap_desc pfm_cell_p
>  };
>  #define PFM_PM_NUM_PMCS      ARRAY_SIZE(pfm_cell_pmc_desc)
>  
> -#define CELL_PMC_PM_STATUS 20
> +#define CELL_PMC_GROUP_CONTROL    16
> +#define CELL_PMC_PM_STATUS        20
> +
>  /*
>   * Mapping from Perfmon logical data counters to Cell hardware counters.
>   */
> @@ -112,6 +114,19 @@ static struct pfm_regmap_desc pfm_cell_p
>  };
>  #define PFM_PM_NUM_PMDS      ARRAY_SIZE(pfm_cell_pmd_desc)
>  
> +#define PFM_EVENT_PMC_BUS_WORD(x)      (((x) >> 48) & 0x00ff)
> +#define PFM_EVENT_PMC_FULL_SIGNAL_NUMBER(x) ((x) & 0xffffffff)
> +#define PFM_EVENT_PMC_SIGNAL_GROUP(x) (((x) & 0xffffffff) / 100)
> +#define PFM_PM_CTR_INPUT_MUX_BIT(pm07_control) (((pm07_control) >> 26) &
> 0x1f)
> +#define PFM_PM_CTR_INPUT_MUX_GROUP_INDEX(pm07_control) ((pm07_control) >>
> 31)
> +#define PFM_GROUP_CONTROL_GROUP0_WORD(grp_ctrl) ((grp_ctrl) >> 30)
> +#define PFM_GROUP_CONTROL_GROUP1_WORD(grp_ctrl) (((grp_ctrl) >> 28) & 0x3)
> +#define PFM_NUM_OF_GROUPS 2
> +#define PFM_PPU_IU1_THREAD1_BASE_BIT 19
> +#define PFM_PPU_XU_THREAD1_BASE_BIT  16
> +#define PFM_COUNTER_CTRL_PMC_PPU_THREAD0 0x100000000ULL
> +#define PFM_COUNTER_CTRL_PMC_PPU_THREAD1 0x200000000ULL
> +
>  /*
>   * Debug-bus signal handling.
>   *
> @@ -691,6 +706,72 @@ static void pfm_cell_disable_counters(st
>               reset_signals(smp_processor_id());
>  }
>  
> +/*
> + * Return the thread id of the specified ppu signal.
> + */
> +static inline u32 get_target_ppu_thread_id(u32 group, u32 bit)
> +{
> +     if ((group == SIG_GROUP_PPU_IU1 &&
> +          bit < PFM_PPU_IU1_THREAD1_BASE_BIT) ||
> +         (group == SIG_GROUP_PPU_XU &&
> +          bit < PFM_PPU_XU_THREAD1_BASE_BIT))
> +             return 0;
> +     else
> +             return 1;
> +}
> +
> +/*
> + * Return whether the specified counter is for PPU signal group.
> + */
> +static inline int is_counter_for_ppu_sig_grp(u32 counter_control, u32
> sig_grp)
> +{
> +     if (!(counter_control & CBE_PM_CTR_INPUT_CONTROL) &&
> +         (counter_control & CBE_PM_CTR_ENABLE) &&
> +         ((sig_grp == SIG_GROUP_PPU_IU1) || (sig_grp ==
> SIG_GROUP_PPU_XU)))
> +             return 1;
> +     else
> +             return 0;
> +}
> +
> +/*
> + * Search ppu signal groups.
> + */
> +static int get_ppu_signal_groups(struct pfm_event_set *set,
> +                              u32 *ppu_sig_grp0, u32 *ppu_sig_grp1)
> +{
> +     u64 pm_event, *used_pmcs = set->used_pmcs;
> +     int i, j;
> +     u32 grp0_wd, grp1_wd, wd, sig_grp;
> +
> +     *ppu_sig_grp0 = 0;
> +     *ppu_sig_grp1 = 0;
> +     grp0_wd = PFM_GROUP_CONTROL_GROUP0_WORD(
> +             set->pmcs[CELL_PMC_GROUP_CONTROL]);
> +     grp1_wd = PFM_GROUP_CONTROL_GROUP1_WORD(
> +             set->pmcs[CELL_PMC_GROUP_CONTROL]);
> +
> +     for (i = 0, j = 0; (i < NR_CTRS) && (j < PFM_NUM_OF_GROUPS); i++) {
> +             if (test_bit(i + NR_CTRS, used_pmcs)) {
> +                     pm_event = set->pmcs[i + NR_CTRS];
> +                     wd = PFM_EVENT_PMC_BUS_WORD(pm_event);
> +                     sig_grp = PFM_EVENT_PMC_SIGNAL_GROUP(pm_event);
> +                     if ((sig_grp == SIG_GROUP_PPU_IU1) ||
> +                         (sig_grp == SIG_GROUP_PPU_XU)) {
> +
> +                             if (wd == grp0_wd && *ppu_sig_grp0 == 0) {
> +                                     *ppu_sig_grp0 = sig_grp;
> +                                     j++;
> +                             } else if (wd == grp1_wd &&
> +                                        *ppu_sig_grp1 == 0) {
> +                                     *ppu_sig_grp1 = sig_grp;
> +                                     j++;
> +                             }
> +                     }
> +             }
> +     }
> +     return j;
> +}
> +
>  /**
>   * pfm_cell_restore_pmcs
>   *
> @@ -699,56 +780,54 @@ static void pfm_cell_disable_counters(st
>   * individually (as is done in other architectures), but that results in
>   * multiple RTAS calls. As an optimization, we will setup the RTAS argument
>   * array so we can do all event-control registers in one RTAS call.
> + *
> + * In per-thread mode,
> + * The counter enable bit of the pmX_control PMC is enabled while the
> target
> + * task runs on the target HW thread.
>   **/
>  void pfm_cell_restore_pmcs(struct pfm_event_set *set)
>  {
> -     struct cell_rtas_arg signals[NR_CTRS];
> -     u64 value, *used_pmcs = set->used_pmcs;
> -     int i, rc, num_used = 0, cpu = smp_processor_id();
> -     s32 signal_number;
> +     u64 ctr_ctrl;
> +     u64 *used_pmcs = set->used_pmcs;
> +     int i;
> +     int cpu = smp_processor_id();
> +     u32 current_th_id;
>       struct pfm_cell_platform_pmu_info *info =
>               ((struct pfm_arch_pmu_info *)
>                (pfm_pmu_conf->arch_info))->platform_info;
>  
> -     memset(signals, 0, sizeof(signals));
> -
>       for (i = 0; i < NR_CTRS; i++) {
> -             /* Write the per-counter control register. If the PMC is not
> -              * in use, then it will simply clear the register, which
> will
> -              * disable the associated counter.
> -              */
> -             info->write_pm07_control(cpu, i, set->pmcs[i]);
> +             ctr_ctrl = set->pmcs[i];
>  
> -             /* Set up the next RTAS array entry for this counter. Only
> -              * include pm07_event registers that are in use by this set
> -              * so the RTAS call doesn't have to process blank array
> entries.
> -              */
> -             if (!test_bit(i + NR_CTRS, used_pmcs)) {
> -                     continue;
> -             }
> +             if (ctr_ctrl & PFM_COUNTER_CTRL_PMC_PPU_THREAD0) {
> +                     current_th_id = info->get_hw_thread_id(cpu);
>  
> -             value = set->pmcs[i + NR_CTRS];
> -             signal_number = RTAS_SIGNAL_NUMBER(value);
> -             if (!signal_number) {
> -                     /* Don't include counters that are counting cycles.
> */
> -                     continue;
> +                     /*
> +                      * Set the counter enable bit down if the current
> +                      * HW thread is NOT 0
> +                      **/
> +                     if (current_th_id)
> +                             ctr_ctrl = ctr_ctrl & ~CBE_PM_CTR_ENABLE;
> +
> +             } else if (ctr_ctrl & PFM_COUNTER_CTRL_PMC_PPU_THREAD1) {
> +                     current_th_id = info->get_hw_thread_id(cpu);
> +
> +                     /*
> +                      * Set the counter enable bit down if the current
> +                      * HW thread is 0
> +                      **/
> +                     if (!current_th_id)
> +                             ctr_ctrl = ctr_ctrl & ~CBE_PM_CTR_ENABLE;
>               }
>  
> -             signals[num_used].cpu = RTAS_CPU(cpu);
> -             signals[num_used].sub_unit = RTAS_SUB_UNIT(value);
> -             signals[num_used].bus_word = 1 << RTAS_BUS_WORD(value);
> -             signals[num_used].signal_group = signal_number / 100;
> -             signals[num_used].bit = signal_number % 100;
> -             num_used++;
> -     }
> -
> -     rc = activate_signals(signals, num_used);
> -     if (rc) {
> -             PFM_WARN("Error calling activate_signal(): %d\n", rc);
> -             /* FIX: We will also need this routine to be able to return
> -              * an error if Stephane agrees to change pfm_arch_write_pmc
> -              * to return an error.
> +             /* Write the per-counter control register. If the PMC is not
> +              * in use, then it will simply clear the register, which
> will
> +              * disable the associated counter.
>                */
> +             info->write_pm07_control(cpu, i, ctr_ctrl);
> +
> +             if (test_bit(i + NR_CTRS, used_pmcs))
> +                     write_pm07_event(cpu, 0, set->pmcs[i + NR_CTRS]);
>       }
>  
>       /* Write all the global PMCs. Need to call pfm_cell_write_pmc()
> @@ -760,6 +839,52 @@ void pfm_cell_restore_pmcs(struct pfm_ev
>  }
>  
>  /**
> + * pfm_cell_load_context
> + *
> + * In per-thread mode,
> + *  The pmX_control PMCs which are used for PPU IU/XU event are marked with
> + *  the thread id(PFM_COUNTER_CTRL_PMC_PPU_THREAD0/THREAD1).
> + **/
> +static int pfm_cell_load_context(struct pfm_context *ctx,
> +                              struct pfm_event_set *set,
> +                              struct task_struct *task)
> +{
> +     int i;
> +     u32 ppu_sig_grp[PFM_NUM_OF_GROUPS] = {SIG_GROUP_NONE,
> SIG_GROUP_NONE};
> +     u32 bit;
> +     int grp_index;
> +     u32 target_th_id;
> +     int ppu_sig_num = 0;
> +
> +     if (!ctx->flags.system)
> +             ppu_sig_num = get_ppu_signal_groups(set, &ppu_sig_grp[0],
> +                                                 &ppu_sig_grp[1]);
> +
> +     for (i = 0; i < NR_CTRS; i++) {
> +             grp_index = PFM_PM_CTR_INPUT_MUX_GROUP_INDEX(set->pmcs[i]);
> +             if (ppu_sig_num &&
> +                 (ppu_sig_grp[grp_index] != SIG_GROUP_NONE) &&
> +                 is_counter_for_ppu_sig_grp(set->pmcs[i],
> +                                            ppu_sig_grp[grp_index])) {
> +
> +                     bit = PFM_PM_CTR_INPUT_MUX_BIT(set->pmcs[i]);
> +                     target_th_id = get_target_ppu_thread_id(
> +                             ppu_sig_grp[grp_index], bit);
> +                     if (!target_th_id)
> +                             set->pmcs[i] |=
> +                                     PFM_COUNTER_CTRL_PMC_PPU_THREAD0;
> +                     else
> +                             set->pmcs[i] |=
> +                                     PFM_COUNTER_CTRL_PMC_PPU_THREAD1;
> +                     PFM_DBG("mark ctr:%d target_thread:%d",
> +                             i, target_th_id);
> +             }
> +     }
> +
> +     return 0;
> +}
> +
> +/**
>   * pfm_cell_unload_context
>   *
>   * For system-wide contexts and self-monitored contexts, make the RTAS call
> @@ -1026,6 +1151,7 @@ static struct pfm_arch_pmu_info pfm_cell
>       .get_ovfl_pmds    = pfm_cell_get_ovfl_pmds,
>       .restore_pmcs     = pfm_cell_restore_pmcs,
>       .ctxswout_thread  = pfm_cell_ctxswout_thread,
> +     .load_context     = pfm_cell_load_context,
>       .unload_context   = pfm_cell_unload_context,
>  };
> 
> 
> _______________________________________________
> perfmon mailing list
> [email protected]
> http://www.hpl.hp.com/hosted/linux/mail-archives/perfmon/

-- 

-Stephane
_______________________________________________
perfmon mailing list
[email protected]
http://www.hpl.hp.com/hosted/linux/mail-archives/perfmon/

Reply via email to