summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@amacapital.net>2014-07-30 15:30:04 -0700
committerAndy Lutomirski <luto@amacapital.net>2014-07-30 15:30:04 -0700
commit1e13707b65ee0d5e763e5663757fa913cf535e1d (patch)
tree76bd4758a06d2fa0cac380dc285e5f83ac94316b
parent981e86877c3cd916949808cb3f0c4b664043cba0 (diff)
downloadmisc-tests-1e13707b65ee0d5e763e5663757fa913cf535e1d.tar.gz
user_visible_state: Handle CPUs / VMs that don't support RDTSCP
-rw-r--r--user_visible_state.c43
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[] = {