|
@@ -161,3 +161,136 @@ extern void __cpuc_flush_dcache_area(void *, size_t);
|
|
|
* is visible to DMA, or data written by DMA to system memory is
|
|
|
* visible to the CPU.
|
|
|
*/
|
|
|
+extern void dmac_map_area(const void *, size_t, int);
|
|
|
+extern void dmac_unmap_area(const void *, size_t, int);
|
|
|
+extern void dmac_flush_range(const void *, const void *);
|
|
|
+
|
|
|
+#endif
|
|
|
+
|
|
|
+/*
|
|
|
+ * Copy user data from/to a page which is mapped into a different
|
|
|
+ * processes address space. Really, we want to allow our "user
|
|
|
+ * space" model to handle this.
|
|
|
+ */
|
|
|
+extern void copy_to_user_page(struct vm_area_struct *, struct page *,
|
|
|
+ unsigned long, void *, const void *, unsigned long);
|
|
|
+#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
|
|
|
+ do { \
|
|
|
+ memcpy(dst, src, len); \
|
|
|
+ } while (0)
|
|
|
+
|
|
|
+/*
|
|
|
+ * Convert calls to our calling convention.
|
|
|
+ */
|
|
|
+
|
|
|
+/* Invalidate I-cache */
|
|
|
+#define __flush_icache_all_generic() \
|
|
|
+ asm("mcr p15, 0, %0, c7, c5, 0" \
|
|
|
+ : : "r" (0));
|
|
|
+
|
|
|
+/* Invalidate I-cache inner shareable */
|
|
|
+#define __flush_icache_all_v7_smp() \
|
|
|
+ asm("mcr p15, 0, %0, c7, c1, 0" \
|
|
|
+ : : "r" (0));
|
|
|
+
|
|
|
+/*
|
|
|
+ * Optimized __flush_icache_all for the common cases. Note that UP ARMv7
|
|
|
+ * will fall through to use __flush_icache_all_generic.
|
|
|
+ */
|
|
|
+#if (defined(CONFIG_CPU_V7) && \
|
|
|
+ (defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K))) || \
|
|
|
+ defined(CONFIG_SMP_ON_UP)
|
|
|
+#define __flush_icache_preferred __cpuc_flush_icache_all
|
|
|
+#elif __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
|
|
|
+#define __flush_icache_preferred __flush_icache_all_v7_smp
|
|
|
+#elif __LINUX_ARM_ARCH__ == 6 && defined(CONFIG_ARM_ERRATA_411920)
|
|
|
+#define __flush_icache_preferred __cpuc_flush_icache_all
|
|
|
+#else
|
|
|
+#define __flush_icache_preferred __flush_icache_all_generic
|
|
|
+#endif
|
|
|
+
|
|
|
+static inline void __flush_icache_all(void)
|
|
|
+{
|
|
|
+ __flush_icache_preferred();
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * Flush caches up to Level of Unification Inner Shareable
|
|
|
+ */
|
|
|
+#define flush_cache_louis() __cpuc_flush_kern_louis()
|
|
|
+
|
|
|
+#define flush_cache_all() __cpuc_flush_kern_all()
|
|
|
+
|
|
|
+static inline void vivt_flush_cache_mm(struct mm_struct *mm)
|
|
|
+{
|
|
|
+ if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm)))
|
|
|
+ __cpuc_flush_user_all();
|
|
|
+}
|
|
|
+
|
|
|
+static inline void
|
|
|
+vivt_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
|
|
|
+{
|
|
|
+ struct mm_struct *mm = vma->vm_mm;
|
|
|
+
|
|
|
+ if (!mm || cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm)))
|
|
|
+ __cpuc_flush_user_range(start & PAGE_MASK, PAGE_ALIGN(end),
|
|
|
+ vma->vm_flags);
|
|
|
+}
|
|
|
+
|
|
|
+static inline void
|
|
|
+vivt_flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn)
|
|
|
+{
|
|
|
+ struct mm_struct *mm = vma->vm_mm;
|
|
|
+
|
|
|
+ if (!mm || cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm))) {
|
|
|
+ unsigned long addr = user_addr & PAGE_MASK;
|
|
|
+ __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#ifndef CONFIG_CPU_CACHE_VIPT
|
|
|
+#define flush_cache_mm(mm) \
|
|
|
+ vivt_flush_cache_mm(mm)
|
|
|
+#define flush_cache_range(vma,start,end) \
|
|
|
+ vivt_flush_cache_range(vma,start,end)
|
|
|
+#define flush_cache_page(vma,addr,pfn) \
|
|
|
+ vivt_flush_cache_page(vma,addr,pfn)
|
|
|
+#else
|
|
|
+extern void flush_cache_mm(struct mm_struct *mm);
|
|
|
+extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
|
|
|
+extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn);
|
|
|
+#endif
|
|
|
+
|
|
|
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
|
|
|
+
|
|
|
+/*
|
|
|
+ * flush_cache_user_range is used when we want to ensure that the
|
|
|
+ * Harvard caches are synchronised for the user space address range.
|
|
|
+ * This is used for the ARM private sys_cacheflush system call.
|
|
|
+ */
|
|
|
+#define flush_cache_user_range(start,end) \
|
|
|
+ __cpuc_coherent_user_range((start) & PAGE_MASK, PAGE_ALIGN(end))
|
|
|
+
|
|
|
+/*
|
|
|
+ * Perform necessary cache operations to ensure that data previously
|
|
|
+ * stored within this range of addresses can be executed by the CPU.
|
|
|
+ */
|
|
|
+#define flush_icache_range(s,e) __cpuc_coherent_kern_range(s,e)
|
|
|
+
|
|
|
+/*
|
|
|
+ * Perform necessary cache operations to ensure that the TLB will
|
|
|
+ * see data written in the specified area.
|
|
|
+ */
|
|
|
+#define clean_dcache_area(start,size) cpu_dcache_clean_area(start, size)
|
|
|
+
|
|
|
+/*
|
|
|
+ * flush_dcache_page is used when the kernel has written to the page
|
|
|
+ * cache page at virtual address page->virtual.
|
|
|
+ *
|
|
|
+ * If this page isn't mapped (ie, page_mapping == NULL), or it might
|
|
|
+ * have userspace mappings, then we _must_ always clean + invalidate
|
|
|
+ * the dcache entries associated with the kernel mapping.
|
|
|
+ *
|
|
|
+ * Otherwise we can defer the operation, and clean the cache when we are
|
|
|
+ * about to change to user space. This is the same method as used on SPARC64.
|
|
|
+ * See update_mmu_cache for the user space part.
|