Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src-draft/trunk]: src/sys/arch/mips/cavium/dev Be a little more judicious wi...



details:   https://anonhg.NetBSD.org/src-all/rev/debe22623b19
branches:  trunk
changeset: 932658:debe22623b19
user:      Taylor R Campbell <riastradh%NetBSD.org@localhost>
date:      Wed May 13 16:07:07 2020 +0000

description:
Be a little more judicious with delays in octeon_rnm.

- Use cycle count busy loops, not microsecond delays.
- Yield if requested in the loop.
- Don't load twice as much data as intended!

diffstat:

 sys/arch/mips/cavium/dev/octeon_rnm.c |  75 ++++++++++++++++++++++------------
 1 files changed, 49 insertions(+), 26 deletions(-)

diffs (139 lines):

diff -r 1b32749f3ec0 -r debe22623b19 sys/arch/mips/cavium/dev/octeon_rnm.c
--- a/sys/arch/mips/cavium/dev/octeon_rnm.c     Wed May 13 07:38:50 2020 +0000
+++ b/sys/arch/mips/cavium/dev/octeon_rnm.c     Wed May 13 16:07:07 2020 +0000
@@ -105,9 +105,10 @@
 
 //#define      OCTEON_RNM_DEBUG
 
-#define        ENT_DELAY_CLOCK 8       /* cycles for each RO sample */
+#define        ENT_DELAY_CLOCK 8       /* cycles for each 64-bit RO sample batch */
 #define        RNG_DELAY_CLOCK 81      /* cycles for each SHA-1 output */
 #define        NROGROUPS       16
+#define        RNG_FIFO_WORDS  (512/sizeof(uint64_t))
 
 struct octeon_rnm_softc {
        bus_space_tag_t         sc_bust;
@@ -126,6 +127,7 @@
 static void octeon_rnm_raw_entropy(struct octeon_rnm_softc *, unsigned);
 static uint64_t octeon_rnm_load(struct octeon_rnm_softc *);
 static void octeon_rnm_iobdma(struct octeon_rnm_softc *, uint64_t *, unsigned);
+static void octeon_rnm_delay(uint32_t);
 
 CFATTACH_DECL_NEW(octeon_rnm, sizeof(struct octeon_rnm_softc),
     octeon_rnm_match, octeon_rnm_attach, NULL, NULL);
@@ -173,7 +175,7 @@
 
        /*
         * Reset the core, enable the RNG engine without entropy, wait
-        * 81 cycles for it to warm up (round up to 1us), and get a
+        * 81 cycles for it to produce a single sample, and draw the
         * deterministic sample to test.
         *
         * XXX Verify that the output matches the SHA-1 computation
@@ -181,7 +183,7 @@
         */
        octeon_rnm_reset(sc);
        octeon_rnm_conditioned_deterministic(sc);
-       delay(1);
+       octeon_rnm_delay(RNG_DELAY_CLOCK*1);
        sample = octeon_rnm_load(sc);
        if (sample != expected)
                aprint_error_dev(self, "self-test: read %016"PRIx64","
@@ -196,6 +198,7 @@
        octeon_rnm_reset(sc);
        sc->sc_rogroup = 0;
        octeon_rnm_raw_entropy(sc, sc->sc_rogroup);
+       octeon_rnm_delay(ENT_DELAY_CLOCK*RNG_FIFO_WORDS);
 
        /* Attach the rndsource.  */
        rndsource_setcb(&sc->sc_rndsrc, octeon_rnm_rng, sc);
@@ -211,23 +214,20 @@
        uint64_t sample[32];
        struct octeon_rnm_softc *sc = vsc;
        size_t needed = NBBY*nbytes;
+       unsigned i;
 
-       /*
-        * Sample all of the ring oscillators at least once, while
-        * preventing concurrent access to the FIFO out of paranoia.
-        */
+       /* Sample the ring oscillators round-robin.  */
        mutex_enter(&sc->sc_lock);
-       for (; needed; needed -= MIN(needed, NBBY*sizeof(sample)/BPB)) {
+       while (needed) {
                /*
-                * Make sure the FIFO is full.  We need 8 cycles for
-                * every 64 bits = 8 bytes, and the FIFO has 512 bytes,
-                * for a total of 512 cycles; round that up to 2us,
-                * under the assumption that the CPU runs at no less
-                * than 256 MHz.
+                * Switch to the next RO group once we drain the FIFO.
+                * By the time rnd_add_data is done, we will have
+                * processed all 512 bytes of the FIFO.  We assume it
+                * takes at least one cycle per byte (realistically,
+                * more like ~80cpb to draw from the FIFO and then
+                * process it with rnd_add_data), so there is no need
+                * for any other delays.
                 */
-               delay(2);
-
-               /* Switch to the next RO group once we drain the FIFO.  */
                sc->sc_rogroup++;
                sc->sc_rogroup %= NROGROUPS;
                octeon_rnm_raw_entropy(sc, sc->sc_rogroup);
@@ -237,18 +237,24 @@
                 * 256 bytes because of limits on the CVMSEG buffer.
                 */
                CTASSERT(sizeof sample == 256);
-               octeon_rnm_iobdma(sc, sample, __arraycount(sample));
+               CTASSERT(2*__arraycount(sample) == RNG_FIFO_WORDS);
+               for (i = 0; i < 2; i++) {
+                       octeon_rnm_iobdma(sc, sample, __arraycount(sample));
 #ifdef OCTEON_RNM_DEBUG
-               hexdump(printf, "rnm", sample, sizeof sample);
+                       hexdump(printf, "rnm", sample, sizeof sample);
 #endif
-               rnd_add_data(&sc->sc_rndsrc, sample, sizeof sample,
-                   NBBY*sizeof(sample)/BPB);
-               octeon_rnm_iobdma(sc, sample, __arraycount(sample));
-#ifdef OCTEON_RNM_DEBUG
-               hexdump(printf, "rnm", sample, sizeof sample);
-#endif
-               rnd_add_data(&sc->sc_rndsrc, sample, sizeof sample,
-                   NBBY*sizeof(sample)/BPB);
+                       rnd_add_data(&sc->sc_rndsrc, sample, sizeof sample,
+                           NBBY*sizeof(sample)/BPB);
+                       needed -= MIN(needed, MAX(1, NBBY*sizeof(sample)/BPB));
+               }
+
+               /* Yield if requested.  */
+               if (__predict_false(curcpu()->ci_schedstate.spc_flags &
+                       SPCF_SHOULDYIELD)) {
+                       mutex_exit(&sc->sc_lock);
+                       preempt();
+                       mutex_enter(&sc->sc_lock);
+               }
        }
        mutex_exit(&sc->sc_lock);
 
@@ -357,3 +363,20 @@
        for (; nwords --> 0; scraddr += 8)
                *buf++ = octeon_cvmseg_read_8(scraddr);
 }
+
+/*
+ * octeon_rnm_delay(ncycles)
+ *
+ *     Wait ncycles, at most UINT32_MAX/2 so we behave reasonably even
+ *     if the cycle counter rolls over.
+ */
+static void
+octeon_rnm_delay(uint32_t ncycles)
+{
+       uint32_t deadline = mips3_cp0_count_read() + ncycles;
+
+       KASSERT(ncycles <= UINT32_MAX/2);
+
+       while ((deadline - mips3_cp0_count_read()) < ncycles)
+               continue;
+}



Home | Main Index | Thread Index | Old Index