diff options
Diffstat (limited to 'mm/page_alloc.c')
| -rw-r--r-- | mm/page_alloc.c | 86 |
1 files changed, 51 insertions, 35 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index f12ad1836abe..2a362c52fdf4 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/pagemap.h> | 21 | #include <linux/pagemap.h> |
| 22 | #include <linux/jiffies.h> | 22 | #include <linux/jiffies.h> |
| 23 | #include <linux/bootmem.h> | 23 | #include <linux/bootmem.h> |
| 24 | #include <linux/memblock.h> | ||
| 24 | #include <linux/compiler.h> | 25 | #include <linux/compiler.h> |
| 25 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
| 26 | #include <linux/kmemcheck.h> | 27 | #include <linux/kmemcheck.h> |
| @@ -3636,6 +3637,41 @@ void __init free_bootmem_with_active_regions(int nid, | |||
| 3636 | } | 3637 | } |
| 3637 | } | 3638 | } |
| 3638 | 3639 | ||
| 3640 | #ifdef CONFIG_HAVE_MEMBLOCK | ||
| 3641 | u64 __init find_memory_core_early(int nid, u64 size, u64 align, | ||
| 3642 | u64 goal, u64 limit) | ||
| 3643 | { | ||
| 3644 | int i; | ||
| 3645 | |||
| 3646 | /* Need to go over early_node_map to find out good range for node */ | ||
| 3647 | for_each_active_range_index_in_nid(i, nid) { | ||
| 3648 | u64 addr; | ||
| 3649 | u64 ei_start, ei_last; | ||
| 3650 | u64 final_start, final_end; | ||
| 3651 | |||
| 3652 | ei_last = early_node_map[i].end_pfn; | ||
| 3653 | ei_last <<= PAGE_SHIFT; | ||
| 3654 | ei_start = early_node_map[i].start_pfn; | ||
| 3655 | ei_start <<= PAGE_SHIFT; | ||
| 3656 | |||
| 3657 | final_start = max(ei_start, goal); | ||
| 3658 | final_end = min(ei_last, limit); | ||
| 3659 | |||
| 3660 | if (final_start >= final_end) | ||
| 3661 | continue; | ||
| 3662 | |||
| 3663 | addr = memblock_find_in_range(final_start, final_end, size, align); | ||
| 3664 | |||
| 3665 | if (addr == MEMBLOCK_ERROR) | ||
| 3666 | continue; | ||
| 3667 | |||
| 3668 | return addr; | ||
| 3669 | } | ||
| 3670 | |||
| 3671 | return MEMBLOCK_ERROR; | ||
| 3672 | } | ||
| 3673 | #endif | ||
| 3674 | |||
| 3639 | int __init add_from_early_node_map(struct range *range, int az, | 3675 | int __init add_from_early_node_map(struct range *range, int az, |
| 3640 | int nr_range, int nid) | 3676 | int nr_range, int nid) |
| 3641 | { | 3677 | { |
| @@ -3655,46 +3691,26 @@ int __init add_from_early_node_map(struct range *range, int az, | |||
| 3655 | void * __init __alloc_memory_core_early(int nid, u64 size, u64 align, | 3691 | void * __init __alloc_memory_core_early(int nid, u64 size, u64 align, |
| 3656 | u64 goal, u64 limit) | 3692 | u64 goal, u64 limit) |
| 3657 | { | 3693 | { |
| 3658 | int i; | ||
| 3659 | void *ptr; | 3694 | void *ptr; |
| 3695 | u64 addr; | ||
| 3660 | 3696 | ||
| 3661 | if (limit > get_max_mapped()) | 3697 | if (limit > memblock.current_limit) |
| 3662 | limit = get_max_mapped(); | 3698 | limit = memblock.current_limit; |
| 3663 | |||
| 3664 | /* need to go over early_node_map to find out good range for node */ | ||
| 3665 | for_each_active_range_index_in_nid(i, nid) { | ||
| 3666 | u64 addr; | ||
| 3667 | u64 ei_start, ei_last; | ||
| 3668 | |||
| 3669 | ei_last = early_node_map[i].end_pfn; | ||
| 3670 | ei_last <<= PAGE_SHIFT; | ||
| 3671 | ei_start = early_node_map[i].start_pfn; | ||
| 3672 | ei_start <<= PAGE_SHIFT; | ||
| 3673 | addr = find_early_area(ei_start, ei_last, | ||
| 3674 | goal, limit, size, align); | ||
| 3675 | |||
| 3676 | if (addr == -1ULL) | ||
| 3677 | continue; | ||
| 3678 | 3699 | ||
| 3679 | #if 0 | 3700 | addr = find_memory_core_early(nid, size, align, goal, limit); |
| 3680 | printk(KERN_DEBUG "alloc (nid=%d %llx - %llx) (%llx - %llx) %llx %llx => %llx\n", | ||
| 3681 | nid, | ||
| 3682 | ei_start, ei_last, goal, limit, size, | ||
| 3683 | align, addr); | ||
| 3684 | #endif | ||
| 3685 | 3701 | ||
| 3686 | ptr = phys_to_virt(addr); | 3702 | if (addr == MEMBLOCK_ERROR) |
| 3687 | memset(ptr, 0, size); | 3703 | return NULL; |
| 3688 | reserve_early_without_check(addr, addr + size, "BOOTMEM"); | ||
| 3689 | /* | ||
| 3690 | * The min_count is set to 0 so that bootmem allocated blocks | ||
| 3691 | * are never reported as leaks. | ||
| 3692 | */ | ||
| 3693 | kmemleak_alloc(ptr, size, 0, 0); | ||
| 3694 | return ptr; | ||
| 3695 | } | ||
| 3696 | 3704 | ||
| 3697 | return NULL; | 3705 | ptr = phys_to_virt(addr); |
| 3706 | memset(ptr, 0, size); | ||
| 3707 | memblock_x86_reserve_range(addr, addr + size, "BOOTMEM"); | ||
| 3708 | /* | ||
| 3709 | * The min_count is set to 0 so that bootmem allocated blocks | ||
| 3710 | * are never reported as leaks. | ||
| 3711 | */ | ||
| 3712 | kmemleak_alloc(ptr, size, 0, 0); | ||
| 3713 | return ptr; | ||
| 3698 | } | 3714 | } |
| 3699 | #endif | 3715 | #endif |
| 3700 | 3716 | ||
