1 /* Copyright 2013-2014 IBM Corp.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * 	http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12  * implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <config.h>
18 #include <stdbool.h>
19 #include <stdint.h>
20 
21 /* The lock backtrace structures consume too much room on the skiboot heap */
22 #undef DEBUG_LOCKS_BACKTRACE
23 
24 #define BITS_PER_LONG (sizeof(long) * 8)
25 
26 #include "dummy-cpu.h"
27 
28 #include <stdlib.h>
29 #include <string.h>
30 
31 /* Use these before we override definitions below. */
real_malloc(size_t size)32 static void *real_malloc(size_t size)
33 {
34 	return malloc(size);
35 }
36 
real_free(void * p)37 static inline void real_free(void *p)
38 {
39 	return free(p);
40 }
41 
42 #undef malloc
43 #undef free
44 #undef realloc
45 
46 #include <skiboot.h>
47 
48 #define is_rodata(p) true
49 
50 #include "../mem_region.c"
51 #include "../malloc.c"
52 #include "../device.c"
53 
54 #include <assert.h>
55 #include <stdio.h>
56 
57 struct dt_node *dt_root;
58 enum proc_chip_quirks proc_chip_quirks;
59 
lock_caller(struct lock * l,const char * caller)60 void lock_caller(struct lock *l, const char *caller)
61 {
62 	(void)caller;
63 	assert(!l->lock_val);
64 	l->lock_val++;
65 }
66 
unlock(struct lock * l)67 void unlock(struct lock *l)
68 {
69 	assert(l->lock_val);
70 	l->lock_val--;
71 }
72 
lock_held_by_me(struct lock * l)73 bool lock_held_by_me(struct lock *l)
74 {
75 	return l->lock_val;
76 }
77 
78 #define TEST_HEAP_ORDER 12
79 #define TEST_HEAP_SIZE (1ULL << TEST_HEAP_ORDER)
80 
heap_empty(void)81 static bool heap_empty(void)
82 {
83 	const struct alloc_hdr *h = region_start(&skiboot_heap);
84 	return h->num_longs == skiboot_heap.len / sizeof(long);
85 }
86 
main(void)87 int main(void)
88 {
89 	char *test_heap;
90 	void *p, *ptrs[100];
91 	size_t i;
92 	struct mem_region *r;
93 
94 	/* Use malloc for the heap, so valgrind can find issues. */
95 	test_heap = real_malloc(TEST_HEAP_SIZE);
96 	skiboot_heap.start = (unsigned long)test_heap;
97 	skiboot_heap.len = TEST_HEAP_SIZE;
98 
99 	lock(&skiboot_heap.free_list_lock);
100 
101 	/* Allocations of various sizes. */
102 	for (i = 0; i < TEST_HEAP_ORDER; i++) {
103 		p = mem_alloc(&skiboot_heap, 1ULL << i, 1, "here");
104 		assert(p);
105 		assert(mem_check(&skiboot_heap));
106 		assert(!strcmp(((struct alloc_hdr *)p)[-1].location, "here"));
107 		assert(p > (void *)test_heap);
108 		assert(p + (1ULL << i) <= (void *)test_heap + TEST_HEAP_SIZE);
109 		assert(mem_allocated_size(p) >= 1ULL << i);
110 		mem_free(&skiboot_heap, p, "freed");
111 		assert(heap_empty());
112 		assert(mem_check(&skiboot_heap));
113 		assert(!strcmp(((struct alloc_hdr *)p)[-1].location, "freed"));
114 	}
115 	p = mem_alloc(&skiboot_heap, 1ULL << i, 1, "here");
116 	assert(!p);
117 	mem_free(&skiboot_heap, p, "freed");
118 	assert(heap_empty());
119 	assert(mem_check(&skiboot_heap));
120 
121 	/* Allocations of various alignments: use small alloc first. */
122 	ptrs[0] = mem_alloc(&skiboot_heap, 1, 1, "small");
123 	for (i = 0; ; i++) {
124 		p = mem_alloc(&skiboot_heap, 1, 1ULL << i, "here");
125 		assert(mem_check(&skiboot_heap));
126 		/* We will eventually fail... */
127 		if (!p) {
128 			assert(i >= TEST_HEAP_ORDER);
129 			break;
130 		}
131 		assert(p);
132 		assert((long)p % (1ULL << i) == 0);
133 		assert(p > (void *)test_heap);
134 		assert(p + 1 <= (void *)test_heap + TEST_HEAP_SIZE);
135 		mem_free(&skiboot_heap, p, "freed");
136 		assert(mem_check(&skiboot_heap));
137 	}
138 	mem_free(&skiboot_heap, ptrs[0], "small freed");
139 	assert(heap_empty());
140 	assert(mem_check(&skiboot_heap));
141 
142 	/* Many little allocations, freed in reverse order. */
143 	for (i = 0; i < 100; i++) {
144 		ptrs[i] = mem_alloc(&skiboot_heap, sizeof(long), 1, "here");
145 		assert(ptrs[i]);
146 		assert(ptrs[i] > (void *)test_heap);
147 		assert(ptrs[i] + sizeof(long)
148 		       <= (void *)test_heap + TEST_HEAP_SIZE);
149 		assert(mem_check(&skiboot_heap));
150 	}
151 	mem_dump_free();
152 	for (i = 0; i < 100; i++)
153 		mem_free(&skiboot_heap, ptrs[100 - 1 - i], "freed");
154 
155 	assert(heap_empty());
156 	assert(mem_check(&skiboot_heap));
157 
158 	/* Check the prev_free gets updated properly. */
159 	ptrs[0] = mem_alloc(&skiboot_heap, sizeof(long), 1, "ptrs[0]");
160 	ptrs[1] = mem_alloc(&skiboot_heap, sizeof(long), 1, "ptrs[1]");
161 	assert(ptrs[1] > ptrs[0]);
162 	mem_free(&skiboot_heap, ptrs[0], "ptrs[0] free");
163 	assert(mem_check(&skiboot_heap));
164 	ptrs[0] = mem_alloc(&skiboot_heap, sizeof(long), 1, "ptrs[0] again");
165 	assert(mem_check(&skiboot_heap));
166 	mem_free(&skiboot_heap, ptrs[1], "ptrs[1] free");
167 	mem_free(&skiboot_heap, ptrs[0], "ptrs[0] free");
168 	assert(mem_check(&skiboot_heap));
169 	assert(heap_empty());
170 
171 #if 0
172 	printf("Heap map:\n");
173 	for (i = 0; i < TEST_HEAP_SIZE / sizeof(long); i++) {
174 		printf("%u", test_bit(skiboot_heap.bitmap, i));
175 		if (i % 64 == 63)
176 			printf("\n");
177 		else if (i % 8 == 7)
178 			printf(" ");
179 	}
180 #endif
181 
182 	/* Simple enlargement, then free */
183 	p = mem_alloc(&skiboot_heap, 1, 1, "one byte");
184 	assert(p);
185 	assert(mem_resize(&skiboot_heap, p, 100, "hundred bytes"));
186 	assert(mem_allocated_size(p) >= 100);
187 	assert(mem_check(&skiboot_heap));
188 	assert(!strcmp(((struct alloc_hdr *)p)[-1].location, "hundred bytes"));
189 	mem_free(&skiboot_heap, p, "freed");
190 
191 	/* Simple shrink, then free */
192 	p = mem_alloc(&skiboot_heap, 100, 1, "100 bytes");
193 	assert(p);
194 	assert(mem_resize(&skiboot_heap, p, 1, "1 byte"));
195 	assert(mem_allocated_size(p) < 100);
196 	assert(mem_check(&skiboot_heap));
197 	assert(!strcmp(((struct alloc_hdr *)p)[-1].location, "1 byte"));
198 	mem_free(&skiboot_heap, p, "freed");
199 
200 	/* Lots of resizing (enlarge). */
201 	p = mem_alloc(&skiboot_heap, 1, 1, "one byte");
202 	assert(p);
203 	for (i = 1; i <= TEST_HEAP_SIZE - sizeof(struct alloc_hdr); i++) {
204 		assert(mem_resize(&skiboot_heap, p, i, "enlarge"));
205 		assert(mem_allocated_size(p) >= i);
206 		assert(mem_check(&skiboot_heap));
207 	}
208 
209 	/* Can't make it larger though. */
210 	assert(!mem_resize(&skiboot_heap, p, i, "enlarge"));
211 
212 	for (i = TEST_HEAP_SIZE - sizeof(struct alloc_hdr); i > 0; i--) {
213 		assert(mem_resize(&skiboot_heap, p, i, "shrink"));
214 		assert(mem_check(&skiboot_heap));
215 	}
216 
217 	mem_free(&skiboot_heap, p, "freed");
218 	assert(mem_check(&skiboot_heap));
219 
220 	unlock(&skiboot_heap.free_list_lock);
221 
222 	/* lock the regions list */
223 	lock(&mem_region_lock);
224 	/* Test splitting of a region. */
225 	r = new_region("base", (unsigned long)test_heap,
226 		       TEST_HEAP_SIZE, NULL, REGION_SKIBOOT_HEAP);
227 	assert(add_region(r));
228 	r = new_region("splitter", (unsigned long)test_heap + TEST_HEAP_SIZE/4,
229 		       TEST_HEAP_SIZE/2, NULL, REGION_RESERVED);
230 	assert(add_region(r));
231 	/* Now we should have *three* regions. */
232 	i = 0;
233 	list_for_each(&regions, r, list) {
234 		if (region_start(r) == test_heap) {
235 			assert(r->len == TEST_HEAP_SIZE/4);
236 			assert(strcmp(r->name, "base") == 0);
237 			assert(r->type == REGION_SKIBOOT_HEAP);
238 		} else if (region_start(r) == test_heap + TEST_HEAP_SIZE / 4) {
239 			assert(r->len == TEST_HEAP_SIZE/2);
240 			assert(strcmp(r->name, "splitter") == 0);
241 			assert(r->type == REGION_RESERVED);
242 			assert(!r->free_list.n.next);
243 		} else if (region_start(r) == test_heap + TEST_HEAP_SIZE/4*3) {
244 			assert(r->len == TEST_HEAP_SIZE/4);
245 			assert(strcmp(r->name, "base") == 0);
246 			assert(r->type == REGION_SKIBOOT_HEAP);
247 		} else
248 			abort();
249 		assert(mem_check(r));
250 		i++;
251 	}
252 	mem_dump_free();
253 	assert(i == 3);
254 	while ((r = list_pop(&regions, struct mem_region, list)) != NULL) {
255 		lock(&skiboot_heap.free_list_lock);
256 		mem_free(&skiboot_heap, r, __location__);
257 		unlock(&skiboot_heap.free_list_lock);
258 	}
259 	unlock(&mem_region_lock);
260 	assert(skiboot_heap.free_list_lock.lock_val == 0);
261 	real_free(test_heap);
262 	return 0;
263 }
264