From: Yi Chen <[email protected]>

This patch adapts 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 -- leaving Hygon without
hardware RNG support and below the performance and security posture of
Intel/AMD implementations.

Hygon C86 CPUs report the HygonGenuine vendor signature (CPUID leaf 0
ebx = 0x6f677948) and support both RDRAND and RDSEED (verified on a C86 7185:
CPUID.01H:ECX.RDRAND[bit 30] = 1, CPUID.(EAX=07H,ECX=0H):EBX.RDSEED[bit 18] = 
1).

Changes
-------

- Add signature_HYGON_ebx to both the RDSEED and RDRAND CPUID 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.  This 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.  An explicit "rdseed" token still selects the
  rdseed path.

Default-device policy: RDRAND vs RDSEED (performance and security tradeoff)
--------------------------------------------------------------------------

The "default" token selects the source used by ordinary std::random_device
construction, so its policy governs the common case of continuous random
number production.

- RDRAND is the higher-throughput hardware RNG instruction, suited to bulk
  generation.  It is the default on Hygon.
- RDSEED provides higher-entropy seed material (closer to a true entropy
  source) at lower throughput.  It remains fully accessible via the explicit
  "rdseed" token, and via the "hw"/"hardware" tokens, so applications that
  need maximum-entropy seeding are not affected.

Choosing RDRAND for the Hygon default therefore favors throughput for the
common case while preserving RDSEED access for security-sensitive callers --
a performance/security balance rather than a security regression.  The
default RDRAND path on Hygon provides the same 32 bits of entropy per call as
RDSEED, so the entropy() guarantee is unchanged.  The existing RDSEED-first
default policy is retained for Intel and AMD; their behavior is entirely
unchanged.

Testing
-------

Tested on Hygon C86 7185 hardware against two libstdc++ builds: an unpatched
build (_default) and a patched build (_hygon_adapter) carrying this change.

Functional before/after: the unpatched libstdc++ does not recognize Hygon in
the CPUID vendor allowlists, so the hardware RNG tokens fail on Hygon; the
patched build takes the hardware path:

  token     unpatched (_default)   patched (_hygon_adapter)
  -------   --------------------   ------------------------
  rdrand    throws (ENOSYS)        OK
  rdseed    throws (ENOSYS)        OK

With the patch, random_device("default"), ("rdrand"), and ("rdseed") all
construct and produce values without throwing; entropy() returns 32 for each.
The existing libstdc++-v3/testsuite/26_numerics/random/random_device/94087.cc
test -- which iterates the "default", "rdrand", "rdseed" (and "rand_s") tokens
with the random_device_available auto-skip helper -- passes on Hygon.
random.cc compiles cleanly with the libstdc++ warning flags
(-Wall -Wextra -Wwrite-strings -Wcast-qual -Wabi=19) under -Werror.

Performance (Hygon C86 7185), throughput generating unsigned int values per
token (warmup excluded; consistent across runs):

  token     lib build              source                M samples/s   ns/sample
  -------   --------------------   -------------------   -----------   ---------
  default   unpatched (_default)   software (getentropy) 1.66          603
  default   patched (_hygon_adapter) hardware RDRAND     2.63          380
  rdrand    patched                hardware RDRAND       2.63          380
  rdseed    patched                hardware RDSEED       0.16          6212

The "default" device is the path used by ordinary std::random_device
construction, so its performance and source matter most.  Two points follow:

- Before vs after the patch (default token): on the unpatched libstdc++ the
  "default" device falls through to a software source (getentropy, backed by
  the kernel entropy pool) at 1.66 M samples/s; with the patch it takes the
  hardware RDRAND path at 2.63 M samples/s -- about 1.6x faster, and it moves
  the default from a software fallback to a hardware RNG.

- Why RDRAND is the Hygon default (vs RDSEED): on this hardware RDRAND is
  ~16x faster than RDSEED (2.63 vs 0.16 M samples/s) while providing the same
  entropy() value (32 bits per call), so RDRAND is the better default for the
  common bulk-generation case.  RDSEED's higher-entropy seed material remains
  available via the explicit "rdseed" and "hw"/"hardware" tokens for callers
  that need it.  The "default" figure matches "rdrand", confirming the patched
  default path selects RDRAND.

Selecting RDRAND for the Hygon default therefore gives both a performance
gain (hardware RDRAND over the software fallback) and a hardware-RNG source
for the default device, while keeping RDSEED accessible -- a
performance/security balance rather than a trade-off.

Notes
-----

- The vendor check remains ebx-only, consistent with the existing Intel/AMD
  pattern in this file; the Hygon ebx value 0x6f677948 ("Hygo") is unique
  among major x86 vendors.
- No configure.ac/acinclude.m4 changes are needed: the
  GLIBCXX_CHECK_X86_RDRAND/GLIBCXX_CHECK_X86_RDSEED macros are vendor-agnostic
  and already enable both paths.

Yi Chen (1):
  libstdc++: Add Hygon x86 RNG instructions support to
    std::random_device

 libstdc++-v3/src/c++11/random.cc | 31 +++++++++++++++++++++++++++----
 1 file changed, 27 insertions(+), 4 deletions(-)

--
2.34.1


Reply via email to