Re: git: 9eecef052155 - main - Add an Armv8 rndr random number provider

From: Jessica Clarke <jrtc27_at_freebsd.org>
Date: Wed, 15 Nov 2023 18:27:57 UTC
On 15 Nov 2023, at 18:12, Andrew Turner <andrew@FreeBSD.org> wrote:
> 
> The branch main has been updated by andrew:
> 
> URL: https://cgit.FreeBSD.org/src/commit/?id=9eecef052155646fbc5f8f533b952b372572d06a
> 
> commit 9eecef052155646fbc5f8f533b952b372572d06a
> Author:     Andrew Turner <andrew@FreeBSD.org>
> AuthorDate: 2023-11-15 17:42:02 +0000
> Commit:     Andrew Turner <andrew@FreeBSD.org>
> CommitDate: 2023-11-15 18:05:08 +0000
> 
>    Add an Armv8 rndr random number provider
> 
>    Armv8.5 adds an optional random number generator. This is implemented
>    as two special registers one to read a random number, the other to
>    re-seed the entropy pool before reading a random number. Both registers
>    will set the condition flags to tell the caller they can't produce a
>    random number in a reasonable amount of time.
> 
>    Without a signal to reseed the entropy pool use the latter register
>    to provide random numbers to the kernel pool. If at a later time we
>    had a way to tell the provider if it needs to reseed or not we could
>    use the former.
> 
>    On an Amazon AWS Graviton3 VM this never failed, however this may not
>    be the case on low end CPUs so retry reading the random number 10 times
>    before returning an error.
> 
>    Reviewed by:    imp, delphij (csprng)
>    Sponsored by:   The FreeBSD Foundation
>    Sponsored by:   Arm Ltd
>    Differential Revision:  https://reviews.freebsd.org/D35411
> ---
> sys/arm64/conf/std.dev           |   1 +
> sys/conf/files.arm64             |   2 +
> sys/dev/random/armv8rng.c        | 135 +++++++++++++++++++++++++++++++++++++++
> sys/dev/random/random_harvestq.c |   1 +
> sys/modules/Makefile             |   2 +
> sys/modules/armv8_rng/Makefile   |  11 ++++
> sys/sys/random.h                 |   1 +
> 7 files changed, 153 insertions(+)
> 
> diff --git a/sys/arm64/conf/std.dev b/sys/arm64/conf/std.dev
> index 74d2407e0aec..0ebf2e775b11 100644
> --- a/sys/arm64/conf/std.dev
> +++ b/sys/arm64/conf/std.dev
> @@ -53,6 +53,7 @@ device vt_simplefb
> 
> # Pseudo devices.
> device crypto # core crypto support
> +device armv8_rng # Armv8.5 rndr RNG
> device loop # Network loopback
> device ether # Ethernet support
> device vlan # 802.1Q VLAN support
> diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
> index 38b9e40463eb..9ccead6a98e1 100644
> --- a/sys/conf/files.arm64
> +++ b/sys/conf/files.arm64
> @@ -379,6 +379,8 @@ dev/psci/psci.c standard
> dev/psci/smccc_arm64.S standard
> dev/psci/smccc.c standard
> 
> +dev/random/armv8rng.c optional armv8_rng !random_loadable
> +
> dev/safexcel/safexcel.c optional safexcel fdt
> 
> dev/sdhci/sdhci_xenon.c optional sdhci_xenon sdhci
> diff --git a/sys/dev/random/armv8rng.c b/sys/dev/random/armv8rng.c
> new file mode 100644
> index 000000000000..3cca42a5bbf3
> --- /dev/null
> +++ b/sys/dev/random/armv8rng.c
> @@ -0,0 +1,135 @@
> +/*-
> + * Copyright (c) 2022 The FreeBSD Foundation
> + *
> + * This software was developed by Andrew Turner under sponsorship from
> + * the FreeBSD Foundation.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + *    notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + *    notice, this list of conditions and the following disclaimer in the
> + *    documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +
> +#include <sys/cdefs.h>
> +
> +#include <sys/param.h>
> +#include <sys/systm.h>
> +#include <sys/conf.h>
> +#include <sys/kernel.h>
> +#include <sys/lock.h>
> +#include <sys/malloc.h>
> +#include <sys/module.h>
> +#include <sys/random.h>
> +
> +#include <machine/armreg.h>
> +
> +#include <dev/random/randomdev.h>
> +
> +static u_int random_rndr_read(void *, u_int);
> +
> +static bool has_rndr;
> +static struct random_source random_armv8_rndr = {
> + .rs_ident = "Armv8 rndr RNG",
> + .rs_source = RANDOM_PURE_ARMV8,
> + .rs_read = random_rndr_read,
> +};
> +
> +static inline int
> +random_rndr_read_one(u_long *buf)
> +{
> + u_long val;
> + int loop, ret;
> +
> + loop = 10;
> + do {
> + __asm __volatile(
> +    ".arch_extension rng   \n"
> +    "mrs %0, rndrrs \n" /* Read the random number */
> +    "cset %w1, ne    \n" /* 1 on success, 0 on failure */
> +    ".arch_extension norng \n"
> +    : "=&r" (val), "=&r"(ret) :: "cc");

Early clobber doesn’t make sense with no inputs.

Jess

> + } while (ret != 0 && --loop > 0);
> +
> + if (ret != 0)
> + *buf = val;
> +
> + return (ret);
> +}
> +
> +static u_int
> +random_rndr_read(void *buf, u_int c)
> +{
> + u_long *b;
> + u_int count;
> +
> + b = buf;
> + for (count = 0; count < c; count += sizeof(*b)) {
> + if (!random_rndr_read_one(b))
> + break;
> +
> + b++;
> + }
> +
> + return (count);
> +}
> +
> +static int
> +rndr_modevent(module_t mod, int type, void *unused)
> +{
> + uint64_t reg;
> + int error = 0;
> +
> + switch (type) {
> + case MOD_LOAD:
> + has_rndr = false;
> + if (get_kernel_reg(ID_AA64ISAR0_EL1, &reg) &&
> +    ID_AA64ISAR0_RNDR_VAL(reg) != ID_AA64ISAR0_RNDR_NONE) {
> + has_rndr = true;
> + random_source_register(&random_armv8_rndr);
> + printf("random: fast provider: \"%s\"\n",
> +    random_armv8_rndr.rs_ident);
> + }
> + break;
> +
> + case MOD_UNLOAD:
> + if (has_rndr)
> + random_source_deregister(&random_armv8_rndr);
> + break;
> +
> + case MOD_SHUTDOWN:
> + break;
> +
> + default:
> + error = EOPNOTSUPP;
> + break;
> +
> + }
> +
> + return (error);
> +}
> +
> +static moduledata_t rndr_mod = {
> + "rndr",
> + rndr_modevent,
> + 0
> +};
> +
> +DECLARE_MODULE(rndr, rndr_mod, SI_SUB_RANDOM, SI_ORDER_FOURTH);
> +MODULE_VERSION(rndr, 1);
> +MODULE_DEPEND(rndr, random_harvestq, 1, 1, 1);
> diff --git a/sys/dev/random/random_harvestq.c b/sys/dev/random/random_harvestq.c
> index 09b81950281b..dce0878513db 100644
> --- a/sys/dev/random/random_harvestq.c
> +++ b/sys/dev/random/random_harvestq.c
> @@ -385,6 +385,7 @@ static const char *random_source_descr[ENTROPYSOURCE] = {
> [RANDOM_PURE_TPM] = "PURE_TPM",
> [RANDOM_PURE_VMGENID] = "PURE_VMGENID",
> [RANDOM_PURE_QUALCOMM] = "PURE_QUALCOMM",
> + [RANDOM_PURE_ARMV8] = "PURE_ARMV8",
> /* "ENTROPYSOURCE" */
> };
> 
> diff --git a/sys/modules/Makefile b/sys/modules/Makefile
> index 3eff75312fd3..f9079498dc1f 100644
> --- a/sys/modules/Makefile
> +++ b/sys/modules/Makefile
> @@ -41,6 +41,7 @@ SUBDIR= \
> ${_arcmsr} \
> ${_allwinner} \
> ${_armv8crypto} \
> + ${_armv8_rng} \
> ${_asmc} \
> ata \
> ath \
> @@ -674,6 +675,7 @@ _cxgb= cxgb
> 
> .if ${MACHINE_CPUARCH} == "aarch64"
> _armv8crypto= armv8crypto
> +_armv8_rng= armv8_rng
> _dpaa2= dpaa2
> _sff= sff
> _em= em
> diff --git a/sys/modules/armv8_rng/Makefile b/sys/modules/armv8_rng/Makefile
> new file mode 100644
> index 000000000000..29d2907aed06
> --- /dev/null
> +++ b/sys/modules/armv8_rng/Makefile
> @@ -0,0 +1,11 @@
> +# $FreeBSD$
> +
> +.PATH: ${SRCTOP}/sys/dev/random
> +
> +KMOD= armv8_rng
> +SRCS= armv8rng.c
> +SRCS+= bus_if.h device_if.h
> +
> +CFLAGS+= -I${SRCTOP}/sys
> +
> +.include <bsd.kmod.mk>
> diff --git a/sys/sys/random.h b/sys/sys/random.h
> index 0e6ae02ac078..aa4457fc8c22 100644
> --- a/sys/sys/random.h
> +++ b/sys/sys/random.h
> @@ -102,6 +102,7 @@ enum random_entropy_source {
> RANDOM_PURE_TPM,
> RANDOM_PURE_VMGENID,
> RANDOM_PURE_QUALCOMM,
> + RANDOM_PURE_ARMV8,
> ENTROPYSOURCE
> };
> _Static_assert(ENTROPYSOURCE <= 32,