aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2010-09-13 11:01:24 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-09-19 07:19:18 -0400
commitd907387c42e9e39261629890e45a08ef4c3ed3fe (patch)
treec25c1c7bde121ccb9ac56a434113c16d24203647
parent79e27dc0677b969e2d53b76fa0fa58467cce946a (diff)
ARM: 6383/1: Implement phys_mem_access_prot() to avoid attributes aliasing
ARMv7 onwards requires that there are no aliases to the same physical location using different memory types (i.e. Normal vs Strongly Ordered). Access to SO mappings when the unaligned accesses are handled in hardware is also Unpredictable (pgprot_noncached() mappings in user space). The /dev/mem driver requires uncached mappings with O_SYNC. The patch implements the phys_mem_access_prot() function which generates Strongly Ordered memory attributes if !pfn_valid() (independent of O_SYNC) and Normal Noncacheable (writecombine) if O_SYNC. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/include/asm/pgtable.h4
-rw-r--r--arch/arm/mm/mmu.c14
2 files changed, 18 insertions, 0 deletions
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h
index ab68cf1ef80f..e90b167ea848 100644
--- a/arch/arm/include/asm/pgtable.h
+++ b/arch/arm/include/asm/pgtable.h
@@ -317,6 +317,10 @@ static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
317#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE 317#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
318#define pgprot_dmacoherent(prot) \ 318#define pgprot_dmacoherent(prot) \
319 __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_BUFFERABLE) 319 __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_BUFFERABLE)
320#define __HAVE_PHYS_MEM_ACCESS_PROT
321struct file;
322extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
323 unsigned long size, pgprot_t vma_prot);
320#else 324#else
321#define pgprot_dmacoherent(prot) \ 325#define pgprot_dmacoherent(prot) \
322 __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_UNCACHED) 326 __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_UNCACHED)
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 6e1c4f6a2b3f..a486bd0d97dc 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -15,6 +15,7 @@
15#include <linux/nodemask.h> 15#include <linux/nodemask.h>
16#include <linux/memblock.h> 16#include <linux/memblock.h>
17#include <linux/sort.h> 17#include <linux/sort.h>
18#include <linux/fs.h>
18 19
19#include <asm/cputype.h> 20#include <asm/cputype.h>
20#include <asm/sections.h> 21#include <asm/sections.h>
@@ -498,6 +499,19 @@ static void __init build_mem_type_table(void)
498 } 499 }
499} 500}
500 501
502#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
503pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
504 unsigned long size, pgprot_t vma_prot)
505{
506 if (!pfn_valid(pfn))
507 return pgprot_noncached(vma_prot);
508 else if (file->f_flags & O_SYNC)
509 return pgprot_writecombine(vma_prot);
510 return vma_prot;
511}
512EXPORT_SYMBOL(phys_mem_access_prot);
513#endif
514
501#define vectors_base() (vectors_high() ? 0xffff0000 : 0) 515#define vectors_base() (vectors_high() ? 0xffff0000 : 0)
502 516
503static void __init *early_alloc(unsigned long sz) 517static void __init *early_alloc(unsigned long sz)