linux/arch/s390/kernel/perf_cpum_cf_diag.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Performance event support for s390x - CPU-measurement Counter Sets
   4 *
   5 *  Copyright IBM Corp. 2019
   6 *  Author(s): Hendrik Brueckner <brueckner@linux.ibm.com>
   7 *             Thomas Richer <tmricht@linux.ibm.com>
   8 */
   9#define KMSG_COMPONENT  "cpum_cf_diag"
  10#define pr_fmt(fmt)     KMSG_COMPONENT ": " fmt
  11
  12#include <linux/kernel.h>
  13#include <linux/kernel_stat.h>
  14#include <linux/percpu.h>
  15#include <linux/notifier.h>
  16#include <linux/init.h>
  17#include <linux/export.h>
  18#include <linux/slab.h>
  19#include <linux/processor.h>
  20
  21#include <asm/ctl_reg.h>
  22#include <asm/irq.h>
  23#include <asm/cpu_mcf.h>
  24#include <asm/timex.h>
  25#include <asm/debug.h>
  26
  27#define CF_DIAG_CTRSET_DEF              0xfeef  /* Counter set header mark */
  28
  29static unsigned int cf_diag_cpu_speed;
  30static debug_info_t *cf_diag_dbg;
  31
  32struct cf_diag_csd {            /* Counter set data per CPU */
  33        size_t used;                    /* Bytes used in data/start */
  34        unsigned char start[PAGE_SIZE]; /* Counter set at event start */
  35        unsigned char data[PAGE_SIZE];  /* Counter set at event delete */
  36};
  37static DEFINE_PER_CPU(struct cf_diag_csd, cf_diag_csd);
  38
  39/* Counter sets are stored as data stream in a page sized memory buffer and
  40 * exported to user space via raw data attached to the event sample data.
  41 * Each counter set starts with an eight byte header consisting of:
  42 * - a two byte eye catcher (0xfeef)
  43 * - a one byte counter set number
  44 * - a two byte counter set size (indicates the number of counters in this set)
  45 * - a three byte reserved value (must be zero) to make the header the same
  46 *   size as a counter value.
  47 * All counter values are eight byte in size.
  48 *
  49 * All counter sets are followed by a 64 byte trailer.
  50 * The trailer consists of a:
  51 * - flag field indicating valid fields when corresponding bit set
  52 * - the counter facility first and second version number
  53 * - the CPU speed if nonzero
  54 * - the time stamp the counter sets have been collected
  55 * - the time of day (TOD) base value
  56 * - the machine type.
  57 *
  58 * The counter sets are saved when the process is prepared to be executed on a
  59 * CPU and saved again when the process is going to be removed from a CPU.
  60 * The difference of both counter sets are calculated and stored in the event
  61 * sample data area.
  62 */
  63
  64struct cf_ctrset_entry {        /* CPU-M CF counter set entry (8 byte) */
  65        unsigned int def:16;    /* 0-15  Data Entry Format */
  66        unsigned int set:16;    /* 16-31 Counter set identifier */
  67        unsigned int ctr:16;    /* 32-47 Number of stored counters */
  68        unsigned int res1:16;   /* 48-63 Reserved */
  69};
  70
  71struct cf_trailer_entry {       /* CPU-M CF_DIAG trailer (64 byte) */
  72        /* 0 - 7 */
  73        union {
  74                struct {
  75                        unsigned int clock_base:1;      /* TOD clock base set */
  76                        unsigned int speed:1;           /* CPU speed set */
  77                        /* Measurement alerts */
  78                        unsigned int mtda:1;    /* Loss of MT ctr. data alert */
  79                        unsigned int caca:1;    /* Counter auth. change alert */
  80                        unsigned int lcda:1;    /* Loss of counter data alert */
  81                };
  82                unsigned long flags;    /* 0-63    All indicators */
  83        };
  84        /* 8 - 15 */
  85        unsigned int cfvn:16;                   /* 64-79   Ctr First Version */
  86        unsigned int csvn:16;                   /* 80-95   Ctr Second Version */
  87        unsigned int cpu_speed:32;              /* 96-127  CPU speed */
  88        /* 16 - 23 */
  89        unsigned long timestamp;                /* 128-191 Timestamp (TOD) */
  90        /* 24 - 55 */
  91        union {
  92                struct {
  93                        unsigned long progusage1;
  94                        unsigned long progusage2;
  95                        unsigned long progusage3;
  96                        unsigned long tod_base;
  97                };
  98                unsigned long progusage[4];
  99        };
 100        /* 56 - 63 */
 101        unsigned int mach_type:16;              /* Machine type */
 102        unsigned int res1:16;                   /* Reserved */
 103        unsigned int res2:32;                   /* Reserved */
 104};
 105
 106/* Create the trailer data at the end of a page. */
 107static void cf_diag_trailer(struct cf_trailer_entry *te)
 108{
 109        struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
 110        struct cpuid cpuid;
 111
 112        te->cfvn = cpuhw->info.cfvn;            /* Counter version numbers */
 113        te->csvn = cpuhw->info.csvn;
 114
 115        get_cpu_id(&cpuid);                     /* Machine type */
 116        te->mach_type = cpuid.machine;
 117        te->cpu_speed = cf_diag_cpu_speed;
 118        if (te->cpu_speed)
 119                te->speed = 1;
 120        te->clock_base = 1;                     /* Save clock base */
 121        memcpy(&te->tod_base, &tod_clock_base[1], 8);
 122        store_tod_clock((__u64 *)&te->timestamp);
 123}
 124
 125/*
 126 * Change the CPUMF state to active.
 127 * Enable and activate the CPU-counter sets according
 128 * to the per-cpu control state.
 129 */
 130static void cf_diag_enable(struct pmu *pmu)
 131{
 132        struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
 133        int err;
 134
 135        debug_sprintf_event(cf_diag_dbg, 5,
 136                            "%s pmu %p cpu %d flags %#x state %#llx\n",
 137                            __func__, pmu, smp_processor_id(), cpuhw->flags,
 138                            cpuhw->state);
 139        if (cpuhw->flags & PMU_F_ENABLED)
 140                return;
 141
 142        err = lcctl(cpuhw->state);
 143        if (err) {
 144                pr_err("Enabling the performance measuring unit "
 145                       "failed with rc=%x\n", err);
 146                return;
 147        }
 148        cpuhw->flags |= PMU_F_ENABLED;
 149}
 150
 151/*
 152 * Change the CPUMF state to inactive.
 153 * Disable and enable (inactive) the CPU-counter sets according
 154 * to the per-cpu control state.
 155 */
 156static void cf_diag_disable(struct pmu *pmu)
 157{
 158        struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
 159        u64 inactive;
 160        int err;
 161
 162        debug_sprintf_event(cf_diag_dbg, 5,
 163                            "%s pmu %p cpu %d flags %#x state %#llx\n",
 164                            __func__, pmu, smp_processor_id(), cpuhw->flags,
 165                            cpuhw->state);
 166        if (!(cpuhw->flags & PMU_F_ENABLED))
 167                return;
 168
 169        inactive = cpuhw->state & ~((1 << CPUMF_LCCTL_ENABLE_SHIFT) - 1);
 170        err = lcctl(inactive);
 171        if (err) {
 172                pr_err("Disabling the performance measuring unit "
 173                       "failed with rc=%x\n", err);
 174                return;
 175        }
 176        cpuhw->flags &= ~PMU_F_ENABLED;
 177}
 178
 179/* Number of perf events counting hardware events */
 180static atomic_t cf_diag_events = ATOMIC_INIT(0);
 181
 182/* Release the PMU if event is the last perf event */
 183static void cf_diag_perf_event_destroy(struct perf_event *event)
 184{
 185        debug_sprintf_event(cf_diag_dbg, 5,
 186                            "%s event %p cpu %d cf_diag_events %d\n",
 187                            __func__, event, event->cpu,
 188                            atomic_read(&cf_diag_events));
 189        if (atomic_dec_return(&cf_diag_events) == 0)
 190                __kernel_cpumcf_end();
 191}
 192
 193/* Setup the event. Test for authorized counter sets and only include counter
 194 * sets which are authorized at the time of the setup. Including unauthorized
 195 * counter sets result in specification exception (and panic).
 196 */
 197static int __hw_perf_event_init(struct perf_event *event)
 198{
 199        struct perf_event_attr *attr = &event->attr;
 200        struct cpu_cf_events *cpuhw;
 201        enum cpumf_ctr_set i;
 202        int err = 0;
 203
 204        debug_sprintf_event(cf_diag_dbg, 5, "%s event %p cpu %d\n", __func__,
 205                            event, event->cpu);
 206
 207        event->hw.config = attr->config;
 208        event->hw.config_base = 0;
 209
 210        /* Add all authorized counter sets to config_base. The
 211         * the hardware init function is either called per-cpu or just once
 212         * for all CPUS (event->cpu == -1).  This depends on the whether
 213         * counting is started for all CPUs or on a per workload base where
 214         * the perf event moves from one CPU to another CPU.
 215         * Checking the authorization on any CPU is fine as the hardware
 216         * applies the same authorization settings to all CPUs.
 217         */
 218        cpuhw = &get_cpu_var(cpu_cf_events);
 219        for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i)
 220                if (cpuhw->info.auth_ctl & cpumf_ctr_ctl[i])
 221                        event->hw.config_base |= cpumf_ctr_ctl[i];
 222        put_cpu_var(cpu_cf_events);
 223
 224        /* No authorized counter sets, nothing to count/sample */
 225        if (!event->hw.config_base) {
 226                err = -EINVAL;
 227                goto out;
 228        }
 229
 230        /* Set sample_period to indicate sampling */
 231        event->hw.sample_period = attr->sample_period;
 232        local64_set(&event->hw.period_left, event->hw.sample_period);
 233        event->hw.last_period  = event->hw.sample_period;
 234out:
 235        debug_sprintf_event(cf_diag_dbg, 5, "%s err %d config_base %#lx\n",
 236                            __func__, err, event->hw.config_base);
 237        return err;
 238}
 239
 240static int cf_diag_event_init(struct perf_event *event)
 241{
 242        struct perf_event_attr *attr = &event->attr;
 243        int err = -ENOENT;
 244
 245        debug_sprintf_event(cf_diag_dbg, 5,
 246                            "%s event %p cpu %d config %#llx "
 247                            "sample_type %#llx cf_diag_events %d\n", __func__,
 248                            event, event->cpu, attr->config, attr->sample_type,
 249                            atomic_read(&cf_diag_events));
 250
 251        if (event->attr.config != PERF_EVENT_CPUM_CF_DIAG ||
 252            event->attr.type != PERF_TYPE_RAW)
 253                goto out;
 254
 255        /* Raw events are used to access counters directly,
 256         * hence do not permit excludes.
 257         * This event is usesless without PERF_SAMPLE_RAW to return counter set
 258         * values as raw data.
 259         */
 260        if (attr->exclude_kernel || attr->exclude_user || attr->exclude_hv ||
 261            !(attr->sample_type & (PERF_SAMPLE_CPU | PERF_SAMPLE_RAW))) {
 262                err = -EOPNOTSUPP;
 263                goto out;
 264        }
 265
 266        /* Initialize for using the CPU-measurement counter facility */
 267        if (atomic_inc_return(&cf_diag_events) == 1) {
 268                if (__kernel_cpumcf_begin()) {
 269                        atomic_dec(&cf_diag_events);
 270                        err = -EBUSY;
 271                        goto out;
 272                }
 273        }
 274        event->destroy = cf_diag_perf_event_destroy;
 275
 276        err = __hw_perf_event_init(event);
 277        if (unlikely(err))
 278                event->destroy(event);
 279out:
 280        debug_sprintf_event(cf_diag_dbg, 5, "%s err %d\n", __func__, err);
 281        return err;
 282}
 283
 284static void cf_diag_read(struct perf_event *event)
 285{
 286        debug_sprintf_event(cf_diag_dbg, 5, "%s event %p\n", __func__, event);
 287}
 288
 289/* Return the maximum possible counter set size (in number of 8 byte counters)
 290 * depending on type and model number.
 291 */
 292static size_t cf_diag_ctrset_size(enum cpumf_ctr_set ctrset,
 293                                 struct cpumf_ctr_info *info)
 294{
 295        size_t ctrset_size = 0;
 296
 297        switch (ctrset) {
 298        case CPUMF_CTR_SET_BASIC:
 299                if (info->cfvn >= 1)
 300                        ctrset_size = 6;
 301                break;
 302        case CPUMF_CTR_SET_USER:
 303                if (info->cfvn == 1)
 304                        ctrset_size = 6;
 305                else if (info->cfvn >= 3)
 306                        ctrset_size = 2;
 307                break;
 308        case CPUMF_CTR_SET_CRYPTO:
 309                if (info->csvn >= 1 && info->csvn <= 5)
 310                        ctrset_size = 16;
 311                else if (info->csvn == 6)
 312                        ctrset_size = 20;
 313                break;
 314        case CPUMF_CTR_SET_EXT:
 315                if (info->csvn == 1)
 316                        ctrset_size = 32;
 317                else if (info->csvn == 2)
 318                        ctrset_size = 48;
 319                else if (info->csvn >= 3 && info->csvn <= 5)
 320                        ctrset_size = 128;
 321                else if (info->csvn == 6)
 322                        ctrset_size = 160;
 323                break;
 324        case CPUMF_CTR_SET_MT_DIAG:
 325                if (info->csvn > 3)
 326                        ctrset_size = 48;
 327                break;
 328        case CPUMF_CTR_SET_MAX:
 329                break;
 330        }
 331
 332        return ctrset_size;
 333}
 334
 335/* Calculate memory needed to store all counter sets together with header and
 336 * trailer data. This is independend of the counter set authorization which
 337 * can vary depending on the configuration.
 338 */
 339static size_t cf_diag_ctrset_maxsize(struct cpumf_ctr_info *info)
 340{
 341        size_t max_size = sizeof(struct cf_trailer_entry);
 342        enum cpumf_ctr_set i;
 343
 344        for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
 345                size_t size = cf_diag_ctrset_size(i, info);
 346
 347                if (size)
 348                        max_size += size * sizeof(u64) +
 349                                    sizeof(struct cf_ctrset_entry);
 350        }
 351        debug_sprintf_event(cf_diag_dbg, 5, "%s max_size %zu\n", __func__,
 352                            max_size);
 353
 354        return max_size;
 355}
 356
 357/* Read a counter set. The counter set number determines which counter set and
 358 * the CPUM-CF first and second version number determine the number of
 359 * available counters in this counter set.
 360 * Each counter set starts with header containing the counter set number and
 361 * the number of 8 byte counters.
 362 *
 363 * The functions returns the number of bytes occupied by this counter set
 364 * including the header.
 365 * If there is no counter in the counter set, this counter set is useless and
 366 * zero is returned on this case.
 367 */
 368static size_t cf_diag_getctrset(struct cf_ctrset_entry *ctrdata, int ctrset,
 369                                size_t room)
 370{
 371        struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
 372        size_t ctrset_size, need = 0;
 373        int rc = 3;                             /* Assume write failure */
 374
 375        ctrdata->def = CF_DIAG_CTRSET_DEF;
 376        ctrdata->set = ctrset;
 377        ctrdata->res1 = 0;
 378        ctrset_size = cf_diag_ctrset_size(ctrset, &cpuhw->info);
 379
 380        if (ctrset_size) {                      /* Save data */
 381                need = ctrset_size * sizeof(u64) + sizeof(*ctrdata);
 382                if (need <= room)
 383                        rc = ctr_stcctm(ctrset, ctrset_size,
 384                                        (u64 *)(ctrdata + 1));
 385                if (rc != 3)
 386                        ctrdata->ctr = ctrset_size;
 387                else
 388                        need = 0;
 389        }
 390
 391        debug_sprintf_event(cf_diag_dbg, 6,
 392                            "%s ctrset %d ctrset_size %zu cfvn %d csvn %d"
 393                            " need %zd rc:%d\n",
 394                            __func__, ctrset, ctrset_size, cpuhw->info.cfvn,
 395                            cpuhw->info.csvn, need, rc);
 396        return need;
 397}
 398
 399/* Read out all counter sets and save them in the provided data buffer.
 400 * The last 64 byte host an artificial trailer entry.
 401 */
 402static size_t cf_diag_getctr(void *data, size_t sz, unsigned long auth)
 403{
 404        struct cf_trailer_entry *trailer;
 405        size_t offset = 0, done;
 406        int i;
 407
 408        memset(data, 0, sz);
 409        sz -= sizeof(*trailer);                 /* Always room for trailer */
 410        for (i = CPUMF_CTR_SET_BASIC; i < CPUMF_CTR_SET_MAX; ++i) {
 411                struct cf_ctrset_entry *ctrdata = data + offset;
 412
 413                if (!(auth & cpumf_ctr_ctl[i]))
 414                        continue;       /* Counter set not authorized */
 415
 416                done = cf_diag_getctrset(ctrdata, i, sz - offset);
 417                offset += done;
 418                debug_sprintf_event(cf_diag_dbg, 6,
 419                                    "%s ctrset %d offset %zu done %zu\n",
 420                                     __func__, i, offset, done);
 421        }
 422        trailer = data + offset;
 423        cf_diag_trailer(trailer);
 424        return offset + sizeof(*trailer);
 425}
 426
 427/* Calculate the difference for each counter in a counter set. */
 428static void cf_diag_diffctrset(u64 *pstart, u64 *pstop, int counters)
 429{
 430        for (; --counters >= 0; ++pstart, ++pstop)
 431                if (*pstop >= *pstart)
 432                        *pstop -= *pstart;
 433                else
 434                        *pstop = *pstart - *pstop;
 435}
 436
 437/* Scan the counter sets and calculate the difference of each counter
 438 * in each set. The result is the increment of each counter during the
 439 * period the counter set has been activated.
 440 *
 441 * Return true on success.
 442 */
 443static int cf_diag_diffctr(struct cf_diag_csd *csd, unsigned long auth)
 444{
 445        struct cf_trailer_entry *trailer_start, *trailer_stop;
 446        struct cf_ctrset_entry *ctrstart, *ctrstop;
 447        size_t offset = 0;
 448
 449        auth &= (1 << CPUMF_LCCTL_ENABLE_SHIFT) - 1;
 450        do {
 451                ctrstart = (struct cf_ctrset_entry *)(csd->start + offset);
 452                ctrstop = (struct cf_ctrset_entry *)(csd->data + offset);
 453
 454                if (memcmp(ctrstop, ctrstart, sizeof(*ctrstop))) {
 455                        pr_err("cpum_cf_diag counter set compare error "
 456                                "in set %i\n", ctrstart->set);
 457                        return 0;
 458                }
 459                auth &= ~cpumf_ctr_ctl[ctrstart->set];
 460                if (ctrstart->def == CF_DIAG_CTRSET_DEF) {
 461                        cf_diag_diffctrset((u64 *)(ctrstart + 1),
 462                                          (u64 *)(ctrstop + 1), ctrstart->ctr);
 463                        offset += ctrstart->ctr * sizeof(u64) +
 464                                  sizeof(*ctrstart);
 465                }
 466                debug_sprintf_event(cf_diag_dbg, 6,
 467                                    "%s set %d ctr %d offset %zu auth %lx\n",
 468                                    __func__, ctrstart->set, ctrstart->ctr,
 469                                    offset, auth);
 470        } while (ctrstart->def && auth);
 471
 472        /* Save time_stamp from start of event in stop's trailer */
 473        trailer_start = (struct cf_trailer_entry *)(csd->start + offset);
 474        trailer_stop = (struct cf_trailer_entry *)(csd->data + offset);
 475        trailer_stop->progusage[0] = trailer_start->timestamp;
 476
 477        return 1;
 478}
 479
 480/* Create perf event sample with the counter sets as raw data.  The sample
 481 * is then pushed to the event subsystem and the function checks for
 482 * possible event overflows. If an event overflow occurs, the PMU is
 483 * stopped.
 484 *
 485 * Return non-zero if an event overflow occurred.
 486 */
 487static int cf_diag_push_sample(struct perf_event *event,
 488                               struct cf_diag_csd *csd)
 489{
 490        struct perf_sample_data data;
 491        struct perf_raw_record raw;
 492        struct pt_regs regs;
 493        int overflow;
 494
 495        /* Setup perf sample */
 496        perf_sample_data_init(&data, 0, event->hw.last_period);
 497        memset(&regs, 0, sizeof(regs));
 498        memset(&raw, 0, sizeof(raw));
 499
 500        if (event->attr.sample_type & PERF_SAMPLE_CPU)
 501                data.cpu_entry.cpu = event->cpu;
 502        if (event->attr.sample_type & PERF_SAMPLE_RAW) {
 503                raw.frag.size = csd->used;
 504                raw.frag.data = csd->data;
 505                raw.size = csd->used;
 506                data.raw = &raw;
 507        }
 508
 509        overflow = perf_event_overflow(event, &data, &regs);
 510        debug_sprintf_event(cf_diag_dbg, 6,
 511                            "%s event %p cpu %d sample_type %#llx raw %d "
 512                            "ov %d\n", __func__, event, event->cpu,
 513                            event->attr.sample_type, raw.size, overflow);
 514        if (overflow)
 515                event->pmu->stop(event, 0);
 516
 517        perf_event_update_userpage(event);
 518        return overflow;
 519}
 520
 521static void cf_diag_start(struct perf_event *event, int flags)
 522{
 523        struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
 524        struct cf_diag_csd *csd = this_cpu_ptr(&cf_diag_csd);
 525        struct hw_perf_event *hwc = &event->hw;
 526
 527        debug_sprintf_event(cf_diag_dbg, 5,
 528                            "%s event %p cpu %d flags %#x hwc-state %#x\n",
 529                            __func__, event, event->cpu, flags, hwc->state);
 530        if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
 531                return;
 532
 533        /* (Re-)enable and activate all counter sets */
 534        lcctl(0);               /* Reset counter sets */
 535        hwc->state = 0;
 536        ctr_set_multiple_enable(&cpuhw->state, hwc->config_base);
 537        lcctl(cpuhw->state);    /* Enable counter sets */
 538        csd->used = cf_diag_getctr(csd->start, sizeof(csd->start),
 539                                   event->hw.config_base);
 540        ctr_set_multiple_start(&cpuhw->state, hwc->config_base);
 541        /* Function cf_diag_enable() starts the counter sets. */
 542}
 543
 544static void cf_diag_stop(struct perf_event *event, int flags)
 545{
 546        struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
 547        struct cf_diag_csd *csd = this_cpu_ptr(&cf_diag_csd);
 548        struct hw_perf_event *hwc = &event->hw;
 549
 550        debug_sprintf_event(cf_diag_dbg, 5,
 551                            "%s event %p cpu %d flags %#x hwc-state %#x\n",
 552                            __func__, event, event->cpu, flags, hwc->state);
 553
 554        /* Deactivate all counter sets */
 555        ctr_set_multiple_stop(&cpuhw->state, hwc->config_base);
 556        local64_inc(&event->count);
 557        csd->used = cf_diag_getctr(csd->data, sizeof(csd->data),
 558                                   event->hw.config_base);
 559        if (cf_diag_diffctr(csd, event->hw.config_base))
 560                cf_diag_push_sample(event, csd);
 561        hwc->state |= PERF_HES_STOPPED;
 562}
 563
 564static int cf_diag_add(struct perf_event *event, int flags)
 565{
 566        struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
 567        int err = 0;
 568
 569        debug_sprintf_event(cf_diag_dbg, 5,
 570                            "%s event %p cpu %d flags %#x cpuhw:%p\n",
 571                            __func__, event, event->cpu, flags, cpuhw);
 572
 573        if (cpuhw->flags & PMU_F_IN_USE) {
 574                err = -EAGAIN;
 575                goto out;
 576        }
 577
 578        event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
 579
 580        cpuhw->flags |= PMU_F_IN_USE;
 581        if (flags & PERF_EF_START)
 582                cf_diag_start(event, PERF_EF_RELOAD);
 583out:
 584        debug_sprintf_event(cf_diag_dbg, 5, "%s err %d\n", __func__, err);
 585        return err;
 586}
 587
 588static void cf_diag_del(struct perf_event *event, int flags)
 589{
 590        struct cpu_cf_events *cpuhw = this_cpu_ptr(&cpu_cf_events);
 591
 592        debug_sprintf_event(cf_diag_dbg, 5,
 593                            "%s event %p cpu %d flags %#x\n",
 594                           __func__, event, event->cpu, flags);
 595
 596        cf_diag_stop(event, PERF_EF_UPDATE);
 597        ctr_set_multiple_stop(&cpuhw->state, event->hw.config_base);
 598        ctr_set_multiple_disable(&cpuhw->state, event->hw.config_base);
 599        cpuhw->flags &= ~PMU_F_IN_USE;
 600}
 601
 602CPUMF_EVENT_ATTR(CF_DIAG, CF_DIAG, PERF_EVENT_CPUM_CF_DIAG);
 603
 604static struct attribute *cf_diag_events_attr[] = {
 605        CPUMF_EVENT_PTR(CF_DIAG, CF_DIAG),
 606        NULL,
 607};
 608
 609PMU_FORMAT_ATTR(event, "config:0-63");
 610
 611static struct attribute *cf_diag_format_attr[] = {
 612        &format_attr_event.attr,
 613        NULL,
 614};
 615
 616static struct attribute_group cf_diag_events_group = {
 617        .name = "events",
 618        .attrs = cf_diag_events_attr,
 619};
 620static struct attribute_group cf_diag_format_group = {
 621        .name = "format",
 622        .attrs = cf_diag_format_attr,
 623};
 624static const struct attribute_group *cf_diag_attr_groups[] = {
 625        &cf_diag_events_group,
 626        &cf_diag_format_group,
 627        NULL,
 628};
 629
 630/* Performance monitoring unit for s390x */
 631static struct pmu cf_diag = {
 632        .task_ctx_nr  = perf_sw_context,
 633        .pmu_enable   = cf_diag_enable,
 634        .pmu_disable  = cf_diag_disable,
 635        .event_init   = cf_diag_event_init,
 636        .add          = cf_diag_add,
 637        .del          = cf_diag_del,
 638        .start        = cf_diag_start,
 639        .stop         = cf_diag_stop,
 640        .read         = cf_diag_read,
 641
 642        .attr_groups  = cf_diag_attr_groups
 643};
 644
 645/* Get the CPU speed, try sampling facility first and CPU attributes second. */
 646static void cf_diag_get_cpu_speed(void)
 647{
 648        if (cpum_sf_avail()) {                  /* Sampling facility first */
 649                struct hws_qsi_info_block si;
 650
 651                memset(&si, 0, sizeof(si));
 652                if (!qsi(&si)) {
 653                        cf_diag_cpu_speed = si.cpu_speed;
 654                        return;
 655                }
 656        }
 657
 658        if (test_facility(34)) {                /* CPU speed extract static part */
 659                unsigned long mhz = __ecag(ECAG_CPU_ATTRIBUTE, 0);
 660
 661                if (mhz != -1UL)
 662                        cf_diag_cpu_speed = mhz & 0xffffffff;
 663        }
 664}
 665
 666/* Initialize the counter set PMU to generate complete counter set data as
 667 * event raw data. This relies on the CPU Measurement Counter Facility device
 668 * already being loaded and initialized.
 669 */
 670static int __init cf_diag_init(void)
 671{
 672        struct cpumf_ctr_info info;
 673        size_t need;
 674        int rc;
 675
 676        if (!kernel_cpumcf_avail() || !stccm_avail() || qctri(&info))
 677                return -ENODEV;
 678        cf_diag_get_cpu_speed();
 679
 680        /* Make sure the counter set data fits into predefined buffer. */
 681        need = cf_diag_ctrset_maxsize(&info);
 682        if (need > sizeof(((struct cf_diag_csd *)0)->start)) {
 683                pr_err("Insufficient memory for PMU(cpum_cf_diag) need=%zu\n",
 684                       need);
 685                return -ENOMEM;
 686        }
 687
 688        /* Setup s390dbf facility */
 689        cf_diag_dbg = debug_register(KMSG_COMPONENT, 2, 1, 128);
 690        if (!cf_diag_dbg) {
 691                pr_err("Registration of s390dbf(cpum_cf_diag) failed\n");
 692                return -ENOMEM;
 693        }
 694        debug_register_view(cf_diag_dbg, &debug_sprintf_view);
 695
 696        rc = perf_pmu_register(&cf_diag, "cpum_cf_diag", PERF_TYPE_RAW);
 697        if (rc) {
 698                debug_unregister_view(cf_diag_dbg, &debug_sprintf_view);
 699                debug_unregister(cf_diag_dbg);
 700                pr_err("Registration of PMU(cpum_cf_diag) failed with rc=%i\n",
 701                       rc);
 702        }
 703        return rc;
 704}
 705arch_initcall(cf_diag_init);
 706