rdrand.c 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * This file is part of the Linux kernel.
  4. *
  5. * Copyright (c) 2011, Intel Corporation
  6. * Authors: Fenghua Yu <[email protected]>,
  7. * H. Peter Anvin <[email protected]>
  8. */
  9. #include <asm/processor.h>
  10. #include <asm/archrandom.h>
  11. #include <asm/sections.h>
  12. /*
  13. * RDRAND has Built-In-Self-Test (BIST) that runs on every invocation.
  14. * Run the instruction a few times as a sanity check. Also make sure
  15. * it's not outputting the same value over and over, which has happened
  16. * as a result of past CPU bugs.
  17. *
  18. * If it fails, it is simple to disable RDRAND and RDSEED here.
  19. */
  20. void x86_init_rdrand(struct cpuinfo_x86 *c)
  21. {
  22. enum { SAMPLES = 8, MIN_CHANGE = 5 };
  23. unsigned long sample, prev;
  24. bool failure = false;
  25. size_t i, changed;
  26. if (!cpu_has(c, X86_FEATURE_RDRAND))
  27. return;
  28. for (changed = 0, i = 0; i < SAMPLES; ++i) {
  29. if (!rdrand_long(&sample)) {
  30. failure = true;
  31. break;
  32. }
  33. changed += i && sample != prev;
  34. prev = sample;
  35. }
  36. if (changed < MIN_CHANGE)
  37. failure = true;
  38. if (failure) {
  39. clear_cpu_cap(c, X86_FEATURE_RDRAND);
  40. clear_cpu_cap(c, X86_FEATURE_RDSEED);
  41. pr_emerg("RDRAND is not reliable on this platform; disabling.\n");
  42. }
  43. }