aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/mm
diff options
context:
space:
mode:
authorWANG Cong <xiyou.wangcong@gmail.com>2012-03-05 18:05:13 -0500
committerIngo Molnar <mingo@elte.hu>2012-03-06 03:38:26 -0500
commit722bc6b16771ed80871e1fd81c86d3627dda2ac8 (patch)
treecfad3c8a90d44a548603c28fb9387bd2021f7a34 /arch/x86/mm
parent550cf00dbc8ee402bef71628cb71246493dd4500 (diff)
x86/mm: Fix the size calculation of mapping tables
For machines that enable PSE, the first 2/4M memory region still uses 4K pages, so needs more PTEs in this case, but find_early_table_space() doesn't count this. This patch fixes it. The bug was found via code review, no misbehavior of the kernel was observed. Signed-off-by: WANG Cong <xiyou.wangcong@gmail.com> Cc: Yinghai Lu <yinghai@kernel.org> Cc: Tejun Heo <tj@kernel.org> Cc: <ianfang.cn@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Link: http://lkml.kernel.org/n/tip-kq6a00qe33h7c7ais2xsywnh@git.kernel.org Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/mm')
-rw-r--r--arch/x86/mm/init.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 6cabf6570d64..2e92fdcbea86 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -30,8 +30,14 @@ int direct_gbpages
30#endif 30#endif
31; 31;
32 32
33static void __init find_early_table_space(unsigned long end, int use_pse, 33struct map_range {
34 int use_gbpages) 34 unsigned long start;
35 unsigned long end;
36 unsigned page_size_mask;
37};
38
39static void __init find_early_table_space(struct map_range *mr, unsigned long end,
40 int use_pse, int use_gbpages)
35{ 41{
36 unsigned long puds, pmds, ptes, tables, start = 0, good_end = end; 42 unsigned long puds, pmds, ptes, tables, start = 0, good_end = end;
37 phys_addr_t base; 43 phys_addr_t base;
@@ -56,6 +62,9 @@ static void __init find_early_table_space(unsigned long end, int use_pse,
56#ifdef CONFIG_X86_32 62#ifdef CONFIG_X86_32
57 extra += PMD_SIZE; 63 extra += PMD_SIZE;
58#endif 64#endif
65 /* The first 2/4M doesn't use large pages. */
66 extra += mr->end - mr->start;
67
59 ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; 68 ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT;
60 } else 69 } else
61 ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; 70 ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT;
@@ -85,12 +94,6 @@ void __init native_pagetable_reserve(u64 start, u64 end)
85 memblock_reserve(start, end - start); 94 memblock_reserve(start, end - start);
86} 95}
87 96
88struct map_range {
89 unsigned long start;
90 unsigned long end;
91 unsigned page_size_mask;
92};
93
94#ifdef CONFIG_X86_32 97#ifdef CONFIG_X86_32
95#define NR_RANGE_MR 3 98#define NR_RANGE_MR 3
96#else /* CONFIG_X86_64 */ 99#else /* CONFIG_X86_64 */
@@ -262,7 +265,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
262 * nodes are discovered. 265 * nodes are discovered.
263 */ 266 */
264 if (!after_bootmem) 267 if (!after_bootmem)
265 find_early_table_space(end, use_pse, use_gbpages); 268 find_early_table_space(&mr[0], end, use_pse, use_gbpages);
266 269
267 for (i = 0; i < nr_range; i++) 270 for (i = 0; i < nr_range; i++)
268 ret = kernel_physical_mapping_init(mr[i].start, mr[i].end, 271 ret = kernel_physical_mapping_init(mr[i].start, mr[i].end,