瀏覽代碼

MN10300: Create general kernel debugger cache flushing

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>
David Howells 14 年之前
父節點
當前提交
7f386ac327

+ 8 - 0
arch/mn10300/include/asm/debugger.h

@@ -14,6 +14,14 @@
 
 
 #if defined(CONFIG_KERNEL_DEBUGGER)
 #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 */
 #else /* CONFIG_KERNEL_DEBUGGER */
 
 
 #endif /* CONFIG_KERNEL_DEBUGGER */
 #endif /* CONFIG_KERNEL_DEBUGGER */

+ 0 - 4
arch/mn10300/kernel/Makefile

@@ -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_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o
 obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-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_MN10300_RTC) += rtc.o
 obj-$(CONFIG_PROFILE) += profile.o profile-low.o
 obj-$(CONFIG_PROFILE) += profile.o profile-low.o
 obj-$(CONFIG_MODULES) += module.o
 obj-$(CONFIG_MODULES) += module.o

+ 1 - 30
arch/mn10300/kernel/entry.S

@@ -306,36 +306,7 @@ ENTRY(nmi_handler)
 	movbu	d0,(GxICR(GDB_NMI_IPI))
 	movbu	d0,(GxICR(GDB_NMI_IPI))
 	movhu	(GxICR(GDB_NMI_IPI)),d0
 	movhu	(GxICR(GDB_NMI_IPI)),d0
 	and	~EPSW_NMID,epsw		# enable NMI
 	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
 	mov     (sp),d0
 	SAVE_ALL
 	SAVE_ALL
 	call    gdbstub_nmi_wait[],0
 	call    gdbstub_nmi_wait[],0

+ 0 - 105
arch/mn10300/kernel/gdb-cache.S

@@ -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

+ 2 - 2
arch/mn10300/kernel/gdb-stub.c

@@ -133,7 +133,7 @@
 #include <asm/system.h>
 #include <asm/system.h>
 #include <asm/gdb-stub.h>
 #include <asm/gdb-stub.h>
 #include <asm/exceptions.h>
 #include <asm/exceptions.h>
-#include <asm/cacheflush.h>
+#include <asm/debugger.h>
 #include <asm/serial-regs.h>
 #include <asm/serial-regs.h>
 #include <asm/busctl-regs.h>
 #include <asm/busctl-regs.h>
 #include <unit/leds.h>
 #include <unit/leds.h>
@@ -1665,7 +1665,7 @@ done:
 	 * NB: We flush both caches, just to be sure...
 	 * NB: We flush both caches, just to be sure...
 	 */
 	 */
 	if (gdbstub_flush_caches)
 	if (gdbstub_flush_caches)
-		gdbstub_purge_cache();
+		debugger_local_cache_flushinv();
 
 
 	gdbstub_load_fpu();
 	gdbstub_load_fpu();
 	mn10300_set_gdbleds(0);
 	mn10300_set_gdbleds(0);

+ 46 - 0
arch/mn10300/mm/Kconfig.cache

@@ -99,3 +99,49 @@ config MN10300_CACHE_INV_ICACHE
 	help
 	help
 	  Set if we need the icache to be invalidated, even if the dcache is in
 	  Set if we need the icache to be invalidated, even if the dcache is in
 	  write-through mode and doesn't need flushing.
 	  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.

+ 9 - 0
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_TAG) += cache-flush-by-tag.o
 cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_REG) += cache-flush-by-reg.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
 cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o
 
 
 obj-y := \
 obj-y := \

+ 160 - 0
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

+ 114 - 0
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

+ 69 - 0
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

+ 120 - 0
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

+ 47 - 0
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

+ 6 - 7
arch/mn10300/mm/cache-flush-by-tag.S

@@ -62,7 +62,7 @@ mn10300_local_dcache_flush:
 
 
 mn10300_local_dcache_flush_loop:
 mn10300_local_dcache_flush_loop:
 	mov	(a0),d0
 	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
 	or	L1_CACHE_TAG_VALID,d0		# retain valid entries in the
 						# cache
 						# cache
 	mov	d0,(a1)				# conditional purge
 	mov	d0,(a1)				# conditional purge
@@ -112,11 +112,11 @@ mn10300_local_dcache_flush_range:
 1:
 1:
 
 
 	# round start addr down
 	# round start addr down
-	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
+	and	L1_CACHE_TAG_MASK,d0
 	mov	d0,a1
 	mov	d0,a1
 
 
 	add	L1_CACHE_BYTES,d1			# round end addr up
 	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
 	# write a request to flush all instances of an address from the cache
 	mov	DCACHE_PURGE(0,0),a0
 	mov	DCACHE_PURGE(0,0),a0
@@ -215,12 +215,11 @@ mn10300_local_dcache_flush_inv_range:
 	bra	mn10300_local_dcache_flush_inv
 	bra	mn10300_local_dcache_flush_inv
 1:
 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
 	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
 	# write a request to flush and invalidate all instances of an address
 	# from the cache
 	# from the cache

+ 4 - 5
arch/mn10300/mm/cache-inv-by-reg.S

@@ -116,9 +116,9 @@ mn10300_local_dcache_inv_range:
 	# and if they're not cacheline-aligned, we must flush any bits outside
 	# and if they're not cacheline-aligned, we must flush any bits outside
 	# the range that share cachelines with stuff inside the range
 	# the range that share cachelines with stuff inside the range
 #ifdef CONFIG_MN10300_CACHE_WBACK
 #ifdef CONFIG_MN10300_CACHE_WBACK
-	btst	~(L1_CACHE_BYTES-1),d0
+	btst	~L1_CACHE_TAG_MASK,d0
 	bne	1f
 	bne	1f
-	btst	~(L1_CACHE_BYTES-1),d1
+	btst	~L1_CACHE_TAG_MASK,d1
 	beq	2f
 	beq	2f
 1:
 1:
 	bra	mn10300_local_dcache_flush_inv_range
 	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
 	# writeback mode, in which case we would be in flush and invalidate by
 	# now
 	# now
 #ifndef CONFIG_MN10300_CACHE_WBACK
 #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
 	mov	L1_CACHE_BYTES-1,d2
 	add	d2,d1
 	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 */
 #endif /* !CONFIG_MN10300_CACHE_WBACK */
 
 
 	sub	d0,d1,d2		# calculate the total size
 	sub	d0,d1,d2		# calculate the total size

+ 4 - 5
arch/mn10300/mm/cache-inv-by-tag.S

@@ -124,9 +124,9 @@ mn10300_local_dcache_inv_range:
 	# and if they're not cacheline-aligned, we must flush any bits outside
 	# and if they're not cacheline-aligned, we must flush any bits outside
 	# the range that share cachelines with stuff inside the range
 	# the range that share cachelines with stuff inside the range
 #ifdef CONFIG_MN10300_CACHE_WBACK
 #ifdef CONFIG_MN10300_CACHE_WBACK
-	btst	~(L1_CACHE_BYTES-1),d0
+	btst	~L1_CACHE_TAG_MASK,d0
 	bne	1f
 	bne	1f
-	btst	~(L1_CACHE_BYTES-1),d1
+	btst	~L1_CACHE_TAG_MASK,d1
 	beq	2f
 	beq	2f
 1:
 1:
 	bra	mn10300_local_dcache_flush_inv_range
 	bra	mn10300_local_dcache_flush_inv_range
@@ -141,11 +141,10 @@ mn10300_local_dcache_inv_range:
 	beq	mn10300_local_dcache_inv_range_end
 	beq	mn10300_local_dcache_inv_range_end
 
 
 #ifndef CONFIG_MN10300_CACHE_WBACK
 #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
 	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 */
 #endif /* !CONFIG_MN10300_CACHE_WBACK */
 	mov	d0,a1
 	mov	d0,a1
 
 

+ 1 - 0
arch/mn10300/proc-mn103e010/include/proc/cache.h

@@ -23,6 +23,7 @@
 #define L1_CACHE_TAG_DIRTY	0x00000008	/* data cache tag dirty bit */
 #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_ENTRY	0x00000ff0	/* cache tag entry address mask */
 #define L1_CACHE_TAG_ADDRESS	0xfffff000	/* cache tag line 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
  * specification of the interval between interrupt checking intervals whilst

+ 1 - 0
arch/mn10300/proc-mn2ws0050/include/proc/cache.h

@@ -29,6 +29,7 @@
 #define L1_CACHE_TAG_DIRTY	0x00000008	/* data cache tag dirty bit */
 #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_ENTRY	0x00000fe0	/* cache tag entry address mask */
 #define L1_CACHE_TAG_ADDRESS	0xfffff000	/* cache tag line 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
  * specification of the interval between interrupt checking intervals whilst