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

[PATCH] ia64: perfmon update

Here is a new perfmon patch. It is important because it
fixes the problem of the close() when the file descriptor
is shared between two related processes. The good thing
is that it simplifies a lot the cleanup of the sampling
buffer.

Here is the ChangeLog:

- fix bug in pfm_close() when the descriptor is
  shared between related processed. Introduce
  a pfm_flush() called for each invocation of
  close(). pfm_close() only called for the last
  user.

- fix pfm_restore_monitoring() to also reload
  the debug registers. They could be modified
  while monitoring is masked.

- fix pfm_close() to clear ctx_fl_is_sampling.

- fix a bug in pfm_handle_work() which could cause
  the wrong PMD to be reset. 

- converted PROTECT_CTX/UNPROTECT_CTX into
  local_irq_save/restore to keep context protection
  but allow IPI to proceed.

- updated pfm_syswide_force_stop() to use
  local_irq_save/restore now that the context
  is protected from the caller side.

- updated pfm_mck_pmc_check() to check if context is 
  loaded before checking for special IBR/DBR combinations.
  Clearing the debug registers is not needed when the context
  is not yet loaded.

- updated perfmon.h to have to correct prototype definitions
  for the pfm_mod_*() functions.

- got rid of the PFM_CTX_TERMINATED state.

- cleanup the DPRINT() statements to remove
  explicit output of current->pid. This is done
   systematically by the macros.

- added a systctl entry (expert_mode) to bypass
  read/write checks on PMC/PMD. As its name indicates
  this is for experts ONLY. Must be root to toggle
  /proc/sys entry.

- corrected pfm_mod_*() to check against the current task.

- removed pfm_mod_fast_read_pmds(). It is never needed.

- added pfm_mod_write_ibrs() and pfm_mod_write_dbrs().
parent d7ee788d
This diff is collapsed.
...@@ -101,6 +101,7 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu ...@@ -101,6 +101,7 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu
{ {
int ret = 0, check_case1 = 0; int ret = 0, check_case1 = 0;
unsigned long val8 = 0, val14 = 0, val13 = 0; unsigned long val8 = 0, val14 = 0, val13 = 0;
int is_loaded;
/* first preserve the reserved fields */ /* first preserve the reserved fields */
pfm_mck_reserved(cnum, val, regs); pfm_mck_reserved(cnum, val, regs);
...@@ -108,6 +109,8 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu ...@@ -108,6 +109,8 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu
/* sanitfy check */ /* sanitfy check */
if (ctx == NULL) return -EINVAL; if (ctx == NULL) return -EINVAL;
is_loaded = ctx->ctx_state == PFM_CTX_LOADED || ctx->ctx_state == PFM_CTX_MASKED;
/* /*
* we must clear the debug registers if pmc13 has a value which enable * we must clear the debug registers if pmc13 has a value which enable
* memory pipeline event constraints. In this case we need to clear the * memory pipeline event constraints. In this case we need to clear the
...@@ -120,7 +123,9 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu ...@@ -120,7 +123,9 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu
* *
* For now, we just check on cfg_dbrXX != 0x3. * For now, we just check on cfg_dbrXX != 0x3.
*/ */
if (cnum == 13 && ((*val & 0x18181818UL) != 0x18181818UL) && ctx->ctx_fl_using_dbreg == 0) { 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) {
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));
...@@ -131,14 +136,14 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu ...@@ -131,14 +136,14 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu
* a count of 0 will mark the debug registers as in use and also * a count of 0 will mark the debug registers as in use and also
* ensure that they are properly cleared. * ensure that they are properly cleared.
*/ */
ret = pfm_write_ibr_dbr(1, ctx, NULL, 0, regs); ret = pfm_write_ibr_dbr(PFM_DATA_RR, ctx, NULL, 0, regs);
if (ret) return ret; if (ret) return ret;
} }
/* /*
* we must clear the (instruction) debug registers if any pmc14.ibrpX bit is enabled * we must clear the (instruction) debug registers if any pmc14.ibrpX bit is enabled
* before they are (fl_using_dbreg==0) to avoid picking up stale information. * before they are (fl_using_dbreg==0) to avoid picking up stale information.
*/ */
if (cnum == 14 && ((*val & 0x2222UL) != 0x2222UL) && ctx->ctx_fl_using_dbreg == 0) { if (cnum == 14 && is_loaded && ((*val & 0x2222UL) != 0x2222UL) && ctx->ctx_fl_using_dbreg == 0) {
DPRINT(("pmc[%d]=0x%lx has active pmc14 settings, clearing ibr\n", cnum, *val)); DPRINT(("pmc[%d]=0x%lx has active pmc14 settings, clearing ibr\n", cnum, *val));
...@@ -149,7 +154,7 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu ...@@ -149,7 +154,7 @@ pfm_mck_pmc_check(struct task_struct *task, pfm_context_t *ctx, unsigned int cnu
* a count of 0 will mark the debug registers as in use and also * a count of 0 will mark the debug registers as in use and also
* ensure that they are properly cleared. * ensure that they are properly cleared.
*/ */
ret = pfm_write_ibr_dbr(0, ctx, NULL, 0, regs); ret = pfm_write_ibr_dbr(PFM_CODE_RR, ctx, NULL, 0, regs);
if (ret) return ret; if (ret) return ret;
} }
......
...@@ -242,9 +242,10 @@ extern int pfm_unregister_buffer_fmt(pfm_uuid_t uuid); ...@@ -242,9 +242,10 @@ extern int pfm_unregister_buffer_fmt(pfm_uuid_t uuid);
/* /*
* perfmon interface exported to modules * perfmon interface exported to modules
*/ */
extern long pfm_mod_fast_read_pmds(struct task_struct *, unsigned long mask[4], unsigned long *addr, struct pt_regs *regs); extern int pfm_mod_read_pmds(struct task_struct *, void *req, unsigned int nreq, struct pt_regs *regs);
extern long pfm_mod_read_pmds(struct task_struct *, pfarg_reg_t *req, unsigned int nreq, struct pt_regs *regs); extern int pfm_mod_write_pmcs(struct task_struct *, void *req, unsigned int nreq, struct pt_regs *regs);
extern long pfm_mod_write_pmcs(struct task_struct *, pfarg_reg_t *req, unsigned int nreq, struct pt_regs *regs); extern int pfm_mod_write_ibrs(struct task_struct *task, void *req, unsigned int nreq, struct pt_regs *regs);
extern int pfm_mod_write_dbrs(struct task_struct *task, void *req, unsigned int nreq, struct pt_regs *regs);
/* /*
* describe the content of the local_cpu_date->pfm_syst_info field * describe the content of the local_cpu_date->pfm_syst_info field
......
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