blob: e1725f021713c0b6263ea8d1c5ec6a694b1c54c7 [file] [log] [blame]
Mark Dykese7810b52020-06-03 15:46:55 -05001/*
mardyk017b51dbe2024-01-17 15:25:36 -06002 * Copyright (c) 2024, Arm Limited. All rights reserved.
Mark Dykese7810b52020-06-03 15:46:55 -05003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
Mark Dykes50297972024-03-15 12:49:22 -05007#include "fifo3d.h"
8#include "nfifo.h"
9
Mark Dykese7810b52020-06-03 15:46:55 -050010#include <arch_helpers.h>
11#include <debug.h>
12#include <drivers/arm/private_timer.h>
13#include <events.h>
Mark Dykese7810b52020-06-03 15:46:55 -050014#include <libfdt.h>
mardyk01c14e4ad2023-10-11 16:50:19 -050015#include <plat_topology.h>
16#include <power_management.h>
Mark Dykese7810b52020-06-03 15:46:55 -050017#include <tftf_lib.h>
Mark Dykese7810b52020-06-03 15:46:55 -050018
Mark Dykes50297972024-03-15 12:49:22 -050019
Mark Dykese7810b52020-06-03 15:46:55 -050020extern char _binary___dtb_start[];
Mark Dykes50297972024-03-15 12:49:22 -050021extern void runtestfunction(int funcid, struct memmod *mmod);
22extern void init_input_arg_struct(void);
Mark Dykese7810b52020-06-03 15:46:55 -050023
24struct memmod tmod __aligned(65536) __section("smcfuzz");
mardyk01c14e4ad2023-10-11 16:50:19 -050025static int cntndarray;
26static struct rand_smc_node *ndarray;
27static struct memmod *mmod;
Mark Dykese7810b52020-06-03 15:46:55 -050028
29/*
30 * switch to use either standard C malloc or custom SMC malloc
31 */
32
33#define FIRST_NODE_DEVTREE_OFFSET (8)
34
35#ifdef SMC_FUZZ_TMALLOC
36#define GENMALLOC(x) malloc((x))
37#define GENFREE(x) free((x))
38#else
39#define GENMALLOC(x) smcmalloc((x), mmod)
40#define GENFREE(x) smcfree((x), mmod)
41#endif
42
43/*
44 * Device tree parameter struct
45 */
46
47struct fdt_header_sf {
48 unsigned int magic;
49 unsigned int totalsize;
50 unsigned int off_dt_struct;
51 unsigned int off_dt_strings;
52 unsigned int off_mem_rsvmap;
53 unsigned int version;
54 unsigned int last_comp_version;
55 unsigned int boot_cpuid_phys;
56 unsigned int size_dt_strings;
57 unsigned int size_dt_struct;
58};
59
60/*
61 * Structure to read the fields of the device tree
62 */
63struct propval {
64 unsigned int len;
65 unsigned int nameoff;
66};
67
68/*
69 * Converting from big endian to little endian to read values
70 * of device tree
71 */
72unsigned int lendconv(unsigned int val)
73{
74 unsigned int res;
75
76 res = val << 24;
77 res |= ((val << 8) & 0xFF0000U);
78 res |= ((val >> 8) & 0xFF00U);
79 res |= ((val >> 24) & 0xFFU);
80 return res;
81}
82
83/*
84 * Function to read strings from device tree
85 */
86void pullstringdt(void **dtb,
87 void *dtb_beg,
88 unsigned int offset,
89 char *cset)
90{
91 int fistr;
92 int cntchr;
93 char rval;
94
95 if (offset != 0U) {
96 *dtb = dtb_beg + offset;
97 }
98 fistr = 0;
99
100 cntchr = 0;
101 while (fistr == 0) {
102 rval = *((char *)*dtb);
103 *dtb += sizeof(char);
104 cset[cntchr] = rval;
105 if (cset[cntchr] == 0) {
106 fistr = 1;
107 }
108 cntchr++;
109 }
110
111 if ((cntchr % 4) != 0) {
112 for (unsigned int i = 0U; (int)i < (4 - (cntchr % 4)); i++) {
113 *dtb += sizeof(char);
114 }
115 }
116}
117
118/*
119 * Structure for Node information extracted from device tree
120 */
121struct rand_smc_node {
122 int *biases; // Biases of the individual nodes
123 int *biasarray; // Array of biases across all nodes
124 char **snames; // String that is unique to the SMC call called in test
mardyk017b51dbe2024-01-17 15:25:36 -0600125 int *snameid; // ID that is unique to the SMC call called in test
Mark Dykese7810b52020-06-03 15:46:55 -0500126 struct rand_smc_node *treenodes; // Selection of nodes that are farther down in the tree
mardyk017b51dbe2024-01-17 15:25:36 -0600127 // that reference further rand_smc_node objects
Mark Dykese7810b52020-06-03 15:46:55 -0500128 int *norcall; // Specifies whether a particular node is a leaf node or tree node
mardyk017b51dbe2024-01-17 15:25:36 -0600129 int entries; // Number of nodes in object
130 int biasent; // Number that gives the total number of entries in biasarray
131 // based on all biases of the nodes
132 char **nname; // Array of node names
Mark Dykese7810b52020-06-03 15:46:55 -0500133};
134
135
136/*
137 * Create bias tree from given device tree description
138 */
139
140struct rand_smc_node *createsmctree(int *casz,
141 struct memmod *mmod)
142{
143 void *dtb;
144 void *dtb_pn;
145 void *dtb_beg;
146 struct fdt_header fhd;
147 unsigned int rval;
148 struct propval pv;
149 char cset[MAX_NAME_CHARS];
150 char nodename[MAX_NAME_CHARS];
151 int dtdone;
152 struct fifo3d f3d;
153 int leafnode = 0;
154 unsigned int fnode = 0U;
155 unsigned int bias_count = 0U;
156 unsigned int bintnode = 0U;
157 unsigned int treenodetrack = 0U;
158 struct fdt_header *fhdptr;
159 struct rand_smc_node *ndarray = NULL;
160 int cntndarray;
161 struct rand_smc_node nrnode;
162 struct rand_smc_node *tndarray;
mardyk017b51dbe2024-01-17 15:25:36 -0600163 struct nfifo nf;
164
165 nfifoinit(&nf, mmod);
Mark Dykese7810b52020-06-03 15:46:55 -0500166
167 f3d.col = 0;
168 f3d.curr_col = 0;
169
170 /*
171 * Read device tree header and check for valid type
172 */
173
174 fhdptr = (struct fdt_header *)_binary___dtb_start;
175
Mark Dykese7810b52020-06-03 15:46:55 -0500176 fhd = *fhdptr;
177 cntndarray = 0;
178 nrnode.entries = 0;
179
180 /*
181 * Create pointers to device tree data
182 */
183 dtb = _binary___dtb_start;
184 dtb_pn = _binary___dtb_start;
185
186 dtb_beg = dtb;
187 fhd = *((struct fdt_header *)dtb);
188 dtb += (fdt32_to_cpu(fhd.off_dt_struct) + FIRST_NODE_DEVTREE_OFFSET);
189 dtdone = 0;
190
191 /*
192 * Reading device tree file
193 */
194 while (dtdone == 0) {
195 rval = *((unsigned int *)dtb);
196 dtb += sizeof(unsigned int);
197
198 /*
199 * Reading node name from device tree and pushing it into the raw data
200 * Table of possible values reading from device tree binary file:
201 * 1 New node found within current tree, possible leaf or tree variant
202 * 2 Node termination of current hiearchy.
203 * Could indicate end of tree or preparation for another branch
204 * 3 Leaf node indication where a bias with a function name should be
205 * found for the current node
206 * 9 End of device tree file and we end the read of the bias tree
207 */
208 if (fdt32_to_cpu(rval) == 1) {
209 pullstringdt(&dtb, dtb_beg, 0U, cset);
210 push_3dfifo_col(&f3d, cset, mmod);
211 strlcpy(nodename, cset, MAX_NAME_CHARS);
212
213 /*
214 * Error checking to make sure that bias is specified
215 */
216 if (fnode == 0U) {
217 fnode = 1U;
218 } else {
219 if (!((fnode == 1U) && (bias_count == 1U))) {
220 printf("ERROR: Did not find bias or multiple bias ");
221 printf("designations before %s %u %u\n",
222 cset, fnode, bias_count);
223 }
224 bias_count = 0U;
225 }
226 }
227
228 /*
229 * Reading node parameters of bias and function name
230 */
231 if (fdt32_to_cpu(rval) == 3) {
232 pv = *((struct propval *)dtb);
233 dtb += sizeof(struct propval);
234 pullstringdt(&dtb_pn, dtb_beg,
235 (fdt32_to_cpu(fhd.off_dt_strings) +
236 fdt32_to_cpu(pv.nameoff)), cset);
237 if (strcmp(cset, "bias") == 0) {
Mark Dykes50297972024-03-15 12:49:22 -0500238 unsigned int bval = *((unsigned int *)dtb);
Mark Dykese7810b52020-06-03 15:46:55 -0500239 dtb += sizeof(unsigned int);
Mark Dykes50297972024-03-15 12:49:22 -0500240 push_3dfifo_bias(&f3d, fdt32_to_cpu(bval));
Mark Dykese7810b52020-06-03 15:46:55 -0500241 bias_count++;
242 if (bintnode == 1U) {
243 fnode = 0U;
244 bintnode = 0U;
245 bias_count = 0U;
246 }
247 }
248 if (strcmp(cset, "functionname") == 0) {
249 pullstringdt(&dtb, dtb_beg, 0, cset);
250 push_3dfifo_fname(&f3d, cset);
mardyk017b51dbe2024-01-17 15:25:36 -0600251 pushnme(cset, &nf, mmod);
252 push_3dfifo_fid(&f3d, searchnme(cset, &nf, mmod));
Mark Dykese7810b52020-06-03 15:46:55 -0500253 leafnode = 1;
254 if (bias_count == 0U) {
255 bintnode = 1U;
256 fnode = 1U;
257 } else {
258 bias_count = 0U;
259 fnode = 0U;
260 }
261 }
262 }
263
264 /*
265 * Node termination and evaluate whether the bias tree requires addition.
266 * The non tree nodes are added.
267 */
268 if (fdt32_to_cpu(rval) == 2) {
269 if ((fnode > 0U) || (bias_count > 0U)) {
270 printf("ERROR: early node termination... ");
271 printf("no bias or functionname field for leaf node, near %s %u\n",
272 nodename, fnode);
273 }
274 f3d.col--;
275 if (leafnode == 1) {
276 leafnode = 0;
277 } else {
278 /*
279 * Create bias tree in memory from raw data
280 */
281 tndarray =
282 GENMALLOC((cntndarray + 1) *
283 sizeof(struct rand_smc_node));
284 unsigned int treenodetrackmal = 0;
285 for (unsigned int j = 0U; (int)j < cntndarray; j++) {
286 tndarray[j].biases = GENMALLOC(ndarray[j].entries * sizeof(int));
287 tndarray[j].snames = GENMALLOC(ndarray[j].entries * sizeof(char *));
mardyk017b51dbe2024-01-17 15:25:36 -0600288 tndarray[j].snameid = GENMALLOC(ndarray[j].entries * sizeof(int));
Mark Dykese7810b52020-06-03 15:46:55 -0500289 tndarray[j].norcall = GENMALLOC(ndarray[j].entries * sizeof(int));
290 tndarray[j].nname = GENMALLOC(ndarray[j].entries * sizeof(char *));
291 tndarray[j].treenodes = GENMALLOC(ndarray[j].entries * sizeof(struct rand_smc_node));
292 tndarray[j].entries = ndarray[j].entries;
293 for (unsigned int i = 0U; (int)i < ndarray[j].entries; i++) {
294 tndarray[j].snames[i] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
295 strlcpy(tndarray[j].snames[i], ndarray[j].snames[i], MAX_NAME_CHARS);
mardyk017b51dbe2024-01-17 15:25:36 -0600296 tndarray[j].snameid[i] = ndarray[j].snameid[i];
Mark Dykese7810b52020-06-03 15:46:55 -0500297 tndarray[j].nname[i] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
298 strlcpy(tndarray[j].nname[i], ndarray[j].nname[i], MAX_NAME_CHARS);
299 tndarray[j].biases[i] = ndarray[j].biases[i];
300 tndarray[j].norcall[i] = ndarray[j].norcall[i];
301 if (tndarray[j].norcall[i] == 1) {
302 tndarray[j].treenodes[i] = tndarray[treenodetrackmal];
303 treenodetrackmal++;
304 }
305 }
306 tndarray[j].biasent = ndarray[j].biasent;
307 tndarray[j].biasarray = GENMALLOC((tndarray[j].biasent) * sizeof(int));
308 for (unsigned int i = 0U; (int)i < ndarray[j].biasent; i++) {
309 tndarray[j].biasarray[i] = ndarray[j].biasarray[i];
310 }
311 }
312 tndarray[cntndarray].biases = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(int));
313 tndarray[cntndarray].snames = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(char *));
mardyk017b51dbe2024-01-17 15:25:36 -0600314 tndarray[cntndarray].snameid = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(int));
Mark Dykese7810b52020-06-03 15:46:55 -0500315 tndarray[cntndarray].norcall = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(int));
316 tndarray[cntndarray].nname = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(char *));
317 tndarray[cntndarray].treenodes = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(struct rand_smc_node));
318 tndarray[cntndarray].entries = f3d.row[f3d.col + 1];
319
320 /*
321 * Populate bias tree with former values in tree
322 */
323 int cntbias = 0;
324 int bias_count = 0;
mardyk017b51dbe2024-01-17 15:25:36 -0600325
Mark Dykese7810b52020-06-03 15:46:55 -0500326 for (unsigned int j = 0U; (int)j < f3d.row[f3d.col + 1]; j++) {
327 tndarray[cntndarray].snames[j] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
328 strlcpy(tndarray[cntndarray].snames[j], f3d.fnamefifo[f3d.col + 1][j], MAX_NAME_CHARS);
mardyk017b51dbe2024-01-17 15:25:36 -0600329 tndarray[cntndarray].snameid[j] = f3d.fidfifo[f3d.col + 1][j];
Mark Dykese7810b52020-06-03 15:46:55 -0500330 tndarray[cntndarray].nname[j] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
331 strlcpy(tndarray[cntndarray].nname[j], f3d.nnfifo[f3d.col + 1][j], MAX_NAME_CHARS);
332 tndarray[cntndarray].biases[j] = f3d.biasfifo[f3d.col + 1][j];
333 cntbias += tndarray[cntndarray].biases[j];
334 if (strcmp(tndarray[cntndarray].snames[j], "none") != 0) {
335 strlcpy(tndarray[cntndarray].snames[j], f3d.fnamefifo[f3d.col + 1][j], MAX_NAME_CHARS);
336 tndarray[cntndarray].norcall[j] = 0;
337 tndarray[cntndarray].treenodes[j] = nrnode;
338 } else {
339 tndarray[cntndarray].norcall[j] = 1;
340 tndarray[cntndarray].treenodes[j] = tndarray[treenodetrack];
341 treenodetrack++;
342 }
343 }
344
345 tndarray[cntndarray].biasent = cntbias;
346 tndarray[cntndarray].biasarray = GENMALLOC((tndarray[cntndarray].biasent) * sizeof(int));
347 for (unsigned int j = 0U; j < tndarray[cntndarray].entries; j++) {
348 for (unsigned int i = 0U; i < tndarray[cntndarray].biases[j]; i++) {
349 tndarray[cntndarray].biasarray[bias_count] = j;
350 bias_count++;
351 }
352 }
353
354 /*
355 * Free memory of old bias tree
356 */
357 if (cntndarray > 0) {
358 for (unsigned int j = 0U; (int)j < cntndarray; j++) {
359 for (unsigned int i = 0U;
360 (int)i < ndarray[j].entries;
361 i++) {
362 GENFREE(ndarray[j].snames[i]);
363 GENFREE(ndarray[j].nname[i]);
364 }
365 GENFREE(ndarray[j].biases);
366 GENFREE(ndarray[j].norcall);
367 GENFREE(ndarray[j].biasarray);
368 GENFREE(ndarray[j].snames);
mardyk017b51dbe2024-01-17 15:25:36 -0600369 GENFREE(ndarray[j].snameid);
Mark Dykese7810b52020-06-03 15:46:55 -0500370 GENFREE(ndarray[j].nname);
371 GENFREE(ndarray[j].treenodes);
372 }
373 GENFREE(ndarray);
374 }
375
376 /*
377 * Move pointers to new bias tree to current tree
378 */
379 ndarray = tndarray;
380 cntndarray++;
381
382 /*
383 * Free raw data
384 */
385 for (unsigned int j = 0U; (int)j < f3d.row[f3d.col + 1]; j++) {
386 GENFREE(f3d.nnfifo[f3d.col + 1][j]);
387 GENFREE(f3d.fnamefifo[f3d.col + 1][j]);
388 }
389 GENFREE(f3d.nnfifo[f3d.col + 1]);
390 GENFREE(f3d.fnamefifo[f3d.col + 1]);
391 GENFREE(f3d.biasfifo[f3d.col + 1]);
mardyk017b51dbe2024-01-17 15:25:36 -0600392 GENFREE(f3d.fidfifo[f3d.col + 1]);
Mark Dykese7810b52020-06-03 15:46:55 -0500393 f3d.curr_col -= 1;
394 }
395 }
396
397 /*
398 * Ending device tree file and freeing raw data
399 */
400 if (fdt32_to_cpu(rval) == 9) {
401 for (unsigned int i = 0U; (int)i < f3d.col; i++) {
402 for (unsigned int j = 0U; (int)j < f3d.row[i]; j++) {
403 GENFREE(f3d.nnfifo[i][j]);
404 GENFREE(f3d.fnamefifo[i][j]);
405 }
406 GENFREE(f3d.nnfifo[i]);
407 GENFREE(f3d.fnamefifo[i]);
408 GENFREE(f3d.biasfifo[i]);
mardyk017b51dbe2024-01-17 15:25:36 -0600409 GENFREE(f3d.fidfifo[i]);
Mark Dykese7810b52020-06-03 15:46:55 -0500410 }
411 GENFREE(f3d.nnfifo);
412 GENFREE(f3d.fnamefifo);
413 GENFREE(f3d.biasfifo);
mardyk017b51dbe2024-01-17 15:25:36 -0600414 GENFREE(f3d.fidfifo);
Mark Dykese7810b52020-06-03 15:46:55 -0500415 GENFREE(f3d.row);
416 dtdone = 1;
417 }
418 }
419
Mark Dykese7810b52020-06-03 15:46:55 -0500420 *casz = cntndarray;
421 return ndarray;
422}
423
424/*
johpow01d5c79cc2021-06-23 16:10:22 -0500425 * Function executes a single SMC fuzz test instance with a supplied seed.
Mark Dykese7810b52020-06-03 15:46:55 -0500426 */
mardyk01c14e4ad2023-10-11 16:50:19 -0500427test_result_t init_smc_fuzzing(void)
Mark Dykese7810b52020-06-03 15:46:55 -0500428{
429 /*
430 * Setting up malloc block parameters
431 */
432 tmod.memptr = (void *)tmod.memory;
433 tmod.memptrend = (void *)tmod.memory;
434 tmod.maxmemblk = ((TOTALMEMORYSIZE / BLKSPACEDIV) / sizeof(struct memblk));
435 tmod.nmemblk = 1;
436 tmod.memptr->address = 0U;
437 tmod.memptr->size = TOTALMEMORYSIZE - (TOTALMEMORYSIZE / BLKSPACEDIV);
438 tmod.memptr->valid = 1;
439 tmod.mallocdeladd[0] = 0U;
440 tmod.precblock[0] = (void *)tmod.memory;
441 tmod.trailblock[0] = NULL;
442 tmod.cntdeladd = 0U;
443 tmod.ptrmemblkqueue = 0U;
444 tmod.mallocdeladd_queue_cnt = 0U;
445 tmod.checkadd = 1U;
446 tmod.checknumentries = 0U;
447 tmod.memerror = 0U;
Mark Dykese7810b52020-06-03 15:46:55 -0500448 mmod = &tmod;
Mark Dykese7810b52020-06-03 15:46:55 -0500449
450 /*
451 * Creating SMC bias tree
452 */
mardyk01c14e4ad2023-10-11 16:50:19 -0500453 ndarray = createsmctree(&cntndarray, &tmod);
Mark Dykese7810b52020-06-03 15:46:55 -0500454
455 if (tmod.memerror != 0) {
456 return TEST_RESULT_FAIL;
457 }
458
mardyk01c14e4ad2023-10-11 16:50:19 -0500459 return TEST_RESULT_SUCCESS;
460}
461
mardyk01c14e4ad2023-10-11 16:50:19 -0500462test_result_t smc_fuzzing_instance(uint32_t seed)
463{
464 struct rand_smc_node *tlnode;
Alex Liang0fa7d212024-06-18 11:17:01 -0500465
Mark Dykese7810b52020-06-03 15:46:55 -0500466 /*
johpow01d5c79cc2021-06-23 16:10:22 -0500467 * Initialize pseudo random number generator with supplied seed.
Mark Dykese7810b52020-06-03 15:46:55 -0500468 */
johpow01d5c79cc2021-06-23 16:10:22 -0500469 srand(seed);
Mark Dykese7810b52020-06-03 15:46:55 -0500470
471 /*
472 * Code to traverse the bias tree and select function based on the biaes within
473 *
474 * The algorithm starts with the first node to pull up the biasarray. The
475 * array is specified as a series of values that reflect the bias of the nodes
476 * in question. So for instance if there are three nodes with a bias of 2,5,7
477 * the biasarray would have the following constituency:
478 *
479 * 0,0,1,1,1,1,1,2,2,2,2,2,2,2.
480 *
481 * Mapping 0 as node 1, 1 as node 2, and 2 as node 3.
482 * The biasent variable contains the count of the size of the biasarray which
483 * provides the input for random selection. This is subsequently applied as an
484 * index to the biasarray. The selection pulls up the node and then is checked
485 * for whether it is a leaf or tree node using the norcall variable.
486 * If it is a leaf then the bias tree traversal ends with an SMC call.
487 * If it is a tree node then the process begins again with
488 * another loop to continue the process of selection until an eventual leaf
489 * node is found.
490 */
johpow01d5c79cc2021-06-23 16:10:22 -0500491 for (unsigned int i = 0U; i < SMC_FUZZ_CALLS_PER_INSTANCE; i++) {
Mark Dykese7810b52020-06-03 15:46:55 -0500492 tlnode = &ndarray[cntndarray - 1];
493 int nd = 0;
mardyk017b51dbe2024-01-17 15:25:36 -0600494
Mark Dykese7810b52020-06-03 15:46:55 -0500495 while (nd == 0) {
496 int nch = rand()%tlnode->biasent;
497 int selent = tlnode->biasarray[nch];
mardyk017b51dbe2024-01-17 15:25:36 -0600498
Mark Dykese7810b52020-06-03 15:46:55 -0500499 if (tlnode->norcall[selent] == 0) {
Mark Dykes50297972024-03-15 12:49:22 -0500500 #ifdef SMC_FUZZER_DEBUG
501 printf("the name of the SMC call is %s\n", tlnode->snames[selent]);
502 #endif
503 runtestfunction(tlnode->snameid[selent], mmod);
Mark Dykese7810b52020-06-03 15:46:55 -0500504 nd = 1;
505 } else {
506 tlnode = &tlnode->treenodes[selent];
507 }
508 }
509 }
mardyk01c14e4ad2023-10-11 16:50:19 -0500510 return TEST_RESULT_SUCCESS;
511}
Mark Dykese7810b52020-06-03 15:46:55 -0500512
mardyk01c14e4ad2023-10-11 16:50:19 -0500513test_result_t smc_fuzzing_deinit(void)
514{
Mark Dykese7810b52020-06-03 15:46:55 -0500515 /*
516 * End of test SMC selection and freeing of nodes
517 */
518 if (cntndarray > 0) {
519 for (unsigned int j = 0U; j < cntndarray; j++) {
520 for (unsigned int i = 0U; i < ndarray[j].entries; i++) {
521 GENFREE(ndarray[j].snames[i]);
522 GENFREE(ndarray[j].nname[i]);
523 }
524 GENFREE(ndarray[j].biases);
525 GENFREE(ndarray[j].norcall);
526 GENFREE(ndarray[j].biasarray);
527 GENFREE(ndarray[j].snames);
mardyk017b51dbe2024-01-17 15:25:36 -0600528 GENFREE(ndarray[j].snameid);
Mark Dykese7810b52020-06-03 15:46:55 -0500529 GENFREE(ndarray[j].nname);
530 GENFREE(ndarray[j].treenodes);
531 }
532 GENFREE(ndarray);
533 }
534
535 return TEST_RESULT_SUCCESS;
536}
johpow01d5c79cc2021-06-23 16:10:22 -0500537
538/*
mardyk017b51dbe2024-01-17 15:25:36 -0600539 * Top of SMC fuzzing module
johpow01d5c79cc2021-06-23 16:10:22 -0500540 */
mardyk01c14e4ad2023-10-11 16:50:19 -0500541test_result_t smc_fuzzer_execute(void)
johpow01d5c79cc2021-06-23 16:10:22 -0500542{
543 /* These SMC_FUZZ_x macros are supplied by the build system. */
544 test_result_t results[SMC_FUZZ_INSTANCE_COUNT];
545 uint32_t seeds[SMC_FUZZ_INSTANCE_COUNT] = {SMC_FUZZ_SEEDS};
546 test_result_t result = TEST_RESULT_SUCCESS;
547 unsigned int i;
548
549 /* Run each instance. */
550 for (i = 0U; i < SMC_FUZZ_INSTANCE_COUNT; i++) {
551 printf("Starting SMC fuzz test with seed 0x%x\n", seeds[i]);
552 results[i] = smc_fuzzing_instance(seeds[i]);
553 }
554
555 /* Report successes and failures. */
556 printf("SMC Fuzz Test Results Summary\n");
557 for (i = 0U; i < SMC_FUZZ_INSTANCE_COUNT; i++) {
558 /* Display instance number. */
559 printf(" Instance #%d\n", i);
560
561 /* Print test results. */
562 printf(" Result: ");
563 if (results[i] == TEST_RESULT_SUCCESS) {
564 printf("SUCCESS\n");
565 } else if (results[i] == TEST_RESULT_FAIL) {
566 printf("FAIL\n");
567 /* If we got a failure, update the result value. */
568 result = TEST_RESULT_FAIL;
569 } else if (results[i] == TEST_RESULT_SKIPPED) {
570 printf("SKIPPED\n");
571 }
572
573 /* Print seed used */
574 printf(" Seed: 0x%x\n", seeds[i]);
575 }
576
577 /*
578 * Print out the smc fuzzer parameters so this test can be replicated.
579 */
580 printf("SMC fuzz build parameters to recreate this test:\n");
581 printf(" SMC_FUZZ_INSTANCE_COUNT=%u\n",
582 SMC_FUZZ_INSTANCE_COUNT);
583 printf(" SMC_FUZZ_CALLS_PER_INSTANCE=%u\n",
584 SMC_FUZZ_CALLS_PER_INSTANCE);
585 printf(" SMC_FUZZ_SEEDS=0x%x", seeds[0]);
586 for (i = 1U; i < SMC_FUZZ_INSTANCE_COUNT; i++) {
587 printf(",0x%x", seeds[i]);
588 }
589 printf("\n");
590
591 return result;
592}
mardyk01c14e4ad2023-10-11 16:50:19 -0500593
mardyk01c14e4ad2023-10-11 16:50:19 -0500594test_result_t smc_fuzzing_top(void)
595{
596 test_result_t result = TEST_RESULT_SUCCESS;
597 init_smc_fuzzing();
mardyk017b51dbe2024-01-17 15:25:36 -0600598
mardyk01c14e4ad2023-10-11 16:50:19 -0500599#ifdef MULTI_CPU_SMC_FUZZER
600 u_register_t lead_mpid, target_mpid;
601 int cpu_node;
602 int32_t aff_info __unused;
603 int64_t ret;
604
605 lead_mpid = read_mpidr_el1() & MPID_MASK;
606 for_each_cpu(cpu_node) {
607 target_mpid = tftf_get_mpidr_from_node(cpu_node) & MPID_MASK;
608 if (lead_mpid == target_mpid) {
609 /* Run on this CPU */
610 if (smc_fuzzer_execute() != TEST_RESULT_SUCCESS)
611 return TEST_RESULT_FAIL;
612 } else {
613 /* Power on other CPU to run through fuzzing instructions */
614 ret = tftf_cpu_on(target_mpid,
615 (uintptr_t) smc_fuzzer_execute, 0);
616 if (ret != PSCI_E_SUCCESS) {
617 ERROR("CPU ON failed for 0x%llx\n",
618 (unsigned long long) target_mpid);
619 return TEST_RESULT_FAIL;
620 }
621
622 }
623 }
624
625 smc_fuzzing_deinit();
626 return result;
627#else
628 result = smc_fuzzer_execute();
629 smc_fuzzing_deinit();
630 return result;
631#endif
632}