This should hopefully fix the warnings reported.
[linux-2.6/linux-mips.git] / mm / bootmem.c
blob43ade5c96740b5271b55560477070cafba725f20
1 /*
2 * linux/mm/initmem.c
4 * Copyright (C) 1999 Ingo Molnar
5 * Discontiguous memory support, Kanoj Sarcar, SGI, Nov 1999
7 * simple boot-time physical memory area allocator and
8 * free memory collector. It's used to deal with reserved
9 * system memory and memory holes as well.
12 #include <linux/mm.h>
13 #include <linux/kernel_stat.h>
14 #include <linux/swap.h>
15 #include <linux/swapctl.h>
16 #include <linux/interrupt.h>
17 #include <linux/init.h>
18 #include <linux/bootmem.h>
19 #include <linux/mmzone.h>
20 #include <asm/dma.h>
23 * Access to this subsystem has to be serialized externally. (this is
24 * true for the boot process anyway)
26 unsigned long max_low_pfn;
28 /* return the number of _pages_ that will be allocated for the boot bitmap */
29 unsigned long __init bootmem_bootmap_pages (unsigned long pages)
31 unsigned long mapsize;
33 mapsize = (pages+7)/8;
34 mapsize = (mapsize + ~PAGE_MASK) & PAGE_MASK;
35 mapsize >>= PAGE_SHIFT;
37 return mapsize;
41 * Called once to set up the allocator itself.
43 static unsigned long __init init_bootmem_core (bootmem_data_t *bdata,
44 unsigned long mapstart, unsigned long start, unsigned long end)
46 unsigned long mapsize = ((end - start)+7)/8;
48 mapsize = (mapsize + (sizeof(long) - 1UL)) & ~(sizeof(long) - 1UL);
49 bdata->node_bootmem_map = phys_to_virt(mapstart << PAGE_SHIFT);
50 bdata->node_boot_start = (start << PAGE_SHIFT);
51 bdata->node_low_pfn = end;
54 * Initially all pages are reserved - setup_arch() has to
55 * register free RAM areas explicitly.
57 memset(bdata->node_bootmem_map, 0xff, mapsize);
59 return mapsize;
63 * Marks a particular physical memory range as unallocatable. Usable RAM
64 * might be used for boot-time allocations - or it might get added
65 * to the free page pool later on.
67 static void __init reserve_bootmem_core(bootmem_data_t *bdata, unsigned long addr, unsigned long size)
69 unsigned long i;
71 * round up, partially reserved pages are considered
72 * fully reserved.
74 unsigned long sidx = (addr - bdata->node_boot_start)/PAGE_SIZE;
75 unsigned long eidx = (addr + size - bdata->node_boot_start +
76 PAGE_SIZE-1)/PAGE_SIZE;
77 unsigned long end = (addr + size + PAGE_SIZE-1)/PAGE_SIZE;
79 if (!size) BUG();
81 if (end > bdata->node_low_pfn)
82 BUG();
83 for (i = sidx; i < eidx; i++)
84 if (test_and_set_bit(i, bdata->node_bootmem_map))
85 BUG();
88 static void __init free_bootmem_core(bootmem_data_t *bdata, unsigned long addr, unsigned long size)
90 unsigned long i;
91 unsigned long start;
93 * round down end of usable mem, partially free pages are
94 * considered reserved.
96 unsigned long sidx;
97 unsigned long eidx = (addr + size - bdata->node_boot_start)/PAGE_SIZE;
98 unsigned long end = (addr + size)/PAGE_SIZE;
100 if (!size) BUG();
101 if (end > bdata->node_low_pfn)
102 BUG();
105 * Round up the beginning of the address.
107 start = (addr + PAGE_SIZE-1) / PAGE_SIZE;
108 sidx = start - (bdata->node_boot_start/PAGE_SIZE);
110 for (i = sidx; i < eidx; i++) {
111 if (!test_and_clear_bit(i, bdata->node_bootmem_map))
112 BUG();
117 * We 'merge' subsequent allocations to save space. We might 'lose'
118 * some fraction of a page if allocations cannot be satisfied due to
119 * size constraints on boxes where there is physical RAM space
120 * fragmentation - in these cases * (mostly large memory boxes) this
121 * is not a problem.
123 * On low memory boxes we get it right in 100% of the cases.
127 * alignment has to be a power of 2 value.
129 static void * __init __alloc_bootmem_core (bootmem_data_t *bdata,
130 unsigned long size, unsigned long align, unsigned long goal)
132 unsigned long i, start = 0;
133 void *ret;
134 unsigned long offset, remaining_size;
135 unsigned long areasize, preferred, incr;
136 unsigned long eidx = bdata->node_low_pfn - (bdata->node_boot_start >>
137 PAGE_SHIFT);
139 if (!size) BUG();
142 * We try to allocate bootmem pages above 'goal'
143 * first, then we try to allocate lower pages.
145 if (goal && (goal >= bdata->node_boot_start) &&
146 ((goal >> PAGE_SHIFT) < bdata->node_low_pfn)) {
147 preferred = goal - bdata->node_boot_start;
148 } else
149 preferred = 0;
151 preferred = ((preferred + align - 1) & ~(align - 1)) >> PAGE_SHIFT;
152 areasize = (size+PAGE_SIZE-1)/PAGE_SIZE;
153 incr = align >> PAGE_SHIFT ? : 1;
155 restart_scan:
156 for (i = preferred; i < eidx; i += incr) {
157 unsigned long j;
158 if (test_bit(i, bdata->node_bootmem_map))
159 continue;
160 for (j = i + 1; j < i + areasize; ++j) {
161 if (j >= eidx)
162 goto fail_block;
163 if (test_bit (j, bdata->node_bootmem_map))
164 goto fail_block;
166 start = i;
167 goto found;
168 fail_block:;
170 if (preferred) {
171 preferred = 0;
172 goto restart_scan;
175 * Whoops, we cannot satisfy the allocation request.
177 BUG();
178 found:
179 if (start >= eidx)
180 BUG();
183 * Is the next page of the previous allocation-end the start
184 * of this allocation's buffer? If yes then we can 'merge'
185 * the previous partial page with this allocation.
187 if (align <= PAGE_SIZE
188 && bdata->last_offset && bdata->last_pos+1 == start) {
189 offset = (bdata->last_offset+align-1) & ~(align-1);
190 if (offset > PAGE_SIZE)
191 BUG();
192 remaining_size = PAGE_SIZE-offset;
193 if (size < remaining_size) {
194 areasize = 0;
195 // last_pos unchanged
196 bdata->last_offset = offset+size;
197 ret = phys_to_virt(bdata->last_pos*PAGE_SIZE + offset +
198 bdata->node_boot_start);
199 } else {
200 remaining_size = size - remaining_size;
201 areasize = (remaining_size+PAGE_SIZE-1)/PAGE_SIZE;
202 ret = phys_to_virt(bdata->last_pos*PAGE_SIZE + offset +
203 bdata->node_boot_start);
204 bdata->last_pos = start+areasize-1;
205 bdata->last_offset = remaining_size;
207 bdata->last_offset &= ~PAGE_MASK;
208 } else {
209 bdata->last_pos = start + areasize - 1;
210 bdata->last_offset = size & ~PAGE_MASK;
211 ret = phys_to_virt(start * PAGE_SIZE + bdata->node_boot_start);
214 * Reserve the area now:
216 for (i = start; i < start+areasize; i++)
217 if (test_and_set_bit(i, bdata->node_bootmem_map))
218 BUG();
219 memset(ret, 0, size);
220 return ret;
223 static unsigned long __init free_all_bootmem_core(int nid, bootmem_data_t *bdata)
225 struct page * page;
226 unsigned long i, count, total = 0;
227 unsigned long idx;
229 if (!bdata->node_bootmem_map) BUG();
231 page = NODE_MEM_MAP(nid);
232 count = 0;
233 idx = bdata->node_low_pfn - (bdata->node_boot_start >> PAGE_SHIFT);
234 for (i = 0; i < idx; i++, page++) {
235 if (!test_bit(i, bdata->node_bootmem_map)) {
236 count++;
237 ClearPageReserved(page);
238 set_page_count(page, 1);
239 __free_page(page);
242 total += count;
245 * Now free the allocator bitmap itself, it's not
246 * needed anymore:
248 page = mem_map + MAP_NR(bdata->node_bootmem_map);
249 count = 0;
250 for (i = 0; i < ((bdata->node_low_pfn-(bdata->node_boot_start >> PAGE_SHIFT))/8 + PAGE_SIZE-1)/PAGE_SIZE; i++,page++) {
251 count++;
252 ClearPageReserved(page);
253 set_page_count(page, 1);
254 __free_page(page);
256 total += count;
257 bdata->node_bootmem_map = NULL;
259 return total;
262 unsigned long __init init_bootmem_node (int nid, unsigned long freepfn, unsigned long startpfn, unsigned long endpfn)
264 return(init_bootmem_core(NODE_DATA(nid)->bdata, freepfn, startpfn, endpfn));
267 void __init reserve_bootmem_node (int nid, unsigned long physaddr, unsigned long size)
269 reserve_bootmem_core(NODE_DATA(nid)->bdata, physaddr, size);
272 void __init free_bootmem_node (int nid, unsigned long physaddr, unsigned long size)
274 return(free_bootmem_core(NODE_DATA(nid)->bdata, physaddr, size));
277 unsigned long __init free_all_bootmem_node (int nid)
279 return(free_all_bootmem_core(nid, NODE_DATA(nid)->bdata));
282 unsigned long __init init_bootmem (unsigned long start, unsigned long pages)
284 max_low_pfn = pages;
285 return(init_bootmem_core(NODE_DATA(0)->bdata, start, 0, pages));
288 void __init reserve_bootmem (unsigned long addr, unsigned long size)
290 reserve_bootmem_core(NODE_DATA(0)->bdata, addr, size);
293 void __init free_bootmem (unsigned long addr, unsigned long size)
295 return(free_bootmem_core(NODE_DATA(0)->bdata, addr, size));
298 unsigned long __init free_all_bootmem (void)
300 return(free_all_bootmem_core(0, NODE_DATA(0)->bdata));
303 void * __init __alloc_bootmem (unsigned long size, unsigned long align, unsigned long goal)
306 * In the discontigmem case, all non-node specific allocations come
307 * from the first node, node 0.
309 return(__alloc_bootmem_core(NODE_DATA(0)->bdata, size, align, goal));
312 void * __init __alloc_bootmem_node (int nid, unsigned long size, unsigned long align, unsigned long goal)
314 return(__alloc_bootmem_core(NODE_DATA(nid)->bdata, size, align, goal));