root/arch/s390/kernel/perf_cpum_cf_diag.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cf_diag_trailer
  2. cf_diag_enable
  3. cf_diag_disable
  4. cf_diag_perf_event_destroy
  5. __hw_perf_event_init
  6. cf_diag_event_init
  7. cf_diag_read
  8. cf_diag_ctrset_size
  9. cf_diag_ctrset_maxsize
  10. cf_diag_getctrset
  11. cf_diag_getctr
  12. cf_diag_diffctrset
  13. cf_diag_diffctr
  14. cf_diag_push_sample
  15. cf_diag_start
  16. cf_diag_stop
  17. cf_diag_add
  18. cf_diag_del
  19. cf_diag_get_cpu_speed
  20. cf_diag_init

   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 
  29 static unsigned int cf_diag_cpu_speed;
  30 static debug_info_t *cf_diag_dbg;
  31 
  32 struct 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 };
  37 static 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 
  64 struct 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 
  71 struct 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. */
 107 static 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  */
 130 static 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  */
 156 static 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 */
 180 static atomic_t cf_diag_events = ATOMIC_INIT(0);
 181 
 182 /* Release the PMU if event is the last perf event */
 183 static 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  */
 197 static 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;
 234 out:
 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 
 240 static 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 type:%u "
 247                             "sample_type %#llx cf_diag_events %d\n", __func__,
 248                             event, event->cpu, attr->config, event->pmu->type,
 249                             attr->sample_type, atomic_read(&cf_diag_events));
 250 
 251         if (event->attr.config != PERF_EVENT_CPUM_CF_DIAG ||
 252             event->attr.type != event->pmu->type)
 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);
 279 out:
 280         debug_sprintf_event(cf_diag_dbg, 5, "%s err %d\n", __func__, err);
 281         return err;
 282 }
 283 
 284 static 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  */
 292 static 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  */
 339 static 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  */
 368 static 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  */
 402 static 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. */
 428 static 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  */
 443 static 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  */
 487 static 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 
 521 static 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 
 544 static 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 
 564 static 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);
 583 out:
 584         debug_sprintf_event(cf_diag_dbg, 5, "%s err %d\n", __func__, err);
 585         return err;
 586 }
 587 
 588 static 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 
 602 CPUMF_EVENT_ATTR(CF_DIAG, CF_DIAG, PERF_EVENT_CPUM_CF_DIAG);
 603 
 604 static struct attribute *cf_diag_events_attr[] = {
 605         CPUMF_EVENT_PTR(CF_DIAG, CF_DIAG),
 606         NULL,
 607 };
 608 
 609 PMU_FORMAT_ATTR(event, "config:0-63");
 610 
 611 static struct attribute *cf_diag_format_attr[] = {
 612         &format_attr_event.attr,
 613         NULL,
 614 };
 615 
 616 static struct attribute_group cf_diag_events_group = {
 617         .name = "events",
 618         .attrs = cf_diag_events_attr,
 619 };
 620 static struct attribute_group cf_diag_format_group = {
 621         .name = "format",
 622         .attrs = cf_diag_format_attr,
 623 };
 624 static 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 */
 631 static 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. */
 646 static 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  */
 670 static 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", -1);
 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 }
 705 arch_initcall(cf_diag_init);

/* [<][>][^][v][top][bottom][index][help] */