xref: /rk3399_ARM-atf/include/lib/utils.h (revision 09d40e0e08283a249e7dce0e106c07c5141f9b7e)
1ed81f3ebSSandrine Bailleux /*
2638b034cSRoberto Vargas  * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
3ed81f3ebSSandrine Bailleux  *
482cb2c1aSdp-arm  * SPDX-License-Identifier: BSD-3-Clause
5ed81f3ebSSandrine Bailleux  */
6ed81f3ebSSandrine Bailleux 
7c3cf06f1SAntonio Nino Diaz #ifndef UTILS_H
8c3cf06f1SAntonio Nino Diaz #define UTILS_H
9ed81f3ebSSandrine Bailleux 
10308d359bSDouglas Raillard /*
11308d359bSDouglas Raillard  * C code should be put in this part of the header to avoid breaking ASM files
12308d359bSDouglas Raillard  * or linker scripts including it.
13308d359bSDouglas Raillard  */
14308d359bSDouglas Raillard #if !(defined(__LINKER__) || defined(__ASSEMBLY__))
15308d359bSDouglas Raillard 
16*09d40e0eSAntonio Nino Diaz #include <stddef.h>
1793c78ed2SAntonio Nino Diaz #include <stdint.h>
18308d359bSDouglas Raillard 
19109ae263SMasahiro Yamada typedef struct mem_region {
2043cbaf06SRoberto Vargas 	uintptr_t base;
2143cbaf06SRoberto Vargas 	size_t nbytes;
2243cbaf06SRoberto Vargas } mem_region_t;
2343cbaf06SRoberto Vargas 
2443cbaf06SRoberto Vargas /*
2543cbaf06SRoberto Vargas  * zero_normalmem all the regions defined in tbl.
2643cbaf06SRoberto Vargas  */
2743cbaf06SRoberto Vargas void clear_mem_regions(mem_region_t *tbl, size_t nregions);
2843cbaf06SRoberto Vargas 
29638b034cSRoberto Vargas /*
30638b034cSRoberto Vargas  * zero_normalmem all the regions defined in region. It dynamically
31638b034cSRoberto Vargas  * maps chunks of 'chunk_size' in 'va' virtual address and clears them.
32638b034cSRoberto Vargas  * For this reason memory regions must be multiple of chunk_size and
33638b034cSRoberto Vargas  * must be aligned to it as well. chunk_size and va can be selected
34638b034cSRoberto Vargas  * in a way that they minimize the number of entries used in the
35638b034cSRoberto Vargas  * translation tables.
36638b034cSRoberto Vargas  */
37c96f297fSRoberto Vargas void clear_map_dyn_mem_regions(struct mem_region *regions,
38638b034cSRoberto Vargas 			       size_t nregions,
39638b034cSRoberto Vargas 			       uintptr_t va,
40c96f297fSRoberto Vargas 			       size_t chunk);
4143cbaf06SRoberto Vargas 
4243cbaf06SRoberto Vargas /*
4343cbaf06SRoberto Vargas  * checks that a region (addr + nbytes-1) of memory is totally covered by
4443cbaf06SRoberto Vargas  * one of the regions defined in tbl. Caller must ensure that (addr+nbytes-1)
4543cbaf06SRoberto Vargas  * doesn't overflow.
4643cbaf06SRoberto Vargas  */
4743cbaf06SRoberto Vargas int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions,
4843cbaf06SRoberto Vargas 			    uintptr_t addr, size_t nbytes);
4943cbaf06SRoberto Vargas 
50308d359bSDouglas Raillard /*
51308d359bSDouglas Raillard  * Fill a region of normal memory of size "length" in bytes with zero bytes.
52308d359bSDouglas Raillard  *
53308d359bSDouglas Raillard  * WARNING: This function can only operate on normal memory. This means that
54308d359bSDouglas Raillard  *          the MMU must be enabled when using this function. Otherwise, use
55308d359bSDouglas Raillard  *          zeromem.
56308d359bSDouglas Raillard  */
57308d359bSDouglas Raillard void zero_normalmem(void *mem, u_register_t length);
58308d359bSDouglas Raillard 
59308d359bSDouglas Raillard /*
60308d359bSDouglas Raillard  * Fill a region of memory of size "length" in bytes with null bytes.
61308d359bSDouglas Raillard  *
62308d359bSDouglas Raillard  * Unlike zero_normalmem, this function has no restriction on the type of
63308d359bSDouglas Raillard  * memory targeted and can be used for any device memory as well as normal
64308d359bSDouglas Raillard  * memory. This function must be used instead of zero_normalmem when MMU is
65308d359bSDouglas Raillard  * disabled.
66308d359bSDouglas Raillard  *
67308d359bSDouglas Raillard  * NOTE: When data cache and MMU are enabled, prefer zero_normalmem for faster
68308d359bSDouglas Raillard  *       zeroing.
69308d359bSDouglas Raillard  */
70308d359bSDouglas Raillard void zeromem(void *mem, u_register_t length);
716a7b3005SSoby Mathew 
726a7b3005SSoby Mathew /*
736a7b3005SSoby Mathew  * Utility function to return the address of a symbol. By default, the
746a7b3005SSoby Mathew  * compiler generates adr/adrp instruction pair to return the reference
756a7b3005SSoby Mathew  * to the symbol and this utility is used to override this compiler
766a7b3005SSoby Mathew  * generated to code to use `ldr` instruction.
776a7b3005SSoby Mathew  *
786a7b3005SSoby Mathew  * This helps when Position Independent Executable needs to reference a symbol
796a7b3005SSoby Mathew  * which is constant and does not depend on the execute address of the binary.
806a7b3005SSoby Mathew  */
816a7b3005SSoby Mathew #define DEFINE_LOAD_SYM_ADDR(_name)		\
826a7b3005SSoby Mathew static inline u_register_t load_addr_## _name(void)		\
836a7b3005SSoby Mathew {								\
846a7b3005SSoby Mathew 	u_register_t v;						\
856a7b3005SSoby Mathew 	/* Create a void reference to silence compiler */	\
866a7b3005SSoby Mathew 	(void) _name;						\
876a7b3005SSoby Mathew 	__asm__ volatile ("ldr %0, =" #_name : "=r" (v));	\
886a7b3005SSoby Mathew 	return v;						\
896a7b3005SSoby Mathew }
906a7b3005SSoby Mathew 
916a7b3005SSoby Mathew /* Helper to invoke the function defined by DEFINE_LOAD_SYM_ADDR() */
926a7b3005SSoby Mathew #define LOAD_ADDR_OF(_name)	(typeof(_name) *) load_addr_## _name()
936a7b3005SSoby Mathew 
94308d359bSDouglas Raillard #endif /* !(defined(__LINKER__) || defined(__ASSEMBLY__)) */
95308d359bSDouglas Raillard 
96c3cf06f1SAntonio Nino Diaz #endif /* UTILS_H */
97