forked from Minki/linux
s390/perf: add support for the CPU-Measurement Sampling Facility
Introduce a perf PMU, "cpum_sf", to support the CPU-Measurement Sampling Facility. You can control the sampling facility through this perf PMU interfaces. Perf sampling events are created for hardware samples. For details about the CPU-Measurement Sampling Facility, see "The Load-Program-Parameter and the CPU-Measurement Facilities" (SA23-2260). Signed-off-by: Hendrik Brueckner <brueckner@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
c716832513
commit
8c069ff4bd
@ -210,6 +210,20 @@ static inline int lsctl(struct hws_lsctl_request_block *req)
|
||||
|
||||
/* Sampling control helper functions */
|
||||
|
||||
#include <linux/time.h>
|
||||
|
||||
static inline unsigned long freq_to_sample_rate(struct hws_qsi_info_block *qsi,
|
||||
unsigned long freq)
|
||||
{
|
||||
return (USEC_PER_SEC / freq) * qsi->cpu_speed;
|
||||
}
|
||||
|
||||
static inline unsigned long sample_rate_to_freq(struct hws_qsi_info_block *qsi,
|
||||
unsigned long rate)
|
||||
{
|
||||
return USEC_PER_SEC * qsi->cpu_speed / rate;
|
||||
}
|
||||
|
||||
#define SDB_TE_ALERT_REQ_MASK 0x4000000000000000UL
|
||||
#define SDB_TE_BUFFER_FULL_MASK 0x8000000000000000UL
|
||||
|
||||
|
@ -15,12 +15,13 @@
|
||||
#include <linux/device.h>
|
||||
#include <asm/cpu_mf.h>
|
||||
|
||||
/* CPU-measurement counter facility */
|
||||
#define PERF_CPUM_CF_MAX_CTR 256
|
||||
|
||||
/* Per-CPU flags for PMU states */
|
||||
#define PMU_F_RESERVED 0x1000
|
||||
#define PMU_F_ENABLED 0x2000
|
||||
#define PMU_F_IN_USE 0x4000
|
||||
#define PMU_F_ERR_IBE 0x0100
|
||||
#define PMU_F_ERR_LSDA 0x0200
|
||||
#define PMU_F_ERR_MASK (PMU_F_ERR_IBE|PMU_F_ERR_LSDA)
|
||||
|
||||
/* Perf defintions for PMU event attributes in sysfs */
|
||||
extern __init const struct attribute_group **cpumf_cf_event_group(void);
|
||||
@ -41,5 +42,15 @@ extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
|
||||
extern unsigned long perf_misc_flags(struct pt_regs *regs);
|
||||
#define perf_misc_flags(regs) perf_misc_flags(regs)
|
||||
|
||||
/* Perf PMU definitions for the counter facility */
|
||||
#define PERF_CPUM_CF_MAX_CTR 256
|
||||
|
||||
/* Perf PMU definitions for the sampling facility */
|
||||
#define PERF_CPUM_SF_MAX_CTR 1
|
||||
#define PERF_EVENT_CPUM_SF 0xB0000UL /* Raw event ID */
|
||||
|
||||
#define TEAR_REG(hwc) ((hwc)->last_tag)
|
||||
#define SAMPL_RATE(hwc) ((hwc)->event_base)
|
||||
|
||||
#endif /* CONFIG_64BIT */
|
||||
#endif /* _ASM_S390_PERF_EVENT_H */
|
||||
|
@ -60,7 +60,7 @@ obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
|
||||
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
|
||||
|
||||
ifdef CONFIG_64BIT
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o \
|
||||
obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o perf_cpum_sf.o \
|
||||
perf_cpum_cf_events.o
|
||||
obj-y += runtime_instr.o cache.o
|
||||
endif
|
||||
|
1024
arch/s390/kernel/perf_cpum_sf.c
Normal file
1024
arch/s390/kernel/perf_cpum_sf.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,7 @@
|
||||
#include <linux/kvm_host.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/sysfs.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/cpu_mf.h>
|
||||
@ -36,6 +37,8 @@ int perf_num_counters(void)
|
||||
|
||||
if (cpum_cf_avail())
|
||||
num += PERF_CPUM_CF_MAX_CTR;
|
||||
if (cpum_sf_avail())
|
||||
num += PERF_CPUM_SF_MAX_CTR;
|
||||
|
||||
return num;
|
||||
}
|
||||
@ -93,24 +96,45 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
|
||||
: PERF_RECORD_MISC_KERNEL;
|
||||
}
|
||||
|
||||
void perf_event_print_debug(void)
|
||||
void print_debug_cf(void)
|
||||
{
|
||||
struct cpumf_ctr_info cf_info;
|
||||
unsigned long flags;
|
||||
int cpu;
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
if (!cpum_cf_avail())
|
||||
return;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
cpu = smp_processor_id();
|
||||
memset(&cf_info, 0, sizeof(cf_info));
|
||||
if (!qctri(&cf_info))
|
||||
pr_info("CPU[%i] CPUM_CF: ver=%u.%u A=%04x E=%04x C=%04x\n",
|
||||
cpu, cf_info.cfvn, cf_info.csvn,
|
||||
cf_info.auth_ctl, cf_info.enable_ctl, cf_info.act_ctl);
|
||||
}
|
||||
|
||||
static void print_debug_sf(void)
|
||||
{
|
||||
struct hws_qsi_info_block si;
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
memset(&si, 0, sizeof(si));
|
||||
if (qsi(&si)) {
|
||||
pr_err("CPU[%i]: CPM_SF: qsi failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pr_info("CPU[%i]: CPM_SF: as=%i es=%i cs=%i bsdes=%i dsdes=%i"
|
||||
" min=%i max=%i cpu_speed=%i tear=%p dear=%p\n",
|
||||
cpu, si.as, si.es, si.cs, si.bsdes, si.dsdes,
|
||||
si.min_sampl_rate, si.max_sampl_rate, si.cpu_speed,
|
||||
si.tear, si.dear);
|
||||
}
|
||||
|
||||
void perf_event_print_debug(void)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
if (cpum_cf_avail())
|
||||
print_debug_cf();
|
||||
if (cpum_sf_avail())
|
||||
print_debug_sf();
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user