From: orca.chen@gmail.com (Min-Hua Chen)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCHv3 1/2] arm: fix non-section-aligned low memory mapping
Date: Thu, 11 Jun 2015 02:59:32 +0800 [thread overview]
Message-ID: <1433962773-8402-2-git-send-email-orca.chen@gmail.com> (raw)
In-Reply-To: <1433962773-8402-1-git-send-email-orca.chen@gmail.com>
In current design, the memblock.current_limit is set to
a section-aligned value in sanity_check_meminfo().
However, the section-aligned memblock may become non-section-aligned
after arm_memblock_init(). For example, the first section-aligned
memblock is 0x00000000-0x01000000 and sanity_check_meminfo sets
current_limit to 0x01000000. After arm_memblock_init, two memory blocks
[0x00c00000 - 0x00d00000] and [0x00ff0000 - 0x01000000] are reserved
by memblock_reserve() and make the original memory block
[0x00000000-0x01000000] becomes:
[0x00000000-0x00c00000]
[0x00d00000-0x00ff0000]
When creating the low memory mapping for [0x00d00000-0x00ff0000],
since the memory block is non-section-aligned, it will need to create
a second level page table. But the current_limit is set to 0x01000000,
and it's possible to allocate a unmapped memory block.
call flow:
setup_arch
+ sanity_check_meminfo
+ arm_memblock_init
+ paging_init
+ map_lowmem
+ bootmem_init
Move the memblock_set_current_limit logic to map_lowmem(), we point
the memblock current_limit to the first section-aligned memblock block.
Since map_lowmem() is called after arm_memblock_init(), there is no way to
change memblock layout. So we can say that the first section-aligned limit
is valid during map_lowmem(). Hence fix the problem described above.
Signed-off-by: Min-Hua Chen <orca.chen@gmail.com>
---
arch/arm/mm/mmu.c | 48 ++++++++++++++----------------------------------
1 file changed, 14 insertions(+), 34 deletions(-)
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 4e6ef89..73e64ab 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1068,7 +1068,6 @@ phys_addr_t arm_lowmem_limit __initdata = 0;
void __init sanity_check_meminfo(void)
{
- phys_addr_t memblock_limit = 0;
int highmem = 0;
phys_addr_t vmalloc_limit = __pa(vmalloc_min - 1) + 1;
struct memblock_region *reg;
@@ -1110,43 +1109,10 @@ void __init sanity_check_meminfo(void)
else
arm_lowmem_limit = block_end;
}
-
- /*
- * Find the first non-section-aligned page, and point
- * memblock_limit at it. This relies on rounding the
- * limit down to be section-aligned, which happens at
- * the end of this function.
- *
- * With this algorithm, the start or end of almost any
- * bank can be non-section-aligned. The only exception
- * is that the start of the bank 0 must be section-
- * aligned, since otherwise memory would need to be
- * allocated when mapping the start of bank 0, which
- * occurs before any free memory is mapped.
- */
- if (!memblock_limit) {
- if (!IS_ALIGNED(block_start, SECTION_SIZE))
- memblock_limit = block_start;
- else if (!IS_ALIGNED(block_end, SECTION_SIZE))
- memblock_limit = arm_lowmem_limit;
- }
-
}
}
high_memory = __va(arm_lowmem_limit - 1) + 1;
-
- /*
- * Round the memblock limit down to a section size. This
- * helps to ensure that we will allocate memory from the
- * last full section, which should be mapped.
- */
- if (memblock_limit)
- memblock_limit = round_down(memblock_limit, SECTION_SIZE);
- if (!memblock_limit)
- memblock_limit = arm_lowmem_limit;
-
- memblock_set_current_limit(memblock_limit);
}
static inline void prepare_page_table(void)
@@ -1331,6 +1297,7 @@ static void __init map_lowmem(void)
struct memblock_region *reg;
phys_addr_t kernel_x_start = round_down(__pa(_stext), SECTION_SIZE);
phys_addr_t kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE);
+ phys_addr_t section_block_limit = 0;
/* Map all the lowmem memory banks. */
for_each_memblock(memory, reg) {
@@ -1384,6 +1351,19 @@ static void __init map_lowmem(void)
create_mapping(&map);
}
}
+
+ /*
+ * The first memblock MUST be section-size-aligned. Otherwise
+ * there is no valid low memory mapping to create 2nd level
+ * page tables.
+ * After the first mapping is created, other 2nd level
+ * page tables can be created from the memory allocated
+ * from the first memblock.
+ */
+ if (!section_memblock_limit) {
+ section_memblock_limit = end;
+ memblock_set_current_limit(section_memblock_limit);
+ }
}
}
--
1.7.10.4
next prev parent reply other threads:[~2015-06-10 18:59 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-06-10 18:59 [PATCHv3 0/2] creating non-section aligned lowmem mappings Min-Hua Chen
2015-06-10 18:59 ` Min-Hua Chen [this message]
2015-06-10 22:40 ` [PATCHv3 1/2] arm: fix non-section-aligned low memory mapping Russell King - ARM Linux
2015-06-11 0:02 ` Min-Hua Chen
2015-06-10 18:59 ` [PATCHv3 2/2] arm: use max_lowmem_limit in find_limit() Min-Hua Chen
2015-06-10 22:41 ` Russell King - ARM Linux
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1433962773-8402-2-git-send-email-orca.chen@gmail.com \
--to=orca.chen@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).