mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-23 23:32:14 +00:00
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
2 changed files with 67 additions and 26 deletions
|
@ -20,9 +20,11 @@
|
||||||
#define CPU_MF_INT_SF_PRA (1 << 29) /* program request alert */
|
#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_SACA (1 << 23) /* sampler auth. change alert */
|
||||||
#define CPU_MF_INT_SF_LSDA (1 << 22) /* loss of sample data 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_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_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| \
|
#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_PRA|CPU_MF_INT_SF_SACA| \
|
||||||
CPU_MF_INT_SF_LSDA)
|
CPU_MF_INT_SF_LSDA)
|
||||||
|
|
|
@ -22,19 +22,12 @@
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/cpu_mf.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 {
|
enum cpumf_ctr_set {
|
||||||
/* CPU counter sets */
|
CPUMF_CTR_SET_BASIC = 0, /* Basic Counter Set */
|
||||||
CPUMF_CTR_SET_BASIC = 0,
|
CPUMF_CTR_SET_USER = 1, /* Problem-State Counter Set */
|
||||||
CPUMF_CTR_SET_USER = 1,
|
CPUMF_CTR_SET_CRYPTO = 2, /* Crypto-Activity Counter Set */
|
||||||
CPUMF_CTR_SET_CRYPTO = 2,
|
CPUMF_CTR_SET_EXT = 3, /* Extended Counter Set */
|
||||||
CPUMF_CTR_SET_EXT = 3,
|
CPUMF_CTR_SET_MT_DIAG = 4, /* MT-diagnostic Counter Set */
|
||||||
|
|
||||||
/* Maximum number of counter sets */
|
/* Maximum number of counter sets */
|
||||||
CPUMF_CTR_SET_MAX,
|
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_USER] = 0x04,
|
||||||
[CPUMF_CTR_SET_CRYPTO] = 0x08,
|
[CPUMF_CTR_SET_CRYPTO] = 0x08,
|
||||||
[CPUMF_CTR_SET_EXT] = 0x01,
|
[CPUMF_CTR_SET_EXT] = 0x01,
|
||||||
|
[CPUMF_CTR_SET_MT_DIAG] = 0x20,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void ctr_set_enable(u64 *state, int ctr_set)
|
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) = {
|
static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
|
||||||
.ctr_set = {
|
.ctr_set = {
|
||||||
[CPUMF_CTR_SET_BASIC] = ATOMIC_INIT(0),
|
[CPUMF_CTR_SET_BASIC] = ATOMIC_INIT(0),
|
||||||
[CPUMF_CTR_SET_USER] = ATOMIC_INIT(0),
|
[CPUMF_CTR_SET_USER] = ATOMIC_INIT(0),
|
||||||
[CPUMF_CTR_SET_CRYPTO] = ATOMIC_INIT(0),
|
[CPUMF_CTR_SET_CRYPTO] = ATOMIC_INIT(0),
|
||||||
[CPUMF_CTR_SET_EXT] = ATOMIC_INIT(0),
|
[CPUMF_CTR_SET_EXT] = ATOMIC_INIT(0),
|
||||||
|
[CPUMF_CTR_SET_MT_DIAG] = ATOMIC_INIT(0),
|
||||||
},
|
},
|
||||||
.state = 0,
|
.state = 0,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.txn_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)
|
if (event < 32)
|
||||||
set = CPUMF_CTR_SET_BASIC;
|
set = CPUMF_CTR_SET_BASIC;
|
||||||
|
@ -98,6 +93,8 @@ static int get_counter_set(u64 event)
|
||||||
set = CPUMF_CTR_SET_CRYPTO;
|
set = CPUMF_CTR_SET_CRYPTO;
|
||||||
else if (event < 256)
|
else if (event < 256)
|
||||||
set = CPUMF_CTR_SET_EXT;
|
set = CPUMF_CTR_SET_EXT;
|
||||||
|
else if (event >= 448 && event < 496)
|
||||||
|
set = CPUMF_CTR_SET_MT_DIAG;
|
||||||
|
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
@ -106,6 +103,7 @@ static int validate_ctr_version(const struct hw_perf_event *hwc)
|
||||||
{
|
{
|
||||||
struct cpu_hw_events *cpuhw;
|
struct cpu_hw_events *cpuhw;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
u16 mtdiag_ctl;
|
||||||
|
|
||||||
cpuhw = &get_cpu_var(cpu_hw_events);
|
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))
|
(cpuhw->info.csvn > 2 && hwc->config > 255))
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
break;
|
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);
|
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 */
|
/* loss of counter data alert */
|
||||||
if (alert & CPU_MF_INT_CF_LCDA)
|
if (alert & CPU_MF_INT_CF_LCDA)
|
||||||
pr_err("CPU[%i] Counter data was lost\n", smp_processor_id());
|
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
|
#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 perf_event_attr *attr = &event->attr;
|
||||||
struct hw_perf_event *hwc = &event->hw;
|
struct hw_perf_event *hwc = &event->hw;
|
||||||
|
enum cpumf_ctr_set set;
|
||||||
int err;
|
int err;
|
||||||
u64 ev;
|
u64 ev;
|
||||||
|
|
||||||
|
@ -353,13 +378,27 @@ static int __hw_perf_event_init(struct perf_event *event)
|
||||||
if (ev > PERF_CPUM_CF_MAX_CTR)
|
if (ev > PERF_CPUM_CF_MAX_CTR)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Use the hardware perf event structure to store the counter number
|
/* Obtain the counter set to which the specified counter belongs */
|
||||||
* in 'config' member and the counter set to which the counter belongs
|
set = get_counter_set(ev);
|
||||||
* in the 'config_base'. The counter set (config_base) is then used
|
switch (set) {
|
||||||
* to enable/disable the counters.
|
case CPUMF_CTR_SET_BASIC:
|
||||||
*/
|
case CPUMF_CTR_SET_USER:
|
||||||
hwc->config = ev;
|
case CPUMF_CTR_SET_CRYPTO:
|
||||||
hwc->config_base = get_counter_set(ev);
|
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 */
|
/* Initialize for using the CPU-measurement counter facility */
|
||||||
if (!atomic_inc_not_zero(&num_events)) {
|
if (!atomic_inc_not_zero(&num_events)) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue