blob: a86feb61eb565339f46409cf055689810d92961d [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
7#include <arch_helpers.h>
8#include <debug.h>
9#include <drivers/arm/private_timer.h>
10#include <events.h>
11#include "fifo3d.h"
mardyk017b51dbe2024-01-17 15:25:36 -060012#include "nfifo.h"
Mark Dykese7810b52020-06-03 15:46:55 -050013#include <libfdt.h>
14
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
19extern char _binary___dtb_start[];
mardyk017b51dbe2024-01-17 15:25:36 -060020extern void runtestfunction(int funcid);
Mark Dykese7810b52020-06-03 15:46:55 -050021
22struct memmod tmod __aligned(65536) __section("smcfuzz");
mardyk01c14e4ad2023-10-11 16:50:19 -050023static int cntndarray;
24static struct rand_smc_node *ndarray;
25static struct memmod *mmod;
Mark Dykese7810b52020-06-03 15:46:55 -050026
27/*
28 * switch to use either standard C malloc or custom SMC malloc
29 */
30
31#define FIRST_NODE_DEVTREE_OFFSET (8)
32
33#ifdef SMC_FUZZ_TMALLOC
34#define GENMALLOC(x) malloc((x))
35#define GENFREE(x) free((x))
36#else
37#define GENMALLOC(x) smcmalloc((x), mmod)
38#define GENFREE(x) smcfree((x), mmod)
39#endif
40
41/*
42 * Device tree parameter struct
43 */
44
45struct fdt_header_sf {
46 unsigned int magic;
47 unsigned int totalsize;
48 unsigned int off_dt_struct;
49 unsigned int off_dt_strings;
50 unsigned int off_mem_rsvmap;
51 unsigned int version;
52 unsigned int last_comp_version;
53 unsigned int boot_cpuid_phys;
54 unsigned int size_dt_strings;
55 unsigned int size_dt_struct;
56};
57
58/*
59 * Structure to read the fields of the device tree
60 */
61struct propval {
62 unsigned int len;
63 unsigned int nameoff;
64};
65
66/*
67 * Converting from big endian to little endian to read values
68 * of device tree
69 */
70unsigned int lendconv(unsigned int val)
71{
72 unsigned int res;
73
74 res = val << 24;
75 res |= ((val << 8) & 0xFF0000U);
76 res |= ((val >> 8) & 0xFF00U);
77 res |= ((val >> 24) & 0xFFU);
78 return res;
79}
80
81/*
82 * Function to read strings from device tree
83 */
84void pullstringdt(void **dtb,
85 void *dtb_beg,
86 unsigned int offset,
87 char *cset)
88{
89 int fistr;
90 int cntchr;
91 char rval;
92
93 if (offset != 0U) {
94 *dtb = dtb_beg + offset;
95 }
96 fistr = 0;
97
98 cntchr = 0;
99 while (fistr == 0) {
100 rval = *((char *)*dtb);
101 *dtb += sizeof(char);
102 cset[cntchr] = rval;
103 if (cset[cntchr] == 0) {
104 fistr = 1;
105 }
106 cntchr++;
107 }
108
109 if ((cntchr % 4) != 0) {
110 for (unsigned int i = 0U; (int)i < (4 - (cntchr % 4)); i++) {
111 *dtb += sizeof(char);
112 }
113 }
114}
115
116/*
117 * Structure for Node information extracted from device tree
118 */
119struct rand_smc_node {
120 int *biases; // Biases of the individual nodes
121 int *biasarray; // Array of biases across all nodes
122 char **snames; // String that is unique to the SMC call called in test
mardyk017b51dbe2024-01-17 15:25:36 -0600123 int *snameid; // ID that is unique to the SMC call called in test
Mark Dykese7810b52020-06-03 15:46:55 -0500124 struct rand_smc_node *treenodes; // Selection of nodes that are farther down in the tree
mardyk017b51dbe2024-01-17 15:25:36 -0600125 // that reference further rand_smc_node objects
Mark Dykese7810b52020-06-03 15:46:55 -0500126 int *norcall; // Specifies whether a particular node is a leaf node or tree node
mardyk017b51dbe2024-01-17 15:25:36 -0600127 int entries; // Number of nodes in object
128 int biasent; // Number that gives the total number of entries in biasarray
129 // based on all biases of the nodes
130 char **nname; // Array of node names
Mark Dykese7810b52020-06-03 15:46:55 -0500131};
132
133
134/*
135 * Create bias tree from given device tree description
136 */
137
138struct rand_smc_node *createsmctree(int *casz,
139 struct memmod *mmod)
140{
141 void *dtb;
142 void *dtb_pn;
143 void *dtb_beg;
144 struct fdt_header fhd;
145 unsigned int rval;
146 struct propval pv;
147 char cset[MAX_NAME_CHARS];
148 char nodename[MAX_NAME_CHARS];
149 int dtdone;
150 struct fifo3d f3d;
151 int leafnode = 0;
152 unsigned int fnode = 0U;
153 unsigned int bias_count = 0U;
154 unsigned int bintnode = 0U;
155 unsigned int treenodetrack = 0U;
156 struct fdt_header *fhdptr;
157 struct rand_smc_node *ndarray = NULL;
158 int cntndarray;
159 struct rand_smc_node nrnode;
160 struct rand_smc_node *tndarray;
mardyk017b51dbe2024-01-17 15:25:36 -0600161 struct nfifo nf;
162
163 nfifoinit(&nf, mmod);
Mark Dykese7810b52020-06-03 15:46:55 -0500164
165 f3d.col = 0;
166 f3d.curr_col = 0;
167
168 /*
169 * Read device tree header and check for valid type
170 */
171
172 fhdptr = (struct fdt_header *)_binary___dtb_start;
173
Mark Dykese7810b52020-06-03 15:46:55 -0500174 fhd = *fhdptr;
175 cntndarray = 0;
176 nrnode.entries = 0;
177
178 /*
179 * Create pointers to device tree data
180 */
181 dtb = _binary___dtb_start;
182 dtb_pn = _binary___dtb_start;
183
184 dtb_beg = dtb;
185 fhd = *((struct fdt_header *)dtb);
186 dtb += (fdt32_to_cpu(fhd.off_dt_struct) + FIRST_NODE_DEVTREE_OFFSET);
187 dtdone = 0;
188
189 /*
190 * Reading device tree file
191 */
192 while (dtdone == 0) {
193 rval = *((unsigned int *)dtb);
194 dtb += sizeof(unsigned int);
195
196 /*
197 * Reading node name from device tree and pushing it into the raw data
198 * Table of possible values reading from device tree binary file:
199 * 1 New node found within current tree, possible leaf or tree variant
200 * 2 Node termination of current hiearchy.
201 * Could indicate end of tree or preparation for another branch
202 * 3 Leaf node indication where a bias with a function name should be
203 * found for the current node
204 * 9 End of device tree file and we end the read of the bias tree
205 */
206 if (fdt32_to_cpu(rval) == 1) {
207 pullstringdt(&dtb, dtb_beg, 0U, cset);
208 push_3dfifo_col(&f3d, cset, mmod);
209 strlcpy(nodename, cset, MAX_NAME_CHARS);
210
211 /*
212 * Error checking to make sure that bias is specified
213 */
214 if (fnode == 0U) {
215 fnode = 1U;
216 } else {
217 if (!((fnode == 1U) && (bias_count == 1U))) {
218 printf("ERROR: Did not find bias or multiple bias ");
219 printf("designations before %s %u %u\n",
220 cset, fnode, bias_count);
221 }
222 bias_count = 0U;
223 }
224 }
225
226 /*
227 * Reading node parameters of bias and function name
228 */
229 if (fdt32_to_cpu(rval) == 3) {
230 pv = *((struct propval *)dtb);
231 dtb += sizeof(struct propval);
232 pullstringdt(&dtb_pn, dtb_beg,
233 (fdt32_to_cpu(fhd.off_dt_strings) +
234 fdt32_to_cpu(pv.nameoff)), cset);
235 if (strcmp(cset, "bias") == 0) {
236 rval = *((unsigned int *)dtb);
237 dtb += sizeof(unsigned int);
238 push_3dfifo_bias(&f3d, fdt32_to_cpu(rval));
239 bias_count++;
240 if (bintnode == 1U) {
241 fnode = 0U;
242 bintnode = 0U;
243 bias_count = 0U;
244 }
245 }
246 if (strcmp(cset, "functionname") == 0) {
247 pullstringdt(&dtb, dtb_beg, 0, cset);
248 push_3dfifo_fname(&f3d, cset);
mardyk017b51dbe2024-01-17 15:25:36 -0600249 pushnme(cset, &nf, mmod);
250 push_3dfifo_fid(&f3d, searchnme(cset, &nf, mmod));
Mark Dykese7810b52020-06-03 15:46:55 -0500251 leafnode = 1;
252 if (bias_count == 0U) {
253 bintnode = 1U;
254 fnode = 1U;
255 } else {
256 bias_count = 0U;
257 fnode = 0U;
258 }
259 }
260 }
261
262 /*
263 * Node termination and evaluate whether the bias tree requires addition.
264 * The non tree nodes are added.
265 */
266 if (fdt32_to_cpu(rval) == 2) {
267 if ((fnode > 0U) || (bias_count > 0U)) {
268 printf("ERROR: early node termination... ");
269 printf("no bias or functionname field for leaf node, near %s %u\n",
270 nodename, fnode);
271 }
272 f3d.col--;
273 if (leafnode == 1) {
274 leafnode = 0;
275 } else {
276 /*
277 * Create bias tree in memory from raw data
278 */
279 tndarray =
280 GENMALLOC((cntndarray + 1) *
281 sizeof(struct rand_smc_node));
282 unsigned int treenodetrackmal = 0;
283 for (unsigned int j = 0U; (int)j < cntndarray; j++) {
284 tndarray[j].biases = GENMALLOC(ndarray[j].entries * sizeof(int));
285 tndarray[j].snames = GENMALLOC(ndarray[j].entries * sizeof(char *));
mardyk017b51dbe2024-01-17 15:25:36 -0600286 tndarray[j].snameid = GENMALLOC(ndarray[j].entries * sizeof(int));
Mark Dykese7810b52020-06-03 15:46:55 -0500287 tndarray[j].norcall = GENMALLOC(ndarray[j].entries * sizeof(int));
288 tndarray[j].nname = GENMALLOC(ndarray[j].entries * sizeof(char *));
289 tndarray[j].treenodes = GENMALLOC(ndarray[j].entries * sizeof(struct rand_smc_node));
290 tndarray[j].entries = ndarray[j].entries;
291 for (unsigned int i = 0U; (int)i < ndarray[j].entries; i++) {
292 tndarray[j].snames[i] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
293 strlcpy(tndarray[j].snames[i], ndarray[j].snames[i], MAX_NAME_CHARS);
mardyk017b51dbe2024-01-17 15:25:36 -0600294 tndarray[j].snameid[i] = ndarray[j].snameid[i];
Mark Dykese7810b52020-06-03 15:46:55 -0500295 tndarray[j].nname[i] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
296 strlcpy(tndarray[j].nname[i], ndarray[j].nname[i], MAX_NAME_CHARS);
297 tndarray[j].biases[i] = ndarray[j].biases[i];
298 tndarray[j].norcall[i] = ndarray[j].norcall[i];
299 if (tndarray[j].norcall[i] == 1) {
300 tndarray[j].treenodes[i] = tndarray[treenodetrackmal];
301 treenodetrackmal++;
302 }
303 }
304 tndarray[j].biasent = ndarray[j].biasent;
305 tndarray[j].biasarray = GENMALLOC((tndarray[j].biasent) * sizeof(int));
306 for (unsigned int i = 0U; (int)i < ndarray[j].biasent; i++) {
307 tndarray[j].biasarray[i] = ndarray[j].biasarray[i];
308 }
309 }
310 tndarray[cntndarray].biases = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(int));
311 tndarray[cntndarray].snames = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(char *));
mardyk017b51dbe2024-01-17 15:25:36 -0600312 tndarray[cntndarray].snameid = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(int));
Mark Dykese7810b52020-06-03 15:46:55 -0500313 tndarray[cntndarray].norcall = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(int));
314 tndarray[cntndarray].nname = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(char *));
315 tndarray[cntndarray].treenodes = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(struct rand_smc_node));
316 tndarray[cntndarray].entries = f3d.row[f3d.col + 1];
317
318 /*
319 * Populate bias tree with former values in tree
320 */
321 int cntbias = 0;
322 int bias_count = 0;
mardyk017b51dbe2024-01-17 15:25:36 -0600323
Mark Dykese7810b52020-06-03 15:46:55 -0500324 for (unsigned int j = 0U; (int)j < f3d.row[f3d.col + 1]; j++) {
325 tndarray[cntndarray].snames[j] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
326 strlcpy(tndarray[cntndarray].snames[j], f3d.fnamefifo[f3d.col + 1][j], MAX_NAME_CHARS);
mardyk017b51dbe2024-01-17 15:25:36 -0600327 tndarray[cntndarray].snameid[j] = f3d.fidfifo[f3d.col + 1][j];
Mark Dykese7810b52020-06-03 15:46:55 -0500328 tndarray[cntndarray].nname[j] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
329 strlcpy(tndarray[cntndarray].nname[j], f3d.nnfifo[f3d.col + 1][j], MAX_NAME_CHARS);
330 tndarray[cntndarray].biases[j] = f3d.biasfifo[f3d.col + 1][j];
331 cntbias += tndarray[cntndarray].biases[j];
332 if (strcmp(tndarray[cntndarray].snames[j], "none") != 0) {
333 strlcpy(tndarray[cntndarray].snames[j], f3d.fnamefifo[f3d.col + 1][j], MAX_NAME_CHARS);
334 tndarray[cntndarray].norcall[j] = 0;
335 tndarray[cntndarray].treenodes[j] = nrnode;
336 } else {
337 tndarray[cntndarray].norcall[j] = 1;
338 tndarray[cntndarray].treenodes[j] = tndarray[treenodetrack];
339 treenodetrack++;
340 }
341 }
342
343 tndarray[cntndarray].biasent = cntbias;
344 tndarray[cntndarray].biasarray = GENMALLOC((tndarray[cntndarray].biasent) * sizeof(int));
345 for (unsigned int j = 0U; j < tndarray[cntndarray].entries; j++) {
346 for (unsigned int i = 0U; i < tndarray[cntndarray].biases[j]; i++) {
347 tndarray[cntndarray].biasarray[bias_count] = j;
348 bias_count++;
349 }
350 }
351
352 /*
353 * Free memory of old bias tree
354 */
355 if (cntndarray > 0) {
356 for (unsigned int j = 0U; (int)j < cntndarray; j++) {
357 for (unsigned int i = 0U;
358 (int)i < ndarray[j].entries;
359 i++) {
360 GENFREE(ndarray[j].snames[i]);
361 GENFREE(ndarray[j].nname[i]);
362 }
363 GENFREE(ndarray[j].biases);
364 GENFREE(ndarray[j].norcall);
365 GENFREE(ndarray[j].biasarray);
366 GENFREE(ndarray[j].snames);
mardyk017b51dbe2024-01-17 15:25:36 -0600367 GENFREE(ndarray[j].snameid);
Mark Dykese7810b52020-06-03 15:46:55 -0500368 GENFREE(ndarray[j].nname);
369 GENFREE(ndarray[j].treenodes);
370 }
371 GENFREE(ndarray);
372 }
373
374 /*
375 * Move pointers to new bias tree to current tree
376 */
377 ndarray = tndarray;
378 cntndarray++;
379
380 /*
381 * Free raw data
382 */
383 for (unsigned int j = 0U; (int)j < f3d.row[f3d.col + 1]; j++) {
384 GENFREE(f3d.nnfifo[f3d.col + 1][j]);
385 GENFREE(f3d.fnamefifo[f3d.col + 1][j]);
386 }
387 GENFREE(f3d.nnfifo[f3d.col + 1]);
388 GENFREE(f3d.fnamefifo[f3d.col + 1]);
389 GENFREE(f3d.biasfifo[f3d.col + 1]);
mardyk017b51dbe2024-01-17 15:25:36 -0600390 GENFREE(f3d.fidfifo[f3d.col + 1]);
Mark Dykese7810b52020-06-03 15:46:55 -0500391 f3d.curr_col -= 1;
392 }
393 }
394
395 /*
396 * Ending device tree file and freeing raw data
397 */
398 if (fdt32_to_cpu(rval) == 9) {
399 for (unsigned int i = 0U; (int)i < f3d.col; i++) {
400 for (unsigned int j = 0U; (int)j < f3d.row[i]; j++) {
401 GENFREE(f3d.nnfifo[i][j]);
402 GENFREE(f3d.fnamefifo[i][j]);
403 }
404 GENFREE(f3d.nnfifo[i]);
405 GENFREE(f3d.fnamefifo[i]);
406 GENFREE(f3d.biasfifo[i]);
mardyk017b51dbe2024-01-17 15:25:36 -0600407 GENFREE(f3d.fidfifo[i]);
Mark Dykese7810b52020-06-03 15:46:55 -0500408 }
409 GENFREE(f3d.nnfifo);
410 GENFREE(f3d.fnamefifo);
411 GENFREE(f3d.biasfifo);
mardyk017b51dbe2024-01-17 15:25:36 -0600412 GENFREE(f3d.fidfifo);
Mark Dykese7810b52020-06-03 15:46:55 -0500413 GENFREE(f3d.row);
414 dtdone = 1;
415 }
416 }
417
Mark Dykese7810b52020-06-03 15:46:55 -0500418 *casz = cntndarray;
419 return ndarray;
420}
421
422/*
johpow01d5c79cc2021-06-23 16:10:22 -0500423 * Function executes a single SMC fuzz test instance with a supplied seed.
Mark Dykese7810b52020-06-03 15:46:55 -0500424 */
mardyk01c14e4ad2023-10-11 16:50:19 -0500425test_result_t init_smc_fuzzing(void)
Mark Dykese7810b52020-06-03 15:46:55 -0500426{
427 /*
428 * Setting up malloc block parameters
429 */
430 tmod.memptr = (void *)tmod.memory;
431 tmod.memptrend = (void *)tmod.memory;
432 tmod.maxmemblk = ((TOTALMEMORYSIZE / BLKSPACEDIV) / sizeof(struct memblk));
433 tmod.nmemblk = 1;
434 tmod.memptr->address = 0U;
435 tmod.memptr->size = TOTALMEMORYSIZE - (TOTALMEMORYSIZE / BLKSPACEDIV);
436 tmod.memptr->valid = 1;
437 tmod.mallocdeladd[0] = 0U;
438 tmod.precblock[0] = (void *)tmod.memory;
439 tmod.trailblock[0] = NULL;
440 tmod.cntdeladd = 0U;
441 tmod.ptrmemblkqueue = 0U;
442 tmod.mallocdeladd_queue_cnt = 0U;
443 tmod.checkadd = 1U;
444 tmod.checknumentries = 0U;
445 tmod.memerror = 0U;
Mark Dykese7810b52020-06-03 15:46:55 -0500446 mmod = &tmod;
Mark Dykese7810b52020-06-03 15:46:55 -0500447
448 /*
449 * Creating SMC bias tree
450 */
mardyk01c14e4ad2023-10-11 16:50:19 -0500451 ndarray = createsmctree(&cntndarray, &tmod);
Mark Dykese7810b52020-06-03 15:46:55 -0500452
453 if (tmod.memerror != 0) {
454 return TEST_RESULT_FAIL;
455 }
456
mardyk01c14e4ad2023-10-11 16:50:19 -0500457 return TEST_RESULT_SUCCESS;
458}
459
mardyk01c14e4ad2023-10-11 16:50:19 -0500460test_result_t smc_fuzzing_instance(uint32_t seed)
461{
462 struct rand_smc_node *tlnode;
Mark Dykese7810b52020-06-03 15:46:55 -0500463 /*
johpow01d5c79cc2021-06-23 16:10:22 -0500464 * Initialize pseudo random number generator with supplied seed.
Mark Dykese7810b52020-06-03 15:46:55 -0500465 */
johpow01d5c79cc2021-06-23 16:10:22 -0500466 srand(seed);
Mark Dykese7810b52020-06-03 15:46:55 -0500467
468 /*
469 * Code to traverse the bias tree and select function based on the biaes within
470 *
471 * The algorithm starts with the first node to pull up the biasarray. The
472 * array is specified as a series of values that reflect the bias of the nodes
473 * in question. So for instance if there are three nodes with a bias of 2,5,7
474 * the biasarray would have the following constituency:
475 *
476 * 0,0,1,1,1,1,1,2,2,2,2,2,2,2.
477 *
478 * Mapping 0 as node 1, 1 as node 2, and 2 as node 3.
479 * The biasent variable contains the count of the size of the biasarray which
480 * provides the input for random selection. This is subsequently applied as an
481 * index to the biasarray. The selection pulls up the node and then is checked
482 * for whether it is a leaf or tree node using the norcall variable.
483 * If it is a leaf then the bias tree traversal ends with an SMC call.
484 * If it is a tree node then the process begins again with
485 * another loop to continue the process of selection until an eventual leaf
486 * node is found.
487 */
johpow01d5c79cc2021-06-23 16:10:22 -0500488 for (unsigned int i = 0U; i < SMC_FUZZ_CALLS_PER_INSTANCE; i++) {
Mark Dykese7810b52020-06-03 15:46:55 -0500489 tlnode = &ndarray[cntndarray - 1];
490 int nd = 0;
mardyk017b51dbe2024-01-17 15:25:36 -0600491
Mark Dykese7810b52020-06-03 15:46:55 -0500492 while (nd == 0) {
493 int nch = rand()%tlnode->biasent;
494 int selent = tlnode->biasarray[nch];
mardyk017b51dbe2024-01-17 15:25:36 -0600495
Mark Dykese7810b52020-06-03 15:46:55 -0500496 if (tlnode->norcall[selent] == 0) {
mardyk017b51dbe2024-01-17 15:25:36 -0600497 runtestfunction(tlnode->snameid[selent]);
Mark Dykese7810b52020-06-03 15:46:55 -0500498 nd = 1;
499 } else {
500 tlnode = &tlnode->treenodes[selent];
501 }
502 }
503 }
mardyk01c14e4ad2023-10-11 16:50:19 -0500504 return TEST_RESULT_SUCCESS;
505}
Mark Dykese7810b52020-06-03 15:46:55 -0500506
mardyk01c14e4ad2023-10-11 16:50:19 -0500507test_result_t smc_fuzzing_deinit(void)
508{
Mark Dykese7810b52020-06-03 15:46:55 -0500509 /*
510 * End of test SMC selection and freeing of nodes
511 */
512 if (cntndarray > 0) {
513 for (unsigned int j = 0U; j < cntndarray; j++) {
514 for (unsigned int i = 0U; i < ndarray[j].entries; i++) {
515 GENFREE(ndarray[j].snames[i]);
516 GENFREE(ndarray[j].nname[i]);
517 }
518 GENFREE(ndarray[j].biases);
519 GENFREE(ndarray[j].norcall);
520 GENFREE(ndarray[j].biasarray);
521 GENFREE(ndarray[j].snames);
mardyk017b51dbe2024-01-17 15:25:36 -0600522 GENFREE(ndarray[j].snameid);
Mark Dykese7810b52020-06-03 15:46:55 -0500523 GENFREE(ndarray[j].nname);
524 GENFREE(ndarray[j].treenodes);
525 }
526 GENFREE(ndarray);
527 }
528
529 return TEST_RESULT_SUCCESS;
530}
johpow01d5c79cc2021-06-23 16:10:22 -0500531
532/*
mardyk017b51dbe2024-01-17 15:25:36 -0600533 * Top of SMC fuzzing module
johpow01d5c79cc2021-06-23 16:10:22 -0500534 */
mardyk01c14e4ad2023-10-11 16:50:19 -0500535test_result_t smc_fuzzer_execute(void)
johpow01d5c79cc2021-06-23 16:10:22 -0500536{
537 /* These SMC_FUZZ_x macros are supplied by the build system. */
538 test_result_t results[SMC_FUZZ_INSTANCE_COUNT];
539 uint32_t seeds[SMC_FUZZ_INSTANCE_COUNT] = {SMC_FUZZ_SEEDS};
540 test_result_t result = TEST_RESULT_SUCCESS;
541 unsigned int i;
542
543 /* Run each instance. */
544 for (i = 0U; i < SMC_FUZZ_INSTANCE_COUNT; i++) {
545 printf("Starting SMC fuzz test with seed 0x%x\n", seeds[i]);
546 results[i] = smc_fuzzing_instance(seeds[i]);
547 }
548
549 /* Report successes and failures. */
550 printf("SMC Fuzz Test Results Summary\n");
551 for (i = 0U; i < SMC_FUZZ_INSTANCE_COUNT; i++) {
552 /* Display instance number. */
553 printf(" Instance #%d\n", i);
554
555 /* Print test results. */
556 printf(" Result: ");
557 if (results[i] == TEST_RESULT_SUCCESS) {
558 printf("SUCCESS\n");
559 } else if (results[i] == TEST_RESULT_FAIL) {
560 printf("FAIL\n");
561 /* If we got a failure, update the result value. */
562 result = TEST_RESULT_FAIL;
563 } else if (results[i] == TEST_RESULT_SKIPPED) {
564 printf("SKIPPED\n");
565 }
566
567 /* Print seed used */
568 printf(" Seed: 0x%x\n", seeds[i]);
569 }
570
571 /*
572 * Print out the smc fuzzer parameters so this test can be replicated.
573 */
574 printf("SMC fuzz build parameters to recreate this test:\n");
575 printf(" SMC_FUZZ_INSTANCE_COUNT=%u\n",
576 SMC_FUZZ_INSTANCE_COUNT);
577 printf(" SMC_FUZZ_CALLS_PER_INSTANCE=%u\n",
578 SMC_FUZZ_CALLS_PER_INSTANCE);
579 printf(" SMC_FUZZ_SEEDS=0x%x", seeds[0]);
580 for (i = 1U; i < SMC_FUZZ_INSTANCE_COUNT; i++) {
581 printf(",0x%x", seeds[i]);
582 }
583 printf("\n");
584
585 return result;
586}
mardyk01c14e4ad2023-10-11 16:50:19 -0500587
mardyk01c14e4ad2023-10-11 16:50:19 -0500588test_result_t smc_fuzzing_top(void)
589{
590 test_result_t result = TEST_RESULT_SUCCESS;
591 init_smc_fuzzing();
mardyk017b51dbe2024-01-17 15:25:36 -0600592
mardyk01c14e4ad2023-10-11 16:50:19 -0500593#ifdef MULTI_CPU_SMC_FUZZER
594 u_register_t lead_mpid, target_mpid;
595 int cpu_node;
596 int32_t aff_info __unused;
597 int64_t ret;
598
599 lead_mpid = read_mpidr_el1() & MPID_MASK;
600 for_each_cpu(cpu_node) {
601 target_mpid = tftf_get_mpidr_from_node(cpu_node) & MPID_MASK;
602 if (lead_mpid == target_mpid) {
603 /* Run on this CPU */
604 if (smc_fuzzer_execute() != TEST_RESULT_SUCCESS)
605 return TEST_RESULT_FAIL;
606 } else {
607 /* Power on other CPU to run through fuzzing instructions */
608 ret = tftf_cpu_on(target_mpid,
609 (uintptr_t) smc_fuzzer_execute, 0);
610 if (ret != PSCI_E_SUCCESS) {
611 ERROR("CPU ON failed for 0x%llx\n",
612 (unsigned long long) target_mpid);
613 return TEST_RESULT_FAIL;
614 }
615
616 }
617 }
618
619 smc_fuzzing_deinit();
620 return result;
621#else
622 result = smc_fuzzer_execute();
623 smc_fuzzing_deinit();
624 return result;
625#endif
626}