Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/aarch64/aarch64 Add support for the ARMv8.5-RNG CPU...
details: https://anonhg.NetBSD.org/src/rev/2252187e73e7
branches: trunk
changeset: 932562:2252187e73e7
user: riastradh <riastradh%NetBSD.org@localhost>
date: Mon May 11 14:44:16 2020 +0000
description:
Add support for the ARMv8.5-RNG CPU random number generator.
We use the RNDRRS system register. I made the following two
wild-arse guesses about the architecture of real implementations,
which might not exist yet:
1. There's only one physical source per CPU package, so not worth
attaching one per core.
2. Like other CPU RNGs -- RDSEED, VIA C3 -- this probably gives about
half a bit of entropy per bit of data (although perhaps we should
say zero and revisit this once it arrives on real silicon).
Tested in qemu as well as I can, using `-cpu max' (which doesn't get
to userland for unrelated reasons).
This uses the numeric notation `mrs %0, s3_3_c2_c4_1' for the rndrrs
system register instead of the more legible `mrs %0, rndrrs' as
suggested in the ARMv8.5 ARM. Why?
- clang doesn't like `mrs %0, rndrrs' for reasons unclear to me.
- gas only likes it with `.arch armv8.5-a+rng', but there's no clear
way to keep that scoped; the `.set push/pop' stack that would be an
obvious choice for this works only on mips.
- gcc supports __attribute__((target("arch=..."))) on functions, but
the version we use doesn't yet know about armv8.5-a+rng.
Later on, we should replace this by a target attribute and the more
obvious `mrs %0, rndrrs' notation.
ok nick
diffstat:
sys/arch/aarch64/aarch64/cpu.c | 73 ++++++++++++++++++++++++++++++++++++++++-
1 files changed, 71 insertions(+), 2 deletions(-)
diffs (115 lines):
diff -r 65b8a8d0d18e -r 2252187e73e7 sys/arch/aarch64/aarch64/cpu.c
--- a/sys/arch/aarch64/aarch64/cpu.c Mon May 11 12:42:58 2020 +0000
+++ b/sys/arch/aarch64/aarch64/cpu.c Mon May 11 14:44:16 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.c,v 1.44 2020/05/10 21:41:19 riastradh Exp $ */
+/* $NetBSD: cpu.c,v 1.45 2020/05/11 14:44:16 riastradh Exp $ */
/*
* Copyright (c) 2017 Ryo Shimizu <ryo%nerv.org@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: cpu.c,v 1.44 2020/05/10 21:41:19 riastradh Exp $");
+__KERNEL_RCSID(1, "$NetBSD: cpu.c,v 1.45 2020/05/11 14:44:16 riastradh Exp $");
#include "locators.h"
#include "opt_arm_debug.h"
@@ -40,6 +40,7 @@
#include <sys/device.h>
#include <sys/kmem.h>
#include <sys/reboot.h>
+#include <sys/rndsource.h>
#include <sys/sysctl.h>
#include <sys/systm.h>
@@ -68,6 +69,7 @@
static void cpu_init_counter(struct cpu_info *);
static void cpu_setup_id(struct cpu_info *);
static void cpu_setup_sysctl(device_t, struct cpu_info *);
+static void cpu_setup_rng(device_t, struct cpu_info *);
#ifdef MULTIPROCESSOR
#define NCPUINFO MAXCPUS
@@ -153,6 +155,7 @@
cpu_init_counter(ci);
cpu_setup_sysctl(dv, ci);
+ cpu_setup_rng(dv, ci);
}
struct cpuidtab {
@@ -502,6 +505,72 @@
CTL_CREATE, CTL_EOL);
}
+static struct krndsource rndrrs_source;
+
+static void
+rndrrs_get(size_t nbytes, void *cookie)
+{
+ /* Entropy bits per data byte, wild-arse guess. */
+ const unsigned bpb = 4;
+ size_t nbits = nbytes*NBBY;
+ uint64_t x;
+ int error;
+
+ while (nbits) {
+ /*
+ * x := random 64-bit sample
+ * error := Z bit, set to 1 if sample is bad
+ *
+ * XXX This should be done by marking the function
+ * __attribute__((target("arch=armv8.5-a+rng"))) and
+ * using `mrs %0, rndrrs', but:
+ *
+ * (a) the version of gcc we use doesn't support that,
+ * and
+ * (b) clang doesn't seem to like `rndrrs' itself.
+ *
+ * So we use the numeric encoding for now.
+ */
+ __asm __volatile(""
+ "mrs %0, s3_3_c2_c4_1\n"
+ "cset %w1, eq"
+ : "=r"(x), "=r"(error));
+ if (error)
+ break;
+ rnd_add_data_sync(&rndrrs_source, &x, sizeof(x),
+ bpb*sizeof(x));
+ nbits -= MIN(nbits, bpb*sizeof(x));
+ }
+
+ explicit_memset(&x, 0, sizeof x);
+}
+
+/*
+ * setup the RNDRRS entropy source
+ */
+static void
+cpu_setup_rng(device_t dv, struct cpu_info *ci)
+{
+ struct aarch64_sysctl_cpu_id *id = &ci->ci_id;
+
+ /* Probably shared between cores. */
+ if (!CPU_IS_PRIMARY(ci))
+ return;
+
+ /* Verify that it is supported. */
+ switch (__SHIFTOUT(id->ac_aa64isar0, ID_AA64ISAR0_EL1_RNDR)) {
+ case ID_AA64ISAR0_EL1_RNDR_RNDRRS:
+ break;
+ default:
+ return;
+ }
+
+ /* Attach it. */
+ rndsource_setcb(&rndrrs_source, rndrrs_get, NULL);
+ rnd_attach_source(&rndrrs_source, "rndrrs", RND_TYPE_RNG,
+ RND_FLAG_DEFAULT|RND_FLAG_HASCB);
+}
+
#ifdef MULTIPROCESSOR
void
cpu_hatch(struct cpu_info *ci)
Home |
Main Index |
Thread Index |
Old Index