xref: /qemu/tests/qtest/xlnx-versal-trng-test.c (revision 1c98a821a2b3620c516f3da0d74719ed6f33bced)
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