chiark / gitweb /
Add a pile of debug output around the CPU dispatching machinery.
[catacomb] / base / dispatch.c
index 4b5e17a99cfeafc8c146ea3db0a9c1c379ba4541..eedf01726aeb1e1321e7c78d626d1869a3cfe5fb 100644 (file)
@@ -30,6 +30,8 @@
 #include "config.h"
 
 #include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -85,8 +87,11 @@ static void cpuid(struct cpuid *cc, unsigned a, unsigned c)
 #ifdef __GNUC__
   /* Stupid dance to detect whether the CPUID instruction is available. */
   f = getflags();
-  if (!(setflags(f |  EFLAGS_ID) & EFLAGS_ID)) return;
-  if (  setflags(f & ~EFLAGS_ID) & EFLAGS_ID ) return;
+  if (!(setflags(f |  EFLAGS_ID) & EFLAGS_ID) ||
+       setflags(f & ~EFLAGS_ID) & EFLAGS_ID) {
+    dispatch_debug("CPUID instruction not available");
+    return;
+  }
   setflags(f);
 
   /* Alas, EBX is magical in PIC code, so abuse ESI instead.  This isn't
@@ -95,6 +100,8 @@ static void cpuid(struct cpuid *cc, unsigned a, unsigned c)
   __asm__ ("pushl %%ebx; cpuid; movl %%ebx, %%esi; popl %%ebx"
           : "=a" (cc->a), "=S" (cc->b), "=c" (cc->c), "=d" (cc->d)
           : "a" (a) , "c" (c));
+#else
+  dispatch_debug("GNU inline assembler not available; can't CPUID");
 #endif
 }
 
@@ -146,6 +153,7 @@ static int xmm_registers_available_p(void)
           : "%ecx", "%edx");
   return (f);
 #else
+  dispatch_debug("GNU inline assembler not available; can't check for XMM");
   return (0);
 #endif
 }
@@ -154,6 +162,31 @@ static int xmm_registers_available_p(void)
 
 /*----- External interface ------------------------------------------------*/
 
+/* --- @dispatch_debug@ --- *
+ *
+ * Arguments:  @const char *fmt@ = a format string
+ *             @...@ = additional arguments
+ *
+ * Returns:    ---
+ *
+ * Use:                Writes a formatted message to standard output if dispatch
+ *             debugging is enabled.
+ */
+
+void dispatch_debug(const char *fmt, ...)
+{
+  va_list ap;
+  const char *e = getenv("CATACOMB_CPUDISPATCH_DEBUG");
+
+  if (e && *e != 'n' && *e != '0') {
+    va_start(ap, fmt);
+    fputs("Catacomb CPUDISPATCH: ", stderr);
+    vfprintf(stderr, fmt, ap);
+    fputc('\n', stderr);
+    va_end(ap);
+  }
+}
+
 /* --- @check_env@ --- *
  *
  * Arguments:  @const char *ftok@ = feature token
@@ -202,30 +235,41 @@ static int IGNORABLE check_env(const char *ftok)
 
 #include <stdio.h>
 
+static int IGNORABLE
+  feat_debug(const char *ftok, const char *check, int verdict)
+{
+  if (verdict >= 0) {
+    dispatch_debug("feature `%s': %s -> %s", ftok, check,
+                  verdict ? "available" : "absent");
+  }
+  return (verdict);
+}
+
 int cpu_feature_p(int feat)
 {
   int IGNORABLE f;
   IGNORE(f);
-#define CHECK_ENV(ftok)                                                        \
-  do { if ((f = check_env(ftok)) >= 0) return (f); } while (0)
+#define CASE_CPUFEAT(feat, ftok, cond) case CPUFEAT_##feat:            \
+  if ((f = feat_debug(ftok, "environment override",                    \
+                     check_env(ftok))) >= 0)                           \
+    return (f);                                                                \
+  else                                                                 \
+    return (feat_debug(ftok, "runtime probe", cond));
 
   switch (feat) {
 #ifdef CPUFAM_X86
-    case CPUFEAT_X86_SSE2: {
-      CHECK_ENV("x86:sse2");
-      return (xmm_registers_available_p() &&
-             cpuid_features_p(CPUID1D_SSE2, 0));
-    }
-    case CPUFEAT_X86_AESNI: {
-      check_env("x86:aesni");
-      return (xmm_registers_available_p() &&
-             cpuid_features_p(CPUID1D_SSE2, CPUID1C_AESNI));
-    }
+    CASE_CPUFEAT(X86_SSE2, "x86:sse2",
+                xmm_registers_available_p() &&
+                cpuid_features_p(CPUID1D_SSE2, 0));
+    CASE_CPUFEAT(X86_AESNI, "x86:aesni",
+                xmm_registers_available_p() &&
+                cpuid_features_p(CPUID1D_SSE2, CPUID1C_AESNI));
 #endif
     default:
+      dispatch_debug("denying unknown feature %d", feat);
       return (0);
   }
-#undef CHECK_ENV
+#undef CASE_CPUFEAT
 }
 
 /*----- That's all, folks -------------------------------------------------*/