From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752990AbbKYVvv (ORCPT ); Wed, 25 Nov 2015 16:51:51 -0500 Received: from terminus.zytor.com ([198.137.202.10]:49931 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752936AbbKYVvr (ORCPT ); Wed, 25 Nov 2015 16:51:47 -0500 Date: Wed, 25 Nov 2015 13:51:34 -0800 From: tip-bot for Len Brown Message-ID: Cc: linux-kernel@vger.kernel.org, len.brown@intel.com, tglx@linutronix.de, mingo@kernel.org, hpa@zytor.com Reply-To: hpa@zytor.com, linux-kernel@vger.kernel.org, len.brown@intel.com, tglx@linutronix.de, mingo@kernel.org In-Reply-To: <058618cc56ec6611171427ad7205e37e377aa8d4.1439738240.git.len.brown@intel.com> References: <058618cc56ec6611171427ad7205e37e377aa8d4.1439738240.git.len.brown@intel.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/cpu] x86: Replace RDRAND forced-reseed with simple sanity check Git-Commit-ID: 0007bccc3cfd1e69deb0fd73ccc426b4cedb061d X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: 0007bccc3cfd1e69deb0fd73ccc426b4cedb061d Gitweb: http://git.kernel.org/tip/0007bccc3cfd1e69deb0fd73ccc426b4cedb061d Author: Len Brown AuthorDate: Sun, 16 Aug 2015 11:20:00 -0400 Committer: Thomas Gleixner CommitDate: Wed, 25 Nov 2015 22:46:43 +0100 x86: Replace RDRAND forced-reseed with simple sanity check x86_init_rdrand() was added with 2 goals: 1. Sanity check that the built-in-self-test circuit on the Digital Random Number Generator (DRNG) is not complaining. As RDRAND HW self-checks on every invocation, this goal is achieved by simply invoking RDRAND and checking its return code. 2. Force a full re-seed of the random number generator. This was done out of paranoia to benefit the most un-sophisticated DRNG implementation conceivable in the architecture, an implementation that does not exist, and unlikely ever will. This worst-case full-re-seed is achieved by invoking a 64-bit RDRAND 8192 times. Unfortunately, this worst-case re-seed costs O(1,000us). Magnifying this cost, it is done from identify_cpu(), which is the synchronous critical path to bring a processor on-line -- repeated for every logical processor in the system at boot and resume from S3. As it is very expensive, and of highly dubious value, we delete the worst-case re-seed from the kernel. We keep the 1st goal -- sanity check the hardware, and mark it absent if it complains. This change reduces the cost of x86_init_rdrand() by a factor of 1,000x, to O(1us) from O(1,000us). Signed-off-by: Len Brown Link: http://lkml.kernel.org/r/058618cc56ec6611171427ad7205e37e377aa8d4.1439738240.git.len.brown@intel.com Signed-off-by: Thomas Gleixner --- arch/x86/kernel/cpu/rdrand.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/arch/x86/kernel/cpu/rdrand.c b/arch/x86/kernel/cpu/rdrand.c index 136ac74..819d949 100644 --- a/arch/x86/kernel/cpu/rdrand.c +++ b/arch/x86/kernel/cpu/rdrand.c @@ -33,28 +33,27 @@ static int __init x86_rdrand_setup(char *s) __setup("nordrand", x86_rdrand_setup); /* - * Force a reseed cycle; we are architecturally guaranteed a reseed - * after no more than 512 128-bit chunks of random data. This also - * acts as a test of the CPU capability. + * RDRAND has Built-In-Self-Test (BIST) that runs on every invocation. + * Run the instruction a few times as a sanity check. + * If it fails, it is simple to disable RDRAND here. */ -#define RESEED_LOOP ((512*128)/sizeof(unsigned long)) +#define SANITY_CHECK_LOOPS 8 void x86_init_rdrand(struct cpuinfo_x86 *c) { #ifdef CONFIG_ARCH_RANDOM unsigned long tmp; - int i, count, ok; + int i; if (!cpu_has(c, X86_FEATURE_RDRAND)) - return; /* Nothing to do */ + return; - for (count = i = 0; i < RESEED_LOOP; i++) { - ok = rdrand_long(&tmp); - if (ok) - count++; + for (i = 0; i < SANITY_CHECK_LOOPS; i++) { + if (!rdrand_long(&tmp)) { + clear_cpu_cap(c, X86_FEATURE_RDRAND); + printk_once(KERN_WARNING "rdrand: disabled\n"); + return; + } } - - if (count != RESEED_LOOP) - clear_cpu_cap(c, X86_FEATURE_RDRAND); #endif }