srso.c 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  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. int main(void)
  12. {
  13. struct perf_event_attr ret_attr, mret_attr;
  14. long long count_rets, count_rets_mispred;
  15. int rrets_fd, mrrets_fd;
  16. unsigned int cpuid1_eax, b, c, d;
  17. __cpuid(1, cpuid1_eax, b, c, d);
  18. if (cpuid1_eax < 0x00800f00 ||
  19. cpuid1_eax > 0x00afffff) {
  20. fprintf(stderr, "This needs to run on a Zen[1-4] machine (CPUID(1).EAX: 0x%x). Exiting...\n", cpuid1_eax);
  21. exit(EXIT_FAILURE);
  22. }
  23. memset(&ret_attr, 0, sizeof(struct perf_event_attr));
  24. memset(&mret_attr, 0, sizeof(struct perf_event_attr));
  25. ret_attr.type = mret_attr.type = PERF_TYPE_RAW;
  26. ret_attr.size = mret_attr.size = sizeof(struct perf_event_attr);
  27. ret_attr.config = 0xc8;
  28. mret_attr.config = 0xc9;
  29. ret_attr.disabled = mret_attr.disabled = 1;
  30. ret_attr.exclude_user = mret_attr.exclude_user = 1;
  31. ret_attr.exclude_hv = mret_attr.exclude_hv = 1;
  32. rrets_fd = syscall(SYS_perf_event_open, &ret_attr, 0, -1, -1, 0);
  33. if (rrets_fd == -1) {
  34. perror("opening retired RETs fd");
  35. exit(EXIT_FAILURE);
  36. }
  37. mrrets_fd = syscall(SYS_perf_event_open, &mret_attr, 0, -1, -1, 0);
  38. if (mrrets_fd == -1) {
  39. perror("opening retired mispredicted RETs fd");
  40. exit(EXIT_FAILURE);
  41. }
  42. ioctl(rrets_fd, PERF_EVENT_IOC_RESET, 0);
  43. ioctl(mrrets_fd, PERF_EVENT_IOC_RESET, 0);
  44. ioctl(rrets_fd, PERF_EVENT_IOC_ENABLE, 0);
  45. ioctl(mrrets_fd, PERF_EVENT_IOC_ENABLE, 0);
  46. printf("Sleeping for 10 seconds\n");
  47. sleep(10);
  48. ioctl(rrets_fd, PERF_EVENT_IOC_DISABLE, 0);
  49. ioctl(mrrets_fd, PERF_EVENT_IOC_DISABLE, 0);
  50. read(rrets_fd, &count_rets, sizeof(long long));
  51. read(mrrets_fd, &count_rets_mispred, sizeof(long long));
  52. printf("RETs: (%lld retired <-> %lld mispredicted)\n",
  53. count_rets, count_rets_mispred);
  54. printf("SRSO Safe-RET mitigation works correctly if both counts are almost equal.\n");
  55. return 0;
  56. }