xref: /arm-trusted-firmware/include/lib/utils.h (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2016-2019, Arm Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #ifndef UTILS_H
8*91f16700Schasinglulu #define UTILS_H
9*91f16700Schasinglulu 
10*91f16700Schasinglulu /*
11*91f16700Schasinglulu  * C code should be put in this part of the header to avoid breaking ASM files
12*91f16700Schasinglulu  * or linker scripts including it.
13*91f16700Schasinglulu  */
14*91f16700Schasinglulu #if !(defined(__LINKER__) || defined(__ASSEMBLER__))
15*91f16700Schasinglulu 
16*91f16700Schasinglulu #include <stddef.h>
17*91f16700Schasinglulu #include <stdint.h>
18*91f16700Schasinglulu 
19*91f16700Schasinglulu typedef struct mem_region {
20*91f16700Schasinglulu 	uintptr_t base;
21*91f16700Schasinglulu 	size_t nbytes;
22*91f16700Schasinglulu } mem_region_t;
23*91f16700Schasinglulu 
24*91f16700Schasinglulu /*
25*91f16700Schasinglulu  * zero_normalmem all the regions defined in tbl.
26*91f16700Schasinglulu  */
27*91f16700Schasinglulu void clear_mem_regions(mem_region_t *tbl, size_t nregions);
28*91f16700Schasinglulu 
29*91f16700Schasinglulu /*
30*91f16700Schasinglulu  * zero_normalmem all the regions defined in region. It dynamically
31*91f16700Schasinglulu  * maps chunks of 'chunk_size' in 'va' virtual address and clears them.
32*91f16700Schasinglulu  * For this reason memory regions must be multiple of chunk_size and
33*91f16700Schasinglulu  * must be aligned to it as well. chunk_size and va can be selected
34*91f16700Schasinglulu  * in a way that they minimize the number of entries used in the
35*91f16700Schasinglulu  * translation tables.
36*91f16700Schasinglulu  */
37*91f16700Schasinglulu void clear_map_dyn_mem_regions(struct mem_region *regions,
38*91f16700Schasinglulu 			       size_t nregions,
39*91f16700Schasinglulu 			       uintptr_t va,
40*91f16700Schasinglulu 			       size_t chunk);
41*91f16700Schasinglulu 
42*91f16700Schasinglulu /*
43*91f16700Schasinglulu  * checks that a region (addr + nbytes-1) of memory is totally covered by
44*91f16700Schasinglulu  * one of the regions defined in tbl. Caller must ensure that (addr+nbytes-1)
45*91f16700Schasinglulu  * doesn't overflow.
46*91f16700Schasinglulu  */
47*91f16700Schasinglulu int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions,
48*91f16700Schasinglulu 			    uintptr_t addr, size_t nbytes);
49*91f16700Schasinglulu 
50*91f16700Schasinglulu /*
51*91f16700Schasinglulu  * Fill a region of normal memory of size "length" in bytes with zero bytes.
52*91f16700Schasinglulu  *
53*91f16700Schasinglulu  * WARNING: This function can only operate on normal memory. This means that
54*91f16700Schasinglulu  *          the MMU must be enabled when using this function. Otherwise, use
55*91f16700Schasinglulu  *          zeromem.
56*91f16700Schasinglulu  */
57*91f16700Schasinglulu void zero_normalmem(void *mem, u_register_t length);
58*91f16700Schasinglulu 
59*91f16700Schasinglulu /*
60*91f16700Schasinglulu  * Fill a region of memory of size "length" in bytes with null bytes.
61*91f16700Schasinglulu  *
62*91f16700Schasinglulu  * Unlike zero_normalmem, this function has no restriction on the type of
63*91f16700Schasinglulu  * memory targeted and can be used for any device memory as well as normal
64*91f16700Schasinglulu  * memory. This function must be used instead of zero_normalmem when MMU is
65*91f16700Schasinglulu  * disabled.
66*91f16700Schasinglulu  *
67*91f16700Schasinglulu  * NOTE: When data cache and MMU are enabled, prefer zero_normalmem for faster
68*91f16700Schasinglulu  *       zeroing.
69*91f16700Schasinglulu  */
70*91f16700Schasinglulu void zeromem(void *mem, u_register_t length);
71*91f16700Schasinglulu 
72*91f16700Schasinglulu /*
73*91f16700Schasinglulu  * Utility function to return the address of a symbol. By default, the
74*91f16700Schasinglulu  * compiler generates adr/adrp instruction pair to return the reference
75*91f16700Schasinglulu  * to the symbol and this utility is used to override this compiler
76*91f16700Schasinglulu  * generated to code to use `ldr` instruction.
77*91f16700Schasinglulu  *
78*91f16700Schasinglulu  * This helps when Position Independent Executable needs to reference a symbol
79*91f16700Schasinglulu  * which is constant and does not depend on the execute address of the binary.
80*91f16700Schasinglulu  */
81*91f16700Schasinglulu #define DEFINE_LOAD_SYM_ADDR(_name)		\
82*91f16700Schasinglulu static inline u_register_t load_addr_## _name(void)			\
83*91f16700Schasinglulu {									\
84*91f16700Schasinglulu 	u_register_t v;							\
85*91f16700Schasinglulu 	__asm__ volatile ("ldr %0, =" #_name : "=r" (v) : "X" (#_name));\
86*91f16700Schasinglulu 	return v;							\
87*91f16700Schasinglulu }
88*91f16700Schasinglulu 
89*91f16700Schasinglulu /* Helper to invoke the function defined by DEFINE_LOAD_SYM_ADDR() */
90*91f16700Schasinglulu #define LOAD_ADDR_OF(_name)	(typeof(_name) *) load_addr_## _name()
91*91f16700Schasinglulu 
92*91f16700Schasinglulu #endif /* !(defined(__LINKER__) || defined(__ASSEMBLER__)) */
93*91f16700Schasinglulu 
94*91f16700Schasinglulu #endif /* UTILS_H */
95