 2e65d1f6ee
			
		
	
	
	2e65d1f6ee
	
	
	
		
			
			One of the kernel debugger cacheflush variants escaped proper testing.  Two of
the labels are wrong, being derived from the code that was copied to construct
the variant.
The first label results in the following assembler message:
    AS      arch/mn10300/mm/cache-dbg-flush-by-reg.o
  arch/mn10300/mm/cache-dbg-flush-by-reg.S: Assembler messages:
  arch/mn10300/mm/cache-dbg-flush-by-reg.S:123: Error: symbol `debugger_local_cache_flushinv_no_dcache' is already defined
And the second label results in the following linker message:
  arch/mn10300/mm/built-in.o:(.text+0x1d39): undefined reference to `mn10300_local_icache_inv_range_reg_end'
  arch/mn10300/mm/built-in.o:(.text+0x1d39): relocation truncated to fit: R_MN10300_PCREL16 against undefined symbol `mn10300_local_icache_inv_range_reg_end'
To test this file the following configuration pieces must be set:
	CONFIG_AM34=y
	CONFIG_MN10300_CACHE_WBACK=y
	CONFIG_MN10300_DEBUGGER_CACHE_FLUSH_BY_REG=y
	CONFIG_MN10300_CACHE_MANAGE_BY_REG=y
	CONFIG_AM34_HAS_CACHE_SNOOP=n
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
		
	
			
		
			
				
	
	
		
			160 lines
		
	
	
	
		
			3.5 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			160 lines
		
	
	
	
		
			3.5 KiB
			
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /* 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_one_no_dcache:
 | |
| 	#
 | |
| 	# now try to flush the icache
 | |
| 	#
 | |
| 	mov	CHCTR,a0
 | |
| 	movhu	(a0),d0
 | |
| 	btst	CHCTR_ICEN,d0
 | |
| 	beq	debugger_local_cache_flushinv_one_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
 |