linux/arch/mn10300/mm/cache-dbg-flush-by-reg.S
David Howells 2e65d1f6ee MN10300: Fix one of the kernel debugger cacheflush variants
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>
2011-06-07 19:03:52 -07:00

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