summaryrefslogtreecommitdiff
path: root/arch/mn10300/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mn10300/mm')
-rw-r--r--arch/mn10300/mm/Kconfig.cache46
-rw-r--r--arch/mn10300/mm/Makefile9
-rw-r--r--arch/mn10300/mm/cache-dbg-flush-by-reg.S160
-rw-r--r--arch/mn10300/mm/cache-dbg-flush-by-tag.S114
-rw-r--r--arch/mn10300/mm/cache-dbg-inv-by-reg.S69
-rw-r--r--arch/mn10300/mm/cache-dbg-inv-by-tag.S120
-rw-r--r--arch/mn10300/mm/cache-dbg-inv.S47
-rw-r--r--arch/mn10300/mm/cache-flush-by-tag.S13
-rw-r--r--arch/mn10300/mm/cache-inv-by-reg.S22
-rw-r--r--arch/mn10300/mm/cache-inv-by-tag.S86
-rw-r--r--arch/mn10300/mm/cache.inc133
-rw-r--r--arch/mn10300/mm/fault.c9
12 files changed, 723 insertions, 105 deletions
diff --git a/arch/mn10300/mm/Kconfig.cache b/arch/mn10300/mm/Kconfig.cache
index c4fd923a55a0..bfbe52691f2c 100644
--- a/arch/mn10300/mm/Kconfig.cache
+++ b/arch/mn10300/mm/Kconfig.cache
@@ -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.
diff --git a/arch/mn10300/mm/Makefile b/arch/mn10300/mm/Makefile
index 203fee23f7d7..11f38466ac28 100644
--- a/arch/mn10300/mm/Makefile
+++ b/arch/mn10300/mm/Makefile
@@ -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
index 000000000000..665919f2ab62
--- /dev/null
+++ b/arch/mn10300/mm/cache-dbg-flush-by-reg.S
@@ -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
index 000000000000..bf56930e6e70
--- /dev/null
+++ b/arch/mn10300/mm/cache-dbg-flush-by-tag.S
@@ -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
index 000000000000..c4e6252941b1
--- /dev/null
+++ b/arch/mn10300/mm/cache-dbg-inv-by-reg.S
@@ -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
index 000000000000..d8ec821e5f88
--- /dev/null
+++ b/arch/mn10300/mm/cache-dbg-inv-by-tag.S
@@ -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
index 000000000000..eba2d6dca066
--- /dev/null
+++ b/arch/mn10300/mm/cache-dbg-inv.S
@@ -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
diff --git a/arch/mn10300/mm/cache-flush-by-tag.S b/arch/mn10300/mm/cache-flush-by-tag.S
index 5cd6a27dd63e..1ddc06849242 100644
--- a/arch/mn10300/mm/cache-flush-by-tag.S
+++ b/arch/mn10300/mm/cache-flush-by-tag.S
@@ -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
diff --git a/arch/mn10300/mm/cache-inv-by-reg.S b/arch/mn10300/mm/cache-inv-by-reg.S
index c8950861ed77..a60825b91e77 100644
--- a/arch/mn10300/mm/cache-inv-by-reg.S
+++ b/arch/mn10300/mm/cache-inv-by-reg.S
@@ -15,6 +15,7 @@
#include <asm/cache.h>
#include <asm/irqflags.h>
#include <asm/cacheflush.h>
+#include "cache.inc"
#define mn10300_local_dcache_inv_range_intr_interval \
+((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
@@ -62,10 +63,7 @@ mn10300_local_icache_inv:
btst CHCTR_ICEN,d0
beq mn10300_local_icache_inv_end
- # invalidate
- or CHCTR_ICINV,d0
- movhu d0,(a0)
- movhu (a0),d0
+ invalidate_icache 1
mn10300_local_icache_inv_end:
ret [],0
@@ -87,11 +85,8 @@ mn10300_local_dcache_inv:
btst CHCTR_DCEN,d0
beq mn10300_local_dcache_inv_end
- # invalidate
- or CHCTR_DCINV,d0
- movhu d0,(a0)
- movhu (a0),d0
-
+ invalidate_dcache 1
+
mn10300_local_dcache_inv_end:
ret [],0
.size mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
@@ -121,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
@@ -141,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
diff --git a/arch/mn10300/mm/cache-inv-by-tag.S b/arch/mn10300/mm/cache-inv-by-tag.S
index e9713b40c0ff..ccedce9c144d 100644
--- a/arch/mn10300/mm/cache-inv-by-tag.S
+++ b/arch/mn10300/mm/cache-inv-by-tag.S
@@ -15,6 +15,7 @@
#include <asm/cache.h>
#include <asm/irqflags.h>
#include <asm/cacheflush.h>
+#include "cache.inc"
#define mn10300_local_dcache_inv_range_intr_interval \
+((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
@@ -70,43 +71,7 @@ mn10300_local_icache_inv:
btst CHCTR_ICEN,d0
beq mn10300_local_icache_inv_end
-#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
- LOCAL_CLI_SAVE(d1)
-
- # 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
- and ~CHCTR_ICINV,d0
- or CHCTR_ICEN,d0
- movhu d0,(a0)
- movhu (a0),d0
-
- LOCAL_IRQ_RESTORE(d1)
-#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
- # invalidate
- or CHCTR_ICINV,d0
- movhu d0,(a0)
- movhu (a0),d0
-#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+ invalidate_icache 1
mn10300_local_icache_inv_end:
ret [],0
@@ -128,43 +93,7 @@ mn10300_local_dcache_inv:
btst CHCTR_DCEN,d0
beq mn10300_local_dcache_inv_end
-#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
- LOCAL_CLI_SAVE(d1)
-
- # disable the dcache
- and ~CHCTR_DCEN,d0
- movhu d0,(a0)
-
- # and wait for it to calm down
- setlb
- movhu (a0),d0
- btst CHCTR_DCBUSY,d0
- lne
-
- # invalidate
- or CHCTR_DCINV,d0
- movhu d0,(a0)
-
- # wait for the cache to finish
- mov CHCTR,a0
- setlb
- movhu (a0),d0
- btst CHCTR_DCBUSY,d0
- lne
-
- # and reenable it
- and ~CHCTR_DCINV,d0
- or CHCTR_DCEN,d0
- movhu d0,(a0)
- movhu (a0),d0
-
- LOCAL_IRQ_RESTORE(d1)
-#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
- # invalidate
- or CHCTR_DCINV,d0
- movhu d0,(a0)
- movhu (a0),d0
-#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+ invalidate_dcache 1
mn10300_local_dcache_inv_end:
ret [],0
@@ -195,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
@@ -212,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
diff --git a/arch/mn10300/mm/cache.inc b/arch/mn10300/mm/cache.inc
new file mode 100644
index 000000000000..394a119b9c73
--- /dev/null
+++ b/arch/mn10300/mm/cache.inc
@@ -0,0 +1,133 @@
+/* MN10300 CPU core caching macros -*- asm -*-
+ *
+ * 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.
+ */
+
+
+###############################################################################
+#
+# Invalidate the instruction cache.
+# A0: Should hold CHCTR
+# D0: Should have been read from CHCTR
+# D1: Will be clobbered
+#
+# On some cores it is necessary to disable the icache whilst we do this.
+#
+###############################################################################
+ .macro invalidate_icache,disable_irq
+
+#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
+ .if \disable_irq
+ # don't want an interrupt routine seeing a disabled cache
+ mov epsw,d1
+ and ~EPSW_IE,epsw
+ or EPSW_NMID,epsw
+ nop
+ nop
+ .endif
+
+ # 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
+ setlb
+ movhu (a0),d0
+ btst CHCTR_ICBUSY,d0
+ lne
+
+ # and reenable it
+ or CHCTR_ICEN,d0
+ movhu d0,(a0)
+ movhu (a0),d0
+
+ .if \disable_irq
+ LOCAL_IRQ_RESTORE(d1)
+ .endif
+
+#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+
+ # invalidate
+ or CHCTR_ICINV,d0
+ movhu d0,(a0)
+ movhu (a0),d0
+
+#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+ .endm
+
+###############################################################################
+#
+# Invalidate the data cache.
+# A0: Should hold CHCTR
+# D0: Should have been read from CHCTR
+# D1: Will be clobbered
+#
+# On some cores it is necessary to disable the dcache whilst we do this.
+#
+###############################################################################
+ .macro invalidate_dcache,disable_irq
+
+#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
+ .if \disable_irq
+ # don't want an interrupt routine seeing a disabled cache
+ mov epsw,d1
+ and ~EPSW_IE,epsw
+ or EPSW_NMID,epsw
+ nop
+ nop
+ .endif
+
+ # disable the dcache
+ and ~CHCTR_DCEN,d0
+ movhu d0,(a0)
+
+ # and wait for it to calm down
+ setlb
+ movhu (a0),d0
+ btst CHCTR_DCBUSY,d0
+ lne
+
+ # invalidate
+ or CHCTR_DCINV,d0
+ movhu d0,(a0)
+
+ # wait for the cache to finish
+ setlb
+ movhu (a0),d0
+ btst CHCTR_DCBUSY,d0
+ lne
+
+ # and reenable it
+ or CHCTR_DCEN,d0
+ movhu d0,(a0)
+ movhu (a0),d0
+
+ .if \disable_irq
+ LOCAL_IRQ_RESTORE(d1)
+ .endif
+
+#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+
+ # invalidate
+ or CHCTR_DCINV,d0
+ movhu d0,(a0)
+ movhu (a0),d0
+
+#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+ .endm
diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c
index 59c3da49d9d9..0945409a8022 100644
--- a/arch/mn10300/mm/fault.c
+++ b/arch/mn10300/mm/fault.c
@@ -28,8 +28,9 @@
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
#include <asm/hardirq.h>
-#include <asm/gdb-stub.h>
#include <asm/cpu-regs.h>
+#include <asm/debugger.h>
+#include <asm/gdb-stub.h>
/*
* Unlock any spinlocks which will prevent us from getting the
@@ -306,10 +307,8 @@ no_context:
printk(" printing pc:\n");
printk(KERN_ALERT "%08lx\n", regs->pc);
-#ifdef CONFIG_GDBSTUB
- gdbstub_intercept(
- regs, fault_code & 0x00010000 ? EXCEP_IAERROR : EXCEP_DAERROR);
-#endif
+ debugger_intercept(fault_code & 0x00010000 ? EXCEP_IAERROR : EXCEP_DAERROR,
+ SIGSEGV, SEGV_ACCERR, regs);
page = PTBR;
page = ((unsigned long *) __va(page))[address >> 22];