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 951c98a821STong Ho static void trng_test_start(void) 961c98a821STong Ho { 971c98a821STong Ho qtest_start("-machine xlnx-versal-virt"); 981c98a821STong Ho } 991c98a821STong Ho 1001c98a821STong Ho static void trng_test_stop(void) 1011c98a821STong Ho { 1021c98a821STong Ho qtest_end(); 1031c98a821STong Ho } 1041c98a821STong Ho 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 1211c98a821STong Ho static void trng_write(unsigned ra, uint32_t val) 1221c98a821STong Ho { 1231c98a821STong Ho writel(TRNG_BASEADDR + ra, val); 1241c98a821STong Ho } 1251c98a821STong Ho 1261c98a821STong Ho static uint32_t trng_read(unsigned ra) 1271c98a821STong Ho { 1281c98a821STong Ho return readl(TRNG_BASEADDR + ra); 1291c98a821STong Ho } 1301c98a821STong Ho 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 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 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 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 1511c98a821STong Ho static uint32_t trng_status(void) 1521c98a821STong Ho { 1531c98a821STong Ho return trng_read(R_TRNG_STATUS); 1541c98a821STong Ho } 1551c98a821STong Ho 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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