diff options
author | Andy Lutomirski <luto@amacapital.net> | 2014-07-30 15:30:04 -0700 |
---|---|---|
committer | Andy Lutomirski <luto@amacapital.net> | 2014-07-30 15:30:04 -0700 |
commit | 1e13707b65ee0d5e763e5663757fa913cf535e1d (patch) | |
tree | 76bd4758a06d2fa0cac380dc285e5f83ac94316b | |
parent | 981e86877c3cd916949808cb3f0c4b664043cba0 (diff) | |
download | misc-tests-1e13707b65ee0d5e763e5663757fa913cf535e1d.tar.gz |
user_visible_state: Handle CPUs / VMs that don't support RDTSCP
-rw-r--r-- | user_visible_state.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/user_visible_state.c b/user_visible_state.c index 715bd60..d878e1a 100644 --- a/user_visible_state.c +++ b/user_visible_state.c @@ -1,11 +1,43 @@ +#include <err.h> #include <stdio.h> #include <stdint.h> +#include <signal.h> +#include <setjmp.h> +#include <string.h> #include <xmmintrin.h> #include <asm/prctl.h> #include <sys/prctl.h> extern int arch_prctl(int, unsigned long); +static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), + int flags) +{ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = handler; + sa.sa_flags = SA_SIGINFO | flags; + sigemptyset(&sa.sa_mask); + if (sigaction(sig, &sa, 0)) + err(1, "sigaction"); +} + +static void clearhandler(int sig) +{ + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + if (sigaction(sig, &sa, 0)) + err(1, "sigaction"); +} + +static jmp_buf sigill_jmp; +static void sigill(int sig, siginfo_t *si, void *ctx_void) +{ + siglongjmp(sigill_jmp, 1); +} + /* returns GDT limit */ static uint16_t show_gdt_and_idt(void) { @@ -120,8 +152,15 @@ static void show_flags(void) static void show_rdtscp(void) { unsigned int cpu; - __builtin_ia32_rdtscp(&cpu); - printf("RDTSCP: cpu %d\n", cpu); + + sethandler(SIGILL, sigill, 0); + if (sigsetjmp(sigill_jmp, 0)) { + printf("RDTSCP: not supported\n"); + } else { + __builtin_ia32_rdtscp(&cpu); + printf("RDTSCP: cpu %d\n", cpu); + } + clearhandler(SIGILL); } static const char *user_seg_types[] = { |