2 * QTests for the Xilinx Versal True Random Number Generator device
4 * Copyright (c) 2023 Advanced Micro Devices, Inc.
6 * SPDX-License-Identifier: GPL-2.0-or-later
9 #include "qemu/osdep.h"
10 #include "libqtest-single.h"
13 #define TRNG_BASEADDR (0xf1230000)
16 #define R_TRNG_INT_CTRL (0x0000)
17 #define TRNG_INT_CTRL_CERTF_RST_MASK (1 << 5)
18 #define TRNG_INT_CTRL_DTF_RST_MASK (1 << 4)
19 #define TRNG_INT_CTRL_DONE_RST_MASK (1 << 3)
20 #define TRNG_INT_CTRL_CERTF_EN_MASK (1 << 2)
21 #define TRNG_INT_CTRL_DTF_EN_MASK (1 << 1)
22 #define TRNG_INT_CTRL_DONE_EN_MASK (1)
25 #define R_TRNG_STATUS (0x0004)
26 #define TRNG_STATUS_QCNT_SHIFT (9)
27 #define TRNG_STATUS_QCNT_MASK (7 << TRNG_STATUS_QCNT_SHIFT)
28 #define TRNG_STATUS_CERTF_MASK (1 << 3)
29 #define TRNG_STATUS_DTF_MASK (1 << 1)
30 #define TRNG_STATUS_DONE_MASK (1)
33 #define R_TRNG_CTRL (0x0008)
34 #define TRNG_CTRL_PERSODISABLE_MASK (1 << 10)
35 #define TRNG_CTRL_SINGLEGENMODE_MASK (1 << 9)
36 #define TRNG_CTRL_PRNGMODE_MASK (1 << 7)
37 #define TRNG_CTRL_TSTMODE_MASK (1 << 6)
38 #define TRNG_CTRL_PRNGSTART_MASK (1 << 5)
39 #define TRNG_CTRL_PRNGXS_MASK (1 << 3)
40 #define TRNG_CTRL_TRSSEN_MASK (1 << 2)
41 #define TRNG_CTRL_QERTUEN_MASK (1 << 1)
42 #define TRNG_CTRL_PRNGSRST_MASK (1)
44 /* TRNG_EXT_SEED_0 ... _11 */
45 #define R_TRNG_EXT_SEED_0 (0x0040)
46 #define R_TRNG_EXT_SEED_11 (R_TRNG_EXT_SEED_0 + 4 * 11)
48 /* TRNG_PER_STRNG_0 ... 11 */
49 #define R_TRNG_PER_STRNG_0 (0x0080)
50 #define R_TRNG_PER_STRNG_11 (R_TRNG_PER_STRNG_0 + 4 * 11)
52 /* TRNG_CORE_OUTPUT */
53 #define R_TRNG_CORE_OUTPUT (0x00c0)
56 #define R_TRNG_RESET (0x00d0)
57 #define TRNG_RESET_VAL_MASK (1)
60 #define R_TRNG_OSC_EN (0x00d4)
61 #define TRNG_OSC_EN_VAL_MASK (1)
63 /* TRNG_TRNG_ISR, _IMR, _IER, _IDR */
64 #define R_TRNG_ISR (0x00e0)
65 #define R_TRNG_IMR (0x00e4)
66 #define R_TRNG_IER (0x00e8)
67 #define R_TRNG_IDR (0x00ec)
68 #define TRNG_IRQ_SLVERR_MASK (1 << 1)
69 #define TRNG_IRQ_CORE_INT_MASK (1)
72 * End test with a formatted error message, by embedding the message
75 #define TRNG_FAILED(FMT, ...) \
77 g_autoptr(GError) err = g_error_new( \
78 g_quark_from_static_string(trng_qname), 0, \
79 FMT, ## __VA_ARGS__); \
80 g_assert_no_error(err); \
83 static const gchar trng_qname
[] = "xlnx-versal-trng-test";
85 static const uint32_t prng_seed
[12] = {
86 0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc,
87 0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98,
90 static const uint32_t pers_str
[12] = {
91 0x76543210, 0x87654321, 0x98765432, 0xa9876543, 0xba987654, 0xfedcba98,
92 0x01234567, 0x12345678, 0x23456789, 0x3456789a, 0x456789ab, 0x56789abc,
95 static void trng_test_start(void)
97 qtest_start("-machine xlnx-versal-virt");
100 static void trng_test_stop(void)
105 static void trng_test_set_uint_prop(const char *name
, uint64_t value
)
107 const char *path
= "/machine/xlnx-versal/trng";
110 response
= qmp("{ 'execute': 'qom-set',"
116 name
, (unsigned long long)value
);
117 g_assert(qdict_haskey(response
, "return"));
118 qobject_unref(response
);
121 static void trng_write(unsigned ra
, uint32_t val
)
123 writel(TRNG_BASEADDR
+ ra
, val
);
126 static uint32_t trng_read(unsigned ra
)
128 return readl(TRNG_BASEADDR
+ ra
);
131 static void trng_bit_set(unsigned ra
, uint32_t bits
)
133 trng_write(ra
, (trng_read(ra
) | bits
));
136 static void trng_bit_clr(unsigned ra
, uint32_t bits
)
138 trng_write(ra
, (trng_read(ra
) & ~bits
));
141 static void trng_ctrl_set(uint32_t bits
)
143 trng_bit_set(R_TRNG_CTRL
, bits
);
146 static void trng_ctrl_clr(uint32_t bits
)
148 trng_bit_clr(R_TRNG_CTRL
, bits
);
151 static uint32_t trng_status(void)
153 return trng_read(R_TRNG_STATUS
);
156 static unsigned trng_qcnt(void)
158 uint32_t sta
= trng_status();
160 return (sta
& TRNG_STATUS_QCNT_MASK
) >> TRNG_STATUS_QCNT_SHIFT
;
163 static const char *trng_info(void)
165 uint32_t sta
= trng_status();
166 uint32_t ctl
= trng_read(R_TRNG_CTRL
);
168 static char info
[64];
170 snprintf(info
, sizeof(info
), "; status=0x%x, ctrl=0x%x", sta
, ctl
);
174 static void trng_check_status(uint32_t status_mask
, const char *act
)
176 uint32_t clear_mask
= 0;
180 * Only selected bits are events in R_TRNG_STATUS, and
181 * clear them needs to go through R_INT_CTRL.
183 if (status_mask
& TRNG_STATUS_CERTF_MASK
) {
184 clear_mask
|= TRNG_INT_CTRL_CERTF_RST_MASK
;
186 if (status_mask
& TRNG_STATUS_DTF_MASK
) {
187 clear_mask
|= TRNG_INT_CTRL_DTF_RST_MASK
;
189 if (status_mask
& TRNG_STATUS_DONE_MASK
) {
190 clear_mask
|= TRNG_INT_CTRL_DONE_RST_MASK
;
193 status
= trng_status();
194 if ((status
& status_mask
) != status_mask
) {
195 TRNG_FAILED("%s: Status bitmask 0x%x failed to be 1%s",
196 act
, status_mask
, trng_info());
200 trng_bit_set(R_TRNG_INT_CTRL
, clear_mask
);
202 if (!!(trng_read(R_TRNG_STATUS
) & status_mask
)) {
203 TRNG_FAILED("%s: Event 0x%0x stuck at 1 after clear: %s",
204 act
, status_mask
, trng_info());
208 static void trng_check_done_status(const char *act
)
210 trng_check_status(TRNG_STATUS_DONE_MASK
, act
);
213 static void trng_check_dtf_status(void)
215 trng_check_status(TRNG_STATUS_DTF_MASK
, "DTF injection");
218 static void trng_check_certf_status(void)
220 trng_check_status(TRNG_STATUS_CERTF_MASK
, "CERTF injection");
223 static void trng_reset(void)
225 trng_write(R_TRNG_RESET
, TRNG_RESET_VAL_MASK
);
226 trng_write(R_TRNG_RESET
, 0);
229 static void trng_load(unsigned r0
, const uint32_t *b384
)
231 static const uint32_t zero
[12] = { 0 };
238 for (k
= 0; k
< 12; k
++) {
239 trng_write(r0
+ 4 * k
, b384
[k
]);
243 static void trng_reseed(const uint32_t *seed
)
248 ctl
= TRNG_CTRL_PRNGSTART_MASK
|
249 TRNG_CTRL_PRNGXS_MASK
|
250 TRNG_CTRL_TRSSEN_MASK
;
252 trng_ctrl_clr(ctl
| TRNG_CTRL_PRNGMODE_MASK
);
255 trng_load(R_TRNG_EXT_SEED_0
, seed
);
257 ctl
&= ~TRNG_CTRL_TRSSEN_MASK
;
259 trng_write(R_TRNG_OSC_EN
, TRNG_OSC_EN_VAL_MASK
);
261 ctl
&= ~TRNG_CTRL_PRNGXS_MASK
;
265 trng_check_done_status(act
);
266 trng_ctrl_clr(TRNG_CTRL_PRNGSTART_MASK
);
269 static void trng_generate(bool auto_enb
)
273 ctl
= TRNG_CTRL_PRNGSTART_MASK
| TRNG_CTRL_SINGLEGENMODE_MASK
;
277 ctl
&= ~TRNG_CTRL_SINGLEGENMODE_MASK
;
280 trng_ctrl_set(ctl
| TRNG_CTRL_PRNGMODE_MASK
);
282 trng_check_done_status("Generate");
283 g_assert(trng_qcnt() != 7);
286 static size_t trng_collect(uint32_t *rnd
, size_t cnt
)
290 for (i
= 0; i
< cnt
; i
++) {
291 if (trng_qcnt() == 0) {
295 rnd
[i
] = trng_read(R_TRNG_CORE_OUTPUT
);
301 /* These tests all generate 512 bits of random data with the device */
302 #define TEST_DATA_WORDS (512 / 32)
304 static void trng_test_autogen(void)
306 const size_t cnt
= TEST_DATA_WORDS
;
307 uint32_t rng
[TEST_DATA_WORDS
], prng
[TEST_DATA_WORDS
];
313 trng_reseed(prng_seed
);
316 n
= trng_collect(prng
, cnt
);
318 TRNG_FAILED("PRNG_1 Auto-gen test failed: expected = %u, got = %u",
319 (unsigned)cnt
, (unsigned)n
);
322 /* TRNG, should not match PRNG */
326 n
= trng_collect(rng
, cnt
);
328 TRNG_FAILED("TRNG Auto-gen test failed: expected = %u, got = %u",
329 (unsigned)cnt
, (unsigned)n
);
332 /* PRNG #2: should matches run #1 */
333 trng_reseed(prng_seed
);
336 n
= trng_collect(rng
, cnt
);
338 TRNG_FAILED("PRNG_2 Auto-gen test failed: expected = %u, got = %u",
339 (unsigned)cnt
, (unsigned)n
);
342 if (memcmp(rng
, prng
, sizeof(rng
))) {
343 TRNG_FAILED("PRNG_2 Auto-gen test failed: does not match PRNG_1");
347 static void trng_test_oneshot(void)
349 const size_t cnt
= TEST_DATA_WORDS
;
350 uint32_t rng
[TEST_DATA_WORDS
];
356 trng_reseed(prng_seed
);
357 trng_generate(false);
359 n
= trng_collect(rng
, cnt
);
361 TRNG_FAILED("PRNG_1 One-shot gen test failed");
364 /* TRNG, should not match PRNG */
366 trng_generate(false);
368 n
= trng_collect(rng
, cnt
);
370 TRNG_FAILED("TRNG One-shot test failed");
374 static void trng_test_per_str(void)
376 const size_t cnt
= TEST_DATA_WORDS
;
377 uint32_t rng
[TEST_DATA_WORDS
], prng
[TEST_DATA_WORDS
];
383 trng_ctrl_set(TRNG_CTRL_PERSODISABLE_MASK
);
384 trng_reseed(prng_seed
);
385 trng_ctrl_clr(TRNG_CTRL_PERSODISABLE_MASK
);
388 n
= trng_collect(prng
, cnt
);
389 g_assert_cmpuint(n
, ==, cnt
);
391 /* #2: zero string should match personalization disabled */
392 trng_load(R_TRNG_PER_STRNG_0
, NULL
);
393 trng_reseed(prng_seed
);
396 n
= trng_collect(rng
, cnt
);
397 g_assert_cmpuint(n
, ==, cnt
);
399 if (memcmp(rng
, prng
, sizeof(rng
))) {
400 TRNG_FAILED("Failed: PER_DISABLE != PER_STRNG_ALL_ZERO");
403 /* #3: non-zero string should not match personalization disabled */
404 trng_load(R_TRNG_PER_STRNG_0
, pers_str
);
405 trng_reseed(prng_seed
);
408 n
= trng_collect(rng
, cnt
);
409 g_assert_cmpuint(n
, ==, cnt
);
411 if (!memcmp(rng
, prng
, sizeof(rng
))) {
412 TRNG_FAILED("Failed: PER_DISABLE == PER_STRNG_NON_ZERO");
416 static void trng_test_forced_prng(void)
418 const char *prop
= "forced-prng";
419 const uint64_t seed
= 0xdeadbeefbad1bad0ULL
;
421 const size_t cnt
= TEST_DATA_WORDS
;
422 uint32_t rng
[TEST_DATA_WORDS
], prng
[TEST_DATA_WORDS
];
426 trng_test_set_uint_prop(prop
, seed
);
433 n
= trng_collect(prng
, cnt
);
434 g_assert_cmpuint(n
, ==, cnt
);
436 /* TRNG run #2 should match run #1 */
441 n
= trng_collect(rng
, cnt
);
442 g_assert_cmpuint(n
, ==, cnt
);
444 if (memcmp(rng
, prng
, sizeof(rng
))) {
445 TRNG_FAILED("Forced-prng test failed: results do not match");
449 static void trng_test_fault_events(void)
451 const char *prop
= "fips-fault-events";
455 /* Fault events only when TRSS is enabled */
456 trng_write(R_TRNG_OSC_EN
, TRNG_OSC_EN_VAL_MASK
);
457 trng_ctrl_set(TRNG_CTRL_TRSSEN_MASK
);
459 trng_test_set_uint_prop(prop
, TRNG_STATUS_CERTF_MASK
);
460 trng_check_certf_status();
462 trng_test_set_uint_prop(prop
, TRNG_STATUS_DTF_MASK
);
463 trng_check_dtf_status();
468 int main(int argc
, char **argv
)
472 g_test_init(&argc
, &argv
, NULL
);
474 #define TRNG_TEST_ADD(n) \
475 qtest_add_func("/hw/misc/xlnx-versal-trng/" #n, trng_test_ ## n);
476 TRNG_TEST_ADD(autogen
);
477 TRNG_TEST_ADD(oneshot
);
478 TRNG_TEST_ADD(per_str
);
479 TRNG_TEST_ADD(forced_prng
);
480 TRNG_TEST_ADD(fault_events
);