1 /*
2  * Copyright (c) 2022, Cypress Semiconductor Corporation. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <stdint.h>
9 #include "ffm/backend.h"
10 #include "stack_watermark.h"
11 #include "lists.h"
12 #include "load/spm_load_api.h"
13 #include "spm.h"
14 #include "tfm_spm_log.h"
15 
16 /* Always output, regardless of log level.
17  * If you don't want output, don't build this code
18  */
19 #define SPMLOG(x) tfm_hal_output_spm_log((x), sizeof(x))
20 #define SPMLOG_VAL(x, y) spm_log_msgval((x), sizeof(x), y)
21 
22 #define STACK_WATERMARK_VAL 0xdeadbeef
23 
watermark_stack(struct partition_t * p_pt)24 void watermark_stack(struct partition_t *p_pt)
25 {
26     const struct partition_load_info_t *p_pldi = p_pt->p_ldinf;
27 
28     for (int i = 0; i < p_pldi->stack_size / 4; i++) {
29         *((uint32_t *)LOAD_ALLOCED_STACK_ADDR(p_pldi) + i) = STACK_WATERMARK_VAL;
30     }
31 }
32 
33 /* Returns the number of bytes of stack that have been used by the specified partition */
used_stack(struct partition_t * p_pt)34 static uint32_t used_stack(struct partition_t *p_pt)
35 {
36     const struct partition_load_info_t *p_pldi = p_pt->p_ldinf;
37     uint32_t unused_words = 0;
38 
39     for (const uint32_t *p = (uint32_t *)LOAD_ALLOCED_STACK_ADDR(p_pldi);
40          p < (uint32_t *)(LOAD_ALLOCED_STACK_ADDR(p_pldi) + p_pldi->stack_size);
41          p++) {
42         if (*p != STACK_WATERMARK_VAL) {
43             break;
44         }
45         unused_words++;
46     }
47 
48     return p_pldi->stack_size - (unused_words * 4);
49 }
50 
dump_used_stacks(void)51 void dump_used_stacks(void)
52 {
53     struct partition_t *p_pt;
54 
55     SPMLOG("Used stack sizes report\r\n");
56     UNI_LIST_FOREACH(p_pt, PARTITION_LIST_ADDR, next) {
57         SPMLOG_VAL("  Partition id: ", p_pt->p_ldinf->pid);
58         SPMLOG_VAL("    Stack bytes: ", p_pt->p_ldinf->stack_size);
59         SPMLOG_VAL("    Stack bytes used: ", used_stack(p_pt));
60     }
61 }
62