On Tue, 6 Oct 2026, 21:30 Sammy Al Hashemi, <[email protected]> wrote:

> Yes I took inspiration from your work :) I hope that it is okay!
>

You can't just take somebody else's work and put your name on it.

Was it copied by hand or produced using an LLM?


Primarily my work here has been a big learning exercise for me. During this
> patch I learned how to properly test with qemu, learned  how to properly
> cross-compile, and learned more of the gcc contributing standard and code.
> I should have given you credit in the patch comments I apologize. But once
> I figured out how to properly cross compile here and ensure that this
> workaround was indeed used, I pushed it up for the community to discuss. I
> apologize Jonathan for  my lack of foresight here ;(.
>
> Best,
> Sammy
>
> On Tue, Oct 6, 2026, at 4:06 PM, Jonathan Wakely wrote:
>
> On Tue, 6 Oct 2026 at 17:35, Sammy Al Hashemi <[email protected]> wrote:
> >
> > From: Sammyalhashe <[email protected]>
>
> This patch looks remarkably similar to my own patch posted to bugzilla
> exactly five years ago:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100444#c14
>
> Even the wording of the comments is identical.
>
> >
> > Patching libstdc++ random so that it checks if rdrand on amd is broken
> > before returning a value.
> >
> > AMD 3000 CPUs seem to have a bug where the RDRAND instruction always
> > emits all 1s (aka 4294967295).
> >
> > This commit provides a workaround (upon detecting an AMD cpu) - to try
> > the random function a number of times. If it continues to return the
> > same broken consistent value, we confirm the random instruction is buggy
> > on this cpu and emit a runtime error.
> >
> > libstdc++-v3/ChangeLog:
> >
> >         PR libstdc++/100444
> >         * src/c++11/random.cc (__x86_cpu_sig_ebx): New function.
> >         (__x86_cpu_supports_rdrand, __x86_cpu_supports_rdseed): New
> >         functions.
> >         (__x86_amd_workaround): New function.
> >         (which_source): Look through __x86_amd_workaround to the
> >         wrapped function.
> >         (random_device::_M_init(const string&)): Use new helpers.  Wrap
> >         RDRAND and RDSEED with __x86_amd_workaround on AMD CPUs.
> >         (random_device::_M_fini): Do nothing for __x86_amd_workaround.
> >
> > Signed-off-by: Sammy Al Hashemi <[email protected]>
> > ---
> > I don't have access to an affected Ryzen 3000 system, so this has not
> > been tested on the hardware that exhibits the bug.
> >
> > Tested on x86_64-linux, cross-built and run under `qemu -cpu
> > EPYC-Rome`. The all-ones failure path was verified with a temporary
> > fault-injection patch (not included).
> >
> > If anyone has an affected machine with a pre-fix BIOS, testing would
> > be appreciated.
> >
> >  libstdc++-v3/src/c++11/random.cc | 139 +++++++++++++++++++++++--------
> >  1 file changed, 102 insertions(+), 37 deletions(-)
> >
> > diff --git a/libstdc++-v3/src/c++11/random.cc
> b/libstdc++-v3/src/c++11/random.cc
> > index 502ba8f44c7..a7888a83c62 100644
> > --- a/libstdc++-v3/src/c++11/random.cc
> > +++ b/libstdc++-v3/src/c++11/random.cc
> > @@ -146,6 +146,57 @@ namespace std _GLIBCXX_VISIBILITY(default)
> >  #endif
> >  #endif
> >
> > +#if USE_RDRAND || USE_RDSEED
> > +    // Check availability of cpuid and if supported, return ebx
> register.
> > +    // The ebx register can be used to identify the cpu manufacturer.
> > +    inline unsigned int
> > +    __x86_cpu_sig_ebx() noexcept
> > +    {
> > +      unsigned int ebx;
> > +      if (__get_cpuid_max(0, &ebx) > 0)
> > +       return ebx;
> > +      return 0;
> > +    }
> > +
> > +    inline bool
> > +    __x86_cpu_supports_rdrand() noexcept
> > +    {
> > +#ifdef USE_RDRAND
> > +      unsigned int eax, ebx, ecx, edx;
> > +      // CPUID.01H:ECX.RDRAND[bit 30]
> > +      __cpuid(1, eax, ebx, ecx, edx);
> > +      return ecx & bit_RDRND;
> > +#else
> > +      return false;
> > +#endif
> > +    }
> > +
> > +    inline bool
> > +    __x86_cpu_supports_rdseed() noexcept
> > +    {
> > +      unsigned int eax, ebx, ecx, edx;
> > +      // CPUID.(EAX=07H, ECX=0H):EBX.RDSEED[bit 18]
> > +      __cpuid_count(7, 0, eax, ebx, ecx, edx);
> > +      return ebx & bit_RDSEED;
> > +    }
> > +
> > +    // Workaround AMD Ryzen 3000 bug, see PR libstdc++/100444
> > +    unsigned int
> > +    __x86_amd_workaround(void* fx)
> > +    {
> > +      auto f = reinterpret_cast<unsigned int(*)(void*)>(fx);
> > +      const unsigned int ALL_ONES = 0xffffffff;
> > +      auto n = f(nullptr);
> > +      int retries = 10;
> > +      while (--retries && n == ALL_ONES)
> > +       n = f(nullptr);
> > +      if (n == ALL_ONES)
> > +       std::__throw_runtime_error(__N("random_device: AMD Ryzen 3000
> bug "
> > +                                      "detected, BIOS update is
> required."));
> > +      return n;
> > +    }
> > +#endif
> > +
> >  #ifdef USE_DARN
> >      unsigned int
> >      __attribute__((target("cpu=power9")))
> > @@ -279,6 +330,11 @@ namespace std _GLIBCXX_VISIBILITY(default)
> >         return darn;
> >  #endif
> >
> > +#if defined USE_RDRAND || defined USE_RDSEED
> > +      if (func == &__x86_amd_workaround)
> > +       return which_source(reinterpret_cast<decltype(func)>(file),
> nullptr);
> > +#endif
> > +
> >  #ifdef _GLIBCXX_USE_DEV_RANDOM
> >        if (file != nullptr)
> >         return device_file;
> > @@ -412,31 +468,33 @@ namespace std _GLIBCXX_VISIBILITY(default)
> >  #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, AMD and Hygon.
> > -      if (__get_cpuid_max(0, &ebx) > 0
> > -         && (ebx == signature_INTEL_ebx
> > -             || ebx == signature_AMD_ebx
> > -             || ebx == signature_HYGON_ebx))
> > +      const unsigned int sig_ebx = __x86_cpu_sig_ebx();
> > +      // For now, we only use RDSEED for Intel, AMD, and Hygon
> > +      // processors.
> > +      if (sig_ebx == signature_INTEL_ebx
> > +         || sig_ebx == signature_AMD_ebx
> > +         || sig_ebx == signature_HYGON_ebx)
> > +      {
> > +       if (__x86_cpu_supports_rdseed())
> >         {
> > -         // CPUID.(EAX=07H, ECX=0H):EBX.RDSEED[bit 18]
> > -         __cpuid_count(7, 0, eax, ebx, ecx, edx);
> > -         if (ebx & bit_RDSEED)
> > -           {
> > -#ifdef USE_RDRAND
> > -             // CPUID.01H:ECX.RDRAND[bit 30]
> > -             __cpuid(1, eax, ebx, ecx, edx);
> > -             if (ecx & bit_RDRND)
> > -               {
> > -                 _M_func = &__x86_rdseed_rdrand;
> > -                 return;
> > -               }
> > -#endif
> > -             _M_func = &__x86_rdseed;
> > -             return;
> > -           }
> > +         if (__x86_cpu_supports_rdrand())
> > +         {
> > +           _M_func = &__x86_rdseed_rdrand;
> > +         }
> > +         else
> > +         {
> > +           _M_func = &__x86_rdseed;
> > +         }
> > +
> > +         // AMD 3000 Workaround
> > +         if (sig_ebx == signature_AMD_ebx)
> > +         {
> > +           _M_file = reinterpret_cast<void*>(_M_func);
> > +           _M_func = &__x86_amd_workaround;
> > +         }
> > +         return;
> >         }
> > +      }
> >        err = unsupported;
> >      }
> >  #endif // USE_RDSEED
> > @@ -444,22 +502,24 @@ namespace std _GLIBCXX_VISIBILITY(default)
> >  #ifdef USE_RDRAND
> >      if (which & rdrand)
> >      {
> > -      unsigned int eax, ebx, ecx, edx;
> > -      // Check availability of cpuid and, for now at least, also the
> > -      // CPU signature for Intel, AMD and Hygon.
> > -      if (__get_cpuid_max(0, &ebx) > 0
> > -         && (ebx == signature_INTEL_ebx
> > -             || ebx == signature_AMD_ebx
> > -             || ebx == signature_HYGON_ebx))
> > +      const unsigned int sig_ebx = __x86_cpu_sig_ebx();
> > +      // For now, we only use RDRAND for Intel, AMD, and Hygon
> > +      // processors.
> > +      if (sig_ebx == signature_INTEL_ebx
> > +         || sig_ebx == signature_AMD_ebx
> > +         || sig_ebx == signature_HYGON_ebx)
> > +      {
> > +       if (__x86_cpu_supports_rdrand())
> >         {
> > -         // CPUID.01H:ECX.RDRAND[bit 30]
> > -         __cpuid(1, eax, ebx, ecx, edx);
> > -         if (ecx & bit_RDRND)
> > -           {
> > -             _M_func = &__x86_rdrand;
> > -             return;
> > -           }
> > +         _M_func = &__x86_rdrand;
> > +         if (sig_ebx == signature_AMD_ebx)
> > +         {
> > +           _M_file = reinterpret_cast<void*>(_M_func);
> > +           _M_func = &__x86_amd_workaround;
> > +         }
> > +         return;
> >         }
> > +      }
> >        err = unsupported;
> >      }
> >  #endif // USE_RDRAND
> > @@ -584,6 +644,11 @@ namespace std _GLIBCXX_VISIBILITY(default)
> >      if (!_M_file)
> >        return;
> >
> > +#if USE_RDRAND || USE_RDSEED
> > +    if (_M_func == &__x86_amd_workaround)
> > +      return;
> > +#endif
> > +
> >  #if USE_LCG
> >      if (_M_func == &__lcg)
> >        {
> > --
> > 2.55.0
> >
>
>
>

Reply via email to