1*1c98a821STong Ho /* 2*1c98a821STong Ho * QTests for the Xilinx Versal True Random Number Generator device 3*1c98a821STong Ho * 4*1c98a821STong Ho * Copyright (c) 2023 Advanced Micro Devices, Inc. 5*1c98a821STong Ho * 6*1c98a821STong Ho * SPDX-License-Identifier: GPL-2.0-or-later 7*1c98a821STong Ho */ 8*1c98a821STong Ho 9*1c98a821STong Ho #include "qemu/osdep.h" 10*1c98a821STong Ho #include "libqtest-single.h" 11*1c98a821STong Ho 12*1c98a821STong Ho /* Base Address */ 13*1c98a821STong Ho #define TRNG_BASEADDR (0xf1230000) 14*1c98a821STong Ho 15*1c98a821STong Ho /* TRNG_INT_CTRL */ 16*1c98a821STong Ho #define R_TRNG_INT_CTRL (0x0000) 17*1c98a821STong Ho #define TRNG_INT_CTRL_CERTF_RST_MASK (1 << 5) 18*1c98a821STong Ho #define TRNG_INT_CTRL_DTF_RST_MASK (1 << 4) 19*1c98a821STong Ho #define TRNG_INT_CTRL_DONE_RST_MASK (1 << 3) 20*1c98a821STong Ho #define TRNG_INT_CTRL_CERTF_EN_MASK (1 << 2) 21*1c98a821STong Ho #define TRNG_INT_CTRL_DTF_EN_MASK (1 << 1) 22*1c98a821STong Ho #define TRNG_INT_CTRL_DONE_EN_MASK (1) 23*1c98a821STong Ho 24*1c98a821STong Ho /* TRNG_STATUS */ 25*1c98a821STong Ho #define R_TRNG_STATUS (0x0004) 26*1c98a821STong Ho #define TRNG_STATUS_QCNT_SHIFT (9) 27*1c98a821STong Ho #define TRNG_STATUS_QCNT_MASK (7 << TRNG_STATUS_QCNT_SHIFT) 28*1c98a821STong Ho #define TRNG_STATUS_CERTF_MASK (1 << 3) 29*1c98a821STong Ho #define TRNG_STATUS_DTF_MASK (1 << 1) 30*1c98a821STong Ho #define TRNG_STATUS_DONE_MASK (1) 31*1c98a821STong Ho 32*1c98a821STong Ho /* TRNG_CTRL */ 33*1c98a821STong Ho #define R_TRNG_CTRL (0x0008) 34*1c98a821STong Ho #define TRNG_CTRL_PERSODISABLE_MASK (1 << 10) 35*1c98a821STong Ho #define TRNG_CTRL_SINGLEGENMODE_MASK (1 << 9) 36*1c98a821STong Ho #define TRNG_CTRL_PRNGMODE_MASK (1 << 7) 37*1c98a821STong Ho #define TRNG_CTRL_TSTMODE_MASK (1 << 6) 38*1c98a821STong Ho #define TRNG_CTRL_PRNGSTART_MASK (1 << 5) 39*1c98a821STong Ho #define TRNG_CTRL_PRNGXS_MASK (1 << 3) 40*1c98a821STong Ho #define TRNG_CTRL_TRSSEN_MASK (1 << 2) 41*1c98a821STong Ho #define TRNG_CTRL_QERTUEN_MASK (1 << 1) 42*1c98a821STong Ho #define TRNG_CTRL_PRNGSRST_MASK (1) 43*1c98a821STong Ho 44*1c98a821STong Ho /* TRNG_EXT_SEED_0 ... _11 */ 45*1c98a821STong Ho #define R_TRNG_EXT_SEED_0 (0x0040) 46*1c98a821STong Ho #define R_TRNG_EXT_SEED_11 (R_TRNG_EXT_SEED_0 + 4 * 11) 47*1c98a821STong Ho 48*1c98a821STong Ho /* TRNG_PER_STRNG_0 ... 11 */ 49*1c98a821STong Ho #define R_TRNG_PER_STRNG_0 (0x0080) 50*1c98a821STong Ho #define R_TRNG_PER_STRNG_11 (R_TRNG_PER_STRNG_0 + 4 * 11) 51*1c98a821STong Ho 52*1c98a821STong Ho /* TRNG_CORE_OUTPUT */ 53*1c98a821STong Ho #define R_TRNG_CORE_OUTPUT (0x00c0) 54*1c98a821STong Ho 55*1c98a821STong Ho /* TRNG_RESET */ 56*1c98a821STong Ho #define R_TRNG_RESET (0x00d0) 57*1c98a821STong Ho #define TRNG_RESET_VAL_MASK (1) 58*1c98a821STong Ho 59*1c98a821STong Ho /* TRNG_OSC_EN */ 60*1c98a821STong Ho #define R_TRNG_OSC_EN (0x00d4) 61*1c98a821STong Ho #define TRNG_OSC_EN_VAL_MASK (1) 62*1c98a821STong Ho 63*1c98a821STong Ho /* TRNG_TRNG_ISR, _IMR, _IER, _IDR */ 64*1c98a821STong Ho #define R_TRNG_ISR (0x00e0) 65*1c98a821STong Ho #define R_TRNG_IMR (0x00e4) 66*1c98a821STong Ho #define R_TRNG_IER (0x00e8) 67*1c98a821STong Ho #define R_TRNG_IDR (0x00ec) 68*1c98a821STong Ho #define TRNG_IRQ_SLVERR_MASK (1 << 1) 69*1c98a821STong Ho #define TRNG_IRQ_CORE_INT_MASK (1) 70*1c98a821STong Ho 71*1c98a821STong Ho /* 72*1c98a821STong Ho * End test with a formatted error message, by embedding the message 73*1c98a821STong Ho * in a GError. 74*1c98a821STong Ho */ 75*1c98a821STong Ho #define TRNG_FAILED(FMT, ...) \ 76*1c98a821STong Ho do { \ 77*1c98a821STong Ho g_autoptr(GError) err = g_error_new( \ 78*1c98a821STong Ho g_quark_from_static_string(trng_qname), 0, \ 79*1c98a821STong Ho FMT, ## __VA_ARGS__); \ 80*1c98a821STong Ho g_assert_no_error(err); \ 81*1c98a821STong Ho } while (0) 82*1c98a821STong Ho 83*1c98a821STong Ho static const gchar trng_qname[] = "xlnx-versal-trng-test"; 84*1c98a821STong Ho 85*1c98a821STong Ho static const uint32_t prng_seed[12] = { 86*1c98a821STong Ho 0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc, 87*1c98a821STong Ho 0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98, 88*1c98a821STong Ho }; 89*1c98a821STong Ho 90*1c98a821STong Ho static const uint32_t pers_str[12] = { 91*1c98a821STong Ho 0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98, 92*1c98a821STong Ho 0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc, 93*1c98a821STong Ho }; 94*1c98a821STong Ho 95*1c98a821STong Ho static void trng_test_start(void) 96*1c98a821STong Ho { 97*1c98a821STong Ho qtest_start("-machine xlnx-versal-virt"); 98*1c98a821STong Ho } 99*1c98a821STong Ho 100*1c98a821STong Ho static void trng_test_stop(void) 101*1c98a821STong Ho { 102*1c98a821STong Ho qtest_end(); 103*1c98a821STong Ho } 104*1c98a821STong Ho 105*1c98a821STong Ho static void trng_test_set_uint_prop(const char *name, uint64_t value) 106*1c98a821STong Ho { 107*1c98a821STong Ho const char *path = "/machine/xlnx-versal/trng"; 108*1c98a821STong Ho QDict *response; 109*1c98a821STong Ho 110*1c98a821STong Ho response = qmp("{ 'execute': 'qom-set'," 111*1c98a821STong Ho " 'arguments': {" 112*1c98a821STong Ho " 'path': %s," 113*1c98a821STong Ho " 'property': %s," 114*1c98a821STong Ho " 'value': %llu" 115*1c98a821STong Ho "} }", path, 116*1c98a821STong Ho name, (unsigned long long)value); 117*1c98a821STong Ho g_assert(qdict_haskey(response, "return")); 118*1c98a821STong Ho qobject_unref(response); 119*1c98a821STong Ho } 120*1c98a821STong Ho 121*1c98a821STong Ho static void trng_write(unsigned ra, uint32_t val) 122*1c98a821STong Ho { 123*1c98a821STong Ho writel(TRNG_BASEADDR + ra, val); 124*1c98a821STong Ho } 125*1c98a821STong Ho 126*1c98a821STong Ho static uint32_t trng_read(unsigned ra) 127*1c98a821STong Ho { 128*1c98a821STong Ho return readl(TRNG_BASEADDR + ra); 129*1c98a821STong Ho } 130*1c98a821STong Ho 131*1c98a821STong Ho static void trng_bit_set(unsigned ra, uint32_t bits) 132*1c98a821STong Ho { 133*1c98a821STong Ho trng_write(ra, (trng_read(ra) | bits)); 134*1c98a821STong Ho } 135*1c98a821STong Ho 136*1c98a821STong Ho static void trng_bit_clr(unsigned ra, uint32_t bits) 137*1c98a821STong Ho { 138*1c98a821STong Ho trng_write(ra, (trng_read(ra) & ~bits)); 139*1c98a821STong Ho } 140*1c98a821STong Ho 141*1c98a821STong Ho static void trng_ctrl_set(uint32_t bits) 142*1c98a821STong Ho { 143*1c98a821STong Ho trng_bit_set(R_TRNG_CTRL, bits); 144*1c98a821STong Ho } 145*1c98a821STong Ho 146*1c98a821STong Ho static void trng_ctrl_clr(uint32_t bits) 147*1c98a821STong Ho { 148*1c98a821STong Ho trng_bit_clr(R_TRNG_CTRL, bits); 149*1c98a821STong Ho } 150*1c98a821STong Ho 151*1c98a821STong Ho static uint32_t trng_status(void) 152*1c98a821STong Ho { 153*1c98a821STong Ho return trng_read(R_TRNG_STATUS); 154*1c98a821STong Ho } 155*1c98a821STong Ho 156*1c98a821STong Ho static unsigned trng_qcnt(void) 157*1c98a821STong Ho { 158*1c98a821STong Ho uint32_t sta = trng_status(); 159*1c98a821STong Ho 160*1c98a821STong Ho return (sta & TRNG_STATUS_QCNT_MASK) >> TRNG_STATUS_QCNT_SHIFT; 161*1c98a821STong Ho } 162*1c98a821STong Ho 163*1c98a821STong Ho static const char *trng_info(void) 164*1c98a821STong Ho { 165*1c98a821STong Ho uint32_t sta = trng_status(); 166*1c98a821STong Ho uint32_t ctl = trng_read(R_TRNG_CTRL); 167*1c98a821STong Ho 168*1c98a821STong Ho static char info[64]; 169*1c98a821STong Ho 170*1c98a821STong Ho snprintf(info, sizeof(info), "; status=0x%x, ctrl=0x%x", sta, ctl); 171*1c98a821STong Ho return info; 172*1c98a821STong Ho } 173*1c98a821STong Ho 174*1c98a821STong Ho static void trng_check_status(uint32_t status_mask, const char *act) 175*1c98a821STong Ho { 176*1c98a821STong Ho uint32_t clear_mask = 0; 177*1c98a821STong Ho uint32_t status; 178*1c98a821STong Ho 179*1c98a821STong Ho /* 180*1c98a821STong Ho * Only selected bits are events in R_TRNG_STATUS, and 181*1c98a821STong Ho * clear them needs to go through R_INT_CTRL. 182*1c98a821STong Ho */ 183*1c98a821STong Ho if (status_mask & TRNG_STATUS_CERTF_MASK) { 184*1c98a821STong Ho clear_mask |= TRNG_INT_CTRL_CERTF_RST_MASK; 185*1c98a821STong Ho } 186*1c98a821STong Ho if (status_mask & TRNG_STATUS_DTF_MASK) { 187*1c98a821STong Ho clear_mask |= TRNG_INT_CTRL_DTF_RST_MASK; 188*1c98a821STong Ho } 189*1c98a821STong Ho if (status_mask & TRNG_STATUS_DONE_MASK) { 190*1c98a821STong Ho clear_mask |= TRNG_INT_CTRL_DONE_RST_MASK; 191*1c98a821STong Ho } 192*1c98a821STong Ho 193*1c98a821STong Ho status = trng_status(); 194*1c98a821STong Ho if ((status & status_mask) != status_mask) { 195*1c98a821STong Ho TRNG_FAILED("%s: Status bitmask 0x%x failed to be 1%s", 196*1c98a821STong Ho act, status_mask, trng_info()); 197*1c98a821STong Ho } 198*1c98a821STong Ho 199*1c98a821STong Ho /* Remove event */ 200*1c98a821STong Ho trng_bit_set(R_TRNG_INT_CTRL, clear_mask); 201*1c98a821STong Ho 202*1c98a821STong Ho if (!!(trng_read(R_TRNG_STATUS) & status_mask)) { 203*1c98a821STong Ho TRNG_FAILED("%s: Event 0x%0x stuck at 1 after clear: %s", 204*1c98a821STong Ho act, status_mask, trng_info()); 205*1c98a821STong Ho } 206*1c98a821STong Ho } 207*1c98a821STong Ho 208*1c98a821STong Ho static void trng_check_done_status(const char *act) 209*1c98a821STong Ho { 210*1c98a821STong Ho trng_check_status(TRNG_STATUS_DONE_MASK, act); 211*1c98a821STong Ho } 212*1c98a821STong Ho 213*1c98a821STong Ho static void trng_check_dtf_status(void) 214*1c98a821STong Ho { 215*1c98a821STong Ho trng_check_status(TRNG_STATUS_DTF_MASK, "DTF injection"); 216*1c98a821STong Ho } 217*1c98a821STong Ho 218*1c98a821STong Ho static void trng_check_certf_status(void) 219*1c98a821STong Ho { 220*1c98a821STong Ho trng_check_status(TRNG_STATUS_CERTF_MASK, "CERTF injection"); 221*1c98a821STong Ho } 222*1c98a821STong Ho 223*1c98a821STong Ho static void trng_reset(void) 224*1c98a821STong Ho { 225*1c98a821STong Ho trng_write(R_TRNG_RESET, TRNG_RESET_VAL_MASK); 226*1c98a821STong Ho trng_write(R_TRNG_RESET, 0); 227*1c98a821STong Ho } 228*1c98a821STong Ho 229*1c98a821STong Ho static void trng_load(unsigned r0, const uint32_t *b384) 230*1c98a821STong Ho { 231*1c98a821STong Ho static const uint32_t zero[12] = { 0 }; 232*1c98a821STong Ho unsigned k; 233*1c98a821STong Ho 234*1c98a821STong Ho if (!b384) { 235*1c98a821STong Ho b384 = zero; 236*1c98a821STong Ho } 237*1c98a821STong Ho 238*1c98a821STong Ho for (k = 0; k < 12; k++) { 239*1c98a821STong Ho trng_write(r0 + 4 * k, b384[k]); 240*1c98a821STong Ho } 241*1c98a821STong Ho } 242*1c98a821STong Ho 243*1c98a821STong Ho static void trng_reseed(const uint32_t *seed) 244*1c98a821STong Ho { 245*1c98a821STong Ho const char *act; 246*1c98a821STong Ho uint32_t ctl; 247*1c98a821STong Ho 248*1c98a821STong Ho ctl = TRNG_CTRL_PRNGSTART_MASK | 249*1c98a821STong Ho TRNG_CTRL_PRNGXS_MASK | 250*1c98a821STong Ho TRNG_CTRL_TRSSEN_MASK; 251*1c98a821STong Ho 252*1c98a821STong Ho trng_ctrl_clr(ctl | TRNG_CTRL_PRNGMODE_MASK); 253*1c98a821STong Ho 254*1c98a821STong Ho if (seed) { 255*1c98a821STong Ho trng_load(R_TRNG_EXT_SEED_0, seed); 256*1c98a821STong Ho act = "Reseed PRNG"; 257*1c98a821STong Ho ctl &= ~TRNG_CTRL_TRSSEN_MASK; 258*1c98a821STong Ho } else { 259*1c98a821STong Ho trng_write(R_TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK); 260*1c98a821STong Ho act = "Reseed TRNG"; 261*1c98a821STong Ho ctl &= ~TRNG_CTRL_PRNGXS_MASK; 262*1c98a821STong Ho } 263*1c98a821STong Ho 264*1c98a821STong Ho trng_ctrl_set(ctl); 265*1c98a821STong Ho trng_check_done_status(act); 266*1c98a821STong Ho trng_ctrl_clr(TRNG_CTRL_PRNGSTART_MASK); 267*1c98a821STong Ho } 268*1c98a821STong Ho 269*1c98a821STong Ho static void trng_generate(bool auto_enb) 270*1c98a821STong Ho { 271*1c98a821STong Ho uint32_t ctl; 272*1c98a821STong Ho 273*1c98a821STong Ho ctl = TRNG_CTRL_PRNGSTART_MASK | TRNG_CTRL_SINGLEGENMODE_MASK; 274*1c98a821STong Ho trng_ctrl_clr(ctl); 275*1c98a821STong Ho 276*1c98a821STong Ho if (auto_enb) { 277*1c98a821STong Ho ctl &= ~TRNG_CTRL_SINGLEGENMODE_MASK; 278*1c98a821STong Ho } 279*1c98a821STong Ho 280*1c98a821STong Ho trng_ctrl_set(ctl | TRNG_CTRL_PRNGMODE_MASK); 281*1c98a821STong Ho 282*1c98a821STong Ho trng_check_done_status("Generate"); 283*1c98a821STong Ho g_assert(trng_qcnt() != 7); 284*1c98a821STong Ho } 285*1c98a821STong Ho 286*1c98a821STong Ho static size_t trng_collect(uint32_t *rnd, size_t cnt) 287*1c98a821STong Ho { 288*1c98a821STong Ho size_t i; 289*1c98a821STong Ho 290*1c98a821STong Ho for (i = 0; i < cnt; i++) { 291*1c98a821STong Ho if (trng_qcnt() == 0) { 292*1c98a821STong Ho return i; 293*1c98a821STong Ho } 294*1c98a821STong Ho 295*1c98a821STong Ho rnd[i] = trng_read(R_TRNG_CORE_OUTPUT); 296*1c98a821STong Ho } 297*1c98a821STong Ho 298*1c98a821STong Ho return i; 299*1c98a821STong Ho } 300*1c98a821STong Ho 301*1c98a821STong Ho static void trng_test_autogen(void) 302*1c98a821STong Ho { 303*1c98a821STong Ho const size_t cnt = 512 / 32; 304*1c98a821STong Ho uint32_t rng[cnt], prng[cnt]; 305*1c98a821STong Ho size_t n; 306*1c98a821STong Ho 307*1c98a821STong Ho trng_reset(); 308*1c98a821STong Ho 309*1c98a821STong Ho /* PRNG run #1 */ 310*1c98a821STong Ho trng_reseed(prng_seed); 311*1c98a821STong Ho trng_generate(true); 312*1c98a821STong Ho 313*1c98a821STong Ho n = trng_collect(prng, cnt); 314*1c98a821STong Ho if (n != cnt) { 315*1c98a821STong Ho TRNG_FAILED("PRNG_1 Auto-gen test failed: expected = %u, got = %u", 316*1c98a821STong Ho (unsigned)cnt, (unsigned)n); 317*1c98a821STong Ho } 318*1c98a821STong Ho 319*1c98a821STong Ho /* TRNG, should not match PRNG */ 320*1c98a821STong Ho trng_reseed(NULL); 321*1c98a821STong Ho trng_generate(true); 322*1c98a821STong Ho 323*1c98a821STong Ho n = trng_collect(rng, cnt); 324*1c98a821STong Ho if (n != cnt) { 325*1c98a821STong Ho TRNG_FAILED("TRNG Auto-gen test failed: expected = %u, got = %u", 326*1c98a821STong Ho (unsigned)cnt, (unsigned)n); 327*1c98a821STong Ho } 328*1c98a821STong Ho 329*1c98a821STong Ho /* PRNG #2: should matches run #1 */ 330*1c98a821STong Ho trng_reseed(prng_seed); 331*1c98a821STong Ho trng_generate(true); 332*1c98a821STong Ho 333*1c98a821STong Ho n = trng_collect(rng, cnt); 334*1c98a821STong Ho if (n != cnt) { 335*1c98a821STong Ho TRNG_FAILED("PRNG_2 Auto-gen test failed: expected = %u, got = %u", 336*1c98a821STong Ho (unsigned)cnt, (unsigned)n); 337*1c98a821STong Ho } 338*1c98a821STong Ho 339*1c98a821STong Ho if (memcmp(rng, prng, sizeof(rng))) { 340*1c98a821STong Ho TRNG_FAILED("PRNG_2 Auto-gen test failed: does not match PRNG_1"); 341*1c98a821STong Ho } 342*1c98a821STong Ho } 343*1c98a821STong Ho 344*1c98a821STong Ho static void trng_test_oneshot(void) 345*1c98a821STong Ho { 346*1c98a821STong Ho const size_t cnt = 512 / 32; 347*1c98a821STong Ho uint32_t rng[cnt]; 348*1c98a821STong Ho size_t n; 349*1c98a821STong Ho 350*1c98a821STong Ho trng_reset(); 351*1c98a821STong Ho 352*1c98a821STong Ho /* PRNG run #1 */ 353*1c98a821STong Ho trng_reseed(prng_seed); 354*1c98a821STong Ho trng_generate(false); 355*1c98a821STong Ho 356*1c98a821STong Ho n = trng_collect(rng, cnt); 357*1c98a821STong Ho if (n == cnt) { 358*1c98a821STong Ho TRNG_FAILED("PRNG_1 One-shot gen test failed"); 359*1c98a821STong Ho } 360*1c98a821STong Ho 361*1c98a821STong Ho /* TRNG, should not match PRNG */ 362*1c98a821STong Ho trng_reseed(NULL); 363*1c98a821STong Ho trng_generate(false); 364*1c98a821STong Ho 365*1c98a821STong Ho n = trng_collect(rng, cnt); 366*1c98a821STong Ho if (n == cnt) { 367*1c98a821STong Ho TRNG_FAILED("TRNG One-shot test failed"); 368*1c98a821STong Ho } 369*1c98a821STong Ho } 370*1c98a821STong Ho 371*1c98a821STong Ho static void trng_test_per_str(void) 372*1c98a821STong Ho { 373*1c98a821STong Ho const size_t cnt = 512 / 32; 374*1c98a821STong Ho uint32_t rng[cnt], prng[cnt]; 375*1c98a821STong Ho size_t n; 376*1c98a821STong Ho 377*1c98a821STong Ho trng_reset(); 378*1c98a821STong Ho 379*1c98a821STong Ho /* #1: disabled */ 380*1c98a821STong Ho trng_ctrl_set(TRNG_CTRL_PERSODISABLE_MASK); 381*1c98a821STong Ho trng_reseed(prng_seed); 382*1c98a821STong Ho trng_ctrl_clr(TRNG_CTRL_PERSODISABLE_MASK); 383*1c98a821STong Ho 384*1c98a821STong Ho trng_generate(true); 385*1c98a821STong Ho n = trng_collect(prng, cnt); 386*1c98a821STong Ho g_assert_cmpuint(n, ==, cnt); 387*1c98a821STong Ho 388*1c98a821STong Ho /* #2: zero string should match personalization disabled */ 389*1c98a821STong Ho trng_load(R_TRNG_PER_STRNG_0, NULL); 390*1c98a821STong Ho trng_reseed(prng_seed); 391*1c98a821STong Ho 392*1c98a821STong Ho trng_generate(true); 393*1c98a821STong Ho n = trng_collect(rng, cnt); 394*1c98a821STong Ho g_assert_cmpuint(n, ==, cnt); 395*1c98a821STong Ho 396*1c98a821STong Ho if (memcmp(rng, prng, sizeof(rng))) { 397*1c98a821STong Ho TRNG_FAILED("Failed: PER_DISABLE != PER_STRNG_ALL_ZERO"); 398*1c98a821STong Ho } 399*1c98a821STong Ho 400*1c98a821STong Ho /* #3: non-zero string should not match personalization disabled */ 401*1c98a821STong Ho trng_load(R_TRNG_PER_STRNG_0, pers_str); 402*1c98a821STong Ho trng_reseed(prng_seed); 403*1c98a821STong Ho 404*1c98a821STong Ho trng_generate(true); 405*1c98a821STong Ho n = trng_collect(rng, cnt); 406*1c98a821STong Ho g_assert_cmpuint(n, ==, cnt); 407*1c98a821STong Ho 408*1c98a821STong Ho if (!memcmp(rng, prng, sizeof(rng))) { 409*1c98a821STong Ho TRNG_FAILED("Failed: PER_DISABLE == PER_STRNG_NON_ZERO"); 410*1c98a821STong Ho } 411*1c98a821STong Ho } 412*1c98a821STong Ho 413*1c98a821STong Ho static void trng_test_forced_prng(void) 414*1c98a821STong Ho { 415*1c98a821STong Ho const char *prop = "forced-prng"; 416*1c98a821STong Ho const uint64_t seed = 0xdeadbeefbad1bad0ULL; 417*1c98a821STong Ho 418*1c98a821STong Ho const size_t cnt = 512 / 32; 419*1c98a821STong Ho uint32_t rng[cnt], prng[cnt]; 420*1c98a821STong Ho size_t n; 421*1c98a821STong Ho 422*1c98a821STong Ho trng_reset(); 423*1c98a821STong Ho trng_test_set_uint_prop(prop, seed); 424*1c98a821STong Ho 425*1c98a821STong Ho /* TRNG run #1 */ 426*1c98a821STong Ho trng_reset(); 427*1c98a821STong Ho trng_reseed(NULL); 428*1c98a821STong Ho trng_generate(true); 429*1c98a821STong Ho 430*1c98a821STong Ho n = trng_collect(prng, cnt); 431*1c98a821STong Ho g_assert_cmpuint(n, ==, cnt); 432*1c98a821STong Ho 433*1c98a821STong Ho /* TRNG run #2 should match run #1 */ 434*1c98a821STong Ho trng_reset(); 435*1c98a821STong Ho trng_reseed(NULL); 436*1c98a821STong Ho trng_generate(true); 437*1c98a821STong Ho 438*1c98a821STong Ho n = trng_collect(rng, cnt); 439*1c98a821STong Ho g_assert_cmpuint(n, ==, cnt); 440*1c98a821STong Ho 441*1c98a821STong Ho if (memcmp(rng, prng, sizeof(rng))) { 442*1c98a821STong Ho TRNG_FAILED("Forced-prng test failed: results do not match"); 443*1c98a821STong Ho } 444*1c98a821STong Ho } 445*1c98a821STong Ho 446*1c98a821STong Ho static void trng_test_fault_events(void) 447*1c98a821STong Ho { 448*1c98a821STong Ho const char *prop = "fips-fault-events"; 449*1c98a821STong Ho 450*1c98a821STong Ho trng_reset(); 451*1c98a821STong Ho 452*1c98a821STong Ho /* Fault events only when TRSS is enabled */ 453*1c98a821STong Ho trng_write(R_TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK); 454*1c98a821STong Ho trng_ctrl_set(TRNG_CTRL_TRSSEN_MASK); 455*1c98a821STong Ho 456*1c98a821STong Ho trng_test_set_uint_prop(prop, TRNG_STATUS_CERTF_MASK); 457*1c98a821STong Ho trng_check_certf_status(); 458*1c98a821STong Ho 459*1c98a821STong Ho trng_test_set_uint_prop(prop, TRNG_STATUS_DTF_MASK); 460*1c98a821STong Ho trng_check_dtf_status(); 461*1c98a821STong Ho 462*1c98a821STong Ho trng_reset(); 463*1c98a821STong Ho } 464*1c98a821STong Ho 465*1c98a821STong Ho int main(int argc, char **argv) 466*1c98a821STong Ho { 467*1c98a821STong Ho int rc; 468*1c98a821STong Ho 469*1c98a821STong Ho g_test_init(&argc, &argv, NULL); 470*1c98a821STong Ho 471*1c98a821STong Ho #define TRNG_TEST_ADD(n) \ 472*1c98a821STong Ho qtest_add_func("/hw/misc/xlnx-versal-trng/" #n, trng_test_ ## n); 473*1c98a821STong Ho TRNG_TEST_ADD(autogen); 474*1c98a821STong Ho TRNG_TEST_ADD(oneshot); 475*1c98a821STong Ho TRNG_TEST_ADD(per_str); 476*1c98a821STong Ho TRNG_TEST_ADD(forced_prng); 477*1c98a821STong Ho TRNG_TEST_ADD(fault_events); 478*1c98a821STong Ho #undef TRNG_TEST_ADD 479*1c98a821STong Ho 480*1c98a821STong Ho trng_test_start(); 481*1c98a821STong Ho rc = g_test_run(); 482*1c98a821STong Ho trng_test_stop(); 483*1c98a821STong Ho 484*1c98a821STong Ho return rc; 485*1c98a821STong Ho } 486