mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-19 02:54:24 +00:00

This patch adds a utility function to return the address of a symbol. By default, the compiler generates adr/adrp instruction pair to return the reference and this utility is used to override this compiler generated to code and use `ldr` instruction. This is needed for Position Independent Executable when it needs to reference a symbol which is constant and does not depend on the execute address of the binary. For example, on the FVP, the GICv3 register context is stored in a secure carveout (arm_el3_tzc_dram) within DDR and does not relocate with the BL image. Now if BL31 is executing at a different address other than the compiled address, using adrp/adr instructions to reference this memory will not work as they generate an address that is PC relative. The way to get around this problem is to reference it as non-PC relative (i.e non-relocatable location) via `ldr` instruction. Change-Id: I5008a951b007144258121690afb68dc8e12ee6f7 Signed-off-by: Soby Mathew <soby.mathew@arm.com>
95 lines
3 KiB
C
95 lines
3 KiB
C
/*
|
|
* Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
|
|
#ifndef __UTILS_H__
|
|
#define __UTILS_H__
|
|
|
|
/*
|
|
* C code should be put in this part of the header to avoid breaking ASM files
|
|
* or linker scripts including it.
|
|
*/
|
|
#if !(defined(__LINKER__) || defined(__ASSEMBLY__))
|
|
|
|
#include <stdint.h>
|
|
|
|
typedef struct mem_region {
|
|
uintptr_t base;
|
|
size_t nbytes;
|
|
} mem_region_t;
|
|
|
|
/*
|
|
* zero_normalmem all the regions defined in tbl.
|
|
*/
|
|
void clear_mem_regions(mem_region_t *tbl, size_t nregions);
|
|
|
|
/*
|
|
* zero_normalmem all the regions defined in region. It dynamically
|
|
* maps chunks of 'chunk_size' in 'va' virtual address and clears them.
|
|
* For this reason memory regions must be multiple of chunk_size and
|
|
* must be aligned to it as well. chunk_size and va can be selected
|
|
* in a way that they minimize the number of entries used in the
|
|
* translation tables.
|
|
*/
|
|
void clear_map_dyn_mem_regions(struct mem_region *regions,
|
|
size_t nregions,
|
|
uintptr_t va,
|
|
size_t chunk);
|
|
|
|
/*
|
|
* checks that a region (addr + nbytes-1) of memory is totally covered by
|
|
* one of the regions defined in tbl. Caller must ensure that (addr+nbytes-1)
|
|
* doesn't overflow.
|
|
*/
|
|
int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions,
|
|
uintptr_t addr, size_t nbytes);
|
|
|
|
/*
|
|
* Fill a region of normal memory of size "length" in bytes with zero bytes.
|
|
*
|
|
* WARNING: This function can only operate on normal memory. This means that
|
|
* the MMU must be enabled when using this function. Otherwise, use
|
|
* zeromem.
|
|
*/
|
|
void zero_normalmem(void *mem, u_register_t length);
|
|
|
|
/*
|
|
* Fill a region of memory of size "length" in bytes with null bytes.
|
|
*
|
|
* Unlike zero_normalmem, this function has no restriction on the type of
|
|
* memory targeted and can be used for any device memory as well as normal
|
|
* memory. This function must be used instead of zero_normalmem when MMU is
|
|
* disabled.
|
|
*
|
|
* NOTE: When data cache and MMU are enabled, prefer zero_normalmem for faster
|
|
* zeroing.
|
|
*/
|
|
void zeromem(void *mem, u_register_t length);
|
|
|
|
/*
|
|
* Utility function to return the address of a symbol. By default, the
|
|
* compiler generates adr/adrp instruction pair to return the reference
|
|
* to the symbol and this utility is used to override this compiler
|
|
* generated to code to use `ldr` instruction.
|
|
*
|
|
* This helps when Position Independent Executable needs to reference a symbol
|
|
* which is constant and does not depend on the execute address of the binary.
|
|
*/
|
|
#define DEFINE_LOAD_SYM_ADDR(_name) \
|
|
static inline u_register_t load_addr_## _name(void) \
|
|
{ \
|
|
u_register_t v; \
|
|
/* Create a void reference to silence compiler */ \
|
|
(void) _name; \
|
|
__asm__ volatile ("ldr %0, =" #_name : "=r" (v)); \
|
|
return v; \
|
|
}
|
|
|
|
/* Helper to invoke the function defined by DEFINE_LOAD_SYM_ADDR() */
|
|
#define LOAD_ADDR_OF(_name) (typeof(_name) *) load_addr_## _name()
|
|
|
|
#endif /* !(defined(__LINKER__) || defined(__ASSEMBLY__)) */
|
|
|
|
#endif /* __UTILS_H__ */
|