aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTony Luck <tony.luck@intel.com>2005-10-28 17:32:30 -0400
committerTony Luck <tony.luck@intel.com>2005-10-28 17:32:30 -0400
commit5833f1420b96c4f9b193b7f2fcbc0003dc032fe8 (patch)
treeccb3933b3c694ba4724c3a392d6e275d992ed86b
parenta1e78db3f54d3481726ed2d3d58d8ad5b19b13d0 (diff)
parentd719948e623622cf9fc8016f7ec63422d929eb3b (diff)
Pull new-efi-memmap into release branch
-rw-r--r--arch/ia64/kernel/efi.c510
-rw-r--r--arch/ia64/kernel/setup.c32
-rw-r--r--arch/ia64/kernel/uncached.c17
-rw-r--r--include/asm-ia64/meminit.h4
4 files changed, 370 insertions, 193 deletions
diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c
index 179f230816ed..f72ea6aebcb1 100644
--- a/arch/ia64/kernel/efi.c
+++ b/arch/ia64/kernel/efi.c
@@ -239,57 +239,30 @@ is_available_memory (efi_memory_desc_t *md)
239 return 0; 239 return 0;
240} 240}
241 241
242/* 242typedef struct kern_memdesc {
243 * Trim descriptor MD so its starts at address START_ADDR. If the descriptor covers 243 u64 attribute;
244 * memory that is normally available to the kernel, issue a warning that some memory 244 u64 start;
245 * is being ignored. 245 u64 num_pages;
246 */ 246} kern_memdesc_t;
247static void
248trim_bottom (efi_memory_desc_t *md, u64 start_addr)
249{
250 u64 num_skipped_pages;
251 247
252 if (md->phys_addr >= start_addr || !md->num_pages) 248static kern_memdesc_t *kern_memmap;
253 return;
254
255 num_skipped_pages = (start_addr - md->phys_addr) >> EFI_PAGE_SHIFT;
256 if (num_skipped_pages > md->num_pages)
257 num_skipped_pages = md->num_pages;
258
259 if (is_available_memory(md))
260 printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole "
261 "at 0x%lx\n", __FUNCTION__,
262 (num_skipped_pages << EFI_PAGE_SHIFT) >> 10,
263 md->phys_addr, start_addr - IA64_GRANULE_SIZE);
264 /*
265 * NOTE: Don't set md->phys_addr to START_ADDR because that could cause the memory
266 * descriptor list to become unsorted. In such a case, md->num_pages will be
267 * zero, so the Right Thing will happen.
268 */
269 md->phys_addr += num_skipped_pages << EFI_PAGE_SHIFT;
270 md->num_pages -= num_skipped_pages;
271}
272 249
273static void 250static void
274trim_top (efi_memory_desc_t *md, u64 end_addr) 251walk (efi_freemem_callback_t callback, void *arg, u64 attr)
275{ 252{
276 u64 num_dropped_pages, md_end_addr; 253 kern_memdesc_t *k;
277 254 u64 start, end, voff;
278 md_end_addr = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT);
279
280 if (md_end_addr <= end_addr || !md->num_pages)
281 return;
282 255
283 num_dropped_pages = (md_end_addr - end_addr) >> EFI_PAGE_SHIFT; 256 voff = (attr == EFI_MEMORY_WB) ? PAGE_OFFSET : __IA64_UNCACHED_OFFSET;
284 if (num_dropped_pages > md->num_pages) 257 for (k = kern_memmap; k->start != ~0UL; k++) {
285 num_dropped_pages = md->num_pages; 258 if (k->attribute != attr)
286 259 continue;
287 if (is_available_memory(md)) 260 start = PAGE_ALIGN(k->start);
288 printk(KERN_NOTICE "efi.%s: ignoring %luKB of memory at 0x%lx due to granule hole " 261 end = (k->start + (k->num_pages << EFI_PAGE_SHIFT)) & PAGE_MASK;
289 "at 0x%lx\n", __FUNCTION__, 262 if (start < end)
290 (num_dropped_pages << EFI_PAGE_SHIFT) >> 10, 263 if ((*callback)(start + voff, end + voff, arg) < 0)
291 md->phys_addr, end_addr); 264 return;
292 md->num_pages -= num_dropped_pages; 265 }
293} 266}
294 267
295/* 268/*
@@ -299,148 +272,19 @@ trim_top (efi_memory_desc_t *md, u64 end_addr)
299void 272void
300efi_memmap_walk (efi_freemem_callback_t callback, void *arg) 273efi_memmap_walk (efi_freemem_callback_t callback, void *arg)
301{ 274{
302 int prev_valid = 0; 275 walk(callback, arg, EFI_MEMORY_WB);
303 struct range {
304 u64 start;
305 u64 end;
306 } prev, curr;
307 void *efi_map_start, *efi_map_end, *p, *q;
308 efi_memory_desc_t *md, *check_md;
309 u64 efi_desc_size, start, end, granule_addr, last_granule_addr, first_non_wb_addr = 0;
310 unsigned long total_mem = 0;
311
312 efi_map_start = __va(ia64_boot_param->efi_memmap);
313 efi_map_end = efi_map_start + ia64_boot_param->efi_memmap_size;
314 efi_desc_size = ia64_boot_param->efi_memdesc_size;
315
316 for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) {
317 md = p;
318
319 /* skip over non-WB memory descriptors; that's all we're interested in... */
320 if (!(md->attribute & EFI_MEMORY_WB))
321 continue;
322
323 /*
324 * granule_addr is the base of md's first granule.
325 * [granule_addr - first_non_wb_addr) is guaranteed to
326 * be contiguous WB memory.
327 */
328 granule_addr = GRANULEROUNDDOWN(md->phys_addr);
329 first_non_wb_addr = max(first_non_wb_addr, granule_addr);
330
331 if (first_non_wb_addr < md->phys_addr) {
332 trim_bottom(md, granule_addr + IA64_GRANULE_SIZE);
333 granule_addr = GRANULEROUNDDOWN(md->phys_addr);
334 first_non_wb_addr = max(first_non_wb_addr, granule_addr);
335 }
336
337 for (q = p; q < efi_map_end; q += efi_desc_size) {
338 check_md = q;
339
340 if ((check_md->attribute & EFI_MEMORY_WB) &&
341 (check_md->phys_addr == first_non_wb_addr))
342 first_non_wb_addr += check_md->num_pages << EFI_PAGE_SHIFT;
343 else
344 break; /* non-WB or hole */
345 }
346
347 last_granule_addr = GRANULEROUNDDOWN(first_non_wb_addr);
348 if (last_granule_addr < md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT))
349 trim_top(md, last_granule_addr);
350
351 if (is_available_memory(md)) {
352 if (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) >= max_addr) {
353 if (md->phys_addr >= max_addr)
354 continue;
355 md->num_pages = (max_addr - md->phys_addr) >> EFI_PAGE_SHIFT;
356 first_non_wb_addr = max_addr;
357 }
358
359 if (total_mem >= mem_limit)
360 continue;
361
362 if (total_mem + (md->num_pages << EFI_PAGE_SHIFT) > mem_limit) {
363 unsigned long limit_addr = md->phys_addr;
364
365 limit_addr += mem_limit - total_mem;
366 limit_addr = GRANULEROUNDDOWN(limit_addr);
367
368 if (md->phys_addr > limit_addr)
369 continue;
370
371 md->num_pages = (limit_addr - md->phys_addr) >>
372 EFI_PAGE_SHIFT;
373 first_non_wb_addr = max_addr = md->phys_addr +
374 (md->num_pages << EFI_PAGE_SHIFT);
375 }
376 total_mem += (md->num_pages << EFI_PAGE_SHIFT);
377
378 if (md->num_pages == 0)
379 continue;
380
381 curr.start = PAGE_OFFSET + md->phys_addr;
382 curr.end = curr.start + (md->num_pages << EFI_PAGE_SHIFT);
383
384 if (!prev_valid) {
385 prev = curr;
386 prev_valid = 1;
387 } else {
388 if (curr.start < prev.start)
389 printk(KERN_ERR "Oops: EFI memory table not ordered!\n");
390
391 if (prev.end == curr.start) {
392 /* merge two consecutive memory ranges */
393 prev.end = curr.end;
394 } else {
395 start = PAGE_ALIGN(prev.start);