s390/cpum_cf: add support for the MT-diagnostic counter set (z13)
Complete the IBM z13 support and support counters from the MT-diagnostic counter set. Note that this counter set is available only if SMT is enabled. 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
db17160dce
commit
ee699f329a
|
@ -20,9 +20,11 @@
|
|||
#define CPU_MF_INT_SF_PRA (1 << 29) /* program request alert */
|
||||
#define CPU_MF_INT_SF_SACA (1 << 23) /* sampler auth. change alert */
|
||||
#define CPU_MF_INT_SF_LSDA (1 << 22) /* loss of sample data alert */
|
||||
#define CPU_MF_INT_CF_MTDA (1 << 15) /* loss of MT ctr. data alert */
|
||||
#define CPU_MF_INT_CF_CACA (1 << 7) /* counter auth. change alert */
|
||||
#define CPU_MF_INT_CF_LCDA (1 << 6) /* loss of counter data alert */
|
||||
#define CPU_MF_INT_CF_MASK (CPU_MF_INT_CF_CACA|CPU_MF_INT_CF_LCDA)
|
||||
#define CPU_MF_INT_CF_MASK (CPU_MF_INT_CF_MTDA|CPU_MF_INT_CF_CACA| \
|
||||
CPU_MF_INT_CF_LCDA)
|
||||
#define CPU_MF_INT_SF_MASK (CPU_MF_INT_SF_IAE|CPU_MF_INT_SF_ISE| \
|
||||
CPU_MF_INT_SF_PRA|CPU_MF_INT_SF_SACA| \
|
||||
CPU_MF_INT_SF_LSDA)
|
||||
|
|
|
@ -22,19 +22,12 @@
|
|||
#include <asm/irq.h>
|
||||
#include <asm/cpu_mf.h>
|
||||
|
||||
/* CPU-measurement counter facility supports these CPU counter sets:
|
||||
* For CPU counter sets:
|
||||
* Basic counter set: 0-31
|
||||
* Problem-state counter set: 32-63
|
||||
* Crypto-activity counter set: 64-127
|
||||
* Extented counter set: 128-159
|
||||
*/
|
||||
enum cpumf_ctr_set {
|
||||
/* CPU counter sets */
|
||||
CPUMF_CTR_SET_BASIC = 0,
|
||||
CPUMF_CTR_SET_USER = 1,
|
||||
CPUMF_CTR_SET_CRYPTO = 2,
|
||||
CPUMF_CTR_SET_EXT = 3,
|
||||
CPUMF_CTR_SET_BASIC = 0, /* Basic Counter Set */
|
||||
CPUMF_CTR_SET_USER = 1, /* Problem-State Counter Set */
|
||||
CPUMF_CTR_SET_CRYPTO = 2, /* Crypto-Activity Counter Set */
|
||||
CPUMF_CTR_SET_EXT = 3, /* Extended Counter Set */
|
||||
CPUMF_CTR_SET_MT_DIAG = 4, /* MT-diagnostic Counter Set */
|
||||
|
||||
/* Maximum number of counter sets */
|
||||
CPUMF_CTR_SET_MAX,
|
||||
|
@ -47,6 +40,7 @@ static const u64 cpumf_state_ctl[CPUMF_CTR_SET_MAX] = {
|
|||
[CPUMF_CTR_SET_USER] = 0x04,
|
||||
[CPUMF_CTR_SET_CRYPTO] = 0x08,
|
||||
[CPUMF_CTR_SET_EXT] = 0x01,
|
||||
[CPUMF_CTR_SET_MT_DIAG] = 0x20,
|
||||
};
|
||||
|
||||
static void ctr_set_enable(u64 *state, int ctr_set)
|
||||
|
@ -76,19 +70,20 @@ struct cpu_hw_events {
|
|||
};
|
||||
static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
|
||||
.ctr_set = {
|
||||
[CPUMF_CTR_SET_BASIC] = ATOMIC_INIT(0),
|
||||
[CPUMF_CTR_SET_USER] = ATOMIC_INIT(0),
|
||||
[CPUMF_CTR_SET_CRYPTO] = ATOMIC_INIT(0),
|
||||
[CPUMF_CTR_SET_EXT] = ATOMIC_INIT(0),
|
||||
[CPUMF_CTR_SET_BASIC] = ATOMIC_INIT(0),
|
||||
[CPUMF_CTR_SET_USER] = ATOMIC_INIT(0),
|
||||
[CPUMF_CTR_SET_CRYPTO] = ATOMIC_INIT(0),
|
||||
[CPUMF_CTR_SET_EXT] = ATOMIC_INIT(0),
|
||||
[CPUMF_CTR_SET_MT_DIAG] = ATOMIC_INIT(0),
|
||||
},
|
||||
.state = 0,
|
||||
.flags = 0,
|
||||
.txn_flags = 0,
|
||||
};
|
||||
|
||||
static int get_counter_set(u64 event)
|
||||
static enum cpumf_ctr_set get_counter_set(u64 event)
|
||||
{
|
||||
int set = -1;
|
||||
int set = CPUMF_CTR_SET_MAX;
|
||||
|
||||
if (event < 32)
|
||||
set = CPUMF_CTR_SET_BASIC;
|
||||
|
@ -98,6 +93,8 @@ static int get_counter_set(u64 event)
|
|||
set = CPUMF_CTR_SET_CRYPTO;
|
||||
else if (event < 256)
|
||||
set = CPUMF_CTR_SET_EXT;
|
||||
else if (event >= 448 && event < 496)
|
||||
set = CPUMF_CTR_SET_MT_DIAG;
|
||||
|
||||
return set;
|
||||
}
|
||||
|
@ -106,6 +103,7 @@ static int validate_ctr_version(const struct hw_perf_event *hwc)
|
|||
{
|
||||
struct cpu_hw_events *cpuhw;
|
||||
int err = 0;
|
||||
u16 mtdiag_ctl;
|
||||
|
||||
cpuhw = &get_cpu_var(cpu_hw_events);
|
||||
|
||||
|
@ -125,6 +123,27 @@ static int validate_ctr_version(const struct hw_perf_event *hwc)
|
|||
(cpuhw->info.csvn > 2 && hwc->config > 255))
|
||||
err = -EOPNOTSUPP;
|
||||
break;
|
||||
case CPUMF_CTR_SET_MT_DIAG:
|
||||
if (cpuhw->info.csvn <= 3)
|
||||
err = -EOPNOTSUPP;
|
||||
/*
|
||||
* MT-diagnostic counters are read-only. The counter set
|
||||
* is automatically enabled and activated on all CPUs with
|
||||
* multithreading (SMT). Deactivation of multithreading
|
||||
* also disables the counter set. State changes are ignored
|
||||
* by lcctl(). Because Linux controls SMT enablement through
|
||||
* a kernel parameter only, the counter set is either disabled
|
||||
* or enabled and active.
|
||||
*
|
||||
* Thus, the counters can only be used if SMT is on and the
|
||||
* counter set is enabled and active.
|
||||
*/
|
||||
mtdiag_ctl = cpumf_state_ctl[CPUMF_CTR_SET_MT_DIAG];
|
||||
if (!((cpuhw->info.auth_ctl & mtdiag_ctl) &&
|
||||
(cpuhw->info.enable_ctl & mtdiag_ctl) &&
|
||||
(cpuhw->info.act_ctl & mtdiag_ctl)))
|
||||
err = -EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
put_cpu_var(cpu_hw_events);
|
||||
|
@ -230,6 +249,11 @@ static void cpumf_measurement_alert(struct ext_code ext_code,
|
|||
/* loss of counter data alert */
|
||||
if (alert & CPU_MF_INT_CF_LCDA)
|
||||
pr_err("CPU[%i] Counter data was lost\n", smp_processor_id());
|
||||
|
||||
/* loss of MT counter data alert */
|
||||
if (alert & CPU_MF_INT_CF_MTDA)
|
||||
pr_warn("CPU[%i] MT counter data was lost\n",
|
||||
smp_processor_id());
|
||||
}
|
||||
|
||||
#define PMC_INIT 0
|
||||
|
@ -310,6 +334,7 @@ static int __hw_perf_event_init(struct perf_event *event)
|
|||
{
|
||||
struct perf_event_attr *attr = &event->attr;
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
enum cpumf_ctr_set set;
|
||||
int err;
|
||||
u64 ev;
|
||||
|
||||
|
@ -353,13 +378,27 @@ static int __hw_perf_event_init(struct perf_event *event)
|
|||
if (ev > PERF_CPUM_CF_MAX_CTR)
|
||||
return -EINVAL;
|
||||
|
||||
/* Use the hardware perf event structure to store the counter number
|
||||
* in 'config' member and the counter set to which the counter belongs
|
||||
* in the 'config_base'. The counter set (config_base) is then used
|
||||
* to enable/disable the counters.
|
||||
*/
|
||||
hwc->config = ev;
|
||||
hwc->config_base = get_counter_set(ev);
|
||||
/* Obtain the counter set to which the specified counter belongs */
|
||||
set = get_counter_set(ev);
|
||||
switch (set) {
|
||||
case CPUMF_CTR_SET_BASIC:
|
||||
case CPUMF_CTR_SET_USER:
|
||||
case CPUMF_CTR_SET_CRYPTO:
|
||||
case CPUMF_CTR_SET_EXT:
|
||||
case CPUMF_CTR_SET_MT_DIAG:
|
||||
/*
|
||||
* Use the hardware perf event structure to store the
|
||||
* counter number in the 'config' member and the counter
|
||||
* set number in the 'config_base'. The counter set number
|
||||
* is then later used to enable/disable the counter(s).
|
||||
*/
|
||||
hwc->config = ev;
|
||||
hwc->config_base = set;
|
||||
break;
|
||||
case CPUMF_CTR_SET_MAX:
|
||||
/* The counter could not be associated to a counter set */
|
||||
return -EINVAL;
|
||||
};
|
||||
|
||||
/* Initialize for using the CPU-measurement counter facility */
|
||||
if (!atomic_inc_not_zero(&num_events)) {
|
||||
|
|
Loading…
Reference in New Issue