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