Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ee699f32 authored by Hendrik Brueckner's avatar Hendrik Brueckner Committed by Martin Schwidefsky
Browse files

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: default avatarHendrik Brueckner <brueckner@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent db17160d
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -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)
+64 −25
Original line number Diff line number Diff line
@@ -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)
@@ -80,15 +74,16 @@ static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
		[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.
	/* 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 = get_counter_set(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)) {