Commit a029a4ea authored by Thomas Richter's avatar Thomas Richter Committed by Vasily Gorbik

s390/cpumf: Allow concurrent access for CPU Measurement Counter Facility

Commit cf6acb8b ("s390/cpumf: Add support for complete counter set extraction")
allows access to the CPU Measurement Counter Facility via character
device /dev/hwctr. The access was exclusive via this device or
via perf_event_open() system call. Only one path at a time was
permitted. The CPU Measurement Counter Facility device driver blocked
access to other processes.

This patch removes this restriction and allows concurrent access to
the CPU Measurement Counter Facility from multiple processes at the same
time via perf_event_open() SVC and via /dev/hwctr device. The access
via /dev/hwctr device is still exclusive, only one process is allowed to
access this device.

This patch
- moves the /dev/hwctr device access from file perf_cpum_cf_diag.c.
  to file perf_cpum_cf.c.
- use only one trace buffer .../s390dbf/cpum_cf.
- remove cfset_csd structure and includes its members it into the
  structure cpu_cf_events. This results in one data structure and
  simplifies the access.
- rework function familiy ctr_set_enable, ctr_set_disable, ctr_set_start
  and ctr_set_stop which operate on a counter set number.
  Now they operate on a counter set bit mask.
- move CF_DIAG event functionality to file perf_cpum_cf.c. It now
  contains the complete functionality of the CPU Measurement Counter
  Facility:
  - Performance measurement support for counters using perf stat.
  - Support for complete counter set extraction with device /dev/hwctr.
  - Support for counter set extraction event CF_DIAG attached to
    samples using perf record.
- removes file perf_cpum_cf_diag.c
Signed-off-by: default avatarThomas Richter <tmricht@linux.ibm.com>
Reviewed-by: default avatarSumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 5fa2ea07
...@@ -32,39 +32,22 @@ static const u64 cpumf_ctr_ctl[CPUMF_CTR_SET_MAX] = { ...@@ -32,39 +32,22 @@ static const u64 cpumf_ctr_ctl[CPUMF_CTR_SET_MAX] = {
[CPUMF_CTR_SET_MT_DIAG] = 0x20, [CPUMF_CTR_SET_MT_DIAG] = 0x20,
}; };
static inline void ctr_set_enable(u64 *state, int ctr_set) static inline void ctr_set_enable(u64 *state, u64 ctrsets)
{
*state |= cpumf_ctr_ctl[ctr_set] << CPUMF_LCCTL_ENABLE_SHIFT;
}
static inline void ctr_set_disable(u64 *state, int ctr_set)
{
*state &= ~(cpumf_ctr_ctl[ctr_set] << CPUMF_LCCTL_ENABLE_SHIFT);
}
static inline void ctr_set_start(u64 *state, int ctr_set)
{
*state |= cpumf_ctr_ctl[ctr_set] << CPUMF_LCCTL_ACTCTL_SHIFT;
}
static inline void ctr_set_stop(u64 *state, int ctr_set)
{
*state &= ~(cpumf_ctr_ctl[ctr_set] << CPUMF_LCCTL_ACTCTL_SHIFT);
}
static inline void ctr_set_multiple_enable(u64 *state, u64 ctrsets)
{ {
*state |= ctrsets << CPUMF_LCCTL_ENABLE_SHIFT; *state |= ctrsets << CPUMF_LCCTL_ENABLE_SHIFT;
} }
static inline void ctr_set_multiple_disable(u64 *state, u64 ctrsets) static inline void ctr_set_disable(u64 *state, u64 ctrsets)
{ {
*state &= ~(ctrsets << CPUMF_LCCTL_ENABLE_SHIFT); *state &= ~(ctrsets << CPUMF_LCCTL_ENABLE_SHIFT);
} }
static inline void ctr_set_multiple_start(u64 *state, u64 ctrsets) static inline void ctr_set_start(u64 *state, u64 ctrsets)
{ {
*state |= ctrsets << CPUMF_LCCTL_ACTCTL_SHIFT; *state |= ctrsets << CPUMF_LCCTL_ACTCTL_SHIFT;
} }
static inline void ctr_set_multiple_stop(u64 *state, u64 ctrsets) static inline void ctr_set_stop(u64 *state, u64 ctrsets)
{ {
*state &= ~(ctrsets << CPUMF_LCCTL_ACTCTL_SHIFT); *state &= ~(ctrsets << CPUMF_LCCTL_ACTCTL_SHIFT);
} }
...@@ -92,8 +75,15 @@ struct cpu_cf_events { ...@@ -92,8 +75,15 @@ struct cpu_cf_events {
struct cpumf_ctr_info info; struct cpumf_ctr_info info;
atomic_t ctr_set[CPUMF_CTR_SET_MAX]; atomic_t ctr_set[CPUMF_CTR_SET_MAX];
atomic64_t alert; atomic64_t alert;
u64 state; u64 state; /* For perf_event_open SVC */
u64 dev_state; /* For /dev/hwctr */
unsigned int flags; unsigned int flags;
size_t used; /* Bytes used in data */
size_t usedss; /* Bytes used in start/stop */
unsigned char start[PAGE_SIZE]; /* Counter set at event add */
unsigned char stop[PAGE_SIZE]; /* Counter set at event delete */
unsigned char data[PAGE_SIZE]; /* Counter set at /dev/hwctr */
unsigned int sets; /* # Counter set saved in memory */
}; };
DECLARE_PER_CPU(struct cpu_cf_events, cpu_cf_events); DECLARE_PER_CPU(struct cpu_cf_events, cpu_cf_events);
...@@ -124,4 +114,6 @@ static inline int stccm_avail(void) ...@@ -124,4 +114,6 @@ static inline int stccm_avail(void)
size_t cpum_cf_ctrset_size(enum cpumf_ctr_set ctrset, size_t cpum_cf_ctrset_size(enum cpumf_ctr_set ctrset,
struct cpumf_ctr_info *info); struct cpumf_ctr_info *info);
int cfset_online_cpu(unsigned int cpu);
int cfset_offline_cpu(unsigned int cpu);
#endif /* _ASM_S390_CPU_MCF_H */ #endif /* _ASM_S390_CPU_MCF_H */
...@@ -71,7 +71,6 @@ obj-$(CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT) += ima_arch.o ...@@ -71,7 +71,6 @@ obj-$(CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT) += ima_arch.o
obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf_common.o obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf_common.o
obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf.o perf_cpum_sf.o obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf.o perf_cpum_sf.o
obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o perf_regs.o obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_events.o perf_regs.o
obj-$(CONFIG_PERF_EVENTS) += perf_cpum_cf_diag.o
obj-$(CONFIG_TRACEPOINTS) += trace.o obj-$(CONFIG_TRACEPOINTS) += trace.o
obj-$(findstring y, $(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) $(CONFIG_PGSTE)) += uv.o obj-$(findstring y, $(CONFIG_PROTECTED_VIRTUALIZATION_GUEST) $(CONFIG_PGSTE)) += uv.o
......
This diff is collapsed.
...@@ -29,7 +29,11 @@ DEFINE_PER_CPU(struct cpu_cf_events, cpu_cf_events) = { ...@@ -29,7 +29,11 @@ DEFINE_PER_CPU(struct cpu_cf_events, cpu_cf_events) = {
}, },
.alert = ATOMIC64_INIT(0), .alert = ATOMIC64_INIT(0),
.state = 0, .state = 0,
.dev_state = 0,
.flags = 0, .flags = 0,
.used = 0,
.usedss = 0,
.sets = 0
}; };
/* Indicator whether the CPU-Measurement Counter Facility Support is ready */ /* Indicator whether the CPU-Measurement Counter Facility Support is ready */
static bool cpum_cf_initalized; static bool cpum_cf_initalized;
...@@ -96,25 +100,10 @@ bool kernel_cpumcf_avail(void) ...@@ -96,25 +100,10 @@ bool kernel_cpumcf_avail(void)
} }
EXPORT_SYMBOL(kernel_cpumcf_avail); EXPORT_SYMBOL(kernel_cpumcf_avail);
/* Reserve/release functions for sharing perf hardware */
static DEFINE_SPINLOCK(cpumcf_owner_lock);
static void *cpumcf_owner;
/* Initialize the CPU-measurement counter facility */ /* Initialize the CPU-measurement counter facility */
int __kernel_cpumcf_begin(void) int __kernel_cpumcf_begin(void)
{ {
int flags = PMC_INIT; int flags = PMC_INIT;
int err = 0;
spin_lock(&cpumcf_owner_lock);
if (cpumcf_owner)
err = -EBUSY;
else
cpumcf_owner = __builtin_return_address(0);
spin_unlock(&cpumcf_owner_lock);
if (err)
return err;
on_each_cpu(cpum_cf_setup_cpu, &flags, 1); on_each_cpu(cpum_cf_setup_cpu, &flags, 1);
irq_subclass_register(IRQ_SUBCLASS_MEASUREMENT_ALERT); irq_subclass_register(IRQ_SUBCLASS_MEASUREMENT_ALERT);
...@@ -144,10 +133,6 @@ void __kernel_cpumcf_end(void) ...@@ -144,10 +133,6 @@ void __kernel_cpumcf_end(void)
on_each_cpu(cpum_cf_setup_cpu, &flags, 1); on_each_cpu(cpum_cf_setup_cpu, &flags, 1);
irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT); irq_subclass_unregister(IRQ_SUBCLASS_MEASUREMENT_ALERT);
spin_lock(&cpumcf_owner_lock);
cpumcf_owner = NULL;
spin_unlock(&cpumcf_owner_lock);
} }
EXPORT_SYMBOL(__kernel_cpumcf_end); EXPORT_SYMBOL(__kernel_cpumcf_end);
...@@ -161,11 +146,13 @@ static int cpum_cf_setup(unsigned int cpu, int flags) ...@@ -161,11 +146,13 @@ static int cpum_cf_setup(unsigned int cpu, int flags)
static int cpum_cf_online_cpu(unsigned int cpu) static int cpum_cf_online_cpu(unsigned int cpu)
{ {
return cpum_cf_setup(cpu, PMC_INIT); cpum_cf_setup(cpu, PMC_INIT);
return cfset_online_cpu(cpu);
} }
static int cpum_cf_offline_cpu(unsigned int cpu) static int cpum_cf_offline_cpu(unsigned int cpu)
{ {
cfset_offline_cpu(cpu);
return cpum_cf_setup(cpu, PMC_RELEASE); return cpum_cf_setup(cpu, PMC_RELEASE);
} }
......
This diff is collapsed.
...@@ -171,7 +171,6 @@ enum cpuhp_state { ...@@ -171,7 +171,6 @@ enum cpuhp_state {
CPUHP_AP_PERF_X86_CSTATE_ONLINE, CPUHP_AP_PERF_X86_CSTATE_ONLINE,
CPUHP_AP_PERF_X86_IDXD_ONLINE, CPUHP_AP_PERF_X86_IDXD_ONLINE,
CPUHP_AP_PERF_S390_CF_ONLINE, CPUHP_AP_PERF_S390_CF_ONLINE,
CPUHP_AP_PERF_S390_CFD_ONLINE,
CPUHP_AP_PERF_S390_SF_ONLINE, CPUHP_AP_PERF_S390_SF_ONLINE,
CPUHP_AP_PERF_ARM_CCI_ONLINE, CPUHP_AP_PERF_ARM_CCI_ONLINE,
CPUHP_AP_PERF_ARM_CCN_ONLINE, CPUHP_AP_PERF_ARM_CCN_ONLINE,
......
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