aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Bader <stefan.bader@canonical.com>2016-05-20 19:58:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-20 20:58:30 -0400
commit4b50bcc7eda4d3cc9e3f2a0aa60e590fedf728c5 (patch)
treed40803c6fbc646ea062c29c03bdcdf16422c775b
parentd2005e3f41d4f9299e2df6a967c8beb5086967a9 (diff)
mm: use phys_addr_t for reserve_bootmem_region() arguments
Since commit 92923ca3aace ("mm: meminit: only set page reserved in the memblock region") the reserved bit is set on reserved memblock regions. However start and end address are passed as unsigned long. This is only 32bit on i386, so it can end up marking the wrong pages reserved for ranges at 4GB and above. This was observed on a 32bit Xen dom0 which was booted with initial memory set to a value below 4G but allowing to balloon in memory (dom0_mem=1024M for example). This would define a reserved bootmem region for the additional memory (for example on a 8GB system there was a reverved region covering the 4GB-8GB range). But since the addresses were passed on as unsigned long, this was actually marking all pages from 0 to 4GB as reserved. Fixes: 92923ca3aacef63 ("mm: meminit: only set page reserved in the memblock region") Link: http://lkml.kernel.org/r/1463491221-10573-1-git-send-email-stefan.bader@canonical.com Signed-off-by: Stefan Bader <stefan.bader@canonical.com> Cc: <stable@vger.kernel.org> [4.2+] Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/mm.h2
-rw-r--r--mm/page_alloc.c2
2 files changed, 2 insertions, 2 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 65d18a45b8e8..fbdb9d40847f 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1763,7 +1763,7 @@ extern void free_highmem_page(struct page *page);
1763extern void adjust_managed_page_count(struct page *page, long count); 1763extern void adjust_managed_page_count(struct page *page, long count);
1764extern void mem_init_print_info(const char *str); 1764extern void mem_init_print_info(const char *str);
1765 1765
1766extern void reserve_bootmem_region(unsigned long start, unsigned long end); 1766extern void reserve_bootmem_region(phys_addr_t start, phys_addr_t end);
1767 1767
1768/* Free the reserved page into the buddy system, so it gets managed. */ 1768/* Free the reserved page into the buddy system, so it gets managed. */
1769static inline void __free_reserved_page(struct page *page) 1769static inline void __free_reserved_page(struct page *page)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 3f4b69aaa23a..2dd1ba4e70cc 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1205,7 +1205,7 @@ static inline void init_reserved_page(unsigned long pfn)
1205 * marks the pages PageReserved. The remaining valid pages are later 1205 * marks the pages PageReserved. The remaining valid pages are later
1206 * sent to the buddy page allocator. 1206 * sent to the buddy page allocator.
1207 */ 1207 */
1208void __meminit reserve_bootmem_region(unsigned long start, unsigned long end) 1208void __meminit reserve_bootmem_region(phys_addr_t start, phys_addr_t end)
1209{ 1209{
1210 unsigned long start_pfn = PFN_DOWN(start); 1210 unsigned long start_pfn = PFN_DOWN(start);
1211 unsigned long end_pfn = PFN_UP(end); 1211 unsigned long end_pfn = PFN_UP(end);