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 > >
