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

[PATCH] ia64: perfmon fix

This patch allows users to set the PMC to their default value, even
though the value might conflict with the type of monitoring
session. This is fine because default values ensure the monitor is not
active.
parent 6dc0d7f6
...@@ -1364,8 +1364,9 @@ pfm_write_pmcs(struct task_struct *task, pfm_context_t *ctx, void *arg, int coun ...@@ -1364,8 +1364,9 @@ pfm_write_pmcs(struct task_struct *task, pfm_context_t *ctx, void *arg, int coun
pfarg_reg_t tmp, *req = (pfarg_reg_t *)arg; pfarg_reg_t tmp, *req = (pfarg_reg_t *)arg;
unsigned long value, reset_pmds; unsigned long value, reset_pmds;
unsigned int cnum, reg_flags, flags; unsigned int cnum, reg_flags, flags;
int i; int is_monitor, is_counting;
int ret = -EINVAL; int i, ret = -EINVAL;
#define PFM_CHECK_PMC_PM(x, y, z) ((x)->ctx_fl_system ^ PMC_PM(y, z))
/* we don't quite support this right now */ /* we don't quite support this right now */
if (task != current) return -EINVAL; if (task != current) return -EINVAL;
...@@ -1384,6 +1385,9 @@ pfm_write_pmcs(struct task_struct *task, pfm_context_t *ctx, void *arg, int coun ...@@ -1384,6 +1385,9 @@ pfm_write_pmcs(struct task_struct *task, pfm_context_t *ctx, void *arg, int coun
reset_pmds = tmp.reg_reset_pmds[0]; reset_pmds = tmp.reg_reset_pmds[0];
flags = 0; flags = 0;
is_counting = PMC_IS_COUNTING(cnum);
is_monitor = PMC_IS_MONITOR(cnum);
/* /*
* we reject all non implemented PMC as well * we reject all non implemented PMC as well
* as attempts to modify PMC[0-3] which are used * as attempts to modify PMC[0-3] which are used
...@@ -1394,21 +1398,19 @@ pfm_write_pmcs(struct task_struct *task, pfm_context_t *ctx, void *arg, int coun ...@@ -1394,21 +1398,19 @@ pfm_write_pmcs(struct task_struct *task, pfm_context_t *ctx, void *arg, int coun
goto error; goto error;
} }
/* /*
* A PMC used to configure monitors must be: * If the PMC is a monitor, then if the value is not the default:
* - system-wide session: privileged monitor * - system-wide session: PMCx.pm=1 (privileged monitor)
* - per-task : user monitor * - per-task : PMCx.pm=0 (user monitor)
* any other configuration is rejected.
*/ */
if (PMC_IS_MONITOR(cnum) || PMC_IS_COUNTING(cnum)) { if ((is_monitor || is_counting) && value != PMC_DFL_VAL(i) && PFM_CHECK_PMC_PM(ctx, cnum, value)) {
DBprintk(("pmc[%u].pm=%ld\n", cnum, PMC_PM(cnum, value))); DBprintk(("pmc%u pmc_pm=%ld fl_system=%d\n",
cnum,
if (ctx->ctx_fl_system ^ PMC_PM(cnum, value)) { PMC_PM(cnum, value),
DBprintk(("pmc_pm=%ld fl_system=%d\n", PMC_PM(cnum, value), ctx->ctx_fl_system)); ctx->ctx_fl_system));
goto error; goto error;
} }
}
if (PMC_IS_COUNTING(cnum)) { if (is_counting) {
pfm_monitor_t *p = (pfm_monitor_t *)&value; pfm_monitor_t *p = (pfm_monitor_t *)&value;
/* /*
* enforce generation of overflow interrupt. Necessary on all * enforce generation of overflow interrupt. Necessary on all
...@@ -1471,7 +1473,7 @@ pfm_write_pmcs(struct task_struct *task, pfm_context_t *ctx, void *arg, int coun ...@@ -1471,7 +1473,7 @@ pfm_write_pmcs(struct task_struct *task, pfm_context_t *ctx, void *arg, int coun
*/ */
ctx->ctx_soft_pmds[cnum].flags = flags; ctx->ctx_soft_pmds[cnum].flags = flags;
if (PMC_IS_COUNTING(cnum)) { if (is_counting) {
ctx->ctx_soft_pmds[cnum].reset_pmds[0] = reset_pmds; ctx->ctx_soft_pmds[cnum].reset_pmds[0] = reset_pmds;
/* mark all PMDS to be accessed as used */ /* mark all PMDS to be accessed as used */
......
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