71 lines
2.0 KiB
C
71 lines
2.0 KiB
C
|
// SPDX-License-Identifier: GPL-2.0
|
||
|
#include <linux/perf_event.h>
|
||
|
#include <cpuid.h>
|
||
|
#include <errno.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <sys/ioctl.h>
|
||
|
#include <sys/syscall.h>
|
||
|
#include <unistd.h>
|
||
|
|
||
|
int main(void)
|
||
|
{
|
||
|
struct perf_event_attr ret_attr, mret_attr;
|
||
|
long long count_rets, count_rets_mispred;
|
||
|
int rrets_fd, mrrets_fd;
|
||
|
unsigned int cpuid1_eax, b, c, d;
|
||
|
|
||
|
__cpuid(1, cpuid1_eax, b, c, d);
|
||
|
|
||
|
if (cpuid1_eax < 0x00800f00 ||
|
||
|
cpuid1_eax > 0x00afffff) {
|
||
|
fprintf(stderr, "This needs to run on a Zen[1-4] machine (CPUID(1).EAX: 0x%x). Exiting...\n", cpuid1_eax);
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
memset(&ret_attr, 0, sizeof(struct perf_event_attr));
|
||
|
memset(&mret_attr, 0, sizeof(struct perf_event_attr));
|
||
|
|
||
|
ret_attr.type = mret_attr.type = PERF_TYPE_RAW;
|
||
|
ret_attr.size = mret_attr.size = sizeof(struct perf_event_attr);
|
||
|
ret_attr.config = 0xc8;
|
||
|
mret_attr.config = 0xc9;
|
||
|
ret_attr.disabled = mret_attr.disabled = 1;
|
||
|
ret_attr.exclude_user = mret_attr.exclude_user = 1;
|
||
|
ret_attr.exclude_hv = mret_attr.exclude_hv = 1;
|
||
|
|
||
|
rrets_fd = syscall(SYS_perf_event_open, &ret_attr, 0, -1, -1, 0);
|
||
|
if (rrets_fd == -1) {
|
||
|
perror("opening retired RETs fd");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
mrrets_fd = syscall(SYS_perf_event_open, &mret_attr, 0, -1, -1, 0);
|
||
|
if (mrrets_fd == -1) {
|
||
|
perror("opening retired mispredicted RETs fd");
|
||
|
exit(EXIT_FAILURE);
|
||
|
}
|
||
|
|
||
|
ioctl(rrets_fd, PERF_EVENT_IOC_RESET, 0);
|
||
|
ioctl(mrrets_fd, PERF_EVENT_IOC_RESET, 0);
|
||
|
|
||
|
ioctl(rrets_fd, PERF_EVENT_IOC_ENABLE, 0);
|
||
|
ioctl(mrrets_fd, PERF_EVENT_IOC_ENABLE, 0);
|
||
|
|
||
|
printf("Sleeping for 10 seconds\n");
|
||
|
sleep(10);
|
||
|
|
||
|
ioctl(rrets_fd, PERF_EVENT_IOC_DISABLE, 0);
|
||
|
ioctl(mrrets_fd, PERF_EVENT_IOC_DISABLE, 0);
|
||
|
|
||
|
read(rrets_fd, &count_rets, sizeof(long long));
|
||
|
read(mrrets_fd, &count_rets_mispred, sizeof(long long));
|
||
|
|
||
|
printf("RETs: (%lld retired <-> %lld mispredicted)\n",
|
||
|
count_rets, count_rets_mispred);
|
||
|
printf("SRSO Safe-RET mitigation works correctly if both counts are almost equal.\n");
|
||
|
|
||
|
return 0;
|
||
|
}
|