From 309caa9cc6ff39d261264ec4ff10e29489afc8f8 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 21 Jun 2010 21:03:18 +0100 Subject: ARM: Prohibit ioremap() on kernel managed RAM ARMv6 and above have a restriction whereby aliasing virtual:physical mappings must not have differing memory type and sharability attributes. Strictly, this covers the memory type (strongly ordered, device, memory), cache attributes (uncached, write combine, write through, write back read alloc, write back write alloc) and the shared bit. However, using ioremap() and its variants on system RAM results in mappings which differ in these attributes from the main system RAM mapping. Other architectures which similar restrictions approch this problem in the same way - they do not permit ioremap on main system RAM. Make ARM behave in the same way, with a WARN_ON() such that users can be traced and an alternative approach found. Signed-off-by: Russell King --- arch/arm/mm/ioremap.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'arch/arm/mm/ioremap.c') diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 28c8b950ef04..03f11935ed08 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -268,6 +268,12 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SUPERSECTION_MASK)) return NULL; + /* + * Don't allow RAM to be mapped - this causes problems with ARMv6+ + */ + if (WARN_ON(pfn_valid(pfn))) + return NULL; + type = get_mem_type(mtype); if (!type) return NULL; -- cgit v1.2.3 From d746196361c9c635128249bb6cf13e709ae6abe1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 26 Jul 2010 10:29:13 +0100 Subject: ARM: use generic ioremap_page_range() We don't need our own implementation of this, use the generic library implementation instead. Signed-off-by: Russell King --- arch/arm/mm/ioremap.c | 74 +++------------------------------------------------ 1 file changed, 4 insertions(+), 70 deletions(-) (limited to 'arch/arm/mm/ioremap.c') diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 03f11935ed08..ab506272b2d3 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -42,78 +42,11 @@ */ #define VM_ARM_SECTION_MAPPING 0x80000000 -static int remap_area_pte(pmd_t *pmd, unsigned long addr, unsigned long end, - unsigned long phys_addr, const struct mem_type *type) -{ - pgprot_t prot = __pgprot(type->prot_pte); - pte_t *pte; - - pte = pte_alloc_kernel(pmd, addr); - if (!pte) - return -ENOMEM; - - do { - if (!pte_none(*pte)) - goto bad; - - set_pte_ext(pte, pfn_pte(phys_addr >> PAGE_SHIFT, prot), 0); - phys_addr += PAGE_SIZE; - } while (pte++, addr += PAGE_SIZE, addr != end); - return 0; - - bad: - printk(KERN_CRIT "remap_area_pte: page already exists\n"); - BUG(); -} - -static inline int remap_area_pmd(pgd_t *pgd, unsigned long addr, - unsigned long end, unsigned long phys_addr, - const struct mem_type *type) -{ - unsigned long next; - pmd_t *pmd; - int ret = 0; - - pmd = pmd_alloc(&init_mm, pgd, addr); - if (!pmd) - return -ENOMEM; - - do { - next = pmd_addr_end(addr, end); - ret = remap_area_pte(pmd, addr, next, phys_addr, type); - if (ret) - return ret; - phys_addr += next - addr; - } while (pmd++, addr = next, addr != end); - return ret; -} - -static int remap_area_pages(unsigned long start, unsigned long pfn, - size_t size, const struct mem_type *type) -{ - unsigned long addr = start; - unsigned long next, end = start + size; - unsigned long phys_addr = __pfn_to_phys(pfn); - pgd_t *pgd; - int err = 0; - - BUG_ON(addr >= end); - pgd = pgd_offset_k(addr); - do { - next = pgd_addr_end(addr, end); - err = remap_area_pmd(pgd, addr, next, phys_addr, type); - if (err) - break; - phys_addr += next - addr; - } while (pgd++, addr = next, addr != end); - - return err; -} - int ioremap_page(unsigned long virt, unsigned long phys, const struct mem_type *mtype) { - return remap_area_pages(virt, __phys_to_pfn(phys), PAGE_SIZE, mtype); + return ioremap_page_range(virt, virt + PAGE_SIZE, phys, + __pgprot(mtype->prot_pte)); } EXPORT_SYMBOL(ioremap_page); @@ -300,7 +233,8 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn, err = remap_area_sections(addr, pfn, size, type); } else #endif - err = remap_area_pages(addr, pfn, size, type); + err = ioremap_page_range(addr, addr + size, __pfn_to_phys(pfn), + __pgprot(type->prot_pte)); if (err) { vunmap((void *)addr); -- cgit v1.2.3