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