]>
Commit | Line | Data |
---|---|---|
55e303ae A |
1 | /* |
2 | * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. | |
3 | * | |
8f6c56a5 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
55e303ae | 5 | * |
8f6c56a5 A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. The rights granted to you under the License | |
10 | * may not be used to create, or enable the creation or redistribution of, | |
11 | * unlawful or unlicensed copies of an Apple operating system, or to | |
12 | * circumvent, violate, or enable the circumvention or violation of, any | |
13 | * terms of an Apple operating system software license agreement. | |
14 | * | |
15 | * Please obtain a copy of the License at | |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. | |
17 | * | |
18 | * The Original Code and all software distributed under the License are | |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
23 | * Please see the License for the specific language governing rights and | |
8ad349bb | 24 | * limitations under the License. |
8f6c56a5 A |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ | |
55e303ae A |
27 | */ |
28 | /* | |
29 | * @OSF_COPYRIGHT@ | |
30 | */ | |
31 | /* | |
32 | * Mach Operating System | |
33 | * Copyright (c) 1991,1990,1989, 1988 Carnegie Mellon University | |
34 | * All Rights Reserved. | |
35 | * | |
36 | * Permission to use, copy, modify and distribute this software and its | |
37 | * documentation is hereby granted, provided that both the copyright | |
38 | * notice and this permission notice appear in all copies of the | |
39 | * software, derivative works or modified versions, and any portions | |
40 | * thereof, and that both notices appear in supporting documentation. | |
41 | * | |
42 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | |
43 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | |
44 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | |
45 | * | |
46 | * Carnegie Mellon requests users of this software to return to | |
47 | * | |
48 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | |
49 | * School of Computer Science | |
50 | * Carnegie Mellon University | |
51 | * Pittsburgh PA 15213-3890 | |
52 | * | |
53 | * any improvements or extensions that they make and grant Carnegie Mellon | |
54 | * the rights to redistribute these changes. | |
55 | */ | |
56 | ||
55e303ae A |
57 | #include <platforms.h> |
58 | #include <mach_kdb.h> | |
55e303ae A |
59 | |
60 | #include <mach/i386/vm_param.h> | |
61 | ||
62 | #include <string.h> | |
63 | #include <mach/vm_param.h> | |
64 | #include <mach/vm_prot.h> | |
65 | #include <mach/machine.h> | |
66 | #include <mach/time_value.h> | |
55e303ae A |
67 | #include <kern/spl.h> |
68 | #include <kern/assert.h> | |
69 | #include <kern/debug.h> | |
70 | #include <kern/misc_protos.h> | |
71 | #include <kern/cpu_data.h> | |
72 | #include <kern/processor.h> | |
73 | #include <vm/vm_page.h> | |
74 | #include <vm/pmap.h> | |
75 | #include <vm/vm_kern.h> | |
76 | #include <i386/pmap.h> | |
77 | #include <i386/ipl.h> | |
55e303ae A |
78 | #include <i386/misc_protos.h> |
79 | #include <i386/mp_slave_boot.h> | |
91447636 | 80 | #include <i386/cpuid.h> |
55e303ae | 81 | #include <mach/thread_status.h> |
4452a7af A |
82 | #include <pexpert/i386/efi.h> |
83 | #include "i386_lowmem.h" | |
55e303ae A |
84 | |
85 | vm_size_t mem_size = 0; | |
55e303ae A |
86 | vm_offset_t first_avail = 0;/* first after page tables */ |
87 | vm_offset_t last_addr; | |
88 | ||
4452a7af A |
89 | uint64_t max_mem; /* Size of physical memory (bytes), adjusted by maxmem */ |
90 | uint64_t mem_actual; | |
91 | uint64_t sane_size = 0; /* Memory size to use for defaults calculations */ | |
92 | ||
93 | #define MAXBOUNCEPOOL (128 * 1024 * 1024) | |
94 | #define MAXLORESERVE ( 32 * 1024 * 1024) | |
95 | ||
96 | extern int bsd_mbuf_cluster_reserve(void); | |
97 | ||
98 | ||
99 | uint32_t bounce_pool_base = 0; | |
100 | uint32_t bounce_pool_size = 0; | |
c0fea474 | 101 | |
4452a7af A |
102 | static void reserve_bouncepool(uint32_t); |
103 | ||
104 | ||
105 | pmap_paddr_t avail_start, avail_end; | |
55e303ae | 106 | vm_offset_t virtual_avail, virtual_end; |
4452a7af | 107 | static pmap_paddr_t avail_remaining; |
91447636 | 108 | vm_offset_t static_memory_end = 0; |
55e303ae | 109 | |
55e303ae A |
110 | #include <mach-o/loader.h> |
111 | vm_offset_t edata, etext, end; | |
112 | ||
91447636 A |
113 | /* |
114 | * _mh_execute_header is the mach_header for the currently executing | |
115 | * 32 bit kernel | |
116 | */ | |
55e303ae A |
117 | extern struct mach_header _mh_execute_header; |
118 | void *sectTEXTB; int sectSizeTEXT; | |
119 | void *sectDATAB; int sectSizeDATA; | |
120 | void *sectOBJCB; int sectSizeOBJC; | |
121 | void *sectLINKB; int sectSizeLINK; | |
122 | void *sectPRELINKB; int sectSizePRELINK; | |
91447636 | 123 | void *sectHIBB; int sectSizeHIB; |
55e303ae | 124 | |
91447636 | 125 | extern void *getsegdatafromheader(struct mach_header *, const char *, int *); |
4452a7af A |
126 | extern struct segment_command *getsegbyname(const char *); |
127 | extern struct section *firstsect(struct segment_command *); | |
128 | extern struct section *nextsect(struct segment_command *, struct section *); | |
129 | ||
130 | ||
131 | void | |
132 | i386_macho_zerofill(void) | |
133 | { | |
134 | struct segment_command *sgp; | |
135 | struct section *sp; | |
136 | ||
137 | sgp = getsegbyname("__DATA"); | |
138 | if (sgp) { | |
139 | sp = firstsect(sgp); | |
140 | if (sp) { | |
141 | do { | |
142 | if ((sp->flags & S_ZEROFILL)) | |
143 | bzero((char *) sp->addr, sp->size); | |
144 | } while ((sp = nextsect(sgp, sp))); | |
145 | } | |
146 | } | |
147 | ||
148 | return; | |
149 | } | |
55e303ae A |
150 | |
151 | /* | |
152 | * Basic VM initialization. | |
153 | */ | |
154 | void | |
4452a7af A |
155 | i386_vm_init(uint64_t maxmem, |
156 | boolean_t IA32e, | |
157 | boot_args *args) | |
55e303ae | 158 | { |
91447636 | 159 | pmap_memory_region_t *pmptr; |
4452a7af A |
160 | pmap_memory_region_t *prev_pmptr; |
161 | EfiMemoryRange *mptr; | |
162 | unsigned int mcount; | |
163 | unsigned int msize; | |
91447636 A |
164 | ppnum_t fap; |
165 | unsigned int i; | |
4452a7af A |
166 | unsigned int safeboot; |
167 | ppnum_t maxpg = 0; | |
168 | uint32_t pmap_type; | |
169 | uint32_t maxbouncepoolsize; | |
170 | uint32_t maxloreserve; | |
171 | uint32_t maxdmaaddr; | |
55e303ae | 172 | |
4452a7af A |
173 | /* |
174 | * Now retrieve addresses for end, edata, and etext | |
55e303ae A |
175 | * from MACH-O headers. |
176 | */ | |
177 | ||
178 | sectTEXTB = (void *) getsegdatafromheader( | |
179 | &_mh_execute_header, "__TEXT", §SizeTEXT); | |
180 | sectDATAB = (void *) getsegdatafromheader( | |
181 | &_mh_execute_header, "__DATA", §SizeDATA); | |
182 | sectOBJCB = (void *) getsegdatafromheader( | |
183 | &_mh_execute_header, "__OBJC", §SizeOBJC); | |
184 | sectLINKB = (void *) getsegdatafromheader( | |
185 | &_mh_execute_header, "__LINKEDIT", §SizeLINK); | |
91447636 A |
186 | sectHIBB = (void *)getsegdatafromheader( |
187 | &_mh_execute_header, "__HIB", §SizeHIB); | |
55e303ae A |
188 | sectPRELINKB = (void *) getsegdatafromheader( |
189 | &_mh_execute_header, "__PRELINK", §SizePRELINK); | |
190 | ||
191 | etext = (vm_offset_t) sectTEXTB + sectSizeTEXT; | |
192 | edata = (vm_offset_t) sectDATAB + sectSizeDATA; | |
55e303ae | 193 | |
55e303ae A |
194 | vm_set_page_size(); |
195 | ||
55e303ae A |
196 | /* |
197 | * Compute the memory size. | |
198 | */ | |
199 | ||
4452a7af A |
200 | if ((1 == vm_himemory_mode) || PE_parse_boot_arg("-x", &safeboot)) { |
201 | maxpg = 1 << (32 - I386_PGSHIFT); | |
202 | } | |
91447636 A |
203 | avail_remaining = 0; |
204 | avail_end = 0; | |
205 | pmptr = pmap_memory_regions; | |
4452a7af | 206 | prev_pmptr = 0; |
91447636 A |
207 | pmap_memory_region_count = pmap_memory_region_current = 0; |
208 | fap = (ppnum_t) i386_btop(first_avail); | |
91447636 | 209 | |
4452a7af A |
210 | mptr = (EfiMemoryRange *)args->MemoryMap; |
211 | if (args->MemoryMapDescriptorSize == 0) | |
212 | panic("Invalid memory map descriptor size"); | |
213 | msize = args->MemoryMapDescriptorSize; | |
214 | mcount = args->MemoryMapSize / msize; | |
215 | ||
21362eb3 | 216 | #define FOURGIG 0x0000000100000000ULL |
4452a7af A |
217 | |
218 | for (i = 0; i < mcount; i++, mptr = (EfiMemoryRange *)(((vm_offset_t)mptr) + msize)) { | |
219 | ppnum_t base, top; | |
220 | ||
221 | if (pmap_memory_region_count >= PMAP_MEMORY_REGIONS_SIZE) { | |
222 | kprintf("WARNING: truncating memory region count at %d\n", pmap_memory_region_count); | |
223 | break; | |
224 | } | |
225 | base = (ppnum_t) (mptr->PhysicalStart >> I386_PGSHIFT); | |
226 | top = (ppnum_t) ((mptr->PhysicalStart) >> I386_PGSHIFT) + mptr->NumberOfPages - 1; | |
227 | ||
228 | switch (mptr->Type) { | |
229 | case kEfiLoaderCode: | |
230 | case kEfiLoaderData: | |
231 | case kEfiBootServicesCode: | |
232 | case kEfiBootServicesData: | |
233 | case kEfiConventionalMemory: | |
234 | /* | |
235 | * Consolidate usable memory types into one. | |
236 | */ | |
237 | pmap_type = kEfiConventionalMemory; | |
238 | sane_size += (uint64_t)(mptr->NumberOfPages << I386_PGSHIFT); | |
239 | break; | |
240 | ||
241 | case kEfiRuntimeServicesCode: | |
242 | case kEfiRuntimeServicesData: | |
243 | case kEfiACPIReclaimMemory: | |
244 | case kEfiACPIMemoryNVS: | |
245 | case kEfiPalCode: | |
246 | /* | |
247 | * sane_size should reflect the total amount of physical ram | |
248 | * in the system, not just the amount that is available for | |
249 | * the OS to use | |
250 | */ | |
251 | sane_size += (uint64_t)(mptr->NumberOfPages << I386_PGSHIFT); | |
252 | /* fall thru */ | |
253 | ||
254 | case kEfiUnusableMemory: | |
255 | case kEfiMemoryMappedIO: | |
256 | case kEfiMemoryMappedIOPortSpace: | |
257 | case kEfiReservedMemoryType: | |
258 | default: | |
259 | pmap_type = mptr->Type; | |
260 | } | |
261 | ||
262 | kprintf("EFI region: type = %d/%d, base = 0x%x, top = 0x%x\n", mptr->Type, pmap_type, base, top); | |
263 | ||
264 | if (maxpg) { | |
265 | if (base >= maxpg) | |
266 | break; | |
267 | top = (top > maxpg) ? maxpg : top; | |
268 | } | |
269 | ||
270 | /* | |
271 | * handle each region | |
272 | */ | |
273 | if (kEfiACPIMemoryNVS == pmap_type) { | |
274 | prev_pmptr = 0; | |
275 | continue; | |
276 | } else if ((mptr->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME || | |
277 | pmap_type != kEfiConventionalMemory) { | |
278 | prev_pmptr = 0; | |
279 | continue; | |
280 | } else { | |
281 | /* | |
282 | * Usable memory region | |
283 | */ | |
284 | if (top < I386_LOWMEM_RESERVED) { | |
285 | prev_pmptr = 0; | |
286 | continue; | |
287 | } | |
288 | if (top < fap) { | |
289 | /* | |
290 | * entire range below first_avail | |
291 | * salvage some low memory pages | |
292 | * we use some very low memory at startup | |
293 | * mark as already allocated here | |
294 | */ | |
295 | if (base >= I386_LOWMEM_RESERVED) | |
296 | pmptr->base = base; | |
297 | else | |
298 | pmptr->base = I386_LOWMEM_RESERVED; | |
299 | /* | |
300 | * mark as already mapped | |
301 | */ | |
302 | pmptr->alloc = pmptr->end = top; | |
303 | pmptr->type = pmap_type; | |
304 | } | |
305 | else if ( (base < fap) && (top > fap) ) { | |
306 | /* | |
307 | * spans first_avail | |
308 | * put mem below first avail in table but | |
309 | * mark already allocated | |
310 | */ | |
311 | pmptr->base = base; | |
312 | pmptr->alloc = pmptr->end = (fap - 1); | |
313 | pmptr->type = pmap_type; | |
314 | /* | |
315 | * we bump these here inline so the accounting | |
316 | * below works correctly | |
317 | */ | |
318 | pmptr++; | |
319 | pmap_memory_region_count++; | |
320 | pmptr->alloc = pmptr->base = fap; | |
321 | pmptr->type = pmap_type; | |
322 | pmptr->end = top; | |
323 | } | |
324 | else { | |
325 | /* | |
326 | * entire range useable | |
327 | */ | |
328 | pmptr->alloc = pmptr->base = base; | |
329 | pmptr->type = pmap_type; | |
330 | pmptr->end = top; | |
331 | } | |
332 | ||
333 | if (i386_ptob(pmptr->end) > avail_end ) | |
334 | avail_end = i386_ptob(pmptr->end); | |
335 | ||
336 | avail_remaining += (pmptr->end - pmptr->base); | |
337 | ||
338 | /* | |
339 | * Consolidate contiguous memory regions, if possible | |
340 | */ | |
341 | if (prev_pmptr && | |
342 | pmptr->type == prev_pmptr->type && | |
343 | pmptr->base == pmptr->alloc && | |
344 | pmptr->base == (prev_pmptr->end + 1)) { | |
345 | prev_pmptr->end = pmptr->end; | |
346 | } else { | |
347 | pmap_memory_region_count++; | |
348 | prev_pmptr = pmptr; | |
349 | pmptr++; | |
350 | } | |
351 | } | |
21362eb3 | 352 | } |
4452a7af | 353 | |
55e303ae | 354 | |
91447636 | 355 | #ifdef PRINT_PMAP_MEMORY_TABLE |
4452a7af A |
356 | { |
357 | unsigned int j; | |
358 | pmap_memory_region_t *p = pmap_memory_regions; | |
359 | vm_offset_t region_start, region_end; | |
360 | vm_offset_t efi_start, efi_end; | |
361 | for (j=0;j<pmap_memory_region_count;j++, p++) { | |
362 | kprintf("type %d base 0x%x alloc 0x%x top 0x%x\n", p->type, | |
363 | p->base << I386_PGSHIFT, p->alloc << I386_PGSHIFT, p->end << I386_PGSHIFT); | |
364 | region_start = p->base << I386_PGSHIFT; | |
365 | region_end = (p->end << I386_PGSHIFT) - 1; | |
366 | mptr = args->MemoryMap; | |
367 | for (i=0; i<mcount; i++, mptr = (EfiMemoryRange *)(((vm_offset_t)mptr) + msize)) { | |
368 | if (mptr->Type != kEfiLoaderCode && | |
369 | mptr->Type != kEfiLoaderData && | |
370 | mptr->Type != kEfiBootServicesCode && | |
371 | mptr->Type != kEfiBootServicesData && | |
372 | mptr->Type != kEfiConventionalMemory) { | |
373 | efi_start = (vm_offset_t)mptr->PhysicalStart; | |
374 | efi_end = efi_start + ((vm_offset_t)mptr->NumberOfPages << I386_PGSHIFT) - 1; | |
375 | if ((efi_start >= region_start && efi_start <= region_end) || | |
376 | (efi_end >= region_start && efi_end <= region_end)) { | |
377 | kprintf(" *** Overlapping region with EFI runtime region %d\n", i); | |
378 | } | |
379 | } | |
380 | ||
381 | } | |
382 | } | |
383 | } | |
91447636 | 384 | #endif |
55e303ae | 385 | |
91447636 | 386 | avail_start = first_avail; |
4452a7af | 387 | mem_actual = sane_size; |
c0fea474 | 388 | |
4452a7af A |
389 | #define MEG (1024*1024) |
390 | ||
391 | /* | |
392 | * For user visible memory size, round up to 128 Mb - accounting for the various stolen memory | |
393 | * not reported by EFI. | |
394 | */ | |
395 | ||
396 | sane_size = (sane_size + 128 * MEG - 1) & ~((uint64_t)(128 * MEG - 1)); | |
397 | ||
398 | /* | |
399 | * if user set maxmem, reduce memory sizes | |
400 | */ | |
401 | if ( (maxmem > (uint64_t)first_avail) && (maxmem < sane_size)) { | |
402 | ppnum_t discarded_pages = (sane_size - maxmem) >> I386_PGSHIFT; | |
403 | sane_size = maxmem; | |
404 | if (avail_remaining > discarded_pages) | |
405 | avail_remaining -= discarded_pages; | |
406 | else | |
407 | avail_remaining = 0; | |
55e303ae | 408 | } |
89b3af67 | 409 | |
4452a7af A |
410 | /* |
411 | * mem_size is only a 32 bit container... follow the PPC route | |
412 | * and pin it to a 2 Gbyte maximum | |
413 | */ | |
414 | if (sane_size > (FOURGIG >> 1)) | |
415 | mem_size = (vm_size_t)(FOURGIG >> 1); | |
416 | else | |
417 | mem_size = (vm_size_t)sane_size; | |
21362eb3 | 418 | max_mem = sane_size; |
8f6c56a5 | 419 | |
4452a7af | 420 | kprintf("Physical memory %d MB\n", sane_size/MEG); |
89b3af67 | 421 | |
4452a7af A |
422 | if (!PE_parse_boot_arg("max_valid_dma_addr", &maxdmaaddr)) |
423 | max_valid_dma_address = 1024ULL * 1024ULL * 4096ULL; | |
424 | else | |
425 | max_valid_dma_address = ((uint64_t) maxdmaaddr) * 1024ULL * 1024ULL; | |
426 | ||
427 | if (!PE_parse_boot_arg("maxbouncepool", &maxbouncepoolsize)) | |
428 | maxbouncepoolsize = MAXBOUNCEPOOL; | |
429 | else | |
430 | maxbouncepoolsize = maxbouncepoolsize * (1024 * 1024); | |
c0fea474 | 431 | |
89b3af67 | 432 | /* |
4452a7af A |
433 | * bsd_mbuf_cluster_reserve depends on sane_size being set |
434 | * in order to correctly determine the size of the mbuf pool | |
435 | * that will be reserved | |
89b3af67 | 436 | */ |
4452a7af A |
437 | if (!PE_parse_boot_arg("maxloreserve", &maxloreserve)) |
438 | maxloreserve = MAXLORESERVE + bsd_mbuf_cluster_reserve(); | |
439 | else | |
440 | maxloreserve = maxloreserve * (1024 * 1024); | |
441 | ||
5d5c5d0d | 442 | |
4452a7af A |
443 | if (avail_end >= max_valid_dma_address) { |
444 | if (maxbouncepoolsize) | |
445 | reserve_bouncepool(maxbouncepoolsize); | |
446 | ||
447 | if (maxloreserve) | |
448 | vm_lopage_poolsize = maxloreserve / PAGE_SIZE; | |
449 | } | |
89b3af67 | 450 | |
4452a7af A |
451 | /* |
452 | * Initialize kernel physical map. | |
453 | * Kernel virtual address starts at VM_KERNEL_MIN_ADDRESS. | |
454 | */ | |
455 | pmap_bootstrap(0, IA32e); | |
21362eb3 A |
456 | } |
457 | ||
4452a7af | 458 | |
55e303ae A |
459 | unsigned int |
460 | pmap_free_pages(void) | |
461 | { | |
462 | return avail_remaining; | |
463 | } | |
464 | ||
4452a7af | 465 | |
55e303ae A |
466 | boolean_t |
467 | pmap_next_page( | |
468 | ppnum_t *pn) | |
469 | { | |
4452a7af A |
470 | |
471 | if (avail_remaining) while (pmap_memory_region_current < pmap_memory_region_count) { | |
472 | if (pmap_memory_regions[pmap_memory_region_current].alloc == | |
473 | pmap_memory_regions[pmap_memory_region_current].end) { | |
474 | pmap_memory_region_current++; | |
475 | continue; | |
476 | } | |
477 | *pn = pmap_memory_regions[pmap_memory_region_current].alloc++; | |
478 | avail_remaining--; | |
479 | ||
480 | return TRUE; | |
91447636 A |
481 | } |
482 | return FALSE; | |
55e303ae A |
483 | } |
484 | ||
4452a7af | 485 | |
55e303ae A |
486 | boolean_t |
487 | pmap_valid_page( | |
91447636 | 488 | ppnum_t pn) |
55e303ae | 489 | { |
4452a7af A |
490 | unsigned int i; |
491 | pmap_memory_region_t *pmptr = pmap_memory_regions; | |
492 | ||
493 | assert(pn); | |
494 | for (i = 0; i < pmap_memory_region_count; i++, pmptr++) { | |
495 | if ( (pn >= pmptr->base) && (pn <= pmptr->end) && pmptr->type == kEfiConventionalMemory ) | |
496 | return TRUE; | |
497 | } | |
498 | return FALSE; | |
499 | } | |
500 | ||
501 | ||
502 | static void | |
503 | reserve_bouncepool(uint32_t bounce_pool_wanted) | |
504 | { | |
505 | pmap_memory_region_t *pmptr = pmap_memory_regions; | |
506 | pmap_memory_region_t *lowest = NULL; | |
507 | unsigned int i; | |
508 | unsigned int pages_needed; | |
509 | ||
510 | pages_needed = bounce_pool_wanted / PAGE_SIZE; | |
511 | ||
512 | for (i = 0; i < pmap_memory_region_count; i++, pmptr++) { | |
513 | if ( (pmptr->type == kEfiConventionalMemory) && ((pmptr->end - pmptr->alloc) >= pages_needed) ) { | |
514 | if ( (lowest == NULL) || (pmptr->alloc < lowest->alloc) ) | |
515 | lowest = pmptr; | |
516 | } | |
517 | } | |
518 | if ( (lowest != NULL) ) { | |
519 | bounce_pool_base = lowest->alloc * PAGE_SIZE; | |
520 | bounce_pool_size = bounce_pool_wanted; | |
521 | ||
522 | lowest->alloc += pages_needed; | |
523 | avail_remaining -= pages_needed; | |
524 | } | |
55e303ae | 525 | } |