aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2011-05-19 08:22:48 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-05-26 05:23:25 -0400
commit40f7bfe4f1c2761abeceb3b2b9dc1feec3c47ed9 (patch)
treef7ed5abed753ec18fd5874d1088afc02dc23de0c
parent7b7bf499f79de3f6c85a340c8453a78789523f85 (diff)
ARM: 6914/1: sparsemem: fix highmem detection when using SPARSEMEM
sanity_check_meminfo walks over the registered memory banks and attempts to split banks across lowmem and highmem when they would otherwise overlap with the vmalloc space. When SPARSEMEM is used, there are two potential problems that occur when the virtual address of the start of a bank is equal to vmalloc_min. 1.) The end of lowmem is calculated as __pa(vmalloc_min - 1) + 1. In the above scenario, this will give the end address of the previous bank, rather than the actual bank we are interested in. This value is later used as the memblock limit and artificially restricts the total amount of available memory. 2.) The checks to determine whether or not a bank belongs to highmem or not only check if __va(bank->start) is greater or less than vmalloc_min. In the case that it is equal, the bank is incorrectly treated as lowmem, which hoses the vmalloc area. This patch fixes these two problems by checking whether the virtual start address of a bank is >= vmalloc_min and then calculating lowmem_end by finding the virtual end address of the highest lowmem bank. Acked-by: Catalin Marinas <catalin.marinas@arm.com> Reviewed-by: Nicolas Pitre <nicolas.pitre@linaro.org> Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/mm/mmu.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 08a92368d9d3..9d9e736c2b4f 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -763,15 +763,12 @@ static void __init sanity_check_meminfo(void)
763{ 763{
764 int i, j, highmem = 0; 764 int i, j, highmem = 0;
765 765
766 lowmem_limit = __pa(vmalloc_min - 1) + 1;
767 memblock_set_current_limit(lowmem_limit);
768
769 for (i = 0, j = 0; i < meminfo.nr_banks; i++) { 766 for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
770 struct membank *bank = &meminfo.bank[j]; 767 struct membank *bank = &meminfo.bank[j];
771 *bank = meminfo.bank[i]; 768 *bank = meminfo.bank[i];
772 769
773#ifdef CONFIG_HIGHMEM 770#ifdef CONFIG_HIGHMEM
774 if (__va(bank->start) > vmalloc_min || 771 if (__va(bank->start) >= vmalloc_min ||
775 __va(bank->start) < (void *)PAGE_OFFSET) 772 __va(bank->start) < (void *)PAGE_OFFSET)
776 highmem = 1; 773 highmem = 1;
777 774
@@ -829,6 +826,9 @@ static void __init sanity_check_meminfo(void)
829 bank->size = newsize; 826 bank->size = newsize;
830 } 827 }
831#endif 828#endif
829 if (!bank->highmem && bank->start + bank->size > lowmem_limit)
830 lowmem_limit = bank->start + bank->size;
831
832 j++; 832 j++;
833 } 833 }
834#ifdef CONFIG_HIGHMEM 834#ifdef CONFIG_HIGHMEM
@@ -852,6 +852,7 @@ static void __init sanity_check_meminfo(void)
852 } 852 }
853#endif 853#endif
854 meminfo.nr_banks = j; 854 meminfo.nr_banks = j;
855 memblock_set_current_limit(lowmem_limit);
855} 856}
856 857
857static inline void prepare_page_table(void) 858static inline void prepare_page_table(void)