disable-tsc-ctxt-sw-stress-test.c 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  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. * at context switches
  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. static uint64_t rdtsc(void)
  27. {
  28. uint32_t lo, hi;
  29. /* We cannot use "=A", since this would use %rax on x86_64 */
  30. __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
  31. return (uint64_t)hi << 32 | lo;
  32. }
  33. static void sigsegv_expect(int sig)
  34. {
  35. /* */
  36. }
  37. static void segvtask(void)
  38. {
  39. if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0)
  40. {
  41. perror("prctl");
  42. exit(0);
  43. }
  44. signal(SIGSEGV, sigsegv_expect);
  45. alarm(10);
  46. rdtsc();
  47. fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n");
  48. exit(0);
  49. }
  50. static void sigsegv_fail(int sig)
  51. {
  52. fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n");
  53. exit(0);
  54. }
  55. static void rdtsctask(void)
  56. {
  57. if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0)
  58. {
  59. perror("prctl");
  60. exit(0);
  61. }
  62. signal(SIGSEGV, sigsegv_fail);
  63. alarm(10);
  64. for(;;) rdtsc();
  65. }
  66. int main(void)
  67. {
  68. int n_tasks = 100, i;
  69. fprintf(stderr, "[No further output means we're allright]\n");
  70. for (i=0; i<n_tasks; i++)
  71. if (fork() == 0)
  72. {
  73. if (i & 1)
  74. segvtask();
  75. else
  76. rdtsctask();
  77. }
  78. for (i=0; i<n_tasks; i++)
  79. wait(NULL);
  80. exit(0);
  81. }