[linux-yocto] [PATCH 12/26] arm: mmu: Fix truncated 40-bit physaddr (LPAE)

Anders Berg anders.berg at lsi.com
Thu Mar 20 03:14:25 PDT 2014


On Thu, Mar 20, 2014 at 04:48:27AM -0400, Bruce Ashfield wrote:
> On 14-03-18 03:49 AM, Charlie Paul wrote:
> >From: Anders Berg <anders.berg at lsi.com>
> >
> >Wrong type for parameter 'phys' caused adress to be truncated to 32-bits,
> >causing iotable_init() to produce wrong MMU mappings on LPAE system.
> >
> >arm/mmu: Fix detection of vmalloc area overlap
> >
> >Fix problem when passing mem=4G (or 4GB memory specified on the device tree
> >memory node) when running without CONFIG_HIGHMEM . In this case, the test for
> >vmalloc area overlap would fail (because of a 32-bit overflow) and the memory
> >block would not be properly truncated to a lowmem compliant size.
> 
> Same comment here. When we change a common file, the change must be suitable
> for all boards.
> 
> Is this safe for all 32 bit ARM boards ? Is it destined for mainline ?
> 

This was originally two commits. Both have been fixed upstream:

20d6956 ARM: LPAE: use phys_addr_t in alloc_init_pud()
36418c5 ARM: 7499/1: mm: Fix vmalloc overlap check for !HIGHMEM

Charile: What's up with all the white-space changes (and what looks like
checkpatch cleanups). This was not in my original commit(s)?

/Anders

> Bruce
> 
> >
> >Signed-off-by: Anders Berg <anders.berg at lsi.com>
> >---
> >  arch/arm/mm/mmu.c |   82 +++++++++++++++++++++++------------------------------
> >  1 file changed, 36 insertions(+), 46 deletions(-)
> >
> >diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
> >index f117e1f..6ccd654 100644
> >--- a/arch/arm/mm/mmu.c
> >+++ b/arch/arm/mm/mmu.c
> >@@ -53,13 +53,13 @@ pmd_t *top_pmd;
> >  #define CPOLICY_WRITEALLOC	4
> >
> >  static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK;
> >-static unsigned int ecc_mask __initdata = 0;
> >+static unsigned int ecc_mask __initdata;
> >  pgprot_t pgprot_user;
> >-pgprot_t pgprot_kernel;
> >-
> >  EXPORT_SYMBOL(pgprot_user);
> >+pgprot_t pgprot_kernel;
> >  EXPORT_SYMBOL(pgprot_kernel);
> >
> >+
> >  struct cachepolicy {
> >  	const char	policy[16];
> >  	unsigned int	cr_mask;
> >@@ -194,8 +194,8 @@ void adjust_cr(unsigned long mask, unsigned long set)
> >  }
> >  #endif
> >
> >-#define PROT_PTE_DEVICE		L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN
> >-#define PROT_SECT_DEVICE	PMD_TYPE_SECT|PMD_SECT_AP_WRITE
> >+#define PROT_PTE_DEVICE		(L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN)
> >+#define PROT_SECT_DEVICE	(PMD_TYPE_SECT|PMD_SECT_AP_WRITE)
> >
> >  static struct mem_type mem_types[] = {
> >  	[MT_DEVICE] = {		  /* Strongly ordered / ARMv6 shared device */
> >@@ -216,7 +216,7 @@ static struct mem_type mem_types[] = {
> >  		.prot_l1	= PMD_TYPE_TABLE,
> >  		.prot_sect	= PROT_SECT_DEVICE | PMD_SECT_WB,
> >  		.domain		= DOMAIN_IO,
> >-	},	
> >+	},
> >  	[MT_DEVICE_WC] = {	/* ioremap_wc */
> >  		.prot_pte	= PROT_PTE_DEVICE | L_PTE_MT_DEV_WC,
> >  		.prot_l1	= PMD_TYPE_TABLE,
> >@@ -532,7 +532,7 @@ static void __init build_mem_type_table(void)
> >  		mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WB;
> >  		break;
> >  	}
> >-	printk("Memory policy: ECC %sabled, Data cache %s\n",
> >+	printk(KERN_INFO "Memory policy: ECC %sabled, Data cache %s\n",
> >  		ecc_mask ? "en" : "dis", cp->policy);
> >
> >  	for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
> >@@ -628,7 +628,7 @@ static void __init alloc_init_section(pud_t *pud, unsigned long addr,
> >  }
> >
> >  static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
> >-	unsigned long end, unsigned long phys, const struct mem_type *type)
> >+	unsigned long end, phys_addr_t phys, const struct mem_type *type)
> >  {
> >  	pud_t *pud = pud_offset(pgd, addr);
> >  	unsigned long next;
> >@@ -653,9 +653,8 @@ static void __init create_36bit_mapping(struct map_desc *md,
> >  	length = PAGE_ALIGN(md->length);
> >
> >  	if (!(cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())) {
> >-		printk(KERN_ERR "MM: CPU does not support supersection "
> >-		       "mapping for 0x%08llx at 0x%08lx\n",
> >-		       (long long)__pfn_to_phys((u64)md->pfn), addr);
> >+		printk(KERN_ERR "MM: CPU does not support supersection mapping for 0x%08llx at 0x%08lx\n",
> >+				(long long)__pfn_to_phys((u64)md->pfn), addr);
> >  		return;
> >  	}
> >
> >@@ -666,16 +665,14 @@ static void __init create_36bit_mapping(struct map_desc *md,
> >  	 *	of the actual domain assignments in use.
> >  	 */
> >  	if (type->domain) {
> >-		printk(KERN_ERR "MM: invalid domain in supersection "
> >-		       "mapping for 0x%08llx at 0x%08lx\n",
> >-		       (long long)__pfn_to_phys((u64)md->pfn), addr);
> >+		printk(KERN_ERR "MM: invalid domain in supersection mapping for 0x%08llx at 0x%08lx\n",
> >+				(long long)__pfn_to_phys((u64)md->pfn), addr);
> >  		return;
> >  	}
> >
> >  	if ((addr | length | __pfn_to_phys(md->pfn)) & ~SUPERSECTION_MASK) {
> >-		printk(KERN_ERR "MM: cannot create mapping for 0x%08llx"
> >-		       " at 0x%08lx invalid alignment\n",
> >-		       (long long)__pfn_to_phys((u64)md->pfn), addr);
> >+		printk(KERN_ERR "MM: cannot create mapping for 0x%08llx at 0x%08lx invalid alignment\n",
> >+				(long long)__pfn_to_phys((u64)md->pfn), addr);
> >  		return;
> >  	}
> >
> >@@ -717,18 +714,16 @@ static void __init create_mapping(struct map_desc *md)
> >  	pgd_t *pgd;
> >
> >  	if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
> >-		printk(KERN_WARNING "BUG: not creating mapping for 0x%08llx"
> >-		       " at 0x%08lx in user region\n",
> >-		       (long long)__pfn_to_phys((u64)md->pfn), md->virtual);
> >+		printk(KERN_WARNING "BUG: not creating mapping for 0x%08llx at 0x%08lx in user region\n",
> >+				(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
> >  		return;
> >  	}
> >
> >  	if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
> >  	    md->virtual >= PAGE_OFFSET &&
> >  	    (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) {
> >-		printk(KERN_WARNING "BUG: mapping for 0x%08llx"
> >-		       " at 0x%08lx out of vmalloc space\n",
> >-		       (long long)__pfn_to_phys((u64)md->pfn), md->virtual);
> >+		printk(KERN_WARNING "BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n",
> >+				(long long)__pfn_to_phys((u64)md->pfn), md->virtual);
> >  	}
> >
> >  	type = &mem_types[md->type];
> >@@ -748,9 +743,8 @@ static void __init create_mapping(struct map_desc *md)
> >  	length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
> >
> >  	if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) {
> >-		printk(KERN_WARNING "BUG: map for 0x%08llx at 0x%08lx can not "
> >-		       "be mapped using pages, ignoring.\n",
> >-		       (long long)__pfn_to_phys(md->pfn), addr);
> >+		printk(KERN_WARNING "BUG: map for 0x%08llx at 0x%08lx can not be mapped using pages, ignoring.\n",
> >+				(long long)__pfn_to_phys(md->pfn), addr);
> >  		return;
> >  	}
> >
> >@@ -783,8 +777,8 @@ void __init iotable_init(struct map_desc *io_desc, int nr)
> >  		create_mapping(md);
> >  		vm->addr = (void *)(md->virtual & PAGE_MASK);
> >  		vm->size = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
> >-		vm->phys_addr = __pfn_to_phys(md->pfn);
> >-		vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;
> >+		vm->phys_addr = __pfn_to_phys(md->pfn);
> >+		vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;
> >  		vm->flags |= VM_ARM_MTYPE(md->type);
> >  		vm->caller = iotable_init;
> >  		vm_area_add_early(vm++);
> >@@ -895,7 +889,7 @@ static int __init early_vmalloc(char *arg)
> >  }
> >  early_param("vmalloc", early_vmalloc);
> >
> >-phys_addr_t arm_lowmem_limit __initdata = 0;
> >+phys_addr_t arm_lowmem_limit __initdata;
> >
> >  void __init sanity_check_meminfo(void)
> >  {
> >@@ -922,8 +916,7 @@ void __init sanity_check_meminfo(void)
> >  		if (!highmem && __va(bank->start) < vmalloc_min &&
> >  		    bank->size > vmalloc_min - __va(bank->start)) {
> >  			if (meminfo.nr_banks >= NR_BANKS) {
> >-				printk(KERN_CRIT "NR_BANKS too low, "
> >-						 "ignoring high memory\n");
> >+				printk(KERN_CRIT "NR_BANKS too low, ignoring high memory\n");
> >  			} else {
> >  				memmove(bank + 1, bank,
> >  					(meminfo.nr_banks - i) * sizeof(*bank));
> >@@ -943,10 +936,9 @@ void __init sanity_check_meminfo(void)
> >  		 * Highmem banks not allowed with !CONFIG_HIGHMEM.
> >  		 */
> >  		if (highmem) {
> >-			printk(KERN_NOTICE "Ignoring RAM at %.8llx-%.8llx "
> >-			       "(!CONFIG_HIGHMEM).\n",
> >-			       (unsigned long long)bank->start,
> >-			       (unsigned long long)bank->start + bank->size - 1);
> >+			printk(KERN_NOTICE "Ignoring RAM at %.8llx-%.8llx (!CONFIG_HIGHMEM).\n",
> >+					(unsigned long long)bank->start,
> >+					(unsigned long long)bank->start + bank->size - 1);
> >  			continue;
> >  		}
> >
> >@@ -956,10 +948,9 @@ void __init sanity_check_meminfo(void)
> >  		 */
> >  		if (__va(bank->start) >= vmalloc_min ||
> >  		    __va(bank->start) < (void *)PAGE_OFFSET) {
> >-			printk(KERN_NOTICE "Ignoring RAM at %.8llx-%.8llx "
> >-			       "(vmalloc region overlap).\n",
> >-			       (unsigned long long)bank->start,
> >-			       (unsigned long long)bank->start + bank->size - 1);
> >+			printk(KERN_NOTICE "Ignoring RAM at %.8llx-%.8llx (vmalloc region overlap).\n",
> >+					(unsigned long long)bank->start,
> >+					(unsigned long long)bank->start + bank->size - 1);
> >  			continue;
> >  		}
> >
> >@@ -967,14 +958,13 @@ void __init sanity_check_meminfo(void)
> >  		 * Check whether this memory bank would partially overlap
> >  		 * the vmalloc area.
> >  		 */
> >-		if (__va(bank->start + bank->size) > vmalloc_min ||
> >-		    __va(bank->start + bank->size) < __va(bank->start)) {
> >+		if (__va(bank->start + bank->size -1) >= vmalloc_min ||
> >+		    __va(bank->start + bank->size -1) <= __va(bank->start)) {
> >  			unsigned long newsize = vmalloc_min - __va(bank->start);
> >-			printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx "
> >-			       "to -%.8llx (vmalloc region overlap).\n",
> >-			       (unsigned long long)bank->start,
> >-			       (unsigned long long)bank->start + bank->size - 1,
> >-			       (unsigned long long)bank->start + newsize - 1);
> >+			printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx to -%.8llx (vmalloc region overlap).\n",
> >+					(unsigned long long)bank->start,
> >+					(unsigned long long)bank->start + bank->size - 1,
> >+					(unsigned long long)bank->start + newsize - 1);
> >  			bank->size = newsize;
> >  		}
> >  #endif
> >
> 
> 


More information about the linux-yocto mailing list