^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * This file is part of the Linux kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2011, Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Authors: Fenghua Yu <fenghua.yu@intel.com>,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * H. Peter Anvin <hpa@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <asm/archrandom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <asm/sections.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) static int __init x86_rdrand_setup(char *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) setup_clear_cpu_cap(X86_FEATURE_RDRAND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) setup_clear_cpu_cap(X86_FEATURE_RDSEED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) __setup("nordrand", x86_rdrand_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * RDRAND has Built-In-Self-Test (BIST) that runs on every invocation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Run the instruction a few times as a sanity check.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * If it fails, it is simple to disable RDRAND here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define SANITY_CHECK_LOOPS 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #ifdef CONFIG_ARCH_RANDOM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) void x86_init_rdrand(struct cpuinfo_x86 *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) unsigned int changed = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) unsigned long tmp, prev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (!cpu_has(c, X86_FEATURE_RDRAND))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) for (i = 0; i < SANITY_CHECK_LOOPS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (!rdrand_long(&tmp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) clear_cpu_cap(c, X86_FEATURE_RDRAND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) pr_warn_once("rdrand: disabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * Stupid sanity-check whether RDRAND does *actually* generate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * some at least random-looking data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) prev = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) for (i = 0; i < SANITY_CHECK_LOOPS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) if (rdrand_long(&tmp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (prev != tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) changed++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) prev = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (WARN_ON_ONCE(!changed))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) pr_emerg(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) "RDRAND gives funky smelling output, might consider not using it by booting with \"nordrand\"");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #endif