]>
Commit | Line | Data |
---|---|---|
55e303ae | 1 | /* |
2d21ac55 | 2 | * Copyright (c) 2003-2006 Apple Computer, Inc. All rights reserved. |
55e303ae | 3 | * |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
55e303ae | 5 | * |
2d21ac55 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. | |
8f6c56a5 | 14 | * |
2d21ac55 A |
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 | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and | |
24 | * limitations under the License. | |
8f6c56a5 | 25 | * |
2d21ac55 | 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> |
0c530ab8 A |
82 | #include <pexpert/i386/efi.h> |
83 | #include "i386_lowmem.h" | |
55e303ae A |
84 | |
85 | vm_size_t mem_size = 0; | |
55e303ae | 86 | vm_offset_t first_avail = 0;/* first after page tables */ |
55e303ae | 87 | |
0c530ab8 A |
88 | uint64_t max_mem; /* Size of physical memory (bytes), adjusted by maxmem */ |
89 | uint64_t mem_actual; | |
90 | uint64_t sane_size = 0; /* Memory size to use for defaults calculations */ | |
91 | ||
92 | #define MAXBOUNCEPOOL (128 * 1024 * 1024) | |
93 | #define MAXLORESERVE ( 32 * 1024 * 1024) | |
94 | ||
95 | extern int bsd_mbuf_cluster_reserve(void); | |
96 | ||
97 | ||
98 | uint32_t bounce_pool_base = 0; | |
99 | uint32_t bounce_pool_size = 0; | |
4452a7af | 100 | |
0c530ab8 A |
101 | static void reserve_bouncepool(uint32_t); |
102 | ||
103 | ||
2d21ac55 | 104 | pmap_paddr_t avail_start, avail_end; |
55e303ae | 105 | vm_offset_t virtual_avail, virtual_end; |
0c530ab8 | 106 | static pmap_paddr_t avail_remaining; |
91447636 | 107 | vm_offset_t static_memory_end = 0; |
55e303ae | 108 | |
55e303ae A |
109 | #include <mach-o/loader.h> |
110 | vm_offset_t edata, etext, end; | |
111 | ||
91447636 A |
112 | /* |
113 | * _mh_execute_header is the mach_header for the currently executing | |
114 | * 32 bit kernel | |
115 | */ | |
55e303ae A |
116 | extern struct mach_header _mh_execute_header; |
117 | void *sectTEXTB; int sectSizeTEXT; | |
118 | void *sectDATAB; int sectSizeDATA; | |
119 | void *sectOBJCB; int sectSizeOBJC; | |
120 | void *sectLINKB; int sectSizeLINK; | |
121 | void *sectPRELINKB; int sectSizePRELINK; | |
91447636 | 122 | void *sectHIBB; int sectSizeHIB; |
55e303ae | 123 | |
91447636 | 124 | extern void *getsegdatafromheader(struct mach_header *, const char *, int *); |
0c530ab8 A |
125 | extern struct segment_command *getsegbyname(const char *); |
126 | extern struct section *firstsect(struct segment_command *); | |
127 | extern struct section *nextsect(struct segment_command *, struct section *); | |
128 | ||
129 | ||
130 | void | |
131 | i386_macho_zerofill(void) | |
132 | { | |
133 | struct segment_command *sgp; | |
134 | struct section *sp; | |
135 | ||
136 | sgp = getsegbyname("__DATA"); | |
137 | if (sgp) { | |
138 | sp = firstsect(sgp); | |
139 | if (sp) { | |
140 | do { | |
141 | if ((sp->flags & S_ZEROFILL)) | |
142 | bzero((char *) sp->addr, sp->size); | |
143 | } while ((sp = nextsect(sgp, sp))); | |
144 | } | |
145 | } | |
146 | ||
147 | return; | |
148 | } | |
55e303ae A |
149 | |
150 | /* | |
151 | * Basic VM initialization. | |
152 | */ | |
153 | void | |
0c530ab8 A |
154 | i386_vm_init(uint64_t maxmem, |
155 | boolean_t IA32e, | |
156 | boot_args *args) | |
55e303ae | 157 | { |
91447636 | 158 | pmap_memory_region_t *pmptr; |
0c530ab8 A |
159 | pmap_memory_region_t *prev_pmptr; |
160 | EfiMemoryRange *mptr; | |
161 | unsigned int mcount; | |
162 | unsigned int msize; | |
91447636 A |
163 | ppnum_t fap; |
164 | unsigned int i; | |
0c530ab8 A |
165 | unsigned int safeboot; |
166 | ppnum_t maxpg = 0; | |
167 | uint32_t pmap_type; | |
168 | uint32_t maxbouncepoolsize; | |
169 | uint32_t maxloreserve; | |
170 | uint32_t maxdmaaddr; | |
55e303ae | 171 | |
0c530ab8 A |
172 | /* |
173 | * Now retrieve addresses for end, edata, and etext | |
55e303ae A |
174 | * from MACH-O headers. |
175 | */ | |
176 | ||
177 | sectTEXTB = (void *) getsegdatafromheader( | |
178 | &_mh_execute_header, "__TEXT", §SizeTEXT); | |
179 | sectDATAB = (void *) getsegdatafromheader( | |
180 | &_mh_execute_header, "__DATA", §SizeDATA); | |
181 | sectOBJCB = (void *) getsegdatafromheader( | |
182 | &_mh_execute_header, "__OBJC", §SizeOBJC); | |
183 | sectLINKB = (void *) getsegdatafromheader( | |
184 | &_mh_execute_header, "__LINKEDIT", §SizeLINK); | |
91447636 A |
185 | sectHIBB = (void *)getsegdatafromheader( |
186 | &_mh_execute_header, "__HIB", §SizeHIB); | |
55e303ae A |
187 | sectPRELINKB = (void *) getsegdatafromheader( |
188 | &_mh_execute_header, "__PRELINK", §SizePRELINK); | |
189 | ||
190 | etext = (vm_offset_t) sectTEXTB + sectSizeTEXT; | |
191 | edata = (vm_offset_t) sectDATAB + sectSizeDATA; | |
55e303ae | 192 | |
55e303ae A |
193 | vm_set_page_size(); |
194 | ||
55e303ae A |
195 | /* |
196 | * Compute the memory size. | |
197 | */ | |
198 | ||
0c530ab8 A |
199 | if ((1 == vm_himemory_mode) || PE_parse_boot_arg("-x", &safeboot)) { |
200 | maxpg = 1 << (32 - I386_PGSHIFT); | |
201 | } | |
91447636 A |
202 | avail_remaining = 0; |
203 | avail_end = 0; | |
204 | pmptr = pmap_memory_regions; | |
0c530ab8 | 205 | prev_pmptr = 0; |
91447636 A |
206 | pmap_memory_region_count = pmap_memory_region_current = 0; |
207 | fap = (ppnum_t) i386_btop(first_avail); | |
91447636 | 208 | |
0c530ab8 A |
209 | mptr = (EfiMemoryRange *)args->MemoryMap; |
210 | if (args->MemoryMapDescriptorSize == 0) | |
211 | panic("Invalid memory map descriptor size"); | |
212 | msize = args->MemoryMapDescriptorSize; | |
213 | mcount = args->MemoryMapSize / msize; | |
214 | ||
6601e61a | 215 | #define FOURGIG 0x0000000100000000ULL |
0c530ab8 A |
216 | |
217 | for (i = 0; i < mcount; i++, mptr = (EfiMemoryRange *)(((vm_offset_t)mptr) + msize)) { | |
218 | ppnum_t base, top; | |
219 | ||
220 | if (pmap_memory_region_count >= PMAP_MEMORY_REGIONS_SIZE) { | |
221 | kprintf("WARNING: truncating memory region count at %d\n", pmap_memory_region_count); | |
222 | break; | |
223 | } | |
224 | base = (ppnum_t) (mptr->PhysicalStart >> I386_PGSHIFT); | |
225 | top = (ppnum_t) ((mptr->PhysicalStart) >> I386_PGSHIFT) + mptr->NumberOfPages - 1; | |
226 | ||
227 | switch (mptr->Type) { | |
228 | case kEfiLoaderCode: | |
229 | case kEfiLoaderData: | |
230 | case kEfiBootServicesCode: | |
231 | case kEfiBootServicesData: | |
232 | case kEfiConventionalMemory: | |
233 | /* | |
234 | * Consolidate usable memory types into one. | |
235 | */ | |
236 | pmap_type = kEfiConventionalMemory; | |
237 | sane_size += (uint64_t)(mptr->NumberOfPages << I386_PGSHIFT); | |
238 | break; | |
239 | ||
240 | case kEfiRuntimeServicesCode: | |
241 | case kEfiRuntimeServicesData: | |
242 | case kEfiACPIReclaimMemory: | |
243 | case kEfiACPIMemoryNVS: | |
244 | case kEfiPalCode: | |
245 | /* | |
246 | * sane_size should reflect the total amount of physical ram | |
247 | * in the system, not just the amount that is available for | |
248 | * the OS to use | |
249 | */ | |
250 | sane_size += (uint64_t)(mptr->NumberOfPages << I386_PGSHIFT); | |
251 | /* fall thru */ | |
252 | ||
253 | case kEfiUnusableMemory: | |
254 | case kEfiMemoryMappedIO: | |
255 | case kEfiMemoryMappedIOPortSpace: | |
256 | case kEfiReservedMemoryType: | |
257 | default: | |
258 | pmap_type = mptr->Type; | |
259 | } | |
260 | ||
2d21ac55 | 261 | kprintf("EFI region: type = %u/%d, base = 0x%x, top = 0x%x\n", mptr->Type, pmap_type, base, top); |
0c530ab8 A |
262 | |
263 | if (maxpg) { | |
264 | if (base >= maxpg) | |
265 | break; | |
266 | top = (top > maxpg) ? maxpg : top; | |
267 | } | |
268 | ||
269 | /* | |
270 | * handle each region | |
271 | */ | |
2d21ac55 A |
272 | if ((mptr->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME || |
273 | pmap_type != kEfiConventionalMemory) { | |
0c530ab8 A |
274 | prev_pmptr = 0; |
275 | continue; | |
276 | } else { | |
277 | /* | |
278 | * Usable memory region | |
279 | */ | |
280 | if (top < I386_LOWMEM_RESERVED) { | |
281 | prev_pmptr = 0; | |
282 | continue; | |
283 | } | |
284 | if (top < fap) { | |
285 | /* | |
286 | * entire range below first_avail | |
287 | * salvage some low memory pages | |
288 | * we use some very low memory at startup | |
289 | * mark as already allocated here | |
290 | */ | |
291 | if (base >= I386_LOWMEM_RESERVED) | |
292 | pmptr->base = base; | |
293 | else | |
294 | pmptr->base = I386_LOWMEM_RESERVED; | |
295 | /* | |
296 | * mark as already mapped | |
297 | */ | |
298 | pmptr->alloc = pmptr->end = top; | |
299 | pmptr->type = pmap_type; | |
300 | } | |
301 | else if ( (base < fap) && (top > fap) ) { | |
302 | /* | |
303 | * spans first_avail | |
304 | * put mem below first avail in table but | |
305 | * mark already allocated | |
306 | */ | |
307 | pmptr->base = base; | |
308 | pmptr->alloc = pmptr->end = (fap - 1); | |
309 | pmptr->type = pmap_type; | |
310 | /* | |
311 | * we bump these here inline so the accounting | |
312 | * below works correctly | |
313 | */ | |
314 | pmptr++; | |
315 | pmap_memory_region_count++; | |
316 | pmptr->alloc = pmptr->base = fap; | |
317 | pmptr->type = pmap_type; | |
318 | pmptr->end = top; | |
319 | } | |
320 | else { | |
321 | /* | |
322 | * entire range useable | |
323 | */ | |
324 | pmptr->alloc = pmptr->base = base; | |
325 | pmptr->type = pmap_type; | |
326 | pmptr->end = top; | |
327 | } | |
328 | ||
329 | if (i386_ptob(pmptr->end) > avail_end ) | |
330 | avail_end = i386_ptob(pmptr->end); | |
331 | ||
332 | avail_remaining += (pmptr->end - pmptr->base); | |
333 | ||
334 | /* | |
335 | * Consolidate contiguous memory regions, if possible | |
336 | */ | |
337 | if (prev_pmptr && | |
338 | pmptr->type == prev_pmptr->type && | |
339 | pmptr->base == pmptr->alloc && | |
340 | pmptr->base == (prev_pmptr->end + 1)) { | |
341 | prev_pmptr->end = pmptr->end; | |
342 | } else { | |
343 | pmap_memory_region_count++; | |
344 | prev_pmptr = pmptr; | |
345 | pmptr++; | |
346 | } | |
347 | } | |
6601e61a | 348 | } |
0c530ab8 | 349 | |
55e303ae | 350 | |
91447636 | 351 | #ifdef PRINT_PMAP_MEMORY_TABLE |
0c530ab8 A |
352 | { |
353 | unsigned int j; | |
354 | pmap_memory_region_t *p = pmap_memory_regions; | |
355 | vm_offset_t region_start, region_end; | |
356 | vm_offset_t efi_start, efi_end; | |
357 | for (j=0;j<pmap_memory_region_count;j++, p++) { | |
358 | kprintf("type %d base 0x%x alloc 0x%x top 0x%x\n", p->type, | |
359 | p->base << I386_PGSHIFT, p->alloc << I386_PGSHIFT, p->end << I386_PGSHIFT); | |
360 | region_start = p->base << I386_PGSHIFT; | |
361 | region_end = (p->end << I386_PGSHIFT) - 1; | |
362 | mptr = args->MemoryMap; | |
363 | for (i=0; i<mcount; i++, mptr = (EfiMemoryRange *)(((vm_offset_t)mptr) + msize)) { | |
364 | if (mptr->Type != kEfiLoaderCode && | |
365 | mptr->Type != kEfiLoaderData && | |
366 | mptr->Type != kEfiBootServicesCode && | |
367 | mptr->Type != kEfiBootServicesData && | |
368 | mptr->Type != kEfiConventionalMemory) { | |
369 | efi_start = (vm_offset_t)mptr->PhysicalStart; | |
370 | efi_end = efi_start + ((vm_offset_t)mptr->NumberOfPages << I386_PGSHIFT) - 1; | |
371 | if ((efi_start >= region_start && efi_start <= region_end) || | |
372 | (efi_end >= region_start && efi_end <= region_end)) { | |
373 | kprintf(" *** Overlapping region with EFI runtime region %d\n", i); | |
374 | } | |
375 | } | |
376 | ||
377 | } | |
378 | } | |
379 | } | |
91447636 | 380 | #endif |
55e303ae | 381 | |
91447636 | 382 | avail_start = first_avail; |
0c530ab8 | 383 | mem_actual = sane_size; |
4452a7af | 384 | |
0c530ab8 A |
385 | #define MEG (1024*1024) |
386 | ||
387 | /* | |
388 | * For user visible memory size, round up to 128 Mb - accounting for the various stolen memory | |
389 | * not reported by EFI. | |
390 | */ | |
391 | ||
392 | sane_size = (sane_size + 128 * MEG - 1) & ~((uint64_t)(128 * MEG - 1)); | |
393 | ||
394 | /* | |
395 | * if user set maxmem, reduce memory sizes | |
396 | */ | |
397 | if ( (maxmem > (uint64_t)first_avail) && (maxmem < sane_size)) { | |
398 | ppnum_t discarded_pages = (sane_size - maxmem) >> I386_PGSHIFT; | |
2d21ac55 A |
399 | ppnum_t highest_pn = 0; |
400 | ppnum_t cur_alloc = 0; | |
401 | uint64_t pages_to_use; | |
402 | unsigned cur_region = 0; | |
403 | ||
404 | sane_size = maxmem; | |
405 | ||
0c530ab8 A |
406 | if (avail_remaining > discarded_pages) |
407 | avail_remaining -= discarded_pages; | |
408 | else | |
409 | avail_remaining = 0; | |
2d21ac55 A |
410 | |
411 | pages_to_use = avail_remaining; | |
412 | ||
413 | while (cur_region < pmap_memory_region_count && pages_to_use) { | |
414 | for (cur_alloc = pmap_memory_regions[cur_region].alloc; | |
415 | cur_alloc < pmap_memory_regions[cur_region].end && pages_to_use; | |
416 | cur_alloc++) { | |
417 | if (cur_alloc > highest_pn) | |
418 | highest_pn = cur_alloc; | |
419 | pages_to_use--; | |
420 | } | |
421 | if (pages_to_use == 0) | |
422 | pmap_memory_regions[cur_region].end = cur_alloc; | |
423 | ||
424 | cur_region++; | |
425 | } | |
426 | pmap_memory_region_count = cur_region; | |
427 | ||
428 | avail_end = i386_ptob(highest_pn + 1); | |
55e303ae | 429 | } |
4452a7af | 430 | |
0c530ab8 A |
431 | /* |
432 | * mem_size is only a 32 bit container... follow the PPC route | |
433 | * and pin it to a 2 Gbyte maximum | |
434 | */ | |
435 | if (sane_size > (FOURGIG >> 1)) | |
436 | mem_size = (vm_size_t)(FOURGIG >> 1); | |
437 | else | |
438 | mem_size = (vm_size_t)sane_size; | |
6601e61a | 439 | max_mem = sane_size; |
5d5c5d0d | 440 | |
2d21ac55 | 441 | kprintf("Physical memory %llu MB\n", sane_size/MEG); |
4452a7af | 442 | |
0c530ab8 A |
443 | if (!PE_parse_boot_arg("max_valid_dma_addr", &maxdmaaddr)) |
444 | max_valid_dma_address = 1024ULL * 1024ULL * 4096ULL; | |
445 | else | |
446 | max_valid_dma_address = ((uint64_t) maxdmaaddr) * 1024ULL * 1024ULL; | |
447 | ||
448 | if (!PE_parse_boot_arg("maxbouncepool", &maxbouncepoolsize)) | |
449 | maxbouncepoolsize = MAXBOUNCEPOOL; | |
450 | else | |
451 | maxbouncepoolsize = maxbouncepoolsize * (1024 * 1024); | |
89b3af67 | 452 | |
4452a7af | 453 | /* |
0c530ab8 A |
454 | * bsd_mbuf_cluster_reserve depends on sane_size being set |
455 | * in order to correctly determine the size of the mbuf pool | |
456 | * that will be reserved | |
4452a7af | 457 | */ |
0c530ab8 A |
458 | if (!PE_parse_boot_arg("maxloreserve", &maxloreserve)) |
459 | maxloreserve = MAXLORESERVE + bsd_mbuf_cluster_reserve(); | |
460 | else | |
461 | maxloreserve = maxloreserve * (1024 * 1024); | |
462 | ||
21362eb3 | 463 | |
0c530ab8 A |
464 | if (avail_end >= max_valid_dma_address) { |
465 | if (maxbouncepoolsize) | |
466 | reserve_bouncepool(maxbouncepoolsize); | |
467 | ||
468 | if (maxloreserve) | |
2d21ac55 | 469 | vm_lopage_poolsize = maxloreserve / PAGE_SIZE; |
0c530ab8 | 470 | } |
2d21ac55 | 471 | |
0c530ab8 A |
472 | /* |
473 | * Initialize kernel physical map. | |
474 | * Kernel virtual address starts at VM_KERNEL_MIN_ADDRESS. | |
475 | */ | |
476 | pmap_bootstrap(0, IA32e); | |
6601e61a A |
477 | } |
478 | ||
0c530ab8 | 479 | |
55e303ae A |
480 | unsigned int |
481 | pmap_free_pages(void) | |
482 | { | |
483 | return avail_remaining; | |
484 | } | |
485 | ||
0c530ab8 | 486 | |
55e303ae A |
487 | boolean_t |
488 | pmap_next_page( | |
489 | ppnum_t *pn) | |
490 | { | |
0c530ab8 A |
491 | |
492 | if (avail_remaining) while (pmap_memory_region_current < pmap_memory_region_count) { | |
493 | if (pmap_memory_regions[pmap_memory_region_current].alloc == | |
494 | pmap_memory_regions[pmap_memory_region_current].end) { | |
495 | pmap_memory_region_current++; | |
496 | continue; | |
497 | } | |
498 | *pn = pmap_memory_regions[pmap_memory_region_current].alloc++; | |
499 | avail_remaining--; | |
500 | ||
501 | return TRUE; | |
91447636 A |
502 | } |
503 | return FALSE; | |
55e303ae A |
504 | } |
505 | ||
0c530ab8 | 506 | |
55e303ae A |
507 | boolean_t |
508 | pmap_valid_page( | |
91447636 | 509 | ppnum_t pn) |
55e303ae | 510 | { |
0c530ab8 A |
511 | unsigned int i; |
512 | pmap_memory_region_t *pmptr = pmap_memory_regions; | |
513 | ||
514 | assert(pn); | |
515 | for (i = 0; i < pmap_memory_region_count; i++, pmptr++) { | |
2d21ac55 | 516 | if ( (pn >= pmptr->base) && (pn <= pmptr->end) ) |
0c530ab8 A |
517 | return TRUE; |
518 | } | |
519 | return FALSE; | |
520 | } | |
521 | ||
522 | ||
523 | static void | |
524 | reserve_bouncepool(uint32_t bounce_pool_wanted) | |
525 | { | |
526 | pmap_memory_region_t *pmptr = pmap_memory_regions; | |
527 | pmap_memory_region_t *lowest = NULL; | |
528 | unsigned int i; | |
529 | unsigned int pages_needed; | |
530 | ||
531 | pages_needed = bounce_pool_wanted / PAGE_SIZE; | |
532 | ||
533 | for (i = 0; i < pmap_memory_region_count; i++, pmptr++) { | |
2d21ac55 | 534 | if ( (pmptr->end - pmptr->alloc) >= pages_needed ) { |
0c530ab8 A |
535 | if ( (lowest == NULL) || (pmptr->alloc < lowest->alloc) ) |
536 | lowest = pmptr; | |
537 | } | |
538 | } | |
539 | if ( (lowest != NULL) ) { | |
540 | bounce_pool_base = lowest->alloc * PAGE_SIZE; | |
541 | bounce_pool_size = bounce_pool_wanted; | |
542 | ||
543 | lowest->alloc += pages_needed; | |
544 | avail_remaining -= pages_needed; | |
545 | } | |
55e303ae | 546 | } |