disable-tsc-test.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
  4. *
  5. * Basic test to test behaviour of PR_GET_TSC and PR_SET_TSC
  6. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <unistd.h>
  10. #include <signal.h>
  11. #include <inttypes.h>
  12. #include <sys/prctl.h>
  13. #include <linux/prctl.h>
  14. /* Get/set the process' ability to use the timestamp counter instruction */
  15. #ifndef PR_GET_TSC
  16. #define PR_GET_TSC 25
  17. #define PR_SET_TSC 26
  18. # define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
  19. # define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
  20. #endif
  21. const char *tsc_names[] =
  22. {
  23. [0] = "[not set]",
  24. [PR_TSC_ENABLE] = "PR_TSC_ENABLE",
  25. [PR_TSC_SIGSEGV] = "PR_TSC_SIGSEGV",
  26. };
  27. static uint64_t rdtsc(void)
  28. {
  29. uint32_t lo, hi;
  30. /* We cannot use "=A", since this would use %rax on x86_64 */
  31. __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
  32. return (uint64_t)hi << 32 | lo;
  33. }
  34. static void sigsegv_cb(int sig)
  35. {
  36. int tsc_val = 0;
  37. printf("[ SIG_SEGV ]\n");
  38. printf("prctl(PR_GET_TSC, &tsc_val); ");
  39. fflush(stdout);
  40. if ( prctl(PR_GET_TSC, &tsc_val) == -1)
  41. perror("prctl");
  42. printf("tsc_val == %s\n", tsc_names[tsc_val]);
  43. printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n");
  44. fflush(stdout);
  45. if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1)
  46. perror("prctl");
  47. printf("rdtsc() == ");
  48. }
  49. int main(void)
  50. {
  51. int tsc_val = 0;
  52. signal(SIGSEGV, sigsegv_cb);
  53. printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
  54. printf("prctl(PR_GET_TSC, &tsc_val); ");
  55. fflush(stdout);
  56. if ( prctl(PR_GET_TSC, &tsc_val) == -1)
  57. perror("prctl");
  58. printf("tsc_val == %s\n", tsc_names[tsc_val]);
  59. printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
  60. printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n");
  61. fflush(stdout);
  62. if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1)
  63. perror("prctl");
  64. printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
  65. printf("prctl(PR_SET_TSC, PR_TSC_SIGSEGV)\n");
  66. fflush(stdout);
  67. if ( prctl(PR_SET_TSC, PR_TSC_SIGSEGV) == -1)
  68. perror("prctl");
  69. printf("rdtsc() == ");
  70. fflush(stdout);
  71. printf("%llu\n", (unsigned long long)rdtsc());
  72. fflush(stdout);
  73. exit(EXIT_SUCCESS);
  74. }