base/dispatch.c, rand/rand.c, and asm: Support `rdseed' for quick noise.
[catacomb] / base / dispatch.c
index bda7f88..50c842e 100644 (file)
@@ -56,6 +56,8 @@ enum {
 #  define CPUID1C_AVX (1u << 28)
 #  define CPUID1C_RDRAND (1u << 30)
 
+  CPUID_7_0_B,                         /* eax = 7, ecx = 0 => ebx&?? */
+#  define CPUID70B_RDSEED (1u << 18)
 };
 
 struct cpuid { unsigned a, b, c, d; };
@@ -99,6 +101,10 @@ static int cpuid_feature_p(unsigned leaf, unsigned bits)
       if (cpuid_maxleaf() < 1) return (0);
       cpuid(&c, 1, 0); r = c.c;
       break;
+    case CPUID_7_0_B:
+      if (cpuid_maxleaf() < 7) return (0);
+      cpuid(&c, 7, 0); r = c.b;
+      break;
     default:
       assert(!"unknown cpuid leaf");
   }
@@ -139,6 +145,7 @@ static int rdrand_works_p(unsigned op)
 
   switch (op) {
     case OP_RDRAND: what = "RDRAND"; break;
+    case OP_RDSEED: what = "RDSEED"; break;
     default: assert(!"unexpected op");
   }
 
@@ -527,6 +534,9 @@ int cpu_feature_p(int feat)
     CASE_CPUFEAT(X86_PCLMUL, "x86:pclmul",
                 cpuid_feature_p(CPUID_1_C, CPUID1C_PCLMUL) &&
                 xmm_registers_available_p());
+    CASE_CPUFEAT(X86_RDSEED, "x86:rdseed",
+                cpuid_feature_p(CPUID_7_0_B, CPUID70B_RDSEED) &&
+                rdrand_works_p(OP_RDSEED));
 #endif
 #ifdef CAPMAP
 #  define FEATP__CASE(feat, tok)                                       \