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>
This commit is contained in:
parent
792576b1c5
commit
7f386ac327
17 changed files with 591 additions and 157 deletions
|
@ -14,6 +14,14 @@
|
|||
|
||||
#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 */
|
||||
|
||||
#endif /* CONFIG_KERNEL_DEBUGGER */
|
||||
|
|
|
@ -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_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_PROFILE) += profile.o profile-low.o
|
||||
obj-$(CONFIG_MODULES) += module.o
|
||||
|
|
|
@ -306,36 +306,7 @@ ENTRY(nmi_handler)
|
|||
movbu d0,(GxICR(GDB_NMI_IPI))
|
||||
movhu (GxICR(GDB_NMI_IPI)),d0
|
||||
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
|
||||
SAVE_ALL
|
||||
call gdbstub_nmi_wait[],0
|
||||
|
|
|
@ -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
|
|
@ -133,7 +133,7 @@
|
|||
#include <asm/system.h>
|
||||
#include <asm/gdb-stub.h>
|
||||
#include <asm/exceptions.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/debugger.h>
|
||||
#include <asm/serial-regs.h>
|
||||
#include <asm/busctl-regs.h>
|
||||
#include <unit/leds.h>
|
||||
|
@ -1665,7 +1665,7 @@ done:
|
|||
* NB: We flush both caches, just to be sure...
|
||||
*/
|
||||
if (gdbstub_flush_caches)
|
||||
gdbstub_purge_cache();
|
||||
debugger_local_cache_flushinv();
|
||||
|
||||
gdbstub_load_fpu();
|
||||
mn10300_set_gdbleds(0);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 := \
|
||||
|
|
160
arch/mn10300/mm/cache-dbg-flush-by-reg.S
Normal file
160
arch/mn10300/mm/cache-dbg-flush-by-reg.S
Normal file
|
@ -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
arch/mn10300/mm/cache-dbg-flush-by-tag.S
Normal file
114
arch/mn10300/mm/cache-dbg-flush-by-tag.S
Normal file
|
@ -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
arch/mn10300/mm/cache-dbg-inv-by-reg.S
Normal file
69
arch/mn10300/mm/cache-dbg-inv-by-reg.S
Normal file
|
@ -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
arch/mn10300/mm/cache-dbg-inv-by-tag.S
Normal file
120
arch/mn10300/mm/cache-dbg-inv-by-tag.S
Normal file
|
@ -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
arch/mn10300/mm/cache-dbg-inv.S
Normal file
47
arch/mn10300/mm/cache-dbg-inv.S
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -116,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
|
||||
|
@ -136,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
|
||||
|
|
|
@ -124,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
|
||||
|
@ -141,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
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#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_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
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#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_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
|
||||
|
|
Loading…
Reference in a new issue