2 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
7 /*******************************************************************************
8 * The profiler stores the timestamps captured during cold boot to the shared
9 * memory for the non-secure world. The non-secure world driver parses the
10 * shared memory block and writes the contents to a file on the device, which
11 * can be later extracted for analysis.
15 * TOP --------------------------- ---
16 * Trusted OS timestamps 3KB
17 * --------------------------- ---
18 * Trusted Firmware timestamps 1KB
19 * BASE --------------------------- ---
21 ******************************************************************************/
24 #include <arch_helpers.h>
27 #include <lib/utils_def.h>
28 #include <lib/xlat_tables/xlat_tables_v2.h>
33 static uint64_t shmem_base_addr
;
35 #define MAX_PROFILER_RECORDS U(16)
36 #define TAG_LEN_BYTES U(56)
38 /*******************************************************************************
39 * Profiler entry format
40 ******************************************************************************/
42 /* text explaining the timestamp location in code */
43 uint8_t tag
[TAG_LEN_BYTES
];
48 static profiler_rec_t
*head
, *cur
, *tail
;
50 static bool is_shmem_buf_mapped
;
52 /*******************************************************************************
53 * Initialise the profiling library
54 ******************************************************************************/
55 void boot_profiler_init(uint64_t shmem_base
, uint32_t tmr_base
)
57 uint64_t shmem_end_base
;
59 assert(shmem_base
!= ULL(0));
60 assert(tmr_base
!= U(0));
62 /* store the buffer address */
63 shmem_base_addr
= shmem_base
;
65 /* calculate the base address of the last record */
66 shmem_end_base
= shmem_base
+ (sizeof(profiler_rec_t
) *
67 (MAX_PROFILER_RECORDS
- U(1)));
69 /* calculate the head, tail and cur values */
70 head
= (profiler_rec_t
*)shmem_base
;
71 tail
= (profiler_rec_t
*)shmem_end_base
;
74 /* timer used to get the current timestamp */
78 /*******************************************************************************
79 * Add tag and timestamp to profiler
80 ******************************************************************************/
81 void boot_profiler_add_record(const char *str
)
85 /* calculate the length of the tag */
86 if (((unsigned int)strlen(str
) + U(1)) > TAG_LEN_BYTES
) {
89 len
= (unsigned int)strlen(str
) + U(1);
95 * The profiler runs with/without MMU enabled. Check
96 * if MMU is enabled and memmap the shmem buffer, in
99 if ((!is_shmem_buf_mapped
) &&
100 ((read_sctlr_el3() & SCTLR_M_BIT
) != U(0))) {
102 (void)mmap_add_dynamic_region(shmem_base_addr
,
105 (MT_NS
| MT_RW
| MT_EXECUTE_NEVER
));
107 is_shmem_buf_mapped
= true;
110 /* write the tag and timestamp to buffer */
111 (void)snprintf((char *)cur
->tag
, len
, "%s", str
);
112 cur
->timestamp
= mmio_read_32(tmr
);
114 /* start from head if we reached the end */
123 /*******************************************************************************
124 * Deinint the profiler
125 ******************************************************************************/
126 void boot_profiler_deinit(void)
128 if (shmem_base_addr
!= ULL(0)) {
130 /* clean up resources */
135 /* flush the shmem for it to be visible to the NS world */
136 flush_dcache_range(shmem_base_addr
, PROFILER_SIZE_BYTES
);
138 /* unmap the shmem buffer */
139 if (is_shmem_buf_mapped
) {
140 (void)mmap_remove_dynamic_region(shmem_base_addr
,
141 PROFILER_SIZE_BYTES
);