xref: /linux/tools/testing/selftests/x86/srso.c (revision a0efa2f362a69e47b9d8b48f770ef3a0249a7911)
1 // SPDX-License-Identifier: GPL-2.0
2 #include <linux/perf_event.h>
3 #include <cpuid.h>
4 #include <errno.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <sys/ioctl.h>
9 #include <sys/syscall.h>
10 #include <unistd.h>
11 
12 int main(void)
13 {
14 	struct perf_event_attr ret_attr, mret_attr;
15 	long long count_rets, count_rets_mispred;
16 	int rrets_fd, mrrets_fd;
17 	unsigned int cpuid1_eax, b, c, d;
18 
19 	__cpuid(1, cpuid1_eax, b, c, d);
20 
21 	if (cpuid1_eax < 0x00800f00 ||
22 	    cpuid1_eax > 0x00afffff) {
23 		fprintf(stderr, "This needs to run on a Zen[1-4] machine (CPUID(1).EAX: 0x%x). Exiting...\n", cpuid1_eax);
24 		exit(EXIT_FAILURE);
25 	}
26 
27 	memset(&ret_attr, 0, sizeof(struct perf_event_attr));
28 	memset(&mret_attr, 0, sizeof(struct perf_event_attr));
29 
30 	ret_attr.type = mret_attr.type = PERF_TYPE_RAW;
31 	ret_attr.size = mret_attr.size = sizeof(struct perf_event_attr);
32 	ret_attr.config = 0xc8;
33 	mret_attr.config = 0xc9;
34 	ret_attr.disabled = mret_attr.disabled = 1;
35 	ret_attr.exclude_user = mret_attr.exclude_user = 1;
36 	ret_attr.exclude_hv = mret_attr.exclude_hv = 1;
37 
38 	rrets_fd = syscall(SYS_perf_event_open, &ret_attr, 0, -1, -1, 0);
39 	if (rrets_fd == -1) {
40 		perror("opening retired RETs fd");
41 		exit(EXIT_FAILURE);
42 	}
43 
44 	mrrets_fd = syscall(SYS_perf_event_open, &mret_attr, 0, -1, -1, 0);
45 	if (mrrets_fd == -1) {
46 		perror("opening retired mispredicted RETs fd");
47 		exit(EXIT_FAILURE);
48 	}
49 
50 	ioctl(rrets_fd, PERF_EVENT_IOC_RESET, 0);
51 	ioctl(mrrets_fd, PERF_EVENT_IOC_RESET, 0);
52 
53 	ioctl(rrets_fd, PERF_EVENT_IOC_ENABLE, 0);
54 	ioctl(mrrets_fd, PERF_EVENT_IOC_ENABLE, 0);
55 
56 	printf("Sleeping for 10 seconds\n");
57 	sleep(10);
58 
59 	ioctl(rrets_fd, PERF_EVENT_IOC_DISABLE, 0);
60 	ioctl(mrrets_fd, PERF_EVENT_IOC_DISABLE, 0);
61 
62 	read(rrets_fd, &count_rets, sizeof(long long));
63 	read(mrrets_fd, &count_rets_mispred, sizeof(long long));
64 
65 	printf("RETs: (%lld retired <-> %lld mispredicted)\n",
66 		count_rets, count_rets_mispred);
67 	printf("SRSO Safe-RET mitigation works correctly if both counts are almost equal.\n");
68 
69 	return 0;
70 }
71