Michal Suchanek 42e06b
From 7ef3d06f1bc4a5e62273726f3dc2bd258ae1c71f Mon Sep 17 00:00:00 2001
Michal Suchanek 42e06b
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
Michal Suchanek 42e06b
Date: Thu, 28 Jul 2022 00:32:18 +1000
Michal Suchanek 42e06b
Subject: [PATCH] powerpc/powernv/kvm: Use darn for H_RANDOM on Power9
Michal Suchanek 42e06b
Michal Suchanek 42e06b
References: bsc#1065729
Michal Suchanek 42e06b
Patch-mainline: v6.0-rc1
Michal Suchanek 42e06b
Git-commit: 7ef3d06f1bc4a5e62273726f3dc2bd258ae1c71f
Michal Suchanek 42e06b
Michal Suchanek 42e06b
The existing logic in KVM to support guests calling H_RANDOM only works
Michal Suchanek 42e06b
on Power8, because it looks for an RNG in the device tree, but on Power9
Michal Suchanek 42e06b
we just use darn.
Michal Suchanek 42e06b
Michal Suchanek 42e06b
In addition the existing code needs to work in real mode, so we have the
Michal Suchanek 42e06b
special cased powernv_get_random_real_mode() to deal with that.
Michal Suchanek 42e06b
Michal Suchanek 42e06b
Instead just have KVM call ppc_md.get_random_seed(), and do the real
Michal Suchanek 42e06b
mode check inside of there, that way we use whatever RNG is available,
Michal Suchanek 42e06b
including darn on Power9.
Michal Suchanek 42e06b
Michal Suchanek 42e06b
Fixes: e928e9cb3601 ("KVM: PPC: Book3S HV: Add fast real-mode H_RANDOM implementation.")
Michal Suchanek 42e06b
Cc: stable@vger.kernel.org # v4.1+
Michal Suchanek 42e06b
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Michal Suchanek 42e06b
Tested-by: Sachin Sant <sachinp@linux.ibm.com>
Michal Suchanek 42e06b
[mpe: Rebase on previous commit, update change log appropriately]
Michal Suchanek 42e06b
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Michal Suchanek 42e06b
Link: https://lore.kernel.org/r/20220727143219.2684192-2-mpe@ellerman.id.au
Michal Suchanek 42e06b
Acked-by: Michal Suchanek <msuchanek@suse.de>
Michal Suchanek 42e06b
---
Michal Suchanek 42e06b
 arch/powerpc/include/asm/archrandom.h |  5 ----
Michal Suchanek 42e06b
 arch/powerpc/kvm/book3s_hv_builtin.c  |  7 +++---
Michal Suchanek 42e06b
 arch/powerpc/platforms/powernv/rng.c  | 36 ++++++---------------------
Michal Suchanek 42e06b
 3 files changed, 12 insertions(+), 36 deletions(-)
Michal Suchanek 42e06b
Michal Suchanek 42e06b
diff --git a/arch/powerpc/include/asm/archrandom.h b/arch/powerpc/include/asm/archrandom.h
Michal Suchanek 42e06b
index 9a53e29680f4..258174304904 100644
Michal Suchanek 42e06b
--- a/arch/powerpc/include/asm/archrandom.h
Michal Suchanek 42e06b
+++ b/arch/powerpc/include/asm/archrandom.h
Michal Suchanek 42e06b
@@ -38,12 +38,7 @@ static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
Michal Suchanek 42e06b
 #endif /* CONFIG_ARCH_RANDOM */
Michal Suchanek 42e06b
 
Michal Suchanek 42e06b
 #ifdef CONFIG_PPC_POWERNV
Michal Suchanek 42e06b
-int powernv_hwrng_present(void);
Michal Suchanek 42e06b
 int powernv_get_random_long(unsigned long *v);
Michal Suchanek 42e06b
-int powernv_get_random_real_mode(unsigned long *v);
Michal Suchanek 42e06b
-#else
Michal Suchanek 42e06b
-static inline int powernv_hwrng_present(void) { return 0; }
Michal Suchanek 42e06b
-static inline int powernv_get_random_real_mode(unsigned long *v) { return 0; }
Michal Suchanek 42e06b
 #endif
Michal Suchanek 42e06b
 
Michal Suchanek 42e06b
 #endif /* _ASM_POWERPC_ARCHRANDOM_H */
Michal Suchanek 42e06b
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
Michal Suchanek 42e06b
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
Michal Suchanek 42e06b
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
Michal Suchanek 42e06b
@@ -19,7 +19,7 @@
Michal Suchanek 42e06b
 #include <asm/cputable.h>
Michal Suchanek 42e06b
 #include <asm/kvm_ppc.h>
Michal Suchanek 42e06b
 #include <asm/kvm_book3s.h>
Michal Suchanek 42e06b
-#include <asm/archrandom.h>
Michal Suchanek 42e06b
+#include <asm/machdep.h>
Michal Suchanek 42e06b
 #include <asm/xics.h>
Michal Suchanek 42e06b
 #include <asm/xive.h>
Michal Suchanek 42e06b
 #include <asm/dbell.h>
Michal Suchanek 42e06b
@@ -176,20 +176,14 @@ EXPORT_SYMBOL_GPL(kvmppc_hcall_impl_hv_realmode);
Michal Suchanek 42e06b
 
Michal Suchanek 42e06b
 int kvmppc_hwrng_present(void)
Michal Suchanek 42e06b
 {
Michal Suchanek 42e06b
-	return powernv_hwrng_present();
Michal Suchanek 42e06b
+	return ppc_md.get_random_seed != NULL;
Michal Suchanek 42e06b
 }
Michal Suchanek 42e06b
 EXPORT_SYMBOL_GPL(kvmppc_hwrng_present);
Michal Suchanek 42e06b
 
Michal Suchanek 42e06b
 long kvmppc_h_random(struct kvm_vcpu *vcpu)
Michal Suchanek 42e06b
 {
Michal Suchanek 42e06b
-	int r;
Michal Suchanek 42e06b
-
Michal Suchanek 42e06b
-	/* Only need to do the expensive mfmsr() on radix */
Michal Suchanek 42e06b
-	if (kvm_is_radix(vcpu->kvm) && (mfmsr() & MSR_IR))
Michal Suchanek 42e06b
-		r = powernv_get_random_long(&vcpu->arch.regs.gpr[4]);
Michal Suchanek 42e06b
-	else
Michal Suchanek 42e06b
-		r = powernv_get_random_real_mode(&vcpu->arch.regs.gpr[4]);
Michal Suchanek 42e06b
-	if (r)
Michal Suchanek 42e06b
+	if (ppc_md.get_random_seed &&
Michal Suchanek 42e06b
+	    ppc_md.get_random_seed(&vcpu->arch.regs.gpr[4]))
Michal Suchanek 42e06b
 		return H_SUCCESS;
Michal Suchanek 42e06b
 
Michal Suchanek 42e06b
 	return H_HARDWARE;
Michal Suchanek 42e06b
diff --git a/arch/powerpc/platforms/powernv/rng.c b/arch/powerpc/platforms/powernv/rng.c
Michal Suchanek 42e06b
index 2287c9cd0cd5..d19305292e1e 100644
Michal Suchanek 42e06b
--- a/arch/powerpc/platforms/powernv/rng.c
Michal Suchanek 42e06b
+++ b/arch/powerpc/platforms/powernv/rng.c
Michal Suchanek 42e06b
@@ -29,15 +29,6 @@ struct powernv_rng {
Michal Suchanek 42e06b
 
Michal Suchanek 42e06b
 static DEFINE_PER_CPU(struct powernv_rng *, powernv_rng);
Michal Suchanek 42e06b
 
Michal Suchanek 42e06b
-int powernv_hwrng_present(void)
Michal Suchanek 42e06b
-{
Michal Suchanek 42e06b
-	struct powernv_rng *rng;
Michal Suchanek 42e06b
-
Michal Suchanek 42e06b
-	rng = get_cpu_var(powernv_rng);
Michal Suchanek 42e06b
-	put_cpu_var(rng);
Michal Suchanek 42e06b
-	return rng != NULL;
Michal Suchanek 42e06b
-}
Michal Suchanek 42e06b
-
Michal Suchanek 42e06b
 static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val)
Michal Suchanek 42e06b
 {
Michal Suchanek 42e06b
 	unsigned long parity;
Michal Suchanek 42e06b
@@ -58,19 +49,6 @@ static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val)
Michal Suchanek 42e06b
 	return val;
Michal Suchanek 42e06b
 }
Michal Suchanek 42e06b
 
Michal Suchanek 42e06b
-int powernv_get_random_real_mode(unsigned long *v)
Michal Suchanek 42e06b
-{
Michal Suchanek 42e06b
-	struct powernv_rng *rng;
Michal Suchanek 42e06b
-
Michal Suchanek 42e06b
-	rng = raw_cpu_read(powernv_rng);
Michal Suchanek 42e06b
-	if (!rng)
Michal Suchanek 42e06b
-		return 0;
Michal Suchanek 42e06b
-
Michal Suchanek 42e06b
-	*v = rng_whiten(rng, __raw_rm_readq(rng->regs_real));
Michal Suchanek 42e06b
-
Michal Suchanek 42e06b
-	return 1;
Michal Suchanek 42e06b
-}
Michal Suchanek 42e06b
-
Michal Suchanek 42e06b
 static int powernv_get_random_darn(unsigned long *v)
Michal Suchanek 42e06b
 {
Michal Suchanek 42e06b
 	unsigned long val;
Michal Suchanek 42e06b
@@ -107,12 +85,14 @@ int powernv_get_random_long(unsigned long *v)
Michal Suchanek 42e06b
 {
Michal Suchanek 42e06b
 	struct powernv_rng *rng;
Michal Suchanek 42e06b
 
Michal Suchanek 42e06b
-	rng = get_cpu_var(powernv_rng);
Michal Suchanek 42e06b
-
Michal Suchanek 42e06b
-	*v = rng_whiten(rng, in_be64(rng->regs));
Michal Suchanek 42e06b
-
Michal Suchanek 42e06b
-	put_cpu_var(rng);
Michal Suchanek 42e06b
-
Michal Suchanek 42e06b
+	if (mfmsr() & MSR_DR) {
Michal Suchanek 42e06b
+		rng = get_cpu_var(powernv_rng);
Michal Suchanek 42e06b
+		*v = rng_whiten(rng, in_be64(rng->regs));
Michal Suchanek 42e06b
+		put_cpu_var(rng);
Michal Suchanek 42e06b
+	} else {
Michal Suchanek 42e06b
+		rng = raw_cpu_read(powernv_rng);
Michal Suchanek 42e06b
+		*v = rng_whiten(rng, __raw_rm_readq(rng->regs_real));
Michal Suchanek 42e06b
+	}
Michal Suchanek 42e06b
 	return 1;
Michal Suchanek 42e06b
 }
Michal Suchanek 42e06b
 EXPORT_SYMBOL_GPL(powernv_get_random_long);
Michal Suchanek 42e06b
-- 
Michal Suchanek 42e06b
2.35.3
Michal Suchanek 42e06b