X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb/blobdiff_plain/a02a22d4b55d233ada2e030a44065f464b79f137..2cb17e021884f46af033c31a4deb5f60714c3997:/base/dispatch.c diff --git a/base/dispatch.c b/base/dispatch.c index 10ae4044..b70d44b6 100644 --- a/base/dispatch.c +++ b/base/dispatch.c @@ -47,6 +47,7 @@ # define CPUID1D_SSE2 (1u << 26) # define CPUID1D_FXSR (1u << 24) # define CPUID1C_AESNI (1u << 25) +# define CPUID1C_RDRAND (1u << 30) struct cpuid { unsigned a, b, c, d; }; @@ -204,13 +205,12 @@ static int xmm_registers_available_p(void) /* Try to find the system's definitions for auxiliary vector entries. */ #ifdef HAVE_SYS_AUXV_H # include -#else -# ifdef HAVE_LINUX_AUXVEC_H -# include -# endif -# ifdef HAVE_ASM_HWCAP_H -# include -# endif +#endif +#ifdef HAVE_LINUX_AUXVEC_H +# include +#endif +#ifdef HAVE_ASM_HWCAP_H +# include #endif /* The type of entries in the auxiliary vector. I'm assuming that `unsigned @@ -224,6 +224,15 @@ struct auxentry { unsigned long type; union auxval value; }; * that the necessary entry types are defined. This is primarily ordered by * entry type to minimize duplication. */ +#if defined(AT_HWCAP) && CPUFAM_ARMEL +# define WANT_ANY 1 +# define WANT_AT_HWCAP(_) _(AT_HWCAP, u, hwcap) +#endif + +#if defined(AT_HWCAP2) && CPUFAM_ARMEL +# define WANT_ANY 1 +# define WANT_AT_HWCAP2(_) _(AT_HWCAP2, u, hwcap2) +#endif /* If we couldn't find any interesting entries then we can switch all of this * machinery off. Also do that if we have no means for atomic updates. @@ -242,6 +251,9 @@ static unsigned hwcaps = 0; #ifndef WANT_AT_HWCAP # define WANT_AT_HWCAP(_) #endif +#ifndef WANT_AT_HWCAP2 +# define WANT_AT_HWCAP2(_) +#endif /* For each CPU family, define two lists. * @@ -255,6 +267,17 @@ static unsigned hwcaps = 0; * intends to satisfy from the auxiliary vector. Each entry contains a * feature name suffix, and the token name (for `check_env'). */ +#if CPUFAM_ARMEL +# define WANTAUX(_) \ + WANT_AT_HWCAP(_) \ + WANT_AT_HWCAP2(_) +# define CAPMAP(_) \ + _(ARM_VFP, "arm:vfp") \ + _(ARM_NEON, "arm:neon") \ + _(ARM_V4, "arm:v4") \ + _(ARM_D32, "arm:d32") \ + _(ARM_AES, "arm:aes") +#endif /* Build the bitmask for `hwcaps' from the `CAPMAP' list. */ enum { @@ -306,8 +329,8 @@ static void probe_hwcaps(void) /* Shiny new libc lets us request individual entry types. This is almost * too easy. */ -# define CAP__GET(type, slot, ubranch) \ - probed.slot.ubranch = (AUXUTYPE_##ubranch)getauxval(type); +# define CAP__GET(type, ubranch, slot) \ + probed.slot = (AUXUTYPE_##ubranch)getauxval(type); WANTAUX(CAP__GET) #else /* Otherwise we're a bit stuck, really. Modern Linux kernels make a copy @@ -346,6 +369,7 @@ static void probe_hwcaps(void) #define CAP__SWITCH(type, ubranch, slot) \ case type: probed.slot = a->value.ubranch; break; WANTAUX(CAP__SWITCH) + case AT_NULL: goto clean; } } @@ -358,6 +382,15 @@ static void probe_hwcaps(void) /* Each CPU family now has to pick through what was found and stashed in * `probed', and set the appropriate flag bits in `hw'. */ +#if CPUFAM_ARMEL + if (probed.hwcap & HWCAP_VFPv3) hw |= HF_ARM_VFP; + if (probed.hwcap & HWCAP_NEON) hw |= HF_ARM_NEON; + if (probed.hwcap & HWCAP_VFPD32) hw |= HF_ARM_D32; + if (probed.hwcap & HWCAP_VFPv4) hw |= HF_ARM_V4; +# ifdef HWCAP2_AES + if (probed.hwcap2 & HWCAP2_AES) hw |= HF_ARM_AES; +# endif +#endif /* Store the bitmask of features we probed for everyone to see. */ DISPATCH_STORE(hwcaps, hw); @@ -496,10 +529,12 @@ int cpu_feature_p(int feat) CASE_CPUFEAT(X86_AESNI, "x86:aesni", xmm_registers_available_p() && cpuid_features_p(CPUID1D_SSE2, CPUID1C_AESNI)); + CASE_CPUFEAT(X86_RDRAND, "x86:rdrand", + cpuid_features_p(0, CPUID1C_RDRAND)); #endif #ifdef CAPMAP # define FEATP__CASE(feat, tok) \ - CASE_CPUFEAT(feat, tok, get_hwcaps & HF_##feat) + CASE_CPUFEAT(feat, tok, get_hwcaps() & HF_##feat) CAPMAP(FEATP__CASE) #undef FEATP__CASE #endif