blob: 1cbf44a4fb854fcb791a461463afde849d3aff10 [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;
Mark Dykese7810b52020-06-03 15:46:55 -0500465 /*
johpow01d5c79cc2021-06-23 16:10:22 -0500466 * Initialize pseudo random number generator with supplied seed.
Mark Dykese7810b52020-06-03 15:46:55 -0500467 */
johpow01d5c79cc2021-06-23 16:10:22 -0500468 srand(seed);
Mark Dykese7810b52020-06-03 15:46:55 -0500469
470 /*
471 * Code to traverse the bias tree and select function based on the biaes within
472 *
473 * The algorithm starts with the first node to pull up the biasarray. The
474 * array is specified as a series of values that reflect the bias of the nodes
475 * in question. So for instance if there are three nodes with a bias of 2,5,7
476 * the biasarray would have the following constituency:
477 *
478 * 0,0,1,1,1,1,1,2,2,2,2,2,2,2.
479 *
480 * Mapping 0 as node 1, 1 as node 2, and 2 as node 3.
481 * The biasent variable contains the count of the size of the biasarray which
482 * provides the input for random selection. This is subsequently applied as an
483 * index to the biasarray. The selection pulls up the node and then is checked
484 * for whether it is a leaf or tree node using the norcall variable.
485 * If it is a leaf then the bias tree traversal ends with an SMC call.
486 * If it is a tree node then the process begins again with
487 * another loop to continue the process of selection until an eventual leaf
488 * node is found.
489 */
johpow01d5c79cc2021-06-23 16:10:22 -0500490 for (unsigned int i = 0U; i < SMC_FUZZ_CALLS_PER_INSTANCE; i++) {
Mark Dykese7810b52020-06-03 15:46:55 -0500491 tlnode = &ndarray[cntndarray - 1];
492 int nd = 0;
mardyk017b51dbe2024-01-17 15:25:36 -0600493
Mark Dykese7810b52020-06-03 15:46:55 -0500494 while (nd == 0) {
495 int nch = rand()%tlnode->biasent;
496 int selent = tlnode->biasarray[nch];
mardyk017b51dbe2024-01-17 15:25:36 -0600497
Mark Dykese7810b52020-06-03 15:46:55 -0500498 if (tlnode->norcall[selent] == 0) {
Mark Dykes50297972024-03-15 12:49:22 -0500499 #ifdef SMC_FUZZER_DEBUG
500 printf("the name of the SMC call is %s\n", tlnode->snames[selent]);
501 #endif
502 runtestfunction(tlnode->snameid[selent], mmod);
Mark Dykese7810b52020-06-03 15:46:55 -0500503 nd = 1;
504 } else {
505 tlnode = &tlnode->treenodes[selent];
506 }
507 }
508 }
mardyk01c14e4ad2023-10-11 16:50:19 -0500509 return TEST_RESULT_SUCCESS;
510}
Mark Dykese7810b52020-06-03 15:46:55 -0500511
mardyk01c14e4ad2023-10-11 16:50:19 -0500512test_result_t smc_fuzzing_deinit(void)
513{
Mark Dykese7810b52020-06-03 15:46:55 -0500514 /*
515 * End of test SMC selection and freeing of nodes
516 */
517 if (cntndarray > 0) {
518 for (unsigned int j = 0U; j < cntndarray; j++) {
519 for (unsigned int i = 0U; i < ndarray[j].entries; i++) {
520 GENFREE(ndarray[j].snames[i]);
521 GENFREE(ndarray[j].nname[i]);
522 }
523 GENFREE(ndarray[j].biases);
524 GENFREE(ndarray[j].norcall);
525 GENFREE(ndarray[j].biasarray);
526 GENFREE(ndarray[j].snames);
mardyk017b51dbe2024-01-17 15:25:36 -0600527 GENFREE(ndarray[j].snameid);
Mark Dykese7810b52020-06-03 15:46:55 -0500528 GENFREE(ndarray[j].nname);
529 GENFREE(ndarray[j].treenodes);
530 }
531 GENFREE(ndarray);
532 }
533
534 return TEST_RESULT_SUCCESS;
535}
johpow01d5c79cc2021-06-23 16:10:22 -0500536
537/*
mardyk017b51dbe2024-01-17 15:25:36 -0600538 * Top of SMC fuzzing module
johpow01d5c79cc2021-06-23 16:10:22 -0500539 */
mardyk01c14e4ad2023-10-11 16:50:19 -0500540test_result_t smc_fuzzer_execute(void)
johpow01d5c79cc2021-06-23 16:10:22 -0500541{
542 /* These SMC_FUZZ_x macros are supplied by the build system. */
543 test_result_t results[SMC_FUZZ_INSTANCE_COUNT];
544 uint32_t seeds[SMC_FUZZ_INSTANCE_COUNT] = {SMC_FUZZ_SEEDS};
545 test_result_t result = TEST_RESULT_SUCCESS;
546 unsigned int i;
547
548 /* Run each instance. */
549 for (i = 0U; i < SMC_FUZZ_INSTANCE_COUNT; i++) {
550 printf("Starting SMC fuzz test with seed 0x%x\n", seeds[i]);
551 results[i] = smc_fuzzing_instance(seeds[i]);
552 }
553
554 /* Report successes and failures. */
555 printf("SMC Fuzz Test Results Summary\n");
556 for (i = 0U; i < SMC_FUZZ_INSTANCE_COUNT; i++) {
557 /* Display instance number. */
558 printf(" Instance #%d\n", i);
559
560 /* Print test results. */
561 printf(" Result: ");
562 if (results[i] == TEST_RESULT_SUCCESS) {
563 printf("SUCCESS\n");
564 } else if (results[i] == TEST_RESULT_FAIL) {
565 printf("FAIL\n");
566 /* If we got a failure, update the result value. */
567 result = TEST_RESULT_FAIL;
568 } else if (results[i] == TEST_RESULT_SKIPPED) {
569 printf("SKIPPED\n");
570 }
571
572 /* Print seed used */
573 printf(" Seed: 0x%x\n", seeds[i]);
574 }
575
576 /*
577 * Print out the smc fuzzer parameters so this test can be replicated.
578 */
579 printf("SMC fuzz build parameters to recreate this test:\n");
580 printf(" SMC_FUZZ_INSTANCE_COUNT=%u\n",
581 SMC_FUZZ_INSTANCE_COUNT);
582 printf(" SMC_FUZZ_CALLS_PER_INSTANCE=%u\n",
583 SMC_FUZZ_CALLS_PER_INSTANCE);
584 printf(" SMC_FUZZ_SEEDS=0x%x", seeds[0]);
585 for (i = 1U; i < SMC_FUZZ_INSTANCE_COUNT; i++) {
586 printf(",0x%x", seeds[i]);
587 }
588 printf("\n");
589
590 return result;
591}
mardyk01c14e4ad2023-10-11 16:50:19 -0500592
mardyk01c14e4ad2023-10-11 16:50:19 -0500593test_result_t smc_fuzzing_top(void)
594{
595 test_result_t result = TEST_RESULT_SUCCESS;
596 init_smc_fuzzing();
mardyk017b51dbe2024-01-17 15:25:36 -0600597
mardyk01c14e4ad2023-10-11 16:50:19 -0500598#ifdef MULTI_CPU_SMC_FUZZER
599 u_register_t lead_mpid, target_mpid;
600 int cpu_node;
601 int32_t aff_info __unused;
602 int64_t ret;
603
604 lead_mpid = read_mpidr_el1() & MPID_MASK;
605 for_each_cpu(cpu_node) {
606 target_mpid = tftf_get_mpidr_from_node(cpu_node) & MPID_MASK;
607 if (lead_mpid == target_mpid) {
608 /* Run on this CPU */
609 if (smc_fuzzer_execute() != TEST_RESULT_SUCCESS)
610 return TEST_RESULT_FAIL;
611 } else {
612 /* Power on other CPU to run through fuzzing instructions */
613 ret = tftf_cpu_on(target_mpid,
614 (uintptr_t) smc_fuzzer_execute, 0);
615 if (ret != PSCI_E_SUCCESS) {
616 ERROR("CPU ON failed for 0x%llx\n",
617 (unsigned long long) target_mpid);
618 return TEST_RESULT_FAIL;
619 }
620
621 }
622 }
623
624 smc_fuzzing_deinit();
625 return result;
626#else
627 result = smc_fuzzer_execute();
628 smc_fuzzing_deinit();
629 return result;
630#endif
631}