powerpc/microwatt: Add support for hardware random number generator
authorPaul Mackerras <paulus@ozlabs.org>
Fri, 18 Jun 2021 03:47:08 +0000 (13:47 +1000)
committerMichael Ellerman <mpe@ellerman.id.au>
Mon, 21 Jun 2021 11:16:32 +0000 (21:16 +1000)
Microwatt's hardware RNG is accessed using the DARN instruction.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
Reviewed-by: Segher Boessenkool <segher@kernel.crashing.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/YMwXPHlV/ZleiQUY@thinks.paulus.ozlabs.org
arch/powerpc/platforms/microwatt/Kconfig
arch/powerpc/platforms/microwatt/Makefile
arch/powerpc/platforms/microwatt/rng.c [new file with mode: 0644]

index 50ed0cedb5f1ad9770a1fc837dc115f02c181800..8f6a81978461fc492ed752e93aeb36c61cdad58f 100644 (file)
@@ -7,6 +7,7 @@ config PPC_MICROWATT
        select PPC_ICP_NATIVE
        select PPC_NATIVE
        select PPC_UDBG_16550
+       select ARCH_RANDOM
        help
           This option enables support for FPGA-based Microwatt implementations.
 
index e6885b3b2ee73a774d0aac86441b6cebca7712ee..116d6d3ad3f010b53dba0cc31ef55a2d32c62e73 100644 (file)
@@ -1 +1 @@
-obj-y  += setup.o
+obj-y  += setup.o rng.o
diff --git a/arch/powerpc/platforms/microwatt/rng.c b/arch/powerpc/platforms/microwatt/rng.c
new file mode 100644 (file)
index 0000000..3d8ee6e
--- /dev/null
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Derived from arch/powerpc/platforms/powernv/rng.c, which is:
+ * Copyright 2013, Michael Ellerman, IBM Corporation.
+ */
+
+#define pr_fmt(fmt)    "microwatt-rng: " fmt
+
+#include <linux/kernel.h>
+#include <linux/smp.h>
+#include <asm/archrandom.h>
+#include <asm/cputable.h>
+#include <asm/machdep.h>
+
+#define DARN_ERR 0xFFFFFFFFFFFFFFFFul
+
+int microwatt_get_random_darn(unsigned long *v)
+{
+       unsigned long val;
+
+       /* Using DARN with L=1 - 64-bit conditioned random number */
+       asm volatile(PPC_DARN(%0, 1) : "=r"(val));
+
+       if (val == DARN_ERR)
+               return 0;
+
+       *v = val;
+
+       return 1;
+}
+
+static __init int rng_init(void)
+{
+       unsigned long val;
+       int i;
+
+       for (i = 0; i < 10; i++) {
+               if (microwatt_get_random_darn(&val)) {
+                       ppc_md.get_random_seed = microwatt_get_random_darn;
+                       return 0;
+               }
+       }
+
+       pr_warn("Unable to use DARN for get_random_seed()\n");
+
+       return -EIO;
+}
+machine_subsys_initcall(, rng_init);