tools/testing/selftests/powerpc/pmu/ebb/ebb.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/powerpc/pmu/ebb/ebb.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/powerpc/pmu/ebb/ebb.c
Extension
.c
Size
9529 bytes
Lines
486
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright 2014, Michael Ellerman, IBM Corp.
 */

#define _GNU_SOURCE	/* For CPU_ZERO etc. */

#include <sched.h>
#include <sys/wait.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>

#include "trace.h"
#include "ebb.h"


void (*ebb_user_func)(void);

void ebb_hook(void)
{
	if (ebb_user_func)
		ebb_user_func();
}

struct ebb_state ebb_state;

u64 sample_period = 0x40000000ull;

void reset_ebb_with_clear_mask(unsigned long mmcr0_clear_mask)
{
	u64 val;

	/* 2) clear MMCR0[PMAO] - docs say BESCR[PMEO] should do this */
	/* 3) set MMCR0[PMAE]	- docs say BESCR[PME] should do this */
	val = mfspr(SPRN_MMCR0);
	mtspr(SPRN_MMCR0, (val & ~mmcr0_clear_mask) | MMCR0_PMAE);

	/* 4) clear BESCR[PMEO] */
	mtspr(SPRN_BESCRR, BESCR_PMEO);

	/* 5) set BESCR[PME] */
	mtspr(SPRN_BESCRS, BESCR_PME);

	/* 6) rfebb 1 - done in our caller */
}

void reset_ebb(void)
{
	reset_ebb_with_clear_mask(MMCR0_PMAO | MMCR0_FC);
}

/* Called outside of the EBB handler to check MMCR0 is sane */
int ebb_check_mmcr0(void)
{
	u64 val;

	val = mfspr(SPRN_MMCR0);
	if ((val & (MMCR0_FC | MMCR0_PMAO)) == MMCR0_FC) {
		/* It's OK if we see FC & PMAO, but not FC by itself */
		printf("Outside of loop, only FC set 0x%llx\n", val);
		return 1;
	}

	return 0;
}

bool ebb_check_count(int pmc, u64 sample_period, int fudge)
{
	u64 count, upper, lower;

	count = ebb_state.stats.pmc_count[PMC_INDEX(pmc)];

	lower = ebb_state.stats.ebb_count * (sample_period - fudge);

	if (count < lower) {
		printf("PMC%d count (0x%llx) below lower limit 0x%llx (-0x%llx)\n",
			pmc, count, lower, lower - count);
		return false;
	}

	upper = ebb_state.stats.ebb_count * (sample_period + fudge);

	if (count > upper) {
		printf("PMC%d count (0x%llx) above upper limit 0x%llx (+0x%llx)\n",
			pmc, count, upper, count - upper);
		return false;

Annotation

Implementation Notes