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