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