MN10300: Create general kernel debugger cache flushing
authorDavid Howells <dhowells@redhat.com>
Fri, 18 Mar 2011 16:54:30 +0000 (16:54 +0000)
committerDavid Howells <dhowells@redhat.com>
Fri, 18 Mar 2011 16:54:30 +0000 (16:54 +0000)
Create general kernel debugger cache flushing for MN10300 and get rid of the
old stuff that gdbstub was using.

Signed-off-by: David Howells <dhowells@redhat.com>
17 files changed:
arch/mn10300/include/asm/debugger.h
arch/mn10300/kernel/Makefile
arch/mn10300/kernel/entry.S
arch/mn10300/kernel/gdb-cache.S [deleted file]
arch/mn10300/kernel/gdb-stub.c
arch/mn10300/mm/Kconfig.cache
arch/mn10300/mm/Makefile
arch/mn10300/mm/cache-dbg-flush-by-reg.S [new file with mode: 0644]
arch/mn10300/mm/cache-dbg-flush-by-tag.S [new file with mode: 0644]
arch/mn10300/mm/cache-dbg-inv-by-reg.S [new file with mode: 0644]
arch/mn10300/mm/cache-dbg-inv-by-tag.S [new file with mode: 0644]
arch/mn10300/mm/cache-dbg-inv.S [new file with mode: 0644]
arch/mn10300/mm/cache-flush-by-tag.S
arch/mn10300/mm/cache-inv-by-reg.S
arch/mn10300/mm/cache-inv-by-tag.S
arch/mn10300/proc-mn103e010/include/proc/cache.h
arch/mn10300/proc-mn2ws0050/include/proc/cache.h

index 4816f0d..4517f83 100644 (file)
 
 #if defined(CONFIG_KERNEL_DEBUGGER)
 
+#ifndef CONFIG_MN10300_DEBUGGER_CACHE_NO_FLUSH
+extern void debugger_local_cache_flushinv(void);
+extern void debugger_local_cache_flushinv_one(u8 *);
+#else
+static inline void debugger_local_cache_flushinv(void) {}
+static inline void debugger_local_cache_flushinv_one(u8 *addr) {}
+#endif
+
 #else /* CONFIG_KERNEL_DEBUGGER */
 
 #endif /* CONFIG_KERNEL_DEBUGGER */
index a06a2e1..48ab401 100644 (file)
@@ -21,10 +21,6 @@ obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-low.o
 obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o
 obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o
 
-ifeq ($(CONFIG_MN10300_CACHE_ENABLED),y)
-obj-$(CONFIG_GDBSTUB) += gdb-cache.o
-endif
-
 obj-$(CONFIG_MN10300_RTC) += rtc.o
 obj-$(CONFIG_PROFILE) += profile.o profile-low.o
 obj-$(CONFIG_MODULES) += module.o
index f00b9ba..8e79a04 100644 (file)
@@ -306,36 +306,7 @@ ENTRY(nmi_handler)
        movbu   d0,(GxICR(GDB_NMI_IPI))
        movhu   (GxICR(GDB_NMI_IPI)),d0
        and     ~EPSW_NMID,epsw         # enable NMI
-#ifdef CONFIG_MN10300_CACHE_ENABLED
-       mov     (gdbstub_nmi_opr_type),d0
-       cmp     GDBSTUB_NMI_CACHE_PURGE,d0
-       bne     4f                      # if not gdb cache purge, jump
-
-       # gdb cache purge nmi ipi
-       add     -20,sp
-       mov     d1,(4,sp)
-       mov     a0,(8,sp)
-       mov     a1,(12,sp)
-       mov     mdr,d0
-       mov     d0,(16,sp)
-       call    gdbstub_local_purge_cache[],0
-       mov     0x1,d0
-       mov     (CPUID),d1
-       asl     d1,d0
-       mov     gdbstub_nmi_cpumask,a0
-       bclr    d0,(a0)
-       mov     (4,sp),d1
-       mov     (8,sp),a0
-       mov     (12,sp),a1
-       mov     (16,sp),d0
-       mov     d0,mdr
-       add     20,sp
-       mov     (sp),d0
-       add     4,sp
-       rti
-4:
-#endif /* CONFIG_MN10300_CACHE_ENABLED */
-       # gdb wait nmi ipi
+
        mov     (sp),d0
        SAVE_ALL
        call    gdbstub_nmi_wait[],0
diff --git a/arch/mn10300/kernel/gdb-cache.S b/arch/mn10300/kernel/gdb-cache.S
deleted file mode 100644 (file)
index 1108bad..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-###############################################################################
-#
-# MN10300 Low-level cache purging routines for gdbstub
-#
-# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
-# Written by David Howells (dhowells@redhat.com)
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU General Public Licence
-# as published by the Free Software Foundation; either version
-# 2 of the Licence, or (at your option) any later version.
-#
-###############################################################################
-#include <linux/sys.h>
-#include <linux/linkage.h>
-#include <asm/smp.h>
-#include <asm/cache.h>
-#include <asm/cpu-regs.h>
-#include <asm/exceptions.h>
-#include <asm/frame.inc>
-#include <asm/serial-regs.h>
-
-       .text
-
-###############################################################################
-#
-# GDB stub cache purge
-#
-###############################################################################
-       .type   gdbstub_purge_cache,@function
-ENTRY(gdbstub_purge_cache)
-       #######################################################################
-       # read the addresses tagged in the cache's tag RAM and attempt to flush
-       # those addresses specifically
-       # - we rely on the hardware to filter out invalid tag entry addresses
-       mov     DCACHE_TAG(0,0),a0              # dcache tag RAM access address
-       mov     DCACHE_PURGE(0,0),a1            # dcache purge request address
-       mov     L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1  # total number of entries
-
-mn10300_dcache_flush_loop:
-       mov     (a0),d0
-       and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
-       or      L1_CACHE_TAG_VALID,d0           # retain valid entries in the
-                                               # cache
-       mov     d0,(a1)                         # conditional purge
-
-mn10300_dcache_flush_skip:
-       add     L1_CACHE_BYTES,a0
-       add     L1_CACHE_BYTES,a1
-       add     -1,d1
-       bne     mn10300_dcache_flush_loop
-
-;;     # unconditionally flush and invalidate the dcache
-;;     mov     DCACHE_PURGE(0,0),a1            # dcache purge request address
-;;     mov     L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1     # total number of
-;;                                                     # entries
-;;
-;; gdbstub_purge_cache__dcache_loop:
-;;     mov     (a1),d0                         # unconditional purge
-;;
-;;     add     L1_CACHE_BYTES,a1
-;;     add     -1,d1
-;;     bne     gdbstub_purge_cache__dcache_loop
-
-       #######################################################################
-       # now invalidate the icache
-       mov     CHCTR,a0
-       movhu   (a0),a1
-
-       mov     epsw,d1
-       and     ~EPSW_IE,epsw
-       nop
-       nop
-
-       # disable the icache
-       and     ~CHCTR_ICEN,d0
-       movhu   d0,(a0)
-
-       # and wait for it to calm down
-       setlb
-       movhu   (a0),d0
-       btst    CHCTR_ICBUSY,d0
-       lne
-
-       # invalidate
-       or      CHCTR_ICINV,d0
-       movhu   d0,(a0)
-
-       # wait for the cache to finish
-       mov     CHCTR,a0
-       setlb
-       movhu   (a0),d0
-       btst    CHCTR_ICBUSY,d0
-       lne
-
-       # and reenable it
-       movhu   a1,(a0)
-       movhu   (a0),d0                 # read back to flush
-                                       # (SIGILLs all over without this)
-
-       mov     d1,epsw
-
-       ret     [],0
-
-       .size   gdbstub_purge_cache,.-gdbstub_purge_cache
index a9c1e91..1e8f24f 100644 (file)
 #include <asm/system.h>
 #include <asm/gdb-stub.h>
 #include <asm/exceptions.h>
-#include <asm/cacheflush.h>
+#include <asm/debugger.h>
 #include <asm/serial-regs.h>
 #include <asm/busctl-regs.h>
 #include <unit/leds.h>
@@ -1665,7 +1665,7 @@ done:
         * NB: We flush both caches, just to be sure...
         */
        if (gdbstub_flush_caches)
-               gdbstub_purge_cache();
+               debugger_local_cache_flushinv();
 
        gdbstub_load_fpu();
        mn10300_set_gdbleds(0);
index c4fd923..bfbe526 100644 (file)
@@ -99,3 +99,49 @@ config MN10300_CACHE_INV_ICACHE
        help
          Set if we need the icache to be invalidated, even if the dcache is in
          write-through mode and doesn't need flushing.
+
+#
+# The kernel debugger gets its own separate cache flushing functions
+#
+config MN10300_DEBUGGER_CACHE_FLUSH_BY_TAG
+       def_bool y if KERNEL_DEBUGGER && \
+                       MN10300_CACHE_WBACK && \
+                       !MN10300_CACHE_SNOOP && \
+                       MN10300_CACHE_MANAGE_BY_TAG
+       help
+         Set if the debugger needs to flush the dcache and invalidate the
+         icache using the cache tag registers to make breakpoints work.
+
+config MN10300_DEBUGGER_CACHE_FLUSH_BY_REG
+       def_bool y if KERNEL_DEBUGGER && \
+                       MN10300_CACHE_WBACK && \
+                       !MN10300_CACHE_SNOOP && \
+                       MN10300_CACHE_MANAGE_BY_REG
+       help
+         Set if the debugger needs to flush the dcache and invalidate the
+         icache using automatic purge registers to make breakpoints work.
+
+config MN10300_DEBUGGER_CACHE_INV_BY_TAG
+       def_bool y if KERNEL_DEBUGGER && \
+                       MN10300_CACHE_WTHRU && \
+                       !MN10300_CACHE_SNOOP && \
+                       MN10300_CACHE_MANAGE_BY_TAG
+       help
+         Set if the debugger needs to invalidate the icache using the cache
+         tag registers to make breakpoints work.
+
+config MN10300_DEBUGGER_CACHE_INV_BY_REG
+       def_bool y if KERNEL_DEBUGGER && \
+                       MN10300_CACHE_WTHRU && \
+                       !MN10300_CACHE_SNOOP && \
+                       MN10300_CACHE_MANAGE_BY_REG
+       help
+         Set if the debugger needs to invalidate the icache using automatic
+         purge registers to make breakpoints work.
+
+config MN10300_DEBUGGER_CACHE_NO_FLUSH
+       def_bool y if KERNEL_DEBUGGER && \
+                       (MN10300_CACHE_DISABLED || MN10300_CACHE_SNOOP)
+       help
+         Set if the debugger does not need to flush the dcache and/or
+         invalidate the icache to make breakpoints work.
index 203fee2..11f3846 100644 (file)
@@ -13,6 +13,15 @@ cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_REG) += cache-inv-by-reg.o
 cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_TAG) += cache-flush-by-tag.o
 cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_REG) += cache-flush-by-reg.o
 
+cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_FLUSH_BY_TAG) += \
+       cache-dbg-flush-by-tag.o cache-dbg-inv-by-tag.o
+cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_FLUSH_BY_REG) += \
+       cache-dbg-flush-by-reg.o
+cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_TAG) += \
+       cache-dbg-inv-by-tag.o cache-dbg-inv.o
+cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_REG) += \
+       cache-dbg-inv-by-reg.o cache-dbg-inv.o
+
 cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o
 
 obj-y := \
diff --git a/arch/mn10300/mm/cache-dbg-flush-by-reg.S b/arch/mn10300/mm/cache-dbg-flush-by-reg.S
new file mode 100644 (file)
index 0000000..665919f
--- /dev/null
@@ -0,0 +1,160 @@
+/* MN10300 CPU cache invalidation routines, using automatic purge registers
+ *
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+       .am33_2
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv(void)
+# Flush the entire data cache back to RAM and invalidate the icache
+#
+###############################################################################
+       ALIGN
+       .globl  debugger_local_cache_flushinv
+        .type  debugger_local_cache_flushinv,@function
+debugger_local_cache_flushinv:
+       #
+       # firstly flush the dcache
+       #
+       movhu   (CHCTR),d0
+       btst    CHCTR_DCEN|CHCTR_ICEN,d0
+       beq     debugger_local_cache_flushinv_end
+
+       mov     DCPGCR,a0
+
+       mov     epsw,d1
+       and     ~EPSW_IE,epsw
+       or      EPSW_NMID,epsw
+       nop
+
+       btst    CHCTR_DCEN,d0
+       beq     debugger_local_cache_flushinv_no_dcache
+
+       # wait for busy bit of area purge
+       setlb
+       mov     (a0),d0
+       btst    DCPGCR_DCPGBSY,d0
+       lne
+
+       # set mask
+       clr     d0
+       mov     d0,(DCPGMR)
+
+       # area purge
+       #
+       # DCPGCR = DCPGCR_DCP
+       #
+       mov     DCPGCR_DCP,d0
+       mov     d0,(a0)
+
+       # wait for busy bit of area purge
+       setlb
+       mov     (a0),d0
+       btst    DCPGCR_DCPGBSY,d0
+       lne
+
+debugger_local_cache_flushinv_no_dcache:
+       #
+       # secondly, invalidate the icache if it is enabled
+       #
+       mov     CHCTR,a0
+       movhu   (a0),d0
+       btst    CHCTR_ICEN,d0
+       beq     debugger_local_cache_flushinv_done
+
+       invalidate_icache 0
+
+debugger_local_cache_flushinv_done:
+       mov     d1,epsw
+
+debugger_local_cache_flushinv_end:
+       ret     [],0
+       .size   debugger_local_cache_flushinv,.-debugger_local_cache_flushinv
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv_one(u8 *addr)
+#
+# Invalidate one particular cacheline if it's in the icache
+#
+###############################################################################
+       ALIGN
+       .globl  debugger_local_cache_flushinv_one
+       .type   debugger_local_cache_flushinv_one,@function
+debugger_local_cache_flushinv_one:
+       movhu   (CHCTR),d1
+       btst    CHCTR_DCEN|CHCTR_ICEN,d1
+       beq     debugger_local_cache_flushinv_one_end
+       btst    CHCTR_DCEN,d1
+       beq     debugger_local_cache_flushinv_one_no_dcache
+
+       # round cacheline addr down
+       and     L1_CACHE_TAG_MASK,d0
+       mov     d0,a1
+       mov     d0,d1
+
+       # determine the dcache purge control reg address
+       mov     DCACHE_PURGE(0,0),a0
+       and     L1_CACHE_TAG_ENTRY,d0
+       add     d0,a0
+
+       # retain valid entries in the cache
+       or      L1_CACHE_TAG_VALID,d1
+
+       # conditionally purge this line in all ways
+       mov     d1,(L1_CACHE_WAYDISP*0,a0)
+
+debugger_local_cache_flushinv_no_dcache:
+       #
+       # now try to flush the icache
+       #
+       mov     CHCTR,a0
+       movhu   (a0),d0
+       btst    CHCTR_ICEN,d0
+       beq     mn10300_local_icache_inv_range_reg_end
+
+       LOCAL_CLI_SAVE(d1)
+
+       mov     ICIVCR,a0
+
+       # wait for the invalidator to quiesce
+       setlb
+       mov     (a0),d0
+       btst    ICIVCR_ICIVBSY,d0
+       lne
+
+       # set the mask
+       mov     L1_CACHE_TAG_MASK,d0
+       mov     d0,(ICIVMR)
+
+       # invalidate the cache line at the given address
+       or      ICIVCR_ICI,a1
+       mov     a1,(a0)
+
+       # wait for the invalidator to quiesce again
+       setlb
+       mov     (a0),d0
+       btst    ICIVCR_ICIVBSY,d0
+       lne
+
+       LOCAL_IRQ_RESTORE(d1)
+
+debugger_local_cache_flushinv_one_end:
+       ret     [],0
+       .size   debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one
diff --git a/arch/mn10300/mm/cache-dbg-flush-by-tag.S b/arch/mn10300/mm/cache-dbg-flush-by-tag.S
new file mode 100644 (file)
index 0000000..bf56930
--- /dev/null
@@ -0,0 +1,114 @@
+/* MN10300 CPU cache invalidation routines, using direct tag flushing
+ *
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+       .am33_2
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv(void)
+#
+# Flush the entire data cache back to RAM and invalidate the icache
+#
+###############################################################################
+       ALIGN
+       .globl  debugger_local_cache_flushinv
+        .type  debugger_local_cache_flushinv,@function
+debugger_local_cache_flushinv:
+       #
+       # firstly flush the dcache
+       #
+       movhu   (CHCTR),d0
+       btst    CHCTR_DCEN|CHCTR_ICEN,d0
+       beq     debugger_local_cache_flushinv_end
+
+       btst    CHCTR_DCEN,d0
+       beq     debugger_local_cache_flushinv_no_dcache
+
+       # read the addresses tagged in the cache's tag RAM and attempt to flush
+       # those addresses specifically
+       # - we rely on the hardware to filter out invalid tag entry addresses
+       mov     DCACHE_TAG(0,0),a0              # dcache tag RAM access address
+       mov     DCACHE_PURGE(0,0),a1            # dcache purge request address
+       mov     L1_CACHE_NWAYS*L1_CACHE_NENTRIES,e0  # total number of entries
+
+mn10300_local_dcache_flush_loop:
+       mov     (a0),d0
+       and     L1_CACHE_TAG_MASK,d0
+       or      L1_CACHE_TAG_VALID,d0           # retain valid entries in the
+                                               # cache
+       mov     d0,(a1)                         # conditional purge
+
+       add     L1_CACHE_BYTES,a0
+       add     L1_CACHE_BYTES,a1
+       add     -1,e0
+       bne     mn10300_local_dcache_flush_loop
+
+debugger_local_cache_flushinv_no_dcache:
+       #
+       # secondly, invalidate the icache if it is enabled
+       #
+       mov     CHCTR,a0
+       movhu   (a0),d0
+       btst    CHCTR_ICEN,d0
+       beq     debugger_local_cache_flushinv_end
+
+       invalidate_icache 1
+
+debugger_local_cache_flushinv_end:
+       ret     [],0
+       .size   debugger_local_cache_flushinv,.-debugger_local_cache_flushinv
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv_one(u8 *addr)
+#
+# Invalidate one particular cacheline if it's in the icache
+#
+###############################################################################
+       ALIGN
+       .globl  debugger_local_cache_flushinv_one
+       .type   debugger_local_cache_flushinv_one,@function
+debugger_local_cache_flushinv_one:
+       movhu   (CHCTR),d1
+       btst    CHCTR_DCEN|CHCTR_ICEN,d1
+       beq     debugger_local_cache_flushinv_one_end
+       btst    CHCTR_DCEN,d1
+       beq     debugger_local_cache_flushinv_one_icache
+
+       # round cacheline addr down
+       and     L1_CACHE_TAG_MASK,d0
+       mov     d0,a1
+
+       # determine the dcache purge control reg address
+       mov     DCACHE_PURGE(0,0),a0
+       and     L1_CACHE_TAG_ENTRY,d0
+       add     d0,a0
+
+       # retain valid entries in the cache
+       or      L1_CACHE_TAG_VALID,a1
+
+       # conditionally purge this line in all ways
+       mov     a1,(L1_CACHE_WAYDISP*0,a0)
+
+       # now go and do the icache
+       bra     debugger_local_cache_flushinv_one_icache
+
+debugger_local_cache_flushinv_one_end:
+       ret     [],0
+       .size   debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one
diff --git a/arch/mn10300/mm/cache-dbg-inv-by-reg.S b/arch/mn10300/mm/cache-dbg-inv-by-reg.S
new file mode 100644 (file)
index 0000000..c4e6252
--- /dev/null
@@ -0,0 +1,69 @@
+/* MN10300 CPU cache invalidation routines, using automatic purge registers
+ *
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+       .am33_2
+
+       .globl  debugger_local_cache_flushinv_one
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv_one(u8 *addr)
+#
+# Invalidate one particular cacheline if it's in the icache
+#
+###############################################################################
+       ALIGN
+       .globl  debugger_local_cache_flushinv_one
+       .type   debugger_local_cache_flushinv_one,@function
+debugger_local_cache_flushinv_one:
+       mov     d0,a1
+
+       mov     CHCTR,a0
+       movhu   (a0),d0
+       btst    CHCTR_ICEN,d0
+       beq     mn10300_local_icache_inv_range_reg_end
+
+       LOCAL_CLI_SAVE(d1)
+
+       mov     ICIVCR,a0
+
+       # wait for the invalidator to quiesce
+       setlb
+       mov     (a0),d0
+       btst    ICIVCR_ICIVBSY,d0
+       lne
+
+       # set the mask
+       mov     ~L1_CACHE_TAG_MASK,d0
+       mov     d0,(ICIVMR)
+
+       # invalidate the cache line at the given address
+       and     ~L1_CACHE_TAG_MASK,a1
+       or      ICIVCR_ICI,a1
+       mov     a1,(a0)
+
+       # wait for the invalidator to quiesce again
+       setlb
+       mov     (a0),d0
+       btst    ICIVCR_ICIVBSY,d0
+       lne
+
+       LOCAL_IRQ_RESTORE(d1)
+
+mn10300_local_icache_inv_range_reg_end:
+       ret     [],0
+       .size   debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one
diff --git a/arch/mn10300/mm/cache-dbg-inv-by-tag.S b/arch/mn10300/mm/cache-dbg-inv-by-tag.S
new file mode 100644 (file)
index 0000000..d8ec821
--- /dev/null
@@ -0,0 +1,120 @@
+/* MN10300 CPU cache invalidation routines, using direct tag flushing
+ *
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+       .am33_2
+
+       .globl  debugger_local_cache_flushinv_one_icache
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv_one(u8 *addr)
+#
+# Invalidate one particular cacheline if it's in the icache
+#
+###############################################################################
+       ALIGN
+       .globl  debugger_local_cache_flushinv_one_icache
+       .type   debugger_local_cache_flushinv_one_icache,@function
+debugger_local_cache_flushinv_one_icache:
+       movm    [d3,a2],(sp)
+
+       mov     CHCTR,a2
+       movhu   (a2),d0
+       btst    CHCTR_ICEN,d0
+       beq     debugger_local_cache_flushinv_one_icache_end
+
+       mov     d0,a1
+       and     L1_CACHE_TAG_MASK,a1
+
+       # read the tags from the tag RAM, and if they indicate a matching valid
+       # cache line then we invalidate that line
+       mov     ICACHE_TAG(0,0),a0
+       mov     a1,d0
+       and     L1_CACHE_TAG_ENTRY,d0
+       add     d0,a0                           # starting icache tag RAM
+                                               # access address
+
+       and     ~(L1_CACHE_DISPARITY-1),a1      # determine comparator base
+       or      L1_CACHE_TAG_VALID,a1
+       mov     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_VALID,d1
+
+       LOCAL_CLI_SAVE(d3)
+
+       # disable the icache
+       movhu   (a2),d0
+       and     ~CHCTR_ICEN,d0
+       movhu   d0,(a2)
+
+       # and wait for it to calm down
+       setlb
+       movhu   (a2),d0
+       btst    CHCTR_ICBUSY,d0
+       lne
+
+       # check all the way tags for this cache entry
+       mov     (a0),d0                         # read the tag in the way 0 slot
+       xor     a1,d0
+       and     d1,d0
+       beq     debugger_local_icache_kill      # jump if matched
+
+       add     L1_CACHE_WAYDISP,a0
+       mov     (a0),d0                         # read the tag in the way 1 slot
+       xor     a1,d0
+       and     d1,d0
+       beq     debugger_local_icache_kill      # jump if matched
+
+       add     L1_CACHE_WAYDISP,a0
+       mov     (a0),d0                         # read the tag in the way 2 slot
+       xor     a1,d0
+       and     d1,d0
+       beq     debugger_local_icache_kill      # jump if matched
+
+       add     L1_CACHE_WAYDISP,a0
+       mov     (a0),d0                         # read the tag in the way 3 slot
+       xor     a1,d0
+       and     d1,d0
+       bne     debugger_local_icache_finish    # jump if not matched
+
+debugger_local_icache_kill:
+       mov     d0,(a0)                         # kill the tag (D0 is 0 at this point)
+
+debugger_local_icache_finish:
+       # wait for the cache to finish what it's doing
+       setlb
+       movhu   (a2),d0
+       btst    CHCTR_ICBUSY,d0
+       lne
+
+       # and reenable it
+       or      CHCTR_ICEN,d0
+       movhu   d0,(a2)
+       movhu   (a2),d0
+
+       # re-enable interrupts
+       LOCAL_IRQ_RESTORE(d3)
+
+debugger_local_cache_flushinv_one_icache_end:
+       ret     [d3,a2],8
+       .size   debugger_local_cache_flushinv_one_icache,.-debugger_local_cache_flushinv_one_icache
+
+#ifdef CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_TAG
+       .globl  debugger_local_cache_flushinv_one
+       .type   debugger_local_cache_flushinv_one,@function
+debugger_local_cache_flushinv_one = debugger_local_cache_flushinv_one_icache
+#endif
diff --git a/arch/mn10300/mm/cache-dbg-inv.S b/arch/mn10300/mm/cache-dbg-inv.S
new file mode 100644 (file)
index 0000000..eba2d6d
--- /dev/null
@@ -0,0 +1,47 @@
+/* MN10300 CPU cache invalidation routines
+ *
+ * Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+       .am33_2
+
+       .globl  debugger_local_cache_flushinv
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv(void)
+#
+# Invalidate the entire icache
+#
+###############################################################################
+       ALIGN
+       .globl  debugger_local_cache_flushinv
+        .type  debugger_local_cache_flushinv,@function
+debugger_local_cache_flushinv:
+       #
+       # we only need to invalidate the icache in this cache mode
+       #
+       mov     CHCTR,a0
+       movhu   (a0),d0
+       btst    CHCTR_ICEN,d0
+       beq     debugger_local_cache_flushinv_end
+
+       invalidate_icache 1
+
+debugger_local_cache_flushinv_end:
+       ret     [],0
+       .size   debugger_local_cache_flushinv,.-debugger_local_cache_flushinv
index 5cd6a27..1ddc068 100644 (file)
@@ -62,7 +62,7 @@ mn10300_local_dcache_flush:
 
 mn10300_local_dcache_flush_loop:
        mov     (a0),d0
-       and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
+       and     L1_CACHE_TAG_MASK,d0
        or      L1_CACHE_TAG_VALID,d0           # retain valid entries in the
                                                # cache
        mov     d0,(a1)                         # conditional purge
@@ -112,11 +112,11 @@ mn10300_local_dcache_flush_range:
 1:
 
        # round start addr down
-       and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
+       and     L1_CACHE_TAG_MASK,d0
        mov     d0,a1
 
        add     L1_CACHE_BYTES,d1                       # round end addr up
-       and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
+       and     L1_CACHE_TAG_MASK,d1
 
        # write a request to flush all instances of an address from the cache
        mov     DCACHE_PURGE(0,0),a0
@@ -215,12 +215,11 @@ mn10300_local_dcache_flush_inv_range:
        bra     mn10300_local_dcache_flush_inv
 1:
 
-       and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0      # round start
-                                                               # addr down
+       and     L1_CACHE_TAG_MASK,d0            # round start addr down
        mov     d0,a1
 
-       add     L1_CACHE_BYTES,d1                       # round end addr up
-       and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
+       add     L1_CACHE_BYTES,d1               # round end addr up
+       and     L1_CACHE_TAG_MASK,d1
 
        # write a request to flush and invalidate all instances of an address
        # from the cache
index d1f363a..a60825b 100644 (file)
@@ -116,9 +116,9 @@ mn10300_local_dcache_inv_range:
        # and if they're not cacheline-aligned, we must flush any bits outside
        # the range that share cachelines with stuff inside the range
 #ifdef CONFIG_MN10300_CACHE_WBACK
-       btst    ~(L1_CACHE_BYTES-1),d0
+       btst    ~L1_CACHE_TAG_MASK,d0
        bne     1f
-       btst    ~(L1_CACHE_BYTES-1),d1
+       btst    ~L1_CACHE_TAG_MASK,d1
        beq     2f
 1:
        bra     mn10300_local_dcache_flush_inv_range
@@ -136,12 +136,11 @@ mn10300_local_dcache_inv_range:
        # writeback mode, in which case we would be in flush and invalidate by
        # now
 #ifndef CONFIG_MN10300_CACHE_WBACK
-       and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0      # round start
-                                                               # addr down
+       and     L1_CACHE_TAG_MASK,d0    # round start addr down
 
        mov     L1_CACHE_BYTES-1,d2
        add     d2,d1
-       and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1      # round end addr up
+       and     L1_CACHE_TAG_MASK,d1    # round end addr up
 #endif /* !CONFIG_MN10300_CACHE_WBACK */
 
        sub     d0,d1,d2                # calculate the total size
index c5c8032..ccedce9 100644 (file)
@@ -124,9 +124,9 @@ mn10300_local_dcache_inv_range:
        # and if they're not cacheline-aligned, we must flush any bits outside
        # the range that share cachelines with stuff inside the range
 #ifdef CONFIG_MN10300_CACHE_WBACK
-       btst    ~(L1_CACHE_BYTES-1),d0
+       btst    ~L1_CACHE_TAG_MASK,d0
        bne     1f
-       btst    ~(L1_CACHE_BYTES-1),d1
+       btst    ~L1_CACHE_TAG_MASK,d1
        beq     2f
 1:
        bra     mn10300_local_dcache_flush_inv_range
@@ -141,11 +141,10 @@ mn10300_local_dcache_inv_range:
        beq     mn10300_local_dcache_inv_range_end
 
 #ifndef CONFIG_MN10300_CACHE_WBACK
-       and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0      # round start
-                                                               # addr down
+       and     L1_CACHE_TAG_MASK,d0            # round start addr down
 
        add     L1_CACHE_BYTES,d1               # round end addr up
-       and     L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
+       and     L1_CACHE_TAG_MASK,d1
 #endif /* !CONFIG_MN10300_CACHE_WBACK */
        mov     d0,a1
 
index c152800..967d144 100644 (file)
@@ -23,6 +23,7 @@
 #define L1_CACHE_TAG_DIRTY     0x00000008      /* data cache tag dirty bit */
 #define L1_CACHE_TAG_ENTRY     0x00000ff0      /* cache tag entry address mask */
 #define L1_CACHE_TAG_ADDRESS   0xfffff000      /* cache tag line address mask */
+#define L1_CACHE_TAG_MASK      +(L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY)
 
 /*
  * specification of the interval between interrupt checking intervals whilst
index cafd7b5..bcb5df2 100644 (file)
@@ -29,6 +29,7 @@
 #define L1_CACHE_TAG_DIRTY     0x00000008      /* data cache tag dirty bit */
 #define L1_CACHE_TAG_ENTRY     0x00000fe0      /* cache tag entry address mask */
 #define L1_CACHE_TAG_ADDRESS   0xfffff000      /* cache tag line address mask */
+#define L1_CACHE_TAG_MASK      +(L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY)
 
 /*
  * specification of the interval between interrupt checking intervals whilst