]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
ARM: 6466/1: implement flush_icache_all for the rest of the CPUs
authorMika Westerberg <mika.westerberg@iki.fi>
Thu, 28 Oct 2010 10:27:40 +0000 (11:27 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 28 Oct 2010 12:54:28 +0000 (13:54 +0100)
Commit 81d11955bf0 ("ARM: 6405/1: Handle __flush_icache_all for
CONFIG_SMP_ON_UP") added a new function to struct cpu_cache_fns:
flush_icache_all(). It also implemented this for v6 and v7 but not
for v5 and backwards. Without the function pointer in place, we
will be calling wrong cache functions.

For example with ep93xx we get following:

    Unable to handle kernel paging request at virtual address ee070f38
    pgd = c0004000
    [ee070f38] *pgd=00000000
    Internal error: Oops: 80000005 [#1] PREEMPT
    last sysfs file:
    Modules linked in:
    CPU: 0    Not tainted  (2.6.36+ #1)
    PC is at 0xee070f38
    LR is at __dma_alloc+0x11c/0x2d0
    pc : [<ee070f38>]    lr : [<c0032c8c>]    psr: 60000013
    sp : c581bde0  ip : 00000000  fp : c0472000
    r10: c0472000  r9 : 000000d0  r8 : 00020000
    r7 : 0001ffff  r6 : 00000000  r5 : c0472400  r4 : c5980000
    r3 : c03ab7e0  r2 : 00000000  r1 : c59a0000  r0 : c5980000
    Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
    Control: c000717f  Table: c0004000  DAC: 00000017
    Process swapper (pid: 1, stack limit = 0xc581a270)
    [<c0032c8c>] (__dma_alloc+0x11c/0x2d0)
    [<c0032e5c>] (dma_alloc_writecombine+0x1c/0x24)
    [<c0204148>] (ep93xx_pcm_preallocate_dma_buffer+0x44/0x60)
    [<c02041c0>] (ep93xx_pcm_new+0x5c/0x88)
    [<c01ff188>] (snd_soc_instantiate_cards+0x8a8/0xbc0)
    [<c01ff59c>] (soc_probe+0xfc/0x134)
    [<c01adafc>] (platform_drv_probe+0x18/0x1c)
    [<c01acca4>] (driver_probe_device+0xb0/0x16c)
    [<c01ac284>] (bus_for_each_drv+0x48/0x84)
    [<c01ace90>] (device_attach+0x50/0x68)
    [<c01ac0f8>] (bus_probe_device+0x24/0x44)
    [<c01aad7c>] (device_add+0x2fc/0x44c)
    [<c01adfa8>] (platform_device_add+0x104/0x15c)
    [<c0015eb8>] (simone_init+0x60/0x94)
    [<c0021410>] (do_one_initcall+0xd0/0x1a4)

__dma_alloc() calls (inlined) __dma_alloc_buffer() which ends up
calling dmac_flush_range(). Now since the entries in the
arm920_cache_fns are shifted by one, we jump into address 0xee070f38
which is actually next instruction after the arm920_cache_fns
structure.

So implement flush_icache_all() for the rest of the supported CPUs
using a generic 'invalidate I cache' instruction.

Signed-off-by: Mika Westerberg <mika.westerberg@iki.fi>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
18 files changed:
arch/arm/mm/cache-fa.S
arch/arm/mm/cache-v3.S
arch/arm/mm/cache-v4.S
arch/arm/mm/cache-v4wb.S
arch/arm/mm/cache-v4wt.S
arch/arm/mm/proc-arm1020.S
arch/arm/mm/proc-arm1020e.S
arch/arm/mm/proc-arm1022.S
arch/arm/mm/proc-arm1026.S
arch/arm/mm/proc-arm920.S
arch/arm/mm/proc-arm922.S
arch/arm/mm/proc-arm925.S
arch/arm/mm/proc-arm926.S
arch/arm/mm/proc-arm940.S
arch/arm/mm/proc-arm946.S
arch/arm/mm/proc-feroceon.S
arch/arm/mm/proc-xsc3.S
arch/arm/mm/proc-xscale.S

index 7148e53e6078fff5b32a5d8d87a5ce1658095ae3..1fa6f71470de52458208eecc20223921b632146d 100644 (file)
 /* FIXME: put optimal value here. Current one is just estimation */
 #define CACHE_DLIMIT   (CACHE_DSIZE * 2)
 
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(fa_flush_icache_all)
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mov     pc, lr
+ENDPROC(fa_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  *
@@ -233,6 +244,7 @@ ENDPROC(fa_dma_unmap_area)
 
        .type   fa_cache_fns, #object
 ENTRY(fa_cache_fns)
+       .long   fa_flush_icache_all
        .long   fa_flush_kern_cache_all
        .long   fa_flush_user_cache_all
        .long   fa_flush_user_cache_range
index c2ff3c599feed47eb77d92190d29958fb95e8315..2e2bc406a18d69f93de13600732bb3d6fa329135 100644 (file)
 #include <asm/page.h>
 #include "proc-macros.S"
 
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(v3_flush_icache_all)
+       mov     pc, lr
+ENDPROC(v3_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  *
@@ -122,6 +131,7 @@ ENDPROC(v3_dma_map_area)
 
        .type   v3_cache_fns, #object
 ENTRY(v3_cache_fns)
+       .long   v3_flush_icache_all
        .long   v3_flush_kern_cache_all
        .long   v3_flush_user_cache_all
        .long   v3_flush_user_cache_range
index 4810f7e3e8139ea8bed712cc4b9cea792660d99a..a8fefb523f194ab97e950af7bf1d9e906c666013 100644 (file)
 #include <asm/page.h>
 #include "proc-macros.S"
 
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(v4_flush_icache_all)
+       mov     pc, lr
+ENDPROC(v4_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  *
@@ -134,6 +143,7 @@ ENDPROC(v4_dma_map_area)
 
        .type   v4_cache_fns, #object
 ENTRY(v4_cache_fns)
+       .long   v4_flush_icache_all
        .long   v4_flush_kern_cache_all
        .long   v4_flush_user_cache_all
        .long   v4_flush_user_cache_range
index df8368afa102771bb99c19045abac26abb42e656..d3644db467b74af63a701a9e34d1335a0905e06d 100644 (file)
@@ -50,6 +50,17 @@ flush_base:
        .long   FLUSH_BASE
        .text
 
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(v4wb_flush_icache_all)
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mov     pc, lr
+ENDPROC(v4wb_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  *
@@ -244,6 +255,7 @@ ENDPROC(v4wb_dma_unmap_area)
 
        .type   v4wb_cache_fns, #object
 ENTRY(v4wb_cache_fns)
+       .long   v4wb_flush_icache_all
        .long   v4wb_flush_kern_cache_all
        .long   v4wb_flush_user_cache_all
        .long   v4wb_flush_user_cache_range
index 45c70312f43bb1db9f49ae9591283d243b072ae8..49c2b66cf3dd6913b7fcdb42bcd877b8a8fa833a 100644 (file)
  */
 #define CACHE_DLIMIT   16384
 
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(v4wt_flush_icache_all)
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mov     pc, lr
+ENDPROC(v4wt_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  *
@@ -188,6 +199,7 @@ ENDPROC(v4wt_dma_map_area)
 
        .type   v4wt_cache_fns, #object
 ENTRY(v4wt_cache_fns)
+       .long   v4wt_flush_icache_all
        .long   v4wt_flush_kern_cache_all
        .long   v4wt_flush_user_cache_all
        .long   v4wt_flush_user_cache_range
index a6f5f8475b96c6400a3aa26e03875a329ff771b1..bcf748d9f4e253bc34ec9a885f5d0fe4f58b16c7 100644 (file)
@@ -119,6 +119,20 @@ ENTRY(cpu_arm1020_do_idle)
 /* ================================= CACHE ================================ */
 
        .align  5
+
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(arm1020_flush_icache_all)
+#ifndef CONFIG_CPU_ICACHE_DISABLE
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+#endif
+       mov     pc, lr
+ENDPROC(arm1020_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  *
@@ -351,6 +365,7 @@ ENTRY(arm1020_dma_unmap_area)
 ENDPROC(arm1020_dma_unmap_area)
 
 ENTRY(arm1020_cache_fns)
+       .long   arm1020_flush_icache_all
        .long   arm1020_flush_kern_cache_all
        .long   arm1020_flush_user_cache_all
        .long   arm1020_flush_user_cache_range
index afc06b9c31332bf7dc25222855d61dcb391bc42d..ab7ec26657eaf024a7f69bf8c2603f47d88c1304 100644 (file)
@@ -119,6 +119,20 @@ ENTRY(cpu_arm1020e_do_idle)
 /* ================================= CACHE ================================ */
 
        .align  5
+
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(arm1020e_flush_icache_all)
+#ifndef CONFIG_CPU_ICACHE_DISABLE
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+#endif
+       mov     pc, lr
+ENDPROC(arm1020e_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  *
@@ -337,6 +351,7 @@ ENTRY(arm1020e_dma_unmap_area)
 ENDPROC(arm1020e_dma_unmap_area)
 
 ENTRY(arm1020e_cache_fns)
+       .long   arm1020e_flush_icache_all
        .long   arm1020e_flush_kern_cache_all
        .long   arm1020e_flush_user_cache_all
        .long   arm1020e_flush_user_cache_range
index 8915e0ba3fe53e1225bbb422b19f22c8a0d4c085..831c5e54e22f0e7fe795bedc4d619dae26ed9c39 100644 (file)
@@ -108,6 +108,20 @@ ENTRY(cpu_arm1022_do_idle)
 /* ================================= CACHE ================================ */
 
        .align  5
+
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(arm1022_flush_icache_all)
+#ifndef CONFIG_CPU_ICACHE_DISABLE
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+#endif
+       mov     pc, lr
+ENDPROC(arm1022_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  *
@@ -326,6 +340,7 @@ ENTRY(arm1022_dma_unmap_area)
 ENDPROC(arm1022_dma_unmap_area)
 
 ENTRY(arm1022_cache_fns)
+       .long   arm1022_flush_icache_all
        .long   arm1022_flush_kern_cache_all
        .long   arm1022_flush_user_cache_all
        .long   arm1022_flush_user_cache_range
index ff446c5d476f029aefb8a57da2fd4a4987e890e3..e3f7e9a166bfc6668574dc2a7518f56cee9476a6 100644 (file)
@@ -108,6 +108,20 @@ ENTRY(cpu_arm1026_do_idle)
 /* ================================= CACHE ================================ */
 
        .align  5
+
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(arm1026_flush_icache_all)
+#ifndef CONFIG_CPU_ICACHE_DISABLE
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+#endif
+       mov     pc, lr
+ENDPROC(arm1026_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  *
@@ -320,6 +334,7 @@ ENTRY(arm1026_dma_unmap_area)
 ENDPROC(arm1026_dma_unmap_area)
 
 ENTRY(arm1026_cache_fns)
+       .long   arm1026_flush_icache_all
        .long   arm1026_flush_kern_cache_all
        .long   arm1026_flush_user_cache_all
        .long   arm1026_flush_user_cache_range
index fecf570939f39553dcc4959a6a963a06827aadc2..6109f278a9045f4429bcd31ca9a4f8a092d3c66f 100644 (file)
@@ -109,6 +109,17 @@ ENTRY(cpu_arm920_do_idle)
 
 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(arm920_flush_icache_all)
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mov     pc, lr
+ENDPROC(arm920_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  *
@@ -305,6 +316,7 @@ ENTRY(arm920_dma_unmap_area)
 ENDPROC(arm920_dma_unmap_area)
 
 ENTRY(arm920_cache_fns)
+       .long   arm920_flush_icache_all
        .long   arm920_flush_kern_cache_all
        .long   arm920_flush_user_cache_all
        .long   arm920_flush_user_cache_range
index e3cbf87c9480c97e8b65086638ef6b6b72e3217c..bb2f0f46a5e6cb28f8789da35ecb7d2f0852a4b1 100644 (file)
@@ -111,6 +111,17 @@ ENTRY(cpu_arm922_do_idle)
 
 #ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
 
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(arm922_flush_icache_all)
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mov     pc, lr
+ENDPROC(arm922_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  *
@@ -307,6 +318,7 @@ ENTRY(arm922_dma_unmap_area)
 ENDPROC(arm922_dma_unmap_area)
 
 ENTRY(arm922_cache_fns)
+       .long   arm922_flush_icache_all
        .long   arm922_flush_kern_cache_all
        .long   arm922_flush_user_cache_all
        .long   arm922_flush_user_cache_range
index 572424c867b5e8560401e7cf40d895a77f140fbe..c13e01accfe2e4d38dc5e7e22d6aba32bfd0ce0a 100644 (file)
@@ -144,6 +144,17 @@ ENTRY(cpu_arm925_do_idle)
        mcr     p15, 0, r1, c1, c0, 0           @ Restore ICache enable
        mov     pc, lr
 
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(arm925_flush_icache_all)
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mov     pc, lr
+ENDPROC(arm925_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  *
@@ -362,6 +373,7 @@ ENTRY(arm925_dma_unmap_area)
 ENDPROC(arm925_dma_unmap_area)
 
 ENTRY(arm925_cache_fns)
+       .long   arm925_flush_icache_all
        .long   arm925_flush_kern_cache_all
        .long   arm925_flush_user_cache_all
        .long   arm925_flush_user_cache_range
index 63d168b4ebe671316ff3add437c26da418dd596f..42eb4315740b1488e26192b5ff0cb07747312df5 100644 (file)
@@ -110,6 +110,17 @@ ENTRY(cpu_arm926_do_idle)
        msr     cpsr_c, r3                      @ Restore FIQ state
        mov     pc, lr
 
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(arm926_flush_icache_all)
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mov     pc, lr
+ENDPROC(arm926_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  *
@@ -325,6 +336,7 @@ ENTRY(arm926_dma_unmap_area)
 ENDPROC(arm926_dma_unmap_area)
 
 ENTRY(arm926_cache_fns)
+       .long   arm926_flush_icache_all
        .long   arm926_flush_kern_cache_all
        .long   arm926_flush_user_cache_all
        .long   arm926_flush_user_cache_range
index f6a62822418e3573d8af5629f7f088f7ce24652d..7b11cdb9935ff4e8d635ee95a6ea09d225cdc10e 100644 (file)
@@ -67,6 +67,17 @@ ENTRY(cpu_arm940_do_idle)
        mcr     p15, 0, r0, c7, c0, 4           @ Wait for interrupt
        mov     pc, lr
 
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(arm940_flush_icache_all)
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mov     pc, lr
+ENDPROC(arm940_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  */
@@ -254,6 +265,7 @@ ENTRY(arm940_dma_unmap_area)
 ENDPROC(arm940_dma_unmap_area)
 
 ENTRY(arm940_cache_fns)
+       .long   arm940_flush_icache_all
        .long   arm940_flush_kern_cache_all
        .long   arm940_flush_user_cache_all
        .long   arm940_flush_user_cache_range
index ea2e7f2eb95b1e6f86f4770c2e1ebca292f11f81..1a5bbf0803427b159096bfc093a5db07dc510731 100644 (file)
@@ -74,6 +74,17 @@ ENTRY(cpu_arm946_do_idle)
        mcr     p15, 0, r0, c7, c0, 4           @ Wait for interrupt
        mov     pc, lr
 
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(arm946_flush_icache_all)
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mov     pc, lr
+ENDPROC(arm946_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  */
@@ -296,6 +307,7 @@ ENTRY(arm946_dma_unmap_area)
 ENDPROC(arm946_dma_unmap_area)
 
 ENTRY(arm946_cache_fns)
+       .long   arm946_flush_icache_all
        .long   arm946_flush_kern_cache_all
        .long   arm946_flush_user_cache_all
        .long   arm946_flush_user_cache_range
index 578da69200cfc2694a2359c18ead388dfd4a7353..b4597edbff97fe794da687178c5f23cf27e37e47 100644 (file)
@@ -123,6 +123,17 @@ ENTRY(cpu_feroceon_do_idle)
        mcr     p15, 0, r0, c7, c0, 4           @ Wait for interrupt
        mov     pc, lr
 
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(feroceon_flush_icache_all)
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mov     pc, lr
+ENDPROC(feroceon_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  *
@@ -401,6 +412,7 @@ ENTRY(feroceon_dma_unmap_area)
 ENDPROC(feroceon_dma_unmap_area)
 
 ENTRY(feroceon_cache_fns)
+       .long   feroceon_flush_icache_all
        .long   feroceon_flush_kern_cache_all
        .long   feroceon_flush_user_cache_all
        .long   feroceon_flush_user_cache_range
@@ -412,6 +424,7 @@ ENTRY(feroceon_cache_fns)
        .long   feroceon_dma_flush_range
 
 ENTRY(feroceon_range_cache_fns)
+       .long   feroceon_flush_icache_all
        .long   feroceon_flush_kern_cache_all
        .long   feroceon_flush_user_cache_all
        .long   feroceon_flush_user_cache_range
index cad07e403044f3a2ba3b62b0812d4b37c6b4ff9f..ec26355cb7c25b8d0e574e74740569213818cd6a 100644 (file)
@@ -140,6 +140,17 @@ ENTRY(cpu_xsc3_do_idle)
 
 /* ================================= CACHE ================================ */
 
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(xsc3_flush_icache_all)
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mov     pc, lr
+ENDPROC(xsc3_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  *
@@ -325,6 +336,7 @@ ENTRY(xsc3_dma_unmap_area)
 ENDPROC(xsc3_dma_unmap_area)
 
 ENTRY(xsc3_cache_fns)
+       .long   xsc3_flush_icache_all
        .long   xsc3_flush_kern_cache_all
        .long   xsc3_flush_user_cache_all
        .long   xsc3_flush_user_cache_range
index cb245edb2c2bc2e25aa355473f8ceab9dc35d493..523408c0bb38aafb69903dbd85f8584d5eef1a3a 100644 (file)
@@ -180,6 +180,17 @@ ENTRY(cpu_xscale_do_idle)
 
 /* ================================= CACHE ================================ */
 
+/*
+ *     flush_icache_all()
+ *
+ *     Unconditionally clean and invalidate the entire icache.
+ */
+ENTRY(xscale_flush_icache_all)
+       mov     r0, #0
+       mcr     p15, 0, r0, c7, c5, 0           @ invalidate I cache
+       mov     pc, lr
+ENDPROC(xscale_flush_icache_all)
+
 /*
  *     flush_user_cache_all()
  *
@@ -397,6 +408,7 @@ ENTRY(xscale_dma_unmap_area)
 ENDPROC(xscale_dma_unmap_area)
 
 ENTRY(xscale_cache_fns)
+       .long   xscale_flush_icache_all
        .long   xscale_flush_kern_cache_all
        .long   xscale_flush_user_cache_all
        .long   xscale_flush_user_cache_range