1*417d4762SAndrew Jones #ifndef _ALLOC_H_ 2*417d4762SAndrew Jones #define _ALLOC_H_ 3*417d4762SAndrew Jones /* 4*417d4762SAndrew Jones * alloc supplies three ingredients to the test framework that are all 5*417d4762SAndrew Jones * related to the support of dynamic memory allocation. 6*417d4762SAndrew Jones * 7*417d4762SAndrew Jones * The first is a set of alloc function wrappers for malloc and its 8*417d4762SAndrew Jones * friends. Using wrappers allows test code and common code to use the 9*417d4762SAndrew Jones * same interface for memory allocation at all stages, even though the 10*417d4762SAndrew Jones * implementations may change with the stage, e.g. pre/post paging. 11*417d4762SAndrew Jones * 12*417d4762SAndrew Jones * The second is a set of implementations for the alloc function 13*417d4762SAndrew Jones * interfaces. These implementations are named early_*, as they can be 14*417d4762SAndrew Jones * used almost immediately by the test framework. 15*417d4762SAndrew Jones * 16*417d4762SAndrew Jones * The third is a very simple physical memory allocator, which the 17*417d4762SAndrew Jones * early_* alloc functions build on. 18*417d4762SAndrew Jones * 19*417d4762SAndrew Jones * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com> 20*417d4762SAndrew Jones * 21*417d4762SAndrew Jones * This work is licensed under the terms of the GNU LGPL, version 2. 22*417d4762SAndrew Jones */ 23*417d4762SAndrew Jones #include "libcflat.h" 24*417d4762SAndrew Jones 25*417d4762SAndrew Jones struct alloc_ops { 26*417d4762SAndrew Jones void *(*malloc)(size_t size); 27*417d4762SAndrew Jones void *(*calloc)(size_t nmemb, size_t size); 28*417d4762SAndrew Jones void (*free)(void *ptr); 29*417d4762SAndrew Jones void *(*memalign)(size_t alignment, size_t size); 30*417d4762SAndrew Jones }; 31*417d4762SAndrew Jones 32*417d4762SAndrew Jones /* 33*417d4762SAndrew Jones * alloc_ops is initialized to early_alloc_ops 34*417d4762SAndrew Jones */ 35*417d4762SAndrew Jones extern struct alloc_ops *alloc_ops; 36*417d4762SAndrew Jones 37*417d4762SAndrew Jones static inline void *malloc(size_t size) 38*417d4762SAndrew Jones { 39*417d4762SAndrew Jones assert(alloc_ops && alloc_ops->malloc); 40*417d4762SAndrew Jones return alloc_ops->malloc(size); 41*417d4762SAndrew Jones } 42*417d4762SAndrew Jones 43*417d4762SAndrew Jones static inline void *calloc(size_t nmemb, size_t size) 44*417d4762SAndrew Jones { 45*417d4762SAndrew Jones assert(alloc_ops && alloc_ops->calloc); 46*417d4762SAndrew Jones return alloc_ops->calloc(nmemb, size); 47*417d4762SAndrew Jones } 48*417d4762SAndrew Jones 49*417d4762SAndrew Jones static inline void free(void *ptr) 50*417d4762SAndrew Jones { 51*417d4762SAndrew Jones assert(alloc_ops && alloc_ops->free); 52*417d4762SAndrew Jones alloc_ops->free(ptr); 53*417d4762SAndrew Jones } 54*417d4762SAndrew Jones 55*417d4762SAndrew Jones static inline void *memalign(size_t alignment, size_t size) 56*417d4762SAndrew Jones { 57*417d4762SAndrew Jones assert(alloc_ops && alloc_ops->memalign); 58*417d4762SAndrew Jones return alloc_ops->memalign(alignment, size); 59*417d4762SAndrew Jones } 60*417d4762SAndrew Jones 61*417d4762SAndrew Jones #ifdef PHYS32 62*417d4762SAndrew Jones typedef u32 phys_addr_t; 63*417d4762SAndrew Jones #else 64*417d4762SAndrew Jones typedef u64 phys_addr_t; 65*417d4762SAndrew Jones #endif 66*417d4762SAndrew Jones #define INVALID_PHYS_ADDR (~(phys_addr_t)0) 67*417d4762SAndrew Jones 68*417d4762SAndrew Jones /* 69*417d4762SAndrew Jones * phys_alloc is a very simple allocator which allows physical memory 70*417d4762SAndrew Jones * to be partitioned into regions until all memory is allocated. 71*417d4762SAndrew Jones * 72*417d4762SAndrew Jones * Note: This is such a simple allocator that there is no way to free 73*417d4762SAndrew Jones * a region. For more complicated memory management a single region 74*417d4762SAndrew Jones * can be allocated, but then have its memory managed by a more 75*417d4762SAndrew Jones * sophisticated allocator, e.g. a page allocator. 76*417d4762SAndrew Jones */ 77*417d4762SAndrew Jones #define DEFAULT_MINIMUM_ALIGNMENT 32 78*417d4762SAndrew Jones 79*417d4762SAndrew Jones /* 80*417d4762SAndrew Jones * phys_alloc_init creates the initial free memory region of size @size 81*417d4762SAndrew Jones * at @base. The minimum alignment is set to DEFAULT_MINIMUM_ALIGNMENT. 82*417d4762SAndrew Jones */ 83*417d4762SAndrew Jones extern void phys_alloc_init(phys_addr_t base, phys_addr_t size); 84*417d4762SAndrew Jones 85*417d4762SAndrew Jones /* 86*417d4762SAndrew Jones * phys_alloc_set_minimum_alignment sets the minimum alignment to 87*417d4762SAndrew Jones * @align. 88*417d4762SAndrew Jones */ 89*417d4762SAndrew Jones extern void phys_alloc_set_minimum_alignment(phys_addr_t align); 90*417d4762SAndrew Jones 91*417d4762SAndrew Jones /* 92*417d4762SAndrew Jones * phys_alloc_aligned returns the base address of a region of size @size, 93*417d4762SAndrew Jones * where the address is aligned to @align, or INVALID_PHYS_ADDR if there 94*417d4762SAndrew Jones * isn't enough free memory to satisfy the request. 95*417d4762SAndrew Jones */ 96*417d4762SAndrew Jones extern phys_addr_t phys_alloc_aligned(phys_addr_t size, phys_addr_t align); 97*417d4762SAndrew Jones 98*417d4762SAndrew Jones /* 99*417d4762SAndrew Jones * phys_zalloc_aligned is like phys_alloc_aligned, but zeros the memory 100*417d4762SAndrew Jones * before returning the address. 101*417d4762SAndrew Jones */ 102*417d4762SAndrew Jones extern phys_addr_t phys_zalloc_aligned(phys_addr_t size, phys_addr_t align); 103*417d4762SAndrew Jones 104*417d4762SAndrew Jones /* 105*417d4762SAndrew Jones * phys_alloc returns the base address of a region of size @size, or 106*417d4762SAndrew Jones * INVALID_PHYS_ADDR if there isn't enough free memory to satisfy the 107*417d4762SAndrew Jones * request. 108*417d4762SAndrew Jones */ 109*417d4762SAndrew Jones extern phys_addr_t phys_alloc(phys_addr_t size); 110*417d4762SAndrew Jones 111*417d4762SAndrew Jones /* 112*417d4762SAndrew Jones * phys_zalloc is like phys_alloc, but zeros the memory before returning. 113*417d4762SAndrew Jones */ 114*417d4762SAndrew Jones extern phys_addr_t phys_zalloc(phys_addr_t size); 115*417d4762SAndrew Jones 116*417d4762SAndrew Jones /* 117*417d4762SAndrew Jones * phys_alloc_show outputs all currently allocated regions with the 118*417d4762SAndrew Jones * following format 119*417d4762SAndrew Jones * <start_addr>-<end_addr> [<USED|FREE>] 120*417d4762SAndrew Jones */ 121*417d4762SAndrew Jones extern void phys_alloc_show(void); 122*417d4762SAndrew Jones 123*417d4762SAndrew Jones #endif /* _ALLOC_H_ */ 124