linux/tools/testing/selftests/powerpc/pmu/ebb/ebb.c
<<
>>
Prefs
   1/*
   2 * Copyright 2014, Michael Ellerman, IBM Corp.
   3 * Licensed under GPLv2.
   4 */
   5
   6#define _GNU_SOURCE     /* For CPU_ZERO etc. */
   7
   8#include <sched.h>
   9#include <sys/wait.h>
  10#include <setjmp.h>
  11#include <signal.h>
  12#include <stdio.h>
  13#include <stdlib.h>
  14#include <string.h>
  15#include <sys/ioctl.h>
  16
  17#include "trace.h"
  18#include "reg.h"
  19#include "ebb.h"
  20
  21
  22void (*ebb_user_func)(void);
  23
  24void ebb_hook(void)
  25{
  26        if (ebb_user_func)
  27                ebb_user_func();
  28}
  29
  30struct ebb_state ebb_state;
  31
  32u64 sample_period = 0x40000000ull;
  33
  34void reset_ebb_with_clear_mask(unsigned long mmcr0_clear_mask)
  35{
  36        u64 val;
  37
  38        /* 2) clear MMCR0[PMAO] - docs say BESCR[PMEO] should do this */
  39        /* 3) set MMCR0[PMAE]   - docs say BESCR[PME] should do this */
  40        val = mfspr(SPRN_MMCR0);
  41        mtspr(SPRN_MMCR0, (val & ~mmcr0_clear_mask) | MMCR0_PMAE);
  42
  43        /* 4) clear BESCR[PMEO] */
  44        mtspr(SPRN_BESCRR, BESCR_PMEO);
  45
  46        /* 5) set BESCR[PME] */
  47        mtspr(SPRN_BESCRS, BESCR_PME);
  48
  49        /* 6) rfebb 1 - done in our caller */
  50}
  51
  52void reset_ebb(void)
  53{
  54        reset_ebb_with_clear_mask(MMCR0_PMAO | MMCR0_FC);
  55}
  56
  57/* Called outside of the EBB handler to check MMCR0 is sane */
  58int ebb_check_mmcr0(void)
  59{
  60        u64 val;
  61
  62        val = mfspr(SPRN_MMCR0);
  63        if ((val & (MMCR0_FC | MMCR0_PMAO)) == MMCR0_FC) {
  64                /* It's OK if we see FC & PMAO, but not FC by itself */
  65                printf("Outside of loop, only FC set 0x%llx\n", val);
  66                return 1;
  67        }
  68
  69        return 0;
  70}
  71
  72bool ebb_check_count(int pmc, u64 sample_period, int fudge)
  73{
  74        u64 count, upper, lower;
  75
  76        count = ebb_state.stats.pmc_count[PMC_INDEX(pmc)];
  77
  78        lower = ebb_state.stats.ebb_count * (sample_period - fudge);
  79
  80        if (count < lower) {
  81                printf("PMC%d count (0x%llx) below lower limit 0x%llx (-0x%llx)\n",
  82                        pmc, count, lower, lower - count);
  83                return false;
  84        }
  85
  86        upper = ebb_state.stats.ebb_count * (sample_period + fudge);
  87
  88        if (count > upper) {
  89                printf("PMC%d count (0x%llx) above upper limit 0x%llx (+0x%llx)\n",
  90                        pmc, count, upper, count - upper);
  91                return false;
  92        }
  93
  94        printf("PMC%d count (0x%llx) is between 0x%llx and 0x%llx delta +0x%llx/-0x%llx\n",
  95                pmc, count, lower, upper, count - lower, upper - count);
  96
  97        return true;
  98}
  99
 100void standard_ebb_callee(void)
 101{
 102        int found, i;
 103        u64 val;
 104
 105        val = mfspr(SPRN_BESCR);
 106        if (!(val & BESCR_PMEO)) {
 107                ebb_state.stats.spurious++;
 108                goto out;
 109        }
 110
 111        ebb_state.stats.ebb_count++;
 112        trace_log_counter(ebb_state.trace, ebb_state.stats.ebb_count);
 113
 114        val = mfspr(SPRN_MMCR0);
 115        trace_log_reg(ebb_state.trace, SPRN_MMCR0, val);
 116
 117        found = 0;
 118        for (i = 1; i <= 6; i++) {
 119                if (ebb_state.pmc_enable[PMC_INDEX(i)])
 120                        found += count_pmc(i, sample_period);
 121        }
 122
 123        if (!found)
 124                ebb_state.stats.no_overflow++;
 125
 126out:
 127        reset_ebb();
 128}
 129
 130extern void ebb_handler(void);
 131
 132void setup_ebb_handler(void (*callee)(void))
 133{
 134        u64 entry;
 135
 136#if defined(_CALL_ELF) && _CALL_ELF == 2
 137        entry = (u64)ebb_handler;
 138#else
 139        struct opd
 140        {
 141            u64 entry;
 142            u64 toc;
 143        } *opd;
 144
 145        opd = (struct opd *)ebb_handler;
 146        entry = opd->entry;
 147#endif
 148        printf("EBB Handler is at %#llx\n", entry);
 149
 150        ebb_user_func = callee;
 151
 152        /* Ensure ebb_user_func is set before we set the handler */
 153        mb();
 154        mtspr(SPRN_EBBHR, entry);
 155
 156        /* Make sure the handler is set before we return */
 157        mb();
 158}
 159
 160void clear_ebb_stats(void)
 161{
 162        memset(&ebb_state.stats, 0, sizeof(ebb_state.stats));
 163}
 164
 165void dump_summary_ebb_state(void)
 166{
 167        printf("ebb_state:\n"                   \
 168               "  ebb_count    = %d\n"          \
 169               "  spurious     = %d\n"          \
 170               "  negative     = %d\n"          \
 171               "  no_overflow  = %d\n"          \
 172               "  pmc[1] count = 0x%llx\n"      \
 173               "  pmc[2] count = 0x%llx\n"      \
 174               "  pmc[3] count = 0x%llx\n"      \
 175               "  pmc[4] count = 0x%llx\n"      \
 176               "  pmc[5] count = 0x%llx\n"      \
 177               "  pmc[6] count = 0x%llx\n",
 178                ebb_state.stats.ebb_count, ebb_state.stats.spurious,
 179                ebb_state.stats.negative, ebb_state.stats.no_overflow,
 180                ebb_state.stats.pmc_count[0], ebb_state.stats.pmc_count[1],
 181                ebb_state.stats.pmc_count[2], ebb_state.stats.pmc_count[3],
 182                ebb_state.stats.pmc_count[4], ebb_state.stats.pmc_count[5]);
 183}
 184
 185static char *decode_mmcr0(u32 value)
 186{
 187        static char buf[16];
 188
 189        buf[0] = '\0';
 190
 191        if (value & (1 << 31))
 192                strcat(buf, "FC ");
 193        if (value & (1 << 26))
 194                strcat(buf, "PMAE ");
 195        if (value & (1 << 7))
 196                strcat(buf, "PMAO ");
 197
 198        return buf;
 199}
 200
 201static char *decode_bescr(u64 value)
 202{
 203        static char buf[16];
 204
 205        buf[0] = '\0';
 206
 207        if (value & (1ull << 63))
 208                strcat(buf, "GE ");
 209        if (value & (1ull << 32))
 210                strcat(buf, "PMAE ");
 211        if (value & 1)
 212                strcat(buf, "PMAO ");
 213
 214        return buf;
 215}
 216
 217void dump_ebb_hw_state(void)
 218{
 219        u64 bescr;
 220        u32 mmcr0;
 221
 222        mmcr0 = mfspr(SPRN_MMCR0);
 223        bescr = mfspr(SPRN_BESCR);
 224
 225        printf("HW state:\n"            \
 226               "MMCR0 0x%016x %s\n"     \
 227               "MMCR2 0x%016lx\n"       \
 228               "EBBHR 0x%016lx\n"       \
 229               "BESCR 0x%016llx %s\n"   \
 230               "PMC1  0x%016lx\n"       \
 231               "PMC2  0x%016lx\n"       \
 232               "PMC3  0x%016lx\n"       \
 233               "PMC4  0x%016lx\n"       \
 234               "PMC5  0x%016lx\n"       \
 235               "PMC6  0x%016lx\n"       \
 236               "SIAR  0x%016lx\n",
 237               mmcr0, decode_mmcr0(mmcr0), mfspr(SPRN_MMCR2),
 238               mfspr(SPRN_EBBHR), bescr, decode_bescr(bescr),
 239               mfspr(SPRN_PMC1), mfspr(SPRN_PMC2), mfspr(SPRN_PMC3),
 240               mfspr(SPRN_PMC4), mfspr(SPRN_PMC5), mfspr(SPRN_PMC6),
 241               mfspr(SPRN_SIAR));
 242}
 243
 244void dump_ebb_state(void)
 245{
 246        dump_summary_ebb_state();
 247
 248        dump_ebb_hw_state();
 249
 250        trace_buffer_print(ebb_state.trace);
 251}
 252
 253int count_pmc(int pmc, uint32_t sample_period)
 254{
 255        uint32_t start_value;
 256        u64 val;
 257
 258        /* 0) Read PMC */
 259        start_value = pmc_sample_period(sample_period);
 260
 261        val = read_pmc(pmc);
 262        if (val < start_value)
 263                ebb_state.stats.negative++;
 264        else
 265                ebb_state.stats.pmc_count[PMC_INDEX(pmc)] += val - start_value;
 266
 267        trace_log_reg(ebb_state.trace, SPRN_PMC1 + pmc - 1, val);
 268
 269        /* 1) Reset PMC */
 270        write_pmc(pmc, start_value);
 271
 272        /* Report if we overflowed */
 273        return val >= COUNTER_OVERFLOW;
 274}
 275
 276int ebb_event_enable(struct event *e)
 277{
 278        int rc;
 279
 280        /* Ensure any SPR writes are ordered vs us */
 281        mb();
 282
 283        rc = ioctl(e->fd, PERF_EVENT_IOC_ENABLE);
 284        if (rc)
 285                return rc;
 286
 287        rc = event_read(e);
 288
 289        /* Ditto */
 290        mb();
 291
 292        return rc;
 293}
 294
 295void ebb_freeze_pmcs(void)
 296{
 297        mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) | MMCR0_FC);
 298        mb();
 299}
 300
 301void ebb_unfreeze_pmcs(void)
 302{
 303        /* Unfreeze counters */
 304        mtspr(SPRN_MMCR0, mfspr(SPRN_MMCR0) & ~MMCR0_FC);
 305        mb();
 306}
 307
 308void ebb_global_enable(void)
 309{
 310        /* Enable EBBs globally and PMU EBBs */
 311        mtspr(SPRN_BESCR, 0x8000000100000000ull);
 312        mb();
 313}
 314
 315void ebb_global_disable(void)
 316{
 317        /* Disable EBBs & freeze counters, events are still scheduled */
 318        mtspr(SPRN_BESCRR, BESCR_PME);
 319        mb();
 320}
 321
 322void event_ebb_init(struct event *e)
 323{
 324        e->attr.config |= (1ull << 63);
 325}
 326
 327void event_bhrb_init(struct event *e, unsigned ifm)
 328{
 329        e->attr.config |= (1ull << 62) | ((u64)ifm << 60);
 330}
 331
 332void event_leader_ebb_init(struct event *e)
 333{
 334        event_ebb_init(e);
 335
 336        e->attr.exclusive = 1;
 337        e->attr.pinned = 1;
 338}
 339
 340int ebb_child(union pipe read_pipe, union pipe write_pipe)
 341{
 342        struct event event;
 343        uint64_t val;
 344
 345        FAIL_IF(wait_for_parent(read_pipe));
 346
 347        event_init_named(&event, 0x1001e, "cycles");
 348        event_leader_ebb_init(&event);
 349
 350        event.attr.exclude_kernel = 1;
 351        event.attr.exclude_hv = 1;
 352        event.attr.exclude_idle = 1;
 353
 354        FAIL_IF(event_open(&event));
 355
 356        ebb_enable_pmc_counting(1);
 357        setup_ebb_handler(standard_ebb_callee);
 358        ebb_global_enable();
 359
 360        FAIL_IF(event_enable(&event));
 361
 362        if (event_read(&event)) {
 363                /*
 364                 * Some tests expect to fail here, so don't report an error on
 365                 * this line, and return a distinguisable error code. Tell the
 366                 * parent an error happened.
 367                 */
 368                notify_parent_of_error(write_pipe);
 369                return 2;
 370        }
 371
 372        mtspr(SPRN_PMC1, pmc_sample_period(sample_period));
 373
 374        FAIL_IF(notify_parent(write_pipe));
 375        FAIL_IF(wait_for_parent(read_pipe));
 376        FAIL_IF(notify_parent(write_pipe));
 377
 378        while (ebb_state.stats.ebb_count < 20) {
 379                FAIL_IF(core_busy_loop());
 380
 381                /* To try and hit SIGILL case */
 382                val  = mfspr(SPRN_MMCRA);
 383                val |= mfspr(SPRN_MMCR2);
 384                val |= mfspr(SPRN_MMCR0);
 385        }
 386
 387        ebb_global_disable();
 388        ebb_freeze_pmcs();
 389
 390        count_pmc(1, sample_period);
 391
 392        dump_ebb_state();
 393
 394        event_close(&event);
 395
 396        FAIL_IF(ebb_state.stats.ebb_count == 0);
 397
 398        return 0;
 399}
 400
 401static jmp_buf setjmp_env;
 402
 403static void sigill_handler(int signal)
 404{
 405        printf("Took sigill\n");
 406        longjmp(setjmp_env, 1);
 407}
 408
 409static struct sigaction sigill_action = {
 410        .sa_handler = sigill_handler,
 411};
 412
 413int catch_sigill(void (*func)(void))
 414{
 415        if (sigaction(SIGILL, &sigill_action, NULL)) {
 416                perror("sigaction");
 417                return 1;
 418        }
 419
 420        if (setjmp(setjmp_env) == 0) {
 421                func();
 422                return 1;
 423        }
 424
 425        return 0;
 426}
 427
 428void write_pmc1(void)
 429{
 430        mtspr(SPRN_PMC1, 0);
 431}
 432
 433void write_pmc(int pmc, u64 value)
 434{
 435        switch (pmc) {
 436                case 1: mtspr(SPRN_PMC1, value); break;
 437                case 2: mtspr(SPRN_PMC2, value); break;
 438                case 3: mtspr(SPRN_PMC3, value); break;
 439                case 4: mtspr(SPRN_PMC4, value); break;
 440                case 5: mtspr(SPRN_PMC5, value); break;
 441                case 6: mtspr(SPRN_PMC6, value); break;
 442        }
 443}
 444
 445u64 read_pmc(int pmc)
 446{
 447        switch (pmc) {
 448                case 1: return mfspr(SPRN_PMC1);
 449                case 2: return mfspr(SPRN_PMC2);
 450                case 3: return mfspr(SPRN_PMC3);
 451                case 4: return mfspr(SPRN_PMC4);
 452                case 5: return mfspr(SPRN_PMC5);
 453                case 6: return mfspr(SPRN_PMC6);
 454        }
 455
 456        return 0;
 457}
 458
 459static void term_handler(int signal)
 460{
 461        dump_summary_ebb_state();
 462        dump_ebb_hw_state();
 463        abort();
 464}
 465
 466struct sigaction term_action = {
 467        .sa_handler = term_handler,
 468};
 469
 470static void __attribute__((constructor)) ebb_init(void)
 471{
 472        clear_ebb_stats();
 473
 474        if (sigaction(SIGTERM, &term_action, NULL))
 475                perror("sigaction");
 476
 477        ebb_state.trace = trace_buffer_allocate(1 * 1024 * 1024);
 478}
 479