Commit 7f386ac3 authored by David Howells's avatar David Howells

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: default avatarDavid Howells <dhowells@redhat.com>
parent 792576b1
...@@ -14,6 +14,14 @@ ...@@ -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 */
......
...@@ -21,10 +21,6 @@ obj-$(CONFIG_GDBSTUB) += gdb-stub.o gdb-low.o ...@@ -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
......
...@@ -306,36 +306,7 @@ ENTRY(nmi_handler) ...@@ -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
......
###############################################################################
#
# 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
...@@ -133,7 +133,7 @@ ...@@ -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 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep) ...@@ -1665,7 +1665,7 @@ static int gdbstub(struct pt_regs *regs, enum exception_code excep)
* 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);
......
...@@ -99,3 +99,49 @@ config MN10300_CACHE_INV_ICACHE ...@@ -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.
...@@ -13,6 +13,15 @@ cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_REG) += cache-inv-by-reg.o ...@@ -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 := \
......
/* 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
/* 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
/* 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
/* 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
/* 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
...@@ -62,7 +62,7 @@ mn10300_local_dcache_flush: ...@@ -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: ...@@ -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: ...@@ -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 and L1_CACHE_TAG_MASK,d0 # round start addr down
# addr down
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 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
......
...@@ -116,9 +116,9 @@ mn10300_local_dcache_inv_range: ...@@ -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: ...@@ -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 and L1_CACHE_TAG_MASK,d0 # round start addr down
# 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
......
...@@ -124,9 +124,9 @@ mn10300_local_dcache_inv_range: ...@@ -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: ...@@ -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 and L1_CACHE_TAG_MASK,d0 # round start addr down
# 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
......
...@@ -23,6 +23,7 @@ ...@@ -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
......
...@@ -29,6 +29,7 @@ ...@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment