blob: 2b8d01729b18c40c17841b4e8396732fe6d2c6a1 [file] [log] [blame]
Mark Dykese7810b52020-06-03 15:46:55 -05001/*
2 * Copyright (c) 2020, Arm Limited. All rights reserved.
3 *
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"
12#include <libfdt.h>
13
14#include <power_management.h>
15#include <sdei.h>
16#include <tftf_lib.h>
17#include <timer.h>
18
19#include <plat_topology.h>
20#include <platform.h>
21
22extern char _binary___dtb_start[];
23
24struct memmod tmod __aligned(65536) __section("smcfuzz");
25
26/*
27 * switch to use either standard C malloc or custom SMC malloc
28 */
29
30#define FIRST_NODE_DEVTREE_OFFSET (8)
31
32#ifdef SMC_FUZZ_TMALLOC
33#define GENMALLOC(x) malloc((x))
34#define GENFREE(x) free((x))
35#else
36#define GENMALLOC(x) smcmalloc((x), mmod)
37#define GENFREE(x) smcfree((x), mmod)
38#endif
39
40/*
41 * Device tree parameter struct
42 */
43
44struct fdt_header_sf {
45 unsigned int magic;
46 unsigned int totalsize;
47 unsigned int off_dt_struct;
48 unsigned int off_dt_strings;
49 unsigned int off_mem_rsvmap;
50 unsigned int version;
51 unsigned int last_comp_version;
52 unsigned int boot_cpuid_phys;
53 unsigned int size_dt_strings;
54 unsigned int size_dt_struct;
55};
56
57/*
58 * Structure to read the fields of the device tree
59 */
60struct propval {
61 unsigned int len;
62 unsigned int nameoff;
63};
64
65/*
66 * Converting from big endian to little endian to read values
67 * of device tree
68 */
69unsigned int lendconv(unsigned int val)
70{
71 unsigned int res;
72
73 res = val << 24;
74 res |= ((val << 8) & 0xFF0000U);
75 res |= ((val >> 8) & 0xFF00U);
76 res |= ((val >> 24) & 0xFFU);
77 return res;
78}
79
80/*
81 * Function to read strings from device tree
82 */
83void pullstringdt(void **dtb,
84 void *dtb_beg,
85 unsigned int offset,
86 char *cset)
87{
88 int fistr;
89 int cntchr;
90 char rval;
91
92 if (offset != 0U) {
93 *dtb = dtb_beg + offset;
94 }
95 fistr = 0;
96
97 cntchr = 0;
98 while (fistr == 0) {
99 rval = *((char *)*dtb);
100 *dtb += sizeof(char);
101 cset[cntchr] = rval;
102 if (cset[cntchr] == 0) {
103 fistr = 1;
104 }
105 cntchr++;
106 }
107
108 if ((cntchr % 4) != 0) {
109 for (unsigned int i = 0U; (int)i < (4 - (cntchr % 4)); i++) {
110 *dtb += sizeof(char);
111 }
112 }
113}
114
115/*
116 * Structure for Node information extracted from device tree
117 */
118struct rand_smc_node {
119 int *biases; // Biases of the individual nodes
120 int *biasarray; // Array of biases across all nodes
121 char **snames; // String that is unique to the SMC call called in test
122 struct rand_smc_node *treenodes; // Selection of nodes that are farther down in the tree
123 // that reference further rand_smc_node objects
124 int *norcall; // Specifies whether a particular node is a leaf node or tree node
125 int entries; // Number of nodes in object
126 int biasent; // Number that gives the total number of entries in biasarray
127 // based on all biases of the nodes
128 char **nname; // Array of node names
129};
130
131
132/*
133 * Create bias tree from given device tree description
134 */
135
136struct rand_smc_node *createsmctree(int *casz,
137 struct memmod *mmod)
138{
139 void *dtb;
140 void *dtb_pn;
141 void *dtb_beg;
142 struct fdt_header fhd;
143 unsigned int rval;
144 struct propval pv;
145 char cset[MAX_NAME_CHARS];
146 char nodename[MAX_NAME_CHARS];
147 int dtdone;
148 struct fifo3d f3d;
149 int leafnode = 0;
150 unsigned int fnode = 0U;
151 unsigned int bias_count = 0U;
152 unsigned int bintnode = 0U;
153 unsigned int treenodetrack = 0U;
154 struct fdt_header *fhdptr;
155 struct rand_smc_node *ndarray = NULL;
156 int cntndarray;
157 struct rand_smc_node nrnode;
158 struct rand_smc_node *tndarray;
159
160 f3d.col = 0;
161 f3d.curr_col = 0;
162
163 /*
164 * Read device tree header and check for valid type
165 */
166
167 fhdptr = (struct fdt_header *)_binary___dtb_start;
168
169 if (fdt_check_header((void *)fhdptr) != 0) {
170 printf("ERROR, not device tree compliant\n");
171 }
172 fhd = *fhdptr;
173 cntndarray = 0;
174 nrnode.entries = 0;
175
176 /*
177 * Create pointers to device tree data
178 */
179 dtb = _binary___dtb_start;
180 dtb_pn = _binary___dtb_start;
181
182 dtb_beg = dtb;
183 fhd = *((struct fdt_header *)dtb);
184 dtb += (fdt32_to_cpu(fhd.off_dt_struct) + FIRST_NODE_DEVTREE_OFFSET);
185 dtdone = 0;
186
187 /*
188 * Reading device tree file
189 */
190 while (dtdone == 0) {
191 rval = *((unsigned int *)dtb);
192 dtb += sizeof(unsigned int);
193
194 /*
195 * Reading node name from device tree and pushing it into the raw data
196 * Table of possible values reading from device tree binary file:
197 * 1 New node found within current tree, possible leaf or tree variant
198 * 2 Node termination of current hiearchy.
199 * Could indicate end of tree or preparation for another branch
200 * 3 Leaf node indication where a bias with a function name should be
201 * found for the current node
202 * 9 End of device tree file and we end the read of the bias tree
203 */
204 if (fdt32_to_cpu(rval) == 1) {
205 pullstringdt(&dtb, dtb_beg, 0U, cset);
206 push_3dfifo_col(&f3d, cset, mmod);
207 strlcpy(nodename, cset, MAX_NAME_CHARS);
208
209 /*
210 * Error checking to make sure that bias is specified
211 */
212 if (fnode == 0U) {
213 fnode = 1U;
214 } else {
215 if (!((fnode == 1U) && (bias_count == 1U))) {
216 printf("ERROR: Did not find bias or multiple bias ");
217 printf("designations before %s %u %u\n",
218 cset, fnode, bias_count);
219 }
220 bias_count = 0U;
221 }
222 }
223
224 /*
225 * Reading node parameters of bias and function name
226 */
227 if (fdt32_to_cpu(rval) == 3) {
228 pv = *((struct propval *)dtb);
229 dtb += sizeof(struct propval);
230 pullstringdt(&dtb_pn, dtb_beg,
231 (fdt32_to_cpu(fhd.off_dt_strings) +
232 fdt32_to_cpu(pv.nameoff)), cset);
233 if (strcmp(cset, "bias") == 0) {
234 rval = *((unsigned int *)dtb);
235 dtb += sizeof(unsigned int);
236 push_3dfifo_bias(&f3d, fdt32_to_cpu(rval));
237 bias_count++;
238 if (bintnode == 1U) {
239 fnode = 0U;
240 bintnode = 0U;
241 bias_count = 0U;
242 }
243 }
244 if (strcmp(cset, "functionname") == 0) {
245 pullstringdt(&dtb, dtb_beg, 0, cset);
246 push_3dfifo_fname(&f3d, cset);
247 leafnode = 1;
248 if (bias_count == 0U) {
249 bintnode = 1U;
250 fnode = 1U;
251 } else {
252 bias_count = 0U;
253 fnode = 0U;
254 }
255 }
256 }
257
258 /*
259 * Node termination and evaluate whether the bias tree requires addition.
260 * The non tree nodes are added.
261 */
262 if (fdt32_to_cpu(rval) == 2) {
263 if ((fnode > 0U) || (bias_count > 0U)) {
264 printf("ERROR: early node termination... ");
265 printf("no bias or functionname field for leaf node, near %s %u\n",
266 nodename, fnode);
267 }
268 f3d.col--;
269 if (leafnode == 1) {
270 leafnode = 0;
271 } else {
272 /*
273 * Create bias tree in memory from raw data
274 */
275 tndarray =
276 GENMALLOC((cntndarray + 1) *
277 sizeof(struct rand_smc_node));
278 unsigned int treenodetrackmal = 0;
279 for (unsigned int j = 0U; (int)j < cntndarray; j++) {
280 tndarray[j].biases = GENMALLOC(ndarray[j].entries * sizeof(int));
281 tndarray[j].snames = GENMALLOC(ndarray[j].entries * sizeof(char *));
282 tndarray[j].norcall = GENMALLOC(ndarray[j].entries * sizeof(int));
283 tndarray[j].nname = GENMALLOC(ndarray[j].entries * sizeof(char *));
284 tndarray[j].treenodes = GENMALLOC(ndarray[j].entries * sizeof(struct rand_smc_node));
285 tndarray[j].entries = ndarray[j].entries;
286 for (unsigned int i = 0U; (int)i < ndarray[j].entries; i++) {
287 tndarray[j].snames[i] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
288 strlcpy(tndarray[j].snames[i], ndarray[j].snames[i], MAX_NAME_CHARS);
289 tndarray[j].nname[i] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
290 strlcpy(tndarray[j].nname[i], ndarray[j].nname[i], MAX_NAME_CHARS);
291 tndarray[j].biases[i] = ndarray[j].biases[i];
292 tndarray[j].norcall[i] = ndarray[j].norcall[i];
293 if (tndarray[j].norcall[i] == 1) {
294 tndarray[j].treenodes[i] = tndarray[treenodetrackmal];
295 treenodetrackmal++;
296 }
297 }
298 tndarray[j].biasent = ndarray[j].biasent;
299 tndarray[j].biasarray = GENMALLOC((tndarray[j].biasent) * sizeof(int));
300 for (unsigned int i = 0U; (int)i < ndarray[j].biasent; i++) {
301 tndarray[j].biasarray[i] = ndarray[j].biasarray[i];
302 }
303 }
304 tndarray[cntndarray].biases = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(int));
305 tndarray[cntndarray].snames = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(char *));
306 tndarray[cntndarray].norcall = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(int));
307 tndarray[cntndarray].nname = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(char *));
308 tndarray[cntndarray].treenodes = GENMALLOC(f3d.row[f3d.col + 1] * sizeof(struct rand_smc_node));
309 tndarray[cntndarray].entries = f3d.row[f3d.col + 1];
310
311 /*
312 * Populate bias tree with former values in tree
313 */
314 int cntbias = 0;
315 int bias_count = 0;
316 for (unsigned int j = 0U; (int)j < f3d.row[f3d.col + 1]; j++) {
317 tndarray[cntndarray].snames[j] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
318 strlcpy(tndarray[cntndarray].snames[j], f3d.fnamefifo[f3d.col + 1][j], MAX_NAME_CHARS);
319 tndarray[cntndarray].nname[j] = GENMALLOC(1 * sizeof(char[MAX_NAME_CHARS]));
320 strlcpy(tndarray[cntndarray].nname[j], f3d.nnfifo[f3d.col + 1][j], MAX_NAME_CHARS);
321 tndarray[cntndarray].biases[j] = f3d.biasfifo[f3d.col + 1][j];
322 cntbias += tndarray[cntndarray].biases[j];
323 if (strcmp(tndarray[cntndarray].snames[j], "none") != 0) {
324 strlcpy(tndarray[cntndarray].snames[j], f3d.fnamefifo[f3d.col + 1][j], MAX_NAME_CHARS);
325 tndarray[cntndarray].norcall[j] = 0;
326 tndarray[cntndarray].treenodes[j] = nrnode;
327 } else {
328 tndarray[cntndarray].norcall[j] = 1;
329 tndarray[cntndarray].treenodes[j] = tndarray[treenodetrack];
330 treenodetrack++;
331 }
332 }
333
334 tndarray[cntndarray].biasent = cntbias;
335 tndarray[cntndarray].biasarray = GENMALLOC((tndarray[cntndarray].biasent) * sizeof(int));
336 for (unsigned int j = 0U; j < tndarray[cntndarray].entries; j++) {
337 for (unsigned int i = 0U; i < tndarray[cntndarray].biases[j]; i++) {
338 tndarray[cntndarray].biasarray[bias_count] = j;
339 bias_count++;
340 }
341 }
342
343 /*
344 * Free memory of old bias tree
345 */
346 if (cntndarray > 0) {
347 for (unsigned int j = 0U; (int)j < cntndarray; j++) {
348 for (unsigned int i = 0U;
349 (int)i < ndarray[j].entries;
350 i++) {
351 GENFREE(ndarray[j].snames[i]);
352 GENFREE(ndarray[j].nname[i]);
353 }
354 GENFREE(ndarray[j].biases);
355 GENFREE(ndarray[j].norcall);
356 GENFREE(ndarray[j].biasarray);
357 GENFREE(ndarray[j].snames);
358 GENFREE(ndarray[j].nname);
359 GENFREE(ndarray[j].treenodes);
360 }
361 GENFREE(ndarray);
362 }
363
364 /*
365 * Move pointers to new bias tree to current tree
366 */
367 ndarray = tndarray;
368 cntndarray++;
369
370 /*
371 * Free raw data
372 */
373 for (unsigned int j = 0U; (int)j < f3d.row[f3d.col + 1]; j++) {
374 GENFREE(f3d.nnfifo[f3d.col + 1][j]);
375 GENFREE(f3d.fnamefifo[f3d.col + 1][j]);
376 }
377 GENFREE(f3d.nnfifo[f3d.col + 1]);
378 GENFREE(f3d.fnamefifo[f3d.col + 1]);
379 GENFREE(f3d.biasfifo[f3d.col + 1]);
380 f3d.curr_col -= 1;
381 }
382 }
383
384 /*
385 * Ending device tree file and freeing raw data
386 */
387 if (fdt32_to_cpu(rval) == 9) {
388 for (unsigned int i = 0U; (int)i < f3d.col; i++) {
389 for (unsigned int j = 0U; (int)j < f3d.row[i]; j++) {
390 GENFREE(f3d.nnfifo[i][j]);
391 GENFREE(f3d.fnamefifo[i][j]);
392 }
393 GENFREE(f3d.nnfifo[i]);
394 GENFREE(f3d.fnamefifo[i]);
395 GENFREE(f3d.biasfifo[i]);
396 }
397 GENFREE(f3d.nnfifo);
398 GENFREE(f3d.fnamefifo);
399 GENFREE(f3d.biasfifo);
400 GENFREE(f3d.row);
401 dtdone = 1;
402 }
403 }
404
405
406 *casz = cntndarray;
407 return ndarray;
408}
409
410/*
411 * Running SMC call from what function name is selected
412 */
413void runtestfunction(char *funcstr)
414{
415 if (strcmp(funcstr, "sdei_version") == 0) {
416 long long ret = sdei_version();
417 if (ret != MAKE_SDEI_VERSION(1, 0, 0)) {
418 tftf_testcase_printf("Unexpected SDEI version: 0x%llx\n",
419 ret);
420 }
421 printf("running %s\n", funcstr);
422 }
423 if (strcmp(funcstr, "sdei_pe_unmask") == 0) {
424 long long ret = sdei_pe_unmask();
425 if (ret < 0) {
426 tftf_testcase_printf("SDEI pe unmask failed: 0x%llx\n",
427 ret);
428 }
429 printf("running %s\n", funcstr);
430 }
431 if (strcmp(funcstr, "sdei_pe_mask") == 0) {
432 int64_t ret = sdei_pe_mask();
433 if (ret < 0) {
434 tftf_testcase_printf("SDEI pe mask failed: 0x%llx\n", ret);
435 }
436 printf("running %s\n", funcstr);
437 }
438 if (strcmp(funcstr, "sdei_event_status") == 0) {
439 int64_t ret = sdei_event_status(0);
440 if (ret < 0) {
441 tftf_testcase_printf("SDEI event status failed: 0x%llx\n",
442 ret);
443 }
444 printf("running %s\n", funcstr);
445 }
446 if (strcmp(funcstr, "sdei_event_signal") == 0) {
447 int64_t ret = sdei_event_signal(0);
448 if (ret < 0) {
449 tftf_testcase_printf("SDEI event signal failed: 0x%llx\n",
450 ret);
451 }
452 printf("running %s\n", funcstr);
453 }
454 if (strcmp(funcstr, "sdei_private_reset") == 0) {
455 int64_t ret = sdei_private_reset();
456 if (ret < 0) {
457 tftf_testcase_printf("SDEI private reset failed: 0x%llx\n",
458 ret);
459 }
460 printf("running %s\n", funcstr);
461 }
462 if (strcmp(funcstr, "sdei_shared_reset") == 0) {
463 int64_t ret = sdei_shared_reset();
464 if (ret < 0) {
465 tftf_testcase_printf("SDEI shared reset failed: 0x%llx\n",
466 ret);
467 }
468 printf("running %s\n", funcstr);
469 }
470}
471
472/*
473 * Top of SMC fuzzing module
474 */
475test_result_t smc_fuzzing_top(void)
476{
477 /*
478 * Setting up malloc block parameters
479 */
480 tmod.memptr = (void *)tmod.memory;
481 tmod.memptrend = (void *)tmod.memory;
482 tmod.maxmemblk = ((TOTALMEMORYSIZE / BLKSPACEDIV) / sizeof(struct memblk));
483 tmod.nmemblk = 1;
484 tmod.memptr->address = 0U;
485 tmod.memptr->size = TOTALMEMORYSIZE - (TOTALMEMORYSIZE / BLKSPACEDIV);
486 tmod.memptr->valid = 1;
487 tmod.mallocdeladd[0] = 0U;
488 tmod.precblock[0] = (void *)tmod.memory;
489 tmod.trailblock[0] = NULL;
490 tmod.cntdeladd = 0U;
491 tmod.ptrmemblkqueue = 0U;
492 tmod.mallocdeladd_queue_cnt = 0U;
493 tmod.checkadd = 1U;
494 tmod.checknumentries = 0U;
495 tmod.memerror = 0U;
496 struct memmod *mmod;
497 mmod = &tmod;
498 int cntndarray;
499 struct rand_smc_node *tlnode;
500
501 /*
502 * Creating SMC bias tree
503 */
504 struct rand_smc_node *ndarray = createsmctree(&cntndarray, &tmod);
505
506 if (tmod.memerror != 0) {
507 return TEST_RESULT_FAIL;
508 }
509
510 /*
511 * Hard coded seed, will change in the near future for better strategy
512 */
513 srand(89758389);
514
515 /*
516 * Code to traverse the bias tree and select function based on the biaes within
517 *
518 * The algorithm starts with the first node to pull up the biasarray. The
519 * array is specified as a series of values that reflect the bias of the nodes
520 * in question. So for instance if there are three nodes with a bias of 2,5,7
521 * the biasarray would have the following constituency:
522 *
523 * 0,0,1,1,1,1,1,2,2,2,2,2,2,2.
524 *
525 * Mapping 0 as node 1, 1 as node 2, and 2 as node 3.
526 * The biasent variable contains the count of the size of the biasarray which
527 * provides the input for random selection. This is subsequently applied as an
528 * index to the biasarray. The selection pulls up the node and then is checked
529 * for whether it is a leaf or tree node using the norcall variable.
530 * If it is a leaf then the bias tree traversal ends with an SMC call.
531 * If it is a tree node then the process begins again with
532 * another loop to continue the process of selection until an eventual leaf
533 * node is found.
534 */
535 for (unsigned int i = 0U; i < 100U; i++) {
536 tlnode = &ndarray[cntndarray - 1];
537 int nd = 0;
538 while (nd == 0) {
539 int nch = rand()%tlnode->biasent;
540 int selent = tlnode->biasarray[nch];
541 if (tlnode->norcall[selent] == 0) {
542 runtestfunction(tlnode->snames[selent]);
543 nd = 1;
544 } else {
545 tlnode = &tlnode->treenodes[selent];
546 }
547 }
548 }
549
550 /*
551 * End of test SMC selection and freeing of nodes
552 */
553 if (cntndarray > 0) {
554 for (unsigned int j = 0U; j < cntndarray; j++) {
555 for (unsigned int i = 0U; i < ndarray[j].entries; i++) {
556 GENFREE(ndarray[j].snames[i]);
557 GENFREE(ndarray[j].nname[i]);
558 }
559 GENFREE(ndarray[j].biases);
560 GENFREE(ndarray[j].norcall);
561 GENFREE(ndarray[j].biasarray);
562 GENFREE(ndarray[j].snames);
563 GENFREE(ndarray[j].nname);
564 GENFREE(ndarray[j].treenodes);
565 }
566 GENFREE(ndarray);
567 }
568
569 return TEST_RESULT_SUCCESS;
570}