Messages in this thread Patch in this message |  | | From | David Carrillo-Cisneros <> | Subject | [PATCH v3 44/46] perf/x86/intel/cmt: add debugfs intel_cmt directory | Date | Sat, 29 Oct 2016 17:38:41 -0700 |
| |
Add debug fs to intel_cmt to help maintenance. It shows the following human readable snapshots of the internals of the CMT driver: - hrchy: A per monr view of the monr hierarchy. - pkgs: A per-package view of all online struct pkg_data. - rmids: A per-package view of occupancy and state of all rmids.
Signed-off-by: David Carrillo-Cisneros <davidcc@google.com> --- arch/x86/events/intel/cmt.c | 385 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 385 insertions(+)
diff --git a/arch/x86/events/intel/cmt.c b/arch/x86/events/intel/cmt.c index 8cbcbc6..554ebd2 100644 --- a/arch/x86/events/intel/cmt.c +++ b/arch/x86/events/intel/cmt.c @@ -2372,6 +2372,376 @@ static ssize_t max_recycle_threshold_store(struct device *dev, static DEVICE_ATTR_RW(max_recycle_threshold); + +#define INTEL_CMT_DEBUGFS + +#ifdef INTEL_CMT_DEBUGFS + +#include <linux/debugfs.h> + +#define DBG_PRINTF(format__, ...) \ + seq_printf(s, "%*s" format__, 4 * pad, "", ##__VA_ARGS__) + +static void cmt_dbg_show__pmonr(struct seq_file *s, + struct pmonr *pmonr, + int pad) +{ + struct pmonr *pos; + union pmonr_rmids rmids; + static const char * const state_strs[] = {"OFF", "UNUSED", "ACTIVE", + "DEP_IDLE", "DEP_DIRTY"}; + + DBG_PRINTF("pmonr: (%p, pkgid: %d, monr: %p)\n", + pmonr, pmonr->pkgd->pkgid, pmonr->monr); + pad++; + + rmids.value = atomic64_read(&pmonr->atomic_rmids); + DBG_PRINTF("atomic_rmids: (%d,%d), state: %s, lender: %p\n", + rmids.sched_rmid, rmids.read_rmid, + state_strs[pmonr->state], pmonr->lender); + + if (pmonr->state == PMONR_ACTIVE) { + DBG_PRINTF("pmonr_deps_head:"); + list_for_each_entry(pos, &pmonr->pmonr_deps_head, + pmonr_deps_entry) { + seq_printf(s, "%p,", pos); + } + seq_puts(s, "\n"); + } + + DBG_PRINTF("last_enter_active: %lu\n", + atomic64_read(&pmonr->last_enter_active)); + +} + +static void cmt_dbg_show__monr(struct seq_file *s, struct monr *monr, int pad) +{ + struct pkg_data *pkgd = NULL; + struct monr *pos; + struct pmonr *pmonr; + int p; + + DBG_PRINTF("\nmonr: %p, parent: %p\n", monr, monr->parent); + + pad++; + + DBG_PRINTF("children: ["); + + + list_for_each_entry(pos, &monr->children, parent_entry) + seq_printf(s, "%p, ", pos); + + seq_puts(s, "]\n"); + + DBG_PRINTF("mon_cgrp: (%s, %p)", + monr->mon_cgrp ? monr->mon_cgrp->css.cgroup->kn->name : "NA", + monr->mon_cgrp); + DBG_PRINTF("mon_events: %p\n", monr->mon_events); + + DBG_PRINTF("pmonrs:\n"); + rcu_read_lock(); + while ((pkgd = cmt_pkgs_data_next_rcu(pkgd))) { + pmonr = pkgd_pmonr(pkgd, monr); + cmt_dbg_show__pmonr(s, pmonr, pad + 1); + } + rcu_read_unlock(); + + DBG_PRINTF("last_rmid_recoup: %lu, nr_dep_pmonrs: %u, flags: %x\n", + atomic64_read(&monr->last_rmid_recoup), + atomic_read(&monr->nr_dep_pmonrs), monr->flags); + DBG_PRINTF("nr_has_user: %d, nr_nosteal_rmid: %d,", + monr->nr_has_user, monr->nr_nosteal_rmid); + DBG_PRINTF("nr_nolazy_rmid: %d, uflags: %x\n", + monr->nr_nolazy_rmid, monr->uflags); + DBG_PRINTF("pkg_uflags: ["); + for (p = 0; p < topology_max_packages(); p++) + seq_printf(s, "%x;", monr->pkg_uflags[p]); + seq_puts(s, "]\n"); +} + + +static void cmt_dbg_show__pkgd(struct seq_file *s, + struct pkg_data *pkgd, int pad, bool csd_full) +{ + struct pmonr *pmonr; + unsigned long flags; + int r; + + raw_spin_lock_irqsave(&pkgd->lock, flags); + + DBG_PRINTF("\npkgd: %p, pkgid: %d, max_rmid: %d\n", + pkgd, pkgd->pkgid, pkgd->max_rmid); + pad++; + + DBG_PRINTF("free_rmids: [%*pbl]\n", + CMT_MAX_NR_RMIDS, pkgd->free_rmids); + DBG_PRINTF("dirty_rmids: [%*pbl]\n", + CMT_MAX_NR_RMIDS, pkgd->dirty_rmids); + + DBG_PRINTF("active_pmonrs:\n"); + list_for_each_entry(pmonr, &pkgd->active_pmonrs, rot_entry) + cmt_dbg_show__pmonr(s, pmonr, pad + 1); + + DBG_PRINTF("dep_idle_pmonrs:\n"); + list_for_each_entry(pmonr, &pkgd->dep_idle_pmonrs, rot_entry) + cmt_dbg_show__pmonr(s, pmonr, pad + 1); + + DBG_PRINTF("dep_dirty_pmonrs:\n"); + list_for_each_entry(pmonr, &pkgd->dep_dirty_pmonrs, rot_entry) + cmt_dbg_show__pmonr(s, pmonr, pad + 1); + /* + * only print pmonr pointer since this pmonrs are contained in either + * Dep_Idle or Dep_Dirty pmonrs. + */ + DBG_PRINTF("dep_pmonrs: ["); + list_for_each_entry(pmonr, &pkgd->dep_pmonrs, pkgd_deps_entry) + seq_printf(s, "%p,", pmonr); + seq_puts(s, "]\n"); + + DBG_PRINTF("nr_dirty_rmids: %d, nr_dep_pmonrs: %d\n", + pkgd->nr_dirty_rmids, pkgd->nr_dep_pmonrs); + + DBG_PRINTF("work_cpu: %d\n", pkgd->work_cpu); + + DBG_PRINTF("ccsds ("); + if (csd_full) + seq_puts(s, "flags, info, func, "); + seq_puts(s, "on_read, value, ret, rmid): ["); + + pad += 1; + for (r = 0; r <= pkgd->max_rmid; r++) { + struct cmt_csd *ccsd = &pkgd->ccsds[r]; + + if (r % 4 == 0) { + seq_puts(s, "\n"); + DBG_PRINTF("("); + } else { + seq_puts(s, "("); + } + + if (csd_full) { + seq_printf(s, "%d, %p, %p, ", ccsd->csd.flags, + ccsd->csd.info, ccsd->csd.func); + } + seq_printf(s, "%d, %llu, %d, %d", + atomic_read(&ccsd->on_read), ccsd->value, + ccsd->ret, ccsd->rmid); + seq_puts(s, "),\t"); + } + seq_puts(s, "]"); + pad -= 1; + + raw_spin_unlock_irqrestore(&pkgd->lock, flags); +} + +static int cmt_dbg_pkgs_show(struct seq_file *s, void *unused) +{ + struct pkg_data *pkgd = NULL; + int pad = 0; + + mutex_lock(&cmt_mutex); + + while ((pkgd = cmt_pkgs_data_next_rcu(pkgd))) { + cmt_dbg_show__pkgd(s, pkgd, pad, false); + seq_puts(s, "\n"); + } + + mutex_unlock(&cmt_mutex); + + return 0; +} + +static int cmt_dbg_hrchy_show(struct seq_file *s, void *unused) +{ + struct monr *pos = NULL; + int pad = 0; + + mutex_lock(&cmt_mutex); + while ((pos = monr_next_descendant_pre(pos, monr_hrchy_root))) + cmt_dbg_show__monr(s, pos, pad); + mutex_unlock(&cmt_mutex); + + return 0; +} + +/* Must run on a CPU in pkgd's pkg. */ +static int cmt_dbg_rmids__rmids(struct seq_file *s, struct pkg_data *pkgd, + unsigned long *rmids, int pad) +{ + unsigned long zero_val[CMT_MAX_NR_RMIDS_LONGS]; + int err, r, nr_printed = 0; + u64 val; + + bitmap_copy(zero_val, rmids, CMT_MAX_NR_RMIDS); + + DBG_PRINTF("non-zero value (rmid, scaled llc_occupancy): ["); + pad++; + for_each_set_bit(r, rmids, CMT_MAX_NR_RMIDS) { + err = cmt_rmid_read(r, &val); + if (!err && !val) + continue; + + if (nr_printed % 4 == 0) { + seq_puts(s, "\n"); + DBG_PRINTF("("); + } else { + seq_puts(s, "("); + } + nr_printed++; + + if (err) { + seq_printf(s, "%d, error: %d),\t", r, err); + __clear_bit(r, zero_val); + continue; + } + seq_printf(s, "%d, %llu), ", r, val * cmt_l3_scale); + __clear_bit(r, zero_val); + } + seq_puts(s, "]\n"); + pad--; + + DBG_PRINTF("zero value: [%*pbl]\n", CMT_MAX_NR_RMIDS, zero_val); + + return 0; +} + +static int __cmt_dbg_rmids__pkgd(struct seq_file *s, + struct pkg_data *pkgd, int pad) +{ + unsigned long rmids_in_pmonr[CMT_MAX_NR_RMIDS_LONGS]; + int r; + + memset(rmids_in_pmonr, 0, CMT_MAX_NR_RMIDS_BYTES); + bitmap_fill(rmids_in_pmonr, pkgd->max_rmid + 1); + + for_each_set_bit(r, pkgd->free_rmids, CMT_MAX_NR_RMIDS) + __clear_bit(r, rmids_in_pmonr); + + for_each_set_bit(r, pkgd->dirty_rmids, CMT_MAX_NR_RMIDS) + __clear_bit(r, rmids_in_pmonr); + + + raw_spin_lock(&pkgd->lock); + + DBG_PRINTF("free_rmids:\n"); + cmt_dbg_rmids__rmids(s, pkgd, pkgd->free_rmids, pad + 1); + + DBG_PRINTF("dirty_rmids:\n"); + cmt_dbg_rmids__rmids(s, pkgd, pkgd->dirty_rmids, pad + 1); + + DBG_PRINTF("rmids_in_pmonr:\n"); + cmt_dbg_rmids__rmids(s, pkgd, rmids_in_pmonr, pad + 1); + + raw_spin_unlock(&pkgd->lock); + + return 0; +} + +struct dbg_smp_data { + struct seq_file *s; + struct pkg_data *pkgd; + int pad; +}; + +void cmt_dbg_rmids_pkgd(void *data) +{ + struct dbg_smp_data *d; + + d = (struct dbg_smp_data *)data; + __cmt_dbg_rmids__pkgd(d->s, d->pkgd, d->pad); +} + +static int cmt_dbg_rmids_show(struct seq_file *s, void *unused) +{ + struct dbg_smp_data d; + struct pkg_data *pkgd = NULL; + int pad = 0, err; + + mutex_lock(&cmt_mutex); + + while ((pkgd = cmt_pkgs_data_next_rcu(pkgd))) { + DBG_PRINTF("pkgid: %d\n", pkgd->pkgid); + d.s = s; + d.pkgd = pkgd; + d.pad = pad + 1; + err = smp_call_function_single(pkgd->work_cpu, + cmt_dbg_rmids_pkgd, &d, true); + seq_puts(s, "\n"); + } + + mutex_unlock(&cmt_mutex); + + return 0; + +} + +#define CMT_DBGS_FILE(name__) \ +static int cmt_dbg_ ## name__ ## _open(struct inode *inode, struct file *file)\ +{\ + return single_open(file, cmt_dbg_ ## name__ ## _show,\ + inode->i_private);\ +} \ +static const struct file_operations cmt_dbg_ ## name__ ## _ops = {\ + .open = cmt_dbg_ ## name__ ## _open,\ + .read = seq_read,\ + .llseek = seq_lseek,\ + .release = single_release,\ +} + +CMT_DBGS_FILE(hrchy); +CMT_DBGS_FILE(pkgs); +CMT_DBGS_FILE(rmids); + +struct dentry *cmt_dbgfs_root; + +static int start_debugfs(void) +{ + struct dentry *root, *pkgs, *hrchy, *rmids; + + root = debugfs_create_dir("intel_cmt", NULL); + if (IS_ERR(root)) + return PTR_ERR(root); + + pkgs = debugfs_create_file("pkgs", 0444, + root, NULL, &cmt_dbg_pkgs_ops); + if (IS_ERR(pkgs)) + return PTR_ERR(pkgs); + + hrchy = debugfs_create_file("hrchy", 0444, + root, NULL, &cmt_dbg_hrchy_ops); + if (IS_ERR(hrchy)) + return PTR_ERR(hrchy); + + rmids = debugfs_create_file("rmids", 0444, + root, NULL, &cmt_dbg_rmids_ops); + if (IS_ERR(rmids)) + return PTR_ERR(rmids); + + cmt_dbgfs_root = root; + + return 0; +} + +static void stop_debugfs(void) +{ + if (!cmt_dbgfs_root) + return; + debugfs_remove_recursive(cmt_dbgfs_root); + cmt_dbgfs_root = NULL; +} + +#else + +static int start_debugfs(void) +{ +} + +static void stop_debugfs(void) +{ +} + +#endif + static struct attribute *intel_cmt_attrs[] = { &dev_attr_max_recycle_threshold.attr, NULL, @@ -2774,6 +3144,15 @@ static void cmt_stop(void) mutex_unlock(&cmt_mutex); } +static void intel_cmt_terminate(void) +{ + stop_debugfs(); + static_branch_dec(&pqr_common_enable_key); + perf_pmu_unregister(&intel_cmt_pmu); + cmt_stop(); + cmt_dealloc(); +} + static int __init cmt_alloc(void) { pkg_uflags_size = sizeof(*pkg_uflags_zeroes) * topology_max_packages(); @@ -2904,6 +3283,12 @@ static int __init intel_cmt_init(void) static_branch_inc(&pqr_common_enable_key); + err = start_debugfs(); + if (err) { + intel_cmt_terminate(); + goto err_exit; + } + return err; err_stop: -- 2.8.0.rc3.226.g39d4020
|  |