aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mn10300/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mn10300/mm')
-rw-r--r--arch/mn10300/mm/Kconfig.cache148
-rw-r--r--arch/mn10300/mm/Makefile32
-rw-r--r--arch/mn10300/mm/cache-dbg-flush-by-reg.S160
-rw-r--r--arch/mn10300/mm/cache-dbg-flush-by-tag.S114
-rw-r--r--arch/mn10300/mm/cache-dbg-inv-by-reg.S69
-rw-r--r--arch/mn10300/mm/cache-dbg-inv-by-tag.S120
-rw-r--r--arch/mn10300/mm/cache-dbg-inv.S47
-rw-r--r--arch/mn10300/mm/cache-disabled.c21
-rw-r--r--arch/mn10300/mm/cache-flush-by-reg.S308
-rw-r--r--arch/mn10300/mm/cache-flush-by-tag.S250
-rw-r--r--arch/mn10300/mm/cache-flush-icache.c155
-rw-r--r--arch/mn10300/mm/cache-inv-by-reg.S350
-rw-r--r--arch/mn10300/mm/cache-inv-by-tag.S276
-rw-r--r--arch/mn10300/mm/cache-inv-icache.c129
-rw-r--r--arch/mn10300/mm/cache-smp-flush.c156
-rw-r--r--arch/mn10300/mm/cache-smp-inv.c153
-rw-r--r--arch/mn10300/mm/cache-smp.c105
-rw-r--r--arch/mn10300/mm/cache-smp.h69
-rw-r--r--arch/mn10300/mm/cache.c54
-rw-r--r--arch/mn10300/mm/cache.inc133
-rw-r--r--arch/mn10300/mm/dma-alloc.c128
-rw-r--r--arch/mn10300/mm/extable.c26
-rw-r--r--arch/mn10300/mm/fault.c414
-rw-r--r--arch/mn10300/mm/init.c136
-rw-r--r--arch/mn10300/mm/misalignment.c966
-rw-r--r--arch/mn10300/mm/mmu-context.c62
-rw-r--r--arch/mn10300/mm/pgtable.c174
-rw-r--r--arch/mn10300/mm/tlb-mn10300.S220
-rw-r--r--arch/mn10300/mm/tlb-smp.c213
29 files changed, 0 insertions, 5188 deletions
diff --git a/arch/mn10300/mm/Kconfig.cache b/arch/mn10300/mm/Kconfig.cache
deleted file mode 100644
index 8cc5d9ec3b6c..000000000000
--- a/arch/mn10300/mm/Kconfig.cache
+++ /dev/null
@@ -1,148 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# MN10300 CPU cache options
-#
-
-choice
- prompt "CPU Caching mode"
- default MN10300_CACHE_WBACK
- help
- This option determines the caching mode for the kernel.
-
- Write-Back caching mode involves the all reads and writes causing
- the affected cacheline to be read into the cache first before being
- operated upon. Memory is not then updated by a write until the cache
- is filled and a cacheline needs to be displaced from the cache to
- make room. Only at that point is it written back.
-
- Write-Through caching only fetches cachelines from memory on a
- read. Writes always get written directly to memory. If the affected
- cacheline is also in cache, it will be updated too.
-
- The final option is to turn of caching entirely.
-
-config MN10300_CACHE_WBACK
- bool "Write-Back"
- help
- The dcache operates in delayed write-back mode. It must be manually
- flushed if writes are made that subsequently need to be executed or
- to be DMA'd by a device.
-
-config MN10300_CACHE_WTHRU
- bool "Write-Through"
- help
- The dcache operates in immediate write-through mode. Writes are
- committed to RAM immediately in addition to being stored in the
- cache. This means that the written data is immediately available for
- execution or DMA.
-
- This is not available for use with an SMP kernel if cache flushing
- and invalidation by automatic purge register is not selected.
-
-config MN10300_CACHE_DISABLED
- bool "Disabled"
- help
- The icache and dcache are disabled.
-
-endchoice
-
-config MN10300_CACHE_ENABLED
- def_bool y if !MN10300_CACHE_DISABLED
-
-
-choice
- prompt "CPU cache flush/invalidate method"
- default MN10300_CACHE_MANAGE_BY_TAG if !AM34_2
- default MN10300_CACHE_MANAGE_BY_REG if AM34_2
- depends on MN10300_CACHE_ENABLED
- help
- This determines the method by which CPU cache flushing and
- invalidation is performed.
-
-config MN10300_CACHE_MANAGE_BY_TAG
- bool "Use the cache tag registers directly"
- depends on !(SMP && MN10300_CACHE_WTHRU)
-
-config MN10300_CACHE_MANAGE_BY_REG
- bool "Flush areas by way of automatic purge registers (AM34 only)"
- depends on AM34_2
-
-endchoice
-
-config MN10300_CACHE_INV_BY_TAG
- def_bool y if MN10300_CACHE_MANAGE_BY_TAG && MN10300_CACHE_ENABLED
-
-config MN10300_CACHE_INV_BY_REG
- def_bool y if MN10300_CACHE_MANAGE_BY_REG && MN10300_CACHE_ENABLED
-
-config MN10300_CACHE_FLUSH_BY_TAG
- def_bool y if MN10300_CACHE_MANAGE_BY_TAG && MN10300_CACHE_WBACK
-
-config MN10300_CACHE_FLUSH_BY_REG
- def_bool y if MN10300_CACHE_MANAGE_BY_REG && MN10300_CACHE_WBACK
-
-
-config MN10300_HAS_CACHE_SNOOP
- def_bool n
-
-config MN10300_CACHE_SNOOP
- bool "Use CPU Cache Snooping"
- depends on MN10300_CACHE_ENABLED && MN10300_HAS_CACHE_SNOOP
- default y
-
-config MN10300_CACHE_FLUSH_ICACHE
- def_bool y if MN10300_CACHE_WBACK && !MN10300_CACHE_SNOOP
- help
- Set if we need the dcache flushing before the icache is invalidated.
-
-config MN10300_CACHE_INV_ICACHE
- def_bool y if MN10300_CACHE_WTHRU && !MN10300_CACHE_SNOOP
- 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.
diff --git a/arch/mn10300/mm/Makefile b/arch/mn10300/mm/Makefile
deleted file mode 100644
index 048ba6f67f9a..000000000000
--- a/arch/mn10300/mm/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for the MN10300-specific memory management code
-#
-
-cache-smp-wback-$(CONFIG_MN10300_CACHE_WBACK) := cache-smp-flush.o
-
-cacheflush-y := cache.o
-cacheflush-$(CONFIG_SMP) += cache-smp.o cache-smp-inv.o $(cache-smp-wback-y)
-cacheflush-$(CONFIG_MN10300_CACHE_INV_ICACHE) += cache-inv-icache.o
-cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_ICACHE) += cache-flush-icache.o
-cacheflush-$(CONFIG_MN10300_CACHE_INV_BY_TAG) += cache-inv-by-tag.o
-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 := \
- init.o fault.o pgtable.o extable.o tlb-mn10300.o mmu-context.o \
- misalignment.o dma-alloc.o $(cacheflush-y)
-
-obj-$(CONFIG_SMP) += tlb-smp.o
diff --git a/arch/mn10300/mm/cache-dbg-flush-by-reg.S b/arch/mn10300/mm/cache-dbg-flush-by-reg.S
deleted file mode 100644
index a775ea5d7cee..000000000000
--- a/arch/mn10300/mm/cache-dbg-flush-by-reg.S
+++ /dev/null
@@ -1,160 +0,0 @@
-/* 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
diff --git a/arch/mn10300/mm/cache-dbg-flush-by-tag.S b/arch/mn10300/mm/cache-dbg-flush-by-tag.S
deleted file mode 100644
index bf56930e6e70..000000000000
--- a/arch/mn10300/mm/cache-dbg-flush-by-tag.S
+++ /dev/null
@@ -1,114 +0,0 @@
-/* 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
diff --git a/arch/mn10300/mm/cache-dbg-inv-by-reg.S b/arch/mn10300/mm/cache-dbg-inv-by-reg.S
deleted file mode 100644
index c4e6252941b1..000000000000
--- a/arch/mn10300/mm/cache-dbg-inv-by-reg.S
+++ /dev/null
@@ -1,69 +0,0 @@
-/* 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
diff --git a/arch/mn10300/mm/cache-dbg-inv-by-tag.S b/arch/mn10300/mm/cache-dbg-inv-by-tag.S
deleted file mode 100644
index d8ec821e5f88..000000000000
--- a/arch/mn10300/mm/cache-dbg-inv-by-tag.S
+++ /dev/null
@@ -1,120 +0,0 @@
-/* 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
diff --git a/arch/mn10300/mm/cache-dbg-inv.S b/arch/mn10300/mm/cache-dbg-inv.S
deleted file mode 100644
index eba2d6dca066..000000000000
--- a/arch/mn10300/mm/cache-dbg-inv.S
+++ /dev/null
@@ -1,47 +0,0 @@
-/* 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
diff --git a/arch/mn10300/mm/cache-disabled.c b/arch/mn10300/mm/cache-disabled.c
deleted file mode 100644
index f669ea42aba6..000000000000
--- a/arch/mn10300/mm/cache-disabled.c
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Handle the cache being disabled
- *
- * Copyright (C) 2010 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/mm.h>
-
-/*
- * allow userspace to flush the instruction cache
- */
-asmlinkage long sys_cacheflush(unsigned long start, unsigned long end)
-{
- if (end < start)
- return -EINVAL;
- return 0;
-}
diff --git a/arch/mn10300/mm/cache-flush-by-reg.S b/arch/mn10300/mm/cache-flush-by-reg.S
deleted file mode 100644
index 1dcae0211671..000000000000
--- a/arch/mn10300/mm/cache-flush-by-reg.S
+++ /dev/null
@@ -1,308 +0,0 @@
-/* MN10300 CPU core caching routines, using indirect regs on cache controller
- *
- * 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/page.h>
-#include <asm/cache.h>
-#include <asm/irqflags.h>
-
- .am33_2
-
-#ifndef CONFIG_SMP
- .globl mn10300_dcache_flush
- .globl mn10300_dcache_flush_page
- .globl mn10300_dcache_flush_range
- .globl mn10300_dcache_flush_range2
- .globl mn10300_dcache_flush_inv
- .globl mn10300_dcache_flush_inv_page
- .globl mn10300_dcache_flush_inv_range
- .globl mn10300_dcache_flush_inv_range2
-
-mn10300_dcache_flush = mn10300_local_dcache_flush
-mn10300_dcache_flush_page = mn10300_local_dcache_flush_page
-mn10300_dcache_flush_range = mn10300_local_dcache_flush_range
-mn10300_dcache_flush_range2 = mn10300_local_dcache_flush_range2
-mn10300_dcache_flush_inv = mn10300_local_dcache_flush_inv
-mn10300_dcache_flush_inv_page = mn10300_local_dcache_flush_inv_page
-mn10300_dcache_flush_inv_range = mn10300_local_dcache_flush_inv_range
-mn10300_dcache_flush_inv_range2 = mn10300_local_dcache_flush_inv_range2
-
-#endif /* !CONFIG_SMP */
-
-###############################################################################
-#
-# void mn10300_local_dcache_flush(void)
-# Flush the entire data cache back to RAM
-#
-###############################################################################
- ALIGN
- .globl mn10300_local_dcache_flush
- .type mn10300_local_dcache_flush,@function
-mn10300_local_dcache_flush:
- movhu (CHCTR),d0
- btst CHCTR_DCEN,d0
- beq mn10300_local_dcache_flush_end
-
- mov DCPGCR,a0
-
- LOCAL_CLI_SAVE(d1)
-
- # 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
-
- LOCAL_IRQ_RESTORE(d1)
-
-mn10300_local_dcache_flush_end:
- ret [],0
- .size mn10300_local_dcache_flush,.-mn10300_local_dcache_flush
-
-###############################################################################
-#
-# void mn10300_local_dcache_flush_page(unsigned long start)
-# void mn10300_local_dcache_flush_range(unsigned long start, unsigned long end)
-# void mn10300_local_dcache_flush_range2(unsigned long start, unsigned long size)
-# Flush a range of addresses on a page in the dcache
-#
-###############################################################################
- ALIGN
- .globl mn10300_local_dcache_flush_page
- .globl mn10300_local_dcache_flush_range
- .globl mn10300_local_dcache_flush_range2
- .type mn10300_local_dcache_flush_page,@function
- .type mn10300_local_dcache_flush_range,@function
- .type mn10300_local_dcache_flush_range2,@function
-mn10300_local_dcache_flush_page:
- and ~(PAGE_SIZE-1),d0
- mov PAGE_SIZE,d1
-mn10300_local_dcache_flush_range2:
- add d0,d1
-mn10300_local_dcache_flush_range:
- movm [d2,d3,a2],(sp)
-
- movhu (CHCTR),d2
- btst CHCTR_DCEN,d2
- beq mn10300_local_dcache_flush_range_end
-
- # calculate alignsize
- #
- # alignsize = L1_CACHE_BYTES;
- # for (i = (end - start - 1) / L1_CACHE_BYTES ; i > 0; i >>= 1)
- # alignsize <<= 1;
- # d2 = alignsize;
- #
- mov L1_CACHE_BYTES,d2
- sub d0,d1,d3
- add -1,d3
- lsr L1_CACHE_SHIFT,d3
- beq 2f
-1:
- add d2,d2
- lsr 1,d3
- bne 1b
-2:
- mov d1,a1 # a1 = end
-
- LOCAL_CLI_SAVE(d3)
- mov DCPGCR,a0
-
- # wait for busy bit of area purge
- setlb
- mov (a0),d1
- btst DCPGCR_DCPGBSY,d1
- lne
-
- # determine the mask
- mov d2,d1
- add -1,d1
- not d1 # d1 = mask = ~(alignsize-1)
- mov d1,(DCPGMR)
-
- and d1,d0,a2 # a2 = mask & start
-
-dcpgloop:
- # area purge
- mov a2,d0
- or DCPGCR_DCP,d0
- mov d0,(a0) # DCPGCR = (mask & start) | DCPGCR_DCP
-
- # wait for busy bit of area purge
- setlb
- mov (a0),d1
- btst DCPGCR_DCPGBSY,d1
- lne
-
- # check purge of end address
- add d2,a2 # a2 += alignsize
- cmp a1,a2 # if (a2 < end) goto dcpgloop
- bns dcpgloop
-
- LOCAL_IRQ_RESTORE(d3)
-
-mn10300_local_dcache_flush_range_end:
- ret [d2,d3,a2],12
-
- .size mn10300_local_dcache_flush_page,.-mn10300_local_dcache_flush_page
- .size mn10300_local_dcache_flush_range,.-mn10300_local_dcache_flush_range
- .size mn10300_local_dcache_flush_range2,.-mn10300_local_dcache_flush_range2
-
-###############################################################################
-#
-# void mn10300_local_dcache_flush_inv(void)
-# Flush the entire data cache and invalidate all entries
-#
-###############################################################################
- ALIGN
- .globl mn10300_local_dcache_flush_inv
- .type mn10300_local_dcache_flush_inv,@function
-mn10300_local_dcache_flush_inv:
- movhu (CHCTR),d0
- btst CHCTR_DCEN,d0
- beq mn10300_local_dcache_flush_inv_end
-
- mov DCPGCR,a0
-
- LOCAL_CLI_SAVE(d1)
-
- # wait for busy bit of area purge & invalidate
- setlb
- mov (a0),d0
- btst DCPGCR_DCPGBSY,d0
- lne
-
- # set the mask to cover everything
- clr d0
- mov d0,(DCPGMR)
-
- # area purge & invalidate
- mov DCPGCR_DCP|DCPGCR_DCI,d0
- mov d0,(a0)
-
- # wait for busy bit of area purge & invalidate
- setlb
- mov (a0),d0
- btst DCPGCR_DCPGBSY,d0
- lne
-
- LOCAL_IRQ_RESTORE(d1)
-
-mn10300_local_dcache_flush_inv_end:
- ret [],0
- .size mn10300_local_dcache_flush_inv,.-mn10300_local_dcache_flush_inv
-
-###############################################################################
-#
-# void mn10300_local_dcache_flush_inv_page(unsigned long start)
-# void mn10300_local_dcache_flush_inv_range(unsigned long start, unsigned long end)
-# void mn10300_local_dcache_flush_inv_range2(unsigned long start, unsigned long size)
-# Flush and invalidate a range of addresses on a page in the dcache
-#
-###############################################################################
- ALIGN
- .globl mn10300_local_dcache_flush_inv_page
- .globl mn10300_local_dcache_flush_inv_range
- .globl mn10300_local_dcache_flush_inv_range2
- .type mn10300_local_dcache_flush_inv_page,@function
- .type mn10300_local_dcache_flush_inv_range,@function
- .type mn10300_local_dcache_flush_inv_range2,@function
-mn10300_local_dcache_flush_inv_page:
- and ~(PAGE_SIZE-1),d0
- mov PAGE_SIZE,d1
-mn10300_local_dcache_flush_inv_range2:
- add d0,d1
-mn10300_local_dcache_flush_inv_range:
- movm [d2,d3,a2],(sp)
-
- movhu (CHCTR),d2
- btst CHCTR_DCEN,d2
- beq mn10300_local_dcache_flush_inv_range_end
-
- # calculate alignsize
- #
- # alignsize = L1_CACHE_BYTES;
- # for (i = (end - start - 1) / L1_CACHE_BYTES; i > 0; i >>= 1)
- # alignsize <<= 1;
- # d2 = alignsize
- #
- mov L1_CACHE_BYTES,d2
- sub d0,d1,d3
- add -1,d3
- lsr L1_CACHE_SHIFT,d3
- beq 2f
-1:
- add d2,d2
- lsr 1,d3
- bne 1b
-2:
- mov d1,a1 # a1 = end
-
- LOCAL_CLI_SAVE(d3)
- mov DCPGCR,a0
-
- # wait for busy bit of area purge & invalidate
- setlb
- mov (a0),d1
- btst DCPGCR_DCPGBSY,d1
- lne
-
- # set the mask
- mov d2,d1
- add -1,d1
- not d1 # d1 = mask = ~(alignsize-1)
- mov d1,(DCPGMR)
-
- and d1,d0,a2 # a2 = mask & start
-
-dcpgivloop:
- # area purge & invalidate
- mov a2,d0
- or DCPGCR_DCP|DCPGCR_DCI,d0
- mov d0,(a0) # DCPGCR = (mask & start)|DCPGCR_DCP|DCPGCR_DCI
-
- # wait for busy bit of area purge & invalidate
- setlb
- mov (a0),d1
- btst DCPGCR_DCPGBSY,d1
- lne
-
- # check purge & invalidate of end address
- add d2,a2 # a2 += alignsize
- cmp a1,a2 # if (a2 < end) goto dcpgivloop
- bns dcpgivloop
-
- LOCAL_IRQ_RESTORE(d3)
-
-mn10300_local_dcache_flush_inv_range_end:
- ret [d2,d3,a2],12
- .size mn10300_local_dcache_flush_inv_page,.-mn10300_local_dcache_flush_inv_page
- .size mn10300_local_dcache_flush_inv_range,.-mn10300_local_dcache_flush_inv_range
- .size mn10300_local_dcache_flush_inv_range2,.-mn10300_local_dcache_flush_inv_range2
diff --git a/arch/mn10300/mm/cache-flush-by-tag.S b/arch/mn10300/mm/cache-flush-by-tag.S
deleted file mode 100644
index 1ddc06849242..000000000000
--- a/arch/mn10300/mm/cache-flush-by-tag.S
+++ /dev/null
@@ -1,250 +0,0 @@
-/* MN10300 CPU core caching routines, using direct tag flushing
- *
- * 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/page.h>
-#include <asm/cache.h>
-#include <asm/irqflags.h>
-
- .am33_2
-
-#ifndef CONFIG_SMP
- .globl mn10300_dcache_flush
- .globl mn10300_dcache_flush_page
- .globl mn10300_dcache_flush_range
- .globl mn10300_dcache_flush_range2
- .globl mn10300_dcache_flush_inv
- .globl mn10300_dcache_flush_inv_page
- .globl mn10300_dcache_flush_inv_range
- .globl mn10300_dcache_flush_inv_range2
-
-mn10300_dcache_flush = mn10300_local_dcache_flush
-mn10300_dcache_flush_page = mn10300_local_dcache_flush_page
-mn10300_dcache_flush_range = mn10300_local_dcache_flush_range
-mn10300_dcache_flush_range2 = mn10300_local_dcache_flush_range2
-mn10300_dcache_flush_inv = mn10300_local_dcache_flush_inv
-mn10300_dcache_flush_inv_page = mn10300_local_dcache_flush_inv_page
-mn10300_dcache_flush_inv_range = mn10300_local_dcache_flush_inv_range
-mn10300_dcache_flush_inv_range2 = mn10300_local_dcache_flush_inv_range2
-
-#endif /* !CONFIG_SMP */
-
-###############################################################################
-#
-# void mn10300_local_dcache_flush(void)
-# Flush the entire data cache back to RAM
-#
-###############################################################################
- ALIGN
- .globl mn10300_local_dcache_flush
- .type mn10300_local_dcache_flush,@function
-mn10300_local_dcache_flush:
- movhu (CHCTR),d0
- btst CHCTR_DCEN,d0
- beq mn10300_local_dcache_flush_end
-
- # 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_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,d1
- bne mn10300_local_dcache_flush_loop
-
-mn10300_local_dcache_flush_end:
- ret [],0
- .size mn10300_local_dcache_flush,.-mn10300_local_dcache_flush
-
-###############################################################################
-#
-# void mn10300_local_dcache_flush_page(unsigned long start)
-# void mn10300_local_dcache_flush_range(unsigned long start, unsigned long end)
-# void mn10300_local_dcache_flush_range2(unsigned long start, unsigned long size)
-# Flush a range of addresses on a page in the dcache
-#
-###############################################################################
- ALIGN
- .globl mn10300_local_dcache_flush_page
- .globl mn10300_local_dcache_flush_range
- .globl mn10300_local_dcache_flush_range2
- .type mn10300_local_dcache_flush_page,@function
- .type mn10300_local_dcache_flush_range,@function
- .type mn10300_local_dcache_flush_range2,@function
-mn10300_local_dcache_flush_page:
- and ~(PAGE_SIZE-1),d0
- mov PAGE_SIZE,d1
-mn10300_local_dcache_flush_range2:
- add d0,d1
-mn10300_local_dcache_flush_range:
- movm [d2],(sp)
-
- movhu (CHCTR),d2
- btst CHCTR_DCEN,d2
- beq mn10300_local_dcache_flush_range_end
-
- sub d0,d1,a0
- cmp MN10300_DCACHE_FLUSH_BORDER,a0
- ble 1f
-
- movm (sp),[d2]
- bra mn10300_local_dcache_flush
-1:
-
- # round start addr down
- and L1_CACHE_TAG_MASK,d0
- mov d0,a1
-
- add L1_CACHE_BYTES,d1 # round end addr up
- 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
- mov a1,d0
- and L1_CACHE_TAG_ENTRY,d0
- add d0,a0 # starting dcache purge control
- # reg address
-
- sub a1,d1
- lsr L1_CACHE_SHIFT,d1 # total number of entries to
- # examine
-
- or L1_CACHE_TAG_VALID,a1 # retain valid entries in the
- # cache
-
-mn10300_local_dcache_flush_range_loop:
- mov a1,(L1_CACHE_WAYDISP*0,a0) # conditionally purge this line
- # all ways
-
- add L1_CACHE_BYTES,a0
- add L1_CACHE_BYTES,a1
- and ~L1_CACHE_WAYDISP,a0 # make sure way stay on way 0
- add -1,d1
- bne mn10300_local_dcache_flush_range_loop
-
-mn10300_local_dcache_flush_range_end:
- ret [d2],4
-
- .size mn10300_local_dcache_flush_page,.-mn10300_local_dcache_flush_page
- .size mn10300_local_dcache_flush_range,.-mn10300_local_dcache_flush_range
- .size mn10300_local_dcache_flush_range2,.-mn10300_local_dcache_flush_range2
-
-###############################################################################
-#
-# void mn10300_local_dcache_flush_inv(void)
-# Flush the entire data cache and invalidate all entries
-#
-###############################################################################
- ALIGN
- .globl mn10300_local_dcache_flush_inv
- .type mn10300_local_dcache_flush_inv,@function
-mn10300_local_dcache_flush_inv:
- movhu (CHCTR),d0
- btst CHCTR_DCEN,d0
- beq mn10300_local_dcache_flush_inv_end
-
- mov L1_CACHE_NENTRIES,d1
- clr a1
-
-mn10300_local_dcache_flush_inv_loop:
- mov (DCACHE_PURGE_WAY0(0),a1),d0 # unconditional purge
- mov (DCACHE_PURGE_WAY1(0),a1),d0 # unconditional purge
- mov (DCACHE_PURGE_WAY2(0),a1),d0 # unconditional purge
- mov (DCACHE_PURGE_WAY3(0),a1),d0 # unconditional purge
-
- add L1_CACHE_BYTES,a1
- add -1,d1
- bne mn10300_local_dcache_flush_inv_loop
-
-mn10300_local_dcache_flush_inv_end:
- ret [],0
- .size mn10300_local_dcache_flush_inv,.-mn10300_local_dcache_flush_inv
-
-###############################################################################
-#
-# void mn10300_local_dcache_flush_inv_page(unsigned long start)
-# void mn10300_local_dcache_flush_inv_range(unsigned long start, unsigned long end)
-# void mn10300_local_dcache_flush_inv_range2(unsigned long start, unsigned long size)
-# Flush and invalidate a range of addresses on a page in the dcache
-#
-###############################################################################
- ALIGN
- .globl mn10300_local_dcache_flush_inv_page
- .globl mn10300_local_dcache_flush_inv_range
- .globl mn10300_local_dcache_flush_inv_range2
- .type mn10300_local_dcache_flush_inv_page,@function
- .type mn10300_local_dcache_flush_inv_range,@function
- .type mn10300_local_dcache_flush_inv_range2,@function
-mn10300_local_dcache_flush_inv_page:
- and ~(PAGE_SIZE-1),d0
- mov PAGE_SIZE,d1
-mn10300_local_dcache_flush_inv_range2:
- add d0,d1
-mn10300_local_dcache_flush_inv_range:
- movm [d2],(sp)
-
- movhu (CHCTR),d2
- btst CHCTR_DCEN,d2
- beq mn10300_local_dcache_flush_inv_range_end
-
- sub d0,d1,a0
- cmp MN10300_DCACHE_FLUSH_INV_BORDER,a0
- ble 1f
-
- movm (sp),[d2]
- bra mn10300_local_dcache_flush_inv
-1:
-
- 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_MASK,d1
-
- # write a request to flush and invalidate all instances of an address
- # from the cache
- mov DCACHE_PURGE(0,0),a0
- mov a1,d0
- and L1_CACHE_TAG_ENTRY,d0
- add d0,a0 # starting dcache purge control
- # reg address
-
- sub a1,d1
- lsr L1_CACHE_SHIFT,d1 # total number of entries to
- # examine
-
-mn10300_local_dcache_flush_inv_range_loop:
- mov a1,(L1_CACHE_WAYDISP*0,a0) # conditionally purge this line
- # in all ways
-
- add L1_CACHE_BYTES,a0
- add L1_CACHE_BYTES,a1
- and ~L1_CACHE_WAYDISP,a0 # make sure way stay on way 0
- add -1,d1
- bne mn10300_local_dcache_flush_inv_range_loop
-
-mn10300_local_dcache_flush_inv_range_end:
- ret [d2],4
- .size mn10300_local_dcache_flush_inv_page,.-mn10300_local_dcache_flush_inv_page
- .size mn10300_local_dcache_flush_inv_range,.-mn10300_local_dcache_flush_inv_range
- .size mn10300_local_dcache_flush_inv_range2,.-mn10300_local_dcache_flush_inv_range2
diff --git a/arch/mn10300/mm/cache-flush-icache.c b/arch/mn10300/mm/cache-flush-icache.c
deleted file mode 100644
index fdb1a9db20f0..000000000000
--- a/arch/mn10300/mm/cache-flush-icache.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/* Flush dcache and invalidate icache when the dcache is in writeback mode
- *
- * Copyright (C) 2010 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/module.h>
-#include <linux/mm.h>
-#include <asm/cacheflush.h>
-#include <asm/smp.h>
-#include "cache-smp.h"
-
-/**
- * flush_icache_page - Flush a page from the dcache and invalidate the icache
- * @vma: The VMA the page is part of.
- * @page: The page to be flushed.
- *
- * Write a page back from the dcache and invalidate the icache so that we can
- * run code from it that we've just written into it
- */
-void flush_icache_page(struct vm_area_struct *vma, struct page *page)
-{
- unsigned long start = page_to_phys(page);
- unsigned long flags;
-
- flags = smp_lock_cache();
-
- mn10300_local_dcache_flush_page(start);
- mn10300_local_icache_inv_page(start);
-
- smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start, start + PAGE_SIZE);
- smp_unlock_cache(flags);
-}
-EXPORT_SYMBOL(flush_icache_page);
-
-/**
- * flush_icache_page_range - Flush dcache and invalidate icache for part of a
- * single page
- * @start: The starting virtual address of the page part.
- * @end: The ending virtual address of the page part.
- *
- * Flush the dcache and invalidate the icache for part of a single page, as
- * determined by the virtual addresses given. The page must be in the paged
- * area.
- */
-static void flush_icache_page_range(unsigned long start, unsigned long end)
-{
- unsigned long addr, size, off;
- struct page *page;
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *ppte, pte;
-
- /* work out how much of the page to flush */
- off = start & ~PAGE_MASK;
- size = end - start;
-
- /* get the physical address the page is mapped to from the page
- * tables */
- pgd = pgd_offset(current->mm, start);
- if (!pgd || !pgd_val(*pgd))
- return;
-
- pud = pud_offset(pgd, start);
- if (!pud || !pud_val(*pud))
- return;
-
- pmd = pmd_offset(pud, start);
- if (!pmd || !pmd_val(*pmd))
- return;
-
- ppte = pte_offset_map(pmd, start);
- if (!ppte)
- return;
- pte = *ppte;
- pte_unmap(ppte);
-
- if (pte_none(pte))
- return;
-
- page = pte_page(pte);
- if (!page)
- return;
-
- addr = page_to_phys(page);
-
- /* flush the dcache and invalidate the icache coverage on that
- * region */
- mn10300_local_dcache_flush_range2(addr + off, size);
- mn10300_local_icache_inv_range2(addr + off, size);
- smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start, end);
-}
-
-/**
- * flush_icache_range - Globally flush dcache and invalidate icache for region
- * @start: The starting virtual address of the region.
- * @end: The ending virtual address of the region.
- *
- * This is used by the kernel to globally flush some code it has just written
- * from the dcache back to RAM and then to globally invalidate the icache over
- * that region so that that code can be run on all CPUs in the system.
- */
-void flush_icache_range(unsigned long start, unsigned long end)
-{
- unsigned long start_page, end_page;
- unsigned long flags;
-
- flags = smp_lock_cache();
-
- if (end > 0x80000000UL) {
- /* addresses above 0xa0000000 do not go through the cache */
- if (end > 0xa0000000UL) {
- end = 0xa0000000UL;
- if (start >= end)
- goto done;
- }
-
- /* kernel addresses between 0x80000000 and 0x9fffffff do not
- * require page tables, so we just map such addresses
- * directly */
- start_page = (start >= 0x80000000UL) ? start : 0x80000000UL;
- mn10300_local_dcache_flush_range(start_page, end);
- mn10300_local_icache_inv_range(start_page, end);
- smp_cache_call(SMP_IDCACHE_INV_FLUSH_RANGE, start_page, end);
- if (start_page == start)
- goto done;
- end = start_page;
- }
-
- start_page = start & PAGE_MASK;
- end_page = (end - 1) & PAGE_MASK;
-
- if (start_page == end_page) {
- /* the first and last bytes are on the same page */
- flush_icache_page_range(start, end);
- } else if (start_page + 1 == end_page) {
- /* split over two virtually contiguous pages */
- flush_icache_page_range(start, end_page);
- flush_icache_page_range(end_page, end);
- } else {
- /* more than 2 pages; just flush the entire cache */
- mn10300_dcache_flush();
- mn10300_icache_inv();
- smp_cache_call(SMP_IDCACHE_INV_FLUSH, 0, 0);
- }
-
-done:
- smp_unlock_cache(flags);
-}
-EXPORT_SYMBOL(flush_icache_range);
diff --git a/arch/mn10300/mm/cache-inv-by-reg.S b/arch/mn10300/mm/cache-inv-by-reg.S
deleted file mode 100644
index a60825b91e77..000000000000
--- a/arch/mn10300/mm/cache-inv-by-reg.S
+++ /dev/null
@@ -1,350 +0,0 @@
-/* MN10300 CPU cache invalidation routines, using automatic purge registers
- *
- * 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/page.h>
-#include <asm/cache.h>
-#include <asm/irqflags.h>
-#include <asm/cacheflush.h>
-#include "cache.inc"
-
-#define mn10300_local_dcache_inv_range_intr_interval \
- +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
-
-#if mn10300_local_dcache_inv_range_intr_interval > 0xff
-#error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
-#endif
-
- .am33_2
-
-#ifndef CONFIG_SMP
- .globl mn10300_icache_inv
- .globl mn10300_icache_inv_page
- .globl mn10300_icache_inv_range
- .globl mn10300_icache_inv_range2
- .globl mn10300_dcache_inv
- .globl mn10300_dcache_inv_page
- .globl mn10300_dcache_inv_range
- .globl mn10300_dcache_inv_range2
-
-mn10300_icache_inv = mn10300_local_icache_inv
-mn10300_icache_inv_page = mn10300_local_icache_inv_page
-mn10300_icache_inv_range = mn10300_local_icache_inv_range
-mn10300_icache_inv_range2 = mn10300_local_icache_inv_range2
-mn10300_dcache_inv = mn10300_local_dcache_inv
-mn10300_dcache_inv_page = mn10300_local_dcache_inv_page
-mn10300_dcache_inv_range = mn10300_local_dcache_inv_range
-mn10300_dcache_inv_range2 = mn10300_local_dcache_inv_range2
-
-#endif /* !CONFIG_SMP */
-
-###############################################################################
-#
-# void mn10300_local_icache_inv(void)
-# Invalidate the entire icache
-#
-###############################################################################
- ALIGN
- .globl mn10300_local_icache_inv
- .type mn10300_local_icache_inv,@function
-mn10300_local_icache_inv:
- mov CHCTR,a0
-
- movhu (a0),d0
- btst CHCTR_ICEN,d0
- beq mn10300_local_icache_inv_end
-
- invalidate_icache 1
-
-mn10300_local_icache_inv_end:
- ret [],0
- .size mn10300_local_icache_inv,.-mn10300_local_icache_inv
-
-###############################################################################
-#
-# void mn10300_local_dcache_inv(void)
-# Invalidate the entire dcache
-#
-###############################################################################
- ALIGN
- .globl mn10300_local_dcache_inv
- .type mn10300_local_dcache_inv,@function
-mn10300_local_dcache_inv:
- mov CHCTR,a0
-
- movhu (a0),d0
- btst CHCTR_DCEN,d0
- beq mn10300_local_dcache_inv_end
-
- invalidate_dcache 1
-
-mn10300_local_dcache_inv_end:
- ret [],0
- .size mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
-
-###############################################################################
-#
-# void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end)
-# void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size)
-# void mn10300_local_dcache_inv_page(unsigned long start)
-# Invalidate a range of addresses on a page in the dcache
-#
-###############################################################################
- ALIGN
- .globl mn10300_local_dcache_inv_page
- .globl mn10300_local_dcache_inv_range
- .globl mn10300_local_dcache_inv_range2
- .type mn10300_local_dcache_inv_page,@function
- .type mn10300_local_dcache_inv_range,@function
- .type mn10300_local_dcache_inv_range2,@function
-mn10300_local_dcache_inv_page:
- and ~(PAGE_SIZE-1),d0
- mov PAGE_SIZE,d1
-mn10300_local_dcache_inv_range2:
- add d0,d1
-mn10300_local_dcache_inv_range:
- # If we are in writeback mode we check the start and end alignments,
- # 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_TAG_MASK,d0
- bne 1f
- btst ~L1_CACHE_TAG_MASK,d1
- beq 2f
-1:
- bra mn10300_local_dcache_flush_inv_range
-2:
-#endif /* CONFIG_MN10300_CACHE_WBACK */
-
- movm [d2,d3,a2],(sp)
-
- mov CHCTR,a0
- movhu (a0),d2
- btst CHCTR_DCEN,d2
- beq mn10300_local_dcache_inv_range_end
-
- # round the addresses out to be full cachelines, unless we're in
- # writeback mode, in which case we would be in flush and invalidate by
- # now
-#ifndef CONFIG_MN10300_CACHE_WBACK
- and L1_CACHE_TAG_MASK,d0 # round start addr down
-
- mov L1_CACHE_BYTES-1,d2
- add d2,d1
- and L1_CACHE_TAG_MASK,d1 # round end addr up
-#endif /* !CONFIG_MN10300_CACHE_WBACK */
-
- sub d0,d1,d2 # calculate the total size
- mov d0,a2 # A2 = start address
- mov d1,a1 # A1 = end address
-
- LOCAL_CLI_SAVE(d3)
-
- mov DCPGCR,a0 # make sure the purger isn't busy
- setlb
- mov (a0),d0
- btst DCPGCR_DCPGBSY,d0
- lne
-
- # skip initial address alignment calculation if address is zero
- mov d2,d1
- cmp 0,a2
- beq 1f
-
-dcivloop:
- /* calculate alignsize
- *
- * alignsize = L1_CACHE_BYTES;
- * while (! start & alignsize) {
- * alignsize <<=1;
- * }
- * d1 = alignsize;
- */
- mov L1_CACHE_BYTES,d1
- lsr 1,d1
- setlb
- add d1,d1
- mov d1,d0
- and a2,d0
- leq
-
-1:
- /* calculate invsize
- *
- * if (totalsize > alignsize) {
- * invsize = alignsize;
- * } else {
- * invsize = totalsize;
- * tmp = 0x80000000;
- * while (! invsize & tmp) {
- * tmp >>= 1;
- * }
- * invsize = tmp;
- * }
- * d1 = invsize
- */
- cmp d2,d1
- bns 2f
- mov d2,d1
-
- mov 0x80000000,d0 # start from 31bit=1
- setlb
- lsr 1,d0
- mov d0,e0
- and d1,e0
- leq
- mov d0,d1
-
-2:
- /* set mask
- *
- * mask = ~(invsize-1);
- * DCPGMR = mask;
- */
- mov d1,d0
- add -1,d0
- not d0
- mov d0,(DCPGMR)
-
- # invalidate area
- mov a2,d0
- or DCPGCR_DCI,d0
- mov d0,(a0) # DCPGCR = (mask & start) | DCPGCR_DCI
-
- setlb # wait for the purge to complete
- mov (a0),d0
- btst DCPGCR_DCPGBSY,d0
- lne
-
- sub d1,d2 # decrease size remaining
- add d1,a2 # increase next start address
-
- /* check invalidating of end address
- *
- * a2 = a2 + invsize
- * if (a2 < end) {
- * goto dcivloop;
- * } */
- cmp a1,a2
- bns dcivloop
-
- LOCAL_IRQ_RESTORE(d3)
-
-mn10300_local_dcache_inv_range_end:
- ret [d2,d3,a2],12
- .size mn10300_local_dcache_inv_page,.-mn10300_local_dcache_inv_page
- .size mn10300_local_dcache_inv_range,.-mn10300_local_dcache_inv_range
- .size mn10300_local_dcache_inv_range2,.-mn10300_local_dcache_inv_range2
-
-###############################################################################
-#
-# void mn10300_local_icache_inv_page(unsigned long start)
-# void mn10300_local_icache_inv_range2(unsigned long start, unsigned long size)
-# void mn10300_local_icache_inv_range(unsigned long start, unsigned long end)
-# Invalidate a range of addresses on a page in the icache
-#
-###############################################################################
- ALIGN
- .globl mn10300_local_icache_inv_page
- .globl mn10300_local_icache_inv_range
- .globl mn10300_local_icache_inv_range2
- .type mn10300_local_icache_inv_page,@function
- .type mn10300_local_icache_inv_range,@function
- .type mn10300_local_icache_inv_range2,@function
-mn10300_local_icache_inv_page:
- and ~(PAGE_SIZE-1),d0
- mov PAGE_SIZE,d1
-mn10300_local_icache_inv_range2:
- add d0,d1
-mn10300_local_icache_inv_range:
- movm [d2,d3,a2],(sp)
-
- mov CHCTR,a0
- movhu (a0),d2
- btst CHCTR_ICEN,d2
- beq mn10300_local_icache_inv_range_reg_end
-
- /* calculate alignsize
- *
- * alignsize = L1_CACHE_BYTES;
- * for (i = (end - start - 1) / L1_CACHE_BYTES ; i > 0; i >>= 1) {
- * alignsize <<= 1;
- * }
- * d2 = alignsize;
- */
- mov L1_CACHE_BYTES,d2
- sub d0,d1,d3
- add -1,d3
- lsr L1_CACHE_SHIFT,d3
- beq 2f
-1:
- add d2,d2
- lsr 1,d3
- bne 1b
-2:
-
- /* a1 = end */
- mov d1,a1
-
- LOCAL_CLI_SAVE(d3)
-
- mov ICIVCR,a0
- /* wait for busy bit of area invalidation */
- setlb
- mov (a0),d1
- btst ICIVCR_ICIVBSY,d1
- lne
-
- /* set mask
- *
- * mask = ~(alignsize-1);
- * ICIVMR = mask;
- */
- mov d2,d1
- add -1,d1
- not d1
- mov d1,(ICIVMR)
- /* a2 = mask & start */
- and d1,d0,a2
-
-icivloop:
- /* area invalidate
- *
- * ICIVCR = (mask & start) | ICIVCR_ICI
- */
- mov a2,d0
- or ICIVCR_ICI,d0
- mov d0,(a0)
-
- /* wait for busy bit of area invalidation */
- setlb
- mov (a0),d1
- btst ICIVCR_ICIVBSY,d1
- lne
-
- /* check invalidating of end address
- *
- * a2 = a2 + alignsize
- * if (a2 < end) {
- * goto icivloop;
- * } */
- add d2,a2
- cmp a1,a2
- bns icivloop
-
- LOCAL_IRQ_RESTORE(d3)
-
-mn10300_local_icache_inv_range_reg_end:
- ret [d2,d3,a2],12
- .size mn10300_local_icache_inv_page,.-mn10300_local_icache_inv_page
- .size mn10300_local_icache_inv_range,.-mn10300_local_icache_inv_range
- .size mn10300_local_icache_inv_range2,.-mn10300_local_icache_inv_range2
diff --git a/arch/mn10300/mm/cache-inv-by-tag.S b/arch/mn10300/mm/cache-inv-by-tag.S
deleted file mode 100644
index ccedce9c144d..000000000000
--- a/arch/mn10300/mm/cache-inv-by-tag.S
+++ /dev/null
@@ -1,276 +0,0 @@
-/* MN10300 CPU core caching routines
- *
- * 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/page.h>
-#include <asm/cache.h>
-#include <asm/irqflags.h>
-#include <asm/cacheflush.h>
-#include "cache.inc"
-
-#define mn10300_local_dcache_inv_range_intr_interval \
- +((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
-
-#if mn10300_local_dcache_inv_range_intr_interval > 0xff
-#error MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL must be 8 or less
-#endif
-
- .am33_2
-
- .globl mn10300_local_icache_inv_page
- .globl mn10300_local_icache_inv_range
- .globl mn10300_local_icache_inv_range2
-
-mn10300_local_icache_inv_page = mn10300_local_icache_inv
-mn10300_local_icache_inv_range = mn10300_local_icache_inv
-mn10300_local_icache_inv_range2 = mn10300_local_icache_inv
-
-#ifndef CONFIG_SMP
- .globl mn10300_icache_inv
- .globl mn10300_icache_inv_page
- .globl mn10300_icache_inv_range
- .globl mn10300_icache_inv_range2
- .globl mn10300_dcache_inv
- .globl mn10300_dcache_inv_page
- .globl mn10300_dcache_inv_range
- .globl mn10300_dcache_inv_range2
-
-mn10300_icache_inv = mn10300_local_icache_inv
-mn10300_icache_inv_page = mn10300_local_icache_inv_page
-mn10300_icache_inv_range = mn10300_local_icache_inv_range
-mn10300_icache_inv_range2 = mn10300_local_icache_inv_range2
-mn10300_dcache_inv = mn10300_local_dcache_inv
-mn10300_dcache_inv_page = mn10300_local_dcache_inv_page
-mn10300_dcache_inv_range = mn10300_local_dcache_inv_range
-mn10300_dcache_inv_range2 = mn10300_local_dcache_inv_range2
-
-#endif /* !CONFIG_SMP */
-
-###############################################################################
-#
-# void mn10300_local_icache_inv(void)
-# Invalidate the entire icache
-#
-###############################################################################
- ALIGN
- .globl mn10300_local_icache_inv
- .type mn10300_local_icache_inv,@function
-mn10300_local_icache_inv:
- mov CHCTR,a0
-
- movhu (a0),d0
- btst CHCTR_ICEN,d0
- beq mn10300_local_icache_inv_end
-
- invalidate_icache 1
-
-mn10300_local_icache_inv_end:
- ret [],0
- .size mn10300_local_icache_inv,.-mn10300_local_icache_inv
-
-###############################################################################
-#
-# void mn10300_local_dcache_inv(void)
-# Invalidate the entire dcache
-#
-###############################################################################
- ALIGN
- .globl mn10300_local_dcache_inv
- .type mn10300_local_dcache_inv,@function
-mn10300_local_dcache_inv:
- mov CHCTR,a0
-
- movhu (a0),d0
- btst CHCTR_DCEN,d0
- beq mn10300_local_dcache_inv_end
-
- invalidate_dcache 1
-
-mn10300_local_dcache_inv_end:
- ret [],0
- .size mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
-
-###############################################################################
-#
-# void mn10300_local_dcache_inv_range(unsigned long start, unsigned long end)
-# void mn10300_local_dcache_inv_range2(unsigned long start, unsigned long size)
-# void mn10300_local_dcache_inv_page(unsigned long start)
-# Invalidate a range of addresses on a page in the dcache
-#
-###############################################################################
- ALIGN
- .globl mn10300_local_dcache_inv_page
- .globl mn10300_local_dcache_inv_range
- .globl mn10300_local_dcache_inv_range2
- .type mn10300_local_dcache_inv_page,@function
- .type mn10300_local_dcache_inv_range,@function
- .type mn10300_local_dcache_inv_range2,@function
-mn10300_local_dcache_inv_page:
- and ~(PAGE_SIZE-1),d0
- mov PAGE_SIZE,d1
-mn10300_local_dcache_inv_range2:
- add d0,d1
-mn10300_local_dcache_inv_range:
- # If we are in writeback mode we check the start and end alignments,
- # 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_TAG_MASK,d0
- bne 1f
- btst ~L1_CACHE_TAG_MASK,d1
- beq 2f
-1:
- bra mn10300_local_dcache_flush_inv_range
-2:
-#endif /* CONFIG_MN10300_CACHE_WBACK */
-
- movm [d2,d3,a2],(sp)
-
- mov CHCTR,a2
- movhu (a2),d2
- btst CHCTR_DCEN,d2
- beq mn10300_local_dcache_inv_range_end
-
-#ifndef CONFIG_MN10300_CACHE_WBACK
- and L1_CACHE_TAG_MASK,d0 # round start addr down
-
- add L1_CACHE_BYTES,d1 # round end addr up
- and L1_CACHE_TAG_MASK,d1
-#endif /* !CONFIG_MN10300_CACHE_WBACK */
- mov d0,a1
-
- clr d2 # we're going to clear tag RAM
- # entries
-
- # read the tags from the tag RAM, and if they indicate a valid dirty
- # cache line then invalidate that line
- mov DCACHE_TAG(0,0),a0
- mov a1,d0
- and L1_CACHE_TAG_ENTRY,d0
- add d0,a0 # starting dcache tag RAM
- # access address
-
- sub a1,d1
- lsr L1_CACHE_SHIFT,d1 # total number of entries to
- # examine
-
- and ~(L1_CACHE_DISPARITY-1),a1 # determine comparator base
-
-mn10300_local_dcache_inv_range_outer_loop:
- LOCAL_CLI_SAVE(d3)
-
- # disable the dcache
- movhu (a2),d0
- and ~CHCTR_DCEN,d0
- movhu d0,(a2)
-
- # and wait for it to calm down
- setlb
- movhu (a2),d0
- btst CHCTR_DCBUSY,d0
- lne
-
-mn10300_local_dcache_inv_range_loop:
-
- # process the way 0 slot
- mov (L1_CACHE_WAYDISP*0,a0),d0 # read the tag in the way 0 slot
- btst L1_CACHE_TAG_VALID,d0
- beq mn10300_local_dcache_inv_range_skip_0 # jump if this cacheline
- # is not valid
-
- xor a1,d0
- lsr 12,d0
- bne mn10300_local_dcache_inv_range_skip_0 # jump if not this cacheline
-
- mov d2,(L1_CACHE_WAYDISP*0,a0) # kill the tag
-
-mn10300_local_dcache_inv_range_skip_0:
-
- # process the way 1 slot
- mov (L1_CACHE_WAYDISP*1,a0),d0 # read the tag in the way 1 slot
- btst L1_CACHE_TAG_VALID,d0
- beq mn10300_local_dcache_inv_range_skip_1 # jump if this cacheline
- # is not valid
-
- xor a1,d0
- lsr 12,d0
- bne mn10300_local_dcache_inv_range_skip_1 # jump if not this cacheline
-
- mov d2,(L1_CACHE_WAYDISP*1,a0) # kill the tag
-
-mn10300_local_dcache_inv_range_skip_1:
-
- # process the way 2 slot
- mov (L1_CACHE_WAYDISP*2,a0),d0 # read the tag in the way 2 slot
- btst L1_CACHE_TAG_VALID,d0
- beq mn10300_local_dcache_inv_range_skip_2 # jump if this cacheline
- # is not valid
-
- xor a1,d0
- lsr 12,d0
- bne mn10300_local_dcache_inv_range_skip_2 # jump if not this cacheline
-
- mov d2,(L1_CACHE_WAYDISP*2,a0) # kill the tag
-
-mn10300_local_dcache_inv_range_skip_2:
-
- # process the way 3 slot
- mov (L1_CACHE_WAYDISP*3,a0),d0 # read the tag in the way 3 slot
- btst L1_CACHE_TAG_VALID,d0
- beq mn10300_local_dcache_inv_range_skip_3 # jump if this cacheline
- # is not valid
-
- xor a1,d0
- lsr 12,d0
- bne mn10300_local_dcache_inv_range_skip_3 # jump if not this cacheline
-
- mov d2,(L1_CACHE_WAYDISP*3,a0) # kill the tag
-
-mn10300_local_dcache_inv_range_skip_3:
-
- # approx every N steps we re-enable the cache and see if there are any
- # interrupts to be processed
- # we also break out if we've reached the end of the loop
- # (the bottom nibble of the count is zero in both cases)
- add L1_CACHE_BYTES,a0
- add L1_CACHE_BYTES,a1
- and ~L1_CACHE_WAYDISP,a0
- add -1,d1
- btst mn10300_local_dcache_inv_range_intr_interval,d1
- bne mn10300_local_dcache_inv_range_loop
-
- # wait for the cache to finish what it's doing
- setlb
- movhu (a2),d0
- btst CHCTR_DCBUSY,d0
- lne
-
- # and reenable it
- or CHCTR_DCEN,d0
- movhu d0,(a2)
- movhu (a2),d0
-
- # re-enable interrupts
- # - we don't bother with delay NOPs as we'll have enough instructions
- # before we disable interrupts again to give the interrupts a chance
- # to happen
- LOCAL_IRQ_RESTORE(d3)
-
- # go around again if the counter hasn't yet reached zero
- add 0,d1
- bne mn10300_local_dcache_inv_range_outer_loop
-
-mn10300_local_dcache_inv_range_end:
- ret [d2,d3,a2],12
- .size mn10300_local_dcache_inv_page,.-mn10300_local_dcache_inv_page
- .size mn10300_local_dcache_inv_range,.-mn10300_local_dcache_inv_range
- .size mn10300_local_dcache_inv_range2,.-mn10300_local_dcache_inv_range2
diff --git a/arch/mn10300/mm/cache-inv-icache.c b/arch/mn10300/mm/cache-inv-icache.c
deleted file mode 100644
index a6b63dde603d..000000000000
--- a/arch/mn10300/mm/cache-inv-icache.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/* Invalidate icache when dcache doesn't need invalidation as it's in
- * write-through mode
- *
- * Copyright (C) 2010 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/module.h>
-#include <linux/mm.h>
-#include <asm/cacheflush.h>
-#include <asm/smp.h>
-#include "cache-smp.h"
-
-/**
- * flush_icache_page_range - Flush dcache and invalidate icache for part of a
- * single page
- * @start: The starting virtual address of the page part.
- * @end: The ending virtual address of the page part.
- *
- * Invalidate the icache for part of a single page, as determined by the
- * virtual addresses given. The page must be in the paged area. The dcache is
- * not flushed as the cache must be in write-through mode to get here.
- */
-static void flush_icache_page_range(unsigned long start, unsigned long end)
-{
- unsigned long addr, size, off;
- struct page *page;
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- pte_t *ppte, pte;
-
- /* work out how much of the page to flush */
- off = start & ~PAGE_MASK;
- size = end - start;
-
- /* get the physical address the page is mapped to from the page
- * tables */
- pgd = pgd_offset(current->mm, start);
- if (!pgd || !pgd_val(*pgd))
- return;
-
- pud = pud_offset(pgd, start);
- if (!pud || !pud_val(*pud))
- return;
-
- pmd = pmd_offset(pud, start);
- if (!pmd || !pmd_val(*pmd))
- return;
-
- ppte = pte_offset_map(pmd, start);
- if (!ppte)
- return;
- pte = *ppte;
- pte_unmap(ppte);
-
- if (pte_none(pte))
- return;
-
- page = pte_page(pte);
- if (!page)
- return;
-
- addr = page_to_phys(page);
-
- /* invalidate the icache coverage on that region */
- mn10300_local_icache_inv_range2(addr + off, size);
- smp_cache_call(SMP_ICACHE_INV_RANGE, start, end);
-}
-
-/**
- * flush_icache_range - Globally flush dcache and invalidate icache for region
- * @start: The starting virtual address of the region.
- * @end: The ending virtual address of the region.
- *
- * This is used by the kernel to globally flush some code it has just written
- * from the dcache back to RAM and then to globally invalidate the icache over
- * that region so that that code can be run on all CPUs in the system.
- */
-void flush_icache_range(unsigned long start, unsigned long end)
-{
- unsigned long start_page, end_page;
- unsigned long flags;
-
- flags = smp_lock_cache();
-
- if (end > 0x80000000UL) {
- /* addresses above 0xa0000000 do not go through the cache */
- if (end > 0xa0000000UL) {
- end = 0xa0000000UL;
- if (start >= end)
- goto done;
- }
-
- /* kernel addresses between 0x80000000 and 0x9fffffff do not
- * require page tables, so we just map such addresses
- * directly */
- start_page = (start >= 0x80000000UL) ? start : 0x80000000UL;
- mn10300_icache_inv_range(start_page, end);
- smp_cache_call(SMP_ICACHE_INV_RANGE, start, end);
- if (start_page == start)
- goto done;
- end = start_page;
- }
-
- start_page = start & PAGE_MASK;
- end_page = (end - 1) & PAGE_MASK;
-
- if (start_page == end_page) {
- /* the first and last bytes are on the same page */
- flush_icache_page_range(start, end);
- } else if (start_page + 1 == end_page) {
- /* split over two virtually contiguous pages */
- flush_icache_page_range(start, end_page);
- flush_icache_page_range(end_page, end);
- } else {
- /* more than 2 pages; just flush the entire cache */
- mn10300_local_icache_inv();
- smp_cache_call(SMP_ICACHE_INV, 0, 0);
- }
-
-done:
- smp_unlock_cache(flags);
-}
-EXPORT_SYMBOL(flush_icache_range);
diff --git a/arch/mn10300/mm/cache-smp-flush.c b/arch/mn10300/mm/cache-smp-flush.c
deleted file mode 100644
index fd51af5eaf70..000000000000
--- a/arch/mn10300/mm/cache-smp-flush.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/* Functions for global dcache flush when writeback caching in SMP
- *
- * Copyright (C) 2010 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/mm.h>
-#include <asm/cacheflush.h>
-#include "cache-smp.h"
-
-/**
- * mn10300_dcache_flush - Globally flush data cache
- *
- * Flush the data cache on all CPUs.
- */
-void mn10300_dcache_flush(void)
-{
- unsigned long flags;
-
- flags = smp_lock_cache();
- mn10300_local_dcache_flush();
- smp_cache_call(SMP_DCACHE_FLUSH, 0, 0);
- smp_unlock_cache(flags);
-}
-
-/**
- * mn10300_dcache_flush_page - Globally flush a page of data cache
- * @start: The address of the page of memory to be flushed.
- *
- * Flush a range of addresses in the data cache on all CPUs covering
- * the page that includes the given address.
- */
-void mn10300_dcache_flush_page(unsigned long start)
-{
- unsigned long flags;
-
- start &= ~(PAGE_SIZE-1);
-
- flags = smp_lock_cache();
- mn10300_local_dcache_flush_page(start);
- smp_cache_call(SMP_DCACHE_FLUSH_RANGE, start, start + PAGE_SIZE);
- smp_unlock_cache(flags);
-}
-
-/**
- * mn10300_dcache_flush_range - Globally flush range of data cache
- * @start: The start address of the region to be flushed.
- * @end: The end address of the region to be flushed.
- *
- * Flush a range of addresses in the data cache on all CPUs, between start and
- * end-1 inclusive.
- */
-void mn10300_dcache_flush_range(unsigned long start, unsigned long end)
-{
- unsigned long flags;
-
- flags = smp_lock_cache();
- mn10300_local_dcache_flush_range(start, end);
- smp_cache_call(SMP_DCACHE_FLUSH_RANGE, start, end);
- smp_unlock_cache(flags);
-}
-
-/**
- * mn10300_dcache_flush_range2 - Globally flush range of data cache
- * @start: The start address of the region to be flushed.
- * @size: The size of the region to be flushed.
- *
- * Flush a range of addresses in the data cache on all CPUs, between start and
- * start+size-1 inclusive.
- */
-void mn10300_dcache_flush_range2(unsigned long start, unsigned long size)
-{
- unsigned long flags;
-
- flags = smp_lock_cache();
- mn10300_local_dcache_flush_range2(start, size);
- smp_cache_call(SMP_DCACHE_FLUSH_RANGE, start, start + size);
- smp_unlock_cache(flags);
-}
-
-/**
- * mn10300_dcache_flush_inv - Globally flush and invalidate data cache
- *
- * Flush and invalidate the data cache on all CPUs.
- */
-void mn10300_dcache_flush_inv(void)
-{
- unsigned long flags;
-
- flags = smp_lock_cache();
- mn10300_local_dcache_flush_inv();
- smp_cache_call(SMP_DCACHE_FLUSH_INV, 0, 0);
- smp_unlock_cache(flags);
-}
-
-/**
- * mn10300_dcache_flush_inv_page - Globally flush and invalidate a page of data
- * cache
- * @start: The address of the page of memory to be flushed and invalidated.
- *
- * Flush and invalidate a range of addresses in the data cache on all CPUs
- * covering the page that includes the given address.
- */
-void mn10300_dcache_flush_inv_page(unsigned long start)
-{
- unsigned long flags;
-
- start &= ~(PAGE_SIZE-1);
-
- flags = smp_lock_cache();
- mn10300_local_dcache_flush_inv_page(start);
- smp_cache_call(SMP_DCACHE_FLUSH_INV_RANGE, start, start + PAGE_SIZE);
- smp_unlock_cache(flags);
-}
-
-/**
- * mn10300_dcache_flush_inv_range - Globally flush and invalidate range of data
- * cache
- * @start: The start address of the region to be flushed and invalidated.
- * @end: The end address of the region to be flushed and invalidated.
- *
- * Flush and invalidate a range of addresses in the data cache on all CPUs,
- * between start and end-1 inclusive.
- */
-void mn10300_dcache_flush_inv_range(unsigned long start, unsigned long end)
-{
- unsigned long flags;
-
- flags = smp_lock_cache();
- mn10300_local_dcache_flush_inv_range(start, end);
- smp_cache_call(SMP_DCACHE_FLUSH_INV_RANGE, start, end);
- smp_unlock_cache(flags);
-}
-
-/**
- * mn10300_dcache_flush_inv_range2 - Globally flush and invalidate range of data
- * cache
- * @start: The start address of the region to be flushed and invalidated.
- * @size: The size of the region to be flushed and invalidated.
- *
- * Flush and invalidate a range of addresses in the data cache on all CPUs,
- * between start and start+size-1 inclusive.
- */
-void mn10300_dcache_flush_inv_range2(unsigned long start, unsigned long size)
-{
- unsigned long flags;
-
- flags = smp_lock_cache();
- mn10300_local_dcache_flush_inv_range2(start, size);
- smp_cache_call(SMP_DCACHE_FLUSH_INV_RANGE, start, start + size);
- smp_unlock_cache(flags);
-}
diff --git a/arch/mn10300/mm/cache-smp-inv.c b/arch/mn10300/mm/cache-smp-inv.c
deleted file mode 100644
index ff1787358c8e..000000000000
--- a/arch/mn10300/mm/cache-smp-inv.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/* Functions for global i/dcache invalidation when caching in SMP
- *
- * Copyright (C) 2010 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/mm.h>
-#include <asm/cacheflush.h>
-#include "cache-smp.h"
-
-/**
- * mn10300_icache_inv - Globally invalidate instruction cache
- *
- * Invalidate the instruction cache on all CPUs.
- */
-void mn10300_icache_inv(void)
-{
- unsigned long flags;
-
- flags = smp_lock_cache();
- mn10300_local_icache_inv();
- smp_cache_call(SMP_ICACHE_INV, 0, 0);
- smp_unlock_cache(flags);
-}
-
-/**
- * mn10300_icache_inv_page - Globally invalidate a page of instruction cache
- * @start: The address of the page of memory to be invalidated.
- *
- * Invalidate a range of addresses in the instruction cache on all CPUs
- * covering the page that includes the given address.
- */
-void mn10300_icache_inv_page(unsigned long start)
-{
- unsigned long flags;
-
- start &= ~(PAGE_SIZE-1);
-
- flags = smp_lock_cache();
- mn10300_local_icache_inv_page(start);
- smp_cache_call(SMP_ICACHE_INV_RANGE, start, start + PAGE_SIZE);
- smp_unlock_cache(flags);
-}
-
-/**
- * mn10300_icache_inv_range - Globally invalidate range of instruction cache
- * @start: The start address of the region to be invalidated.
- * @end: The end address of the region to be invalidated.
- *
- * Invalidate a range of addresses in the instruction cache on all CPUs,
- * between start and end-1 inclusive.
- */
-void mn10300_icache_inv_range(unsigned long start, unsigned long end)
-{
- unsigned long flags;
-
- flags = smp_lock_cache();
- mn10300_local_icache_inv_range(start, end);
- smp_cache_call(SMP_ICACHE_INV_RANGE, start, end);
- smp_unlock_cache(flags);
-}
-
-/**
- * mn10300_icache_inv_range2 - Globally invalidate range of instruction cache
- * @start: The start address of the region to be invalidated.
- * @size: The size of the region to be invalidated.
- *
- * Invalidate a range of addresses in the instruction cache on all CPUs,
- * between start and start+size-1 inclusive.
- */
-void mn10300_icache_inv_range2(unsigned long start, unsigned long size)
-{
- unsigned long flags;
-
- flags = smp_lock_cache();
- mn10300_local_icache_inv_range2(start, size);
- smp_cache_call(SMP_ICACHE_INV_RANGE, start, start + size);
- smp_unlock_cache(flags);
-}
-
-/**
- * mn10300_dcache_inv - Globally invalidate data cache
- *
- * Invalidate the data cache on all CPUs.
- */
-void mn10300_dcache_inv(void)
-{
- unsigned long flags;
-
- flags = smp_lock_cache();
- mn10300_local_dcache_inv();
- smp_cache_call(SMP_DCACHE_INV, 0, 0);
- smp_unlock_cache(flags);
-}
-
-/**
- * mn10300_dcache_inv_page - Globally invalidate a page of data cache
- * @start: The address of the page of memory to be invalidated.
- *
- * Invalidate a range of addresses in the data cache on all CPUs covering the
- * page that includes the given address.
- */
-void mn10300_dcache_inv_page(unsigned long start)
-{
- unsigned long flags;
-
- start &= ~(PAGE_SIZE-1);
-
- flags = smp_lock_cache();
- mn10300_local_dcache_inv_page(start);
- smp_cache_call(SMP_DCACHE_INV_RANGE, start, start + PAGE_SIZE);
- smp_unlock_cache(flags);
-}
-
-/**
- * mn10300_dcache_inv_range - Globally invalidate range of data cache
- * @start: The start address of the region to be invalidated.
- * @end: The end address of the region to be invalidated.
- *
- * Invalidate a range of addresses in the data cache on all CPUs, between start
- * and end-1 inclusive.
- */
-void mn10300_dcache_inv_range(unsigned long start, unsigned long end)
-{
- unsigned long flags;
-
- flags = smp_lock_cache();
- mn10300_local_dcache_inv_range(start, end);
- smp_cache_call(SMP_DCACHE_INV_RANGE, start, end);
- smp_unlock_cache(flags);
-}
-
-/**
- * mn10300_dcache_inv_range2 - Globally invalidate range of data cache
- * @start: The start address of the region to be invalidated.
- * @size: The size of the region to be invalidated.
- *
- * Invalidate a range of addresses in the data cache on all CPUs, between start
- * and start+size-1 inclusive.
- */
-void mn10300_dcache_inv_range2(unsigned long start, unsigned long size)
-{
- unsigned long flags;
-
- flags = smp_lock_cache();
- mn10300_local_dcache_inv_range2(start, size);
- smp_cache_call(SMP_DCACHE_INV_RANGE, start, start + size);
- smp_unlock_cache(flags);
-}
diff --git a/arch/mn10300/mm/cache-smp.c b/arch/mn10300/mm/cache-smp.c
deleted file mode 100644
index e80996064d3d..000000000000
--- a/arch/mn10300/mm/cache-smp.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/* SMP global caching code
- *
- * Copyright (C) 2010 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/module.h>
-#include <linux/mm.h>
-#include <linux/mman.h>
-#include <linux/threads.h>
-#include <linux/interrupt.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/cacheflush.h>
-#include <asm/io.h>
-#include <linux/uaccess.h>
-#include <asm/smp.h>
-#include "cache-smp.h"
-
-DEFINE_SPINLOCK(smp_cache_lock);
-static unsigned long smp_cache_mask;
-static unsigned long smp_cache_start;
-static unsigned long smp_cache_end;
-static cpumask_t smp_cache_ipi_map; /* Bitmask of cache IPI done CPUs */
-
-/**
- * smp_cache_interrupt - Handle IPI request to flush caches.
- *
- * Handle a request delivered by IPI to flush the current CPU's
- * caches. The parameters are stored in smp_cache_*.
- */
-void smp_cache_interrupt(void)
-{
- unsigned long opr_mask = smp_cache_mask;
-
- switch ((enum smp_dcache_ops)(opr_mask & SMP_DCACHE_OP_MASK)) {
- case SMP_DCACHE_NOP:
- break;
- case SMP_DCACHE_INV:
- mn10300_local_dcache_inv();
- break;
- case SMP_DCACHE_INV_RANGE:
- mn10300_local_dcache_inv_range(smp_cache_start, smp_cache_end);
- break;
- case SMP_DCACHE_FLUSH:
- mn10300_local_dcache_flush();
- break;
- case SMP_DCACHE_FLUSH_RANGE:
- mn10300_local_dcache_flush_range(smp_cache_start,
- smp_cache_end);
- break;
- case SMP_DCACHE_FLUSH_INV:
- mn10300_local_dcache_flush_inv();
- break;
- case SMP_DCACHE_FLUSH_INV_RANGE:
- mn10300_local_dcache_flush_inv_range(smp_cache_start,
- smp_cache_end);
- break;
- }
-
- switch ((enum smp_icache_ops)(opr_mask & SMP_ICACHE_OP_MASK)) {
- case SMP_ICACHE_NOP:
- break;
- case SMP_ICACHE_INV:
- mn10300_local_icache_inv();
- break;
- case SMP_ICACHE_INV_RANGE:
- mn10300_local_icache_inv_range(smp_cache_start, smp_cache_end);
- break;
- }
-
- cpumask_clear_cpu(smp_processor_id(), &smp_cache_ipi_map);
-}
-
-/**
- * smp_cache_call - Issue an IPI to request the other CPUs flush caches
- * @opr_mask: Cache operation flags
- * @start: Start address of request
- * @end: End address of request
- *
- * Send cache flush IPI to other CPUs. This invokes smp_cache_interrupt()
- * above on those other CPUs and then waits for them to finish.
- *
- * The caller must hold smp_cache_lock.
- */
-void smp_cache_call(unsigned long opr_mask,
- unsigned long start, unsigned long end)
-{
- smp_cache_mask = opr_mask;
- smp_cache_start = start;
- smp_cache_end = end;
- cpumask_copy(&smp_cache_ipi_map, cpu_online_mask);
- cpumask_clear_cpu(smp_processor_id(), &smp_cache_ipi_map);
-
- send_IPI_allbutself(FLUSH_CACHE_IPI);
-
- while (!cpumask_empty(&smp_cache_ipi_map))
- /* nothing. lockup detection does not belong here */
- mb();
-}
diff --git a/arch/mn10300/mm/cache-smp.h b/arch/mn10300/mm/cache-smp.h
deleted file mode 100644
index cb52892aa66a..000000000000
--- a/arch/mn10300/mm/cache-smp.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* SMP caching definitions
- *
- * Copyright (C) 2010 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.
- */
-
-
-/*
- * Operation requests for smp_cache_call().
- *
- * One of smp_icache_ops and one of smp_dcache_ops can be OR'd together.
- */
-enum smp_icache_ops {
- SMP_ICACHE_NOP = 0x0000,
- SMP_ICACHE_INV = 0x0001,
- SMP_ICACHE_INV_RANGE = 0x0002,
-};
-#define SMP_ICACHE_OP_MASK 0x0003
-
-enum smp_dcache_ops {
- SMP_DCACHE_NOP = 0x0000,
- SMP_DCACHE_INV = 0x0004,
- SMP_DCACHE_INV_RANGE = 0x0008,
- SMP_DCACHE_FLUSH = 0x000c,
- SMP_DCACHE_FLUSH_RANGE = 0x0010,
- SMP_DCACHE_FLUSH_INV = 0x0014,
- SMP_DCACHE_FLUSH_INV_RANGE = 0x0018,
-};
-#define SMP_DCACHE_OP_MASK 0x001c
-
-#define SMP_IDCACHE_INV_FLUSH (SMP_ICACHE_INV | SMP_DCACHE_FLUSH)
-#define SMP_IDCACHE_INV_FLUSH_RANGE (SMP_ICACHE_INV_RANGE | SMP_DCACHE_FLUSH_RANGE)
-
-/*
- * cache-smp.c
- */
-#ifdef CONFIG_SMP
-extern spinlock_t smp_cache_lock;
-
-extern void smp_cache_call(unsigned long opr_mask,
- unsigned long addr, unsigned long end);
-
-static inline unsigned long smp_lock_cache(void)
- __acquires(&smp_cache_lock)
-{
- unsigned long flags;
- spin_lock_irqsave(&smp_cache_lock, flags);
- return flags;
-}
-
-static inline void smp_unlock_cache(unsigned long flags)
- __releases(&smp_cache_lock)
-{
- spin_unlock_irqrestore(&smp_cache_lock, flags);
-}
-
-#else
-static inline unsigned long smp_lock_cache(void) { return 0; }
-static inline void smp_unlock_cache(unsigned long flags) {}
-static inline void smp_cache_call(unsigned long opr_mask,
- unsigned long addr, unsigned long end)
-{
-}
-#endif /* CONFIG_SMP */
diff --git a/arch/mn10300/mm/cache.c b/arch/mn10300/mm/cache.c
deleted file mode 100644
index 0b925cce2b83..000000000000
--- a/arch/mn10300/mm/cache.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* MN10300 Cache flushing routines
- *
- * 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/module.h>
-#include <linux/mm.h>
-#include <linux/mman.h>
-#include <linux/threads.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/cacheflush.h>
-#include <asm/io.h>
-#include <linux/uaccess.h>
-#include <asm/smp.h>
-#include "cache-smp.h"
-
-EXPORT_SYMBOL(mn10300_icache_inv);
-EXPORT_SYMBOL(mn10300_icache_inv_range);
-EXPORT_SYMBOL(mn10300_icache_inv_range2);
-EXPORT_SYMBOL(mn10300_icache_inv_page);
-EXPORT_SYMBOL(mn10300_dcache_inv);
-EXPORT_SYMBOL(mn10300_dcache_inv_range);
-EXPORT_SYMBOL(mn10300_dcache_inv_range2);
-EXPORT_SYMBOL(mn10300_dcache_inv_page);
-
-#ifdef CONFIG_MN10300_CACHE_WBACK
-EXPORT_SYMBOL(mn10300_dcache_flush);
-EXPORT_SYMBOL(mn10300_dcache_flush_inv);
-EXPORT_SYMBOL(mn10300_dcache_flush_inv_range);
-EXPORT_SYMBOL(mn10300_dcache_flush_inv_range2);
-EXPORT_SYMBOL(mn10300_dcache_flush_inv_page);
-EXPORT_SYMBOL(mn10300_dcache_flush_range);
-EXPORT_SYMBOL(mn10300_dcache_flush_range2);
-EXPORT_SYMBOL(mn10300_dcache_flush_page);
-#endif
-
-/*
- * allow userspace to flush the instruction cache
- */
-asmlinkage long sys_cacheflush(unsigned long start, unsigned long end)
-{
- if (end < start)
- return -EINVAL;
-
- flush_icache_range(start, end);
- return 0;
-}
diff --git a/arch/mn10300/mm/cache.inc b/arch/mn10300/mm/cache.inc
deleted file mode 100644
index 394a119b9c73..000000000000
--- a/arch/mn10300/mm/cache.inc
+++ /dev/null
@@ -1,133 +0,0 @@
-/* MN10300 CPU core caching macros -*- asm -*-
- *
- * 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.
- */
-
-
-###############################################################################
-#
-# Invalidate the instruction cache.
-# A0: Should hold CHCTR
-# D0: Should have been read from CHCTR
-# D1: Will be clobbered
-#
-# On some cores it is necessary to disable the icache whilst we do this.
-#
-###############################################################################
- .macro invalidate_icache,disable_irq
-
-#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
- .if \disable_irq
- # don't want an interrupt routine seeing a disabled cache
- mov epsw,d1
- and ~EPSW_IE,epsw
- or EPSW_NMID,epsw
- nop
- nop
- .endif
-
- # 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
- setlb
- movhu (a0),d0
- btst CHCTR_ICBUSY,d0
- lne
-
- # and reenable it
- or CHCTR_ICEN,d0
- movhu d0,(a0)
- movhu (a0),d0
-
- .if \disable_irq
- LOCAL_IRQ_RESTORE(d1)
- .endif
-
-#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
-
- # invalidate
- or CHCTR_ICINV,d0
- movhu d0,(a0)
- movhu (a0),d0
-
-#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
- .endm
-
-###############################################################################
-#
-# Invalidate the data cache.
-# A0: Should hold CHCTR
-# D0: Should have been read from CHCTR
-# D1: Will be clobbered
-#
-# On some cores it is necessary to disable the dcache whilst we do this.
-#
-###############################################################################
- .macro invalidate_dcache,disable_irq
-
-#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
- .if \disable_irq
- # don't want an interrupt routine seeing a disabled cache
- mov epsw,d1
- and ~EPSW_IE,epsw
- or EPSW_NMID,epsw
- nop
- nop
- .endif
-
- # disable the dcache
- and ~CHCTR_DCEN,d0
- movhu d0,(a0)
-
- # and wait for it to calm down
- setlb
- movhu (a0),d0
- btst CHCTR_DCBUSY,d0
- lne
-
- # invalidate
- or CHCTR_DCINV,d0
- movhu d0,(a0)
-
- # wait for the cache to finish
- setlb
- movhu (a0),d0
- btst CHCTR_DCBUSY,d0
- lne
-
- # and reenable it
- or CHCTR_DCEN,d0
- movhu d0,(a0)
- movhu (a0),d0
-
- .if \disable_irq
- LOCAL_IRQ_RESTORE(d1)
- .endif
-
-#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
-
- # invalidate
- or CHCTR_DCINV,d0
- movhu d0,(a0)
- movhu (a0),d0
-
-#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
- .endm
diff --git a/arch/mn10300/mm/dma-alloc.c b/arch/mn10300/mm/dma-alloc.c
deleted file mode 100644
index e3910d4db102..000000000000
--- a/arch/mn10300/mm/dma-alloc.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* MN10300 Dynamic DMA mapping support
- *
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Written by David Howells (dhowells@redhat.com)
- * Derived from: arch/i386/kernel/pci-dma.c
- *
- * 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/types.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <linux/gfp.h>
-#include <linux/export.h>
-#include <asm/io.h>
-
-static unsigned long pci_sram_allocated = 0xbc000000;
-
-static void *mn10300_dma_alloc(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
-{
- unsigned long addr;
- void *ret;
-
- pr_debug("dma_alloc_coherent(%s,%zu,%x)\n",
- dev ? dev_name(dev) : "?", size, gfp);
-
- if (0xbe000000 - pci_sram_allocated >= size) {
- size = (size + 255) & ~255;
- addr = pci_sram_allocated;
- pci_sram_allocated += size;
- ret = (void *) addr;
- goto done;
- }
-
- if (dev == NULL || dev->coherent_dma_mask < 0xffffffff)
- gfp |= GFP_DMA;
-
- addr = __get_free_pages(gfp, get_order(size));
- if (!addr)
- return NULL;
-
- /* map the coherent memory through the uncached memory window */
- ret = (void *) (addr | 0x20000000);
-
- /* fill the memory with obvious rubbish */
- memset((void *) addr, 0xfb, size);
-
- /* write back and evict all cache lines covering this region */
- mn10300_dcache_flush_inv_range2(virt_to_phys((void *) addr), PAGE_SIZE);
-
-done:
- *dma_handle = virt_to_bus((void *) addr);
- printk("dma_alloc_coherent() = %p [%x]\n", ret, *dma_handle);
- return ret;
-}
-
-static void mn10300_dma_free(struct device *dev, size_t size, void *vaddr,
- dma_addr_t dma_handle, unsigned long attrs)
-{
- unsigned long addr = (unsigned long) vaddr & ~0x20000000;
-
- if (addr >= 0x9c000000)
- return;
-
- free_pages(addr, get_order(size));
-}
-
-static int mn10300_dma_map_sg(struct device *dev, struct scatterlist *sglist,
- int nents, enum dma_data_direction direction,
- unsigned long attrs)
-{
- struct scatterlist *sg;
- int i;
-
- for_each_sg(sglist, sg, nents, i) {
- BUG_ON(!sg_page(sg));
-
- sg->dma_address = sg_phys(sg);
- }
-
- mn10300_dcache_flush_inv();
- return nents;
-}
-
-static dma_addr_t mn10300_dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction direction, unsigned long attrs)
-{
- return page_to_bus(page) + offset;
-}
-
-static void mn10300_dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction direction)
-{
- mn10300_dcache_flush_inv();
-}
-
-static void mn10300_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
- int nelems, enum dma_data_direction direction)
-{
- mn10300_dcache_flush_inv();
-}
-
-static int mn10300_dma_supported(struct device *dev, u64 mask)
-{
- /*
- * we fall back to GFP_DMA when the mask isn't all 1s, so we can't
- * guarantee allocations that must be within a tighter range than
- * GFP_DMA
- */
- if (mask < 0x00ffffff)
- return 0;
- return 1;
-}
-
-const struct dma_map_ops mn10300_dma_ops = {
- .alloc = mn10300_dma_alloc,
- .free = mn10300_dma_free,
- .map_page = mn10300_dma_map_page,
- .map_sg = mn10300_dma_map_sg,
- .sync_single_for_device = mn10300_dma_sync_single_for_device,
- .sync_sg_for_device = mn10300_dma_sync_sg_for_device,
-};
diff --git a/arch/mn10300/mm/extable.c b/arch/mn10300/mm/extable.c
deleted file mode 100644
index 045a903ee6b9..000000000000
--- a/arch/mn10300/mm/extable.c
+++ /dev/null
@@ -1,26 +0,0 @@
-/* MN10300 In-kernel exception handling
- *
- * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- *
- * 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/extable.h>
-#include <linux/spinlock.h>
-#include <linux/uaccess.h>
-
-int fixup_exception(struct pt_regs *regs)
-{
- const struct exception_table_entry *fixup;
-
- fixup = search_exception_tables(regs->pc);
- if (fixup) {
- regs->pc = fixup->fixup;
- return 1;
- }
-
- return 0;
-}
diff --git a/arch/mn10300/mm/fault.c b/arch/mn10300/mm/fault.c
deleted file mode 100644
index f0bfa1448744..000000000000
--- a/arch/mn10300/mm/fault.c
+++ /dev/null
@@ -1,414 +0,0 @@
-/* MN10300 MMU Fault handler
- *
- * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Modified 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/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/vt_kern.h> /* For unblank_screen() */
-#include <linux/uaccess.h>
-
-#include <asm/pgalloc.h>
-#include <asm/hardirq.h>
-#include <asm/cpu-regs.h>
-#include <asm/debugger.h>
-#include <asm/gdb-stub.h>
-
-/*
- * Unlock any spinlocks which will prevent us from getting the
- * message out
- */
-void bust_spinlocks(int yes)
-{
- if (yes) {
- oops_in_progress = 1;
- } else {
- int loglevel_save = console_loglevel;
-#ifdef CONFIG_VT
- unblank_screen();
-#endif
- oops_in_progress = 0;
- /*
- * OK, the message is on the console. Now we call printk()
- * without oops_in_progress set so that printk will give klogd
- * a poke. Hold onto your hats...
- */
- console_loglevel = 15; /* NMI oopser may have shut the console
- * up */
- printk(" ");
- console_loglevel = loglevel_save;
- }
-}
-
-void do_BUG(const char *file, int line)
-{
- bust_spinlocks(1);
- printk(KERN_EMERG CUT_HERE);
- printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line);
-}
-
-#if 0
-static void print_pagetable_entries(pgd_t *pgdir, unsigned long address)
-{
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *pte;
-
- pgd = pgdir + __pgd_offset(address);
- printk(KERN_DEBUG "pgd entry %p: %016Lx\n",
- pgd, (long long) pgd_val(*pgd));
-
- if (!pgd_present(*pgd)) {
- printk(KERN_DEBUG "... pgd not present!\n");
- return;
- }
- pmd = pmd_offset(pgd, address);
- printk(KERN_DEBUG "pmd entry %p: %016Lx\n",
- pmd, (long long)pmd_val(*pmd));
-
- if (!pmd_present(*pmd)) {
- printk(KERN_DEBUG "... pmd not present!\n");
- return;
- }
- pte = pte_offset(pmd, address);
- printk(KERN_DEBUG "pte entry %p: %016Lx\n",
- pte, (long long) pte_val(*pte));
-
- if (!pte_present(*pte))
- printk(KERN_DEBUG "... pte not present!\n");
-}
-#endif
-
-/*
- * This routine handles page faults. It determines the address,
- * and the problem, and then passes it off to one of the appropriate
- * routines.
- *
- * fault_code:
- * - LSW: either MMUFCR_IFC or MMUFCR_DFC as appropriate
- * - MSW: 0 if data access, 1 if instruction access
- * - bit 0: TLB miss flag
- * - bit 1: initial write
- * - bit 2: page invalid
- * - bit 3: protection violation
- * - bit 4: accessor (0=user 1=kernel)
- * - bit 5: 0=read 1=write
- * - bit 6-8: page protection spec
- * - bit 9: illegal address
- * - bit 16: 0=data 1=ins
- *
- */
-asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long fault_code,
- unsigned long address)
-{
- struct vm_area_struct *vma;
- struct task_struct *tsk;
- struct mm_struct *mm;
- unsigned long page;
- siginfo_t info;
- int fault;
- unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
-
-#ifdef CONFIG_GDBSTUB
- /* handle GDB stub causing a fault */
- if (gdbstub_busy) {
- gdbstub_exception(regs, TBR & TBR_INT_CODE);
- return;
- }
-#endif
-
-#if 0
- printk(KERN_DEBUG "--- do_page_fault(%p,%s:%04lx,%08lx)\n",
- regs,
- fault_code & 0x10000 ? "ins" : "data",
- fault_code & 0xffff, address);
-#endif
-
- tsk = current;
-
- /*
- * We fault-in kernel-space virtual memory on-demand. The
- * 'reference' page table is init_mm.pgd.
- *
- * NOTE! We MUST NOT take any locks for this case. We may
- * be in an interrupt or a critical region, and should
- * only copy the information from the master page table,
- * nothing more.
- *
- * This verifies that the fault happens in kernel space
- * and that the fault was a page not present (invalid) error
- */
- if (address >= VMALLOC_START && address < VMALLOC_END &&
- (fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_SR &&
- (fault_code & MMUFCR_xFC_PGINVAL) == MMUFCR_xFC_PGINVAL
- )
- goto vmalloc_fault;
-
- mm = tsk->mm;
- info.si_code = SEGV_MAPERR;
-
- /*
- * If we're in an interrupt or have no user
- * context, we must not take the fault..
- */
- if (faulthandler_disabled() || !mm)
- goto no_context;
-
- if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR)
- flags |= FAULT_FLAG_USER;
-retry:
- down_read(&mm->mmap_sem);
-
- vma = find_vma(mm, address);
- if (!vma)
- goto bad_area;
- if (vma->vm_start <= address)
- goto good_area;
- if (!(vma->vm_flags & VM_GROWSDOWN))
- goto bad_area;
-
- if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) {
- /* accessing the stack below the stack pointer is always a
- * bug */
- if ((address & PAGE_MASK) + 2 * PAGE_SIZE < regs->sp) {
-#if 0
- printk(KERN_WARNING
- "[%d] ### Access below stack @%lx (sp=%lx)\n",
- current->pid, address, regs->sp);
- printk(KERN_WARNING
- "vma [%08x - %08x]\n",
- vma->vm_start, vma->vm_end);
- show_registers(regs);
- printk(KERN_WARNING
- "[%d] ### Code: [%08lx]"
- " %02x %02x %02x %02x %02x %02x %02x %02x\n",
- current->pid,
- regs->pc,
- ((u8 *) regs->pc)[0],
- ((u8 *) regs->pc)[1],
- ((u8 *) regs->pc)[2],
- ((u8 *) regs->pc)[3],
- ((u8 *) regs->pc)[4],
- ((u8 *) regs->pc)[5],
- ((u8 *) regs->pc)[6],
- ((u8 *) regs->pc)[7]
- );
-#endif
- goto bad_area;
- }
- }
-
- if (expand_stack(vma, address))
- goto bad_area;
-
-/*
- * Ok, we have a good vm_area for this memory access, so
- * we can handle it..
- */
-good_area:
- info.si_code = SEGV_ACCERR;
- switch (fault_code & (MMUFCR_xFC_PGINVAL|MMUFCR_xFC_TYPE)) {
- default: /* 3: write, present */
- case MMUFCR_xFC_TYPE_WRITE:
-#ifdef TEST_VERIFY_AREA
- if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_SR)
- printk(KERN_DEBUG "WP fault at %08lx\n", regs->pc);
-#endif
- /* write to absent page */
- case MMUFCR_xFC_PGINVAL | MMUFCR_xFC_TYPE_WRITE:
- if (!(vma->vm_flags & VM_WRITE))
- goto bad_area;
- flags |= FAULT_FLAG_WRITE;
- break;
-
- /* read from protected page */
- case MMUFCR_xFC_TYPE_READ:
- goto bad_area;
-
- /* read from absent page present */
- case MMUFCR_xFC_PGINVAL | MMUFCR_xFC_TYPE_READ:
- if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
- goto bad_area;
- break;
- }
-
- /*
- * If for any reason at all we couldn't handle the fault,
- * make sure we exit gracefully rather than endlessly redo
- * the fault.
- */
- fault = handle_mm_fault(vma, address, flags);
-
- if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
- return;
-
- if (unlikely(fault & VM_FAULT_ERROR)) {
- if (fault & VM_FAULT_OOM)
- goto out_of_memory;
- else if (fault & VM_FAULT_SIGSEGV)
- goto bad_area;
- else if (fault & VM_FAULT_SIGBUS)
- goto do_sigbus;
- BUG();
- }
- if (flags & FAULT_FLAG_ALLOW_RETRY) {
- if (fault & VM_FAULT_MAJOR)
- current->maj_flt++;
- else
- current->min_flt++;
- if (fault & VM_FAULT_RETRY) {
- flags &= ~FAULT_FLAG_ALLOW_RETRY;
-
- /* No need to up_read(&mm->mmap_sem) as we would
- * have already released it in __lock_page_or_retry
- * in mm/filemap.c.
- */
-
- goto retry;
- }
- }
-
- up_read(&mm->mmap_sem);
- return;
-
-/*
- * Something tried to access memory that isn't in our memory map..
- * Fix it, but check if it's kernel or user first..
- */
-bad_area:
- up_read(&mm->mmap_sem);
-
- /* User mode accesses just cause a SIGSEGV */
- if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) {
- info.si_signo = SIGSEGV;
- info.si_errno = 0;
- /* info.si_code has been set above */
- info.si_addr = (void *)address;
- force_sig_info(SIGSEGV, &info, tsk);
- return;
- }
-
-no_context:
- /* Are we prepared to handle this kernel fault? */
- if (fixup_exception(regs))
- return;
-
-/*
- * Oops. The kernel tried to access some bad page. We'll have to
- * terminate things with extreme prejudice.
- */
-
- bust_spinlocks(1);
-
- if (address < PAGE_SIZE)
- printk(KERN_ALERT
- "Unable to handle kernel NULL pointer dereference");
- else
- printk(KERN_ALERT
- "Unable to handle kernel paging request");
- printk(" at virtual address %08lx\n", address);
- printk(" printing pc:\n");
- printk(KERN_ALERT "%08lx\n", regs->pc);
-
- debugger_intercept(fault_code & 0x00010000 ? EXCEP_IAERROR : EXCEP_DAERROR,
- SIGSEGV, SEGV_ACCERR, regs);
-
- page = PTBR;
- page = ((unsigned long *) __va(page))[address >> 22];
- printk(KERN_ALERT "*pde = %08lx\n", page);
- if (page & 1) {
- page &= PAGE_MASK;
- address &= 0x003ff000;
- page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
- printk(KERN_ALERT "*pte = %08lx\n", page);
- }
-
- die("Oops", regs, fault_code);
- do_exit(SIGKILL);
-
-/*
- * We ran out of memory, or some other thing happened to us that made
- * us unable to handle the page fault gracefully.
- */
-out_of_memory:
- up_read(&mm->mmap_sem);
- if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_USR) {
- pagefault_out_of_memory();
- return;
- }
- goto no_context;
-
-do_sigbus:
- up_read(&mm->mmap_sem);
-
- /*
- * Send a sigbus, regardless of whether we were in kernel
- * or user mode.
- */
- info.si_signo = SIGBUS;
- info.si_errno = 0;
- info.si_code = BUS_ADRERR;
- info.si_addr = (void *)address;
- force_sig_info(SIGBUS, &info, tsk);
-
- /* Kernel mode? Handle exceptions or die */
- if ((fault_code & MMUFCR_xFC_ACCESS) == MMUFCR_xFC_ACCESS_SR)
- goto no_context;
- return;
-
-vmalloc_fault:
- {
- /*
- * Synchronize this task's top level page-table
- * with the 'reference' page table.
- *
- * Do _not_ use "tsk" here. We might be inside
- * an interrupt in the middle of a task switch..
- */
- int index = pgd_index(address);
- pgd_t *pgd, *pgd_k;
- pud_t *pud, *pud_k;
- pmd_t *pmd, *pmd_k;
- pte_t *pte_k;
-
- pgd_k = init_mm.pgd + index;
-
- if (!pgd_present(*pgd_k))
- goto no_context;
-
- pud_k = pud_offset(pgd_k, address);
- if (!pud_present(*pud_k))
- goto no_context;
-
- pmd_k = pmd_offset(pud_k, address);
- if (!pmd_present(*pmd_k))
- goto no_context;
-
- pgd = (pgd_t *) PTBR + index;
- pud = pud_offset(pgd, address);
- pmd = pmd_offset(pud, address);
- set_pmd(pmd, *pmd_k);
-
- pte_k = pte_offset_kernel(pmd_k, address);
- if (!pte_present(*pte_k))
- goto no_context;
- return;
- }
-}
diff --git a/arch/mn10300/mm/init.c b/arch/mn10300/mm/init.c
deleted file mode 100644
index 8ce677d5575e..000000000000
--- a/arch/mn10300/mm/init.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/* MN10300 Memory management initialisation
- *
- * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Modified 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/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/initrd.h>
-#include <linux/highmem.h>
-#include <linux/pagemap.h>
-#include <linux/bootmem.h>
-#include <linux/gfp.h>
-
-#include <asm/processor.h>
-#include <linux/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/pgalloc.h>
-#include <asm/dma.h>
-#include <asm/tlb.h>
-#include <asm/sections.h>
-
-unsigned long highstart_pfn, highend_pfn;
-
-#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
-static struct vm_struct user_iomap_vm;
-#endif
-
-/*
- * set up paging
- */
-void __init paging_init(void)
-{
- unsigned long zones_size[MAX_NR_ZONES] = {0,};
- pte_t *ppte;
- int loop;
-
- /* main kernel space -> RAM mapping is handled as 1:1 transparent by
- * the MMU */
- memset(swapper_pg_dir, 0, sizeof(swapper_pg_dir));
- memset(kernel_vmalloc_ptes, 0, sizeof(kernel_vmalloc_ptes));
-
- /* load the VMALLOC area PTE table addresses into the kernel PGD */
- ppte = kernel_vmalloc_ptes;
- for (loop = VMALLOC_START / (PAGE_SIZE * PTRS_PER_PTE);
- loop < VMALLOC_END / (PAGE_SIZE * PTRS_PER_PTE);
- loop++
- ) {
- set_pgd(swapper_pg_dir + loop, __pgd(__pa(ppte) | _PAGE_TABLE));
- ppte += PAGE_SIZE / sizeof(pte_t);
- }
-
- /* declare the sizes of the RAM zones (only use the normal zone) */
- zones_size[ZONE_NORMAL] =
- contig_page_data.bdata->node_low_pfn -
- contig_page_data.bdata->node_min_pfn;
-
- /* pass the memory from the bootmem allocator to the main allocator */
- free_area_init(zones_size);
-
-#ifdef CONFIG_MN10300_HAS_ATOMIC_OPS_UNIT
- /* The Atomic Operation Unit registers need to be mapped to userspace
- * for all processes. The following uses vm_area_register_early() to
- * reserve the first page of the vmalloc area and sets the pte for that
- * page.
- *
- * glibc hardcodes this virtual mapping, so we're pretty much stuck with
- * it from now on.
- */
- user_iomap_vm.flags = VM_USERMAP;
- user_iomap_vm.size = 1 << PAGE_SHIFT;
- vm_area_register_early(&user_iomap_vm, PAGE_SIZE);
- ppte = kernel_vmalloc_ptes;
- set_pte(ppte, pfn_pte(USER_ATOMIC_OPS_PAGE_ADDR >> PAGE_SHIFT,
- PAGE_USERIO));
-#endif
-
- local_flush_tlb_all();
-}
-
-/*
- * transfer all the memory from the bootmem allocator to the runtime allocator
- */
-void __init mem_init(void)
-{
- BUG_ON(!mem_map);
-
-#define START_PFN (contig_page_data.bdata->node_min_pfn)
-#define MAX_LOW_PFN (contig_page_data.bdata->node_low_pfn)
-
- max_mapnr = MAX_LOW_PFN - START_PFN;
- high_memory = (void *) __va(MAX_LOW_PFN * PAGE_SIZE);
-
- /* clear the zero-page */
- memset(empty_zero_page, 0, PAGE_SIZE);
-
- /* this will put all low memory onto the freelists */
- free_all_bootmem();
-
- mem_init_print_info(NULL);
-}
-
-/*
- * recycle memory containing stuff only required for initialisation
- */
-void free_initmem(void)
-{
- free_initmem_default(POISON_FREE_INITMEM);
-}
-
-/*
- * dispose of the memory on which the initial ramdisk resided
- */
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
- free_reserved_area((void *)start, (void *)end, POISON_FREE_INITMEM,
- "initrd");
-}
-#endif
diff --git a/arch/mn10300/mm/misalignment.c b/arch/mn10300/mm/misalignment.c
deleted file mode 100644
index 8ace89617c1c..000000000000
--- a/arch/mn10300/mm/misalignment.c
+++ /dev/null
@@ -1,966 +0,0 @@
-/* MN10300 Misalignment fixup handler
- *
- * 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/extable.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ptrace.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <asm/processor.h>
-#include <linux/uaccess.h>
-#include <asm/io.h>
-#include <linux/atomic.h>
-#include <asm/smp.h>
-#include <asm/pgalloc.h>
-#include <asm/cpu-regs.h>
-#include <asm/busctl-regs.h>
-#include <asm/fpu.h>
-#include <asm/gdb-stub.h>
-#include <asm/asm-offsets.h>
-
-#if 0
-#define kdebug(FMT, ...) printk(KERN_DEBUG "MISALIGN: "FMT"\n", ##__VA_ARGS__)
-#else
-#define kdebug(FMT, ...) do {} while (0)
-#endif
-
-static int misalignment_addr(unsigned long *registers, unsigned long sp,
- unsigned params, unsigned opcode,
- unsigned long disp,
- void **_address, unsigned long **_postinc,
- unsigned long *_inc);
-
-static int misalignment_reg(unsigned long *registers, unsigned params,
- unsigned opcode, unsigned long disp,
- unsigned long **_register);
-
-static void misalignment_MOV_Lcc(struct pt_regs *regs, uint32_t opcode);
-
-static const unsigned Dreg_index[] = {
- REG_D0 >> 2, REG_D1 >> 2, REG_D2 >> 2, REG_D3 >> 2
-};
-
-static const unsigned Areg_index[] = {
- REG_A0 >> 2, REG_A1 >> 2, REG_A2 >> 2, REG_A3 >> 2
-};
-
-static const unsigned Rreg_index[] = {
- REG_E0 >> 2, REG_E1 >> 2, REG_E2 >> 2, REG_E3 >> 2,
- REG_E4 >> 2, REG_E5 >> 2, REG_E6 >> 2, REG_E7 >> 2,
- REG_A0 >> 2, REG_A1 >> 2, REG_A2 >> 2, REG_A3 >> 2,
- REG_D0 >> 2, REG_D1 >> 2, REG_D2 >> 2, REG_D3 >> 2
-};
-
-enum format_id {
- FMT_S0,
- FMT_S1,
- FMT_S2,
- FMT_S4,
- FMT_D0,
- FMT_D1,
- FMT_D2,
- FMT_D4,
- FMT_D6,
- FMT_D7,
- FMT_D8,
- FMT_D9,
- FMT_D10,
-};
-
-static const struct {
- u_int8_t opsz, dispsz;
-} format_tbl[16] = {
- [FMT_S0] = { 8, 0 },
- [FMT_S1] = { 8, 8 },
- [FMT_S2] = { 8, 16 },
- [FMT_S4] = { 8, 32 },
- [FMT_D0] = { 16, 0 },
- [FMT_D1] = { 16, 8 },
- [FMT_D2] = { 16, 16 },
- [FMT_D4] = { 16, 32 },
- [FMT_D6] = { 24, 0 },
- [FMT_D7] = { 24, 8 },
- [FMT_D8] = { 24, 24 },
- [FMT_D9] = { 24, 32 },
- [FMT_D10] = { 32, 0 },
-};
-
-enum value_id {
- DM0, /* data reg in opcode in bits 0-1 */
- DM1, /* data reg in opcode in bits 2-3 */
- DM2, /* data reg in opcode in bits 4-5 */
- AM0, /* addr reg in opcode in bits 0-1 */
- AM1, /* addr reg in opcode in bits 2-3 */
- AM2, /* addr reg in opcode in bits 4-5 */
- RM0, /* reg in opcode in bits 0-3 */
- RM1, /* reg in opcode in bits 2-5 */
- RM2, /* reg in opcode in bits 4-7 */
- RM4, /* reg in opcode in bits 8-11 */
- RM6, /* reg in opcode in bits 12-15 */
-
- RD0, /* reg in displacement in bits 0-3 */
- RD2, /* reg in displacement in bits 4-7 */
-
- SP, /* stack pointer */
-
- SD8, /* 8-bit signed displacement */
- SD16, /* 16-bit signed displacement */
- SD24, /* 24-bit signed displacement */
- SIMM4_2, /* 4-bit signed displacement in opcode bits 4-7 */
- SIMM8, /* 8-bit signed immediate */
- IMM8, /* 8-bit unsigned immediate */
- IMM16, /* 16-bit unsigned immediate */
- IMM24, /* 24-bit unsigned immediate */
- IMM32, /* 32-bit unsigned immediate */
- IMM32_HIGH8, /* 32-bit unsigned immediate, LSB in opcode */
-
- IMM32_MEM, /* 32-bit unsigned displacement */
- IMM32_HIGH8_MEM, /* 32-bit unsigned displacement, LSB in opcode */
-
- DN0 = DM0,
- DN1 = DM1,
- DN2 = DM2,
- AN0 = AM0,
- AN1 = AM1,
- AN2 = AM2,
- RN0 = RM0,
- RN1 = RM1,
- RN2 = RM2,
- RN4 = RM4,
- RN6 = RM6,
- DI = DM1,
- RI = RM2,
-
-};
-
-struct mn10300_opcode {
- const char name[8];
- u_int32_t opcode;
- u_int32_t opmask;
- unsigned exclusion;
-
- enum format_id format;
-
- unsigned cpu_mask;
-#define AM33 330
-
- unsigned params[2];
-#define MEM(ADDR) (0x80000000 | (ADDR))
-#define MEM2(ADDR1, ADDR2) (0x80000000 | (ADDR1) << 8 | (ADDR2))
-#define MEMINC(ADDR) (0x81000000 | (ADDR))
-#define MEMINC2(ADDR, INC) (0x81000000 | (ADDR) << 8 | (INC))
-};
-
-/* LIBOPCODES EXCERPT
- Assemble Matsushita MN10300 instructions.
- Copyright 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
-
- 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.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public Licence for more details.
-
- You should have received a copy of the GNU General Public Licence
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-static const struct mn10300_opcode mn10300_opcodes[] = {
-{ "mov", 0x4200, 0xf300, 0, FMT_S1, 0, {DM1, MEM2(IMM8, SP)}},
-{ "mov", 0x4300, 0xf300, 0, FMT_S1, 0, {AM1, MEM2(IMM8, SP)}},
-{ "mov", 0x5800, 0xfc00, 0, FMT_S1, 0, {MEM2(IMM8, SP), DN0}},
-{ "mov", 0x5c00, 0xfc00, 0, FMT_S1, 0, {MEM2(IMM8, SP), AN0}},
-{ "mov", 0x60, 0xf0, 0, FMT_S0, 0, {DM1, MEM(AN0)}},
-{ "mov", 0x70, 0xf0, 0, FMT_S0, 0, {MEM(AM0), DN1}},
-{ "mov", 0xf000, 0xfff0, 0, FMT_D0, 0, {MEM(AM0), AN1}},
-{ "mov", 0xf010, 0xfff0, 0, FMT_D0, 0, {AM1, MEM(AN0)}},
-{ "mov", 0xf300, 0xffc0, 0, FMT_D0, 0, {MEM2(DI, AM0), DN2}},
-{ "mov", 0xf340, 0xffc0, 0, FMT_D0, 0, {DM2, MEM2(DI, AN0)}},
-{ "mov", 0xf380, 0xffc0, 0, FMT_D0, 0, {MEM2(DI, AM0), AN2}},
-{ "mov", 0xf3c0, 0xffc0, 0, FMT_D0, 0, {AM2, MEM2(DI, AN0)}},
-{ "mov", 0xf80000, 0xfff000, 0, FMT_D1, 0, {MEM2(SD8, AM0), DN1}},
-{ "mov", 0xf81000, 0xfff000, 0, FMT_D1, 0, {DM1, MEM2(SD8, AN0)}},
-{ "mov", 0xf82000, 0xfff000, 0, FMT_D1, 0, {MEM2(SD8,AM0), AN1}},
-{ "mov", 0xf83000, 0xfff000, 0, FMT_D1, 0, {AM1, MEM2(SD8, AN0)}},
-{ "mov", 0xf90a00, 0xffff00, 0, FMT_D6, AM33, {MEM(RM0), RN2}},
-{ "mov", 0xf91a00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEM(RN0)}},
-{ "mov", 0xf96a00, 0xffff00, 0x12, FMT_D6, AM33, {MEMINC(RM0), RN2}},
-{ "mov", 0xf97a00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEMINC(RN0)}},
-{ "mov", 0xfa000000, 0xfff00000, 0, FMT_D2, 0, {MEM2(SD16, AM0), DN1}},
-{ "mov", 0xfa100000, 0xfff00000, 0, FMT_D2, 0, {DM1, MEM2(SD16, AN0)}},
-{ "mov", 0xfa200000, 0xfff00000, 0, FMT_D2, 0, {MEM2(SD16, AM0), AN1}},
-{ "mov", 0xfa300000, 0xfff00000, 0, FMT_D2, 0, {AM1, MEM2(SD16, AN0)}},
-{ "mov", 0xfa900000, 0xfff30000, 0, FMT_D2, 0, {AM1, MEM2(IMM16, SP)}},
-{ "mov", 0xfa910000, 0xfff30000, 0, FMT_D2, 0, {DM1, MEM2(IMM16, SP)}},
-{ "mov", 0xfab00000, 0xfffc0000, 0, FMT_D2, 0, {MEM2(IMM16, SP), AN0}},
-{ "mov", 0xfab40000, 0xfffc0000, 0, FMT_D2, 0, {MEM2(IMM16, SP), DN0}},
-{ "mov", 0xfb0a0000, 0xffff0000, 0, FMT_D7, AM33, {MEM2(SD8, RM0), RN2}},
-{ "mov", 0xfb1a0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEM2(SD8, RN0)}},
-{ "mov", 0xfb6a0000, 0xffff0000, 0x22, FMT_D7, AM33, {MEMINC2 (RM0, SIMM8), RN2}},
-{ "mov", 0xfb7a0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEMINC2 (RN0, SIMM8)}},
-{ "mov", 0xfb8a0000, 0xffff0f00, 0, FMT_D7, AM33, {MEM2(IMM8, SP), RN2}},
-{ "mov", 0xfb8e0000, 0xffff000f, 0, FMT_D7, AM33, {MEM2(RI, RM0), RD2}},
-{ "mov", 0xfb9a0000, 0xffff0f00, 0, FMT_D7, AM33, {RM2, MEM2(IMM8, SP)}},
-{ "mov", 0xfb9e0000, 0xffff000f, 0, FMT_D7, AM33, {RD2, MEM2(RI, RN0)}},
-{ "mov", 0xfc000000, 0xfff00000, 0, FMT_D4, 0, {MEM2(IMM32,AM0), DN1}},
-{ "mov", 0xfc100000, 0xfff00000, 0, FMT_D4, 0, {DM1, MEM2(IMM32,AN0)}},
-{ "mov", 0xfc200000, 0xfff00000, 0, FMT_D4, 0, {MEM2(IMM32,AM0), AN1}},
-{ "mov", 0xfc300000, 0xfff00000, 0, FMT_D4, 0, {AM1, MEM2(IMM32,AN0)}},
-{ "mov", 0xfc800000, 0xfff30000, 0, FMT_D4, 0, {AM1, MEM(IMM32_MEM)}},
-{ "mov", 0xfc810000, 0xfff30000, 0, FMT_D4, 0, {DM1, MEM(IMM32_MEM)}},
-{ "mov", 0xfc900000, 0xfff30000, 0, FMT_D4, 0, {AM1, MEM2(IMM32, SP)}},
-{ "mov", 0xfc910000, 0xfff30000, 0, FMT_D4, 0, {DM1, MEM2(IMM32, SP)}},
-{ "mov", 0xfca00000, 0xfffc0000, 0, FMT_D4, 0, {MEM(IMM32_MEM), AN0}},
-{ "mov", 0xfca40000, 0xfffc0000, 0, FMT_D4, 0, {MEM(IMM32_MEM), DN0}},
-{ "mov", 0xfcb00000, 0xfffc0000, 0, FMT_D4, 0, {MEM2(IMM32, SP), AN0}},
-{ "mov", 0xfcb40000, 0xfffc0000, 0, FMT_D4, 0, {MEM2(IMM32, SP), DN0}},
-{ "mov", 0xfd0a0000, 0xffff0000, 0, FMT_D8, AM33, {MEM2(SD24, RM0), RN2}},
-{ "mov", 0xfd1a0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEM2(SD24, RN0)}},
-{ "mov", 0xfd6a0000, 0xffff0000, 0x22, FMT_D8, AM33, {MEMINC2 (RM0, IMM24), RN2}},
-{ "mov", 0xfd7a0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEMINC2 (RN0, IMM24)}},
-{ "mov", 0xfd8a0000, 0xffff0f00, 0, FMT_D8, AM33, {MEM2(IMM24, SP), RN2}},
-{ "mov", 0xfd9a0000, 0xffff0f00, 0, FMT_D8, AM33, {RM2, MEM2(IMM24, SP)}},
-{ "mov", 0xfe0a0000, 0xffff0000, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8,RM0), RN2}},
-{ "mov", 0xfe0a0000, 0xffff0000, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8,RM0), RN2}},
-{ "mov", 0xfe0e0000, 0xffff0f00, 0, FMT_D9, AM33, {MEM(IMM32_HIGH8_MEM), RN2}},
-{ "mov", 0xfe1a0000, 0xffff0000, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, RN0)}},
-{ "mov", 0xfe1a0000, 0xffff0000, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, RN0)}},
-{ "mov", 0xfe1e0000, 0xffff0f00, 0, FMT_D9, AM33, {RM2, MEM(IMM32_HIGH8_MEM)}},
-{ "mov", 0xfe6a0000, 0xffff0000, 0x22, FMT_D9, AM33, {MEMINC2 (RM0, IMM32_HIGH8), RN2}},
-{ "mov", 0xfe7a0000, 0xffff0000, 0, FMT_D9, AM33, {RN2, MEMINC2 (RM0, IMM32_HIGH8)}},
-{ "mov", 0xfe8a0000, 0xffff0f00, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8, SP), RN2}},
-{ "mov", 0xfe9a0000, 0xffff0f00, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, SP)}},
-
-{ "movhu", 0xf060, 0xfff0, 0, FMT_D0, 0, {MEM(AM0), DN1}},
-{ "movhu", 0xf070, 0xfff0, 0, FMT_D0, 0, {DM1, MEM(AN0)}},
-{ "movhu", 0xf480, 0xffc0, 0, FMT_D0, 0, {MEM2(DI, AM0), DN2}},
-{ "movhu", 0xf4c0, 0xffc0, 0, FMT_D0, 0, {DM2, MEM2(DI, AN0)}},
-{ "movhu", 0xf86000, 0xfff000, 0, FMT_D1, 0, {MEM2(SD8, AM0), DN1}},
-{ "movhu", 0xf87000, 0xfff000, 0, FMT_D1, 0, {DM1, MEM2(SD8, AN0)}},
-{ "movhu", 0xf89300, 0xfff300, 0, FMT_D1, 0, {DM1, MEM2(IMM8, SP)}},
-{ "movhu", 0xf8bc00, 0xfffc00, 0, FMT_D1, 0, {MEM2(IMM8, SP), DN0}},
-{ "movhu", 0xf94a00, 0xffff00, 0, FMT_D6, AM33, {MEM(RM0), RN2}},
-{ "movhu", 0xf95a00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEM(RN0)}},
-{ "movhu", 0xf9ea00, 0xffff00, 0x12, FMT_D6, AM33, {MEMINC(RM0), RN2}},
-{ "movhu", 0xf9fa00, 0xffff00, 0, FMT_D6, AM33, {RM2, MEMINC(RN0)}},
-{ "movhu", 0xfa600000, 0xfff00000, 0, FMT_D2, 0, {MEM2(SD16, AM0), DN1}},
-{ "movhu", 0xfa700000, 0xfff00000, 0, FMT_D2, 0, {DM1, MEM2(SD16, AN0)}},
-{ "movhu", 0xfa930000, 0xfff30000, 0, FMT_D2, 0, {DM1, MEM2(IMM16, SP)}},
-{ "movhu", 0xfabc0000, 0xfffc0000, 0, FMT_D2, 0, {MEM2(IMM16, SP), DN0}},
-{ "movhu", 0xfb4a0000, 0xffff0000, 0, FMT_D7, AM33, {MEM2(SD8, RM0), RN2}},
-{ "movhu", 0xfb5a0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEM2(SD8, RN0)}},
-{ "movhu", 0xfbca0000, 0xffff0f00, 0, FMT_D7, AM33, {MEM2(IMM8, SP), RN2}},
-{ "movhu", 0xfbce0000, 0xffff000f, 0, FMT_D7, AM33, {MEM2(RI, RM0), RD2}},
-{ "movhu", 0xfbda0000, 0xffff0f00, 0, FMT_D7, AM33, {RM2, MEM2(IMM8, SP)}},
-{ "movhu", 0xfbde0000, 0xffff000f, 0, FMT_D7, AM33, {RD2, MEM2(RI, RN0)}},
-{ "movhu", 0xfbea0000, 0xffff0000, 0x22, FMT_D7, AM33, {MEMINC2 (RM0, SIMM8), RN2}},
-{ "movhu", 0xfbfa0000, 0xffff0000, 0, FMT_D7, AM33, {RM2, MEMINC2 (RN0, SIMM8)}},
-{ "movhu", 0xfc600000, 0xfff00000, 0, FMT_D4, 0, {MEM2(IMM32,AM0), DN1}},
-{ "movhu", 0xfc700000, 0xfff00000, 0, FMT_D4, 0, {DM1, MEM2(IMM32,AN0)}},
-{ "movhu", 0xfc830000, 0xfff30000, 0, FMT_D4, 0, {DM1, MEM(IMM32_MEM)}},
-{ "movhu", 0xfc930000, 0xfff30000, 0, FMT_D4, 0, {DM1, MEM2(IMM32, SP)}},
-{ "movhu", 0xfcac0000, 0xfffc0000, 0, FMT_D4, 0, {MEM(IMM32_MEM), DN0}},
-{ "movhu", 0xfcbc0000, 0xfffc0000, 0, FMT_D4, 0, {MEM2(IMM32, SP), DN0}},
-{ "movhu", 0xfd4a0000, 0xffff0000, 0, FMT_D8, AM33, {MEM2(SD24, RM0), RN2}},
-{ "movhu", 0xfd5a0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEM2(SD24, RN0)}},
-{ "movhu", 0xfdca0000, 0xffff0f00, 0, FMT_D8, AM33, {MEM2(IMM24, SP), RN2}},
-{ "movhu", 0xfdda0000, 0xffff0f00, 0, FMT_D8, AM33, {RM2, MEM2(IMM24, SP)}},
-{ "movhu", 0xfdea0000, 0xffff0000, 0x22, FMT_D8, AM33, {MEMINC2 (RM0, IMM24), RN2}},
-{ "movhu", 0xfdfa0000, 0xffff0000, 0, FMT_D8, AM33, {RM2, MEMINC2 (RN0, IMM24)}},
-{ "movhu", 0xfe4a0000, 0xffff0000, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8,RM0), RN2}},
-{ "movhu", 0xfe4e0000, 0xffff0f00, 0, FMT_D9, AM33, {MEM(IMM32_HIGH8_MEM), RN2}},
-{ "movhu", 0xfe5a0000, 0xffff0000, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, RN0)}},
-{ "movhu", 0xfe5e0000, 0xffff0f00, 0, FMT_D9, AM33, {RM2, MEM(IMM32_HIGH8_MEM)}},
-{ "movhu", 0xfeca0000, 0xffff0f00, 0, FMT_D9, AM33, {MEM2(IMM32_HIGH8, SP), RN2}},
-{ "movhu", 0xfeda0000, 0xffff0f00, 0, FMT_D9, AM33, {RM2, MEM2(IMM32_HIGH8, SP)}},
-{ "movhu", 0xfeea0000, 0xffff0000, 0x22, FMT_D9, AM33, {MEMINC2 (RM0, IMM32_HIGH8), RN2}},
-{ "movhu", 0xfefa0000, 0xffff0000, 0, FMT_D9, AM33, {RN2, MEMINC2 (RM0, IMM32_HIGH8)}},
-
-{ "mov_llt", 0xf7e00000, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
-{ "mov_lgt", 0xf7e00001, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
-{ "mov_lge", 0xf7e00002, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
-{ "mov_lle", 0xf7e00003, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
-{ "mov_lcs", 0xf7e00004, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
-{ "mov_lhi", 0xf7e00005, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
-{ "mov_lcc", 0xf7e00006, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
-{ "mov_lls", 0xf7e00007, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
-{ "mov_leq", 0xf7e00008, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
-{ "mov_lne", 0xf7e00009, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
-{ "mov_lra", 0xf7e0000a, 0xffff000f, 0x22, FMT_D10, AM33, {MEMINC2 (RN4,SIMM4_2), RM6}},
-
-{ "", 0, 0, 0, 0, 0, {0}},
-};
-
-/*
- * fix up misalignment problems where possible
- */
-asmlinkage void misalignment(struct pt_regs *regs, enum exception_code code)
-{
- const struct exception_table_entry *fixup;
- const struct mn10300_opcode *pop;
- unsigned long *registers = (unsigned long *) regs;
- unsigned long data, *store, *postinc, disp, inc, sp;
- mm_segment_t seg;
- siginfo_t info;
- uint32_t opcode, noc, xo, xm;
- uint8_t *pc, byte, datasz;
- void *address;
- unsigned tmp, npop, dispsz, loop;
-
- /* we don't fix up userspace misalignment faults */
- if (user_mode(regs))
- goto bus_error;
-
- sp = (unsigned long) regs + sizeof(*regs);
-
- kdebug("==>misalignment({pc=%lx,sp=%lx})", regs->pc, sp);
-
- if (regs->epsw & EPSW_IE)
- asm volatile("or %0,epsw" : : "i"(EPSW_IE));
-
- seg = get_fs();
- set_fs(KERNEL_DS);
-
- fixup = search_exception_tables(regs->pc);
-
- /* first thing to do is to match the opcode */
- pc = (u_int8_t *) regs->pc;
-
- if (__get_user(byte, pc) != 0)
- goto fetch_error;
- opcode = byte;
- noc = 8;
-
- for (pop = mn10300_opcodes; pop->name[0]; pop++) {
- npop = ilog2(pop->opcode | pop->opmask);
- if (npop <= 0 || npop > 31)
- continue;
- npop = (npop + 8) & ~7;
-
- got_more_bits:
- if (npop == noc) {
- if ((opcode & pop->opmask) == pop->opcode)
- goto found_opcode;
- } else if (npop > noc) {
- xo = pop->opcode >> (npop - noc);
- xm = pop->opmask >> (npop - noc);
-
- if ((opcode & xm) != xo)
- continue;
-
- /* we've got a partial match (an exact match on the
- * first N bytes), so we need to get some more data */
- pc++;
- if (__get_user(byte, pc) != 0)
- goto fetch_error;
- opcode = opcode << 8 | byte;
- noc += 8;
- goto got_more_bits;
- } else {
- /* there's already been a partial match as long as the
- * complete match we're now considering, so this one
- * should't match */
- continue;
- }
- }
-
- /* didn't manage to find a fixup */
- printk(KERN_CRIT "MISALIGN: %lx: unsupported instruction %x\n",
- regs->pc, opcode);
-
-failed:
- set_fs(seg);
- if (die_if_no_fixup("misalignment error", regs, code))
- return;
-
-bus_error:
- info.si_signo = SIGBUS;
- info.si_errno = 0;
- info.si_code = BUS_ADRALN;
- info.si_addr = (void *) regs->pc;
- force_sig_info(SIGBUS, &info, current);
- return;
-
- /* error reading opcodes */
-fetch_error:
- printk(KERN_CRIT
- "MISALIGN: %p: fault whilst reading instruction data\n",
- pc);
- goto failed;
-
-bad_addr_mode:
- printk(KERN_CRIT
- "MISALIGN: %lx: unsupported addressing mode %x\n",
- regs->pc, opcode);
- goto failed;
-
-bad_reg_mode:
- printk(KERN_CRIT
- "MISALIGN: %lx: unsupported register mode %x\n",
- regs->pc, opcode);
- goto failed;
-
-unsupported_instruction:
- printk(KERN_CRIT
- "MISALIGN: %lx: unsupported instruction %x (%s)\n",
- regs->pc, opcode, pop->name);
- goto failed;
-
-transfer_failed:
- set_fs(seg);
- if (fixup) {
- regs->pc = fixup->fixup;
- return;
- }
- if (die_if_no_fixup("misalignment fixup", regs, code))
- return;
-
- info.si_signo = SIGSEGV;
- info.si_errno = 0;
- info.si_code = SEGV_MAPERR;
- info.si_addr = (void *) regs->pc;
- force_sig_info(SIGSEGV, &info, current);
- return;
-
- /* we matched the opcode */
-found_opcode:
- kdebug("%lx: %x==%x { %x, %x }",
- regs->pc, opcode, pop->opcode, pop->params[0], pop->params[1]);
-
- tmp = format_tbl[pop->format].opsz;
- BUG_ON(tmp > noc); /* match was less complete than it ought to have been */
-
- if (tmp < noc) {
- tmp = noc - tmp;
- opcode >>= tmp;
- pc -= tmp >> 3;
- }
-
- /* grab the extra displacement (note it's LSB first) */
- disp = 0;
- dispsz = format_tbl[pop->format].dispsz;
- for (loop = 0; loop < dispsz; loop += 8) {
- pc++;
- if (__get_user(byte, pc) != 0)
- goto fetch_error;
- disp |= byte << loop;
- kdebug("{%p} disp[%02x]=%02x", pc, loop, byte);
- }
-
- kdebug("disp=%lx", disp);
-
- set_fs(KERNEL_XDS);
- if (fixup)
- set_fs(seg);
-
- tmp = (pop->params[0] ^ pop->params[1]) & 0x80000000;
- if (!tmp) {
- printk(KERN_CRIT
- "MISALIGN: %lx: insn not move to/from memory %x\n",
- regs->pc, opcode);
- goto failed;
- }
-
- /* determine the data transfer size of the move */
- if (pop->name[3] == 0 || /* "mov" */
- pop->name[4] == 'l') /* mov_lcc */
- inc = datasz = 4;
- else if (pop->name[3] == 'h') /* movhu */
- inc = datasz = 2;
- else
- goto unsupported_instruction;
-
- if (pop->params[0] & 0x80000000) {
- /* move memory to register */
- if (!misalignment_addr(registers, sp,
- pop->params[0], opcode, disp,
- &address, &postinc, &inc))
- goto bad_addr_mode;
-
- if (!misalignment_reg(registers, pop->params[1], opcode, disp,
- &store))
- goto bad_reg_mode;
-
- kdebug("mov%u (%p),DARn", datasz, address);
- if (copy_from_user(&data, (void *) address, datasz) != 0)
- goto transfer_failed;
- if (pop->params[0] & 0x1000000) {
- kdebug("inc=%lx", inc);
- *postinc += inc;
- }
-
- *store = data;
- kdebug("loaded %lx", data);
- } else {
- /* move register to memory */
- if (!misalignment_reg(registers, pop->params[0], opcode, disp,
- &store))
- goto bad_reg_mode;
-
- if (!misalignment_addr(registers, sp,
- pop->params[1], opcode, disp,
- &address, &postinc, &inc))
- goto bad_addr_mode;
-
- data = *store;
-
- kdebug("mov%u %lx,(%p)", datasz, data, address);
- if (copy_to_user((void *) address, &data, datasz) != 0)
- goto transfer_failed;
- if (pop->params[1] & 0x1000000)
- *postinc += inc;
- }
-
- tmp = format_tbl[pop->format].opsz + format_tbl[pop->format].dispsz;
- regs->pc += tmp >> 3;
-
- /* handle MOV_Lcc, which are currently the only FMT_D10 insns that
- * access memory */
- if (pop->format == FMT_D10)
- misalignment_MOV_Lcc(regs, opcode);
-
- set_fs(seg);
-}
-
-/*
- * determine the address that was being accessed
- */
-static int misalignment_addr(unsigned long *registers, unsigned long sp,
- unsigned params, unsigned opcode,
- unsigned long disp,
- void **_address, unsigned long **_postinc,
- unsigned long *_inc)
-{
- unsigned long *postinc = NULL, address = 0, tmp;
-
- if (!(params & 0x1000000)) {
- kdebug("noinc");
- *_inc = 0;
- _inc = NULL;
- }
-
- params &= 0x00ffffff;
-
- do {
- switch (params & 0xff) {
- case DM0:
- postinc = &registers[Dreg_index[opcode & 0x03]];
- address += *postinc;
- break;
- case DM1:
- postinc = &registers[Dreg_index[opcode >> 2 & 0x03]];
- address += *postinc;
- break;
- case DM2:
- postinc = &registers[Dreg_index[opcode >> 4 & 0x03]];
- address += *postinc;
- break;
- case AM0:
- postinc = &registers[Areg_index[opcode & 0x03]];
- address += *postinc;
- break;
- case AM1:
- postinc = &registers[Areg_index[opcode >> 2 & 0x03]];
- address += *postinc;
- break;
- case AM2:
- postinc = &registers[Areg_index[opcode >> 4 & 0x03]];
- address += *postinc;
- break;
- case RM0:
- postinc = &registers[Rreg_index[opcode & 0x0f]];
- address += *postinc;
- break;
- case RM1:
- postinc = &registers[Rreg_index[opcode >> 2 & 0x0f]];
- address += *postinc;
- break;
- case RM2:
- postinc = &registers[Rreg_index[opcode >> 4 & 0x0f]];
- address += *postinc;
- break;
- case RM4:
- postinc = &registers[Rreg_index[opcode >> 8 & 0x0f]];
- address += *postinc;
- break;
- case RM6:
- postinc = &registers[Rreg_index[opcode >> 12 & 0x0f]];
- address += *postinc;
- break;
- case RD0:
- postinc = &registers[Rreg_index[disp & 0x0f]];
- address += *postinc;
- break;
- case RD2:
- postinc = &registers[Rreg_index[disp >> 4 & 0x0f]];
- address += *postinc;
- break;
- case SP:
- address += sp;
- break;
-
- /* displacements are either to be added to the address
- * before use, or, in the case of post-inc addressing,
- * to be added into the base register after use */
- case SD8:
- case SIMM8:
- disp = (long) (int8_t) (disp & 0xff);
- goto displace_or_inc;
- case SD16:
- disp = (long) (int16_t) (disp & 0xffff);
- goto displace_or_inc;
- case SD24:
- tmp = disp << 8;
- asm("asr 8,%0" : "=r"(tmp) : "0"(tmp) : "cc");
- disp = (long) tmp;
- goto displace_or_inc;
- case SIMM4_2:
- tmp = opcode >> 4 & 0x0f;
- tmp <<= 28;
- asm("asr 28,%0" : "=r"(tmp) : "0"(tmp) : "cc");
- disp = (long) tmp;
- goto displace_or_inc;
- case IMM8:
- disp &= 0x000000ff;
- goto displace_or_inc;
- case IMM16:
- disp &= 0x0000ffff;
- goto displace_or_inc;
- case IMM24:
- disp &= 0x00ffffff;
- goto displace_or_inc;
- case IMM32:
- case IMM32_MEM:
- case IMM32_HIGH8:
- case IMM32_HIGH8_MEM:
- displace_or_inc:
- kdebug("%s %lx", _inc ? "incr" : "disp", disp);
- if (!_inc)
- address += disp;
- else
- *_inc = disp;
- break;
- default:
- BUG();
- return 0;
- }
- } while ((params >>= 8));
-
- *_address = (void *) address;
- *_postinc = postinc;
- return 1;
-}
-
-/*
- * determine the register that is acting as source/dest
- */
-static int misalignment_reg(unsigned long *registers, unsigned params,
- unsigned opcode, unsigned long disp,
- unsigned long **_register)
-{
- params &= 0x7fffffff;
-
- if (params & 0xffffff00)
- return 0;
-
- switch (params & 0xff) {
- case DM0:
- *_register = &registers[Dreg_index[opcode & 0x03]];
- break;
- case DM1:
- *_register = &registers[Dreg_index[opcode >> 2 & 0x03]];
- break;
- case DM2:
- *_register = &registers[Dreg_index[opcode >> 4 & 0x03]];
- break;
- case AM0:
- *_register = &registers[Areg_index[opcode & 0x03]];
- break;
- case AM1:
- *_register = &registers[Areg_index[opcode >> 2 & 0x03]];
- break;
- case AM2:
- *_register = &registers[Areg_index[opcode >> 4 & 0x03]];
- break;
- case RM0:
- *_register = &registers[Rreg_index[opcode & 0x0f]];
- break;
- case RM1:
- *_register = &registers[Rreg_index[opcode >> 2 & 0x0f]];
- break;
- case RM2:
- *_register = &registers[Rreg_index[opcode >> 4 & 0x0f]];
- break;
- case RM4:
- *_register = &registers[Rreg_index[opcode >> 8 & 0x0f]];
- break;
- case RM6:
- *_register = &registers[Rreg_index[opcode >> 12 & 0x0f]];
- break;
- case RD0:
- *_register = &registers[Rreg_index[disp & 0x0f]];
- break;
- case RD2:
- *_register = &registers[Rreg_index[disp >> 4 & 0x0f]];
- break;
- case SP:
- *_register = &registers[REG_SP >> 2];
- break;
-
- default:
- BUG();
- return 0;
- }
-
- return 1;
-}
-
-/*
- * handle the conditional loop part of the move-and-loop instructions
- */
-static void misalignment_MOV_Lcc(struct pt_regs *regs, uint32_t opcode)
-{
- unsigned long epsw = regs->epsw;
- unsigned long NxorV;
-
- kdebug("MOV_Lcc %x [flags=%lx]", opcode, epsw & 0xf);
-
- /* calculate N^V and shift onto the same bit position as Z */
- NxorV = ((epsw >> 3) ^ epsw >> 1) & 1;
-
- switch (opcode & 0xf) {
- case 0x0: /* MOV_LLT: N^V */
- if (NxorV)
- goto take_the_loop;
- return;
- case 0x1: /* MOV_LGT: ~(Z or (N^V))*/
- if (!((epsw & EPSW_FLAG_Z) | NxorV))
- goto take_the_loop;
- return;
- case 0x2: /* MOV_LGE: ~(N^V) */
- if (!NxorV)
- goto take_the_loop;
- return;
- case 0x3: /* MOV_LLE: Z or (N^V) */
- if ((epsw & EPSW_FLAG_Z) | NxorV)
- goto take_the_loop;
- return;
-
- case 0x4: /* MOV_LCS: C */
- if (epsw & EPSW_FLAG_C)
- goto take_the_loop;
- return;
- case 0x5: /* MOV_LHI: ~(C or Z) */
- if (!(epsw & (EPSW_FLAG_C | EPSW_FLAG_Z)))
- goto take_the_loop;
- return;
- case 0x6: /* MOV_LCC: ~C */
- if (!(epsw & EPSW_FLAG_C))
- goto take_the_loop;
- return;
- case 0x7: /* MOV_LLS: C or Z */
- if (epsw & (EPSW_FLAG_C | EPSW_FLAG_Z))
- goto take_the_loop;
- return;
-
- case 0x8: /* MOV_LEQ: Z */
- if (epsw & EPSW_FLAG_Z)
- goto take_the_loop;
- return;
- case 0x9: /* MOV_LNE: ~Z */
- if (!(epsw & EPSW_FLAG_Z))
- goto take_the_loop;
- return;
- case 0xa: /* MOV_LRA: always */
- goto take_the_loop;
-
- default:
- BUG();
- }
-
-take_the_loop:
- /* wind the PC back to just after the SETLB insn */
- kdebug("loop LAR=%lx", regs->lar);
- regs->pc = regs->lar - 4;
-}
-
-/*
- * misalignment handler tests
- */
-#ifdef CONFIG_TEST_MISALIGNMENT_HANDLER
-static u8 __initdata testbuf[512] __attribute__((aligned(16))) = {
- [257] = 0x11,
- [258] = 0x22,
- [259] = 0x33,
- [260] = 0x44,
-};
-
-#define ASSERTCMP(X, OP, Y) \
-do { \
- if (unlikely(!((X) OP (Y)))) { \
- printk(KERN_ERR "\n"); \
- printk(KERN_ERR "MISALIGN: Assertion failed at line %u\n", \
- __LINE__); \
- printk(KERN_ERR "0x%lx " #OP " 0x%lx is false\n", \
- (unsigned long)(X), (unsigned long)(Y)); \
- BUG(); \
- } \
-} while(0)
-
-static int __init test_misalignment(void)
-{
- register void *r asm("e0");
- register u32 y asm("e1");
- void *p = testbuf, *q;
- u32 tmp, tmp2, x;
-
- printk(KERN_NOTICE "==>test_misalignment() [testbuf=%p]\n", p);
- p++;
-
- printk(KERN_NOTICE "___ MOV (Am),Dn ___\n");
- q = p + 256;
- asm volatile("mov (%0),%1" : "+a"(q), "=d"(x));
- ASSERTCMP(q, ==, p + 256);
- ASSERTCMP(x, ==, 0x44332211);
-
- printk(KERN_NOTICE "___ MOV (256,Am),Dn ___\n");
- q = p;
- asm volatile("mov (256,%0),%1" : "+a"(q), "=d"(x));
- ASSERTCMP(q, ==, p);
- ASSERTCMP(x, ==, 0x44332211);
-
- printk(KERN_NOTICE "___ MOV (Di,Am),Dn ___\n");
- tmp = 256;
- q = p;
- asm volatile("mov (%2,%0),%1" : "+a"(q), "=d"(x), "+d"(tmp));
- ASSERTCMP(q, ==, p);
- ASSERTCMP(x, ==, 0x44332211);
- ASSERTCMP(tmp, ==, 256);
-
- printk(KERN_NOTICE "___ MOV (256,Rm),Rn ___\n");
- r = p;
- asm volatile("mov (256,%0),%1" : "+r"(r), "=r"(y));
- ASSERTCMP(r, ==, p);
- ASSERTCMP(y, ==, 0x44332211);
-
- printk(KERN_NOTICE "___ MOV (Rm+),Rn ___\n");
- r = p + 256;
- asm volatile("mov (%0+),%1" : "+r"(r), "=r"(y));
- ASSERTCMP(r, ==, p + 256 + 4);
- ASSERTCMP(y, ==, 0x44332211);
-
- printk(KERN_NOTICE "___ MOV (Rm+,8),Rn ___\n");
- r = p + 256;
- asm volatile("mov (%0+,8),%1" : "+r"(r), "=r"(y));
- ASSERTCMP(r, ==, p + 256 + 8);
- ASSERTCMP(y, ==, 0x44332211);
-
- printk(KERN_NOTICE "___ MOV (7,SP),Rn ___\n");
- asm volatile(
- "add -16,sp \n"
- "mov +0x11,%0 \n"
- "movbu %0,(7,sp) \n"
- "mov +0x22,%0 \n"
- "movbu %0,(8,sp) \n"
- "mov +0x33,%0 \n"
- "movbu %0,(9,sp) \n"
- "mov +0x44,%0 \n"
- "movbu %0,(10,sp) \n"
- "mov (7,sp),%1 \n"
- "add +16,sp \n"
- : "+a"(q), "=d"(x));
- ASSERTCMP(x, ==, 0x44332211);
-
- printk(KERN_NOTICE "___ MOV (259,SP),Rn ___\n");
- asm volatile(
- "add -264,sp \n"
- "mov +0x11,%0 \n"
- "movbu %0,(259,sp) \n"
- "mov +0x22,%0 \n"
- "movbu %0,(260,sp) \n"
- "mov +0x33,%0 \n"
- "movbu %0,(261,sp) \n"
- "mov +0x55,%0 \n"
- "movbu %0,(262,sp) \n"
- "mov (259,sp),%1 \n"
- "add +264,sp \n"
- : "+d"(tmp), "=d"(x));
- ASSERTCMP(x, ==, 0x55332211);
-
- printk(KERN_NOTICE "___ MOV (260,SP),Rn ___\n");
- asm volatile(
- "add -264,sp \n"
- "mov +0x11,%0 \n"
- "movbu %0,(260,sp) \n"
- "mov +0x22,%0 \n"
- "movbu %0,(261,sp) \n"
- "mov +0x33,%0 \n"
- "movbu %0,(262,sp) \n"
- "mov +0x55,%0 \n"
- "movbu %0,(263,sp) \n"
- "mov (260,sp),%1 \n"
- "add +264,sp \n"
- : "+d"(tmp), "=d"(x));
- ASSERTCMP(x, ==, 0x55332211);
-
-
- printk(KERN_NOTICE "___ MOV_LNE ___\n");
- tmp = 1;
- tmp2 = 2;
- q = p + 256;
- asm volatile(
- "setlb \n"
- "mov %2,%3 \n"
- "mov %1,%2 \n"
- "cmp +0,%1 \n"
- "mov_lne (%0+,4),%1"
- : "+r"(q), "+d"(tmp), "+d"(tmp2), "=d"(x)
- :
- : "cc");
- ASSERTCMP(q, ==, p + 256 + 12);
- ASSERTCMP(x, ==, 0x44332211);
-
- printk(KERN_NOTICE "___ MOV in SETLB ___\n");
- tmp = 1;
- tmp2 = 2;
- q = p + 256;
- asm volatile(
- "setlb \n"
- "mov %1,%3 \n"
- "mov (%0+),%1 \n"
- "cmp +0,%1 \n"
- "lne "
- : "+a"(q), "+d"(tmp), "+d"(tmp2), "=d"(x)
- :
- : "cc");
-
- ASSERTCMP(q, ==, p + 256 + 8);
- ASSERTCMP(x, ==, 0x44332211);
-
- printk(KERN_NOTICE "<==test_misalignment()\n");
- return 0;
-}
-
-arch_initcall(test_misalignment);
-
-#endif /* CONFIG_TEST_MISALIGNMENT_HANDLER */
diff --git a/arch/mn10300/mm/mmu-context.c b/arch/mn10300/mm/mmu-context.c
deleted file mode 100644
index a4f7d3dcc6e6..000000000000
--- a/arch/mn10300/mm/mmu-context.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/* MN10300 MMU context allocation and management
- *
- * 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/sched.h>
-#include <linux/mm.h>
-#include <asm/mmu_context.h>
-#include <asm/tlbflush.h>
-
-#ifdef CONFIG_MN10300_TLB_USE_PIDR
-/*
- * list of the MMU contexts last allocated on each CPU
- */
-unsigned long mmu_context_cache[NR_CPUS] = {
- [0 ... NR_CPUS - 1] =
- MMU_CONTEXT_FIRST_VERSION * 2 - (1 - MMU_CONTEXT_TLBPID_LOCK_NR),
-};
-#endif /* CONFIG_MN10300_TLB_USE_PIDR */
-
-/*
- * preemptively set a TLB entry
- */
-void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
-{
- unsigned long pteu, ptel, cnx, flags;
- pte_t pte = *ptep;
-
- addr &= PAGE_MASK;
- ptel = pte_val(pte) & ~(xPTEL_UNUSED1 | xPTEL_UNUSED2);
-
- /* make sure the context doesn't migrate and defend against
- * interference from vmalloc'd regions */
- local_irq_save(flags);
-
- cnx = ~MMU_NO_CONTEXT;
-#ifdef CONFIG_MN10300_TLB_USE_PIDR
- cnx = mm_context(vma->vm_mm);
-#endif
-
- if (cnx != MMU_NO_CONTEXT) {
- pteu = addr;
-#ifdef CONFIG_MN10300_TLB_USE_PIDR
- pteu |= cnx & MMU_CONTEXT_TLBPID_MASK;
-#endif
- if (!(pte_val(pte) & _PAGE_NX)) {
- IPTEU = pteu;
- if (IPTEL & xPTEL_V)
- IPTEL = ptel;
- }
- DPTEU = pteu;
- if (DPTEL & xPTEL_V)
- DPTEL = ptel;
- }
-
- local_irq_restore(flags);
-}
diff --git a/arch/mn10300/mm/pgtable.c b/arch/mn10300/mm/pgtable.c
deleted file mode 100644
index 9577cf768875..000000000000
--- a/arch/mn10300/mm/pgtable.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/* MN10300 Page table management
- *
- * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
- * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
- * Modified 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/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/gfp.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/smp.h>
-#include <linux/highmem.h>
-#include <linux/pagemap.h>
-#include <linux/spinlock.h>
-#include <linux/quicklist.h>
-
-#include <asm/pgtable.h>
-#include <asm/pgalloc.h>
-#include <asm/tlb.h>
-#include <asm/tlbflush.h>
-
-/*
- * Associate a large virtual page frame with a given physical page frame
- * and protection flags for that frame. pfn is for the base of the page,
- * vaddr is what the page gets mapped to - both must be properly aligned.
- * The pmd must already be instantiated. Assumes PAE mode.
- */
-void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags)
-{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
-
- if (vaddr & (PMD_SIZE-1)) { /* vaddr is misaligned */
- printk(KERN_ERR "set_pmd_pfn: vaddr misaligned\n");
- return; /* BUG(); */
- }
- if (pfn & (PTRS_PER_PTE-1)) { /* pfn is misaligned */
- printk(KERN_ERR "set_pmd_pfn: pfn misaligned\n");
- return; /* BUG(); */
- }
- pgd = swapper_pg_dir + pgd_index(vaddr);
- if (pgd_none(*pgd)) {
- printk(KERN_ERR "set_pmd_pfn: pgd_none\n");
- return; /* BUG(); */
- }
- pud = pud_offset(pgd, vaddr);
- pmd = pmd_offset(pud, vaddr);
- set_pmd(pmd, pfn_pmd(pfn, flags));
- /*
- * It's enough to flush this one mapping.
- * (PGE mappings get flushed as well)
- */
- local_flush_tlb_one(vaddr);
-}
-
-pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
-{
- pte_t *pte = (pte_t *)__get_free_page(GFP_KERNEL);
- if (pte)
- clear_page(pte);
- return pte;
-}
-
-struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
-{
- struct page *pte;
-
-#ifdef CONFIG_HIGHPTE
- pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM, 0);
-#else
- pte = alloc_pages(GFP_KERNEL, 0);
-#endif
- if (!pte)
- return NULL;
- clear_highpage(pte);
- if (!pgtable_page_ctor(pte)) {
- __free_page(pte);
- return NULL;
- }
- return pte;
-}
-
-/*
- * List of all pgd's needed for non-PAE so it can invalidate entries
- * in both cached and uncached pgd's; not needed for PAE since the
- * kernel pmd is shared. If PAE were not to share the pmd a similar
- * tactic would be needed. This is essentially codepath-based locking
- * against pageattr.c; it is the unique case in which a valid change
- * of kernel pagetables can't be lazily synchronized by vmalloc faults.
- * vmalloc faults work because attached pagetables are never freed.
- * If the locking proves to be non-performant, a ticketing scheme with
- * checks at dup_mmap(), exec(), and other mmlist addition points
- * could be used. The locking scheme was chosen on the basis of
- * manfred's recommendations and having no core impact whatsoever.
- * -- nyc
- */
-DEFINE_SPINLOCK(pgd_lock);
-struct page *pgd_list;
-
-static inline void pgd_list_add(pgd_t *pgd)
-{
- struct page *page = virt_to_page(pgd);
- page->index = (unsigned long) pgd_list;
- if (pgd_list)
- set_page_private(pgd_list, (unsigned long) &page->index);
- pgd_list = page;
- set_page_private(page, (unsigned long) &pgd_list);
-}
-
-static inline void pgd_list_del(pgd_t *pgd)
-{
- struct page *next, **pprev, *page = virt_to_page(pgd);
- next = (struct page *) page->index;
- pprev = (struct page **) page_private(page);
- *pprev = next;
- if (next)
- set_page_private(next, (unsigned long) pprev);
-}
-
-void pgd_ctor(void *pgd)
-{
- unsigned long flags;
-
- if (PTRS_PER_PMD == 1)
- spin_lock_irqsave(&pgd_lock, flags);
-
- memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
- swapper_pg_dir + USER_PTRS_PER_PGD,
- (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
-
- if (PTRS_PER_PMD > 1)
- return;
-
- pgd_list_add(pgd);
- spin_unlock_irqrestore(&pgd_lock, flags);
- memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
-}
-
-/* never called when PTRS_PER_PMD > 1 */
-void pgd_dtor(void *pgd)
-{
- unsigned long flags; /* can be called from interrupt context */
-
- spin_lock_irqsave(&pgd_lock, flags);
- pgd_list_del(pgd);
- spin_unlock_irqrestore(&pgd_lock, flags);
-}
-
-pgd_t *pgd_alloc(struct mm_struct *mm)
-{
- return quicklist_alloc(0, GFP_KERNEL, pgd_ctor);
-}
-
-void pgd_free(struct mm_struct *mm, pgd_t *pgd)
-{
- quicklist_free(0, pgd_dtor, pgd);
-}
-
-void __init pgtable_cache_init(void)
-{
-}
-
-void check_pgt_cache(void)
-{
- quicklist_trim(0, pgd_dtor, 25, 16);
-}
diff --git a/arch/mn10300/mm/tlb-mn10300.S b/arch/mn10300/mm/tlb-mn10300.S
deleted file mode 100644
index b9940177d81b..000000000000
--- a/arch/mn10300/mm/tlb-mn10300.S
+++ /dev/null
@@ -1,220 +0,0 @@
-###############################################################################
-#
-# TLB loading functions
-#
-# Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd.
-# Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
-# Modified 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/intctl-regs.h>
-#include <asm/frame.inc>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-
-###############################################################################
-#
-# Instruction TLB Miss handler entry point
-#
-###############################################################################
- .type itlb_miss,@function
-ENTRY(itlb_miss)
-#ifdef CONFIG_GDBSTUB
- movm [d2,d3,a2],(sp)
-#else
- or EPSW_nAR,epsw # switch D0-D3 & A0-A3 to the alternate
- # register bank
- nop
- nop
- nop
-#endif
-
-#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
- mov (MMUCTR),d2
- mov d2,(MMUCTR)
-#endif
-
- and ~EPSW_NMID,epsw
- mov (IPTEU),d3
- mov (PTBR),a2
- mov d3,d2
- and 0xffc00000,d2
- lsr 20,d2
- mov (a2,d2),a2 # PTD *ptd = PGD[addr 31..22]
- btst _PAGE_VALID,a2
- beq itlb_miss_fault # jump if doesn't point anywhere
-
- and ~(PAGE_SIZE-1),a2
- mov d3,d2
- and 0x003ff000,d2
- lsr 10,d2
- add d2,a2
- mov (a2),d2 # get pte from PTD[addr 21..12]
- btst _PAGE_VALID,d2
- beq itlb_miss_fault # jump if doesn't point to a page
- # (might be a swap id)
-#if ((_PAGE_ACCESSED & 0xffffff00) == 0)
- bset _PAGE_ACCESSED,(0,a2)
-#elif ((_PAGE_ACCESSED & 0xffff00ff) == 0)
- bset +(_PAGE_ACCESSED >> 8),(1,a2)
-#else
-#error "_PAGE_ACCESSED value is out of range"
-#endif
- and ~xPTEL2_UNUSED1,d2
-itlb_miss_set:
- mov d2,(IPTEL2) # change the TLB
-#ifdef CONFIG_GDBSTUB
- movm (sp),[d2,d3,a2]
-#endif
- rti
-
-itlb_miss_fault:
- mov _PAGE_VALID,d2 # force address error handler to be
- # invoked
- bra itlb_miss_set
-
- .size itlb_miss, . - itlb_miss
-
-###############################################################################
-#
-# Data TLB Miss handler entry point
-#
-###############################################################################
- .type dtlb_miss,@function
-ENTRY(dtlb_miss)
-#ifdef CONFIG_GDBSTUB
- movm [d2,d3,a2],(sp)
-#else
- or EPSW_nAR,epsw # switch D0-D3 & A0-A3 to the alternate
- # register bank
- nop
- nop
- nop
-#endif
-
-#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
- mov (MMUCTR),d2
- mov d2,(MMUCTR)
-#endif
-
- and ~EPSW_NMID,epsw
- mov (DPTEU),d3
- mov (PTBR),a2
- mov d3,d2
- and 0xffc00000,d2
- lsr 20,d2
- mov (a2,d2),a2 # PTD *ptd = PGD[addr 31..22]
- btst _PAGE_VALID,a2
- beq dtlb_miss_fault # jump if doesn't point anywhere
-
- and ~(PAGE_SIZE-1),a2
- mov d3,d2
- and 0x003ff000,d2
- lsr 10,d2
- add d2,a2
- mov (a2),d2 # get pte from PTD[addr 21..12]
- btst _PAGE_VALID,d2
- beq dtlb_miss_fault # jump if doesn't point to a page
- # (might be a swap id)
-#if ((_PAGE_ACCESSED & 0xffffff00) == 0)
- bset _PAGE_ACCESSED,(0,a2)
-#elif ((_PAGE_ACCESSED & 0xffff00ff) == 0)
- bset +(_PAGE_ACCESSED >> 8),(1,a2)
-#else
-#error "_PAGE_ACCESSED value is out of range"
-#endif
- and ~xPTEL2_UNUSED1,d2
-dtlb_miss_set:
- mov d2,(DPTEL2) # change the TLB
-#ifdef CONFIG_GDBSTUB
- movm (sp),[d2,d3,a2]
-#endif
- rti
-
-dtlb_miss_fault:
- mov _PAGE_VALID,d2 # force address error handler to be
- # invoked
- bra dtlb_miss_set
- .size dtlb_miss, . - dtlb_miss
-
-###############################################################################
-#
-# Instruction TLB Address Error handler entry point
-#
-###############################################################################
- .type itlb_aerror,@function
-ENTRY(itlb_aerror)
- add -4,sp
- SAVE_ALL
-
-#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
- mov (MMUCTR),d1
- mov d1,(MMUCTR)
-#endif
-
- and ~EPSW_NMID,epsw
- add -4,sp # need to pass three params
-
- # calculate the fault code
- movhu (MMUFCR_IFC),d1
- or 0x00010000,d1 # it's an instruction fetch
-
- # determine the page address
- mov (IPTEU),d0
- and PAGE_MASK,d0
- mov d0,(12,sp)
-
- clr d0
- mov d0,(IPTEL2)
-
- or EPSW_IE,epsw
- mov fp,d0
- call do_page_fault[],0 # do_page_fault(regs,code,addr
-
- jmp ret_from_exception
- .size itlb_aerror, . - itlb_aerror
-
-###############################################################################
-#
-# Data TLB Address Error handler entry point
-#
-###############################################################################
- .type dtlb_aerror,@function
-ENTRY(dtlb_aerror)
- add -4,sp
- SAVE_ALL
-
-#if defined(CONFIG_ERRATUM_NEED_TO_RELOAD_MMUCTR)
- mov (MMUCTR),d1
- mov d1,(MMUCTR)
-#endif
-
- add -4,sp # need to pass three params
- and ~EPSW_NMID,epsw
-
- # calculate the fault code
- movhu (MMUFCR_DFC),d1
-
- # determine the page address
- mov (DPTEU),a2
- mov a2,d0
- and PAGE_MASK,d0
- mov d0,(12,sp)
-
- clr d0
- mov d0,(DPTEL2)
-
- or EPSW_IE,epsw
- mov fp,d0
- call do_page_fault[],0 # do_page_fault(regs,code,addr
-
- jmp ret_from_exception
- .size dtlb_aerror, . - dtlb_aerror
diff --git a/arch/mn10300/mm/tlb-smp.c b/arch/mn10300/mm/tlb-smp.c
deleted file mode 100644
index 085f2bb691ac..000000000000
--- a/arch/mn10300/mm/tlb-smp.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/* SMP TLB support routines.
- *
- * Copyright (C) 2006-2008 Panasonic Corporation
- * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <linux/jiffies.h>
-#include <linux/cpumask.h>
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/sched/mm.h>
-#include <linux/profile.h>
-#include <linux/smp.h>
-#include <asm/tlbflush.h>
-#include <asm/bitops.h>
-#include <asm/processor.h>
-#include <asm/bug.h>
-#include <asm/exceptions.h>
-#include <asm/hardirq.h>
-#include <asm/fpu.h>
-#include <asm/mmu_context.h>
-#include <asm/thread_info.h>
-#include <asm/cpu-regs.h>
-#include <asm/intctl-regs.h>
-
-/*
- * For flush TLB
- */
-#define FLUSH_ALL 0xffffffff
-
-static cpumask_t flush_cpumask;
-static struct mm_struct *flush_mm;
-static unsigned long flush_va;
-static DEFINE_SPINLOCK(tlbstate_lock);
-
-DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = {
- &init_mm, 0
-};
-
-static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
- unsigned long va);
-static void do_flush_tlb_all(void *info);
-
-/**
- * smp_flush_tlb - Callback to invalidate the TLB.
- * @unused: Callback context (ignored).
- */
-void smp_flush_tlb(void *unused)
-{
- unsigned long cpu_id;
-
- cpu_id = get_cpu();
-
- if (!cpumask_test_cpu(cpu_id, &flush_cpumask))
- /* This was a BUG() but until someone can quote me the line
- * from the intel manual that guarantees an IPI to multiple
- * CPUs is retried _only_ on the erroring CPUs its staying as a
- * return
- *
- * BUG();
- */
- goto out;
-
- if (flush_va == FLUSH_ALL)
- local_flush_tlb();
- else
- local_flush_tlb_page(flush_mm, flush_va);
-
- smp_mb__before_atomic();
- cpumask_clear_cpu(cpu_id, &flush_cpumask);
- smp_mb__after_atomic();
-out:
- put_cpu();
-}
-
-/**
- * flush_tlb_others - Tell the specified CPUs to invalidate their TLBs
- * @cpumask: The list of CPUs to target.
- * @mm: The VM context to flush from (if va!=FLUSH_ALL).
- * @va: Virtual address to flush or FLUSH_ALL to flush everything.
- */
-static void flush_tlb_others(cpumask_t cpumask, struct mm_struct *mm,
- unsigned long va)
-{
- cpumask_t tmp;
-
- /* A couple of sanity checks (to be removed):
- * - mask must not be empty
- * - current CPU must not be in mask
- * - we do not send IPIs to as-yet unbooted CPUs.
- */
- BUG_ON(!mm);
- BUG_ON(cpumask_empty(&cpumask));
- BUG_ON(cpumask_test_cpu(smp_processor_id(), &cpumask));
-
- cpumask_and(&tmp, &cpumask, cpu_online_mask);
- BUG_ON(!cpumask_equal(&cpumask, &tmp));
-
- /* I'm not happy about this global shared spinlock in the MM hot path,
- * but we'll see how contended it is.
- *
- * Temporarily this turns IRQs off, so that lockups are detected by the
- * NMI watchdog.
- */
- spin_lock(&tlbstate_lock);
-
- flush_mm = mm;
- flush_va = va;
-#if NR_CPUS <= BITS_PER_LONG
- atomic_or(cpumask.bits[0], (atomic_t *)&flush_cpumask.bits[0]);
-#else
-#error Not supported.
-#endif
-
- /* FIXME: if NR_CPUS>=3, change send_IPI_mask */
- smp_call_function(smp_flush_tlb, NULL, 1);
-
- while (!cpumask_empty(&flush_cpumask))
- /* Lockup detection does not belong here */
- smp_mb();
-
- flush_mm = NULL;
- flush_va = 0;
- spin_unlock(&tlbstate_lock);
-}
-
-/**
- * flush_tlb_mm - Invalidate TLB of specified VM context
- * @mm: The VM context to invalidate.
- */
-void flush_tlb_mm(struct mm_struct *mm)
-{
- cpumask_t cpu_mask;
-
- preempt_disable();
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
-
- local_flush_tlb();
- if (!cpumask_empty(&cpu_mask))
- flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
-
- preempt_enable();
-}
-
-/**
- * flush_tlb_current_task - Invalidate TLB of current task
- */
-void flush_tlb_current_task(void)
-{
- struct mm_struct *mm = current->mm;
- cpumask_t cpu_mask;
-
- preempt_disable();
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
-
- local_flush_tlb();
- if (!cpumask_empty(&cpu_mask))
- flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
-
- preempt_enable();
-}
-
-/**
- * flush_tlb_page - Invalidate TLB of page
- * @vma: The VM context to invalidate the page for.
- * @va: The virtual address of the page to invalidate.
- */
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
-{
- struct mm_struct *mm = vma->vm_mm;
- cpumask_t cpu_mask;
-
- preempt_disable();
- cpumask_copy(&cpu_mask, mm_cpumask(mm));
- cpumask_clear_cpu(smp_processor_id(), &cpu_mask);
-
- local_flush_tlb_page(mm, va);
- if (!cpumask_empty(&cpu_mask))
- flush_tlb_others(cpu_mask, mm, va);
-
- preempt_enable();
-}
-
-/**
- * do_flush_tlb_all - Callback to completely invalidate a TLB
- * @unused: Callback context (ignored).
- */
-static void do_flush_tlb_all(void *unused)
-{
- local_flush_tlb_all();
-}
-
-/**
- * flush_tlb_all - Completely invalidate TLBs on all CPUs
- */
-void flush_tlb_all(void)
-{
- on_each_cpu(do_flush_tlb_all, 0, 1);
-}