Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157147058
D45591.id140220.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
21 KB
Referenced Files
None
Subscribers
None
D45591.id140220.diff
View Options
diff --git a/sys/arm64/qoriq/caam/caam.c b/sys/arm64/qoriq/caam/caam.c
--- a/sys/arm64/qoriq/caam/caam.c
+++ b/sys/arm64/qoriq/caam/caam.c
@@ -32,6 +32,7 @@
#include "caam_debug.h"
#include "caam_internal.h"
#include "caam_test.h"
+#include "caam_trng.h"
#include "jr/caam_jobdesc.h"
#include "jr/caam_jr.h"
#include "jr/caam_jr_hw.h"
@@ -420,21 +421,30 @@
goto cleanup_rman;
}
+ /* After CAAM is ready, initialize the RNG drivers */
+ rv = caam_trng_attach(dev);
+ if (rv != 0) {
+ CAAM_LOG_ERROR("caam_trng_attach failed rv=(%d)\n", rv);
+ goto cleanup_jobrings;
+ }
+
#ifdef CAAM_DEBUG
/* Add the caam test device for development */
rv = caam_test_attach(dev);
if (rv != 0) {
CAAM_LOG_ERROR("caam_test_attach failed rv=(%d)\n", rv);
- goto cleanup_jobrings;
+ goto cleanup_trng;
}
#endif
return (0);
#ifdef CAAM_DEBUG
+cleanup_trng:
+ caam_trng_detach(dev);
+#endif
cleanup_jobrings:
- caam_jobrings_detach(dev);
-#endif
+ caam_jobrings_detach(dev);
cleanup_rman:
rman_fini(&sc->mem_rman);
cleanup_resource:
@@ -495,6 +505,8 @@
{
struct caam_softc *sc = device_get_softc(dev);
+ /* Remove TRNG drivers */
+ caam_trng_detach(dev);
#ifdef CAAM_DEBUG
/* Remove the caam test device */
caam_test_detach(dev);
diff --git a/sys/arm64/qoriq/caam/caam_trng.h b/sys/arm64/qoriq/caam/caam_trng.h
new file mode 100644
--- /dev/null
+++ b/sys/arm64/qoriq/caam/caam_trng.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2023 Alstom Group
+ * Copyright 2023 Sii Poland
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CAAM_RNG_H
+#define CAAM_RNG_H
+
+#include <sys/types.h>
+#include <sys/mutex.h>
+#include <sys/taskqueue.h>
+
+/*
+ * @brief Initialize CAAM TRNG module.
+ *
+ * Setup random harvester cache and refill.
+ * Register as a random source.
+ * Make TRNG side access /dev/random_caam character device.
+ *
+ * @param [in] dev caam device handle
+ *
+ * @retval :: 0 is returned on success
+ * @retval :: errno is returned on internal error
+ */
+int caam_trng_attach(device_t dev);
+
+/*
+ * @brief Uninitialize CAAM TRNG module and unregister our random source.
+ *
+ * @param [in] dev caam device handle
+ *
+ * @retval :: 0 is returned on success
+ * @retval :: errno is returned on internal error
+ */
+int caam_trng_detach(device_t dev);
+
+#endif /* CAAM_RNG_H */
\ No newline at end of file
diff --git a/sys/arm64/qoriq/caam/caam_trng.c b/sys/arm64/qoriq/caam/caam_trng.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/qoriq/caam/caam_trng.c
@@ -0,0 +1,702 @@
+/*
+ * Copyright 2021 NXP
+ * Copyright 2023 Alstom Group
+ * Copyright 2023 Sii Poland
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/conf.h> /* cdevsw struct */
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/proc.h>
+#include <sys/random.h>
+#include <sys/taskqueue.h>
+#include <sys/uio.h> /* uio struct */
+
+#include <machine/atomic.h>
+#include <machine/bus.h>
+
+#include <dev/random/randomdev.h>
+
+#include "caam.h"
+#include "caam_debug.h"
+#include "caam_internal.h"
+#include "caam_trng.h"
+#include "jr/caam_jobdesc.h"
+#include "jr/caam_jr_hw.h"
+
+MALLOC_DEFINE(M_TRNG, "CAAMTRNG", "CAAM TRNG malloc");
+
+#define NEXT_BUF_NUM(num) (((num) + 1) % (TRNG_CACHE_COUNT));
+#define TRNG_CACHE_SIZE 8192
+#define TRNG_CACHE_COUNT 2
+_Static_assert(TRNG_CACHE_COUNT >= 2,
+ "Need at least 2 buffers to function properly");
+
+struct trng_cache;
+
+/* Taskqueue responsible for maintaining proper levels of TRNG cache */
+struct trng_tq {
+ struct taskqueue *tq;
+ struct task task;
+ struct trng_cache *c;
+ device_t dev;
+};
+
+/*
+ * NOTE: Currently there is only one cache consumer so atomic r/w
+ * on data_left ensures that data is either non-empty and read or
+ * empty and pending refill.
+ * If there will be more concurrent consumers, we need to add locks.
+ */
+struct cache_buf {
+ uint8_t *data;
+ uint32_t data_left;
+};
+
+/* Precached random data for fast access by harvester callback */
+struct trng_cache {
+ int current_buf;
+ struct cache_buf buf[TRNG_CACHE_COUNT];
+
+ struct trng_tq *refill_tq;
+};
+static struct trng_cache g_cache;
+
+/* Workaround for API limitations of random(4). */
+static device_t g_caam_dev;
+
+int caam_trng_get_bytes(device_t dev, uint8_t *bytes, int byte_len);
+
+/*
+ * Wrapper for reading from random cache.
+ * Reads len bytes or up to bytes available in current buffer.
+ * If the current one has become exhausted gets a new buffer and
+ * enqueues a refill job.
+ */
+static uint32_t
+trng_cache_buf_read(struct trng_cache *c, uint8_t *buf, uint32_t len)
+{
+ struct cache_buf *cur;
+ uint32_t read_len;
+
+ cur = &c->buf[c->current_buf];
+
+ read_len = MIN(len, atomic_load_int(&cur->data_left));
+ memcpy(buf, &cur->data[TRNG_CACHE_SIZE - cur->data_left], read_len);
+
+ atomic_subtract_int(&cur->data_left, read_len);
+
+ if (atomic_load_int(&cur->data_left) == 0) {
+ c->current_buf = NEXT_BUF_NUM(c->current_buf);
+ taskqueue_enqueue(c->refill_tq->tq, &c->refill_tq->task);
+ }
+
+ return (read_len);
+}
+
+/* Run RNG job with cache buffer as data destination */
+static int
+trng_cache_refill(device_t dev, struct trng_cache *c, int buf_num)
+{
+ int ret = 0;
+
+ ret = caam_trng_get_bytes(dev, c->buf[buf_num].data, TRNG_CACHE_SIZE);
+ if (ret != 0) {
+ CAAM_LOG_ERROR("caam_trng_get_bytes failed\n");
+ } else {
+ atomic_store_int(&c->buf[buf_num].data_left, TRNG_CACHE_SIZE);
+ }
+
+ return (ret);
+}
+
+/* Traverse random cache buffers array and run refill jobs on empty ones */
+static void
+trng_cache_refill_worker(void *context, int pending)
+{
+ struct trng_tq *tq = context;
+ struct trng_cache *c = tq->c;
+ int buf_num = c->current_buf;
+
+ /* Refill empty buffers starting with the next one to be used */
+ for (int i = 0; i < TRNG_CACHE_COUNT - 1; ++i) {
+ buf_num = NEXT_BUF_NUM(buf_num);
+ if (atomic_load_int(&c->buf[buf_num].data_left) == 0) {
+ trng_cache_refill(tq->dev, c, buf_num);
+ }
+ }
+}
+
+/* Setup random cache refill task */
+static struct trng_tq *
+trng_cache_refill_setup(device_t dev, struct trng_cache *c)
+{
+ struct trng_tq *trng_tq;
+
+ trng_tq = malloc(sizeof(*trng_tq), M_TRNG, M_WAITOK | M_ZERO);
+ if (trng_tq == NULL) {
+ CAAM_LOG_ERROR("Could not allocate trng_tq\n");
+ return (NULL);
+ }
+ trng_tq->c = c;
+ trng_tq->dev = dev;
+
+ TASK_INIT(&trng_tq->task, 0, trng_cache_refill_worker, trng_tq);
+ trng_tq->tq = taskqueue_create_fast("caam_trng_tq", M_WAITOK | M_ZERO,
+ taskqueue_thread_enqueue, &trng_tq->tq);
+ taskqueue_start_threads(&trng_tq->tq, 1, PI_SOFT, "caam_trng_th");
+
+ return (trng_tq);
+}
+
+/* Stop and teardown random cache refill task */
+static void
+trng_cache_refill_teardown(struct trng_tq *tq)
+{
+ taskqueue_free(tq->tq);
+ free(tq, M_TRNG);
+}
+
+/*
+ * Allocate cache buffers and setup refill task.
+ * Deinit with trng_cache_deinit().
+ */
+static int
+trng_cache_init(device_t dev, struct trng_cache *c, size_t cache_size)
+{
+ int i;
+ int ret = 0;
+
+ c->current_buf = 0;
+
+ /*
+ * Contigmalloc will actively reclaim memory until it can make
+ * a contiguous buffer. This can take a varying amount of time so
+ * we'll allocate only once at attach while memory is not (that)
+ * fragmented.
+ */
+ for (i = 0; i < TRNG_CACHE_COUNT; ++i) {
+ c->buf[i].data_left = 0;
+ c->buf[i].data = contigmalloc(TRNG_CACHE_SIZE, M_TRNG, M_WAITOK,
+ 0, ~(vm_paddr_t)0, PAGE_SIZE, 0);
+ if (!c->buf[i].data) {
+ CAAM_LOG_ERROR(
+ "Could not allocate trng_tq->contig_buf\n");
+ ret = ENOMEM;
+ goto free_bufs;
+ }
+ }
+
+ c->refill_tq = trng_cache_refill_setup(dev, c);
+ if (!c->refill_tq) {
+ CAAM_LOG_ERROR("trng_cache_init failed\n");
+ ret = ENOMEM;
+ goto free_bufs;
+ }
+
+ return (0);
+
+free_bufs:
+ for (i -= 1; i >= 0; --i)
+ contigfree(c->buf[i].data, TRNG_CACHE_SIZE, M_TRNG);
+
+ return (ret);
+}
+
+/*
+ * Free cache buffers and teardown refill task.
+ */
+static void
+trng_cache_deinit(struct trng_cache *c)
+{
+ trng_cache_refill_teardown(c->refill_tq);
+
+ for (int i = 0; i < TRNG_CACHE_COUNT; ++i)
+ contigfree(c->buf[i].data, TRNG_CACHE_SIZE, M_TRNG);
+}
+
+/*----------------------- RNG initialization functions ----------------------*/
+/* Is the HW RNG instantiated?
+ * Return code:
+ * 0 - Not in the instantiated state
+ * 1 - In the instantiated state
+ * state_handle - 0 for SH0, 1 for SH1
+ */
+static int
+is_trng_instantiated(device_t dev, uint32_t *state_handle)
+{
+ int ret_code = 0;
+ uint32_t rdsta;
+
+ rdsta = caam_reg_read(dev, RNG_REG_RDSTA_OFFSET);
+
+ /*Check if either of the two state handles has been instantiated */
+ if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED) {
+ *state_handle = 0;
+ ret_code = 1;
+ } else if (rdsta & RNG_STATE1_HANDLE_INSTANTIATED) {
+ *state_handle = 1;
+ ret_code = 1;
+ }
+
+ return ret_code;
+}
+
+/* Construct descriptor to instantiate RNG */
+static int
+cnstr_trng_instantiate_jobdesc(uint32_t *desc)
+{
+ caam_jobdesc_init(desc);
+ caam_jobdesc_add_word(desc, 0xb0800000u);
+ /* Class1 Alg Operation,RNG Optype, Instantiate */
+ caam_jobdesc_add_word(desc, 0x82500004u);
+ /* Wait for done */
+ caam_jobdesc_add_word(desc, 0xa2000001u);
+ /*Load to clear written */
+ caam_jobdesc_add_word(desc, 0x10880004u);
+ /*Pri Mode Reg clear */
+ caam_jobdesc_add_word(desc, 0x00000001u);
+ /* Generate secure keys */
+ caam_jobdesc_add_word(desc, 0x82501000u);
+
+ return 0;
+}
+
+/* @brief Submit descriptor to instantiate the RNG
+ * @retval 0 on success
+ * @retval other on error
+ */
+static int
+run_trng_instantiate_job(device_t dev)
+{
+ int ret = 0;
+ struct job_descriptor desc;
+ struct job_descriptor *jobdesc = &desc;
+ jobdesc->arg = NULL;
+ jobdesc->callback = NULL;
+
+ /* create the hw_rng descriptor */
+ cnstr_trng_instantiate_jobdesc(jobdesc->desc);
+
+ /* Finally, generate the requested random data bytes */
+ ret = caam_run_descriptor_jr_blocking(dev, jobdesc, NULL);
+ if (ret != 0) {
+ CAAM_LOG_WARN("Error in running descriptor\n");
+ ret = EIO;
+ }
+
+ return ret;
+}
+
+/* @brief Kick the TRNG block of the RNG HW Engine
+ * @param [in] ent_delay Entropy delay to be used
+ * By default, the TRNG runs for 200 clocks per sample;
+ * 1200 clocks per sample generates better entropy.
+ */
+static void
+kick_trng(device_t dev, int ent_delay)
+{
+ uint32_t val;
+
+ /* put RNG4 into program mode */
+ val = caam_reg_read(dev, RNG_REG_RTMCTL_OFFSET);
+ val = val | RTMCTL_PRGM;
+ caam_reg_write(dev, RNG_REG_RTMCTL_OFFSET, val);
+
+ /* rtsdctl bits 0-15 contain "Entropy Delay, which defines the
+ * length (in system clocks) of each Entropy sample taken
+ */
+ val = caam_reg_read(dev, RNG_REG_RTSDCTL_OFFSET);
+ val = (val & ~RTSDCTL_ENT_DLY_MASK) |
+ (ent_delay << RTSDCTL_ENT_DLY_SHIFT);
+ caam_reg_write(dev, RNG_REG_RTSDCTL_OFFSET, val);
+ /* min. freq. count, equal to 1/4 of the entropy sample length */
+ caam_reg_write(dev, RNG_REG_RTFRQMIN_OFFSET, ent_delay >> 2);
+ /* disable maximum frequency count */
+ caam_reg_write(dev, RNG_REG_RTFRQMAX_OFFSET, RTFRQMAX_DISABLE);
+
+ /* select raw sampling in both entropy shifter
+ * and statistical checker
+ */
+ val = caam_reg_read(dev, RNG_REG_RTMCTL_OFFSET);
+ val = val | RTMCTL_SAMP_MODE_RAW_ES_SC;
+ caam_reg_write(dev, RNG_REG_RTMCTL_OFFSET, val);
+
+ /* put RNG4 into run mode */
+ val = caam_reg_read(dev, RNG_REG_RTMCTL_OFFSET);
+ val = val & ~RTMCTL_PRGM;
+ caam_reg_write(dev, RNG_REG_RTMCTL_OFFSET, val);
+}
+
+/* This function instantiates the rng
+ *
+ * Return code:
+ * 0 - All is well
+ * <0 - Error occurred somewhere
+ */
+static int
+instantiate_trng(device_t dev)
+{
+ int ret = 0;
+ int ent_delay = RTSDCTL_ENT_DLY_MIN;
+ uint32_t state_handle;
+
+ ret = is_trng_instantiated(dev, &state_handle);
+ if (ret != 0) {
+ CAAM_LOG_NOTICE(
+ "RNG already instantiated, make sure it is running\n");
+
+ /* put RNG4 into run mode */
+ uint32_t val = caam_reg_read(dev, RNG_REG_RTMCTL_OFFSET);
+ val = val & ~RTMCTL_PRGM;
+ caam_reg_write(dev, RNG_REG_RTMCTL_OFFSET, val);
+
+ return 0;
+ }
+
+ do {
+ kick_trng(dev, ent_delay);
+ ent_delay += 400;
+ /*if instantiate_rng(...) fails, the loop will rerun
+ *and the kick_trng(...) function will modify the
+ *upper and lower limits of the entropy sampling
+ *interval, leading to a sucessful initialization
+ */
+ ret = run_trng_instantiate_job(dev);
+ } while ((ret != 0) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
+
+ if (ret != 0) {
+ CAAM_LOG_ERROR("RNG: Failed to instantiate RNG\n");
+ return ret;
+ }
+
+ CAAM_LOG_INFO("RNG: Instantiated\n");
+
+ return ret;
+}
+
+/*------------------ Functions to generate the RNG numbers ------------------*/
+/* Construct descriptor to generate Random words */
+static int
+cnstr_trng_jobdesc(uint32_t *desc, uint32_t state_handle, uint32_t *add_inp,
+ uint32_t add_ip_len, caam_jr_dma_map_t *out_data_map, bool little_endian)
+{
+ bus_addr_t phys_addr_out = out_data_map->bus_addr;
+
+ /* Current descriptor support only 64K length */
+ if (out_data_map->buflen > 0xffffu)
+ return EINVAL;
+ /* Additional Input not supported by current descriptor */
+ if (add_ip_len > 0U)
+ return EINVAL;
+
+ CAAM_LOG_DEBUG("Constructing descriptor\n");
+ caam_jobdesc_init(desc);
+ /* Class1 Alg Operation,RNG Optype, Generate */
+ caam_jobdesc_add_word(desc, 0xb0800000u);
+ caam_jobdesc_add_word(desc,
+ 0x82500000u | (state_handle << ALG_AAI_SH_SHIFT));
+ caam_jobdesc_add_word(desc, 0x60340000u | out_data_map->buflen);
+ caam_jobdesc_add_ptr(desc, phys_addr_out, little_endian);
+
+ return 0;
+}
+
+/* Generate Random Data using HW RNG
+ * Parameters:
+ * uint8_t* add_input - user specified optional input byte array
+ * uint32_t add_input_len - number of bytes of additional input
+ * uint8_t* out - user specified output byte array
+ * uint32_t out_len - number of bytes to store in output byte array
+ * Return code:
+ * 0 - SUCCESS
+ * !0 - ERROR
+ */
+static int
+run_trng_generate_job(device_t dev, uint32_t *add_input, uint32_t add_input_len,
+ uint8_t *out, uint32_t out_len, uint32_t state_handle)
+{
+ int ret = 0;
+ struct job_descriptor desc;
+ struct job_descriptor *jobdesc = &desc;
+ caam_jr_dma_map_t out_data_map;
+ struct caam_softc *sc;
+ device_t jr_dev;
+
+ sc = device_get_softc(dev);
+
+ jobdesc->arg = NULL;
+ jobdesc->callback = NULL;
+
+ jr_dev = jr_pool_acquire(&sc->jr_pool);
+ if (jr_dev == NULL) {
+ CAAM_LOG_ERROR("Failed to acquire JR\n");
+ goto exit;
+ }
+
+ /* Map the output buffer to the DMA memory */
+ ret = caam_jr_dma_map(jr_dev, &out_data_map, out, out_len, 0,
+ BUS_DMA_NOWAIT, JR_MAP_SYNC);
+ if (ret != 0) {
+ CAAM_LOG_ERROR("DMA mapping failed\n");
+ goto jr_free;
+ }
+
+ /* create the hw_rng descriptor */
+ ret = cnstr_trng_jobdesc(jobdesc->desc, state_handle, add_input,
+ add_input_len, &out_data_map, sc->little_endian);
+ if (ret != 0) {
+ CAAM_LOG_ERROR("Descriptor construction failed\n");
+ goto dma_unmap;
+ }
+
+ /* Finally, generate the requested random data bytes */
+ ret = caam_run_descriptor_jr_blocking(dev, jobdesc, jr_dev);
+ if (ret != 0) {
+ CAAM_LOG_ERROR("Error in running descriptor\n");
+ goto dma_unmap;
+ }
+
+dma_unmap:
+ caam_jr_dma_unmap(jr_dev, &out_data_map, JR_MAP_SYNC);
+
+jr_free:
+ jr_pool_release(&sc->jr_pool, jr_dev);
+
+exit:
+ return ret;
+}
+
+/* Generate random bytes, and stuff them into the bytes buffer
+ *
+ * If the HW RNG has not already been instantiated,
+ * it will be instantiated before data is generated.
+ *
+ * Parameters:
+ * uint8_t* bytes - byte buffer large enough to hold the requested random date
+ * int byte_len - number of random bytes to generate
+ *
+ * Return code:
+ * 0 - All is well
+ * ~0 - Error occurred somewhere
+ */
+int
+caam_trng_get_bytes(device_t dev, uint8_t *bytes, int byte_len)
+{
+ int ret_code = 0;
+ int init_ret_code = 0;
+ uint32_t state_handle = 0;
+
+ /* If this is the first time this routine is called,
+ * then the rng will not already be instantiated.
+ * Therefore, before generating data, instantiate the rng
+ */
+ init_ret_code = is_trng_instantiated(dev, &state_handle);
+ if (init_ret_code == 0) {
+ CAAM_LOG_INFO("Instantiating the HW RNG\n");
+
+ /* Instantiate the hw RNG */
+ ret_code = instantiate_trng(dev);
+ if (ret_code != 0) {
+ CAAM_LOG_ERROR("HW RNG Instantiate failed\n");
+ }
+ }
+
+ if (ret_code == 0) {
+ ret_code = run_trng_generate_job(dev, 0, 0, bytes, byte_len,
+ state_handle);
+ if (ret_code != 0) {
+ CAAM_LOG_ERROR("HW RNG Generate failed\n");
+ }
+ }
+
+ return ret_code;
+}
+
+/*------------ Random harvester (random_caam) interface functions -----------*/
+static u_int random_caam_read(void *, u_int);
+
+static struct random_source random_caam = {
+ .rs_ident = "NXP QorIQ platforms CAAM TRNG",
+ .rs_source = RANDOM_PURE_CAAMTRNG,
+ .rs_read = random_caam_read
+};
+
+/* Blocking read function will return prebuffered data */
+static u_int
+random_caam_read(void *buf, u_int c)
+{
+ struct trng_cache *cache = &g_cache;
+
+ c = trng_cache_buf_read(cache, buf, c);
+
+ CAAM_LOG_DEBUG("Read out %iB\n", c);
+
+ return c;
+}
+
+/*------ Random character device (random_caam_cdev) interface functions -----*/
+#define BUFFERSIZE 256
+
+/* Function prototypes */
+static d_open_t random_caam_cdev_open;
+static d_close_t random_caam_cdev_close;
+static d_read_t random_caam_cdev_read;
+
+/* Character device entry points */
+static struct cdevsw random_caam_cdevsw = {
+ .d_version = D_VERSION,
+ .d_open = random_caam_cdev_open,
+ .d_close = random_caam_cdev_close,
+ .d_read = random_caam_cdev_read,
+ .d_name = "random_caam_cdev",
+};
+
+/* vars */
+static struct cdev *random_caam_cdev;
+
+static int
+random_caam_cdev_open(struct cdev *dev __unused, int oflags __unused,
+ int devtype __unused, struct thread *td __unused)
+{
+ device_t caam_dev = g_caam_dev;
+
+ if (caam_dev == NULL) {
+ CAAM_LOG_ERROR("No CAAM module available!\n");
+ return (ENXIO);
+ }
+
+ CAAM_LOG_DEBUG("Opened CAAM TRNG character device successfully.\n");
+ return (0);
+}
+
+static int
+random_caam_cdev_close(struct cdev *dev __unused, int fflag __unused,
+ int devtype __unused, struct thread *td __unused)
+{
+ CAAM_LOG_DEBUG("Closing CAAM TRNG character device.\n");
+ return (0);
+}
+
+/*
+ * The read function reads from random device and set it to userland for
+ * accessing.
+ */
+static int
+random_caam_cdev_read(struct cdev *dev __unused, struct uio *uio,
+ int ioflag __unused)
+{
+ size_t read_len;
+ int error = 0;
+ uint8_t random_buf[BUFFERSIZE];
+ device_t caam_dev = g_caam_dev;
+
+ while (uio->uio_resid > 0) {
+ /* Maximum data to read is either local buff or user request */
+ read_len = MIN((size_t)uio->uio_resid, sizeof(random_buf));
+
+ error = caam_trng_get_bytes(caam_dev, random_buf, read_len);
+ if (error != 0) {
+ CAAM_LOG_ERROR("RNG generation failed!\n");
+ break;
+ }
+
+ /*
+ * uiomove() may yield the CPU before each 'read_len' bytes (up
+ * to bufsize) are copied out.
+ */
+ if ((error = uiomove(random_buf, read_len, uio)) != 0) {
+ CAAM_LOG_ERROR("uiomove failed!\n");
+ break;
+ }
+ }
+
+ explicit_bzero(random_buf, sizeof(random_buf));
+
+ return (error);
+}
+
+/*--------------------- CAAM device management functions --------------------*/
+int
+caam_trng_attach(device_t dev)
+{
+ int error = 0;
+ struct make_dev_args args;
+ struct trng_cache *c = &g_cache;
+
+ /* Add the random source and the character device only on the first CAAM
+ * device.*/
+ if (g_caam_dev == NULL) {
+ g_caam_dev = dev;
+
+ error = trng_cache_init(dev, c, TRNG_CACHE_SIZE);
+ if (error) {
+ CAAM_LOG_ERROR("Failed to init TRNG cache ret=%d\n",
+ error);
+ goto exit;
+ }
+
+ /* Initial fill before harvester can read from our buffers */
+ for (int i = 0; i < TRNG_CACHE_COUNT; ++i) {
+ error = trng_cache_refill(dev, c, i);
+ if (error) {
+ trng_cache_deinit(c);
+ goto exit;
+ }
+ }
+
+ random_source_register(&random_caam);
+ CAAM_LOG_INFO("CAAM TRNG registering fast provider: \"%s\"\n",
+ random_caam.rs_ident);
+
+ /* Register the device as read only */
+ make_dev_args_init(&args);
+ args.mda_flags = MAKEDEV_CHECKNAME | MAKEDEV_WAITOK;
+ args.mda_devsw = &random_caam_cdevsw;
+ args.mda_cr = 0;
+ args.mda_uid = UID_ROOT;
+ args.mda_gid = GID_WHEEL;
+ args.mda_mode = 0400;
+
+ error = make_dev_s(&args, &random_caam_cdev, "random_caam");
+
+ CAAM_LOG_INFO(
+ "CAAM TRNG /dev/random_caam character device loaded.\n");
+ }
+
+exit:
+ return error;
+}
+
+int
+caam_trng_detach(device_t dev)
+{
+ struct trng_cache *c = &g_cache;
+
+ /* Deregister rng source and rmove character device only if correct CAAM
+ * device is detached */
+ if (dev == g_caam_dev) {
+ CAAM_LOG_INFO(
+ "CAAM TRNG /dev/random_caam character device removed.\n");
+ destroy_dev(random_caam_cdev);
+
+ CAAM_LOG_INFO("CAAM TRNG deregistering fast provider: \"%s\"\n",
+ random_caam.rs_ident);
+ random_source_deregister(&random_caam);
+
+ trng_cache_deinit(c);
+
+ /* at this time no clients should exist that can use the
+ * g_caam_dev */
+ g_caam_dev = NULL;
+ }
+
+ return 0;
+}
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -687,6 +687,7 @@
arm64/qoriq/clk/qoriq_clk_pll.c optional clk soc_nxp_ls
arm64/qoriq/clk/qoriq_clkgen.c optional clk soc_nxp_ls fdt
arm64/qoriq/caam/caam.c optional caam soc_nxp_ls
+arm64/qoriq/caam/caam_trng.c optional caam soc_nxp_ls
arm64/qoriq/caam/caam_test.c optional caam caam_debug soc_nxp_ls
arm64/qoriq/caam/jr/caam_jr.c optional caam soc_nxp_ls
arm64/qoriq/caam/jr/caam_jr_pool.c optional caam soc_nxp_ls
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_VMGENID] = "PURE_VMGENID",
[RANDOM_PURE_QUALCOMM] = "PURE_QUALCOMM",
[RANDOM_PURE_ARMV8] = "PURE_ARMV8",
+ [RANDOM_PURE_CAAMTRNG] = "PURE_CAAMTRNG",
/* "ENTROPYSOURCE" */
};
diff --git a/sys/sys/random.h b/sys/sys/random.h
--- a/sys/sys/random.h
+++ b/sys/sys/random.h
@@ -103,6 +103,7 @@
RANDOM_PURE_VMGENID,
RANDOM_PURE_QUALCOMM,
RANDOM_PURE_ARMV8,
+ RANDOM_PURE_CAAMTRNG,
ENTROPYSOURCE
};
_Static_assert(ENTROPYSOURCE <= 32,
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, May 19, 6:40 PM (11 h, 34 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33283305
Default Alt Text
D45591.id140220.diff (21 KB)
Attached To
Mode
D45591: caam: Add caam_trng support in caam driver
Attached
Detach File
Event Timeline
Log In to Comment