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