diff options
Diffstat (limited to 'arch/ia64/mm/init.c')
| -rw-r--r-- | arch/ia64/mm/init.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index 2f50c064513c..30617ccb4f7e 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c | |||
| @@ -415,6 +415,61 @@ ia64_mmu_init (void *my_cpu_data) | |||
| 415 | } | 415 | } |
| 416 | 416 | ||
| 417 | #ifdef CONFIG_VIRTUAL_MEM_MAP | 417 | #ifdef CONFIG_VIRTUAL_MEM_MAP |
| 418 | int vmemmap_find_next_valid_pfn(int node, int i) | ||
| 419 | { | ||
| 420 | unsigned long end_address, hole_next_pfn; | ||
| 421 | unsigned long stop_address; | ||
| 422 | pg_data_t *pgdat = NODE_DATA(node); | ||
| 423 | |||
| 424 | end_address = (unsigned long) &vmem_map[pgdat->node_start_pfn + i]; | ||
| 425 | end_address = PAGE_ALIGN(end_address); | ||
| 426 | |||
| 427 | stop_address = (unsigned long) &vmem_map[ | ||
| 428 | pgdat->node_start_pfn + pgdat->node_spanned_pages]; | ||
| 429 | |||
| 430 | do { | ||
| 431 | pgd_t *pgd; | ||
| 432 | pud_t *pud; | ||
| 433 | pmd_t *pmd; | ||
| 434 | pte_t *pte; | ||
| 435 | |||
| 436 | pgd = pgd_offset_k(end_address); | ||
| 437 | if (pgd_none(*pgd)) { | ||
| 438 | end_address += PGDIR_SIZE; | ||
| 439 | continue; | ||
| 440 | } | ||
| 441 | |||
| 442 | pud = pud_offset(pgd, end_address); | ||
| 443 | if (pud_none(*pud)) { | ||
| 444 | end_address += PUD_SIZE; | ||
| 445 | continue; | ||
| 446 | } | ||
| 447 | |||
| 448 | pmd = pmd_offset(pud, end_address); | ||
| 449 | if (pmd_none(*pmd)) { | ||
| 450 | end_address += PMD_SIZE; | ||
| 451 | continue; | ||
| 452 | } | ||
| 453 | |||
| 454 | pte = pte_offset_kernel(pmd, end_address); | ||
| 455 | retry_pte: | ||
| 456 | if (pte_none(*pte)) { | ||
| 457 | end_address += PAGE_SIZE; | ||
| 458 | pte++; | ||
| 459 | if ((end_address < stop_address) && | ||
| 460 | (end_address != ALIGN(end_address, 1UL << PMD_SHIFT))) | ||
| 461 | goto retry_pte; | ||
| 462 | continue; | ||
| 463 | } | ||
| 464 | /* Found next valid vmem_map page */ | ||
| 465 | break; | ||
| 466 | } while (end_address < stop_address); | ||
| 467 | |||
| 468 | end_address = min(end_address, stop_address); | ||
| 469 | end_address = end_address - (unsigned long) vmem_map + sizeof(struct page) - 1; | ||
| 470 | hole_next_pfn = end_address / sizeof(struct page); | ||
| 471 | return hole_next_pfn - pgdat->node_start_pfn; | ||
| 472 | } | ||
| 418 | 473 | ||
| 419 | int __init | 474 | int __init |
| 420 | create_mem_map_page_table (u64 start, u64 end, void *arg) | 475 | create_mem_map_page_table (u64 start, u64 end, void *arg) |
