Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions BM/pmu/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-only
# Copyright (c) 2026 Intel Corporation.

CC = gcc
TARGET = rdpmc_user_disable_test

$(TARGET): rdpmc_user_disable_test.c
$(CC) -o $@ $<

clean:
rm -f $(TARGET)
62 changes: 62 additions & 0 deletions BM/pmu/pmu_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,59 @@ counting_multi_test() {
done
}

rdpmc_user_disable() {
local logfile1="temp1.log"
local logfile2="temp2.log"
local logfile3="temp3.log"
local logfile4="temp4.log"
#23H.00H:EBX[2]: RDPMC_USR_DISABLE
do_cmd "cpuid_check 23 0 0 0 b 2"
[ $? -ne 0 ] && die "Platform does not support RDPMC USR DISABLE feature"

rdpmc_attr=$1
echo $rdpmc_attr > /sys/devices/cpu/rdpmc

clear_files $logfile1 $logfile2 $logfile3 $logfile4
[ -f rdpmc_user_disable_test ] || die "please compile rdpmc_user_disable_test firstly "
rdpmc_user_disable_test 0 system gp > $logfile1
rdpmc_user_disable_test 0 system fixed > $logfile2
rdpmc_user_disable_test 0 process gp > $logfile3
rdpmc_user_disable_test 0 process fixed > $logfile4
case $rdpmc_attr in
0)
for file in $logfile1 $logfile2 $logfile3 $logfile4;
do
cat $file | grep "Receive and handle #GP fault"
[ $? -eq 0 ] || die "rdpmc user disable test fail with rdpmc 0"
clear_files $file
done
;;
1)
for file in $logfile1 $logfile2;
do
num=$(cat $file | awk '{print $NF}')
clear_files $file
[ $num -eq 0 ] || die "rdpmc user disable test fail with rdpmc 1"
done

for file in $logfile3 $logfile4;
do
num=$(cat $file | awk '{print $NF}')
clear_files $file
[ $num -gt 0 ] || die "rdpmc user disable test fail with rdpmc 1"
done
;;
2)
for file in $logfile1 $logfile2 $logfile3 $logfile4;
do
num=$(cat $file | awk '{print $NF}')
clear_files $file
[ $num -gt 0 ] || die "rdpmc user disable test fail with rdpmc 2"
done
;;
esac
}

pmu_test() {
case $TEST_SCENARIO in
fix_counter)
Expand Down Expand Up @@ -549,6 +602,15 @@ pmu_test() {
counting_multi)
counting_multi_test
;;
rdpmc_user_disable_0)
rdpmc_user_disable 0
;;
rdpmc_user_disable_1)
rdpmc_user_disable 1
;;
rdpmc_user_disable_2)
rdpmc_user_disable 2
;;
esac
return 0
}
Expand Down
182 changes: 182 additions & 0 deletions BM/pmu/rdpmc_user_disable_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
// SPDX-License-Identifier: GPL-2.0-only
// Copyright (c) 2026 Intel Corporation.

#define LINUX
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include <stdint.h>
#include <stdlib.h>
#include <asm/unistd.h>
#include <signal.h>
#include <string.h>
#include <sched.h>

typedef unsigned long long u64;
int pagesize;

// Read memory barrier
#define rmb() asm volatile("" ::: "memory")

struct cpu {
int fd;
struct perf_event_mmap_page *buf;
};

int perf_open(struct cpu *ctx, int cpu, unsigned int counter, int pid)
{
int ret;

struct perf_event_attr attr = {
.type = PERF_TYPE_RAW,
.size = sizeof(struct perf_event_attr),
.config = counter,
.sample_type = PERF_SAMPLE_READ,
.precise_ip = 0,
};

ctx->buf = NULL;
ctx->fd = syscall(__NR_perf_event_open, &attr, pid, cpu, -1, 0);
if (ctx->fd < 0) {
printf("Failed to open event 0x%x err %d\n", counter, ctx->fd);
return -1;
}

ctx->buf = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, ctx->fd, 0);
if (ctx->buf == MAP_FAILED) {
close(ctx->fd);
printf("Failed to mmap event 0x%x\n", counter);
return -1;
}

ret = ioctl(ctx->fd, PERF_EVENT_IOC_ENABLE, 0);
if (ret < 0) {
printf("Failed to enable event 0x%x\n", counter);
return -1;
}

return 0;
}

void perf_close(struct cpu *ctx)
{
close(ctx->fd);
if (ctx->buf)
munmap(ctx->buf, pagesize);
}

unsigned long long perf_read(struct cpu *ctx)
{
u64 val;
unsigned int seq;
u64 offset;
typeof(ctx->buf) buf = ctx->buf;

do {
seq = buf->lock;
/* Pairs with the rmb below in perf_read */
rmb();
/* XXX fallback */
val = __builtin_ia32_rdpmc(buf->index - 1);
offset = buf->offset;
/* Pairs with the rmb above in perf_read */
rmb();
} while (buf->lock != seq);
return val;
}

void gp_fault_handler(int sig, siginfo_t *si, void *unused)
{
printf("Receive and handle #GP fault\n");
exit(-2);
}

int main(int argc, const char **argv)
{
struct sigaction sa;
cpu_set_t cpuset;
struct cpu cpu;
unsigned int counter;
u64 count;
int cpuid;
int pid;
int ret;

if (argc != 4) {
printf("Usage: %s <cpuid> <system | process> <gp | fixed>\n", argv[0]);
return -1;
}

if (!strncmp(argv[2], "system", 6))
pid = -1;
else if (!strncmp(argv[2], "process", 7))
pid = 0;
else {
printf("Usage: %s <cpuid> <system | process> <gp | fixed>\n", argv[0]);
return -1;
}

if (!strncmp(argv[3], "gp", 6))
counter = 0xc4; /* branches */
else if (!strncmp(argv[3], "fixed", 5))
counter = 0xc0; /* instructions */
else {
printf("Usage: %s <cpuid> <system | process> <gp | fixed>\n", argv[0]);
return -1;
}

cpuid = atoi(argv[1]);

sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = gp_fault_handler;

if (sigaction(SIGSEGV, &sa, NULL) == -1) {
printf("Fail to set the #GP handler\n");
return -1;
}

CPU_ZERO(&cpuset);
CPU_SET(cpuid, &cpuset);
if (sched_setaffinity(0, sizeof(cpu_set_t), &cpuset) == -1) {
printf("Fail to bind the program to cpu %d\n", cpuid);
return -1;
}

pagesize = sysconf(_SC_PAGESIZE);

/* open & enable event */
ret = perf_open(&cpu, cpuid, counter, pid);
if (ret < 0)
goto err;

/* do something here */
sleep(1);

/* read event */
count = perf_read(&cpu);

/* disable event */
ret = ioctl(cpu.fd, PERF_EVENT_IOC_DISABLE, 0);
if (ret < 0) {
printf("Failed to disable event 0x%x\n", counter);
goto err;
}

/* close event */
perf_close(&cpu);

printf("CPU %d - %s %s event (0x%x) count %lld\n",
cpuid, argv[2], argv[3], counter, count);

return count;

err:
printf("rdpmc-user-disable test case: CPU %d - %s %s event (0x%x) FAIL!\n",
cpuid, argv[2], argv[3], counter);
return -1;
}
38 changes: 38 additions & 0 deletions BM/pmu/tests_dmr
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# This file collects the PMU cases for DMR platform
pmu_tests.sh -t basic
pmu_tests.sh -t uncore
pmu_tests.sh -t uncore_dmesg
pmu_tests.sh -t uncore_events
pmu_iommu_tests.sh -t iommu_clocks
pmu_iommu_tests.sh -t iommu_all_basic
apebs_tests.sh -t data_src -w 0
apebs_tests.sh -t ip_1 -w 0
apebs_tests.sh -t ip_2 -w 0
apebs_tests.sh -t lbr_1 -w 0
apebs_tests.sh -t lbr_2 -w 0
apebs_tests.sh -t large_pebs -w 0
apebs_tests.sh -t large_pebs -w 1
apebs_tests.sh -t xmm_1 -w 1
apebs_tests.sh -t xmm_2 -w 1
apebs_tests.sh -t ip_1 -w 1
apebs_tests.sh -t ip_2 -w 1
apebs_tests.sh -t data_src -w 1
apebs_tests.sh -t lbr_1 -w 1
apebs_tests.sh -t lbr_2 -w 1
apebs_tests.sh -t ip_1 -w 1
apebs_tests.sh -t ip_2 -w 1
apebs_tests.sh -t data_src -w 1
pmu_tests.sh -t timed_pebs_msr
pmu_tests.sh -t lbr_events_cpuid
pmu_tests.sh -t lbr_events_s
pmu_tests.sh -t lbr_events_all
pmu_tests.sh -t arch_pebs_cpuid
pmu_tests.sh -t arch_pebs_gp_reg_group
pmu_tests.sh -t arch_pebs_xer_group
pmu_tests.sh -t arch_pebs_counter_group
pmu_tests.sh -t arch_pebs_counter_group_stress
pmu_tests.sh -t arch_pebs_gp_counter
pmu_tests.sh -t arch_pebs_basic_group
pmu_tests.sh -t rdpmc_user_disable_0
pmu_tests.sh -t rdpmc_user_disable_1
pmu_tests.sh -t rdpmc_user_disable_2
Loading