Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,22 @@
bhrb_filter_map_test
bhrb_no_crash_wo_pmu_test
check_extended_reg_test
intr_regs_no_crash_wo_pmu_test
mmcr0_cc56run_test
mmcr0_exceptionbits_test
mmcr0_fc56_pmc1ce_test
mmcr0_fc56_pmc56_test
mmcr0_pmccext_test
mmcr0_pmcjce_test
mmcr1_comb_test
mmcr1_sel_unit_cache_test
mmcr2_fcs_fch_test
mmcr2_l2l3_test
mmcr3_src_test
mmcra_bhrb_any_test
mmcra_bhrb_cond_test
mmcra_bhrb_disable_no_branch_test
mmcra_bhrb_disable_test
mmcra_bhrb_ind_call_test
mmcra_thresh_cmp_test
mmcra_thresh_marked_sample_test
@@ -0,0 +1,17 @@
# SPDX-License-Identifier: GPL-2.0
TEST_GEN_PROGS := mmcr0_exceptionbits_test mmcr0_cc56run_test mmcr0_pmccext_test \
mmcr0_pmcjce_test mmcr0_fc56_pmc1ce_test mmcr0_fc56_pmc56_test \
mmcr1_comb_test mmcr2_l2l3_test mmcr2_fcs_fch_test \
mmcr3_src_test mmcra_thresh_marked_sample_test mmcra_thresh_cmp_test \
mmcra_bhrb_ind_call_test mmcra_bhrb_any_test mmcra_bhrb_cond_test \
mmcra_bhrb_disable_test bhrb_no_crash_wo_pmu_test intr_regs_no_crash_wo_pmu_test \
bhrb_filter_map_test mmcr1_sel_unit_cache_test mmcra_bhrb_disable_no_branch_test \
check_extended_reg_test
top_srcdir = ../../../../../..
include ../../../lib.mk
include ../../flags.mk
CFLAGS += -m64
$(TEST_GEN_PROGS): ../../harness.c ../../utils.c ../event.c ../lib.c misc.c misc.h ../loop.S ../branch_loops.S
@@ -0,0 +1,117 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Athira Rajeev, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
/*
* A perf sampling test to check bhrb filter
* map. All the branch filters are not supported
* in powerpc. Supported filters in:
* power10/power11: any, any_call, ind_call, cond
* power9: any, any_call
*
* Testcase checks event open for invalid bhrb filter
* types should fail and valid filter types should pass.
* Testcase does validity check for these branch
* sample types.
*/
/* Invalid types for powerpc */
/* Valid bhrb filters in power9/power10/power11 */
int bhrb_filter_map_valid_common[] = {
PERF_SAMPLE_BRANCH_ANY,
PERF_SAMPLE_BRANCH_ANY_CALL,
};
/* Valid bhrb filters in power10/power11 */
int bhrb_filter_map_valid_p10[] = {
PERF_SAMPLE_BRANCH_IND_CALL,
PERF_SAMPLE_BRANCH_COND,
};
#define EventCode 0x1001e
static int bhrb_filter_map_test(void)
{
struct event event;
int i;
/* Check for platform support for the test */
SKIP_IF(platform_check_for_tests());
/*
* Skip for Generic compat PMU since
* bhrb filters is not supported
*/
SKIP_IF(check_for_generic_compat_pmu());
/* Init the event for the sampling test */
event_init(&event, EventCode);
event.attr.sample_period = 1000;
event.attr.sample_type = PERF_SAMPLE_BRANCH_STACK;
event.attr.disabled = 1;
/* Invalid filter maps which are expected to fail in event_open */
for (i = PERF_SAMPLE_BRANCH_USER_SHIFT; i < PERF_SAMPLE_BRANCH_MAX_SHIFT; i++) {
/* Skip the valid branch sample type */
if (i == PERF_SAMPLE_BRANCH_ANY_SHIFT || i == PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT \
|| i == PERF_SAMPLE_BRANCH_IND_CALL_SHIFT || i == PERF_SAMPLE_BRANCH_COND_SHIFT)
continue;
event.attr.branch_sample_type = 1U << i;
FAIL_IF(!event_open(&event));
}
/* valid filter maps for power9/power10/power11 which are expected to pass in event_open */
for (i = 0; i < ARRAY_SIZE(bhrb_filter_map_valid_common); i++) {
event.attr.branch_sample_type = bhrb_filter_map_valid_common[i];
FAIL_IF(event_open(&event));
event_close(&event);
}
/*
* filter maps which are valid in power10/power11 and invalid in power9.
* PVR check is used here since PMU specific data like bhrb filter
* alternative tests is handled by respective PMU driver code and
* using PVR will work correctly for all cases including generic
* compat mode.
*/
switch (PVR_VER(mfspr(SPRN_PVR))) {
case POWER11:
case POWER10:
for (i = 0; i < ARRAY_SIZE(bhrb_filter_map_valid_p10); i++) {
event.attr.branch_sample_type = bhrb_filter_map_valid_p10[i];
FAIL_IF(event_open(&event));
event_close(&event);
}
break;
default:
for (i = 0; i < ARRAY_SIZE(bhrb_filter_map_valid_p10); i++) {
event.attr.branch_sample_type = bhrb_filter_map_valid_p10[i];
FAIL_IF(!event_open(&event));
}
}
/*
* Combine filter maps which includes a valid branch filter and an invalid branch
* filter. Example: any ( PERF_SAMPLE_BRANCH_ANY) and any_call
* (PERF_SAMPLE_BRANCH_ANY_CALL).
* The perf_event_open should fail in this case.
*/
event.attr.branch_sample_type = PERF_SAMPLE_BRANCH_ANY | PERF_SAMPLE_BRANCH_ANY_CALL;
FAIL_IF(!event_open(&event));
return 0;
}
int main(void)
{
return test_harness(bhrb_filter_map_test, "bhrb_filter_map_test");
}
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Athira Rajeev, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
/*
* A perf sampling test for making sure
* enabling branch stack doesn't crash in any
* environment, say:
* - With generic compat PMU
* - without any PMU registered
* - With platform specific PMU
* A fix for bhrb sampling crash was added in kernel
* via commit: b460b512417a ("powerpc/perf: Fix crashes
* with generic_compat_pmu & BHRB")
*
* This testcase exercises this code by doing branch
* stack enable for software event. s/w event is used
* since software event will work even in platform
* without PMU.
*/
static int bhrb_no_crash_wo_pmu_test(void)
{
struct event event;
/*
* Init the event for the sampling test.
* This uses software event which works on
* any platform.
*/
event_init_opts(&event, 0, PERF_TYPE_SOFTWARE, "cycles");
event.attr.sample_period = 1000;
event.attr.sample_type = PERF_SAMPLE_BRANCH_STACK;
event.attr.disabled = 1;
/*
* Return code of event_open is not
* considered since test just expects no crash from
* using PERF_SAMPLE_BRANCH_STACK. Also for environment
* like generic compat PMU, branch stack is unsupported.
*/
event_open(&event);
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(bhrb_no_crash_wo_pmu_test, "bhrb_no_crash_wo_pmu_test");
}
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2024, Kajol Jain, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
/*
* A perf sampling test to check extended
* reg support.
*/
static int check_extended_reg_test(void)
{
/* Check for platform support for the test */
SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00));
/* Skip for Generic compat PMU */
SKIP_IF(check_for_generic_compat_pmu());
/* Check if platform supports extended regs */
platform_extended_mask = perf_get_platform_reg_mask();
FAIL_IF(check_extended_regs_support());
return 0;
}
int main(void)
{
return test_harness(check_extended_reg_test, "check_extended_reg_test");
}
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Athira Rajeev, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
/*
* A perf sampling test for making sure
* sampling with -intr-regs doesn't crash
* in any environment, say:
* - With generic compat PMU
* - without any PMU registered
* - With platform specific PMU.
* A fix for crash with intr_regs was
* addressed in commit: f75e7d73bdf7 in kernel.
*
* This testcase exercises this code path by doing
* intr_regs using software event. Software event is
* used since s/w event will work even in platform
* without PMU.
*/
static int intr_regs_no_crash_wo_pmu_test(void)
{
struct event event;
/*
* Init the event for the sampling test.
* This uses software event which works on
* any platform.
*/
event_init_opts(&event, 0, PERF_TYPE_SOFTWARE, "cycles");
event.attr.sample_period = 1000;
event.attr.sample_type = PERF_SAMPLE_REGS_INTR;
event.attr.disabled = 1;
/*
* Return code of event_open is not considered
* since test just expects no crash from using
* PERF_SAMPLE_REGS_INTR.
*/
event_open(&event);
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(intr_regs_no_crash_wo_pmu_test, "intr_regs_no_crash_wo_pmu_test");
}
@@ -0,0 +1,553 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Athira Rajeev, IBM Corp.
* Copyright 2022, Madhavan Srinivasan, IBM Corp.
* Copyright 2022, Kajol Jain, IBM Corp.
*/
#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <ctype.h>
#include "misc.h"
#define PAGE_SIZE sysconf(_SC_PAGESIZE)
/* Storage for platform version */
int pvr;
u64 platform_extended_mask;
/* Mask and Shift for Event code fields */
int ev_mask_pmcxsel, ev_shift_pmcxsel; //pmcxsel field
int ev_mask_marked, ev_shift_marked; //marked filed
int ev_mask_comb, ev_shift_comb; //combine field
int ev_mask_unit, ev_shift_unit; //unit field
int ev_mask_pmc, ev_shift_pmc; //pmc field
int ev_mask_cache, ev_shift_cache; //Cache sel field
int ev_mask_sample, ev_shift_sample; //Random sampling field
int ev_mask_thd_sel, ev_shift_thd_sel; //thresh_sel field
int ev_mask_thd_start, ev_shift_thd_start; //thresh_start field
int ev_mask_thd_stop, ev_shift_thd_stop; //thresh_stop field
int ev_mask_thd_cmp, ev_shift_thd_cmp; //thresh cmp field
int ev_mask_sm, ev_shift_sm; //SDAR mode field
int ev_mask_rsq, ev_shift_rsq; //radix scope qual field
int ev_mask_l2l3, ev_shift_l2l3; //l2l3 sel field
int ev_mask_mmcr3_src, ev_shift_mmcr3_src; //mmcr3 field
static void init_ev_encodes(void)
{
ev_mask_pmcxsel = 0xff;
ev_shift_pmcxsel = 0;
ev_mask_marked = 1;
ev_shift_marked = 8;
ev_mask_unit = 0xf;
ev_shift_unit = 12;
ev_mask_pmc = 0xf;
ev_shift_pmc = 16;
ev_mask_sample = 0x1f;
ev_shift_sample = 24;
ev_mask_thd_sel = 0x7;
ev_shift_thd_sel = 29;
ev_mask_thd_start = 0xf;
ev_shift_thd_start = 36;
ev_mask_thd_stop = 0xf;
ev_shift_thd_stop = 32;
switch (pvr) {
case POWER11:
case POWER10:
ev_mask_thd_cmp = 0x3ffff;
ev_shift_thd_cmp = 0;
ev_mask_rsq = 1;
ev_shift_rsq = 9;
ev_mask_comb = 3;
ev_shift_comb = 10;
ev_mask_cache = 3;
ev_shift_cache = 20;
ev_mask_sm = 0x3;
ev_shift_sm = 22;
ev_mask_l2l3 = 0x1f;
ev_shift_l2l3 = 40;
ev_mask_mmcr3_src = 0x7fff;
ev_shift_mmcr3_src = 45;
break;
case POWER9:
ev_mask_comb = 3;
ev_shift_comb = 10;
ev_mask_cache = 0xf;
ev_shift_cache = 20;
ev_mask_thd_cmp = 0x3ff;
ev_shift_thd_cmp = 40;
ev_mask_sm = 0x3;
ev_shift_sm = 50;
break;
default:
FAIL_IF_EXIT(1);
}
}
/* Return the extended regs mask value */
u64 perf_get_platform_reg_mask(void)
{
if (have_hwcap2(PPC_FEATURE2_ARCH_3_1))
return PERF_POWER10_MASK;
if (have_hwcap2(PPC_FEATURE2_ARCH_3_00))
return PERF_POWER9_MASK;
return -1;
}
int check_extended_regs_support(void)
{
int fd;
struct event event;
event_init(&event, 0x1001e);
event.attr.type = 4;
event.attr.sample_period = 1;
event.attr.disabled = 1;
event.attr.sample_type = PERF_SAMPLE_REGS_INTR;
event.attr.sample_regs_intr = platform_extended_mask;
fd = event_open(&event);
if (fd != -1)
return 0;
return -1;
}
int platform_check_for_tests(void)
{
pvr = PVR_VER(mfspr(SPRN_PVR));
/*
* Check for supported platforms
* for sampling test
*/
switch (pvr) {
case POWER11:
case POWER10:
case POWER9:
break;
default:
goto out;
}
/*
* Check PMU driver registered by looking for
* PPC_FEATURE2_EBB bit in AT_HWCAP2
*/
if (!have_hwcap2(PPC_FEATURE2_EBB) || !have_hwcap2(PPC_FEATURE2_ARCH_3_00))
goto out;
return 0;
out:
printf("%s: Tests unsupported for this platform\n", __func__);
return -1;
}
int check_pvr_for_sampling_tests(void)
{
SKIP_IF(platform_check_for_tests());
platform_extended_mask = perf_get_platform_reg_mask();
/* check if platform supports extended regs */
if (check_extended_regs_support())
goto out;
init_ev_encodes();
return 0;
out:
printf("%s: Sampling tests un-supported\n", __func__);
return -1;
}
/*
* Allocate mmap buffer of "mmap_pages" number of
* pages.
*/
void *event_sample_buf_mmap(int fd, int mmap_pages)
{
size_t page_size = sysconf(_SC_PAGESIZE);
size_t mmap_size;
void *buff;
if (mmap_pages <= 0)
return NULL;
if (fd <= 0)
return NULL;
mmap_size = page_size * (1 + mmap_pages);
buff = mmap(NULL, mmap_size,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (buff == MAP_FAILED) {
perror("mmap() failed.");
return NULL;
}
return buff;
}
/*
* Post process the mmap buffer.
* - If sample_count != NULL then return count of total
* number of samples present in the mmap buffer.
* - If sample_count == NULL then return the address
* of first sample from the mmap buffer
*/
void *__event_read_samples(void *sample_buff, size_t *size, u64 *sample_count)
{
size_t page_size = sysconf(_SC_PAGESIZE);
struct perf_event_header *header = sample_buff + page_size;
struct perf_event_mmap_page *metadata_page = sample_buff;
unsigned long data_head, data_tail;
/*
* PERF_RECORD_SAMPLE:
* struct {
* struct perf_event_header hdr;
* u64 data[];
* };
*/
data_head = metadata_page->data_head;
/* sync memory before reading sample */
mb();
data_tail = metadata_page->data_tail;
/* Check for sample_count */
if (sample_count)
*sample_count = 0;
while (1) {
/*
* Reads the mmap data buffer by moving
* the data_tail to know the last read data.
* data_head points to head in data buffer.
* refer "struct perf_event_mmap_page" in
* "include/uapi/linux/perf_event.h".
*/
if (data_head - data_tail < sizeof(header))
return NULL;
data_tail += sizeof(header);
if (header->type == PERF_RECORD_SAMPLE) {
*size = (header->size - sizeof(header));
if (!sample_count)
return sample_buff + page_size + data_tail;
data_tail += *size;
*sample_count += 1;
} else {
*size = (header->size - sizeof(header));
if ((metadata_page->data_tail + *size) > metadata_page->data_head)
data_tail = metadata_page->data_head;
else
data_tail += *size;
}
header = (struct perf_event_header *)((void *)header + header->size);
}
return NULL;
}
int collect_samples(void *sample_buff)
{
u64 sample_count;
size_t size = 0;
__event_read_samples(sample_buff, &size, &sample_count);
return sample_count;
}
static void *perf_read_first_sample(void *sample_buff, size_t *size)
{
return __event_read_samples(sample_buff, size, NULL);
}
u64 *get_intr_regs(struct event *event, void *sample_buff)
{
u64 type = event->attr.sample_type;
u64 *intr_regs;
size_t size = 0;
if ((type ^ (PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_BRANCH_STACK)) &&
(type ^ PERF_SAMPLE_REGS_INTR))
return NULL;
intr_regs = (u64 *)perf_read_first_sample(sample_buff, &size);
if (!intr_regs)
return NULL;
if (type & PERF_SAMPLE_BRANCH_STACK) {
/*
* PERF_RECORD_SAMPLE and PERF_SAMPLE_BRANCH_STACK:
* struct {
* struct perf_event_header hdr;
* u64 number_of_branches;
* struct perf_branch_entry[number_of_branches];
* u64 data[];
* };
* struct perf_branch_entry {
* u64 from;
* u64 to;
* u64 misc;
* };
*/
intr_regs += ((*intr_regs) * 3) + 1;
}
/*
* First entry in the sample buffer used to specify
* PERF_SAMPLE_REGS_ABI_64, skip perf regs abi to access
* interrupt registers.
*/
++intr_regs;
return intr_regs;
}
static const int __perf_reg_mask(const char *register_name)
{
if (!strcmp(register_name, "R0"))
return 0;
else if (!strcmp(register_name, "R1"))
return 1;
else if (!strcmp(register_name, "R2"))
return 2;
else if (!strcmp(register_name, "R3"))
return 3;
else if (!strcmp(register_name, "R4"))
return 4;
else if (!strcmp(register_name, "R5"))
return 5;
else if (!strcmp(register_name, "R6"))
return 6;
else if (!strcmp(register_name, "R7"))
return 7;
else if (!strcmp(register_name, "R8"))
return 8;
else if (!strcmp(register_name, "R9"))
return 9;
else if (!strcmp(register_name, "R10"))
return 10;
else if (!strcmp(register_name, "R11"))
return 11;
else if (!strcmp(register_name, "R12"))
return 12;
else if (!strcmp(register_name, "R13"))
return 13;
else if (!strcmp(register_name, "R14"))
return 14;
else if (!strcmp(register_name, "R15"))
return 15;
else if (!strcmp(register_name, "R16"))
return 16;
else if (!strcmp(register_name, "R17"))
return 17;
else if (!strcmp(register_name, "R18"))
return 18;
else if (!strcmp(register_name, "R19"))
return 19;
else if (!strcmp(register_name, "R20"))
return 20;
else if (!strcmp(register_name, "R21"))
return 21;
else if (!strcmp(register_name, "R22"))
return 22;
else if (!strcmp(register_name, "R23"))
return 23;
else if (!strcmp(register_name, "R24"))
return 24;
else if (!strcmp(register_name, "R25"))
return 25;
else if (!strcmp(register_name, "R26"))
return 26;
else if (!strcmp(register_name, "R27"))
return 27;
else if (!strcmp(register_name, "R28"))
return 28;
else if (!strcmp(register_name, "R29"))
return 29;
else if (!strcmp(register_name, "R30"))
return 30;
else if (!strcmp(register_name, "R31"))
return 31;
else if (!strcmp(register_name, "NIP"))
return 32;
else if (!strcmp(register_name, "MSR"))
return 33;
else if (!strcmp(register_name, "ORIG_R3"))
return 34;
else if (!strcmp(register_name, "CTR"))
return 35;
else if (!strcmp(register_name, "LINK"))
return 36;
else if (!strcmp(register_name, "XER"))
return 37;
else if (!strcmp(register_name, "CCR"))
return 38;
else if (!strcmp(register_name, "SOFTE"))
return 39;
else if (!strcmp(register_name, "TRAP"))
return 40;
else if (!strcmp(register_name, "DAR"))
return 41;
else if (!strcmp(register_name, "DSISR"))
return 42;
else if (!strcmp(register_name, "SIER"))
return 43;
else if (!strcmp(register_name, "MMCRA"))
return 44;
else if (!strcmp(register_name, "MMCR0"))
return 45;
else if (!strcmp(register_name, "MMCR1"))
return 46;
else if (!strcmp(register_name, "MMCR2"))
return 47;
else if (!strcmp(register_name, "MMCR3"))
return 48;
else if (!strcmp(register_name, "SIER2"))
return 49;
else if (!strcmp(register_name, "SIER3"))
return 50;
else if (!strcmp(register_name, "PMC1"))
return 51;
else if (!strcmp(register_name, "PMC2"))
return 52;
else if (!strcmp(register_name, "PMC3"))
return 53;
else if (!strcmp(register_name, "PMC4"))
return 54;
else if (!strcmp(register_name, "PMC5"))
return 55;
else if (!strcmp(register_name, "PMC6"))
return 56;
else if (!strcmp(register_name, "SDAR"))
return 57;
else if (!strcmp(register_name, "SIAR"))
return 58;
else
return -1;
}
u64 get_reg_value(u64 *intr_regs, char *register_name)
{
int register_bit_position;
register_bit_position = __perf_reg_mask(register_name);
if (register_bit_position < 0 || (!((platform_extended_mask >>
(register_bit_position - 1)) & 1)))
return -1;
return *(intr_regs + register_bit_position);
}
int get_thresh_cmp_val(struct event event)
{
int exp = 0;
u64 result = 0;
u64 value;
if (!have_hwcap2(PPC_FEATURE2_ARCH_3_1))
return EV_CODE_EXTRACT(event.attr.config, thd_cmp);
value = EV_CODE_EXTRACT(event.attr.config1, thd_cmp);
if (!value)
return value;
/*
* Incase of P10, thresh_cmp value is not part of raw event code
* and provided via attr.config1 parameter. To program threshold in MMCRA,
* take a 18 bit number N and shift right 2 places and increment
* the exponent E by 1 until the upper 10 bits of N are zero.
* Write E to the threshold exponent and write the lower 8 bits of N
* to the threshold mantissa.
* The max threshold that can be written is 261120.
*/
if (value > 261120)
value = 261120;
while ((64 - __builtin_clzl(value)) > 8) {
exp++;
value >>= 2;
}
/*
* Note that it is invalid to write a mantissa with the
* upper 2 bits of mantissa being zero, unless the
* exponent is also zero.
*/
if (!(value & 0xC0) && exp)
result = -1;
else
result = (exp << 8) | value;
return result;
}
/*
* Utility function to check for generic compat PMU
* by comparing base_platform value from auxv and real
* PVR value.
* auxv_base_platform() func gives information of "base platform"
* corresponding to PVR value. Incase, if the distro doesn't
* support platform PVR (missing cputable support), base platform
* in auxv will have a default value other than the real PVR's.
* In this case, ISAv3 PMU (generic compat PMU) will be registered
* in the system. auxv_generic_compat_pmu() makes use of the base
* platform value from auxv to do this check.
*/
static bool auxv_generic_compat_pmu(void)
{
int base_pvr = 0;
if (!strcmp(auxv_base_platform(), "power9"))
base_pvr = POWER9;
else if (!strcmp(auxv_base_platform(), "power10"))
base_pvr = POWER10;
else if (!strcmp(auxv_base_platform(), "power11"))
base_pvr = POWER11;
return (!base_pvr);
}
/*
* Check for generic compat PMU.
* First check for presence of pmu_name from
* "/sys/bus/event_source/devices/cpu/caps".
* If doesn't exist, fallback to using value
* auxv.
*/
bool check_for_generic_compat_pmu(void)
{
char pmu_name[256];
memset(pmu_name, 0, sizeof(pmu_name));
if (read_sysfs_file("bus/event_source/devices/cpu/caps/pmu_name",
pmu_name, sizeof(pmu_name)) < 0)
return auxv_generic_compat_pmu();
if (!strcmp(pmu_name, "ISAv3"))
return true;
else
return false;
}
/*
* Check if system is booted in compat mode.
*/
bool check_for_compat_mode(void)
{
char *platform = auxv_platform();
char *base_platform = auxv_base_platform();
return strcmp(platform, base_platform);
}
@@ -0,0 +1,236 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright 2022, Athira Rajeev, IBM Corp.
* Copyright 2022, Madhavan Srinivasan, IBM Corp.
* Copyright 2022, Kajol Jain, IBM Corp.
*/
#include <sys/stat.h>
#include "../event.h"
#define POWER11 0x82
#define POWER10 0x80
#define POWER9 0x4e
#define PERF_POWER9_MASK 0x7f8ffffffffffff
#define PERF_POWER10_MASK 0x7ffffffffffffff
#define PERF_POWER11_MASK PERF_POWER10_MASK
#define MMCR0_FC56 0x00000010UL /* freeze counters 5 and 6 */
#define MMCR0_PMCCEXT 0x00000200UL /* PMCCEXT control */
#define MMCR1_RSQ 0x200000000000ULL /* radix scope qual field */
#define BHRB_DISABLE 0x2000000000ULL /* MMCRA BHRB DISABLE bit */
extern int ev_mask_pmcxsel, ev_shift_pmcxsel;
extern int ev_mask_marked, ev_shift_marked;
extern int ev_mask_comb, ev_shift_comb;
extern int ev_mask_unit, ev_shift_unit;
extern int ev_mask_pmc, ev_shift_pmc;
extern int ev_mask_cache, ev_shift_cache;
extern int ev_mask_sample, ev_shift_sample;
extern int ev_mask_thd_sel, ev_shift_thd_sel;
extern int ev_mask_thd_start, ev_shift_thd_start;
extern int ev_mask_thd_stop, ev_shift_thd_stop;
extern int ev_mask_thd_cmp, ev_shift_thd_cmp;
extern int ev_mask_sm, ev_shift_sm;
extern int ev_mask_rsq, ev_shift_rsq;
extern int ev_mask_l2l3, ev_shift_l2l3;
extern int ev_mask_mmcr3_src, ev_shift_mmcr3_src;
extern int pvr;
extern u64 platform_extended_mask;
extern int check_pvr_for_sampling_tests(void);
extern int platform_check_for_tests(void);
extern int check_extended_regs_support(void);
extern u64 perf_get_platform_reg_mask(void);
/*
* Event code field extraction macro.
* Raw event code is combination of multiple
* fields. Macro to extract individual fields
*
* x - Raw event code value
* y - Field to extract
*/
#define EV_CODE_EXTRACT(x, y) \
((x >> ev_shift_##y) & ev_mask_##y)
void *event_sample_buf_mmap(int fd, int mmap_pages);
void *__event_read_samples(void *sample_buff, size_t *size, u64 *sample_count);
int collect_samples(void *sample_buff);
u64 *get_intr_regs(struct event *event, void *sample_buff);
u64 get_reg_value(u64 *intr_regs, char *register_name);
int get_thresh_cmp_val(struct event event);
bool check_for_generic_compat_pmu(void);
bool check_for_compat_mode(void);
static inline int get_mmcr0_fc56(u64 mmcr0, int pmc)
{
return (mmcr0 & MMCR0_FC56);
}
static inline int get_mmcr0_pmccext(u64 mmcr0, int pmc)
{
return (mmcr0 & MMCR0_PMCCEXT);
}
static inline int get_mmcr0_pmao(u64 mmcr0, int pmc)
{
return ((mmcr0 >> 7) & 0x1);
}
static inline int get_mmcr0_cc56run(u64 mmcr0, int pmc)
{
return ((mmcr0 >> 8) & 0x1);
}
static inline int get_mmcr0_pmcjce(u64 mmcr0, int pmc)
{
return ((mmcr0 >> 14) & 0x1);
}
static inline int get_mmcr0_pmc1ce(u64 mmcr0, int pmc)
{
return ((mmcr0 >> 15) & 0x1);
}
static inline int get_mmcr0_pmae(u64 mmcr0, int pmc)
{
return ((mmcr0 >> 27) & 0x1);
}
static inline int get_mmcr1_pmcxsel(u64 mmcr1, int pmc)
{
return ((mmcr1 >> ((24 - (((pmc) - 1) * 8))) & 0xff));
}
static inline int get_mmcr1_unit(u64 mmcr1, int pmc)
{
return ((mmcr1 >> ((60 - (4 * ((pmc) - 1))))) & 0xf);
}
static inline int get_mmcr1_comb(u64 mmcr1, int pmc)
{
return ((mmcr1 >> (38 - ((pmc - 1) * 2))) & 0x3);
}
static inline int get_mmcr1_cache(u64 mmcr1, int pmc)
{
return ((mmcr1 >> 46) & 0x3);
}
static inline int get_mmcr1_rsq(u64 mmcr1, int pmc)
{
return mmcr1 & MMCR1_RSQ;
}
static inline int get_mmcr2_fcs(u64 mmcr2, int pmc)
{
return ((mmcr2 & (1ull << (63 - (((pmc) - 1) * 9)))) >> (63 - (((pmc) - 1) * 9)));
}
static inline int get_mmcr2_fcp(u64 mmcr2, int pmc)
{
return ((mmcr2 & (1ull << (62 - (((pmc) - 1) * 9)))) >> (62 - (((pmc) - 1) * 9)));
}
static inline int get_mmcr2_fcpc(u64 mmcr2, int pmc)
{
return ((mmcr2 & (1ull << (61 - (((pmc) - 1) * 9)))) >> (61 - (((pmc) - 1) * 9)));
}
static inline int get_mmcr2_fcm1(u64 mmcr2, int pmc)
{
return ((mmcr2 & (1ull << (60 - (((pmc) - 1) * 9)))) >> (60 - (((pmc) - 1) * 9)));
}
static inline int get_mmcr2_fcm0(u64 mmcr2, int pmc)
{
return ((mmcr2 & (1ull << (59 - (((pmc) - 1) * 9)))) >> (59 - (((pmc) - 1) * 9)));
}
static inline int get_mmcr2_fcwait(u64 mmcr2, int pmc)
{
return ((mmcr2 & (1ull << (58 - (((pmc) - 1) * 9)))) >> (58 - (((pmc) - 1) * 9)));
}
static inline int get_mmcr2_fch(u64 mmcr2, int pmc)
{
return ((mmcr2 & (1ull << (57 - (((pmc) - 1) * 9)))) >> (57 - (((pmc) - 1) * 9)));
}
static inline int get_mmcr2_fcti(u64 mmcr2, int pmc)
{
return ((mmcr2 & (1ull << (56 - (((pmc) - 1) * 9)))) >> (56 - (((pmc) - 1) * 9)));
}
static inline int get_mmcr2_fcta(u64 mmcr2, int pmc)
{
return ((mmcr2 & (1ull << (55 - (((pmc) - 1) * 9)))) >> (55 - (((pmc) - 1) * 9)));
}
static inline int get_mmcr2_l2l3(u64 mmcr2, int pmc)
{
if (have_hwcap2(PPC_FEATURE2_ARCH_3_1))
return ((mmcr2 & 0xf8) >> 3);
return 0;
}
static inline int get_mmcr3_src(u64 mmcr3, int pmc)
{
if (!have_hwcap2(PPC_FEATURE2_ARCH_3_1))
return 0;
return ((mmcr3 >> ((49 - (15 * ((pmc) - 1))))) & 0x7fff);
}
static inline int get_mmcra_thd_cmp(u64 mmcra, int pmc)
{
if (have_hwcap2(PPC_FEATURE2_ARCH_3_1))
return ((mmcra >> 45) & 0x7ff);
return ((mmcra >> 45) & 0x3ff);
}
static inline int get_mmcra_sm(u64 mmcra, int pmc)
{
return ((mmcra >> 42) & 0x3);
}
static inline u64 get_mmcra_bhrb_disable(u64 mmcra, int pmc)
{
if (have_hwcap2(PPC_FEATURE2_ARCH_3_1))
return mmcra & BHRB_DISABLE;
return 0;
}
static inline int get_mmcra_ifm(u64 mmcra, int pmc)
{
return ((mmcra >> 30) & 0x3);
}
static inline int get_mmcra_thd_sel(u64 mmcra, int pmc)
{
return ((mmcra >> 16) & 0x7);
}
static inline int get_mmcra_thd_start(u64 mmcra, int pmc)
{
return ((mmcra >> 12) & 0xf);
}
static inline int get_mmcra_thd_stop(u64 mmcra, int pmc)
{
return ((mmcra >> 8) & 0xf);
}
static inline int get_mmcra_rand_samp_elig(u64 mmcra, int pmc)
{
return ((mmcra >> 4) & 0x7);
}
static inline int get_mmcra_sample_mode(u64 mmcra, int pmc)
{
return ((mmcra >> 1) & 0x3);
}
static inline int get_mmcra_marked(u64 mmcra, int pmc)
{
return mmcra & 0x1;
}
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Athira Rajeev, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
extern void thirty_two_instruction_loop(int loops);
/*
* A perf sampling test for mmcr0
* field: cc56run.
*/
static int mmcr0_cc56run(void)
{
struct event event;
u64 *intr_regs;
/* Check for platform support for the test */
SKIP_IF(check_pvr_for_sampling_tests());
SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
/* Init the event for the sampling test */
event_init_sampling(&event, 0x500fa);
event.attr.sample_regs_intr = platform_extended_mask;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make the event overflow */
thirty_two_instruction_loop(10000);
FAIL_IF(event_disable(&event));
/* Check for sample count */
FAIL_IF(!collect_samples(event.mmap_buffer));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/* Verify that cc56run bit is set in MMCR0 */
FAIL_IF(!get_mmcr0_cc56run(get_reg_value(intr_regs, "MMCR0"), 5));
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(mmcr0_cc56run, "mmcr0_cc56run");
}
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Athira Rajeev, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
extern void thirty_two_instruction_loop(int loops);
/*
* A perf sampling test for mmcr0
* fields : pmae, pmao.
*/
static int mmcr0_exceptionbits(void)
{
struct event event;
u64 *intr_regs;
/* Check for platform support for the test */
SKIP_IF(check_pvr_for_sampling_tests());
/* Init the event for the sampling test */
event_init_sampling(&event, 0x500fa);
event.attr.sample_regs_intr = platform_extended_mask;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make the event overflow */
thirty_two_instruction_loop(10000);
FAIL_IF(event_disable(&event));
/* Check for sample count */
FAIL_IF(!collect_samples(event.mmap_buffer));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/* Verify that pmae is cleared and pmao is set in MMCR0 */
FAIL_IF(get_mmcr0_pmae(get_reg_value(intr_regs, "MMCR0"), 5));
FAIL_IF(!get_mmcr0_pmao(get_reg_value(intr_regs, "MMCR0"), 5));
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(mmcr0_exceptionbits, "mmcr0_exceptionbits");
}
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Athira Rajeev, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
extern void thirty_two_instruction_loop(int loops);
/*
* A perf sampling test for mmcr0
* fields: fc56, pmc1ce.
*/
static int mmcr0_fc56_pmc1ce(void)
{
struct event event;
u64 *intr_regs;
/* Check for platform support for the test */
SKIP_IF(check_pvr_for_sampling_tests());
/* Init the event for the sampling test */
event_init_sampling(&event, 0x1001e);
event.attr.sample_regs_intr = platform_extended_mask;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make the event overflow */
thirty_two_instruction_loop(10000);
FAIL_IF(event_disable(&event));
/* Check for sample count */
FAIL_IF(!collect_samples(event.mmap_buffer));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/* Verify that fc56, pmc1ce fields are set in MMCR0 */
FAIL_IF(!get_mmcr0_fc56(get_reg_value(intr_regs, "MMCR0"), 1));
FAIL_IF(!get_mmcr0_pmc1ce(get_reg_value(intr_regs, "MMCR0"), 1));
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(mmcr0_fc56_pmc1ce, "mmcr0_fc56_pmc1ce");
}
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Athira Rajeev, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
extern void thirty_two_instruction_loop(int loops);
/*
* A perf sampling test for mmcr0
* fields: fc56_pmc56
*/
static int mmcr0_fc56_pmc56(void)
{
struct event event;
u64 *intr_regs;
/* Check for platform support for the test */
SKIP_IF(check_pvr_for_sampling_tests());
/* Init the event for the sampling test */
event_init_sampling(&event, 0x500fa);
event.attr.sample_regs_intr = platform_extended_mask;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make the event overflow */
thirty_two_instruction_loop(10000);
FAIL_IF(event_disable(&event));
/* Check for sample count */
FAIL_IF(!collect_samples(event.mmap_buffer));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/* Verify that fc56 is not set in MMCR0 when using PMC5 */
FAIL_IF(get_mmcr0_fc56(get_reg_value(intr_regs, "MMCR0"), 5));
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(mmcr0_fc56_pmc56, "mmcr0_fc56_pmc56");
}
@@ -0,0 +1,59 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Athira Rajeev, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
extern void thirty_two_instruction_loop(int loops);
/*
* A perf sampling test for mmcr0
* field: pmccext
*/
static int mmcr0_pmccext(void)
{
struct event event;
u64 *intr_regs;
/* Check for platform support for the test */
SKIP_IF(check_pvr_for_sampling_tests());
SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
/* Init the event for the sampling test */
event_init_sampling(&event, 0x4001e);
event.attr.sample_regs_intr = platform_extended_mask;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make the event overflow */
thirty_two_instruction_loop(10000);
FAIL_IF(event_disable(&event));
/* Check for sample count */
FAIL_IF(!collect_samples(event.mmap_buffer));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/* Verify that pmccext field is set in MMCR0 */
FAIL_IF(!get_mmcr0_pmccext(get_reg_value(intr_regs, "MMCR0"), 4));
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(mmcr0_pmccext, "mmcr0_pmccext");
}
@@ -0,0 +1,58 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Athira Rajeev, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
extern void thirty_two_instruction_loop(int loops);
/*
* A perf sampling test for mmcr0
* field: pmcjce
*/
static int mmcr0_pmcjce(void)
{
struct event event;
u64 *intr_regs;
/* Check for platform support for the test */
SKIP_IF(check_pvr_for_sampling_tests());
/* Init the event for the sampling test */
event_init_sampling(&event, 0x500fa);
event.attr.sample_regs_intr = platform_extended_mask;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make the event overflow */
thirty_two_instruction_loop(10000);
FAIL_IF(event_disable(&event));
/* Check for sample count */
FAIL_IF(!collect_samples(event.mmap_buffer));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/* Verify that pmcjce field is set in MMCR0 */
FAIL_IF(!get_mmcr0_pmcjce(get_reg_value(intr_regs, "MMCR0"), 5));
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(mmcr0_pmcjce, "mmcr0_pmcjce");
}
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Athira Rajeev, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
/* All successful D-side store dispatches for this thread that were L2 Miss */
#define EventCode 0x46880
extern void thirty_two_instruction_loop_with_ll_sc(u64 loops, u64 *ll_sc_target);
/*
* A perf sampling test for mmcr1
* fields : comb.
*/
static int mmcr1_comb(void)
{
struct event event;
u64 *intr_regs;
u64 dummy;
/* Check for platform support for the test */
SKIP_IF(check_pvr_for_sampling_tests());
/* Init the event for the sampling test */
event_init_sampling(&event, EventCode);
event.attr.sample_regs_intr = platform_extended_mask;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make the event overflow */
thirty_two_instruction_loop_with_ll_sc(10000000, &dummy);
FAIL_IF(event_disable(&event));
/* Check for sample count */
FAIL_IF(!collect_samples(event.mmap_buffer));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/*
* Verify that comb field match with
* corresponding event code fields
*/
FAIL_IF(EV_CODE_EXTRACT(event.attr.config, comb) !=
get_mmcr1_comb(get_reg_value(intr_regs, "MMCR1"), 4));
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(mmcr1_comb, "mmcr1_comb");
}
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Athira Rajeev, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
#define MALLOC_SIZE (0x10000 * 10) /* Ought to be enough .. */
/* The data cache was reloaded from local core's L3 due to a demand load */
#define EventCode 0x21c040
/*
* A perf sampling test for mmcr1
* fields : pmcxsel, unit, cache.
*/
static int mmcr1_sel_unit_cache(void)
{
struct event event;
u64 *intr_regs;
char *p;
int i;
/* Check for platform support for the test */
SKIP_IF(check_pvr_for_sampling_tests());
p = malloc(MALLOC_SIZE);
FAIL_IF(!p);
/* Init the event for the sampling test */
event_init_sampling(&event, EventCode);
event.attr.sample_regs_intr = platform_extended_mask;
event.attr.sample_period = 1;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
event_enable(&event);
/* workload to make the event overflow */
for (i = 0; i < MALLOC_SIZE; i += 0x10000)
p[i] = i;
event_disable(&event);
/* Check for sample count */
FAIL_IF(!collect_samples(event.mmap_buffer));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/*
* Verify that pmcxsel, unit and cache field of MMCR1
* match with corresponding event code fields
*/
FAIL_IF(EV_CODE_EXTRACT(event.attr.config, pmcxsel) !=
get_mmcr1_pmcxsel(get_reg_value(intr_regs, "MMCR1"), 1));
FAIL_IF(EV_CODE_EXTRACT(event.attr.config, unit) !=
get_mmcr1_unit(get_reg_value(intr_regs, "MMCR1"), 1));
FAIL_IF(EV_CODE_EXTRACT(event.attr.config, cache) !=
get_mmcr1_cache(get_reg_value(intr_regs, "MMCR1"), 1));
free(p);
event_close(&event);
return 0;
}
int main(void)
{
FAIL_IF(test_harness(mmcr1_sel_unit_cache, "mmcr1_sel_unit_cache"));
}
@@ -0,0 +1,85 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Madhavan Srinivasan, IBM Corp.
*/
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
extern void thirty_two_instruction_loop(int loops);
static bool is_hv;
static void sig_usr2_handler(int signum, siginfo_t *info, void *data)
{
ucontext_t *uctx = data;
is_hv = !!(uctx->uc_mcontext.gp_regs[PT_MSR] & MSR_HV);
}
/*
* A perf sampling test for mmcr2
* fields : fcs, fch.
*/
static int mmcr2_fcs_fch(void)
{
struct sigaction sigact = {
.sa_sigaction = sig_usr2_handler,
.sa_flags = SA_SIGINFO
};
struct event event;
u64 *intr_regs;
FAIL_IF(sigaction(SIGUSR2, &sigact, NULL));
FAIL_IF(kill(getpid(), SIGUSR2));
/* Check for platform support for the test */
SKIP_IF(check_pvr_for_sampling_tests());
/* Init the event for the sampling test */
event_init_sampling(&event, 0x1001e);
event.attr.sample_regs_intr = platform_extended_mask;
event.attr.exclude_kernel = 1;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make the event overflow */
thirty_two_instruction_loop(10000);
FAIL_IF(event_disable(&event));
/* Check for sample count */
FAIL_IF(!collect_samples(event.mmap_buffer));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/*
* Verify that fcs and fch field of MMCR2 match
* with corresponding modifier fields.
*/
if (is_hv)
FAIL_IF(event.attr.exclude_kernel !=
get_mmcr2_fch(get_reg_value(intr_regs, "MMCR2"), 1));
else
FAIL_IF(event.attr.exclude_kernel !=
get_mmcr2_fcs(get_reg_value(intr_regs, "MMCR2"), 1));
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(mmcr2_fcs_fch, "mmcr2_fcs_fch");
}
@@ -0,0 +1,74 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Madhavan Srinivasan, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
/* All successful D-side store dispatches for this thread */
#define EventCode 0x010000046080
#define MALLOC_SIZE (0x10000 * 10) /* Ought to be enough .. */
/*
* A perf sampling test for mmcr2
* fields : l2l3
*/
static int mmcr2_l2l3(void)
{
struct event event;
u64 *intr_regs;
char *p;
int i;
/* Check for platform support for the test */
SKIP_IF(check_pvr_for_sampling_tests());
SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
/* Init the event for the sampling test */
event_init_sampling(&event, EventCode);
event.attr.sample_regs_intr = platform_extended_mask;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make the event overflow */
p = malloc(MALLOC_SIZE);
FAIL_IF(!p);
for (i = 0; i < MALLOC_SIZE; i += 0x10000)
p[i] = i;
FAIL_IF(event_disable(&event));
/* Check for sample count */
FAIL_IF(!collect_samples(event.mmap_buffer));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/*
* Verify that l2l3 field of MMCR2 match with
* corresponding event code field
*/
FAIL_IF(EV_CODE_EXTRACT(event.attr.config, l2l3) !=
get_mmcr2_l2l3(get_reg_value(intr_regs, "MMCR2"), 4));
event_close(&event);
free(p);
return 0;
}
int main(void)
{
return test_harness(mmcr2_l2l3, "mmcr2_l2l3");
}
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Kajol Jain, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
extern void thirty_two_instruction_loop_with_ll_sc(u64 loops, u64 *ll_sc_target);
/* The data cache was reloaded from local core's L3 due to a demand load */
#define EventCode 0x1340000001c040
/*
* A perf sampling test for mmcr3
* fields.
*/
static int mmcr3_src(void)
{
struct event event;
u64 *intr_regs;
u64 dummy;
/* Check for platform support for the test */
SKIP_IF(check_pvr_for_sampling_tests());
SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
/* Init the event for the sampling test */
event_init_sampling(&event, EventCode);
event.attr.sample_regs_intr = platform_extended_mask;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make event overflow */
thirty_two_instruction_loop_with_ll_sc(1000000, &dummy);
FAIL_IF(event_disable(&event));
/* Check for sample count */
FAIL_IF(!collect_samples(event.mmap_buffer));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/*
* Verify that src field of MMCR3 match with
* corresponding event code field
*/
FAIL_IF(EV_CODE_EXTRACT(event.attr.config, mmcr3_src) !=
get_mmcr3_src(get_reg_value(intr_regs, "MMCR3"), 1));
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(mmcr3_src, "mmcr3_src");
}
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Kajol Jain, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
extern void thirty_two_instruction_loop(int loops);
/* Instructions */
#define EventCode 0x500fa
/* ifm field for any branch mode */
#define IFM_ANY_BRANCH 0x0
/*
* A perf sampling test for mmcra
* field: ifm for bhrb any call.
*/
static int mmcra_bhrb_any_test(void)
{
struct event event;
u64 *intr_regs;
/* Check for platform support for the test */
SKIP_IF(check_pvr_for_sampling_tests());
/* Init the event for the sampling test */
event_init_sampling(&event, EventCode);
event.attr.sample_regs_intr = platform_extended_mask;
event.attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
event.attr.branch_sample_type = PERF_SAMPLE_BRANCH_ANY;
event.attr.exclude_kernel = 1;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make the event overflow */
thirty_two_instruction_loop(10000);
FAIL_IF(event_disable(&event));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/* Verify that ifm bit is set properly in MMCRA */
FAIL_IF(get_mmcra_ifm(get_reg_value(intr_regs, "MMCRA"), 5) != IFM_ANY_BRANCH);
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(mmcra_bhrb_any_test, "mmcra_bhrb_any_test");
}
@@ -0,0 +1,69 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Kajol Jain, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
extern void thirty_two_instruction_loop(int loops);
/* Instructions */
#define EventCode 0x500fa
/* ifm field for conditional branch mode */
#define IFM_COND_BRANCH 0x3
/*
* A perf sampling test for mmcra
* field: ifm for bhrb cond call.
*/
static int mmcra_bhrb_cond_test(void)
{
struct event event;
u64 *intr_regs;
/*
* Check for platform support for the test.
* This test is only aplicable on ISA v3.1
*/
SKIP_IF(check_pvr_for_sampling_tests());
SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
/* Init the event for the sampling test */
event_init_sampling(&event, EventCode);
event.attr.sample_regs_intr = platform_extended_mask;
event.attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
event.attr.branch_sample_type = PERF_SAMPLE_BRANCH_COND;
event.attr.exclude_kernel = 1;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make the event overflow */
thirty_two_instruction_loop(10000);
FAIL_IF(event_disable(&event));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/* Verify that ifm bit is set properly in MMCRA */
FAIL_IF(get_mmcra_ifm(get_reg_value(intr_regs, "MMCRA"), 5) != IFM_COND_BRANCH);
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(mmcra_bhrb_cond_test, "mmcra_bhrb_cond_test");
}
@@ -0,0 +1,64 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Kajol Jain, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
extern void thirty_two_instruction_loop(int loops);
/* Instructions */
#define EventCode 0x500fa
/*
* A perf sampling test for mmcra
* field: bhrb_disable.
*/
static int mmcra_bhrb_disable_no_branch_test(void)
{
struct event event;
u64 *intr_regs;
/*
* Check for platform support for the test.
* This test is only aplicable on ISA v3.1
*/
SKIP_IF(check_pvr_for_sampling_tests());
SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
/* Init the event for the sampling test */
event_init_sampling(&event, EventCode);
event.attr.sample_regs_intr = platform_extended_mask;
event.attr.exclude_kernel = 1;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make the event overflow */
thirty_two_instruction_loop(10000);
FAIL_IF(event_disable(&event));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/* Verify that bhrb_disable bit is set in MMCRA for non-branch samples */
FAIL_IF(!get_mmcra_bhrb_disable(get_reg_value(intr_regs, "MMCRA"), 5));
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(mmcra_bhrb_disable_no_branch_test, "mmcra_bhrb_disable_no_branch_test");
}
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Kajol Jain, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
extern void thirty_two_instruction_loop(int loops);
/* Instructions */
#define EventCode 0x500fa
/*
* A perf sampling test for mmcra
* field: bhrb_disable.
*/
static int mmcra_bhrb_disable_test(void)
{
struct event event;
u64 *intr_regs;
/*
* Check for platform support for the test.
* This test is only aplicable on ISA v3.1
*/
SKIP_IF(check_pvr_for_sampling_tests());
SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
/* Init the event for the sampling test */
event_init_sampling(&event, EventCode);
event.attr.sample_regs_intr = platform_extended_mask;
event.attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
event.attr.branch_sample_type = PERF_SAMPLE_BRANCH_ANY;
event.attr.exclude_kernel = 1;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make the event overflow */
thirty_two_instruction_loop(10000);
FAIL_IF(event_disable(&event));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/* Verify that bhrb_disable bit is set in MMCRA */
FAIL_IF(get_mmcra_bhrb_disable(get_reg_value(intr_regs, "MMCRA"), 5));
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(mmcra_bhrb_disable_test, "mmcra_bhrb_disable_test");
}
@@ -0,0 +1,69 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Kajol Jain, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
extern void indirect_branch_loop(void);
/* Instructions */
#define EventCode 0x500fa
/* ifm field for indirect branch mode */
#define IFM_IND_BRANCH 0x2
/*
* A perf sampling test for mmcra
* field: ifm for bhrb ind_call.
*/
static int mmcra_bhrb_ind_call_test(void)
{
struct event event;
u64 *intr_regs;
/*
* Check for platform support for the test.
* This test is only aplicable on ISA v3.1
*/
SKIP_IF(check_pvr_for_sampling_tests());
SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1));
/* Init the event for the sampling test */
event_init_sampling(&event, EventCode);
event.attr.sample_regs_intr = platform_extended_mask;
event.attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
event.attr.branch_sample_type = PERF_SAMPLE_BRANCH_IND_CALL;
event.attr.exclude_kernel = 1;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make the event overflow */
indirect_branch_loop();
FAIL_IF(event_disable(&event));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/* Verify that ifm bit is set properly in MMCRA */
FAIL_IF(get_mmcra_ifm(get_reg_value(intr_regs, "MMCRA"), 5) != IFM_IND_BRANCH);
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(mmcra_bhrb_ind_call_test, "mmcra_bhrb_ind_call_test");
}
@@ -0,0 +1,74 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Kajol Jain, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
/*
* Primary PMU event used here is PM_MRK_INST_CMPL (0x401e0)
* Threshold event selection used is issue to complete for cycles
* Sampling criteria is Load only sampling
*/
#define p9_EventCode 0x13E35340401e0
#define p10_EventCode 0x35340401e0
extern void thirty_two_instruction_loop_with_ll_sc(u64 loops, u64 *ll_sc_target);
/* A perf sampling test to test mmcra fields */
static int mmcra_thresh_cmp(void)
{
struct event event;
u64 *intr_regs;
u64 dummy;
/* Check for platform support for the test */
SKIP_IF(check_pvr_for_sampling_tests());
/* Skip for comapt mode */
SKIP_IF(check_for_compat_mode());
/* Init the event for the sampling test */
if (!have_hwcap2(PPC_FEATURE2_ARCH_3_1)) {
event_init_sampling(&event, p9_EventCode);
} else {
event_init_sampling(&event, p10_EventCode);
event.attr.config1 = 1000;
}
event.attr.sample_regs_intr = platform_extended_mask;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make the event overflow */
thirty_two_instruction_loop_with_ll_sc(1000000, &dummy);
FAIL_IF(event_disable(&event));
/* Check for sample count */
FAIL_IF(!collect_samples(event.mmap_buffer));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/* Verify that thresh cmp match with the corresponding event code fields */
FAIL_IF(get_thresh_cmp_val(event) !=
get_mmcra_thd_cmp(get_reg_value(intr_regs, "MMCRA"), 4));
event_close(&event);
return 0;
}
int main(void)
{
FAIL_IF(test_harness(mmcra_thresh_cmp, "mmcra_thresh_cmp"));
}
@@ -0,0 +1,80 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright 2022, Kajol Jain, IBM Corp.
*/
#include <stdio.h>
#include <stdlib.h>
#include "../event.h"
#include "misc.h"
#include "utils.h"
/*
* Primary PMU event used here is PM_MRK_INST_CMPL (0x401e0)
* Threshold event selection used is issue to complete for cycles
* Sampling criteria is Load only sampling
*/
#define EventCode 0x35340401e0
extern void thirty_two_instruction_loop_with_ll_sc(u64 loops, u64 *ll_sc_target);
/* A perf sampling test to test mmcra fields */
static int mmcra_thresh_marked_sample(void)
{
struct event event;
u64 *intr_regs;
u64 dummy;
/* Check for platform support for the test */
SKIP_IF(check_pvr_for_sampling_tests());
/* Init the event for the sampling test */
event_init_sampling(&event, EventCode);
event.attr.sample_regs_intr = platform_extended_mask;
FAIL_IF(event_open(&event));
event.mmap_buffer = event_sample_buf_mmap(event.fd, 1);
FAIL_IF(event_enable(&event));
/* workload to make the event overflow */
thirty_two_instruction_loop_with_ll_sc(1000000, &dummy);
FAIL_IF(event_disable(&event));
/* Check for sample count */
FAIL_IF(!collect_samples(event.mmap_buffer));
intr_regs = get_intr_regs(&event, event.mmap_buffer);
/* Check for intr_regs */
FAIL_IF(!intr_regs);
/*
* Verify that thresh sel/start/stop, marked, random sample
* eligibility, sdar mode and sample mode fields match with
* the corresponding event code fields
*/
FAIL_IF(EV_CODE_EXTRACT(event.attr.config, thd_sel) !=
get_mmcra_thd_sel(get_reg_value(intr_regs, "MMCRA"), 4));
FAIL_IF(EV_CODE_EXTRACT(event.attr.config, thd_start) !=
get_mmcra_thd_start(get_reg_value(intr_regs, "MMCRA"), 4));
FAIL_IF(EV_CODE_EXTRACT(event.attr.config, thd_stop) !=
get_mmcra_thd_stop(get_reg_value(intr_regs, "MMCRA"), 4));
FAIL_IF(EV_CODE_EXTRACT(event.attr.config, marked) !=
get_mmcra_marked(get_reg_value(intr_regs, "MMCRA"), 4));
FAIL_IF((EV_CODE_EXTRACT(event.attr.config, sample) >> 2) !=
get_mmcra_rand_samp_elig(get_reg_value(intr_regs, "MMCRA"), 4));
FAIL_IF((EV_CODE_EXTRACT(event.attr.config, sample) & 0x3) !=
get_mmcra_sample_mode(get_reg_value(intr_regs, "MMCRA"), 4));
FAIL_IF(EV_CODE_EXTRACT(event.attr.config, sm) !=
get_mmcra_sm(get_reg_value(intr_regs, "MMCRA"), 4));
event_close(&event);
return 0;
}
int main(void)
{
return test_harness(mmcra_thresh_marked_sample, "mmcra_thresh_marked_sample");
}