[U-Boot] [RFC PATCH] ARM: Merge v7 and v8 outer cache operations

Mark Rutland mark.rutland at arm.com
Thu Feb 12 16:56:52 CET 2015


On Sat, Jan 31, 2015 at 03:08:54AM +0000, fenghua at phytium.com.cn wrote:
> From: David Feng <fenghua at phytium.com.cn>
> 
> Armv7 and Armv8 allow outer cache exist, it is outside of the architecture
> defined cache hierarchy and can not be manipulated by architecture defined
> instructions. It's processor specific.
> This patch merge v7_outer_cache_* and v8 l3_cache_*.

This commit message is a little misleading, though it probably makes
sense to have something of this sort ARMv8. Info dump below.

Recently the ARMv8 architecture reference manual was clarified to
mention that any such system caches _must_ respect maintenance by VA,
and are affected by the architected instructions for this. The arm64
Linux port relies on this property.

Set/Way maintenance will not affect system caches. So if you want to
flush/empty the entire cache hierarchy, you will need to rely on a
mechanism specific to the outer cache implementation (rather than one
specific to the processor).

Additionally, the interconnect and cache hierarchies in ARMv8
implementations are becoming more complex, and it is more likely that
dirty lines may migrate arbitrarily between CPUs and the system caches.
Due to this you will need to ensure that CPU caches are disabled and
empty before system cache maintenance is performed (I don't know whether
your current sequences for ARMv7 ensure that).

Thanks,
Mark.

> 
> Signed-off-by: David Feng <fenghua at phytium.com.cn>
> ---
>  arch/arm/cpu/armv7/cache_v7.c                |   22 +++++++++++-----------
>  arch/arm/cpu/armv7/cpu.c                     |    2 +-
>  arch/arm/cpu/armv7/exynos/soc.c              |    2 +-
>  arch/arm/cpu/armv7/mx6/soc.c                 |    4 ++--
>  arch/arm/cpu/armv7/omap3/board.c             |    2 +-
>  arch/arm/cpu/armv7/omap4/hwinit.c            |    4 ++--
>  arch/arm/cpu/armv7/s5pc1xx/cache.c           |    4 ++--
>  arch/arm/cpu/armv7/uniphier/cache_uniphier.c |   14 +++++++-------
>  arch/arm/cpu/armv8/cache_v8.c                |   21 ++++++++++++++++-----
>  arch/arm/cpu/armv8/fsl-lsch3/cpu.c           |    2 +-
>  arch/arm/include/asm/armv7.h                 |    7 -------
>  arch/arm/include/asm/cache.h                 |    7 +++++++
>  arch/arm/include/asm/system.h                |    2 --
>  arch/arm/lib/cache-pl310.c                   |   12 ++++++------
>  14 files changed, 57 insertions(+), 48 deletions(-)
> 
> diff --git a/arch/arm/cpu/armv7/cache_v7.c b/arch/arm/cpu/armv7/cache_v7.c
> index 0f9d837..7d4d5d3 100644
> --- a/arch/arm/cpu/armv7/cache_v7.c
> +++ b/arch/arm/cpu/armv7/cache_v7.c
> @@ -237,7 +237,7 @@ void invalidate_dcache_all(void)
>  {
>         v7_maint_dcache_all(ARMV7_DCACHE_INVAL_ALL);
> 
> -       v7_outer_cache_inval_all();
> +       outer_cache_inval_all();
>  }
> 
>  /*
> @@ -248,7 +248,7 @@ void flush_dcache_all(void)
>  {
>         v7_maint_dcache_all(ARMV7_DCACHE_CLEAN_INVAL_ALL);
> 
> -       v7_outer_cache_flush_all();
> +       outer_cache_flush_all();
>  }
> 
>  /*
> @@ -259,7 +259,7 @@ void invalidate_dcache_range(unsigned long start, unsigned long stop)
>  {
>         v7_dcache_maint_range(start, stop, ARMV7_DCACHE_INVAL_RANGE);
> 
> -       v7_outer_cache_inval_range(start, stop);
> +       outer_cache_inval_range(start, stop);
>  }
> 
>  /*
> @@ -271,12 +271,12 @@ void flush_dcache_range(unsigned long start, unsigned long stop)
>  {
>         v7_dcache_maint_range(start, stop, ARMV7_DCACHE_CLEAN_INVAL_RANGE);
> 
> -       v7_outer_cache_flush_range(start, stop);
> +       outer_cache_flush_range(start, stop);
>  }
> 
>  void arm_init_before_mmu(void)
>  {
> -       v7_outer_cache_enable();
> +       outer_cache_enable();
>         invalidate_dcache_all();
>         v7_inval_tlb();
>  }
> @@ -355,9 +355,9 @@ void invalidate_icache_all(void)
>  #endif
> 
>  /*  Stub implementations for outer cache operations */
> -__weak void v7_outer_cache_enable(void) {}
> -__weak void v7_outer_cache_disable(void) {}
> -__weak void v7_outer_cache_flush_all(void) {}
> -__weak void v7_outer_cache_inval_all(void) {}
> -__weak void v7_outer_cache_flush_range(u32 start, u32 end) {}
> -__weak void v7_outer_cache_inval_range(u32 start, u32 end) {}
> +__weak void outer_cache_enable(void) {}
> +__weak void outer_cache_disable(void) {}
> +__weak void outer_cache_flush_all(void) {}
> +__weak void outer_cache_inval_all(void) {}
> +__weak void outer_cache_flush_range(unsigned long start, unsigned long end) {}
> +__weak void outer_cache_inval_range(unsigned long start, unsigned long end) {}
> diff --git a/arch/arm/cpu/armv7/cpu.c b/arch/arm/cpu/armv7/cpu.c
> index 01cdb7e..07ad549 100644
> --- a/arch/arm/cpu/armv7/cpu.c
> +++ b/arch/arm/cpu/armv7/cpu.c
> @@ -47,7 +47,7 @@ int cleanup_before_linux(void)
>          * dcache_disable() in turn flushes the d-cache and disables MMU
>          */
>         dcache_disable();
> -       v7_outer_cache_disable();
> +       outer_cache_disable();
> 
>         /*
>          * After D-cache is flushed and before it is disabled there may
> diff --git a/arch/arm/cpu/armv7/exynos/soc.c b/arch/arm/cpu/armv7/exynos/soc.c
> index 8c7d7d8..3813c6c 100644
> --- a/arch/arm/cpu/armv7/exynos/soc.c
> +++ b/arch/arm/cpu/armv7/exynos/soc.c
> @@ -50,7 +50,7 @@ static void exynos5_set_l2cache_params(void)
>  /*
>   * Sets L2 cache related parameters before enabling data cache
>   */
> -void v7_outer_cache_enable(void)
> +void outer_cache_enable(void)
>  {
>         if (cpu_is_exynos5())
>                 exynos5_set_l2cache_params();
> diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c
> index 5f5f497..e3f0fdd 100644
> --- a/arch/arm/cpu/armv7/mx6/soc.c
> +++ b/arch/arm/cpu/armv7/mx6/soc.c
> @@ -472,7 +472,7 @@ void imx_setup_hdmi(void)
> 
>  #ifndef CONFIG_SYS_L2CACHE_OFF
>  #define IOMUXC_GPR11_L2CACHE_AS_OCRAM 0x00000002
> -void v7_outer_cache_enable(void)
> +void outer_cache_enable(void)
>  {
>         struct pl310_regs *const pl310 = (struct pl310_regs *)L2_PL310_BASE;
>         unsigned int val;
> @@ -521,7 +521,7 @@ void v7_outer_cache_enable(void)
>         setbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN);
>  }
> 
> -void v7_outer_cache_disable(void)
> +void outer_cache_disable(void)
>  {
>         struct pl310_regs *const pl310 = (struct pl310_regs *)L2_PL310_BASE;
> 
> diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c
> index 90d6ae7..d5e215d 100644
> --- a/arch/arm/cpu/armv7/omap3/board.c
> +++ b/arch/arm/cpu/armv7/omap3/board.c
> @@ -470,7 +470,7 @@ static void omap3_invalidate_l2_cache_secure(void)
>         }
>  }
> 
> -void v7_outer_cache_enable(void)
> +void outer_cache_enable(void)
>  {
>         /* Set L2EN */
>         omap3_update_aux_cr_secure(0x2, 0);
> diff --git a/arch/arm/cpu/armv7/omap4/hwinit.c b/arch/arm/cpu/armv7/omap4/hwinit.c
> index db16548..9841aaa 100644
> --- a/arch/arm/cpu/armv7/omap4/hwinit.c
> +++ b/arch/arm/cpu/armv7/omap4/hwinit.c
> @@ -157,12 +157,12 @@ void init_omap_revision(void)
>  }
> 
>  #ifndef CONFIG_SYS_L2CACHE_OFF
> -void v7_outer_cache_enable(void)
> +void outer_cache_enable(void)
>  {
>         set_pl310_ctrl_reg(1);
>  }
> 
> -void v7_outer_cache_disable(void)
> +void outer_cache_disable(void)
>  {
>         set_pl310_ctrl_reg(0);
>  }
> diff --git a/arch/arm/cpu/armv7/s5pc1xx/cache.c b/arch/arm/cpu/armv7/s5pc1xx/cache.c
> index 51af299..de6f08d 100644
> --- a/arch/arm/cpu/armv7/s5pc1xx/cache.c
> +++ b/arch/arm/cpu/armv7/s5pc1xx/cache.c
> @@ -23,7 +23,7 @@ void disable_caches(void)
>  #endif
> 
>  #ifndef CONFIG_SYS_L2CACHE_OFF
> -void v7_outer_cache_enable(void)
> +void outer_cache_enable(void)
>  {
>         __asm(
>                 "push    {r0, r1, r2, lr}\n\t"
> @@ -34,7 +34,7 @@ void v7_outer_cache_enable(void)
>         );
>  }
> 
> -void v7_outer_cache_disable(void)
> +void outer_cache_disable(void)
>  {
>         __asm(
>                 "push    {r0, r1, r2, lr}\n\t"
> diff --git a/arch/arm/cpu/armv7/uniphier/cache_uniphier.c b/arch/arm/cpu/armv7/uniphier/cache_uniphier.c
> index e47f977..76487cb 100644
> --- a/arch/arm/cpu/armv7/uniphier/cache_uniphier.c
> +++ b/arch/arm/cpu/armv7/uniphier/cache_uniphier.c
> @@ -29,12 +29,12 @@ static void uniphier_cache_maint_all(u32 operation)
>         readl(SSCOPE); /* need a read back to confirm */
>  }
> 
> -void v7_outer_cache_flush_all(void)
> +void outer_cache_flush_all(void)
>  {
>         uniphier_cache_maint_all(SSCOQM_CM_WB_INV);
>  }
> 
> -void v7_outer_cache_inval_all(void)
> +void outer_cache_inval_all(void)
>  {
>         uniphier_cache_maint_all(SSCOQM_CM_INV);
>  }
> @@ -92,17 +92,17 @@ static void uniphier_cache_maint_range(u32 start, u32 end, u32 operation)
>         readl(SSCOPE); /* need a read back to confirm */
>  }
> 
> -void v7_outer_cache_flush_range(u32 start, u32 end)
> +void outer_cache_flush_range(u32 start, u32 end)
>  {
>         uniphier_cache_maint_range(start, end, SSCOQM_CM_WB_INV);
>  }
> 
> -void v7_outer_cache_inval_range(u32 start, u32 end)
> +void outer_cache_inval_range(u32 start, u32 end)
>  {
>         uniphier_cache_maint_range(start, end, SSCOQM_CM_INV);
>  }
> 
> -void v7_outer_cache_enable(void)
> +void outer_cache_enable(void)
>  {
>         u32 tmp;
>         tmp = readl(SSCC);
> @@ -111,7 +111,7 @@ void v7_outer_cache_enable(void)
>  }
>  #endif
> 
> -void v7_outer_cache_disable(void)
> +void outer_cache_disable(void)
>  {
>         u32 tmp;
>         tmp = readl(SSCC);
> @@ -141,7 +141,7 @@ void enable_caches(void)
>          */
> 
>         /* L2 disable */
> -       v7_outer_cache_disable();
> +       outer_cache_disable();
> 
>         /* L1 disable */
>         reg = get_cr();
> diff --git a/arch/arm/cpu/armv8/cache_v8.c b/arch/arm/cpu/armv8/cache_v8.c
> index 9dbcdf2..e4415e8 100644
> --- a/arch/arm/cpu/armv8/cache_v8.c
> +++ b/arch/arm/cpu/armv8/cache_v8.c
> @@ -11,6 +11,16 @@
> 
>  DECLARE_GLOBAL_DATA_PTR;
> 
> +/*
> + * Stubs for outer cache operations
> + */
> +__weak void outer_cache_enable(void) {}
> +__weak void outer_cache_disable(void) {}
> +__weak void outer_cache_flush_all(void) {}
> +__weak void outer_cache_inval_all(void) {}
> +__weak void outer_cache_flush_range(unsigned long start, unsigned long end) {}
> +__weak void outer_cache_inval_range(unsigned long start, unsigned long end) {}
> +
>  #ifndef CONFIG_SYS_DCACHE_OFF
>  void set_pgtable_section(u64 *page_table, u64 index, u64 section,
>                          u64 memory_type)
> @@ -71,10 +81,7 @@ static void mmu_setup(void)
>  void invalidate_dcache_all(void)
>  {
>         __asm_invalidate_dcache_all();
> -}
> -
> -void __weak flush_l3_cache(void)
> -{
> +       outer_cache_inval_all();
>  }
> 
>  /*
> @@ -83,7 +90,7 @@ void __weak flush_l3_cache(void)
>  void flush_dcache_all(void)
>  {
>         __asm_flush_dcache_all();
> -       flush_l3_cache();
> +       outer_cache_flush_all();
>  }
> 
>  /*
> @@ -92,6 +99,7 @@ void flush_dcache_all(void)
>  void invalidate_dcache_range(unsigned long start, unsigned long stop)
>  {
>         __asm_flush_dcache_range(start, stop);
> +       outer_cache_inval_range(start, stop);
>  }
> 
>  /*
> @@ -100,12 +108,14 @@ void invalidate_dcache_range(unsigned long start, unsigned long stop)
>  void flush_dcache_range(unsigned long start, unsigned long stop)
>  {
>         __asm_flush_dcache_range(start, stop);
> +       outer_cache_flush_range(start, stop);
>  }
> 
>  void dcache_enable(void)
>  {
>         /* The data cache is not active unless the mmu is enabled */
>         if (!(get_sctlr() & CR_M)) {
> +               outer_cache_enable();
>                 invalidate_dcache_all();
>                 __asm_invalidate_tlb_all();
>                 mmu_setup();
> @@ -128,6 +138,7 @@ void dcache_disable(void)
> 
>         flush_dcache_all();
>         __asm_invalidate_tlb_all();
> +       outer_cache_disable();
>  }
> 
>  int dcache_status(void)
> diff --git a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
> index 47b947f..1f36f7e 100644
> --- a/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
> +++ b/arch/arm/cpu/armv8/fsl-lsch3/cpu.c
> @@ -275,7 +275,7 @@ static void hnf_pstate_req(u64 *ptr, u64 state)
>         }
>  }
> 
> -void flush_l3_cache(void)
> +void outer_cache_flush_all(void)
>  {
>         hnf_pstate_req((u64 *)HNF0_PSTATE_REQ, HNFPSTAT_SFONLY);
>         hnf_pstate_req((u64 *)HNF1_PSTATE_REQ, HNFPSTAT_SFONLY);
> diff --git a/arch/arm/include/asm/armv7.h b/arch/arm/include/asm/armv7.h
> index a13da23..004434f 100644
> --- a/arch/arm/include/asm/armv7.h
> +++ b/arch/arm/include/asm/armv7.h
> @@ -69,13 +69,6 @@
>  #define CP15DSB        asm volatile ("mcr     p15, 0, %0, c7, c10, 4" : : "r" (0))
>  #define CP15DMB        asm volatile ("mcr     p15, 0, %0, c7, c10, 5" : : "r" (0))
> 
> -void v7_outer_cache_enable(void);
> -void v7_outer_cache_disable(void);
> -void v7_outer_cache_flush_all(void);
> -void v7_outer_cache_inval_all(void);
> -void v7_outer_cache_flush_range(u32 start, u32 end);
> -void v7_outer_cache_inval_range(u32 start, u32 end);
> -
>  #if defined(CONFIG_ARMV7_NONSEC) || defined(CONFIG_ARMV7_VIRT)
> 
>  int armv7_init_nonsec(void);
> diff --git a/arch/arm/include/asm/cache.h b/arch/arm/include/asm/cache.h
> index a836e9f..5a4ac2f 100644
> --- a/arch/arm/include/asm/cache.h
> +++ b/arch/arm/include/asm/cache.h
> @@ -36,6 +36,13 @@ void dram_bank_mmu_setup(int bank);
> 
>  #endif
> 
> +void outer_cache_enable(void);
> +void outer_cache_disable(void);
> +void outer_cache_flush_all(void);
> +void outer_cache_inval_all(void);
> +void outer_cache_flush_range(unsigned long start, unsigned long end);
> +void outer_cache_inval_range(unsigned long start, unsigned long end);
> +
>  /*
>   * The current upper bound for ARM L1 data cache line sizes is 64 bytes.  We
>   * use that value for aligning DMA buffers unless the board config has specified
> diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
> index 89f2294..3b0fd0d 100644
> --- a/arch/arm/include/asm/system.h
> +++ b/arch/arm/include/asm/system.h
> @@ -78,8 +78,6 @@ void gic_send_sgi(unsigned long sgino);
>  void wait_for_wakeup(void);
>  void smp_kick_all_cpus(void);
> 
> -void flush_l3_cache(void);
> -
>  #endif /* __ASSEMBLY__ */
> 
>  #else /* CONFIG_ARM64 */
> diff --git a/arch/arm/lib/cache-pl310.c b/arch/arm/lib/cache-pl310.c
> index 1ad1f8a..4735407 100644
> --- a/arch/arm/lib/cache-pl310.c
> +++ b/arch/arm/lib/cache-pl310.c
> @@ -39,18 +39,18 @@ static void pl310_background_op_all_ways(u32 *op_reg)
>         pl310_cache_sync();
>  }
> 
> -void v7_outer_cache_inval_all(void)
> +void outer_cache_inval_all(void)
>  {
>         pl310_background_op_all_ways(&pl310->pl310_inv_way);
>  }
> 
> -void v7_outer_cache_flush_all(void)
> +void outer_cache_flush_all(void)
>  {
>         pl310_background_op_all_ways(&pl310->pl310_clean_inv_way);
>  }
> 
>  /* Flush(clean invalidate) memory from start to stop-1 */
> -void v7_outer_cache_flush_range(u32 start, u32 stop)
> +void outer_cache_flush_range(unsigned long start, unsigned long stop)
>  {
>         /* PL310 currently supports only 32 bytes cache line */
>         u32 pa, line_size = 32;
> @@ -68,7 +68,7 @@ void v7_outer_cache_flush_range(u32 start, u32 stop)
>  }
> 
>  /* invalidate memory from start to stop-1 */
> -void v7_outer_cache_inval_range(u32 start, u32 stop)
> +void outer_cache_inval_range(unsigned long start, unsigned long stop)
>  {
>         /* PL310 currently supports only 32 bytes cache line */
>         u32 pa, line_size = 32;
> @@ -78,7 +78,7 @@ void v7_outer_cache_inval_range(u32 start, u32 stop)
>          * invalidate the first cache-line
>          */
>         if (start & (line_size - 1)) {
> -               printf("ERROR: %s - start address is not aligned - 0x%08x\n",
> +               printf("ERROR: %s - start address is not aligned - 0x%lx\n",
>                         __func__, start);
>                 /* move to next cache line */
>                 start = (start + line_size - 1) & ~(line_size - 1);
> @@ -89,7 +89,7 @@ void v7_outer_cache_inval_range(u32 start, u32 stop)
>          * invalidate the last cache-line
>          */
>         if (stop & (line_size - 1)) {
> -               printf("ERROR: %s - stop address is not aligned - 0x%08x\n",
> +               printf("ERROR: %s - stop address is not aligned - 0x%lx\n",
>                         __func__, stop);
>                 /* align to the beginning of this cache line */
>                 stop &= ~(line_size - 1);
> --
> 1.7.9.5
> 
> 
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
> 


More information about the U-Boot mailing list