diff options
| author | Erik Bosman <ebn310@few.vu.nl> | 2008-04-11 18:57:22 +0200 | 
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-04-19 19:19:55 +0200 | 
| commit | f1326973262382150c26bf4dfccd0fce310c4a9c (patch) | |
| tree | 746cda0780feebf8e97d34f1b8e64f77bb15c3e7 /Documentation/prctl/disable-tsc-test.c | |
| parent | 529e25f646e08901a6dad5768f681efffd77225e (diff) | |
| download | olio-linux-3.10-f1326973262382150c26bf4dfccd0fce310c4a9c.tar.xz olio-linux-3.10-f1326973262382150c26bf4dfccd0fce310c4a9c.zip  | |
generic, x86: add tests for prctl PR_GET_TSC and PR_SET_TSC
This patch adds three tests that test whether the PR_GET_TSC and
PR_SET_TSC commands have the desirable effect.
The tests check whether the control register is updated correctly
at context switches and try to discover bugs while enabling/disabling
the timestamp counter.
Signed-off-by: Erik Bosman <ejbosman@cs.vu.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'Documentation/prctl/disable-tsc-test.c')
| -rw-r--r-- | Documentation/prctl/disable-tsc-test.c | 94 | 
1 files changed, 94 insertions, 0 deletions
diff --git a/Documentation/prctl/disable-tsc-test.c b/Documentation/prctl/disable-tsc-test.c new file mode 100644 index 00000000000..843c81eac23 --- /dev/null +++ b/Documentation/prctl/disable-tsc-test.c @@ -0,0 +1,94 @@ +/* + * 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", +}; + +uint64_t rdtsc() { +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; +} + +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(int argc, char **argv) +{ +	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); +} +  |