rdrand.c 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  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 <fenghua.yu@intel.com>,
  7. * H. Peter Anvin <hpa@linux.intel.com>
  8. */
  9. #include <linux/printk.h>
  10. #include <asm/processor.h>
  11. #include <asm/archrandom.h>
  12. #include <asm/sections.h>
  13. /*
  14. * RDRAND has Built-In-Self-Test (BIST) that runs on every invocation.
  15. * Run the instruction a few times as a sanity check. Also make sure
  16. * it's not outputting the same value over and over, which has happened
  17. * as a result of past CPU bugs.
  18. *
  19. * If it fails, it is simple to disable RDRAND and RDSEED here.
  20. */
  21. void x86_init_rdrand(struct cpuinfo_x86 *c)
  22. {
  23. enum { SAMPLES = 8, MIN_CHANGE = 5 };
  24. unsigned long sample, prev;
  25. bool failure = false;
  26. size_t i, changed;
  27. if (!cpu_has(c, X86_FEATURE_RDRAND))
  28. return;
  29. for (changed = 0, i = 0; i < SAMPLES; ++i) {
  30. if (!rdrand_long(&sample)) {
  31. failure = true;
  32. break;
  33. }
  34. changed += i && sample != prev;
  35. prev = sample;
  36. }
  37. if (changed < MIN_CHANGE)
  38. failure = true;
  39. if (failure) {
  40. clear_cpu_cap(c, X86_FEATURE_RDRAND);
  41. clear_cpu_cap(c, X86_FEATURE_RDSEED);
  42. pr_emerg("RDRAND is not reliable on this platform; disabling.\n");
  43. }
  44. }