blob: 10544f9c0b556baa5fd34b0c050dc8cca413ca46 [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 <debug.h>
8#include <drivers/arm/private_timer.h>
9#include <events.h>
10#include "fifo3d.h"
11#include <libfdt.h>
12
13#include <power_management.h>
14#include <sdei.h>
15#include <tftf_lib.h>
16#include <timer.h>
17
18#include <plat_topology.h>
19#include <platform.h>
20
21/*
22 * Priority encoder for enabling proper alignment of returned malloc
23 * addresses
24 */
25struct peret priorityencoder(unsigned int num)
26{
27 unsigned int topbit = 0U;
28 struct peret prt;
29 unsigned int cntbit = 0U;
30
31 for (unsigned int i = TOPBITSIZE; i != 0U; i--) {
32 if (((num >> i) & 1U) == 1U) {
33 if (topbit < i) {
34 topbit = i;
35 }
36 cntbit++;
37 }
38 }
39 if ((num & 1U) == 1U) {
40 cntbit++;
41 }
42
43 prt.pow2 = 0U;
44 if (cntbit == 1U) {
45 prt.pow2 = 1U;
46 }
47 prt.tbit = topbit;
48 return prt;
49}
50
51/*
52 * Generic malloc function requesting memory. Alignment of
53 * returned memory is the next largest size if not a power
54 * of two. The memmod structure is required to represent memory image
55 */
56void *smcmalloc(unsigned int rsize,
57 struct memmod *mmod)
58{
59 unsigned int alignnum;
60 unsigned int modval;
61 unsigned int aladd;
62 unsigned int mallocdeladd_pos = 0U;
63 struct memblk *newblk = NULL;
64 bool foundmem = false;
65 struct peret prt;
66 int incrnmemblk = 0;
67 int incrcntdeladd = 0;
68
69 /*
70 * minimum size is 16
71 */
72 if (rsize < 16U) {
73 rsize = 16U;
74 }
75
76 /*
77 * Is size on a power of 2 boundary? if not select next largest power of 2
78 * to place the memory request in
79 */
80 prt = priorityencoder(rsize);
81 if (prt.pow2 == 1U) {
82 alignnum = 1U << prt.tbit;
83 } else {
84 alignnum = 1U << (prt.tbit + 1);
85 }
86 mmod->memptr = (void *)mmod->memory;
87 for (unsigned int i = 0U; i < mmod->nmemblk; i++) {
88 modval = mmod->memptr->address % alignnum;
89 if (modval == 0U) {
90 aladd = 0U;
91 } else {
92 aladd = alignnum - modval;
93 }
94
95 /*
96 * Searching sizes and alignments of memory blocks to find a candidate that will
97 * accept the size
98 */
99 if ((rsize <= (mmod->memptr->size - aladd)) &&
100 (mmod->memptr->size > aladd) && (mmod->memptr->valid == 1)) {
101 foundmem = true;
102
103 /*
104 * Reuse malloc table entries that have been retired.
105 * If none exists create new entry
106 */
107 if (mmod->mallocdeladd_queue_cnt > 0U) {
108 mmod->mallocdeladd_queue_cnt--;
109 mallocdeladd_pos =
110 mmod->mallocdeladd_queue[mmod->
111 mallocdeladd_queue_cnt];
112 } else {
113 mallocdeladd_pos = mmod->cntdeladd;
114 incrcntdeladd = 1;
115 }
116
117 /*
118 * Determining if the size adheres to power of 2 boundary and
119 * if a retired malloc block
120 * can be utilized from the malloc table
121 */
122 if (modval == 0U) {
123 if (mmod->ptrmemblkqueue > 0U) {
124 newblk = mmod->memblkqueue[mmod->ptrmemblkqueue - 1U];
125 mmod->ptrmemblkqueue--;
126 } else {
127 newblk = mmod->memptrend;
128 newblk++;
129 incrnmemblk = 1;
130 }
131
132 /*
133 * Setting memory block parameters for newly created memory
134 */
135 newblk->size = 0U;
136 newblk->address = mmod->memptr->address;
137 newblk->valid = 1;
138 mmod->precblock[mallocdeladd_pos] = newblk;
139
140 /*
141 * Scrolling through the malloc attribute table to
142 * find entries that have values that
143 * match the newly created block and replace them with it
144 */
145 unsigned int fadd = newblk->address + newblk->size;
146 for (unsigned int j = 0U; j < mmod->cntdeladd; j++) {
147 if ((fadd == mmod->mallocdeladd[j]) && (mmod->mallocdeladd_valid[j] == 1U)) {
148 mmod->precblock[j] = newblk;
149 }
150 if ((fadd ==
151 (mmod->mallocdeladd[j] + mmod->memallocsize[j])) && (mmod->mallocdeladd_valid[j] == 1U)) {
152 mmod->trailblock[j] = newblk;
153 }
154 }
155
156 /*
157 * Setting table parameters
158 */
159 mmod->mallocdeladd[mallocdeladd_pos] =
160 mmod->memptr->address;
161 mmod->memallocsize[mallocdeladd_pos] = rsize;
162 mmod->memptr->size -= rsize;
163 mmod->memptr->address += (rsize);
164 mmod->trailblock[mallocdeladd_pos] = mmod->memptr;
165 mmod->mallocdeladd_valid[mallocdeladd_pos] = 1U;
166 mmod->memptr = (void *)mmod->memory;
167
168 /*
169 * Removing entries from malloc table that can be
170 * merged with other blocks
171 */
172 for (unsigned int j = 0U; j < mmod->nmemblk; j++) {
173 if (mmod->memptr->valid == 1) {
174 if ((mmod->trailblock[mallocdeladd_pos]->address +
175 mmod->trailblock[mallocdeladd_pos]->size) == mmod->memptr->address) {
176 if ((mmod->memptr->size ==
177 0U) && (mmod->trailblock[mallocdeladd_pos]->size != 0U)) {
178 mmod->memptr->valid = 0;
179 mmod->memblkqueue[mmod->ptrmemblkqueue] = mmod->memptr;
180 mmod->ptrmemblkqueue++;
181 if (mmod->ptrmemblkqueue >= mmod->maxmemblk) {
182 mmod->memerror = 1U;
183 }
184 }
185 }
186 }
187 mmod->memptr++;
188 }
189 } else {
190 /*
191 * Allocating memory that is aligned with power of 2
192 */
193 unsigned int nblksize = mmod->memptr->size - rsize - (alignnum - modval);
194 if (mmod->ptrmemblkqueue > 0U) {
195 newblk = mmod->memblkqueue[mmod->ptrmemblkqueue - 1U];
196 mmod->ptrmemblkqueue--;
197 } else {
198 newblk = mmod->memptrend;
199 newblk++;
200 incrnmemblk = 1;
201 }
202 newblk->size = nblksize;
203 newblk->address = mmod->memptr->address +
204 (alignnum - modval) + rsize;
205 newblk->valid = 1;
206 mmod->trailblock[mallocdeladd_pos] = newblk;
207
208 /*
209 * Scrolling through the malloc attribute table to find entries
210 * that have values that
211 * match the newly created block and replace them with it
212 */
213 unsigned int fadd = newblk->address + newblk->size;
214 for (unsigned int i = 0U; i < mmod->cntdeladd; i++) {
215 if ((fadd == mmod->mallocdeladd[i]) && (mmod->mallocdeladd_valid[i] == 1U)) {
216 mmod->precblock[i] = newblk;
217 }
218 if ((fadd == (mmod->mallocdeladd[i] +
219 mmod->memallocsize[i])) && (mmod->mallocdeladd_valid[i] == 1U)) {
220 mmod->trailblock[i] = newblk;
221 }
222 }
223
224 /*
225 * Setting table parameters
226 */
227 mmod->memallocsize[mallocdeladd_pos] = rsize;
228 mmod->memptr->size = (alignnum - modval);
229 mmod->mallocdeladd[mallocdeladd_pos] = mmod->memptr->address + mmod->memptr->size;
230 mmod->precblock[mallocdeladd_pos] = mmod->memptr;
231 mmod->mallocdeladd_valid[mallocdeladd_pos] = 1U;
232 }
233 if (incrcntdeladd == 1) {
234 mmod->cntdeladd++;
235 if (mmod->cntdeladd >= mmod->maxmemblk) {
236 printf("ERROR: size of GENMALLOC table exceeded\n");
237 mmod->memerror = 2U;
238 }
239 }
240 break;
241 }
242 mmod->memptr++;
243 }
244 if (incrnmemblk == 1) {
245 mmod->nmemblk++;
246 mmod->memptrend++;
247 if (mmod->nmemblk >=
248 ((TOTALMEMORYSIZE / BLKSPACEDIV)/sizeof(struct memblk))) {
249 printf("SMC GENMALLOC exceeded block limit of %ld\n",
250 ((TOTALMEMORYSIZE / BLKSPACEDIV) / sizeof(struct memblk)));
251 mmod->memerror = 3U;
252 }
253 }
254 if (foundmem == false) {
255 printf("ERROR: SMC GENMALLOC did not find memory region, size is %u\n", rsize);
256 mmod->memerror = 4U;
257 }
258
259/*
260 * Debug functions
261 */
262
263#ifdef DEBUG_SMC_MALLOC
264 if (mmod->checkadd == 1) {
265 for (unsigned int i = 0U; i < mmod->checknumentries; i++) {
266 if (((mmod->mallocdeladd[mallocdeladd_pos] >
267 mmod->checksa[i])
268 && (mmod->mallocdeladd[mallocdeladd_pos] <
269 mmod->checkea[i]))
270 || (((mmod->mallocdeladd[mallocdeladd_pos] + rsize) >
271 mmod->checksa[i])
272 && ((mmod->mallocdeladd[mallocdeladd_pos] + rsize) <
273 mmod->checkea[i]))) {
274 printf("ERROR: found overlap with previous addressin smc GENMALLOC\n");
275 printf("New address %u size %u\n", mmod->mallocdeladd[mallocdeladd_pos], rsize);
276 printf("Conflicting address %u size %u\n", mmod->checksa[i], (mmod->checkea[i] - mmod->checksa[i]));
277 mmod->memerror = 5U;
278 }
279 }
280 mmod->checksa[mmod->checknumentries] =
281 mmod->mallocdeladd[mallocdeladd_pos];
282 mmod->checkea[mmod->checknumentries] =
283 mmod->mallocdeladd[mallocdeladd_pos] + rsize;
284 mmod->checknumentries++;
285 if (mmod->checknumentries >= (4U * mmod->maxmemblk)) {
286 printf("ERROR: check queue size exceeded\n"); mmod->memerror = 6U;
287 }
288 mmod->memptr = (void *)mmod->memory;
289 for (unsigned int i = 0U; i < mmod->nmemblk; i++) {
290 if (mmod->memptr->valid == 1) {
291 if (((mmod->mallocdeladd[mallocdeladd_pos] >
292 mmod->memptr->address)
293 && (mmod->mallocdeladd[mallocdeladd_pos] < (mmod->memptr->address + mmod->memptr->size)))
294 || (((mmod->mallocdeladd[mallocdeladd_pos] + rsize) > mmod->memptr->address)
295 && ((mmod->mallocdeladd[mallocdeladd_pos] +
296 rsize) < (mmod->memptr->address + mmod->memptr->size)))) {
297 printf("ERROR: found overlap with GENFREE memory region in smc GENMALLOC\n");
298 printf("New address %u size %u\n", mmod->mallocdeladd[mallocdeladd_pos], rsize);
299 printf("Conflicting address %u size %u\n", mmod->memptr->address, mmod->memptr->size);
300 mmod->memerror = 7U;
301 }
302 }
303 mmod->memptr++;
304 }
305 for (unsigned int i = 0U; i < mmod->cntdeladd; i++) {
306 if (mmod->mallocdeladd_valid[i] == 1) {
307 mmod->memptr = (void *)mmod->memory;
308 for (unsigned int j = 0U; j < mmod->nmemblk; j++) {
309 if (mmod->memptr->valid == 1) {
310 if (((mmod->mallocdeladd[i] >
311 mmod->memptr->address)
312 && (mmod->mallocdeladd[i] < (mmod->memptr->address + mmod->memptr->size)))
313 || (((mmod->mallocdeladd[i] + mmod->memallocsize[i]) > mmod->memptr->address)
314 && ((mmod->mallocdeladd[i] + mmod->memallocsize[i]) <
315 (mmod->memptr->address + mmod->memptr->size)))) {
316 printf("ERROR: found overlap with GENFREE memory region ");
317 printf("full search in smc GENMALLOC\n");
318 printf("New address %u size %u\n", mmod->mallocdeladd[i],
319 mmod->memallocsize[i]);
320 printf("Conflicting address %u size %u\n", mmod->memptr->address,
321 mmod->memptr->size);
322 mmod->memerror = 8U;
323 }
324 }
325 mmod->memptr++;
326 }
327 }
328 }
329 mmod->memptr = (void *)mmod->memory;
330 newblk = (void *)mmod->memory;
331 for (unsigned int i = 0U; i < mmod->nmemblk; i++) {
332 if (mmod->memptr->valid == 1) {
333 for (unsigned int j = 0U; j < mmod->nmemblk; j++) {
334 if (newblk->valid == 1) {
335 if (((mmod->memptr->address >
336 newblk->address) && (mmod->memptr->address < (newblk->address + newblk->size)))
337 || (((mmod->memptr->address + mmod->memptr->size) >
338 newblk->address) && ((mmod->memptr->address +
339 mmod->memptr->size) < (newblk->address + newblk->size)))) {
340 printf("ERROR: found overlap in GENFREE memory regions in smc GENMALLOC\n");
341 printf("Region 1 address %u size %u\n", mmod->memptr->address, mmod->memptr->size);
342 printf("Region 2 address %u size %u\n", newblk->address, newblk->size);
343 mmod->memerror = 9U;
344 }
345 }
346 newblk++;
347 }
348 }
349 mmod->memptr++;
350 newblk = (void *)mmod->memory;
351 }
352 }
353#endif
354 return (void *)mmod->memory + ((TOTALMEMORYSIZE / BLKSPACEDIV)) +
355 mmod->mallocdeladd[mallocdeladd_pos];
356#ifdef DEBUG_SMC_MALLOC
357 return (void *)mmod->memory + 0x100U + mmod->mallocdeladd[mallocdeladd_pos];
358#endif
359}
360
361/*
362 * Memory free function for memory allocated from malloc function.
363 * The memmod structure is
364 * required to represent memory image
365 */
366
367int smcfree(void *faddptr,
368 struct memmod *mmod)
369{
370 unsigned int fadd = faddptr - ((TOTALMEMORYSIZE/BLKSPACEDIV)) -
371 (void *)mmod->memory;
372 int fentry = 0;
373 struct memblk *newblk = NULL;
374 int incrnmemblk = 0;
375
376 /*
377 * Scrolling through the malloc attribute table to find entries that match
378 * the user supplied address
379 */
380
381
382 for (unsigned int i = 0U; i < mmod->cntdeladd; i++) {
383 if ((fadd == mmod->mallocdeladd[i]) &&
384 (mmod->mallocdeladd_valid[i] == 1U)) {
385 fentry = 1;
386 if (mmod->trailblock[i] != NULL) {
387 if ((mmod->precblock[i]->address + mmod->precblock[i]->size) == fadd) {
388
389 /*
390 * Found matching attribute block and then proceed to merge with
391 * surrounding blocks
392 */
393
394 mmod->precblock[i]->size += mmod->memallocsize[i] + mmod->trailblock[i]->size;
395 mmod->memblkqueue[mmod->ptrmemblkqueue] = mmod->trailblock[i];
396 mmod->ptrmemblkqueue++;
397 if (mmod->ptrmemblkqueue >= mmod->maxmemblk) {
398 printf("ERROR: GENMALLOC size exceeded in memory block queue\n");
399 exit(1);
400 }
401 mmod->trailblock[i]->valid = 0;
402 newblk = mmod->precblock[i];
403 mmod->memptr = (void *)mmod->memory;
404
405 /*
406 * Scrolling through the malloc attribute table to find entries that have values that
407 * match the newly merged block and replace them with it
408 */
409
410 for (unsigned int j = 0U; j < mmod->nmemblk; j++) {
411 if (mmod->memptr->valid == 1) {
412 if ((mmod->trailblock[i]->address + mmod->trailblock[i]->size) == mmod->memptr->address) {
413 if ((mmod->memptr->size == 0U) &&
414 (mmod->trailblock[i]->size != 0U)) {
415 mmod->memptr->valid = 0;
416 mmod->memblkqueue[mmod->ptrmemblkqueue] = mmod->memptr;
417 mmod->ptrmemblkqueue++;
418 if (mmod->ptrmemblkqueue >= mmod->maxmemblk) {
419 printf("ERROR: GENMALLOC size exceeded in memory block queue\n");
420 exit(1);
421 }
422 }
423 }
424 }
425 mmod->memptr++;
426 }
427 }
428 }
429
430 /*
431 * Setting table parameters
432 */
433
434 mmod->mallocdeladd_valid[i] = 0U;
435 mmod->mallocdeladd_queue[mmod->mallocdeladd_queue_cnt] = i;
436 mmod->mallocdeladd_queue_cnt++;
437 if (mmod->mallocdeladd_queue_cnt >= mmod->maxmemblk) {
438 printf("ERROR: GENMALLOC reuse queue size exceeded\n");
439 exit(1);
440 }
441
442 /*
443 * Scrolling through the malloc attribute table to find entries
444 * that have values that
445 * match the newly merged block and replace them with it
446 */
447
448 unsigned int faddGENFREE = newblk->address + newblk->size;
449 for (unsigned int j = 0U; j < mmod->cntdeladd; j++) {
450 if ((faddGENFREE == mmod->mallocdeladd[j]) &&
451 (mmod->mallocdeladd_valid[j] == 1U))
452 mmod->precblock[j] = newblk;
453 if ((faddGENFREE ==
454 (mmod->mallocdeladd[j] +
455 mmod->memallocsize[i])) &&
456 (mmod->mallocdeladd_valid[j] == 1U))
457 mmod->trailblock[j] = newblk;
458 }
459 }
460 }
461 if (incrnmemblk == 1) {
462 mmod->nmemblk++;
463 mmod->memptrend++;
464 if (mmod->nmemblk >=
465 ((TOTALMEMORYSIZE / BLKSPACEDIV) / sizeof(struct memblk))) {
466 printf("SMC GENFREE exceeded block limit of %ld\n",
467 ((TOTALMEMORYSIZE / BLKSPACEDIV) / sizeof(struct memblk)));
468 exit(1);
469 }
470 }
471 if (fentry == 0) {
472 printf("ERROR: smcGENFREE cannot find address to GENFREE %u\n", fadd);
473 exit(1);
474 }
475#ifdef DEBUG_SMC_MALLOC
476
477/*
478 * Debug functions
479 */
480
481 if (mmod->checkadd == 1) {
482 for (unsigned int i = 0U; i < mmod->checknumentries; i++) {
483 if (fadd == mmod->checksa[i]) {
484 mmod->checksa[i] = 0U;
485 mmod->checkea[i] = 0U;
486 }
487 }
488 mmod->memptr = (void *)mmod->memory;
489 newblk = (void *)mmod->memory;
490 for (unsigned int i = 0U; i < mmod->nmemblk; i++) {
491 if (mmod->memptr->valid == 1) {
492 for (unsigned int j = 0U; j < mmod->nmemblk; j++) {
493 if (newblk->valid == 1) {
494 if (((mmod->memptr->address > newblk->address)
495 && (mmod->memptr->address < (newblk->address + newblk->size)))
496 || (((mmod->memptr->address + mmod->memptr->size) > newblk->address)
497 && ((mmod->memptr->address + mmod->memptr->size) < ((newblk->address + newblk->size))))) {
498 printf("ERROR: found overlap in GENFREE memory regions in smc GENMALLOC\n");
499 printf("Region 1 address %u size %u\n", mmod->memptr->address, mmod->memptr->size);
500 printf("Region 2 address %u size %u\n", newblk->address, newblk->size);
501 }
502 }
503 newblk++;
504 }
505 }
506 mmod->memptr++;
507 newblk = (void *)mmod->memory;
508 }
509 }
510#endif
511 return 0;
512}
513
514/*
515 * Diplay malloc tables for debug purposes
516 */
517
518#ifdef DEBUG_SMC_MALLOC
519void displayblocks(struct memmod *mmod)
520{
521 mmod->memptr = (void *)mmod->memory;
522 printf("Displaying blocks:\n");
523 for (unsigned int i = 0U; i < mmod->nmemblk; i++) {
524 if (mmod->memptr->valid == 1) {
525 printf("*********************************************************************************************\n");
526 printf("%u * Address: %u * Size: %u * Valid: %u *\n", i, mmod->memptr->address, mmod->memptr->size, mmod->memptr->valid);
527 }
528 mmod->memptr++;
529 }
530}
531
532void displaymalloctable(struct memmod *mmod)
533{
534 printf("\n\nDisplaying GENMALLOC table\n");
535 for (unsigned int i = 0U; i < mmod->cntdeladd; i++) {
536 if (mmod->mallocdeladd_valid[i] == 1U) {
537 printf("**********************************************************************************************\n");
538 printf("GENMALLOC Address: %u\n", mmod->mallocdeladd[i]);
539 printf("**********************************************************************************************\n");
540 printf("GENMALLOC Size: %u\n", mmod->memallocsize[i]);
541 printf("**********************************************************************************************\n");
542 if (mmod->trailblock[i] != NULL) {
543 printf("Trail Block:\n");
544 printf("* Address: %u * Size: %u *\n",
545 mmod->trailblock[i]->address,
546 mmod->trailblock[i]->size);
547 }
548 printf("**********************************************************************************************\n");
549 if (mmod->precblock[i] != NULL) {
550 printf("Previous Block:\n");
551 printf("* Address: %u * Size: %u *\n",
552 mmod->precblock[i]->address,
553 mmod->precblock[i]->size);
554 }
555 printf("**********************************************************************************************\n\n\n");
556 }
557 }
558}
559#endif