From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752969AbaGPVp7 (ORCPT ); Wed, 16 Jul 2014 17:45:59 -0400 Received: from mail-pd0-f169.google.com ([209.85.192.169]:56493 "EHLO mail-pd0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752823AbaGPVpx (ORCPT ); Wed, 16 Jul 2014 17:45:53 -0400 From: Andy Lutomirski To: kvm@vger.kernel.org, "H. Peter Anvin" , "Theodore Ts'o" , linux-kernel@vger.kernel.org, Kees Cook , x86@kernel.org Cc: Daniel Borkmann , Srivatsa Vaddagiri , Raghavendra K T , Gleb Natapov , Paolo Bonzini , bsd@redhat.com, Andy Lutomirski Subject: [PATCH v3 2/5] random,x86: Add arch_get_slow_rng_u64 Date: Wed, 16 Jul 2014 14:45:34 -0700 Message-Id: <5778e65d5ca52bebbaa023e177d863e44f098e96.1405546879.git.luto@amacapital.net> X-Mailer: git-send-email 1.9.3 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org arch_get_slow_rng_u64 tries to get 64 bits of RNG seed data. Unlike arch_get_random_{bytes,seed}, etc., it makes no claims about entropy content. It's also likely to be much slower and should not be used frequently. That being said, it should be fast enough to call several times during boot without any noticeable slowdown. This initial implementation backs it with MSR_KVM_GET_RNG_SEED if available. The intent is for other hypervisor guest implementations to implement this interface. Signed-off-by: Andy Lutomirski --- arch/x86/Kconfig | 4 ++++ arch/x86/include/asm/archslowrng.h | 30 ++++++++++++++++++++++++++++++ arch/x86/kernel/kvm.c | 22 ++++++++++++++++++++++ include/linux/random.h | 9 +++++++++ 4 files changed, 65 insertions(+) create mode 100644 arch/x86/include/asm/archslowrng.h diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index a8f749e..4dfb539 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -593,6 +593,7 @@ config KVM_GUEST bool "KVM Guest support (including kvmclock)" depends on PARAVIRT select PARAVIRT_CLOCK + select ARCH_SLOW_RNG default y ---help--- This option enables various optimizations for running under the KVM @@ -627,6 +628,9 @@ config PARAVIRT_TIME_ACCOUNTING config PARAVIRT_CLOCK bool +config ARCH_SLOW_RNG + bool + endif #HYPERVISOR_GUEST config NO_BOOTMEM diff --git a/arch/x86/include/asm/archslowrng.h b/arch/x86/include/asm/archslowrng.h new file mode 100644 index 0000000..c8e8d0d --- /dev/null +++ b/arch/x86/include/asm/archslowrng.h @@ -0,0 +1,30 @@ +/* + * This file is part of the Linux kernel. + * + * Copyright (c) 2014 Andy Lutomirski + * Authors: Andy Lutomirski + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef ASM_X86_ARCHSLOWRANDOM_H +#define ASM_X86_ARCHSLOWRANDOM_H + +#ifndef CONFIG_ARCH_SLOW_RNG +# error archslowrng.h should not be included if !CONFIG_ARCH_SLOW_RNG +#endif + +/* + * Performance is irrelevant here, so there's no point in using the + * paravirt ops mechanism. Instead just use a function pointer. + */ +extern int (*arch_get_slow_rng_u64)(u64 *v); + +#endif /* ASM_X86_ARCHSLOWRANDOM_H */ diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index 3dd8e2c..8d64d28 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -416,6 +416,25 @@ void kvm_disable_steal_time(void) wrmsr(MSR_KVM_STEAL_TIME, 0, 0); } +static int nop_get_slow_rng_u64(u64 *v) +{ + return 0; +} + +static int kvm_get_slow_rng_u64(u64 *v) +{ + /* + * Allow migration from a hypervisor with the GET_RNG_SEED + * feature to a hypervisor without it. + */ + if (rdmsrl_safe(MSR_KVM_GET_RNG_SEED, v) == 0) + return 1; + else + return 0; +} + +int (*arch_get_slow_rng_u64)(u64 *v) = nop_get_slow_rng_u64; + #ifdef CONFIG_SMP static void __init kvm_smp_prepare_boot_cpu(void) { @@ -493,6 +512,9 @@ void __init kvm_guest_init(void) if (kvmclock_vsyscall) kvm_setup_vsyscall_timeinfo(); + if (kvm_para_has_feature(KVM_FEATURE_GET_RNG_SEED)) + arch_get_slow_rng_u64 = kvm_get_slow_rng_u64; + #ifdef CONFIG_SMP smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu; register_cpu_notifier(&kvm_cpu_notifier); diff --git a/include/linux/random.h b/include/linux/random.h index 57fbbff..ceafbcf 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -106,6 +106,15 @@ static inline int arch_has_random_seed(void) } #endif +#ifdef CONFIG_ARCH_SLOW_RNG +# include +#else +static inline int arch_get_slow_rng_u64(u64 *v) +{ + return 0; +} +#endif + /* Pseudo random number generator from numerical recipes. */ static inline u32 next_pseudo_random32(u32 seed) { -- 1.9.3