xref: /qemu/tests/qtest/xlnx-versal-trng-test.c (revision cabe58b0)
11c98a821STong Ho /*
21c98a821STong Ho  * QTests for the Xilinx Versal True Random Number Generator device
31c98a821STong Ho  *
41c98a821STong Ho  * Copyright (c) 2023 Advanced Micro Devices, Inc.
51c98a821STong Ho  *
61c98a821STong Ho  * SPDX-License-Identifier: GPL-2.0-or-later
71c98a821STong Ho  */
81c98a821STong Ho 
91c98a821STong Ho #include "qemu/osdep.h"
101c98a821STong Ho #include "libqtest-single.h"
111c98a821STong Ho 
121c98a821STong Ho /* Base Address */
131c98a821STong Ho #define TRNG_BASEADDR      (0xf1230000)
141c98a821STong Ho 
151c98a821STong Ho /* TRNG_INT_CTRL */
161c98a821STong Ho #define R_TRNG_INT_CTRL                 (0x0000)
171c98a821STong Ho #define   TRNG_INT_CTRL_CERTF_RST_MASK  (1 << 5)
181c98a821STong Ho #define   TRNG_INT_CTRL_DTF_RST_MASK    (1 << 4)
191c98a821STong Ho #define   TRNG_INT_CTRL_DONE_RST_MASK   (1 << 3)
201c98a821STong Ho #define   TRNG_INT_CTRL_CERTF_EN_MASK   (1 << 2)
211c98a821STong Ho #define   TRNG_INT_CTRL_DTF_EN_MASK     (1 << 1)
221c98a821STong Ho #define   TRNG_INT_CTRL_DONE_EN_MASK    (1)
231c98a821STong Ho 
241c98a821STong Ho /* TRNG_STATUS */
251c98a821STong Ho #define R_TRNG_STATUS              (0x0004)
261c98a821STong Ho #define   TRNG_STATUS_QCNT_SHIFT   (9)
271c98a821STong Ho #define   TRNG_STATUS_QCNT_MASK    (7 << TRNG_STATUS_QCNT_SHIFT)
281c98a821STong Ho #define   TRNG_STATUS_CERTF_MASK   (1 << 3)
291c98a821STong Ho #define   TRNG_STATUS_DTF_MASK     (1 << 1)
301c98a821STong Ho #define   TRNG_STATUS_DONE_MASK    (1)
311c98a821STong Ho 
321c98a821STong Ho /* TRNG_CTRL */
331c98a821STong Ho #define R_TRNG_CTRL                (0x0008)
341c98a821STong Ho #define   TRNG_CTRL_PERSODISABLE_MASK   (1 << 10)
351c98a821STong Ho #define   TRNG_CTRL_SINGLEGENMODE_MASK  (1 << 9)
361c98a821STong Ho #define   TRNG_CTRL_PRNGMODE_MASK       (1 << 7)
371c98a821STong Ho #define   TRNG_CTRL_TSTMODE_MASK        (1 << 6)
381c98a821STong Ho #define   TRNG_CTRL_PRNGSTART_MASK      (1 << 5)
391c98a821STong Ho #define   TRNG_CTRL_PRNGXS_MASK         (1 << 3)
401c98a821STong Ho #define   TRNG_CTRL_TRSSEN_MASK         (1 << 2)
411c98a821STong Ho #define   TRNG_CTRL_QERTUEN_MASK        (1 << 1)
421c98a821STong Ho #define   TRNG_CTRL_PRNGSRST_MASK       (1)
431c98a821STong Ho 
441c98a821STong Ho /* TRNG_EXT_SEED_0 ... _11 */
451c98a821STong Ho #define R_TRNG_EXT_SEED_0          (0x0040)
461c98a821STong Ho #define R_TRNG_EXT_SEED_11         (R_TRNG_EXT_SEED_0 + 4 * 11)
471c98a821STong Ho 
481c98a821STong Ho /* TRNG_PER_STRNG_0 ... 11 */
491c98a821STong Ho #define R_TRNG_PER_STRNG_0         (0x0080)
501c98a821STong Ho #define R_TRNG_PER_STRNG_11        (R_TRNG_PER_STRNG_0 + 4 * 11)
511c98a821STong Ho 
521c98a821STong Ho /* TRNG_CORE_OUTPUT */
531c98a821STong Ho #define R_TRNG_CORE_OUTPUT         (0x00c0)
541c98a821STong Ho 
551c98a821STong Ho /* TRNG_RESET */
561c98a821STong Ho #define R_TRNG_RESET               (0x00d0)
571c98a821STong Ho #define   TRNG_RESET_VAL_MASK      (1)
581c98a821STong Ho 
591c98a821STong Ho /* TRNG_OSC_EN */
601c98a821STong Ho #define R_TRNG_OSC_EN              (0x00d4)
611c98a821STong Ho #define   TRNG_OSC_EN_VAL_MASK     (1)
621c98a821STong Ho 
631c98a821STong Ho /* TRNG_TRNG_ISR, _IMR, _IER, _IDR */
641c98a821STong Ho #define R_TRNG_ISR                 (0x00e0)
651c98a821STong Ho #define R_TRNG_IMR                 (0x00e4)
661c98a821STong Ho #define R_TRNG_IER                 (0x00e8)
671c98a821STong Ho #define R_TRNG_IDR                 (0x00ec)
681c98a821STong Ho #define   TRNG_IRQ_SLVERR_MASK     (1 << 1)
691c98a821STong Ho #define   TRNG_IRQ_CORE_INT_MASK   (1)
701c98a821STong Ho 
711c98a821STong Ho /*
721c98a821STong Ho  * End test with a formatted error message, by embedding the message
731c98a821STong Ho  * in a GError.
741c98a821STong Ho  */
751c98a821STong Ho #define TRNG_FAILED(FMT, ...)                           \
761c98a821STong Ho     do {                                                \
771c98a821STong Ho         g_autoptr(GError) err = g_error_new(            \
781c98a821STong Ho             g_quark_from_static_string(trng_qname), 0,  \
791c98a821STong Ho             FMT, ## __VA_ARGS__);                       \
801c98a821STong Ho         g_assert_no_error(err);                         \
811c98a821STong Ho     } while (0)
821c98a821STong Ho 
831c98a821STong Ho static const gchar trng_qname[] = "xlnx-versal-trng-test";
841c98a821STong Ho 
851c98a821STong Ho static const uint32_t prng_seed[12] = {
861c98a821STong Ho     0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc,
871c98a821STong Ho     0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98,
881c98a821STong Ho };
891c98a821STong Ho 
901c98a821STong Ho static const uint32_t pers_str[12] = {
911c98a821STong Ho     0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98,
921c98a821STong Ho     0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc,
931c98a821STong Ho };
941c98a821STong Ho 
trng_test_start(void)951c98a821STong Ho static void trng_test_start(void)
961c98a821STong Ho {
971c98a821STong Ho     qtest_start("-machine xlnx-versal-virt");
981c98a821STong Ho }
991c98a821STong Ho 
trng_test_stop(void)1001c98a821STong Ho static void trng_test_stop(void)
1011c98a821STong Ho {
1021c98a821STong Ho     qtest_end();
1031c98a821STong Ho }
1041c98a821STong Ho 
trng_test_set_uint_prop(const char * name,uint64_t value)1051c98a821STong Ho static void trng_test_set_uint_prop(const char *name, uint64_t value)
1061c98a821STong Ho {
1071c98a821STong Ho     const char *path = "/machine/xlnx-versal/trng";
1081c98a821STong Ho     QDict *response;
1091c98a821STong Ho 
1101c98a821STong Ho     response = qmp("{ 'execute': 'qom-set',"
1111c98a821STong Ho                     " 'arguments': {"
1121c98a821STong Ho                        " 'path': %s,"
1131c98a821STong Ho                        " 'property': %s,"
1141c98a821STong Ho                        " 'value': %llu"
1151c98a821STong Ho                       "} }", path,
1161c98a821STong Ho                    name, (unsigned long long)value);
1171c98a821STong Ho     g_assert(qdict_haskey(response, "return"));
1181c98a821STong Ho     qobject_unref(response);
1191c98a821STong Ho }
1201c98a821STong Ho 
trng_write(unsigned ra,uint32_t val)1211c98a821STong Ho static void trng_write(unsigned ra, uint32_t val)
1221c98a821STong Ho {
1231c98a821STong Ho     writel(TRNG_BASEADDR + ra, val);
1241c98a821STong Ho }
1251c98a821STong Ho 
trng_read(unsigned ra)1261c98a821STong Ho static uint32_t trng_read(unsigned ra)
1271c98a821STong Ho {
1281c98a821STong Ho     return readl(TRNG_BASEADDR + ra);
1291c98a821STong Ho }
1301c98a821STong Ho 
trng_bit_set(unsigned ra,uint32_t bits)1311c98a821STong Ho static void trng_bit_set(unsigned ra, uint32_t bits)
1321c98a821STong Ho {
1331c98a821STong Ho     trng_write(ra, (trng_read(ra) | bits));
1341c98a821STong Ho }
1351c98a821STong Ho 
trng_bit_clr(unsigned ra,uint32_t bits)1361c98a821STong Ho static void trng_bit_clr(unsigned ra, uint32_t bits)
1371c98a821STong Ho {
1381c98a821STong Ho     trng_write(ra, (trng_read(ra) & ~bits));
1391c98a821STong Ho }
1401c98a821STong Ho 
trng_ctrl_set(uint32_t bits)1411c98a821STong Ho static void trng_ctrl_set(uint32_t bits)
1421c98a821STong Ho {
1431c98a821STong Ho     trng_bit_set(R_TRNG_CTRL, bits);
1441c98a821STong Ho }
1451c98a821STong Ho 
trng_ctrl_clr(uint32_t bits)1461c98a821STong Ho static void trng_ctrl_clr(uint32_t bits)
1471c98a821STong Ho {
1481c98a821STong Ho     trng_bit_clr(R_TRNG_CTRL, bits);
1491c98a821STong Ho }
1501c98a821STong Ho 
trng_status(void)1511c98a821STong Ho static uint32_t trng_status(void)
1521c98a821STong Ho {
1531c98a821STong Ho     return trng_read(R_TRNG_STATUS);
1541c98a821STong Ho }
1551c98a821STong Ho 
trng_qcnt(void)1561c98a821STong Ho static unsigned trng_qcnt(void)
1571c98a821STong Ho {
1581c98a821STong Ho     uint32_t sta = trng_status();
1591c98a821STong Ho 
1601c98a821STong Ho     return (sta & TRNG_STATUS_QCNT_MASK) >> TRNG_STATUS_QCNT_SHIFT;
1611c98a821STong Ho }
1621c98a821STong Ho 
trng_info(void)1631c98a821STong Ho static const char *trng_info(void)
1641c98a821STong Ho {
1651c98a821STong Ho     uint32_t sta = trng_status();
1661c98a821STong Ho     uint32_t ctl = trng_read(R_TRNG_CTRL);
1671c98a821STong Ho 
1681c98a821STong Ho     static char info[64];
1691c98a821STong Ho 
1701c98a821STong Ho     snprintf(info, sizeof(info), "; status=0x%x, ctrl=0x%x", sta, ctl);
1711c98a821STong Ho     return info;
1721c98a821STong Ho }
1731c98a821STong Ho 
trng_check_status(uint32_t status_mask,const char * act)1741c98a821STong Ho static void trng_check_status(uint32_t status_mask, const char *act)
1751c98a821STong Ho {
1761c98a821STong Ho     uint32_t clear_mask = 0;
1771c98a821STong Ho     uint32_t status;
1781c98a821STong Ho 
1791c98a821STong Ho     /*
1801c98a821STong Ho      * Only selected bits are events in R_TRNG_STATUS, and
1811c98a821STong Ho      * clear them needs to go through R_INT_CTRL.
1821c98a821STong Ho      */
1831c98a821STong Ho     if (status_mask & TRNG_STATUS_CERTF_MASK) {
1841c98a821STong Ho         clear_mask |= TRNG_INT_CTRL_CERTF_RST_MASK;
1851c98a821STong Ho     }
1861c98a821STong Ho     if (status_mask & TRNG_STATUS_DTF_MASK) {
1871c98a821STong Ho         clear_mask |= TRNG_INT_CTRL_DTF_RST_MASK;
1881c98a821STong Ho     }
1891c98a821STong Ho     if (status_mask & TRNG_STATUS_DONE_MASK) {
1901c98a821STong Ho         clear_mask |= TRNG_INT_CTRL_DONE_RST_MASK;
1911c98a821STong Ho     }
1921c98a821STong Ho 
1931c98a821STong Ho     status = trng_status();
1941c98a821STong Ho     if ((status & status_mask) != status_mask) {
1951c98a821STong Ho         TRNG_FAILED("%s: Status bitmask 0x%x failed to be 1%s",
1961c98a821STong Ho                     act, status_mask, trng_info());
1971c98a821STong Ho     }
1981c98a821STong Ho 
1991c98a821STong Ho     /* Remove event */
2001c98a821STong Ho     trng_bit_set(R_TRNG_INT_CTRL, clear_mask);
2011c98a821STong Ho 
2021c98a821STong Ho     if (!!(trng_read(R_TRNG_STATUS) & status_mask)) {
2031c98a821STong Ho         TRNG_FAILED("%s: Event 0x%0x stuck at 1 after clear: %s",
2041c98a821STong Ho                     act, status_mask, trng_info());
2051c98a821STong Ho     }
2061c98a821STong Ho }
2071c98a821STong Ho 
trng_check_done_status(const char * act)2081c98a821STong Ho static void trng_check_done_status(const char *act)
2091c98a821STong Ho {
2101c98a821STong Ho     trng_check_status(TRNG_STATUS_DONE_MASK, act);
2111c98a821STong Ho }
2121c98a821STong Ho 
trng_check_dtf_status(void)2131c98a821STong Ho static void trng_check_dtf_status(void)
2141c98a821STong Ho {
2151c98a821STong Ho     trng_check_status(TRNG_STATUS_DTF_MASK, "DTF injection");
2161c98a821STong Ho }
2171c98a821STong Ho 
trng_check_certf_status(void)2181c98a821STong Ho static void trng_check_certf_status(void)
2191c98a821STong Ho {
2201c98a821STong Ho     trng_check_status(TRNG_STATUS_CERTF_MASK, "CERTF injection");
2211c98a821STong Ho }
2221c98a821STong Ho 
trng_reset(void)2231c98a821STong Ho static void trng_reset(void)
2241c98a821STong Ho {
2251c98a821STong Ho     trng_write(R_TRNG_RESET, TRNG_RESET_VAL_MASK);
2261c98a821STong Ho     trng_write(R_TRNG_RESET, 0);
2271c98a821STong Ho }
2281c98a821STong Ho 
trng_load(unsigned r0,const uint32_t * b384)2291c98a821STong Ho static void trng_load(unsigned r0, const uint32_t *b384)
2301c98a821STong Ho {
2311c98a821STong Ho     static const uint32_t zero[12] = { 0 };
2321c98a821STong Ho     unsigned k;
2331c98a821STong Ho 
2341c98a821STong Ho     if (!b384) {
2351c98a821STong Ho         b384 = zero;
2361c98a821STong Ho     }
2371c98a821STong Ho 
2381c98a821STong Ho     for (k = 0; k < 12; k++) {
2391c98a821STong Ho         trng_write(r0 + 4 * k, b384[k]);
2401c98a821STong Ho     }
2411c98a821STong Ho }
2421c98a821STong Ho 
trng_reseed(const uint32_t * seed)2431c98a821STong Ho static void trng_reseed(const uint32_t *seed)
2441c98a821STong Ho {
2451c98a821STong Ho     const char *act;
2461c98a821STong Ho     uint32_t ctl;
2471c98a821STong Ho 
2481c98a821STong Ho     ctl = TRNG_CTRL_PRNGSTART_MASK |
2491c98a821STong Ho           TRNG_CTRL_PRNGXS_MASK |
2501c98a821STong Ho           TRNG_CTRL_TRSSEN_MASK;
2511c98a821STong Ho 
2521c98a821STong Ho     trng_ctrl_clr(ctl | TRNG_CTRL_PRNGMODE_MASK);
2531c98a821STong Ho 
2541c98a821STong Ho     if (seed) {
2551c98a821STong Ho         trng_load(R_TRNG_EXT_SEED_0, seed);
2561c98a821STong Ho         act = "Reseed PRNG";
2571c98a821STong Ho         ctl &= ~TRNG_CTRL_TRSSEN_MASK;
2581c98a821STong Ho     } else {
2591c98a821STong Ho         trng_write(R_TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK);
2601c98a821STong Ho         act = "Reseed TRNG";
2611c98a821STong Ho         ctl &= ~TRNG_CTRL_PRNGXS_MASK;
2621c98a821STong Ho     }
2631c98a821STong Ho 
2641c98a821STong Ho     trng_ctrl_set(ctl);
2651c98a821STong Ho     trng_check_done_status(act);
2661c98a821STong Ho     trng_ctrl_clr(TRNG_CTRL_PRNGSTART_MASK);
2671c98a821STong Ho }
2681c98a821STong Ho 
trng_generate(bool auto_enb)2691c98a821STong Ho static void trng_generate(bool auto_enb)
2701c98a821STong Ho {
2711c98a821STong Ho     uint32_t ctl;
2721c98a821STong Ho 
2731c98a821STong Ho     ctl = TRNG_CTRL_PRNGSTART_MASK | TRNG_CTRL_SINGLEGENMODE_MASK;
2741c98a821STong Ho     trng_ctrl_clr(ctl);
2751c98a821STong Ho 
2761c98a821STong Ho     if (auto_enb) {
2771c98a821STong Ho         ctl &= ~TRNG_CTRL_SINGLEGENMODE_MASK;
2781c98a821STong Ho     }
2791c98a821STong Ho 
2801c98a821STong Ho     trng_ctrl_set(ctl | TRNG_CTRL_PRNGMODE_MASK);
2811c98a821STong Ho 
2821c98a821STong Ho     trng_check_done_status("Generate");
2831c98a821STong Ho     g_assert(trng_qcnt() != 7);
2841c98a821STong Ho }
2851c98a821STong Ho 
trng_collect(uint32_t * rnd,size_t cnt)2861c98a821STong Ho static size_t trng_collect(uint32_t *rnd, size_t cnt)
2871c98a821STong Ho {
2881c98a821STong Ho     size_t i;
2891c98a821STong Ho 
2901c98a821STong Ho     for (i = 0; i < cnt; i++) {
2911c98a821STong Ho         if (trng_qcnt() == 0) {
2921c98a821STong Ho             return i;
2931c98a821STong Ho         }
2941c98a821STong Ho 
2951c98a821STong Ho         rnd[i] = trng_read(R_TRNG_CORE_OUTPUT);
2961c98a821STong Ho     }
2971c98a821STong Ho 
2981c98a821STong Ho     return i;
2991c98a821STong Ho }
3001c98a821STong Ho 
301*cabe58b0SPeter Maydell /* These tests all generate 512 bits of random data with the device */
302*cabe58b0SPeter Maydell #define TEST_DATA_WORDS (512 / 32)
303*cabe58b0SPeter Maydell 
trng_test_autogen(void)3041c98a821STong Ho static void trng_test_autogen(void)
3051c98a821STong Ho {
306*cabe58b0SPeter Maydell     const size_t cnt = TEST_DATA_WORDS;
307*cabe58b0SPeter Maydell     uint32_t rng[TEST_DATA_WORDS], prng[TEST_DATA_WORDS];
3081c98a821STong Ho     size_t n;
3091c98a821STong Ho 
3101c98a821STong Ho     trng_reset();
3111c98a821STong Ho 
3121c98a821STong Ho     /* PRNG run #1 */
3131c98a821STong Ho     trng_reseed(prng_seed);
3141c98a821STong Ho     trng_generate(true);
3151c98a821STong Ho 
3161c98a821STong Ho     n = trng_collect(prng, cnt);
3171c98a821STong Ho     if (n != cnt) {
3181c98a821STong Ho         TRNG_FAILED("PRNG_1 Auto-gen test failed: expected = %u, got = %u",
3191c98a821STong Ho                     (unsigned)cnt, (unsigned)n);
3201c98a821STong Ho     }
3211c98a821STong Ho 
3221c98a821STong Ho     /* TRNG, should not match PRNG */
3231c98a821STong Ho     trng_reseed(NULL);
3241c98a821STong Ho     trng_generate(true);
3251c98a821STong Ho 
3261c98a821STong Ho     n = trng_collect(rng, cnt);
3271c98a821STong Ho     if (n != cnt) {
3281c98a821STong Ho         TRNG_FAILED("TRNG Auto-gen test failed: expected = %u, got = %u",
3291c98a821STong Ho                     (unsigned)cnt, (unsigned)n);
3301c98a821STong Ho     }
3311c98a821STong Ho 
3321c98a821STong Ho     /* PRNG #2: should matches run #1 */
3331c98a821STong Ho     trng_reseed(prng_seed);
3341c98a821STong Ho     trng_generate(true);
3351c98a821STong Ho 
3361c98a821STong Ho     n = trng_collect(rng, cnt);
3371c98a821STong Ho     if (n != cnt) {
3381c98a821STong Ho         TRNG_FAILED("PRNG_2 Auto-gen test failed: expected = %u, got = %u",
3391c98a821STong Ho                     (unsigned)cnt, (unsigned)n);
3401c98a821STong Ho     }
3411c98a821STong Ho 
3421c98a821STong Ho     if (memcmp(rng, prng, sizeof(rng))) {
3431c98a821STong Ho         TRNG_FAILED("PRNG_2 Auto-gen test failed: does not match PRNG_1");
3441c98a821STong Ho     }
3451c98a821STong Ho }
3461c98a821STong Ho 
trng_test_oneshot(void)3471c98a821STong Ho static void trng_test_oneshot(void)
3481c98a821STong Ho {
349*cabe58b0SPeter Maydell     const size_t cnt = TEST_DATA_WORDS;
350*cabe58b0SPeter Maydell     uint32_t rng[TEST_DATA_WORDS];
3511c98a821STong Ho     size_t n;
3521c98a821STong Ho 
3531c98a821STong Ho     trng_reset();
3541c98a821STong Ho 
3551c98a821STong Ho     /* PRNG run #1 */
3561c98a821STong Ho     trng_reseed(prng_seed);
3571c98a821STong Ho     trng_generate(false);
3581c98a821STong Ho 
3591c98a821STong Ho     n = trng_collect(rng, cnt);
3601c98a821STong Ho     if (n == cnt) {
3611c98a821STong Ho         TRNG_FAILED("PRNG_1 One-shot gen test failed");
3621c98a821STong Ho     }
3631c98a821STong Ho 
3641c98a821STong Ho     /* TRNG, should not match PRNG */
3651c98a821STong Ho     trng_reseed(NULL);
3661c98a821STong Ho     trng_generate(false);
3671c98a821STong Ho 
3681c98a821STong Ho     n = trng_collect(rng, cnt);
3691c98a821STong Ho     if (n == cnt) {
3701c98a821STong Ho         TRNG_FAILED("TRNG One-shot test failed");
3711c98a821STong Ho     }
3721c98a821STong Ho }
3731c98a821STong Ho 
trng_test_per_str(void)3741c98a821STong Ho static void trng_test_per_str(void)
3751c98a821STong Ho {
376*cabe58b0SPeter Maydell     const size_t cnt = TEST_DATA_WORDS;
377*cabe58b0SPeter Maydell     uint32_t rng[TEST_DATA_WORDS], prng[TEST_DATA_WORDS];
3781c98a821STong Ho     size_t n;
3791c98a821STong Ho 
3801c98a821STong Ho     trng_reset();
3811c98a821STong Ho 
3821c98a821STong Ho     /* #1: disabled */
3831c98a821STong Ho     trng_ctrl_set(TRNG_CTRL_PERSODISABLE_MASK);
3841c98a821STong Ho     trng_reseed(prng_seed);
3851c98a821STong Ho     trng_ctrl_clr(TRNG_CTRL_PERSODISABLE_MASK);
3861c98a821STong Ho 
3871c98a821STong Ho     trng_generate(true);
3881c98a821STong Ho     n = trng_collect(prng, cnt);
3891c98a821STong Ho     g_assert_cmpuint(n, ==, cnt);
3901c98a821STong Ho 
3911c98a821STong Ho     /* #2: zero string should match personalization disabled */
3921c98a821STong Ho     trng_load(R_TRNG_PER_STRNG_0, NULL);
3931c98a821STong Ho     trng_reseed(prng_seed);
3941c98a821STong Ho 
3951c98a821STong Ho     trng_generate(true);
3961c98a821STong Ho     n = trng_collect(rng, cnt);
3971c98a821STong Ho     g_assert_cmpuint(n, ==, cnt);
3981c98a821STong Ho 
3991c98a821STong Ho     if (memcmp(rng, prng, sizeof(rng))) {
4001c98a821STong Ho         TRNG_FAILED("Failed: PER_DISABLE != PER_STRNG_ALL_ZERO");
4011c98a821STong Ho     }
4021c98a821STong Ho 
4031c98a821STong Ho     /* #3: non-zero string should not match personalization disabled */
4041c98a821STong Ho     trng_load(R_TRNG_PER_STRNG_0, pers_str);
4051c98a821STong Ho     trng_reseed(prng_seed);
4061c98a821STong Ho 
4071c98a821STong Ho     trng_generate(true);
4081c98a821STong Ho     n = trng_collect(rng, cnt);
4091c98a821STong Ho     g_assert_cmpuint(n, ==, cnt);
4101c98a821STong Ho 
4111c98a821STong Ho     if (!memcmp(rng, prng, sizeof(rng))) {
4121c98a821STong Ho         TRNG_FAILED("Failed: PER_DISABLE == PER_STRNG_NON_ZERO");
4131c98a821STong Ho     }
4141c98a821STong Ho }
4151c98a821STong Ho 
trng_test_forced_prng(void)4161c98a821STong Ho static void trng_test_forced_prng(void)
4171c98a821STong Ho {
4181c98a821STong Ho     const char *prop = "forced-prng";
4191c98a821STong Ho     const uint64_t seed = 0xdeadbeefbad1bad0ULL;
4201c98a821STong Ho 
421*cabe58b0SPeter Maydell     const size_t cnt = TEST_DATA_WORDS;
422*cabe58b0SPeter Maydell     uint32_t rng[TEST_DATA_WORDS], prng[TEST_DATA_WORDS];
4231c98a821STong Ho     size_t n;
4241c98a821STong Ho 
4251c98a821STong Ho     trng_reset();
4261c98a821STong Ho     trng_test_set_uint_prop(prop, seed);
4271c98a821STong Ho 
4281c98a821STong Ho     /* TRNG run #1 */
4291c98a821STong Ho     trng_reset();
4301c98a821STong Ho     trng_reseed(NULL);
4311c98a821STong Ho     trng_generate(true);
4321c98a821STong Ho 
4331c98a821STong Ho     n = trng_collect(prng, cnt);
4341c98a821STong Ho     g_assert_cmpuint(n, ==, cnt);
4351c98a821STong Ho 
4361c98a821STong Ho     /* TRNG run #2 should match run #1 */
4371c98a821STong Ho     trng_reset();
4381c98a821STong Ho     trng_reseed(NULL);
4391c98a821STong Ho     trng_generate(true);
4401c98a821STong Ho 
4411c98a821STong Ho     n = trng_collect(rng, cnt);
4421c98a821STong Ho     g_assert_cmpuint(n, ==, cnt);
4431c98a821STong Ho 
4441c98a821STong Ho     if (memcmp(rng, prng, sizeof(rng))) {
4451c98a821STong Ho         TRNG_FAILED("Forced-prng test failed: results do not match");
4461c98a821STong Ho     }
4471c98a821STong Ho }
4481c98a821STong Ho 
trng_test_fault_events(void)4491c98a821STong Ho static void trng_test_fault_events(void)
4501c98a821STong Ho {
4511c98a821STong Ho     const char *prop = "fips-fault-events";
4521c98a821STong Ho 
4531c98a821STong Ho     trng_reset();
4541c98a821STong Ho 
4551c98a821STong Ho     /* Fault events only when TRSS is enabled */
4561c98a821STong Ho     trng_write(R_TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK);
4571c98a821STong Ho     trng_ctrl_set(TRNG_CTRL_TRSSEN_MASK);
4581c98a821STong Ho 
4591c98a821STong Ho     trng_test_set_uint_prop(prop, TRNG_STATUS_CERTF_MASK);
4601c98a821STong Ho     trng_check_certf_status();
4611c98a821STong Ho 
4621c98a821STong Ho     trng_test_set_uint_prop(prop, TRNG_STATUS_DTF_MASK);
4631c98a821STong Ho     trng_check_dtf_status();
4641c98a821STong Ho 
4651c98a821STong Ho     trng_reset();
4661c98a821STong Ho }
4671c98a821STong Ho 
main(int argc,char ** argv)4681c98a821STong Ho int main(int argc, char **argv)
4691c98a821STong Ho {
4701c98a821STong Ho     int rc;
4711c98a821STong Ho 
4721c98a821STong Ho     g_test_init(&argc, &argv, NULL);
4731c98a821STong Ho 
4741c98a821STong Ho     #define TRNG_TEST_ADD(n) \
4751c98a821STong Ho             qtest_add_func("/hw/misc/xlnx-versal-trng/" #n, trng_test_ ## n);
4761c98a821STong Ho     TRNG_TEST_ADD(autogen);
4771c98a821STong Ho     TRNG_TEST_ADD(oneshot);
4781c98a821STong Ho     TRNG_TEST_ADD(per_str);
4791c98a821STong Ho     TRNG_TEST_ADD(forced_prng);
4801c98a821STong Ho     TRNG_TEST_ADD(fault_events);
4811c98a821STong Ho     #undef TRNG_TEST_ADD
4821c98a821STong Ho 
4831c98a821STong Ho     trng_test_start();
4841c98a821STong Ho     rc = g_test_run();
4851c98a821STong Ho     trng_test_stop();
4861c98a821STong Ho 
4871c98a821STong Ho     return rc;
4881c98a821STong Ho }
489