disable-tsc-on-off-stress-test.c 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
  4. *
  5. * Tests if the control register is updated correctly
  6. * when set with prctl()
  7. *
  8. * Warning: this test will cause a very high load for a few seconds
  9. *
  10. */
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <unistd.h>
  14. #include <signal.h>
  15. #include <inttypes.h>
  16. #include <wait.h>
  17. #include <sys/prctl.h>
  18. #include <linux/prctl.h>
  19. /* Get/set the process' ability to use the timestamp counter instruction */
  20. #ifndef PR_GET_TSC
  21. #define PR_GET_TSC 25
  22. #define PR_SET_TSC 26
  23. # define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
  24. # define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
  25. #endif
  26. /* snippet from wikipedia :-) */
  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. int should_segv = 0;
  35. static void sigsegv_cb(int sig)
  36. {
  37. if (!should_segv)
  38. {
  39. fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n");
  40. exit(0);
  41. }
  42. if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0)
  43. {
  44. perror("prctl");
  45. exit(0);
  46. }
  47. should_segv = 0;
  48. rdtsc();
  49. }
  50. static void task(void)
  51. {
  52. signal(SIGSEGV, sigsegv_cb);
  53. alarm(10);
  54. for(;;)
  55. {
  56. rdtsc();
  57. if (should_segv)
  58. {
  59. fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n");
  60. exit(0);
  61. }
  62. if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0)
  63. {
  64. perror("prctl");
  65. exit(0);
  66. }
  67. should_segv = 1;
  68. }
  69. }
  70. int main(void)
  71. {
  72. int n_tasks = 100, i;
  73. fprintf(stderr, "[No further output means we're allright]\n");
  74. for (i=0; i<n_tasks; i++)
  75. if (fork() == 0)
  76. task();
  77. for (i=0; i<n_tasks; i++)
  78. wait(NULL);
  79. exit(0);
  80. }