]> git.baikalelectronics.ru Git - kernel.git/commitdiff
powerpc/powernv/kvm: Use darn for H_RANDOM on Power9
authorJason A. Donenfeld <Jason@zx2c4.com>
Wed, 27 Jul 2022 14:32:18 +0000 (00:32 +1000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Aug 2022 12:24:25 +0000 (14:24 +0200)
[ Upstream commit 9b487f25e1133f6718ae207082dbbfa745e4e879 ]

The existing logic in KVM to support guests calling H_RANDOM only works
on Power8, because it looks for an RNG in the device tree, but on Power9
we just use darn.

In addition the existing code needs to work in real mode, so we have the
special cased powernv_get_random_real_mode() to deal with that.

Instead just have KVM call ppc_md.get_random_seed(), and do the real
mode check inside of there, that way we use whatever RNG is available,
including darn on Power9.

Fixes: 1746d4c9c4c7 ("KVM: PPC: Book3S HV: Add fast real-mode H_RANDOM implementation.")
Cc: stable@vger.kernel.org # v4.1+
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Tested-by: Sachin Sant <sachinp@linux.ibm.com>
[mpe: Rebase on previous commit, update change log appropriately]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20220727143219.2684192-2-mpe@ellerman.id.au
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/powerpc/include/asm/archrandom.h
arch/powerpc/kvm/book3s_hv_builtin.c
arch/powerpc/platforms/powernv/rng.c

index 9a53e29680f4162d8513fe2a9a00f3b3abbba4c9..258174304904b525abe4ebb0304f54a8f9913ae3 100644 (file)
@@ -38,12 +38,7 @@ static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
 #endif /* CONFIG_ARCH_RANDOM */
 
 #ifdef CONFIG_PPC_POWERNV
-int powernv_hwrng_present(void);
 int powernv_get_random_long(unsigned long *v);
-int powernv_get_random_real_mode(unsigned long *v);
-#else
-static inline int powernv_hwrng_present(void) { return 0; }
-static inline int powernv_get_random_real_mode(unsigned long *v) { return 0; }
 #endif
 
 #endif /* _ASM_POWERPC_ARCHRANDOM_H */
index 70b7a8f97153844f5d1eb4f1f29f744b93fb0084..b148629b7f03378c26ce315b88254c45c46d7b43 100644 (file)
@@ -20,7 +20,7 @@
 #include <asm/interrupt.h>
 #include <asm/kvm_ppc.h>
 #include <asm/kvm_book3s.h>
-#include <asm/archrandom.h>
+#include <asm/machdep.h>
 #include <asm/xics.h>
 #include <asm/xive.h>
 #include <asm/dbell.h>
@@ -177,13 +177,14 @@ EXPORT_SYMBOL_GPL(kvmppc_hcall_impl_hv_realmode);
 
 int kvmppc_hwrng_present(void)
 {
-       return powernv_hwrng_present();
+       return ppc_md.get_random_seed != NULL;
 }
 EXPORT_SYMBOL_GPL(kvmppc_hwrng_present);
 
 long kvmppc_rm_h_random(struct kvm_vcpu *vcpu)
 {
-       if (powernv_get_random_real_mode(&vcpu->arch.regs.gpr[4]))
+       if (ppc_md.get_random_seed &&
+           ppc_md.get_random_seed(&vcpu->arch.regs.gpr[4]))
                return H_SUCCESS;
 
        return H_HARDWARE;
index a99033c3dce7134a45a1094897779082076c11d6..5f81ff9b5265f79619d4875258aa44aed255978a 100644 (file)
@@ -29,15 +29,6 @@ struct powernv_rng {
 
 static DEFINE_PER_CPU(struct powernv_rng *, powernv_rng);
 
-int powernv_hwrng_present(void)
-{
-       struct powernv_rng *rng;
-
-       rng = get_cpu_var(powernv_rng);
-       put_cpu_var(rng);
-       return rng != NULL;
-}
-
 static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val)
 {
        unsigned long parity;
@@ -58,19 +49,6 @@ static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val)
        return val;
 }
 
-int powernv_get_random_real_mode(unsigned long *v)
-{
-       struct powernv_rng *rng;
-
-       rng = raw_cpu_read(powernv_rng);
-       if (!rng)
-               return 0;
-
-       *v = rng_whiten(rng, __raw_rm_readq(rng->regs_real));
-
-       return 1;
-}
-
 static int powernv_get_random_darn(unsigned long *v)
 {
        unsigned long val;
@@ -107,12 +85,14 @@ int powernv_get_random_long(unsigned long *v)
 {
        struct powernv_rng *rng;
 
-       rng = get_cpu_var(powernv_rng);
-
-       *v = rng_whiten(rng, in_be64(rng->regs));
-
-       put_cpu_var(rng);
-
+       if (mfmsr() & MSR_DR) {
+               rng = get_cpu_var(powernv_rng);
+               *v = rng_whiten(rng, in_be64(rng->regs));
+               put_cpu_var(rng);
+       } else {
+               rng = raw_cpu_read(powernv_rng);
+               *v = rng_whiten(rng, __raw_rm_readq(rng->regs_real));
+       }
        return 1;
 }
 EXPORT_SYMBOL_GPL(powernv_get_random_long);