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