s390/perf: Add service level information for CPU-Measurement Facilities

Register a service level handler to report information about available
CPU-Measurement facilities.

Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
Hendrik Brueckner 2013-12-13 12:38:39 +01:00 committed by Martin Schwidefsky
parent e28bb79d99
commit 99c64b6679

View file

@ -16,17 +16,19 @@
#include <linux/kvm_host.h>
#include <linux/percpu.h>
#include <linux/export.h>
#include <linux/seq_file.h>
#include <linux/spinlock.h>
#include <linux/sysfs.h>
#include <asm/irq.h>
#include <asm/cpu_mf.h>
#include <asm/lowcore.h>
#include <asm/processor.h>
#include <asm/sysinfo.h>
const char *perf_pmu_name(void)
{
if (cpum_cf_avail() || cpum_sf_avail())
return "CPU-measurement facilities (CPUMF)";
return "CPU-Measurement Facilities (CPU-MF)";
return "pmu";
}
EXPORT_SYMBOL(perf_pmu_name);
@ -138,6 +140,60 @@ void perf_event_print_debug(void)
local_irq_restore(flags);
}
/* Service level infrastructure */
static void sl_print_counter(struct seq_file *m)
{
struct cpumf_ctr_info ci;
memset(&ci, 0, sizeof(ci));
if (qctri(&ci))
return;
seq_printf(m, "CPU-MF: Counter facility: version=%u.%u "
"authorization=%04x\n", ci.cfvn, ci.csvn, ci.auth_ctl);
}
static void sl_print_sampling(struct seq_file *m)
{
struct hws_qsi_info_block si;
memset(&si, 0, sizeof(si));
if (qsi(&si))
return;
if (!si.as && !si.ad)
return;
seq_printf(m, "CPU-MF: Sampling facility: min_rate=%lu max_rate=%lu"
" cpu_speed=%u\n", si.min_sampl_rate, si.max_sampl_rate,
si.cpu_speed);
if (si.as)
seq_printf(m, "CPU-MF: Sampling facility: mode=basic"
" sample_size=%u\n", si.bsdes);
if (si.ad)
seq_printf(m, "CPU-MF: Sampling facility: mode=diagnostic"
" sample_size=%u\n", si.dsdes);
}
static void service_level_perf_print(struct seq_file *m,
struct service_level *sl)
{
if (cpum_cf_avail())
sl_print_counter(m);
if (cpum_sf_avail())
sl_print_sampling(m);
}
static struct service_level service_level_perf = {
.seq_print = service_level_perf_print,
};
static int __init service_level_perf_register(void)
{
return register_service_level(&service_level_perf);
}
arch_initcall(service_level_perf_register);
/* See also arch/s390/kernel/traps.c */
static unsigned long __store_trace(struct perf_callchain_entry *entry,
unsigned long sp,