Patchwork [3.5.y.z,extended,stable] Patch "x86/mm: account for PGDIR_SIZE alignment" has been added to staging queue

mail settings
Submitter Luis Henriques
Date May 15, 2013, 10:34 a.m.
Message ID <>
Download mbox | patch
Permalink /patch/244011/
State New
Headers show


Luis Henriques - May 15, 2013, 10:34 a.m.
This is a note to let you know that I have just added a patch titled

    x86/mm: account for PGDIR_SIZE alignment

to the linux-3.5.y-queue branch of the 3.5.y.z extended stable tree 
which can be found at:;a=shortlog;h=refs/heads/linux-3.5.y-queue

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.5.y.z tree, see



From ca72c2a18cb8b82b1bdbf4f73e423f19e599cc3f Mon Sep 17 00:00:00 2001
From: Jerry Hoemann <>
Date: Tue, 30 Apr 2013 15:15:55 -0600
Subject: [PATCH] x86/mm: account for PGDIR_SIZE alignment

Patch for 3.0-stable.  Function find_early_table_space removed upstream.

Fixes panic in alloc_low_page due to pgt_buf overflow during

find_early_table_space sizes pgt_buf based upon the size of the
memory being mapped, but it does not take into account the alignment
of the memory.  When the region being mapped spans a 512GB (PGDIR_SIZE)
alignment, a panic from alloc_low_pages occurs.

kernel_physical_mapping_init takes into account PGDIR_SIZE alignment.
This causes an extra call to alloc_low_page to be made.  This extra call
isn't accounted for by find_early_table_space and causes a kernel panic.

Change is to take into account PGDIR_SIZE alignment in find_early_table_space.

Signed-off-by: Jerry Hoemann <>
Signed-off-by: Luis Henriques<>
 arch/x86/mm/init.c | 5 +++++
 1 file changed, 5 insertions(+)



diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index 4e4dcda..4779d7c 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -45,11 +45,15 @@  static void __init find_early_table_space(struct map_range *mr, int nr_range)
 	int i;
 	unsigned long puds = 0, pmds = 0, ptes = 0, tables;
 	unsigned long start = 0, good_end;
+	unsigned long pgd_extra = 0;
 	phys_addr_t base;

 	for (i = 0; i < nr_range; i++) {
 		unsigned long range, extra;

+		if ((mr[i].end >> PGDIR_SHIFT) - (mr[i].start >> PGDIR_SHIFT))
+			pgd_extra++;
 		range = mr[i].end - mr[i].start;
 		puds += (range + PUD_SIZE - 1) >> PUD_SHIFT;

@@ -74,6 +78,7 @@  static void __init find_early_table_space(struct map_range *mr, int nr_range)
 	tables = roundup(puds * sizeof(pud_t), PAGE_SIZE);
 	tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE);
 	tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE);
+	tables += (pgd_extra * PAGE_SIZE);

 #ifdef CONFIG_X86_32
 	/* for fixmap */