Commit c34d5588 authored by Stéphane Eranian's avatar Stéphane Eranian Committed by David Mosberger

[PATCH] ia64: perfmon update

- Cleanup the read/write check routines for pfm_write_pmcs,
  pfm_write_pmds, pfm_read_pmds.

- Autodetect the PMU model. No need to have the kernel compiled for
  Itanium, HP Simulator, or Itanium2. The support for all PMU models
  is included.  Probing is based on processor family and
  platform_name, if necessary.  With this patch, it is possible to use
  an Itanium2 compiled kernel on an Itanium 1 system and get perfmon
  to work.

- Removed remaining dependency on CONFIG_MCKINLEY by adding a new
  field (flags) to pmu_config_t.  Update /proc/perfmon to show the new
  field.

- Fixed a bug in the Itanium2 pmc_ita2_write_check() where an inactive
  PMC13 would be considered active.
parent 7810c5f1
This diff is collapsed.
...@@ -6,13 +6,6 @@ ...@@ -6,13 +6,6 @@
* Stephane Eranian <eranian@hpl.hp.com> * Stephane Eranian <eranian@hpl.hp.com>
*/ */
#define RDEP(x) (1UL<<(x))
#if defined(CONFIG_ITANIUM) || defined (CONFIG_MCKINLEY)
#error "This file should not be used when CONFIG_ITANIUM or CONFIG_MCKINLEY is defined"
#endif
static pfm_reg_desc_t pfm_gen_pmc_desc[PMU_MAX_PMCS]={ static pfm_reg_desc_t pfm_gen_pmc_desc[PMU_MAX_PMCS]={
/* pmc0 */ { PFM_REG_CONTROL , 0, 0x1UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc0 */ { PFM_REG_CONTROL , 0, 0x1UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc1 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc1 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
...@@ -40,10 +33,9 @@ static pfm_reg_desc_t pfm_gen_pmd_desc[PMU_MAX_PMDS]={ ...@@ -40,10 +33,9 @@ static pfm_reg_desc_t pfm_gen_pmd_desc[PMU_MAX_PMDS]={
/* /*
* impl_pmcs, impl_pmds are computed at runtime to minimize errors! * impl_pmcs, impl_pmds are computed at runtime to minimize errors!
*/ */
static pmu_config_t pmu_conf={ static pmu_config_t pmu_conf_gen={
.pmu_name = "Generic", .pmu_name = "Generic",
.pmu_family = 0xff, /* any */ .pmu_family = 0xff, /* any */
.enabled = 0,
.ovfl_val = (1UL << 32) - 1, .ovfl_val = (1UL << 32) - 1,
.num_ibrs = 0, /* does not use */ .num_ibrs = 0, /* does not use */
.num_dbrs = 0, /* does not use */ .num_dbrs = 0, /* does not use */
......
...@@ -14,12 +14,6 @@ ...@@ -14,12 +14,6 @@
* they do not count anything. But you can read/write them. * they do not count anything. But you can read/write them.
*/ */
#define RDEP(x) (1UL<<(x))
#ifndef CONFIG_IA64_HP_SIM
#error "This file should only be included for the HP Simulator"
#endif
static pfm_reg_desc_t pfm_hpsim_pmc_desc[PMU_MAX_PMCS]={ static pfm_reg_desc_t pfm_hpsim_pmc_desc[PMU_MAX_PMCS]={
/* pmc0 */ { PFM_REG_CONTROL , 0, 0x1UL, -1UL, NULL, NULL, {0UL, 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc0 */ { PFM_REG_CONTROL , 0, 0x1UL, -1UL, NULL, NULL, {0UL, 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
/* pmc1 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL, 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc1 */ { PFM_REG_CONTROL , 0, 0x0UL, -1UL, NULL, NULL, {0UL, 0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
...@@ -60,16 +54,22 @@ static pfm_reg_desc_t pfm_hpsim_pmd_desc[PMU_MAX_PMDS]={ ...@@ -60,16 +54,22 @@ static pfm_reg_desc_t pfm_hpsim_pmd_desc[PMU_MAX_PMDS]={
{ PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */ { PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */
}; };
static int
pfm_hpsim_probe(void)
{
return local_cpu_data->family == 0x7 && ia64_platform_is("hpsim") ? 0 : -1;
}
/* /*
* impl_pmcs, impl_pmds are computed at runtime to minimize errors! * impl_pmcs, impl_pmds are computed at runtime to minimize errors!
*/ */
static pmu_config_t pmu_conf={ static pmu_config_t pmu_conf_hpsim={
.pmu_name = "hpsim", .pmu_name = "hpsim",
.pmu_family = 0x7, /* ski emulator reports as Itanium */ .pmu_family = 0x7, /* ski emulator reports as Itanium */
.enabled = 0,
.ovfl_val = (1UL << 32) - 1, .ovfl_val = (1UL << 32) - 1,
.num_ibrs = 0, /* does not use */ .num_ibrs = 0, /* does not use */
.num_dbrs = 0, /* does not use */ .num_dbrs = 0, /* does not use */
.pmd_desc = pfm_hpsim_pmd_desc, .pmd_desc = pfm_hpsim_pmd_desc,
.pmc_desc = pfm_hpsim_pmc_desc .pmc_desc = pfm_hpsim_pmc_desc,
.probe = pfm_hpsim_probe
}; };
...@@ -5,15 +5,7 @@ ...@@ -5,15 +5,7 @@
* Copyright (C) 2002-2003 Hewlett Packard Co * Copyright (C) 2002-2003 Hewlett Packard Co
* Stephane Eranian <eranian@hpl.hp.com> * Stephane Eranian <eranian@hpl.hp.com>
*/ */
#define RDEP(x) (1UL<<(x))
#ifndef CONFIG_ITANIUM
#error "This file is only valid when CONFIG_ITANIUM is defined"
#endif
static int pfm_ita_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs); static int pfm_ita_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs);
static int pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs);
static pfm_reg_desc_t pfm_ita_pmc_desc[PMU_MAX_PMCS]={ static pfm_reg_desc_t pfm_ita_pmc_desc[PMU_MAX_PMCS]={
/* pmc0 */ { PFM_REG_CONTROL , 0, 0x1UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc0 */ { PFM_REG_CONTROL , 0, 0x1UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
...@@ -55,31 +47,28 @@ static pfm_reg_desc_t pfm_ita_pmd_desc[PMU_MAX_PMDS]={ ...@@ -55,31 +47,28 @@ static pfm_reg_desc_t pfm_ita_pmd_desc[PMU_MAX_PMDS]={
{ PFM_REG_END , 0, 0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */ { PFM_REG_END , 0, 0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */
}; };
/* static int
* impl_pmcs, impl_pmds are computed at runtime to minimize errors! pfm_ita_probe(void)
*/ {
static pmu_config_t pmu_conf={ return local_cpu_data->family == 0x7 && !ia64_platform_is("hpsim") ? 0 : -1;
.pmu_name = "Itanium", }
.pmu_family = 0x7,
.enabled = 0,
.ovfl_val = (1UL << 32) - 1,
.pmd_desc = pfm_ita_pmd_desc,
.pmc_desc = pfm_ita_pmc_desc,
.num_ibrs = 8,
.num_dbrs = 8,
.use_rr_dbregs = 1 /* debug register are use for range retrictions */
};
static int static int
pfm_ita_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs) pfm_ita_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs)
{ {
int ret; int ret;
int is_loaded;
/* sanitfy check */
if (ctx == NULL) return -EINVAL;
is_loaded = ctx->ctx_state == PFM_CTX_LOADED || ctx->ctx_state == PFM_CTX_MASKED;
/* /*
* we must clear the (instruction) debug registers if pmc13.ta bit is cleared * we must clear the (instruction) debug registers if pmc13.ta bit is cleared
* before they are written (fl_using_dbreg==0) to avoid picking up stale information. * before they are written (fl_using_dbreg==0) to avoid picking up stale information.
*/ */
if (cnum == 13 && ((*val & 0x1) == 0UL) && ctx->ctx_fl_using_dbreg == 0) { if (cnum == 13 && is_loaded && ((*val & 0x1) == 0UL) && ctx->ctx_fl_using_dbreg == 0) {
DPRINT(("pmc[%d]=0x%lx has active pmc13.ta cleared, clearing ibr\n", cnum, *val)); DPRINT(("pmc[%d]=0x%lx has active pmc13.ta cleared, clearing ibr\n", cnum, *val));
...@@ -98,7 +87,7 @@ pfm_ita_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu ...@@ -98,7 +87,7 @@ pfm_ita_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu
* we must clear the (data) debug registers if pmc11.pt bit is cleared * we must clear the (data) debug registers if pmc11.pt bit is cleared
* before they are written (fl_using_dbreg==0) to avoid picking up stale information. * before they are written (fl_using_dbreg==0) to avoid picking up stale information.
*/ */
if (cnum == 11 && ((*val >> 28)& 0x1) == 0 && ctx->ctx_fl_using_dbreg == 0) { if (cnum == 11 && is_loaded && ((*val >> 28)& 0x1) == 0 && ctx->ctx_fl_using_dbreg == 0) {
DPRINT(("pmc[%d]=0x%lx has active pmc11.pt cleared, clearing dbr\n", cnum, *val)); DPRINT(("pmc[%d]=0x%lx has active pmc11.pt cleared, clearing dbr\n", cnum, *val));
...@@ -115,3 +104,19 @@ pfm_ita_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu ...@@ -115,3 +104,19 @@ pfm_ita_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu
return 0; return 0;
} }
/*
* impl_pmcs, impl_pmds are computed at runtime to minimize errors!
*/
static pmu_config_t pmu_conf_ita={
.pmu_name = "Itanium",
.pmu_family = 0x7,
.ovfl_val = (1UL << 32) - 1,
.pmd_desc = pfm_ita_pmd_desc,
.pmc_desc = pfm_ita_pmc_desc,
.num_ibrs = 8,
.num_dbrs = 8,
.use_rr_dbregs = 1, /* debug register are use for range retrictions */
.probe = pfm_ita_probe
};
...@@ -5,15 +5,7 @@ ...@@ -5,15 +5,7 @@
* Copyright (C) 2002-2003 Hewlett Packard Co * Copyright (C) 2002-2003 Hewlett Packard Co
* Stephane Eranian <eranian@hpl.hp.com> * Stephane Eranian <eranian@hpl.hp.com>
*/ */
#define RDEP(x) (1UL<<(x))
#ifndef CONFIG_MCKINLEY
#error "This file is only valid when CONFIG_MCKINLEY is defined"
#endif
static int pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs); static int pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnum, unsigned long *val, struct pt_regs *regs);
static int pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs);
static pfm_reg_desc_t pfm_mck_pmc_desc[PMU_MAX_PMCS]={ static pfm_reg_desc_t pfm_mck_pmc_desc[PMU_MAX_PMCS]={
/* pmc0 */ { PFM_REG_CONTROL , 0, 0x1UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}}, /* pmc0 */ { PFM_REG_CONTROL , 0, 0x1UL, -1UL, NULL, NULL, {0UL,0UL, 0UL, 0UL}, {0UL,0UL, 0UL, 0UL}},
...@@ -57,21 +49,6 @@ static pfm_reg_desc_t pfm_mck_pmd_desc[PMU_MAX_PMDS]={ ...@@ -57,21 +49,6 @@ static pfm_reg_desc_t pfm_mck_pmd_desc[PMU_MAX_PMDS]={
{ PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */ { PFM_REG_END , 0, 0x0UL, -1UL, NULL, NULL, {0,}, {0,}}, /* end marker */
}; };
/*
* impl_pmcs, impl_pmds are computed at runtime to minimize errors!
*/
static pmu_config_t pmu_conf={
.pmu_name = "Itanium 2",
.pmu_family = 0x1f,
.enabled = 0,
.ovfl_val = (1UL << 47) - 1,
.pmd_desc = pfm_mck_pmd_desc,
.pmc_desc = pfm_mck_pmc_desc,
.num_ibrs = 8,
.num_dbrs = 8,
.use_rr_dbregs = 1 /* debug register are use for range retrictions */
};
/* /*
* PMC reserved fields must have their power-up values preserved * PMC reserved fields must have their power-up values preserved
*/ */
...@@ -120,12 +97,11 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu ...@@ -120,12 +97,11 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu
* one of the pmc13.cfg_dbrpXX field is different from 0x3 * one of the pmc13.cfg_dbrpXX field is different from 0x3
* AND * AND
* at the corresponding pmc13.ena_dbrpXX is set. * at the corresponding pmc13.ena_dbrpXX is set.
*
* For now, we just check on cfg_dbrXX != 0x3.
*/ */
DPRINT(("cnum=%u val=0x%lx, using_dbreg=%d loaded=%d\n", cnum, *val, ctx->ctx_fl_using_dbreg, is_loaded)); DPRINT(("cnum=%u val=0x%lx, using_dbreg=%d loaded=%d\n", cnum, *val, ctx->ctx_fl_using_dbreg, is_loaded));
if (cnum == 13 && is_loaded && ((*val & 0x18181818UL) != 0x18181818UL) && ctx->ctx_fl_using_dbreg == 0) { if (cnum == 13 && is_loaded
&& (*val & 0x1e00000000000UL) && (*val & 0x18181818UL) != 0x18181818UL && ctx->ctx_fl_using_dbreg == 0) {
DPRINT(("pmc[%d]=0x%lx has active pmc13 settings, clearing dbr\n", cnum, *val)); DPRINT(("pmc[%d]=0x%lx has active pmc13 settings, clearing dbr\n", cnum, *val));
...@@ -192,3 +168,20 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu ...@@ -192,3 +168,20 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu
return ret ? -EINVAL : 0; return ret ? -EINVAL : 0;
} }
/*
* impl_pmcs, impl_pmds are computed at runtime to minimize errors!
*/
static pmu_config_t pmu_conf_mck={
.pmu_name = "Itanium 2",
.pmu_family = 0x1f,
.flags = PFM_PMU_IRQ_RESEND,
.ovfl_val = (1UL << 47) - 1,
.pmd_desc = pfm_mck_pmd_desc,
.pmc_desc = pfm_mck_pmc_desc,
.num_ibrs = 8,
.num_dbrs = 8,
.use_rr_dbregs = 1 /* debug register are use for range retrictions */
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment