xref: /kvm-unit-tests/lib/alloc.h (revision 417d476228ec217723154b24e351a5948efbb2af)
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