From: Valentin R Sitsikov <valentin.sitdikov@siemens.com>
To: linux-sh@vger.kernel.org
Subject: Re: [PATCH] sh: sh4a: Cache optimization if no cache alias
Date: Wed, 28 Oct 2009 08:11:11 +0000 [thread overview]
Message-ID: <4AE7FC9F.5070001@siemens.com> (raw)
In-Reply-To: <4AD5C968.1030005@siemens.com>
Hello Paul!
If you don`t mind could you please comment on this patch?
Best regards,
Valentin
Valentin R Sitsikov wrote:
> Signed-off-by: Valentin Sitdikov <valentin.sitdikov@siemens.com>
> ---
> arch/sh/include/asm/system_32.h | 2 +-
> arch/sh/mm/Makefile | 1 +
> arch/sh/mm/cache-sh4a.c | 169
> +++++++++++++++++++++++++++++++++++++++
> arch/sh/mm/cache.c | 6 ++
> 4 files changed, 177 insertions(+), 1 deletions(-)
> create mode 100644 arch/sh/mm/cache-sh4a.c
>
> diff --git a/arch/sh/include/asm/system_32.h
> b/arch/sh/include/asm/system_32.h
> index 607d413..7fe8011 100644
> --- a/arch/sh/include/asm/system_32.h
> +++ b/arch/sh/include/asm/system_32.h
> @@ -72,7 +72,7 @@ do { \
> #define __ocbp(addr) __asm__ __volatile__ ( "ocbp @%0\n\t" : : "r"
> (addr))
> #define __ocbi(addr) __asm__ __volatile__ ( "ocbi @%0\n\t" : : "r"
> (addr))
> #define __ocbwb(addr) __asm__ __volatile__ ( "ocbwb @%0\n\t" : : "r"
> (addr))
> -
> +#define __icbi(addr) __asm__ __volatile__ ( "icbi @%0\n\t" : : "r"
> (addr))
> struct task_struct *__switch_to(struct task_struct *prev,
> struct task_struct *next);
>
> diff --git a/arch/sh/mm/Makefile b/arch/sh/mm/Makefile
> index b70024d..3a2de1d 100644
> --- a/arch/sh/mm/Makefile
> +++ b/arch/sh/mm/Makefile
> @@ -10,6 +10,7 @@ cacheops-$(CONFIG_CPU_SH3) := cache-sh3.o
> cacheops-$(CONFIG_CPU_SH4) := cache-sh4.o flush-sh4.o
> cacheops-$(CONFIG_CPU_SH5) := cache-sh5.o flush-sh4.o
> cacheops-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o
> +cacheops-$(CONFIG_CPU_SH4A) += cache-sh4a.o
>
> obj-y += $(cacheops-y)
>
> diff --git a/arch/sh/mm/cache-sh4a.c b/arch/sh/mm/cache-sh4a.c
> new file mode 100644
> index 0000000..147f0e3
> --- /dev/null
> +++ b/arch/sh/mm/cache-sh4a.c
> @@ -0,0 +1,169 @@
> +/*
> + * arch/sh/mm/cache-sh4a.c
> + *
> + * Copyright (C) 1999, 2000, 2002 Niibe Yutaka
> + * Copyright (C) 2001 - 2009 Paul Mundt
> + * Copyright (C) 2003 Richard Curnow
> + * Copyright (c) 2007 STMicroelectronics (R&D) Ltd.
> + * Copyright (c) 2009 Valentin Sitdikov
> + *
> + * This file is subject to the terms and conditions of the GNU General
> Public
> + * License. See the file "COPYING" in the main directory of this archive
> + * for more details.
> + */
> +#include <linux/init.h>
> +#include <linux/mm.h>
> +#include <linux/io.h>
> +#include <linux/mutex.h>
> +#include <linux/fs.h>
> +#include <linux/highmem.h>
> +#include <linux/pagemap.h>
> +#include <asm/pgtable.h>
> +#include <asm/mmu_context.h>
> +#include <asm/cacheflush.h>
> +
> +/*
> + * The maximum number of pages we support up to when doing ranged dcache
> + * flushing. Anything exceeding this will simply flush the dcache in its
> + * entirety.
> + */
> +#define MAX_ICACHE_PAGES 32
> +
> +
> +static void sh4a_invalidate_icache(void *start, int size)
> +{
> + reg_size_t aligned_start, v, cnt, end;
> +
> + aligned_start = register_align(start);
> + v = aligned_start & ~(L1_CACHE_BYTES-1);
> + end = (aligned_start + size + L1_CACHE_BYTES-1)
> + & ~(L1_CACHE_BYTES-1);
> + cnt = (end - v) / L1_CACHE_BYTES;
> +
> + while (cnt >= 8) {
> + __icbi(v); v += L1_CACHE_BYTES;
> + __icbi(v); v += L1_CACHE_BYTES;
> + __icbi(v); v += L1_CACHE_BYTES;
> + __icbi(v); v += L1_CACHE_BYTES;
> + __icbi(v); v += L1_CACHE_BYTES;
> + __icbi(v); v += L1_CACHE_BYTES;
> + __icbi(v); v += L1_CACHE_BYTES;
> + __icbi(v); v += L1_CACHE_BYTES;
> + cnt -= 8;
> + }
> +
> + while (cnt) {
> + __icbi(v); v += L1_CACHE_BYTES;
> + cnt--;
> + }
> +}
> +
> +/*
> + * Write back the dirty D-caches and invalidate them.
> + *
> + * START: Virtual Address (U0, P1, or P3)
> + * SIZE: Size of the region.
> + */
> +static void sh4a_purge_dcache(void *start, int size)
> +{
> + reg_size_t aligned_start, v, cnt, end;
> +
> + aligned_start = register_align(start);
> + v = aligned_start & ~(L1_CACHE_BYTES-1);
> + end = (aligned_start + size + L1_CACHE_BYTES-1)
> + & ~(L1_CACHE_BYTES-1);
> + cnt = (end - v) / L1_CACHE_BYTES;
> +
> + while (cnt >= 8) {
> + __ocbp(v); v += L1_CACHE_BYTES;
> + __ocbp(v); v += L1_CACHE_BYTES;
> + __ocbp(v); v += L1_CACHE_BYTES;
> + __ocbp(v); v += L1_CACHE_BYTES;
> + __ocbp(v); v += L1_CACHE_BYTES;
> + __ocbp(v); v += L1_CACHE_BYTES;
> + __ocbp(v); v += L1_CACHE_BYTES;
> + __ocbp(v); v += L1_CACHE_BYTES;
> + cnt -= 8;
> + }
> + while (cnt) {
> + __ocbp(v); v += L1_CACHE_BYTES;
> + cnt--;
> + }
> +}
> +
> +/*
> + * Write back the range of D-cache, and purge the I-cache.
> + *
> + * Called from kernel/module.c:sys_init_module and routine for a.out
> format,
> + * signal handler code and kprobes code
> + */
> +static void __uses_jump_to_uncached sh4a_flush_icache_range(void *args)
> +{
> + struct flusher_data *data = args;
> + unsigned long start, end;
> + unsigned long flags, v;
> +
> + start = data->addr1;
> + end = data->addr2;
> +
> + /* If there are too many pages then just blow away the caches */
> + if (((end - start) >> PAGE_SHIFT) >= MAX_ICACHE_PAGES) {
> + local_flush_cache_all(NULL);
> + return;
> + }
> +
> + /*
> + * Selectively flush d-cache then invalidate the i-cache.
> + * This is inefficient, so only use this for small ranges.
> + */
> + start &= ~(L1_CACHE_BYTES-1);
> + end += L1_CACHE_BYTES-1;
> + end &= ~(L1_CACHE_BYTES-1);
> +
> + local_irq_save(flags);
> + jump_to_uncached();
> +
> + for (v = start; v < end; v += L1_CACHE_BYTES) {
> + __ocbwb(v);
> + __icbi(v);
> + }
> +
> + back_to_cached();
> + local_irq_restore(flags);
> +}
> +
> +/*
> + * Write back & invalidate the D-cache of the page.
> + * (To avoid "alias" issues)
> + */
> +static void sh4a_flush_dcache_page(void *arg)
> +{
> + struct page *page = arg;
> + struct address_space *mapping = page_mapping(page);
> +
> +#ifndef CONFIG_SMP
> + if (mapping && !mapping_mapped(mapping))
> + set_bit(PG_dcache_dirty, &page->flags);
> + else
> +#endif
> + {
> + sh4a_purge_dcache(page_address(page), PAGE_SIZE);
> + sh4a_invalidate_icache(page_address(page), PAGE_SIZE);
> + }
> +}
> +
> +
> +/*
> + * SH-4 has virtually indexed and physically tagged cache.
> + */
> +void __init sh4a_cache_init(void)
> +{
> + printk("SH4A cache optimization\n");
> +
> + local_flush_icache_range = sh4a_flush_icache_range;
> + /* Not sure about alias cases - not checked yet */
> + if (boot_cpu_data.dcache.n_aliases = 0) {
> + local_flush_dcache_page = sh4a_flush_dcache_page;
> + }
> +
> +}
> diff --git a/arch/sh/mm/cache.c b/arch/sh/mm/cache.c
> index 4aa9260..72904d9 100644
> --- a/arch/sh/mm/cache.c
> +++ b/arch/sh/mm/cache.c
> @@ -310,6 +310,12 @@ void __init cpu_cache_init(void)
> extern void __weak sh4_cache_init(void);
>
> sh4_cache_init();
> +
> + if(boot_cpu_data.family = CPU_FAMILY_SH4A) {
> + extern void __weak sh4a_cache_init(void);
> +
> + sh4a_cache_init();
> + }
> }
>
> if (boot_cpu_data.family = CPU_FAMILY_SH5) {
next prev parent reply other threads:[~2009-10-28 8:11 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-10-14 12:51 [PATCH] sh: sh4a: Cache optimization if no cache alias Valentin R Sitsikov
2009-10-28 8:11 ` Valentin R Sitsikov [this message]
2009-10-28 9:28 ` Paul Mundt
2009-11-05 23:22 ` Matt Fleming
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4AE7FC9F.5070001@siemens.com \
--to=valentin.sitdikov@siemens.com \
--cc=linux-sh@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).