linux-sh.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Valentin R Sitsikov <valentin.sitdikov@siemens.com>
To: linux-sh@vger.kernel.org
Subject: [PATCH] sh: sh4a: Cache optimization if no cache alias
Date: Wed, 14 Oct 2009 12:51:52 +0000	[thread overview]
Message-ID: <4AD5C968.1030005@siemens.com> (raw)

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) {
-- 
1.6.3.3


             reply	other threads:[~2009-10-14 12:51 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-10-14 12:51 Valentin R Sitsikov [this message]
2009-10-28  8:11 ` [PATCH] sh: sh4a: Cache optimization if no cache alias Valentin R Sitsikov
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=4AD5C968.1030005@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).