diff --git a/sys/arm64/conf/std.dev b/sys/arm64/conf/std.dev --- a/sys/arm64/conf/std.dev +++ b/sys/arm64/conf/std.dev @@ -53,6 +53,7 @@ # 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 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -379,6 +379,8 @@ 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 --- /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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +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"); + } 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, ®) && + 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 --- a/sys/dev/random/random_harvestq.c +++ b/sys/dev/random/random_harvestq.c @@ -385,6 +385,7 @@ [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 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -41,6 +41,7 @@ ${_arcmsr} \ ${_allwinner} \ ${_armv8crypto} \ + ${_armv8_rng} \ ${_asmc} \ ata \ ath \ @@ -674,6 +675,7 @@ .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 --- /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 diff --git a/sys/sys/random.h b/sys/sys/random.h --- a/sys/sys/random.h +++ b/sys/sys/random.h @@ -102,6 +102,7 @@ RANDOM_PURE_TPM, RANDOM_PURE_VMGENID, RANDOM_PURE_QUALCOMM, + RANDOM_PURE_ARMV8, ENTROPYSOURCE }; _Static_assert(ENTROPYSOURCE <= 32,