mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-29 07:34:06 +08:00
92dd8dd4d0
Move prctl tests from Documentation/prctl to selftests/prctl. Remove prctl from Makefile to move the test. Update prctl Makefile to work under selftests. prctl will not be run as part of selftests suite and will not be included in install targets. They can be built separately for now. Acked-by: Jonathan Corbet <corbet@lwn.net> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
96 lines
2.1 KiB
C
96 lines
2.1 KiB
C
/*
|
|
* Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
|
|
*
|
|
* Basic test to test behaviour of PR_GET_TSC and PR_SET_TSC
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <inttypes.h>
|
|
|
|
|
|
#include <sys/prctl.h>
|
|
#include <linux/prctl.h>
|
|
|
|
/* Get/set the process' ability to use the timestamp counter instruction */
|
|
#ifndef PR_GET_TSC
|
|
#define PR_GET_TSC 25
|
|
#define PR_SET_TSC 26
|
|
# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
|
|
# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
|
|
#endif
|
|
|
|
const char *tsc_names[] =
|
|
{
|
|
[0] = "[not set]",
|
|
[PR_TSC_ENABLE] = "PR_TSC_ENABLE",
|
|
[PR_TSC_SIGSEGV] = "PR_TSC_SIGSEGV",
|
|
};
|
|
|
|
static uint64_t rdtsc(void)
|
|
{
|
|
uint32_t lo, hi;
|
|
/* We cannot use "=A", since this would use %rax on x86_64 */
|
|
__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
|
|
return (uint64_t)hi << 32 | lo;
|
|
}
|
|
|
|
static void sigsegv_cb(int sig)
|
|
{
|
|
int tsc_val = 0;
|
|
|
|
printf("[ SIG_SEGV ]\n");
|
|
printf("prctl(PR_GET_TSC, &tsc_val); ");
|
|
fflush(stdout);
|
|
|
|
if ( prctl(PR_GET_TSC, &tsc_val) == -1)
|
|
perror("prctl");
|
|
|
|
printf("tsc_val == %s\n", tsc_names[tsc_val]);
|
|
printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n");
|
|
fflush(stdout);
|
|
if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1)
|
|
perror("prctl");
|
|
|
|
printf("rdtsc() == ");
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
int tsc_val = 0;
|
|
|
|
signal(SIGSEGV, sigsegv_cb);
|
|
|
|
printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
|
|
printf("prctl(PR_GET_TSC, &tsc_val); ");
|
|
fflush(stdout);
|
|
|
|
if ( prctl(PR_GET_TSC, &tsc_val) == -1)
|
|
perror("prctl");
|
|
|
|
printf("tsc_val == %s\n", tsc_names[tsc_val]);
|
|
printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
|
|
printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n");
|
|
fflush(stdout);
|
|
|
|
if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1)
|
|
perror("prctl");
|
|
|
|
printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
|
|
printf("prctl(PR_SET_TSC, PR_TSC_SIGSEGV)\n");
|
|
fflush(stdout);
|
|
|
|
if ( prctl(PR_SET_TSC, PR_TSC_SIGSEGV) == -1)
|
|
perror("prctl");
|
|
|
|
printf("rdtsc() == ");
|
|
fflush(stdout);
|
|
printf("%llu\n", (unsigned long long)rdtsc());
|
|
fflush(stdout);
|
|
|
|
exit(EXIT_SUCCESS);
|
|
}
|
|
|