aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2012-10-22 19:35:18 -0400
committerH. Peter Anvin <hpa@linux.intel.com>2012-10-24 14:52:21 -0400
commit6ede1fd3cb404c0016de6ac529df46d561bd558b (patch)
treec5537b527a5a065fff2bd9b33d003561a0d87206
parent94777fc51b3ad85ff9f705ddf7cdd0eb3bbad5a6 (diff)
x86, mm: Trim memory in memblock to be page aligned
We will not map partial pages, so need to make sure memblock allocation will not allocate those bytes out. Also we will use for_each_mem_pfn_range() to loop to map memory range to keep them consistent. Signed-off-by: Yinghai Lu <yinghai@kernel.org> Link: http://lkml.kernel.org/r/CAE9FiQVZirvaBMFYRfXMmWEcHbKSicQEHz4VAwUv0xFCk51ZNw@mail.gmail.com Acked-by: Jacob Shin <jacob.shin@amd.com> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> Cc: <stable@vger.kernel.org>
-rw-r--r--arch/x86/kernel/e820.c3
-rw-r--r--include/linux/memblock.h1
-rw-r--r--mm/memblock.c24
3 files changed, 28 insertions, 0 deletions
diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
index ed858e9e9a74..df06ade26bef 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -1077,6 +1077,9 @@ void __init memblock_x86_fill(void)
1077 memblock_add(ei->addr, ei->size); 1077 memblock_add(ei->addr, ei->size);
1078 } 1078 }
1079 1079
1080 /* throw away partial pages */
1081 memblock_trim_memory(PAGE_SIZE);
1082
1080 memblock_dump_all(); 1083 memblock_dump_all();
1081} 1084}
1082 1085
diff --git a/include/linux/memblock.h b/include/linux/memblock.h
index 569d67d4243e..d452ee191066 100644
--- a/include/linux/memblock.h
+++ b/include/linux/memblock.h
@@ -57,6 +57,7 @@ int memblock_add(phys_addr_t base, phys_addr_t size);
57int memblock_remove(phys_addr_t base, phys_addr_t size); 57int memblock_remove(phys_addr_t base, phys_addr_t size);
58int memblock_free(phys_addr_t base, phys_addr_t size); 58int memblock_free(phys_addr_t base, phys_addr_t size);
59int memblock_reserve(phys_addr_t base, phys_addr_t size); 59int memblock_reserve(phys_addr_t base, phys_addr_t size);
60void memblock_trim_memory(phys_addr_t align);
60 61
61#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP 62#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
62void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn, 63void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn,
diff --git a/mm/memblock.c b/mm/memblock.c
index 931eef145af5..625905523c2a 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -930,6 +930,30 @@ int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t si
930 return memblock_overlaps_region(&memblock.reserved, base, size) >= 0; 930 return memblock_overlaps_region(&memblock.reserved, base, size) >= 0;
931} 931}
932 932
933void __init_memblock memblock_trim_memory(phys_addr_t align)
934{
935 int i;
936 phys_addr_t start, end, orig_start, orig_end;
937 struct memblock_type *mem = &memblock.memory;
938
939 for (i = 0; i < mem->cnt; i++) {
940 orig_start = mem->regions[i].base;
941 orig_end = mem->regions[i].base + mem->regions[i].size;
942 start = round_up(orig_start, align);
943 end = round_down(orig_end, align);
944
945 if (start == orig_start && end == orig_end)
946 continue;
947
948 if (start < end) {
949 mem->regions[i].base = start;
950 mem->regions[i].size = end - start;
951 } else {
952 memblock_remove_region(mem, i);
953 i--;
954 }
955 }
956}
933 957
934void __init_memblock memblock_set_current_limit(phys_addr_t limit) 958void __init_memblock memblock_set_current_limit(phys_addr_t limit)
935{ 959{