On Tue, 30 Jun 2026 at 11:28, <[email protected]> wrote:
>
> From: Yi Chen <[email protected]>
>
> Adapt std::random_device to use the Hygon x86 hardware RNG instructions
> RDRAND and RDSEED, bringing Hygon C86 platforms to parity with Intel and AMD.
> Prior to this change Hygon was absent from the CPUID vendor allowlists that
> gate RDRAND/RDSEED in random_device::_M_init, so std::random_device fell
> through to a software RNG.
>
> Hygon C86 CPUs report the HygonGenuine vendor signature (CPUID leaf 0
> ebx 0x6f677948) and support both RDRAND and RDSEED.  Add signature_HYGON_ebx
> to the RDSEED and RDRAND vendor allowlists in random_device::_M_init, matching
> the existing ebx-only Intel/AMD pattern.  With this, the explicit "rdseed" and
> "rdrand" token paths select sources on Hygon in exactly the same order as on
> Intel/AMD.
>
> For the default device (the "default" token, which == any) Hygon prefers 
> RDRAND,
> the higher-throughput instruction, suited to bulk generation; RDSEED provides
> higher-entropy seed material at lower throughput and remains fully accessible
> via the explicit "rdseed" token and the "hw"/"hardware" tokens.  Choosing 
> RDRAND
> for the Hygon default therefore favors throughput for the common case while
> preserving RDSEED access for security-sensitive callers, and the entropy()
> guarantee is unchanged (32 bits per call for both paths).  The default policy 
> is
> handled by a dedicated check at the top of _M_init, kept separate from the
> explicit-token paths so their selection order stays identical to Intel/AMD.
> The existing RDSEED-first default policy is retained for Intel and AMD; their
> behavior is entirely unchanged.
>
> Tested on Hygon C86 7185: random_device("default"), ("rdrand") and ("rdseed")
> all succeed; entropy() returns 32 for each; the existing 94087.cc test, which
> exercises the default-token path, passes on Hygon.

Thanks, I'll get this pushed to trunk.

>
>         * src/c++11/random.cc (random_device::_M_init): Add 
> signature_HYGON_ebx to
>         the RDSEED and RDRAND CPUID vendor allowlists.  For the default 
> device on
>         Hygon, prefer RDRAND via a dedicated check at the top of the function.
>
> Signed-off-by: Yi Chen <[email protected]>
> ---
>  libstdc++-v3/src/c++11/random.cc | 31 +++++++++++++++++++++++++++----
>  1 file changed, 27 insertions(+), 4 deletions(-)
>
> diff --git a/libstdc++-v3/src/c++11/random.cc 
> b/libstdc++-v3/src/c++11/random.cc
> index 2f37fd5b88e..d616852b44d 100644
> --- a/libstdc++-v3/src/c++11/random.cc
> +++ b/libstdc++-v3/src/c++11/random.cc
> @@ -390,14 +390,35 @@ namespace std _GLIBCXX_VISIBILITY(default)
>      }
>  #endif // _GLIBCXX_USE_CRT_RAND_S
>
> +#ifdef USE_RDRAND
> +    // For the default device on Hygon prefer RDRAND (faster than RDSEED for
> +    // bulk generation); an explicit "rdseed" token still selects rdseed 
> below.
> +    if (which == any)
> +    {
> +      unsigned int eax, ebx, ecx, edx;
> +      if (__get_cpuid_max(0, &ebx) > 0 && ebx == signature_HYGON_ebx)
> +       {
> +         // CPUID.01H:ECX.RDRAND[bit 30]
> +         __cpuid(1, eax, ebx, ecx, edx);
> +         if (ecx & bit_RDRND)
> +           {
> +             _M_func = &__x86_rdrand;
> +             return;
> +           }
> +       }
> +    }
> +#endif // USE_RDRAND
> +
>  #ifdef USE_RDSEED
>      if (which & rdseed)
>      {
>        unsigned int eax, ebx, ecx, edx;
>        // Check availability of cpuid and, for now at least, also the
> -      // CPU signature for Intel and AMD.
> +      // CPU signature for Intel, AMD and Hygon.
>        if (__get_cpuid_max(0, &ebx) > 0
> -         && (ebx == signature_INTEL_ebx || ebx == signature_AMD_ebx))
> +         && (ebx == signature_INTEL_ebx
> +             || ebx == signature_AMD_ebx
> +             || ebx == signature_HYGON_ebx))
>         {
>           // CPUID.(EAX=07H, ECX=0H):EBX.RDSEED[bit 18]
>           __cpuid_count(7, 0, eax, ebx, ecx, edx);
> @@ -425,9 +446,11 @@ namespace std _GLIBCXX_VISIBILITY(default)
>      {
>        unsigned int eax, ebx, ecx, edx;
>        // Check availability of cpuid and, for now at least, also the
> -      // CPU signature for Intel and AMD.
> +      // CPU signature for Intel, AMD and Hygon.
>        if (__get_cpuid_max(0, &ebx) > 0
> -         && (ebx == signature_INTEL_ebx || ebx == signature_AMD_ebx))
> +         && (ebx == signature_INTEL_ebx
> +             || ebx == signature_AMD_ebx
> +             || ebx == signature_HYGON_ebx))
>         {
>           // CPUID.01H:ECX.RDRAND[bit 30]
>           __cpuid(1, eax, ebx, ecx, edx);
> --
> 2.34.1
>
>

Reply via email to