2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* This file is subject to the terms and conditions of the GNU General Public
|
|
|
|
* License. See the file "COPYING" in the main directory of this archive
|
|
|
|
* for more details.
|
|
|
|
*
|
2011-04-05 05:15:29 +08:00
|
|
|
* Copyright (C) 1996 David S. Miller (davem@davemloft.net)
|
2005-04-17 06:20:36 +08:00
|
|
|
* Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Ralf Baechle (ralf@gnu.org)
|
|
|
|
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
|
|
|
|
*/
|
2014-03-04 18:23:57 +08:00
|
|
|
#include <linux/cpu_pm.h>
|
2007-11-03 09:01:37 +08:00
|
|
|
#include <linux/hardirq.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/init.h>
|
2007-09-28 01:26:43 +08:00
|
|
|
#include <linux/highmem.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/kernel.h>
|
2007-10-12 06:46:05 +08:00
|
|
|
#include <linux/linkage.h>
|
2013-09-17 18:44:31 +08:00
|
|
|
#include <linux/preempt.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/sched.h>
|
2009-06-19 21:05:26 +08:00
|
|
|
#include <linux/smp.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/mm.h>
|
2016-08-22 03:58:14 +08:00
|
|
|
#include <linux/export.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/bitops.h>
|
2021-02-10 17:56:39 +08:00
|
|
|
#include <linux/dma-map-ops.h> /* for dma_default_coherent */
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
#include <asm/bcache.h>
|
|
|
|
#include <asm/bootinfo.h>
|
2005-07-13 19:48:45 +08:00
|
|
|
#include <asm/cache.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <asm/cacheops.h>
|
|
|
|
#include <asm/cpu.h>
|
|
|
|
#include <asm/cpu-features.h>
|
2013-09-17 16:25:47 +08:00
|
|
|
#include <asm/cpu-type.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <asm/io.h>
|
|
|
|
#include <asm/page.h>
|
|
|
|
#include <asm/r4kcache.h>
|
2007-07-28 19:45:47 +08:00
|
|
|
#include <asm/sections.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <asm/mmu_context.h>
|
2005-04-26 00:36:23 +08:00
|
|
|
#include <asm/cacheflush.h> /* for run_uncached() */
|
2012-05-15 15:04:49 +08:00
|
|
|
#include <asm/traps.h>
|
2017-08-13 10:49:41 +08:00
|
|
|
#include <asm/mips-cps.h>
|
2006-05-12 20:20:06 +08:00
|
|
|
|
2016-07-13 21:12:50 +08:00
|
|
|
/*
|
|
|
|
* Bits describing what cache ops an SMP callback function may perform.
|
|
|
|
*
|
|
|
|
* R4K_HIT - Virtual user or kernel address based cache operations. The
|
|
|
|
* active_mm must be checked before using user addresses, falling
|
|
|
|
* back to kmap.
|
|
|
|
* R4K_INDEX - Index based cache operations.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define R4K_HIT BIT(0)
|
|
|
|
#define R4K_INDEX BIT(1)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* r4k_op_needs_ipi() - Decide if a cache op needs to be done on every core.
|
|
|
|
* @type: Type of cache operations (R4K_HIT or R4K_INDEX).
|
|
|
|
*
|
|
|
|
* Decides whether a cache op needs to be performed on every core in the system.
|
2016-07-13 21:12:52 +08:00
|
|
|
* This may change depending on the @type of cache operation, as well as the set
|
|
|
|
* of online CPUs, so preemption should be disabled by the caller to prevent CPU
|
|
|
|
* hotplug from changing the result.
|
2016-07-13 21:12:50 +08:00
|
|
|
*
|
|
|
|
* Returns: 1 if the cache operation @type should be done on every core in
|
|
|
|
* the system.
|
|
|
|
* 0 if the cache operation @type is globalized and only needs to
|
|
|
|
* be performed on a simple CPU.
|
|
|
|
*/
|
|
|
|
static inline bool r4k_op_needs_ipi(unsigned int type)
|
|
|
|
{
|
|
|
|
/* The MIPS Coherence Manager (CM) globalizes address-based cache ops */
|
MIPS: c-r4k: Use SMP calls for CM indexed cache ops
The MIPS Coherence Manager (CM) can propagate address-based ("hit")
cache operations to other cores in the coherent system, alleviating
software of the need to use SMP calls, however indexed cache operations
are not propagated by hardware since doing so makes no sense for
separate caches.
Update r4k_op_needs_ipi() to report that only hit cache operations are
globalized by the CM, requiring indexed cache operations to be
globalized by software via an SMP call.
r4k_on_each_cpu() previously had a special case for CONFIG_MIPS_MT_SMP,
intended to avoid the SMP calls when the only other CPUs in the system
were other VPEs in the same core, and hence sharing the same caches.
This was changed by commit cccf34e9411c ("MIPS: c-r4k: Fix cache
flushing for MT cores") to apparently handle multi-core multi-VPE
systems, but it focussed mainly on hit cache ops, so the SMP calls were
still disabled entirely for CM systems.
This doesn't normally cause problems, but tests can be written to hit
these corner cases by using multiple threads, or changing task
affinities to force the process to migrate cores. For example the
failure of mprotect RW->RX to globally sync icaches (via
flush_cache_range) can be detected by modifying and mprotecting a code
page on one core, and migrating to a different core to execute from it.
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Leonid Yegoshin <leonid.yegoshin@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/13807/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2016-07-13 21:12:56 +08:00
|
|
|
if (type == R4K_HIT && mips_cm_present())
|
2016-07-13 21:12:50 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Hardware doesn't globalize the required cache ops, so SMP calls may
|
2016-07-13 21:12:52 +08:00
|
|
|
* be needed, but only if there are foreign CPUs (non-siblings with
|
|
|
|
* separate caches).
|
2016-07-13 21:12:50 +08:00
|
|
|
*/
|
2016-07-13 21:12:52 +08:00
|
|
|
/* cpu_foreign_map[] undeclared when !CONFIG_SMP */
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
return !cpumask_empty(&cpu_foreign_map[0]);
|
|
|
|
#else
|
|
|
|
return false;
|
|
|
|
#endif
|
2016-07-13 21:12:50 +08:00
|
|
|
}
|
|
|
|
|
2006-05-12 20:20:06 +08:00
|
|
|
/*
|
|
|
|
* Special Variant of smp_call_function for use by cache functions:
|
|
|
|
*
|
|
|
|
* o No return value
|
|
|
|
* o collapses to normal function call on UP kernels
|
|
|
|
* o collapses to normal function call on systems with a single shared
|
|
|
|
* primary cache.
|
2010-10-30 02:08:25 +08:00
|
|
|
* o doesn't disable interrupts on the local CPU
|
2006-05-12 20:20:06 +08:00
|
|
|
*/
|
2016-07-13 21:12:50 +08:00
|
|
|
static inline void r4k_on_each_cpu(unsigned int type,
|
|
|
|
void (*func)(void *info), void *info)
|
2006-05-12 20:20:06 +08:00
|
|
|
{
|
|
|
|
preempt_disable();
|
2016-07-13 21:12:50 +08:00
|
|
|
if (r4k_op_needs_ipi(type))
|
2016-07-13 21:12:52 +08:00
|
|
|
smp_call_function_many(&cpu_foreign_map[smp_processor_id()],
|
|
|
|
func, info, 1);
|
2006-05-12 20:20:06 +08:00
|
|
|
func(info);
|
|
|
|
preempt_enable();
|
|
|
|
}
|
|
|
|
|
2005-07-13 19:48:45 +08:00
|
|
|
/*
|
|
|
|
* Must die.
|
|
|
|
*/
|
|
|
|
static unsigned long icache_size __read_mostly;
|
|
|
|
static unsigned long dcache_size __read_mostly;
|
2016-03-03 09:45:09 +08:00
|
|
|
static unsigned long vcache_size __read_mostly;
|
2005-07-13 19:48:45 +08:00
|
|
|
static unsigned long scache_size __read_mostly;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2005-09-02 02:33:58 +08:00
|
|
|
#define cpu_is_r4600_v1_x() ((read_c0_prid() & 0xfffffff0) == 0x00002010)
|
|
|
|
#define cpu_is_r4600_v2_x() ((read_c0_prid() & 0xfffffff0) == 0x00002020)
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
#define R4600_HIT_CACHEOP_WAR_IMPL \
|
|
|
|
do { \
|
2020-08-25 00:32:45 +08:00
|
|
|
if (IS_ENABLED(CONFIG_WAR_R4600_V2_HIT_CACHEOP) && \
|
|
|
|
cpu_is_r4600_v2_x()) \
|
2005-04-17 06:20:36 +08:00
|
|
|
*(volatile unsigned long *)CKSEG1; \
|
2020-08-25 00:32:44 +08:00
|
|
|
if (IS_ENABLED(CONFIG_WAR_R4600_V1_HIT_CACHEOP)) \
|
2005-04-17 06:20:36 +08:00
|
|
|
__asm__ __volatile__("nop;nop;nop;nop"); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
static void (*r4k_blast_dcache_page)(unsigned long addr);
|
|
|
|
|
|
|
|
static inline void r4k_blast_dcache_page_dc32(unsigned long addr)
|
|
|
|
{
|
|
|
|
R4600_HIT_CACHEOP_WAR_IMPL;
|
|
|
|
blast_dcache32_page(addr);
|
|
|
|
}
|
|
|
|
|
2009-04-24 08:36:53 +08:00
|
|
|
static inline void r4k_blast_dcache_page_dc64(unsigned long addr)
|
|
|
|
{
|
|
|
|
blast_dcache64_page(addr);
|
|
|
|
}
|
|
|
|
|
2014-05-29 05:52:09 +08:00
|
|
|
static inline void r4k_blast_dcache_page_dc128(unsigned long addr)
|
|
|
|
{
|
|
|
|
blast_dcache128_page(addr);
|
|
|
|
}
|
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 21:38:59 +08:00
|
|
|
static void r4k_blast_dcache_page_setup(void)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
unsigned long dc_lsize = cpu_dcache_line_size();
|
|
|
|
|
2014-05-29 05:52:09 +08:00
|
|
|
switch (dc_lsize) {
|
|
|
|
case 0:
|
2006-06-21 01:06:52 +08:00
|
|
|
r4k_blast_dcache_page = (void *)cache_noop;
|
2014-05-29 05:52:09 +08:00
|
|
|
break;
|
|
|
|
case 16:
|
2005-04-17 06:20:36 +08:00
|
|
|
r4k_blast_dcache_page = blast_dcache16_page;
|
2014-05-29 05:52:09 +08:00
|
|
|
break;
|
|
|
|
case 32:
|
2005-04-17 06:20:36 +08:00
|
|
|
r4k_blast_dcache_page = r4k_blast_dcache_page_dc32;
|
2014-05-29 05:52:09 +08:00
|
|
|
break;
|
|
|
|
case 64:
|
2009-04-24 08:36:53 +08:00
|
|
|
r4k_blast_dcache_page = r4k_blast_dcache_page_dc64;
|
2014-05-29 05:52:09 +08:00
|
|
|
break;
|
|
|
|
case 128:
|
|
|
|
r4k_blast_dcache_page = r4k_blast_dcache_page_dc128;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2014-01-15 22:47:28 +08:00
|
|
|
#ifndef CONFIG_EVA
|
|
|
|
#define r4k_blast_dcache_user_page r4k_blast_dcache_page
|
|
|
|
#else
|
|
|
|
|
|
|
|
static void (*r4k_blast_dcache_user_page)(unsigned long addr);
|
|
|
|
|
|
|
|
static void r4k_blast_dcache_user_page_setup(void)
|
|
|
|
{
|
|
|
|
unsigned long dc_lsize = cpu_dcache_line_size();
|
|
|
|
|
|
|
|
if (dc_lsize == 0)
|
|
|
|
r4k_blast_dcache_user_page = (void *)cache_noop;
|
|
|
|
else if (dc_lsize == 16)
|
|
|
|
r4k_blast_dcache_user_page = blast_dcache16_user_page;
|
|
|
|
else if (dc_lsize == 32)
|
|
|
|
r4k_blast_dcache_user_page = blast_dcache32_user_page;
|
|
|
|
else if (dc_lsize == 64)
|
|
|
|
r4k_blast_dcache_user_page = blast_dcache64_user_page;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2012-11-22 10:34:10 +08:00
|
|
|
void (* r4k_blast_dcache)(void);
|
|
|
|
EXPORT_SYMBOL(r4k_blast_dcache);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 21:38:59 +08:00
|
|
|
static void r4k_blast_dcache_setup(void)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
unsigned long dc_lsize = cpu_dcache_line_size();
|
|
|
|
|
2006-06-21 01:06:52 +08:00
|
|
|
if (dc_lsize == 0)
|
|
|
|
r4k_blast_dcache = (void *)cache_noop;
|
|
|
|
else if (dc_lsize == 16)
|
2005-04-17 06:20:36 +08:00
|
|
|
r4k_blast_dcache = blast_dcache16;
|
|
|
|
else if (dc_lsize == 32)
|
|
|
|
r4k_blast_dcache = blast_dcache32;
|
2009-04-24 08:36:53 +08:00
|
|
|
else if (dc_lsize == 64)
|
|
|
|
r4k_blast_dcache = blast_dcache64;
|
2014-05-29 05:52:09 +08:00
|
|
|
else if (dc_lsize == 128)
|
|
|
|
r4k_blast_dcache = blast_dcache128;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2020-08-25 00:32:47 +08:00
|
|
|
/* force code alignment (used for CONFIG_WAR_TX49XX_ICACHE_INDEX_INV) */
|
2005-04-17 06:20:36 +08:00
|
|
|
#define JUMP_TO_ALIGN(order) \
|
|
|
|
__asm__ __volatile__( \
|
|
|
|
"b\t1f\n\t" \
|
|
|
|
".align\t" #order "\n\t" \
|
|
|
|
"1:\n\t" \
|
|
|
|
)
|
|
|
|
#define CACHE32_UNROLL32_ALIGN JUMP_TO_ALIGN(10) /* 32 * 32 = 1024 */
|
2013-01-22 19:59:30 +08:00
|
|
|
#define CACHE32_UNROLL32_ALIGN2 JUMP_TO_ALIGN(11)
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
static inline void blast_r4600_v1_icache32(void)
|
|
|
|
{
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
local_irq_save(flags);
|
|
|
|
blast_icache32();
|
|
|
|
local_irq_restore(flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void tx49_blast_icache32(void)
|
|
|
|
{
|
|
|
|
unsigned long start = INDEX_BASE;
|
|
|
|
unsigned long end = start + current_cpu_data.icache.waysize;
|
|
|
|
unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
|
|
|
|
unsigned long ws_end = current_cpu_data.icache.ways <<
|
2013-01-22 19:59:30 +08:00
|
|
|
current_cpu_data.icache.waybit;
|
2005-04-17 06:20:36 +08:00
|
|
|
unsigned long ws, addr;
|
|
|
|
|
|
|
|
CACHE32_UNROLL32_ALIGN2;
|
|
|
|
/* I'm in even chunk. blast odd chunks */
|
2005-09-04 06:56:17 +08:00
|
|
|
for (ws = 0; ws < ws_end; ws += ws_inc)
|
|
|
|
for (addr = start + 0x400; addr < end; addr += 0x400 * 2)
|
2019-10-09 02:22:00 +08:00
|
|
|
cache_unroll(32, kernel_cache, Index_Invalidate_I,
|
|
|
|
addr | ws, 32);
|
2005-04-17 06:20:36 +08:00
|
|
|
CACHE32_UNROLL32_ALIGN;
|
|
|
|
/* I'm in odd chunk. blast even chunks */
|
2005-09-04 06:56:17 +08:00
|
|
|
for (ws = 0; ws < ws_end; ws += ws_inc)
|
|
|
|
for (addr = start; addr < end; addr += 0x400 * 2)
|
2019-10-09 02:22:00 +08:00
|
|
|
cache_unroll(32, kernel_cache, Index_Invalidate_I,
|
|
|
|
addr | ws, 32);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void (* r4k_blast_icache_page)(unsigned long addr);
|
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 21:38:59 +08:00
|
|
|
static void r4k_blast_icache_page_setup(void)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
unsigned long ic_lsize = cpu_icache_line_size();
|
|
|
|
|
2006-06-21 01:06:52 +08:00
|
|
|
if (ic_lsize == 0)
|
|
|
|
r4k_blast_icache_page = (void *)cache_noop;
|
|
|
|
else if (ic_lsize == 16)
|
2005-04-17 06:20:36 +08:00
|
|
|
r4k_blast_icache_page = blast_icache16_page;
|
2019-10-20 22:43:13 +08:00
|
|
|
else if (ic_lsize == 32 && current_cpu_type() == CPU_LOONGSON2EF)
|
2014-01-15 09:56:38 +08:00
|
|
|
r4k_blast_icache_page = loongson2_blast_icache32_page;
|
2005-04-17 06:20:36 +08:00
|
|
|
else if (ic_lsize == 32)
|
|
|
|
r4k_blast_icache_page = blast_icache32_page;
|
|
|
|
else if (ic_lsize == 64)
|
|
|
|
r4k_blast_icache_page = blast_icache64_page;
|
2014-05-29 05:52:09 +08:00
|
|
|
else if (ic_lsize == 128)
|
|
|
|
r4k_blast_icache_page = blast_icache128_page;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2014-01-15 22:47:28 +08:00
|
|
|
#ifndef CONFIG_EVA
|
|
|
|
#define r4k_blast_icache_user_page r4k_blast_icache_page
|
|
|
|
#else
|
|
|
|
|
|
|
|
static void (*r4k_blast_icache_user_page)(unsigned long addr);
|
|
|
|
|
2015-04-28 06:47:57 +08:00
|
|
|
static void r4k_blast_icache_user_page_setup(void)
|
2014-01-15 22:47:28 +08:00
|
|
|
{
|
|
|
|
unsigned long ic_lsize = cpu_icache_line_size();
|
|
|
|
|
|
|
|
if (ic_lsize == 0)
|
|
|
|
r4k_blast_icache_user_page = (void *)cache_noop;
|
|
|
|
else if (ic_lsize == 16)
|
|
|
|
r4k_blast_icache_user_page = blast_icache16_user_page;
|
|
|
|
else if (ic_lsize == 32)
|
|
|
|
r4k_blast_icache_user_page = blast_icache32_user_page;
|
|
|
|
else if (ic_lsize == 64)
|
|
|
|
r4k_blast_icache_user_page = blast_icache64_user_page;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2012-11-22 10:34:10 +08:00
|
|
|
void (* r4k_blast_icache)(void);
|
|
|
|
EXPORT_SYMBOL(r4k_blast_icache);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 21:38:59 +08:00
|
|
|
static void r4k_blast_icache_setup(void)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
unsigned long ic_lsize = cpu_icache_line_size();
|
|
|
|
|
2006-06-21 01:06:52 +08:00
|
|
|
if (ic_lsize == 0)
|
|
|
|
r4k_blast_icache = (void *)cache_noop;
|
|
|
|
else if (ic_lsize == 16)
|
2005-04-17 06:20:36 +08:00
|
|
|
r4k_blast_icache = blast_icache16;
|
|
|
|
else if (ic_lsize == 32) {
|
2020-08-25 00:32:43 +08:00
|
|
|
if (IS_ENABLED(CONFIG_WAR_R4600_V1_INDEX_ICACHEOP) &&
|
|
|
|
cpu_is_r4600_v1_x())
|
2005-04-17 06:20:36 +08:00
|
|
|
r4k_blast_icache = blast_r4600_v1_icache32;
|
2020-08-25 00:32:47 +08:00
|
|
|
else if (IS_ENABLED(CONFIG_WAR_TX49XX_ICACHE_INDEX_INV))
|
2005-04-17 06:20:36 +08:00
|
|
|
r4k_blast_icache = tx49_blast_icache32;
|
2019-10-20 22:43:13 +08:00
|
|
|
else if (current_cpu_type() == CPU_LOONGSON2EF)
|
2014-01-15 09:56:38 +08:00
|
|
|
r4k_blast_icache = loongson2_blast_icache32;
|
2005-04-17 06:20:36 +08:00
|
|
|
else
|
|
|
|
r4k_blast_icache = blast_icache32;
|
|
|
|
} else if (ic_lsize == 64)
|
|
|
|
r4k_blast_icache = blast_icache64;
|
2014-05-29 05:52:09 +08:00
|
|
|
else if (ic_lsize == 128)
|
|
|
|
r4k_blast_icache = blast_icache128;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void (* r4k_blast_scache_page)(unsigned long addr);
|
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 21:38:59 +08:00
|
|
|
static void r4k_blast_scache_page_setup(void)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
unsigned long sc_lsize = cpu_scache_line_size();
|
|
|
|
|
2006-02-28 03:05:55 +08:00
|
|
|
if (scache_size == 0)
|
2006-06-21 01:06:52 +08:00
|
|
|
r4k_blast_scache_page = (void *)cache_noop;
|
2006-02-28 03:05:55 +08:00
|
|
|
else if (sc_lsize == 16)
|
2005-04-17 06:20:36 +08:00
|
|
|
r4k_blast_scache_page = blast_scache16_page;
|
|
|
|
else if (sc_lsize == 32)
|
|
|
|
r4k_blast_scache_page = blast_scache32_page;
|
|
|
|
else if (sc_lsize == 64)
|
|
|
|
r4k_blast_scache_page = blast_scache64_page;
|
|
|
|
else if (sc_lsize == 128)
|
|
|
|
r4k_blast_scache_page = blast_scache128_page;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void (* r4k_blast_scache)(void);
|
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 21:38:59 +08:00
|
|
|
static void r4k_blast_scache_setup(void)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
unsigned long sc_lsize = cpu_scache_line_size();
|
|
|
|
|
2006-02-28 03:05:55 +08:00
|
|
|
if (scache_size == 0)
|
2006-06-21 01:06:52 +08:00
|
|
|
r4k_blast_scache = (void *)cache_noop;
|
2006-02-28 03:05:55 +08:00
|
|
|
else if (sc_lsize == 16)
|
2005-04-17 06:20:36 +08:00
|
|
|
r4k_blast_scache = blast_scache16;
|
|
|
|
else if (sc_lsize == 32)
|
|
|
|
r4k_blast_scache = blast_scache32;
|
|
|
|
else if (sc_lsize == 64)
|
|
|
|
r4k_blast_scache = blast_scache64;
|
|
|
|
else if (sc_lsize == 128)
|
|
|
|
r4k_blast_scache = blast_scache128;
|
|
|
|
}
|
|
|
|
|
2018-11-15 15:53:53 +08:00
|
|
|
static void (*r4k_blast_scache_node)(long node);
|
|
|
|
|
|
|
|
static void r4k_blast_scache_node_setup(void)
|
|
|
|
{
|
|
|
|
unsigned long sc_lsize = cpu_scache_line_size();
|
|
|
|
|
2019-10-20 22:43:13 +08:00
|
|
|
if (current_cpu_type() != CPU_LOONGSON64)
|
2018-11-15 15:53:53 +08:00
|
|
|
r4k_blast_scache_node = (void *)cache_noop;
|
|
|
|
else if (sc_lsize == 16)
|
|
|
|
r4k_blast_scache_node = blast_scache16_node;
|
|
|
|
else if (sc_lsize == 32)
|
|
|
|
r4k_blast_scache_node = blast_scache32_node;
|
|
|
|
else if (sc_lsize == 64)
|
|
|
|
r4k_blast_scache_node = blast_scache64_node;
|
|
|
|
else if (sc_lsize == 128)
|
|
|
|
r4k_blast_scache_node = blast_scache128_node;
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static inline void local_r4k___flush_cache_all(void * args)
|
|
|
|
{
|
2007-10-12 06:46:15 +08:00
|
|
|
switch (current_cpu_type()) {
|
2019-10-20 22:43:13 +08:00
|
|
|
case CPU_LOONGSON2EF:
|
2005-04-17 06:20:36 +08:00
|
|
|
case CPU_R4000SC:
|
|
|
|
case CPU_R4000MC:
|
|
|
|
case CPU_R4400SC:
|
|
|
|
case CPU_R4400MC:
|
|
|
|
case CPU_R10000:
|
|
|
|
case CPU_R12000:
|
2006-05-17 10:23:59 +08:00
|
|
|
case CPU_R14000:
|
2015-01-21 20:59:45 +08:00
|
|
|
case CPU_R16000:
|
2013-09-26 00:21:26 +08:00
|
|
|
/*
|
|
|
|
* These caches are inclusive caches, that is, if something
|
|
|
|
* is not cached in the S-cache, we know it also won't be
|
|
|
|
* in one of the primary caches.
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
r4k_blast_scache();
|
2013-09-26 00:21:26 +08:00
|
|
|
break;
|
|
|
|
|
2019-10-20 22:43:13 +08:00
|
|
|
case CPU_LOONGSON64:
|
2018-11-15 15:53:53 +08:00
|
|
|
/* Use get_ebase_cpunum() for both NUMA=y/n */
|
|
|
|
r4k_blast_scache_node(get_ebase_cpunum() >> 2);
|
|
|
|
break;
|
|
|
|
|
2016-04-05 01:55:36 +08:00
|
|
|
case CPU_BMIPS5000:
|
|
|
|
r4k_blast_scache();
|
|
|
|
__sync();
|
|
|
|
break;
|
|
|
|
|
2013-09-26 00:21:26 +08:00
|
|
|
default:
|
|
|
|
r4k_blast_dcache();
|
|
|
|
r4k_blast_icache();
|
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void r4k___flush_cache_all(void)
|
|
|
|
{
|
2016-07-13 21:12:50 +08:00
|
|
|
r4k_on_each_cpu(R4K_INDEX, local_r4k___flush_cache_all, NULL);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
MIPS: c-r4k: Fix valid ASID optimisation
Several cache operations are optimised to return early from the SMP call
handler if the memory map in question has no valid ASID on the current
CPU, or any online CPU in the case of MIPS_MT_SMP. The idea is that if a
memory map has never been used on a CPU it shouldn't have cache lines in
need of flushing.
However this doesn't cover all cases when ASIDs for other CPUs need to
be checked:
- Offline VPEs may have recently been online and brought lines into the
(shared) cache, so they should also be checked, rather than only
online CPUs.
- SMP systems with a Coherence Manager (CM), but with MT disabled still
have globalized hit cache ops, but don't use SMP calls, so all present
CPUs should be taken into account.
- R6 systems have a different multithreading implementation, so
MIPS_MT_SMP won't be set, but as above may still have a CM which
globalizes hit cache ops.
Additionally for non-globalized cache operations where an SMP call to a
single VPE in each foreign core is used, it is not necessary to check
every CPU in the system, only sibling CPUs sharing the same first level
cache.
Fix this by making has_valid_asid() take a cache op type argument like
r4k_on_each_cpu(), so it can determine whether r4k_on_each_cpu() will
have done SMP calls to other cores. It can then determine which set of
CPUs to check the ASIDs of based on that, excluding foreign CPUs if an
SMP call will have been performed.
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Leonid Yegoshin <leonid.yegoshin@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/13804/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2016-07-13 21:12:51 +08:00
|
|
|
/**
|
|
|
|
* has_valid_asid() - Determine if an mm already has an ASID.
|
|
|
|
* @mm: Memory map.
|
|
|
|
* @type: R4K_HIT or R4K_INDEX, type of cache op.
|
|
|
|
*
|
|
|
|
* Determines whether @mm already has an ASID on any of the CPUs which cache ops
|
|
|
|
* of type @type within an r4k_on_each_cpu() call will affect. If
|
|
|
|
* r4k_on_each_cpu() does an SMP call to a single VPE in each core, then the
|
|
|
|
* scope of the operation is confined to sibling CPUs, otherwise all online CPUs
|
|
|
|
* will need to be checked.
|
|
|
|
*
|
|
|
|
* Must be called in non-preemptive context.
|
|
|
|
*
|
|
|
|
* Returns: 1 if the CPUs affected by @type cache ops have an ASID for @mm.
|
|
|
|
* 0 otherwise.
|
|
|
|
*/
|
|
|
|
static inline int has_valid_asid(const struct mm_struct *mm, unsigned int type)
|
2007-10-08 23:38:37 +08:00
|
|
|
{
|
MIPS: c-r4k: Fix valid ASID optimisation
Several cache operations are optimised to return early from the SMP call
handler if the memory map in question has no valid ASID on the current
CPU, or any online CPU in the case of MIPS_MT_SMP. The idea is that if a
memory map has never been used on a CPU it shouldn't have cache lines in
need of flushing.
However this doesn't cover all cases when ASIDs for other CPUs need to
be checked:
- Offline VPEs may have recently been online and brought lines into the
(shared) cache, so they should also be checked, rather than only
online CPUs.
- SMP systems with a Coherence Manager (CM), but with MT disabled still
have globalized hit cache ops, but don't use SMP calls, so all present
CPUs should be taken into account.
- R6 systems have a different multithreading implementation, so
MIPS_MT_SMP won't be set, but as above may still have a CM which
globalizes hit cache ops.
Additionally for non-globalized cache operations where an SMP call to a
single VPE in each foreign core is used, it is not necessary to check
every CPU in the system, only sibling CPUs sharing the same first level
cache.
Fix this by making has_valid_asid() take a cache op type argument like
r4k_on_each_cpu(), so it can determine whether r4k_on_each_cpu() will
have done SMP calls to other cores. It can then determine which set of
CPUs to check the ASIDs of based on that, excluding foreign CPUs if an
SMP call will have been performed.
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Leonid Yegoshin <leonid.yegoshin@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/13804/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2016-07-13 21:12:51 +08:00
|
|
|
unsigned int i;
|
|
|
|
const cpumask_t *mask = cpu_present_mask;
|
2007-10-08 23:38:37 +08:00
|
|
|
|
MIPS: MemoryMapID (MMID) Support
Introduce support for using MemoryMapIDs (MMIDs) as an alternative to
Address Space IDs (ASIDs). The major difference between the two is that
MMIDs are global - ie. an MMID uniquely identifies an address space
across all coherent CPUs. In contrast ASIDs are non-global per-CPU IDs,
wherein each address space is allocated a separate ASID for each CPU
upon which it is used. This global namespace allows a new GINVT
instruction be used to globally invalidate TLB entries associated with a
particular MMID across all coherent CPUs in the system, removing the
need for IPIs to invalidate entries with separate ASIDs on each CPU.
The allocation scheme used here is largely borrowed from arm64 (see
arch/arm64/mm/context.c). In essence we maintain a bitmap to track
available MMIDs, and MMIDs in active use at the time of a rollover to a
new MMID version are preserved in the new version. The allocation scheme
requires efficient 64 bit atomics in order to perform reasonably, so
this support depends upon CONFIG_GENERIC_ATOMIC64=n (ie. currently it
will only be included in MIPS64 kernels).
The first, and currently only, available CPU with support for MMIDs is
the MIPS I6500. This CPU supports 16 bit MMIDs, and so for now we cap
our MMIDs to 16 bits wide in order to prevent the bitmap growing to
absurd sizes if any future CPU does implement 32 bit MMIDs as the
architecture manuals suggest is recommended.
When MMIDs are in use we also make use of GINVT instruction which is
available due to the global nature of MMIDs. By executing a sequence of
GINVT & SYNC 0x14 instructions we can avoid the overhead of an IPI to
each remote CPU in many cases. One complication is that GINVT will
invalidate wired entries (in all cases apart from type 0, which targets
the entire TLB). In order to avoid GINVT invalidating any wired TLB
entries we set up, we make sure to create those entries using a reserved
MMID (0) that we never associate with any address space.
Also of note is that KVM will require further work in order to support
MMIDs & GINVT, since KVM is involved in allocating IDs for guests & in
configuring the MMU. That work is not part of this patch, so for now
when MMIDs are in use KVM is disabled.
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: linux-mips@vger.kernel.org
2019-02-02 09:43:28 +08:00
|
|
|
if (cpu_has_mmid)
|
|
|
|
return cpu_context(0, mm) != 0;
|
|
|
|
|
MIPS: c-r4k: Fix valid ASID optimisation
Several cache operations are optimised to return early from the SMP call
handler if the memory map in question has no valid ASID on the current
CPU, or any online CPU in the case of MIPS_MT_SMP. The idea is that if a
memory map has never been used on a CPU it shouldn't have cache lines in
need of flushing.
However this doesn't cover all cases when ASIDs for other CPUs need to
be checked:
- Offline VPEs may have recently been online and brought lines into the
(shared) cache, so they should also be checked, rather than only
online CPUs.
- SMP systems with a Coherence Manager (CM), but with MT disabled still
have globalized hit cache ops, but don't use SMP calls, so all present
CPUs should be taken into account.
- R6 systems have a different multithreading implementation, so
MIPS_MT_SMP won't be set, but as above may still have a CM which
globalizes hit cache ops.
Additionally for non-globalized cache operations where an SMP call to a
single VPE in each foreign core is used, it is not necessary to check
every CPU in the system, only sibling CPUs sharing the same first level
cache.
Fix this by making has_valid_asid() take a cache op type argument like
r4k_on_each_cpu(), so it can determine whether r4k_on_each_cpu() will
have done SMP calls to other cores. It can then determine which set of
CPUs to check the ASIDs of based on that, excluding foreign CPUs if an
SMP call will have been performed.
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Leonid Yegoshin <leonid.yegoshin@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/13804/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2016-07-13 21:12:51 +08:00
|
|
|
/* cpu_sibling_map[] undeclared when !CONFIG_SMP */
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
|
/*
|
|
|
|
* If r4k_on_each_cpu does SMP calls, it does them to a single VPE in
|
|
|
|
* each foreign core, so we only need to worry about siblings.
|
|
|
|
* Otherwise we need to worry about all present CPUs.
|
|
|
|
*/
|
|
|
|
if (r4k_op_needs_ipi(type))
|
|
|
|
mask = &cpu_sibling_map[smp_processor_id()];
|
|
|
|
#endif
|
|
|
|
for_each_cpu(i, mask)
|
2007-10-08 23:38:37 +08:00
|
|
|
if (cpu_context(i, mm))
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-04-05 22:13:23 +08:00
|
|
|
static void r4k__flush_cache_vmap(void)
|
|
|
|
{
|
|
|
|
r4k_blast_dcache();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void r4k__flush_cache_vunmap(void)
|
|
|
|
{
|
|
|
|
r4k_blast_dcache();
|
|
|
|
}
|
|
|
|
|
MIPS: SMP: Clear ASID without confusing has_valid_asid()
The SMP flush_tlb_*() functions may clear the memory map's ASIDs for
other CPUs if the mm has only a single user (the current CPU) in order
to avoid SMP calls. However this makes it appear to has_valid_asid(),
which is used by various cache flush functions, as if the CPUs have
never run in the mm, and therefore can't have cached any of its memory.
For flush_tlb_mm() this doesn't sound unreasonable.
flush_tlb_range() corresponds to flush_cache_range() which does do full
indexed cache flushes, but only on the icache if the specified mapping
is executable, otherwise it doesn't guarantee that there are no cache
contents left for the mm.
flush_tlb_page() corresponds to flush_cache_page(), which will perform
address based cache ops on the specified page only, and also only
touches the icache if the page is executable. It does not guarantee that
there are no cache contents left for the mm.
For example, this affects flush_cache_range() which uses the
has_valid_asid() optimisation. It is required to flush the icache when
mappings are made executable (e.g. using mprotect) so they are
immediately usable. If some code is changed to non executable in order
to be modified then it will not be flushed from the icache during that
time, but the ASID on other CPUs may still be cleared for TLB flushing.
When the code is changed back to executable, flush_cache_range() will
assume the code hasn't run on those other CPUs due to the zero ASID, and
won't invalidate the icache on them.
This is fixed by clearing the other CPUs ASIDs to 1 instead of 0 for the
above two flush_tlb_*() functions when the corresponding cache flushes
are likely to be incomplete (non executable range flush, or any page
flush). This ASID appears valid to has_valid_asid(), but still triggers
ASID regeneration due to the upper ASID version bits being 0, which is
less than the minimum ASID version of 1 and so always treated as stale.
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Leonid Yegoshin <leonid.yegoshin@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/13795/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2016-07-13 21:12:44 +08:00
|
|
|
/*
|
|
|
|
* Note: flush_tlb_range() assumes flush_cache_range() sufficiently flushes
|
|
|
|
* whole caches when vma is executable.
|
|
|
|
*/
|
2005-04-17 06:20:36 +08:00
|
|
|
static inline void local_r4k_flush_cache_range(void * args)
|
|
|
|
{
|
|
|
|
struct vm_area_struct *vma = args;
|
2008-02-11 22:51:40 +08:00
|
|
|
int exec = vma->vm_flags & VM_EXEC;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
MIPS: c-r4k: Fix valid ASID optimisation
Several cache operations are optimised to return early from the SMP call
handler if the memory map in question has no valid ASID on the current
CPU, or any online CPU in the case of MIPS_MT_SMP. The idea is that if a
memory map has never been used on a CPU it shouldn't have cache lines in
need of flushing.
However this doesn't cover all cases when ASIDs for other CPUs need to
be checked:
- Offline VPEs may have recently been online and brought lines into the
(shared) cache, so they should also be checked, rather than only
online CPUs.
- SMP systems with a Coherence Manager (CM), but with MT disabled still
have globalized hit cache ops, but don't use SMP calls, so all present
CPUs should be taken into account.
- R6 systems have a different multithreading implementation, so
MIPS_MT_SMP won't be set, but as above may still have a CM which
globalizes hit cache ops.
Additionally for non-globalized cache operations where an SMP call to a
single VPE in each foreign core is used, it is not necessary to check
every CPU in the system, only sibling CPUs sharing the same first level
cache.
Fix this by making has_valid_asid() take a cache op type argument like
r4k_on_each_cpu(), so it can determine whether r4k_on_each_cpu() will
have done SMP calls to other cores. It can then determine which set of
CPUs to check the ASIDs of based on that, excluding foreign CPUs if an
SMP call will have been performed.
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Leonid Yegoshin <leonid.yegoshin@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/13804/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2016-07-13 21:12:51 +08:00
|
|
|
if (!has_valid_asid(vma->vm_mm, R4K_INDEX))
|
2005-04-17 06:20:36 +08:00
|
|
|
return;
|
|
|
|
|
2016-01-22 18:58:25 +08:00
|
|
|
/*
|
|
|
|
* If dcache can alias, we must blast it since mapping is changing.
|
|
|
|
* If executable, we must ensure any dirty lines are written back far
|
|
|
|
* enough to be visible to icache.
|
|
|
|
*/
|
|
|
|
if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc))
|
|
|
|
r4k_blast_dcache();
|
|
|
|
/* If executable, blast stale lines from icache */
|
2008-02-11 22:51:40 +08:00
|
|
|
if (exec)
|
|
|
|
r4k_blast_icache();
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void r4k_flush_cache_range(struct vm_area_struct *vma,
|
|
|
|
unsigned long start, unsigned long end)
|
|
|
|
{
|
2008-02-11 22:51:40 +08:00
|
|
|
int exec = vma->vm_flags & VM_EXEC;
|
2006-08-22 20:15:47 +08:00
|
|
|
|
2016-01-22 18:58:25 +08:00
|
|
|
if (cpu_has_dc_aliases || exec)
|
2016-07-13 21:12:50 +08:00
|
|
|
r4k_on_each_cpu(R4K_INDEX, local_r4k_flush_cache_range, vma);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void local_r4k_flush_cache_mm(void * args)
|
|
|
|
{
|
|
|
|
struct mm_struct *mm = args;
|
|
|
|
|
MIPS: c-r4k: Fix valid ASID optimisation
Several cache operations are optimised to return early from the SMP call
handler if the memory map in question has no valid ASID on the current
CPU, or any online CPU in the case of MIPS_MT_SMP. The idea is that if a
memory map has never been used on a CPU it shouldn't have cache lines in
need of flushing.
However this doesn't cover all cases when ASIDs for other CPUs need to
be checked:
- Offline VPEs may have recently been online and brought lines into the
(shared) cache, so they should also be checked, rather than only
online CPUs.
- SMP systems with a Coherence Manager (CM), but with MT disabled still
have globalized hit cache ops, but don't use SMP calls, so all present
CPUs should be taken into account.
- R6 systems have a different multithreading implementation, so
MIPS_MT_SMP won't be set, but as above may still have a CM which
globalizes hit cache ops.
Additionally for non-globalized cache operations where an SMP call to a
single VPE in each foreign core is used, it is not necessary to check
every CPU in the system, only sibling CPUs sharing the same first level
cache.
Fix this by making has_valid_asid() take a cache op type argument like
r4k_on_each_cpu(), so it can determine whether r4k_on_each_cpu() will
have done SMP calls to other cores. It can then determine which set of
CPUs to check the ASIDs of based on that, excluding foreign CPUs if an
SMP call will have been performed.
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Leonid Yegoshin <leonid.yegoshin@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/13804/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2016-07-13 21:12:51 +08:00
|
|
|
if (!has_valid_asid(mm, R4K_INDEX))
|
2005-04-17 06:20:36 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Kludge alert. For obscure reasons R4000SC and R4400SC go nuts if we
|
2015-01-21 20:59:45 +08:00
|
|
|
* only flush the primary caches but R1x000 behave sane ...
|
2006-11-30 09:14:48 +08:00
|
|
|
* R4000SC and R4400SC indexed S-cache ops also invalidate primary
|
|
|
|
* caches, so we can bail out early.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2007-10-12 06:46:15 +08:00
|
|
|
if (current_cpu_type() == CPU_R4000SC ||
|
|
|
|
current_cpu_type() == CPU_R4000MC ||
|
|
|
|
current_cpu_type() == CPU_R4400SC ||
|
|
|
|
current_cpu_type() == CPU_R4400MC) {
|
2005-04-17 06:20:36 +08:00
|
|
|
r4k_blast_scache();
|
2006-11-30 09:14:48 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
r4k_blast_dcache();
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void r4k_flush_cache_mm(struct mm_struct *mm)
|
|
|
|
{
|
|
|
|
if (!cpu_has_dc_aliases)
|
|
|
|
return;
|
|
|
|
|
2016-07-13 21:12:50 +08:00
|
|
|
r4k_on_each_cpu(R4K_INDEX, local_r4k_flush_cache_mm, mm);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
struct flush_cache_page_args {
|
|
|
|
struct vm_area_struct *vma;
|
2005-10-12 07:02:34 +08:00
|
|
|
unsigned long addr;
|
2006-03-13 17:23:03 +08:00
|
|
|
unsigned long pfn;
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static inline void local_r4k_flush_cache_page(void *args)
|
|
|
|
{
|
|
|
|
struct flush_cache_page_args *fcp_args = args;
|
|
|
|
struct vm_area_struct *vma = fcp_args->vma;
|
2005-10-12 07:02:34 +08:00
|
|
|
unsigned long addr = fcp_args->addr;
|
2007-09-28 01:26:43 +08:00
|
|
|
struct page *page = pfn_to_page(fcp_args->pfn);
|
2005-04-17 06:20:36 +08:00
|
|
|
int exec = vma->vm_flags & VM_EXEC;
|
|
|
|
struct mm_struct *mm = vma->vm_mm;
|
2008-06-15 05:22:08 +08:00
|
|
|
int map_coherent = 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
pmd_t *pmdp;
|
|
|
|
pte_t *ptep;
|
2007-09-28 01:26:43 +08:00
|
|
|
void *vaddr;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2005-02-10 21:54:37 +08:00
|
|
|
/*
|
MIPS: c-r4k: Fix valid ASID optimisation
Several cache operations are optimised to return early from the SMP call
handler if the memory map in question has no valid ASID on the current
CPU, or any online CPU in the case of MIPS_MT_SMP. The idea is that if a
memory map has never been used on a CPU it shouldn't have cache lines in
need of flushing.
However this doesn't cover all cases when ASIDs for other CPUs need to
be checked:
- Offline VPEs may have recently been online and brought lines into the
(shared) cache, so they should also be checked, rather than only
online CPUs.
- SMP systems with a Coherence Manager (CM), but with MT disabled still
have globalized hit cache ops, but don't use SMP calls, so all present
CPUs should be taken into account.
- R6 systems have a different multithreading implementation, so
MIPS_MT_SMP won't be set, but as above may still have a CM which
globalizes hit cache ops.
Additionally for non-globalized cache operations where an SMP call to a
single VPE in each foreign core is used, it is not necessary to check
every CPU in the system, only sibling CPUs sharing the same first level
cache.
Fix this by making has_valid_asid() take a cache op type argument like
r4k_on_each_cpu(), so it can determine whether r4k_on_each_cpu() will
have done SMP calls to other cores. It can then determine which set of
CPUs to check the ASIDs of based on that, excluding foreign CPUs if an
SMP call will have been performed.
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Leonid Yegoshin <leonid.yegoshin@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/13804/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2016-07-13 21:12:51 +08:00
|
|
|
* If owns no valid ASID yet, cannot possibly have gotten
|
2005-02-10 21:54:37 +08:00
|
|
|
* this page into the cache.
|
|
|
|
*/
|
MIPS: c-r4k: Fix valid ASID optimisation
Several cache operations are optimised to return early from the SMP call
handler if the memory map in question has no valid ASID on the current
CPU, or any online CPU in the case of MIPS_MT_SMP. The idea is that if a
memory map has never been used on a CPU it shouldn't have cache lines in
need of flushing.
However this doesn't cover all cases when ASIDs for other CPUs need to
be checked:
- Offline VPEs may have recently been online and brought lines into the
(shared) cache, so they should also be checked, rather than only
online CPUs.
- SMP systems with a Coherence Manager (CM), but with MT disabled still
have globalized hit cache ops, but don't use SMP calls, so all present
CPUs should be taken into account.
- R6 systems have a different multithreading implementation, so
MIPS_MT_SMP won't be set, but as above may still have a CM which
globalizes hit cache ops.
Additionally for non-globalized cache operations where an SMP call to a
single VPE in each foreign core is used, it is not necessary to check
every CPU in the system, only sibling CPUs sharing the same first level
cache.
Fix this by making has_valid_asid() take a cache op type argument like
r4k_on_each_cpu(), so it can determine whether r4k_on_each_cpu() will
have done SMP calls to other cores. It can then determine which set of
CPUs to check the ASIDs of based on that, excluding foreign CPUs if an
SMP call will have been performed.
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Leonid Yegoshin <leonid.yegoshin@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/13804/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2016-07-13 21:12:51 +08:00
|
|
|
if (!has_valid_asid(mm, R4K_HIT))
|
2005-02-10 21:54:37 +08:00
|
|
|
return;
|
|
|
|
|
2005-10-12 07:02:34 +08:00
|
|
|
addr &= PAGE_MASK;
|
2020-06-09 12:33:05 +08:00
|
|
|
pmdp = pmd_off(mm, addr);
|
|
|
|
ptep = pte_offset_kernel(pmdp, addr);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the page isn't marked valid, the page cannot possibly be
|
|
|
|
* in the cache.
|
|
|
|
*/
|
2008-01-29 18:14:55 +08:00
|
|
|
if (!(pte_present(*ptep)))
|
2005-04-17 06:20:36 +08:00
|
|
|
return;
|
|
|
|
|
2007-09-28 01:26:43 +08:00
|
|
|
if ((mm == current->active_mm) && (pte_val(*ptep) & _PAGE_VALID))
|
|
|
|
vaddr = NULL;
|
|
|
|
else {
|
2023-08-02 23:13:45 +08:00
|
|
|
struct folio *folio = page_folio(page);
|
2007-09-28 01:26:43 +08:00
|
|
|
/*
|
|
|
|
* Use kmap_coherent or kmap_atomic to do flushes for
|
|
|
|
* another ASID than the current one.
|
|
|
|
*/
|
2008-06-15 05:22:08 +08:00
|
|
|
map_coherent = (cpu_has_dc_aliases &&
|
2023-08-02 23:13:45 +08:00
|
|
|
folio_mapped(folio) &&
|
|
|
|
!folio_test_dcache_dirty(folio));
|
2008-06-15 05:22:08 +08:00
|
|
|
if (map_coherent)
|
2007-09-28 01:26:43 +08:00
|
|
|
vaddr = kmap_coherent(page, addr);
|
|
|
|
else
|
2011-11-25 23:14:15 +08:00
|
|
|
vaddr = kmap_atomic(page);
|
2007-09-28 01:26:43 +08:00
|
|
|
addr = (unsigned long)vaddr;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu_has_dc_aliases || (exec && !cpu_has_ic_fills_f_dc)) {
|
2014-01-16 21:11:08 +08:00
|
|
|
vaddr ? r4k_blast_dcache_page(addr) :
|
|
|
|
r4k_blast_dcache_user_page(addr);
|
2008-04-29 00:14:26 +08:00
|
|
|
if (exec && !cpu_icache_snoops_remote_store)
|
|
|
|
r4k_blast_scache_page(addr);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
if (exec) {
|
2007-09-28 01:26:43 +08:00
|
|
|
if (vaddr && cpu_has_vtag_icache && mm == current->active_mm) {
|
2019-02-02 09:43:19 +08:00
|
|
|
drop_mmu_context(mm);
|
2005-04-17 06:20:36 +08:00
|
|
|
} else
|
2014-01-16 21:11:08 +08:00
|
|
|
vaddr ? r4k_blast_icache_page(addr) :
|
|
|
|
r4k_blast_icache_user_page(addr);
|
2007-09-28 01:26:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (vaddr) {
|
2008-06-15 05:22:08 +08:00
|
|
|
if (map_coherent)
|
2007-09-28 01:26:43 +08:00
|
|
|
kunmap_coherent();
|
|
|
|
else
|
2011-11-25 23:14:15 +08:00
|
|
|
kunmap_atomic(vaddr);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-10-12 07:02:34 +08:00
|
|
|
static void r4k_flush_cache_page(struct vm_area_struct *vma,
|
|
|
|
unsigned long addr, unsigned long pfn)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct flush_cache_page_args args;
|
|
|
|
|
|
|
|
args.vma = vma;
|
2005-10-12 07:02:34 +08:00
|
|
|
args.addr = addr;
|
2006-03-13 17:23:03 +08:00
|
|
|
args.pfn = pfn;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2016-07-13 21:12:50 +08:00
|
|
|
r4k_on_each_cpu(R4K_HIT, local_r4k_flush_cache_page, &args);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void local_r4k_flush_data_cache_page(void * addr)
|
|
|
|
{
|
|
|
|
r4k_blast_dcache_page((unsigned long) addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void r4k_flush_data_cache_page(unsigned long addr)
|
|
|
|
{
|
2007-11-03 09:01:37 +08:00
|
|
|
if (in_atomic())
|
|
|
|
local_r4k_flush_data_cache_page((void *)addr);
|
|
|
|
else
|
2016-07-13 21:12:50 +08:00
|
|
|
r4k_on_each_cpu(R4K_HIT, local_r4k_flush_data_cache_page,
|
|
|
|
(void *) addr);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
struct flush_icache_range_args {
|
2006-01-29 01:27:51 +08:00
|
|
|
unsigned long start;
|
|
|
|
unsigned long end;
|
2016-07-13 21:12:54 +08:00
|
|
|
unsigned int type;
|
2016-09-02 00:30:15 +08:00
|
|
|
bool user;
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
2016-07-13 21:12:54 +08:00
|
|
|
static inline void __local_r4k_flush_icache_range(unsigned long start,
|
|
|
|
unsigned long end,
|
2016-09-02 00:30:15 +08:00
|
|
|
unsigned int type,
|
|
|
|
bool user)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
if (!cpu_has_ic_fills_f_dc) {
|
2016-07-13 21:12:54 +08:00
|
|
|
if (type == R4K_INDEX ||
|
|
|
|
(type & R4K_INDEX && end - start >= dcache_size)) {
|
2005-04-17 06:20:36 +08:00
|
|
|
r4k_blast_dcache();
|
|
|
|
} else {
|
2005-09-10 04:26:54 +08:00
|
|
|
R4600_HIT_CACHEOP_WAR_IMPL;
|
2016-09-02 00:30:15 +08:00
|
|
|
if (user)
|
|
|
|
protected_blast_dcache_range(start, end);
|
|
|
|
else
|
|
|
|
blast_dcache_range(start, end);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-13 21:12:54 +08:00
|
|
|
if (type == R4K_INDEX ||
|
|
|
|
(type & R4K_INDEX && end - start > icache_size))
|
2005-04-17 06:20:36 +08:00
|
|
|
r4k_blast_icache();
|
2013-09-26 00:21:26 +08:00
|
|
|
else {
|
|
|
|
switch (boot_cpu_type()) {
|
2019-10-20 22:43:13 +08:00
|
|
|
case CPU_LOONGSON2EF:
|
2014-01-15 09:56:37 +08:00
|
|
|
protected_loongson2_blast_icache_range(start, end);
|
2013-09-26 00:21:26 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2016-09-02 00:30:15 +08:00
|
|
|
if (user)
|
|
|
|
protected_blast_icache_range(start, end);
|
|
|
|
else
|
|
|
|
blast_icache_range(start, end);
|
2013-09-26 00:21:26 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2016-07-13 21:12:54 +08:00
|
|
|
static inline void local_r4k_flush_icache_range(unsigned long start,
|
|
|
|
unsigned long end)
|
|
|
|
{
|
2016-09-02 00:30:15 +08:00
|
|
|
__local_r4k_flush_icache_range(start, end, R4K_HIT | R4K_INDEX, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void local_r4k_flush_icache_user_range(unsigned long start,
|
|
|
|
unsigned long end)
|
|
|
|
{
|
|
|
|
__local_r4k_flush_icache_range(start, end, R4K_HIT | R4K_INDEX, true);
|
2016-07-13 21:12:54 +08:00
|
|
|
}
|
|
|
|
|
2008-08-05 02:53:57 +08:00
|
|
|
static inline void local_r4k_flush_icache_range_ipi(void *args)
|
|
|
|
{
|
|
|
|
struct flush_icache_range_args *fir_args = args;
|
|
|
|
unsigned long start = fir_args->start;
|
|
|
|
unsigned long end = fir_args->end;
|
2016-07-13 21:12:54 +08:00
|
|
|
unsigned int type = fir_args->type;
|
2016-09-02 00:30:15 +08:00
|
|
|
bool user = fir_args->user;
|
2008-08-05 02:53:57 +08:00
|
|
|
|
2016-09-02 00:30:15 +08:00
|
|
|
__local_r4k_flush_icache_range(start, end, type, user);
|
2008-08-05 02:53:57 +08:00
|
|
|
}
|
|
|
|
|
2016-09-02 00:30:15 +08:00
|
|
|
static void __r4k_flush_icache_range(unsigned long start, unsigned long end,
|
|
|
|
bool user)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct flush_icache_range_args args;
|
2016-07-13 21:12:55 +08:00
|
|
|
unsigned long size, cache_size;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
args.start = start;
|
|
|
|
args.end = end;
|
2016-07-13 21:12:54 +08:00
|
|
|
args.type = R4K_HIT | R4K_INDEX;
|
2016-09-02 00:30:15 +08:00
|
|
|
args.user = user;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2016-07-13 21:12:55 +08:00
|
|
|
/*
|
|
|
|
* Indexed cache ops require an SMP call.
|
|
|
|
* Consider if that can or should be avoided.
|
|
|
|
*/
|
|
|
|
preempt_disable();
|
|
|
|
if (r4k_op_needs_ipi(R4K_INDEX) && !r4k_op_needs_ipi(R4K_HIT)) {
|
|
|
|
/*
|
|
|
|
* If address-based cache ops don't require an SMP call, then
|
|
|
|
* use them exclusively for small flushes.
|
|
|
|
*/
|
2016-09-05 22:24:54 +08:00
|
|
|
size = end - start;
|
2016-07-13 21:12:55 +08:00
|
|
|
cache_size = icache_size;
|
|
|
|
if (!cpu_has_ic_fills_f_dc) {
|
|
|
|
size *= 2;
|
|
|
|
cache_size += dcache_size;
|
|
|
|
}
|
|
|
|
if (size <= cache_size)
|
|
|
|
args.type &= ~R4K_INDEX;
|
|
|
|
}
|
2016-07-13 21:12:54 +08:00
|
|
|
r4k_on_each_cpu(args.type, local_r4k_flush_icache_range_ipi, &args);
|
2016-07-13 21:12:55 +08:00
|
|
|
preempt_enable();
|
2005-07-13 02:35:38 +08:00
|
|
|
instruction_hazard();
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2016-09-02 00:30:15 +08:00
|
|
|
static void r4k_flush_icache_range(unsigned long start, unsigned long end)
|
|
|
|
{
|
|
|
|
return __r4k_flush_icache_range(start, end, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void r4k_flush_icache_user_range(unsigned long start, unsigned long end)
|
|
|
|
{
|
|
|
|
return __r4k_flush_icache_range(start, end, true);
|
|
|
|
}
|
|
|
|
|
2018-06-15 19:08:31 +08:00
|
|
|
#ifdef CONFIG_DMA_NONCOHERENT
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
|
|
|
|
{
|
|
|
|
/* Catch bad driver code */
|
2016-11-26 02:46:09 +08:00
|
|
|
if (WARN_ON(size == 0))
|
|
|
|
return;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2013-09-17 18:44:31 +08:00
|
|
|
preempt_disable();
|
2006-07-06 20:04:01 +08:00
|
|
|
if (cpu_has_inclusive_pcaches) {
|
2018-11-15 15:53:53 +08:00
|
|
|
if (size >= scache_size) {
|
2019-10-20 22:43:13 +08:00
|
|
|
if (current_cpu_type() != CPU_LOONGSON64)
|
2018-11-15 15:53:53 +08:00
|
|
|
r4k_blast_scache();
|
|
|
|
else
|
|
|
|
r4k_blast_scache_node(pa_to_nid(addr));
|
|
|
|
} else {
|
2006-02-09 23:39:06 +08:00
|
|
|
blast_scache_range(addr, addr + size);
|
2018-11-15 15:53:53 +08:00
|
|
|
}
|
2013-10-02 14:03:03 +08:00
|
|
|
preempt_enable();
|
2010-09-07 12:03:46 +08:00
|
|
|
__sync();
|
2005-04-17 06:20:36 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Either no secondary cache or the available caches don't have the
|
|
|
|
* subset property so we have to flush the primary caches
|
2018-04-27 07:28:34 +08:00
|
|
|
* explicitly.
|
|
|
|
* If we would need IPI to perform an INDEX-type operation, then
|
|
|
|
* we have to use the HIT-type alternative as IPI cannot be used
|
|
|
|
* here due to interrupts possibly being disabled.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2018-04-27 07:28:34 +08:00
|
|
|
if (!r4k_op_needs_ipi(R4K_INDEX) && size >= dcache_size) {
|
2005-04-17 06:20:36 +08:00
|
|
|
r4k_blast_dcache();
|
|
|
|
} else {
|
|
|
|
R4600_HIT_CACHEOP_WAR_IMPL;
|
2006-02-09 23:39:06 +08:00
|
|
|
blast_dcache_range(addr, addr + size);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2013-09-17 18:44:31 +08:00
|
|
|
preempt_enable();
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
bc_wback_inv(addr, size);
|
2010-09-07 12:03:46 +08:00
|
|
|
__sync();
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2020-02-08 06:33:07 +08:00
|
|
|
static void prefetch_cache_inv(unsigned long addr, unsigned long size)
|
|
|
|
{
|
|
|
|
unsigned int linesz = cpu_scache_line_size();
|
|
|
|
unsigned long addr0 = addr, addr1;
|
|
|
|
|
|
|
|
addr0 &= ~(linesz - 1);
|
|
|
|
addr1 = (addr0 + size - 1) & ~(linesz - 1);
|
|
|
|
|
|
|
|
protected_writeback_scache_line(addr0);
|
|
|
|
if (likely(addr1 != addr0))
|
|
|
|
protected_writeback_scache_line(addr1);
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
|
|
|
addr0 += linesz;
|
|
|
|
if (likely(addr1 != addr0))
|
|
|
|
protected_writeback_scache_line(addr0);
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
|
|
|
addr1 -= linesz;
|
|
|
|
if (likely(addr1 > addr0))
|
|
|
|
protected_writeback_scache_line(addr0);
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
|
|
|
|
{
|
|
|
|
/* Catch bad driver code */
|
2016-11-26 02:46:09 +08:00
|
|
|
if (WARN_ON(size == 0))
|
|
|
|
return;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2013-09-17 18:44:31 +08:00
|
|
|
preempt_disable();
|
2020-02-08 06:33:07 +08:00
|
|
|
|
|
|
|
if (current_cpu_type() == CPU_BMIPS5000)
|
|
|
|
prefetch_cache_inv(addr, size);
|
|
|
|
|
2006-07-06 20:04:01 +08:00
|
|
|
if (cpu_has_inclusive_pcaches) {
|
2018-11-15 15:53:53 +08:00
|
|
|
if (size >= scache_size) {
|
2019-10-20 22:43:13 +08:00
|
|
|
if (current_cpu_type() != CPU_LOONGSON64)
|
2018-11-15 15:53:53 +08:00
|
|
|
r4k_blast_scache();
|
|
|
|
else
|
|
|
|
r4k_blast_scache_node(pa_to_nid(addr));
|
|
|
|
} else {
|
2009-01-12 02:44:49 +08:00
|
|
|
/*
|
|
|
|
* There is no clearly documented alignment requirement
|
|
|
|
* for the cache instruction on MIPS processors and
|
|
|
|
* some processors, among them the RM5200 and RM7000
|
|
|
|
* QED processors will throw an address error for cache
|
2013-01-22 19:59:30 +08:00
|
|
|
* hit ops with insufficient alignment. Solved by
|
2009-01-12 02:44:49 +08:00
|
|
|
* aligning the address to cache line size.
|
|
|
|
*/
|
2007-11-27 06:40:01 +08:00
|
|
|
blast_inv_scache_range(addr, addr + size);
|
2009-01-12 02:44:49 +08:00
|
|
|
}
|
2013-10-02 14:03:03 +08:00
|
|
|
preempt_enable();
|
2010-09-07 12:03:46 +08:00
|
|
|
__sync();
|
2005-04-17 06:20:36 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-04-27 07:28:34 +08:00
|
|
|
if (!r4k_op_needs_ipi(R4K_INDEX) && size >= dcache_size) {
|
2005-04-17 06:20:36 +08:00
|
|
|
r4k_blast_dcache();
|
|
|
|
} else {
|
|
|
|
R4600_HIT_CACHEOP_WAR_IMPL;
|
2007-11-27 06:40:01 +08:00
|
|
|
blast_inv_dcache_range(addr, addr + size);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2013-09-17 18:44:31 +08:00
|
|
|
preempt_enable();
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
bc_inv(addr, size);
|
2010-09-07 12:03:46 +08:00
|
|
|
__sync();
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2018-06-15 19:08:31 +08:00
|
|
|
#endif /* CONFIG_DMA_NONCOHERENT */
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
static void r4k_flush_icache_all(void)
|
|
|
|
{
|
|
|
|
if (cpu_has_vtag_icache)
|
|
|
|
r4k_blast_icache();
|
|
|
|
}
|
|
|
|
|
2011-06-17 23:20:28 +08:00
|
|
|
struct flush_kernel_vmap_range_args {
|
|
|
|
unsigned long vaddr;
|
|
|
|
int size;
|
|
|
|
};
|
|
|
|
|
2016-07-13 21:12:53 +08:00
|
|
|
static inline void local_r4k_flush_kernel_vmap_range_index(void *args)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Aliases only affect the primary caches so don't bother with
|
|
|
|
* S-caches or T-caches.
|
|
|
|
*/
|
|
|
|
r4k_blast_dcache();
|
|
|
|
}
|
|
|
|
|
2011-06-17 23:20:28 +08:00
|
|
|
static inline void local_r4k_flush_kernel_vmap_range(void *args)
|
|
|
|
{
|
|
|
|
struct flush_kernel_vmap_range_args *vmra = args;
|
|
|
|
unsigned long vaddr = vmra->vaddr;
|
|
|
|
int size = vmra->size;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Aliases only affect the primary caches so don't bother with
|
|
|
|
* S-caches or T-caches.
|
|
|
|
*/
|
2016-07-13 21:12:53 +08:00
|
|
|
R4600_HIT_CACHEOP_WAR_IMPL;
|
|
|
|
blast_dcache_range(vaddr, vaddr + size);
|
2011-06-17 23:20:28 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void r4k_flush_kernel_vmap_range(unsigned long vaddr, int size)
|
|
|
|
{
|
|
|
|
struct flush_kernel_vmap_range_args args;
|
|
|
|
|
|
|
|
args.vaddr = (unsigned long) vaddr;
|
|
|
|
args.size = size;
|
|
|
|
|
2016-07-13 21:12:53 +08:00
|
|
|
if (size >= dcache_size)
|
|
|
|
r4k_on_each_cpu(R4K_INDEX,
|
|
|
|
local_r4k_flush_kernel_vmap_range_index, NULL);
|
|
|
|
else
|
|
|
|
r4k_on_each_cpu(R4K_HIT, local_r4k_flush_kernel_vmap_range,
|
|
|
|
&args);
|
2011-06-17 23:20:28 +08:00
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
static inline void rm7k_erratum31(void)
|
|
|
|
{
|
|
|
|
const unsigned long ic_lsize = 32;
|
|
|
|
unsigned long addr;
|
|
|
|
|
|
|
|
/* RM7000 erratum #31. The icache is screwed at startup. */
|
|
|
|
write_c0_taglo(0);
|
|
|
|
write_c0_taghi(0);
|
|
|
|
|
|
|
|
for (addr = INDEX_BASE; addr <= INDEX_BASE + 4096; addr += ic_lsize) {
|
|
|
|
__asm__ __volatile__ (
|
2005-09-02 17:56:12 +08:00
|
|
|
".set push\n\t"
|
2005-04-17 06:20:36 +08:00
|
|
|
".set noreorder\n\t"
|
|
|
|
".set mips3\n\t"
|
|
|
|
"cache\t%1, 0(%0)\n\t"
|
|
|
|
"cache\t%1, 0x1000(%0)\n\t"
|
|
|
|
"cache\t%1, 0x2000(%0)\n\t"
|
|
|
|
"cache\t%1, 0x3000(%0)\n\t"
|
|
|
|
"cache\t%2, 0(%0)\n\t"
|
|
|
|
"cache\t%2, 0x1000(%0)\n\t"
|
|
|
|
"cache\t%2, 0x2000(%0)\n\t"
|
|
|
|
"cache\t%2, 0x3000(%0)\n\t"
|
|
|
|
"cache\t%1, 0(%0)\n\t"
|
|
|
|
"cache\t%1, 0x1000(%0)\n\t"
|
|
|
|
"cache\t%1, 0x2000(%0)\n\t"
|
|
|
|
"cache\t%1, 0x3000(%0)\n\t"
|
2005-09-02 17:56:12 +08:00
|
|
|
".set pop\n"
|
2005-04-17 06:20:36 +08:00
|
|
|
:
|
2020-04-26 19:09:52 +08:00
|
|
|
: "r" (addr), "i" (Index_Store_Tag_I), "i" (Fill_I));
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-16 09:02:29 +08:00
|
|
|
static inline int alias_74k_erratum(struct cpuinfo_mips *c)
|
2012-06-26 12:11:03 +08:00
|
|
|
{
|
2013-09-19 02:08:15 +08:00
|
|
|
unsigned int imp = c->processor_id & PRID_IMP_MASK;
|
|
|
|
unsigned int rev = c->processor_id & PRID_REV_MASK;
|
2014-11-16 09:02:29 +08:00
|
|
|
int present = 0;
|
2013-09-19 02:08:15 +08:00
|
|
|
|
2012-06-26 12:11:03 +08:00
|
|
|
/*
|
|
|
|
* Early versions of the 74K do not update the cache tags on a
|
|
|
|
* vtag miss/ptag hit which can occur in the case of KSEG0/KUSEG
|
2014-11-16 09:02:29 +08:00
|
|
|
* aliases. In this case it is better to treat the cache as always
|
|
|
|
* having aliases. Also disable the synonym tag update feature
|
|
|
|
* where available. In this case no opportunistic tag update will
|
|
|
|
* happen where a load causes a virtual address miss but a physical
|
|
|
|
* address hit during a D-cache look-up.
|
2012-06-26 12:11:03 +08:00
|
|
|
*/
|
2013-09-19 02:08:15 +08:00
|
|
|
switch (imp) {
|
|
|
|
case PRID_IMP_74K:
|
|
|
|
if (rev <= PRID_REV_ENCODE_332(2, 4, 0))
|
2014-11-16 09:02:29 +08:00
|
|
|
present = 1;
|
2013-09-19 02:08:15 +08:00
|
|
|
if (rev == PRID_REV_ENCODE_332(2, 4, 0))
|
2020-06-17 20:34:42 +08:00
|
|
|
write_c0_config6(read_c0_config6() | MTI_CONF6_SYND);
|
2013-09-19 02:08:15 +08:00
|
|
|
break;
|
|
|
|
case PRID_IMP_1074K:
|
|
|
|
if (rev <= PRID_REV_ENCODE_332(1, 1, 0)) {
|
2014-11-16 09:02:29 +08:00
|
|
|
present = 1;
|
2020-06-17 20:34:42 +08:00
|
|
|
write_c0_config6(read_c0_config6() | MTI_CONF6_SYND);
|
2013-09-19 02:08:15 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BUG();
|
2012-06-26 12:11:03 +08:00
|
|
|
}
|
2014-11-16 09:02:29 +08:00
|
|
|
|
|
|
|
return present;
|
2012-06-26 12:11:03 +08:00
|
|
|
}
|
|
|
|
|
2014-10-21 12:28:00 +08:00
|
|
|
static void b5k_instruction_hazard(void)
|
|
|
|
{
|
|
|
|
__sync();
|
|
|
|
__sync();
|
|
|
|
__asm__ __volatile__(
|
|
|
|
" nop; nop; nop; nop; nop; nop; nop; nop\n"
|
|
|
|
" nop; nop; nop; nop; nop; nop; nop; nop\n"
|
|
|
|
" nop; nop; nop; nop; nop; nop; nop; nop\n"
|
|
|
|
" nop; nop; nop; nop; nop; nop; nop; nop\n"
|
|
|
|
: : : "memory");
|
|
|
|
}
|
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 21:38:59 +08:00
|
|
|
static char *way_string[] = { NULL, "direct mapped", "2-way",
|
2015-07-09 17:40:41 +08:00
|
|
|
"3-way", "4-way", "5-way", "6-way", "7-way", "8-way",
|
|
|
|
"9-way", "10-way", "11-way", "12-way",
|
|
|
|
"13-way", "14-way", "15-way", "16-way",
|
2005-04-17 06:20:36 +08:00
|
|
|
};
|
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 21:38:59 +08:00
|
|
|
static void probe_pcache(void)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct cpuinfo_mips *c = ¤t_cpu_data;
|
|
|
|
unsigned int config = read_c0_config();
|
|
|
|
unsigned int prid = read_c0_prid();
|
2014-11-16 09:02:29 +08:00
|
|
|
int has_74k_erratum = 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
unsigned long config1;
|
|
|
|
unsigned int lsize;
|
|
|
|
|
2013-09-17 16:25:47 +08:00
|
|
|
switch (current_cpu_type()) {
|
2005-04-17 06:20:36 +08:00
|
|
|
case CPU_R4600: /* QED style two way caches? */
|
|
|
|
case CPU_R4700:
|
|
|
|
case CPU_R5000:
|
|
|
|
case CPU_NEVADA:
|
|
|
|
icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
|
|
|
|
c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
|
|
|
|
c->icache.ways = 2;
|
2006-04-08 00:33:31 +08:00
|
|
|
c->icache.waybit = __ffs(icache_size/2);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
|
|
|
|
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
|
|
|
|
c->dcache.ways = 2;
|
2006-04-08 00:33:31 +08:00
|
|
|
c->dcache.waybit= __ffs(dcache_size/2);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
c->options |= MIPS_CPU_CACHE_CDEX_P;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CPU_R5500:
|
|
|
|
icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
|
|
|
|
c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
|
|
|
|
c->icache.ways = 2;
|
|
|
|
c->icache.waybit= 0;
|
|
|
|
|
|
|
|
dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
|
|
|
|
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
|
|
|
|
c->dcache.ways = 2;
|
|
|
|
c->dcache.waybit = 0;
|
|
|
|
|
2009-03-18 08:04:01 +08:00
|
|
|
c->options |= MIPS_CPU_CACHE_CDEX_P | MIPS_CPU_PREFETCH;
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CPU_TX49XX:
|
|
|
|
icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
|
|
|
|
c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
|
|
|
|
c->icache.ways = 4;
|
|
|
|
c->icache.waybit= 0;
|
|
|
|
|
|
|
|
dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
|
|
|
|
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
|
|
|
|
c->dcache.ways = 4;
|
|
|
|
c->dcache.waybit = 0;
|
|
|
|
|
|
|
|
c->options |= MIPS_CPU_CACHE_CDEX_P;
|
2006-03-17 11:59:22 +08:00
|
|
|
c->options |= MIPS_CPU_PREFETCH;
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case CPU_R4000PC:
|
|
|
|
case CPU_R4000SC:
|
|
|
|
case CPU_R4000MC:
|
|
|
|
case CPU_R4400PC:
|
|
|
|
case CPU_R4400SC:
|
|
|
|
case CPU_R4400MC:
|
2021-01-13 23:10:07 +08:00
|
|
|
case CPU_R4300:
|
2005-04-17 06:20:36 +08:00
|
|
|
icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
|
|
|
|
c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
|
|
|
|
c->icache.ways = 1;
|
2013-01-22 19:59:30 +08:00
|
|
|
c->icache.waybit = 0; /* doesn't matter */
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
|
|
|
|
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
|
|
|
|
c->dcache.ways = 1;
|
|
|
|
c->dcache.waybit = 0; /* does not matter */
|
|
|
|
|
|
|
|
c->options |= MIPS_CPU_CACHE_CDEX_P;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CPU_R10000:
|
|
|
|
case CPU_R12000:
|
2006-05-17 10:23:59 +08:00
|
|
|
case CPU_R14000:
|
2015-01-21 20:59:45 +08:00
|
|
|
case CPU_R16000:
|
2005-04-17 06:20:36 +08:00
|
|
|
icache_size = 1 << (12 + ((config & R10K_CONF_IC) >> 29));
|
|
|
|
c->icache.linesz = 64;
|
|
|
|
c->icache.ways = 2;
|
|
|
|
c->icache.waybit = 0;
|
|
|
|
|
|
|
|
dcache_size = 1 << (12 + ((config & R10K_CONF_DC) >> 26));
|
|
|
|
c->dcache.linesz = 32;
|
|
|
|
c->dcache.ways = 2;
|
|
|
|
c->dcache.waybit = 0;
|
|
|
|
|
|
|
|
c->options |= MIPS_CPU_PREFETCH;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CPU_RM7000:
|
|
|
|
rm7k_erratum31();
|
|
|
|
|
|
|
|
icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
|
|
|
|
c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
|
|
|
|
c->icache.ways = 4;
|
2006-04-08 00:33:31 +08:00
|
|
|
c->icache.waybit = __ffs(icache_size / c->icache.ways);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
|
|
|
|
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
|
|
|
|
c->dcache.ways = 4;
|
2006-04-08 00:33:31 +08:00
|
|
|
c->dcache.waybit = __ffs(dcache_size / c->dcache.ways);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
c->options |= MIPS_CPU_CACHE_CDEX_P;
|
|
|
|
c->options |= MIPS_CPU_PREFETCH;
|
|
|
|
break;
|
|
|
|
|
2019-10-20 22:43:13 +08:00
|
|
|
case CPU_LOONGSON2EF:
|
2007-06-06 14:52:43 +08:00
|
|
|
icache_size = 1 << (12 + ((config & CONF_IC) >> 9));
|
|
|
|
c->icache.linesz = 16 << ((config & CONF_IB) >> 5);
|
|
|
|
if (prid & 0x3)
|
|
|
|
c->icache.ways = 4;
|
|
|
|
else
|
|
|
|
c->icache.ways = 2;
|
|
|
|
c->icache.waybit = 0;
|
|
|
|
|
|
|
|
dcache_size = 1 << (12 + ((config & CONF_DC) >> 6));
|
|
|
|
c->dcache.linesz = 16 << ((config & CONF_DB) >> 4);
|
|
|
|
if (prid & 0x3)
|
|
|
|
c->dcache.ways = 4;
|
|
|
|
else
|
|
|
|
c->dcache.ways = 2;
|
|
|
|
c->dcache.waybit = 0;
|
|
|
|
break;
|
|
|
|
|
2019-10-20 22:43:13 +08:00
|
|
|
case CPU_LOONGSON64:
|
2014-03-21 18:44:00 +08:00
|
|
|
config1 = read_c0_config1();
|
|
|
|
lsize = (config1 >> 19) & 7;
|
|
|
|
if (lsize)
|
|
|
|
c->icache.linesz = 2 << lsize;
|
|
|
|
else
|
|
|
|
c->icache.linesz = 0;
|
|
|
|
c->icache.sets = 64 << ((config1 >> 22) & 7);
|
|
|
|
c->icache.ways = 1 + ((config1 >> 16) & 7);
|
|
|
|
icache_size = c->icache.sets *
|
|
|
|
c->icache.ways *
|
|
|
|
c->icache.linesz;
|
|
|
|
c->icache.waybit = 0;
|
|
|
|
|
|
|
|
lsize = (config1 >> 10) & 7;
|
|
|
|
if (lsize)
|
|
|
|
c->dcache.linesz = 2 << lsize;
|
|
|
|
else
|
|
|
|
c->dcache.linesz = 0;
|
|
|
|
c->dcache.sets = 64 << ((config1 >> 13) & 7);
|
|
|
|
c->dcache.ways = 1 + ((config1 >> 7) & 7);
|
|
|
|
dcache_size = c->dcache.sets *
|
|
|
|
c->dcache.ways *
|
|
|
|
c->dcache.linesz;
|
|
|
|
c->dcache.waybit = 0;
|
MIPS: Loongson: Add Loongson-3A R4 basic support
All Loongson-3 CPU family:
Code-name Brand-name PRId
Loongson-3A R1 Loongson-3A1000 0x6305
Loongson-3A R2 Loongson-3A2000 0x6308
Loongson-3A R2.1 Loongson-3A2000 0x630c
Loongson-3A R3 Loongson-3A3000 0x6309
Loongson-3A R3.1 Loongson-3A3000 0x630d
Loongson-3A R4 Loongson-3A4000 0xc000
Loongson-3B R1 Loongson-3B1000 0x6306
Loongson-3B R2 Loongson-3B1500 0x6307
Features of R4 revision of Loongson-3A:
- All R2/R3 features, including SFB, V-Cache, FTLB, RIXI, DSP, etc.
- Support variable ASID bits.
- Support MSA and VZ extensions.
- Support CPUCFG (CPU config) and CSR (Control and Status Register)
extensions.
- 64 entries of VTLB (classic TLB), 2048 entries of FTLB (8-way
set-associative).
Now 64-bit Loongson processors has three types of PRID.IMP: 0x6300 is
the classic one so we call it PRID_IMP_LOONGSON_64C (e.g., Loongson-2E/
2F/3A1000/3B1000/3B1500/3A2000/3A3000), 0x6100 is for some processors
which has reduced capabilities so we call it PRID_IMP_LOONGSON_64R
(e.g., Loongson-2K), 0xc000 is supposed to cover all new processors in
general (e.g., Loongson-3A4000+) so we call it PRID_IMP_LOONGSON_64G.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@linux-mips.org
Cc: linux-mips@vger.kernel.org
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: Huacai Chen <chenhuacai@gmail.com>
2019-09-21 21:50:27 +08:00
|
|
|
if ((c->processor_id & (PRID_IMP_MASK | PRID_REV_MASK)) >=
|
2020-04-22 22:43:44 +08:00
|
|
|
(PRID_IMP_LOONGSON_64C | PRID_REV_LOONGSON3A_R2_0) ||
|
|
|
|
(c->processor_id & PRID_IMP_MASK) == PRID_IMP_LOONGSON_64R)
|
MIPS: Loongson-3: Introduce CONFIG_LOONGSON3_ENHANCEMENT
New Loongson 3 CPU (since Loongson-3A R2, as opposed to Loongson-3A R1,
Loongson-3B R1 and Loongson-3B R2) has many enhancements, such as FTLB,
L1-VCache, EI/DI/Wait/Prefetch instruction, DSP/DSPv2 ASE, User Local
register, Read-Inhibit/Execute-Inhibit, SFB (Store Fill Buffer), Fast
TLB refill support, etc.
This patch introduce a config option, CONFIG_LOONGSON3_ENHANCEMENT, to
enable those enhancements which are not probed at run time. If you want
a generic kernel to run on all Loongson 3 machines, please say 'N'
here. If you want a high-performance kernel to run on new Loongson 3
machines only, please say 'Y' here.
Some additional explanations:
1) SFB locates between core and L1 cache, it causes memory access out
of order, so writel/outl (and other similar functions) need a I/O
reorder barrier.
2) Loongson 3 has a bug that di instruction can not save the irqflag,
so arch_local_irq_save() is modified. Since CPU_MIPSR2 is selected
by CONFIG_LOONGSON3_ENHANCEMENT, generic kernel doesn't use ei/di
at all.
3) CPU_HAS_PREFETCH is selected by CONFIG_LOONGSON3_ENHANCEMENT, so
MIPS_CPU_PREFETCH (used by uasm) probing is also put in this patch.
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
Cc: Steven J . Hill <sjhill@realitydiluted.com>
Cc: Fuxin Zhang <zhangfx@lemote.com>
Cc: Zhangjin Wu <wuzhangjin@gmail.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/12755/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2016-03-03 09:45:13 +08:00
|
|
|
c->options |= MIPS_CPU_PREFETCH;
|
2014-03-21 18:44:00 +08:00
|
|
|
break;
|
|
|
|
|
2014-05-29 05:52:09 +08:00
|
|
|
case CPU_CAVIUM_OCTEON3:
|
|
|
|
/* For now lie about the number of ways. */
|
|
|
|
c->icache.linesz = 128;
|
|
|
|
c->icache.sets = 16;
|
|
|
|
c->icache.ways = 8;
|
|
|
|
c->icache.flags |= MIPS_CACHE_VTAG;
|
|
|
|
icache_size = c->icache.sets * c->icache.ways * c->icache.linesz;
|
|
|
|
|
|
|
|
c->dcache.linesz = 128;
|
|
|
|
c->dcache.ways = 8;
|
|
|
|
c->dcache.sets = 8;
|
|
|
|
dcache_size = c->dcache.sets * c->dcache.ways * c->dcache.linesz;
|
|
|
|
c->options |= MIPS_CPU_PREFETCH;
|
|
|
|
break;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
default:
|
|
|
|
if (!(config & MIPS_CONF_M))
|
|
|
|
panic("Don't know how to probe P-caches on this cpu.");
|
|
|
|
|
|
|
|
/*
|
|
|
|
* So we seem to be a MIPS32 or MIPS64 CPU
|
|
|
|
* So let's probe the I-cache ...
|
|
|
|
*/
|
|
|
|
config1 = read_c0_config1();
|
|
|
|
|
2013-09-20 01:18:41 +08:00
|
|
|
lsize = (config1 >> 19) & 7;
|
|
|
|
|
|
|
|
/* IL == 7 is reserved */
|
|
|
|
if (lsize == 7)
|
|
|
|
panic("Invalid icache line size");
|
|
|
|
|
|
|
|
c->icache.linesz = lsize ? 2 << lsize : 0;
|
|
|
|
|
2012-07-19 15:11:13 +08:00
|
|
|
c->icache.sets = 32 << (((config1 >> 22) + 1) & 7);
|
2005-04-17 06:20:36 +08:00
|
|
|
c->icache.ways = 1 + ((config1 >> 16) & 7);
|
|
|
|
|
|
|
|
icache_size = c->icache.sets *
|
2013-01-22 19:59:30 +08:00
|
|
|
c->icache.ways *
|
|
|
|
c->icache.linesz;
|
2006-04-08 00:33:31 +08:00
|
|
|
c->icache.waybit = __ffs(icache_size/c->icache.ways);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2016-06-16 02:29:59 +08:00
|
|
|
if (config & MIPS_CONF_VI)
|
2005-04-17 06:20:36 +08:00
|
|
|
c->icache.flags |= MIPS_CACHE_VTAG;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now probe the MIPS32 / MIPS64 data cache.
|
|
|
|
*/
|
|
|
|
c->dcache.flags = 0;
|
|
|
|
|
2013-09-20 01:18:41 +08:00
|
|
|
lsize = (config1 >> 10) & 7;
|
|
|
|
|
|
|
|
/* DL == 7 is reserved */
|
|
|
|
if (lsize == 7)
|
|
|
|
panic("Invalid dcache line size");
|
|
|
|
|
|
|
|
c->dcache.linesz = lsize ? 2 << lsize : 0;
|
|
|
|
|
2012-07-19 15:11:13 +08:00
|
|
|
c->dcache.sets = 32 << (((config1 >> 13) + 1) & 7);
|
2005-04-17 06:20:36 +08:00
|
|
|
c->dcache.ways = 1 + ((config1 >> 7) & 7);
|
|
|
|
|
|
|
|
dcache_size = c->dcache.sets *
|
2013-01-22 19:59:30 +08:00
|
|
|
c->dcache.ways *
|
|
|
|
c->dcache.linesz;
|
2006-04-08 00:33:31 +08:00
|
|
|
c->dcache.waybit = __ffs(dcache_size/c->dcache.ways);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
c->options |= MIPS_CPU_PREFETCH;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Processor configuration sanity check for the R4000SC erratum
|
2013-01-22 19:59:30 +08:00
|
|
|
* #5. With page sizes larger than 32kB there is no possibility
|
2005-04-17 06:20:36 +08:00
|
|
|
* to get a VCE exception anymore so we don't care about this
|
|
|
|
* misconfiguration. The case is rather theoretical anyway;
|
|
|
|
* presumably no vendor is shipping his hardware in the "bad"
|
|
|
|
* configuration.
|
|
|
|
*/
|
2013-09-17 23:58:10 +08:00
|
|
|
if ((prid & PRID_IMP_MASK) == PRID_IMP_R4000 &&
|
|
|
|
(prid & PRID_REV_MASK) < PRID_REV_R4400 &&
|
2005-04-17 06:20:36 +08:00
|
|
|
!(config & CONF_SC) && c->icache.linesz != 16 &&
|
|
|
|
PAGE_SIZE <= 0x8000)
|
|
|
|
panic("Improper R4000SC processor configuration detected");
|
|
|
|
|
|
|
|
/* compute a couple of other cache variables */
|
|
|
|
c->icache.waysize = icache_size / c->icache.ways;
|
|
|
|
c->dcache.waysize = dcache_size / c->dcache.ways;
|
|
|
|
|
2006-06-21 01:06:52 +08:00
|
|
|
c->icache.sets = c->icache.linesz ?
|
|
|
|
icache_size / (c->icache.linesz * c->icache.ways) : 0;
|
|
|
|
c->dcache.sets = c->dcache.linesz ?
|
|
|
|
dcache_size / (c->dcache.linesz * c->dcache.ways) : 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/*
|
2015-01-21 20:59:45 +08:00
|
|
|
* R1x000 P-caches are odd in a positive way. They're 32kB 2-way
|
|
|
|
* virtually indexed so normally would suffer from aliases. So
|
2005-04-17 06:20:36 +08:00
|
|
|
* normally they'd suffer from aliases but magic in the hardware deals
|
|
|
|
* with that for us so we don't need to take care ourselves.
|
|
|
|
*/
|
2013-09-17 16:25:47 +08:00
|
|
|
switch (current_cpu_type()) {
|
2005-02-08 05:41:32 +08:00
|
|
|
case CPU_20KC:
|
2005-02-08 05:53:39 +08:00
|
|
|
case CPU_25KF:
|
2016-08-20 01:13:34 +08:00
|
|
|
case CPU_I6400:
|
2017-06-03 03:39:04 +08:00
|
|
|
case CPU_I6500:
|
2007-10-12 06:46:05 +08:00
|
|
|
case CPU_SB1:
|
|
|
|
case CPU_SB1A:
|
2006-03-13 17:23:03 +08:00
|
|
|
c->dcache.flags |= MIPS_CACHE_PINDEX;
|
2007-10-12 06:46:05 +08:00
|
|
|
break;
|
|
|
|
|
2005-02-04 23:51:26 +08:00
|
|
|
case CPU_R10000:
|
|
|
|
case CPU_R12000:
|
2006-05-17 10:23:59 +08:00
|
|
|
case CPU_R14000:
|
2015-01-21 20:59:45 +08:00
|
|
|
case CPU_R16000:
|
2005-02-04 23:51:26 +08:00
|
|
|
break;
|
2007-10-12 06:46:05 +08:00
|
|
|
|
2014-06-29 06:28:08 +08:00
|
|
|
case CPU_74K:
|
|
|
|
case CPU_1074K:
|
2014-11-16 09:02:29 +08:00
|
|
|
has_74k_erratum = alias_74k_erratum(c);
|
2020-05-04 16:51:29 +08:00
|
|
|
fallthrough;
|
2012-07-07 05:56:00 +08:00
|
|
|
case CPU_M14KC:
|
2012-12-07 11:51:35 +08:00
|
|
|
case CPU_M14KEC:
|
2005-02-04 23:51:26 +08:00
|
|
|
case CPU_24K:
|
2006-04-27 22:50:32 +08:00
|
|
|
case CPU_34K:
|
2008-04-29 00:14:26 +08:00
|
|
|
case CPU_1004K:
|
2013-11-27 18:07:53 +08:00
|
|
|
case CPU_INTERAPTIV:
|
2014-01-23 00:19:38 +08:00
|
|
|
case CPU_P5600:
|
2013-11-15 00:12:27 +08:00
|
|
|
case CPU_PROAPTIV:
|
2014-03-04 21:34:43 +08:00
|
|
|
case CPU_M5150:
|
2014-11-24 20:59:01 +08:00
|
|
|
case CPU_QEMU_GENERIC:
|
2016-02-03 11:26:38 +08:00
|
|
|
case CPU_P6600:
|
2016-02-04 00:17:29 +08:00
|
|
|
case CPU_M6250:
|
2014-01-31 01:21:29 +08:00
|
|
|
if (!(read_c0_config7() & MIPS_CONF7_IAR) &&
|
|
|
|
(c->icache.waysize > PAGE_SIZE))
|
|
|
|
c->icache.flags |= MIPS_CACHE_ALIASES;
|
2014-11-16 09:02:29 +08:00
|
|
|
if (!has_74k_erratum && (read_c0_config7() & MIPS_CONF7_AR)) {
|
2014-01-31 01:21:29 +08:00
|
|
|
/*
|
|
|
|
* Effectively physically indexed dcache,
|
|
|
|
* thus no virtual aliases.
|
|
|
|
*/
|
2006-06-20 04:56:25 +08:00
|
|
|
c->dcache.flags |= MIPS_CACHE_PINDEX;
|
|
|
|
break;
|
|
|
|
}
|
2020-05-04 16:51:29 +08:00
|
|
|
fallthrough;
|
2005-02-04 23:51:26 +08:00
|
|
|
default:
|
2014-11-16 09:02:29 +08:00
|
|
|
if (has_74k_erratum || c->dcache.waysize > PAGE_SIZE)
|
2006-06-20 04:56:25 +08:00
|
|
|
c->dcache.flags |= MIPS_CACHE_ALIASES;
|
2005-02-04 23:51:26 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2016-08-20 01:13:35 +08:00
|
|
|
/* Physically indexed caches don't suffer from virtual aliasing */
|
|
|
|
if (c->dcache.flags & MIPS_CACHE_PINDEX)
|
|
|
|
c->dcache.flags &= ~MIPS_CACHE_ALIASES;
|
|
|
|
|
2017-06-03 06:17:25 +08:00
|
|
|
/*
|
|
|
|
* In systems with CM the icache fills from L2 or closer caches, and
|
|
|
|
* thus sees remote stores without needing to write them back any
|
|
|
|
* further than that.
|
|
|
|
*/
|
|
|
|
if (mips_cm_present())
|
|
|
|
c->icache.flags |= MIPS_IC_SNOOPS_REMOTE;
|
|
|
|
|
2013-09-17 16:25:47 +08:00
|
|
|
switch (current_cpu_type()) {
|
2005-04-17 06:20:36 +08:00
|
|
|
case CPU_20KC:
|
|
|
|
/*
|
|
|
|
* Some older 20Kc chips doesn't have the 'VI' bit in
|
|
|
|
* the config register.
|
|
|
|
*/
|
|
|
|
c->icache.flags |= MIPS_CACHE_VTAG;
|
|
|
|
break;
|
|
|
|
|
2009-03-26 00:49:28 +08:00
|
|
|
case CPU_ALCHEMY:
|
2016-01-22 18:58:26 +08:00
|
|
|
case CPU_I6400:
|
2017-06-03 03:39:04 +08:00
|
|
|
case CPU_I6500:
|
2005-04-17 06:20:36 +08:00
|
|
|
c->icache.flags |= MIPS_CACHE_IC_F_DC;
|
|
|
|
break;
|
|
|
|
|
2016-04-05 01:55:34 +08:00
|
|
|
case CPU_BMIPS5000:
|
|
|
|
c->icache.flags |= MIPS_CACHE_IC_F_DC;
|
MIPS: BMIPS: Clear MIPS_CACHE_ALIASES earlier
BMIPS5000 and BMIPS5200 processor have no D cache aliases, and this is
properly handled by the per-CPU override added at the end of
r4k_cache_init(), the problem is that the output of probe_pcache()
disagrees with that, since this is too late:
Primary instruction cache 32kB, VIPT, 4-way, linesize 64 bytes.
Primary data cache 32kB, 4-way, VIPT, cache aliases, linesize 32 bytes
With the change moved earlier, we now have a consistent output with the
settings we are intending to have:
Primary instruction cache 32kB, VIPT, 4-way, linesize 64 bytes.
Primary data cache 32kB, 4-way, VIPT, no aliases, linesize 32 bytes
Fixes: d74b0172e4e2c ("MIPS: BMIPS: Add special cache handling in c-r4k.c")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/13011/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2016-04-05 01:55:35 +08:00
|
|
|
/* Cache aliases are handled in hardware; allow HIGHMEM */
|
|
|
|
c->dcache.flags &= ~MIPS_CACHE_ALIASES;
|
2016-04-05 01:55:34 +08:00
|
|
|
break;
|
|
|
|
|
2019-10-20 22:43:13 +08:00
|
|
|
case CPU_LOONGSON2EF:
|
2013-09-26 00:21:26 +08:00
|
|
|
/*
|
|
|
|
* LOONGSON2 has 4 way icache, but when using indexed cache op,
|
|
|
|
* one op will act on all 4 ways
|
|
|
|
*/
|
|
|
|
c->icache.ways = 1;
|
|
|
|
}
|
2007-06-06 14:52:43 +08:00
|
|
|
|
2020-02-28 13:52:38 +08:00
|
|
|
pr_info("Primary instruction cache %ldkB, %s, %s, linesize %d bytes.\n",
|
|
|
|
icache_size >> 10,
|
|
|
|
c->icache.flags & MIPS_CACHE_VTAG ? "VIVT" : "VIPT",
|
|
|
|
way_string[c->icache.ways], c->icache.linesz);
|
|
|
|
|
|
|
|
pr_info("Primary data cache %ldkB, %s, %s, %s, linesize %d bytes\n",
|
|
|
|
dcache_size >> 10, way_string[c->dcache.ways],
|
|
|
|
(c->dcache.flags & MIPS_CACHE_PINDEX) ? "PIPT" : "VIPT",
|
|
|
|
(c->dcache.flags & MIPS_CACHE_ALIASES) ?
|
2007-10-15 23:35:45 +08:00
|
|
|
"cache aliases" : "no aliases",
|
2020-02-28 13:52:38 +08:00
|
|
|
c->dcache.linesz);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2016-03-03 09:45:09 +08:00
|
|
|
static void probe_vcache(void)
|
|
|
|
{
|
|
|
|
struct cpuinfo_mips *c = ¤t_cpu_data;
|
|
|
|
unsigned int config2, lsize;
|
|
|
|
|
2019-10-20 22:43:13 +08:00
|
|
|
if (current_cpu_type() != CPU_LOONGSON64)
|
2016-03-03 09:45:09 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
config2 = read_c0_config2();
|
|
|
|
if ((lsize = ((config2 >> 20) & 15)))
|
|
|
|
c->vcache.linesz = 2 << lsize;
|
|
|
|
else
|
|
|
|
c->vcache.linesz = lsize;
|
|
|
|
|
|
|
|
c->vcache.sets = 64 << ((config2 >> 24) & 15);
|
|
|
|
c->vcache.ways = 1 + ((config2 >> 16) & 15);
|
|
|
|
|
|
|
|
vcache_size = c->vcache.sets * c->vcache.ways * c->vcache.linesz;
|
|
|
|
|
|
|
|
c->vcache.waybit = 0;
|
2017-03-16 21:00:29 +08:00
|
|
|
c->vcache.waysize = vcache_size / c->vcache.ways;
|
2016-03-03 09:45:09 +08:00
|
|
|
|
|
|
|
pr_info("Unified victim cache %ldkB %s, linesize %d bytes.\n",
|
|
|
|
vcache_size >> 10, way_string[c->vcache.ways], c->vcache.linesz);
|
|
|
|
}
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
* If you even _breathe_ on this function, look at the gcc output and make sure
|
|
|
|
* it does not pop things on and off the stack for the cache sizing loop that
|
|
|
|
* executes in KSEG1 space or else you will crash and burn badly. You have
|
|
|
|
* been warned.
|
|
|
|
*/
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 21:38:59 +08:00
|
|
|
static int probe_scache(void)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
unsigned long flags, addr, begin, end, pow2;
|
|
|
|
unsigned int config = read_c0_config();
|
|
|
|
struct cpuinfo_mips *c = ¤t_cpu_data;
|
|
|
|
|
|
|
|
if (config & CONF_SC)
|
|
|
|
return 0;
|
|
|
|
|
2007-07-28 19:45:47 +08:00
|
|
|
begin = (unsigned long) &_stext;
|
2005-04-17 06:20:36 +08:00
|
|
|
begin &= ~((4 * 1024 * 1024) - 1);
|
|
|
|
end = begin + (4 * 1024 * 1024);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is such a bitch, you'd think they would make it easy to do
|
|
|
|
* this. Away you daemons of stupidity!
|
|
|
|
*/
|
|
|
|
local_irq_save(flags);
|
|
|
|
|
|
|
|
/* Fill each size-multiple cache line with a valid tag. */
|
|
|
|
pow2 = (64 * 1024);
|
|
|
|
for (addr = begin; addr < end; addr = (begin + pow2)) {
|
|
|
|
unsigned long *p = (unsigned long *) addr;
|
|
|
|
__asm__ __volatile__("nop" : : "r" (*p)); /* whee... */
|
|
|
|
pow2 <<= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Load first line with zero (therefore invalid) tag. */
|
|
|
|
write_c0_taglo(0);
|
|
|
|
write_c0_taghi(0);
|
|
|
|
__asm__ __volatile__("nop; nop; nop; nop;"); /* avoid the hazard */
|
|
|
|
cache_op(Index_Store_Tag_I, begin);
|
|
|
|
cache_op(Index_Store_Tag_D, begin);
|
|
|
|
cache_op(Index_Store_Tag_SD, begin);
|
|
|
|
|
|
|
|
/* Now search for the wrap around point. */
|
|
|
|
pow2 = (128 * 1024);
|
|
|
|
for (addr = begin + (128 * 1024); addr < end; addr = begin + pow2) {
|
|
|
|
cache_op(Index_Load_Tag_SD, addr);
|
|
|
|
__asm__ __volatile__("nop; nop; nop; nop;"); /* hazard... */
|
|
|
|
if (!read_c0_taglo())
|
|
|
|
break;
|
|
|
|
pow2 <<= 1;
|
|
|
|
}
|
|
|
|
local_irq_restore(flags);
|
|
|
|
addr -= begin;
|
|
|
|
|
|
|
|
scache_size = addr;
|
|
|
|
c->scache.linesz = 16 << ((config & R4K_CONF_SB) >> 22);
|
|
|
|
c->scache.ways = 1;
|
2015-06-03 04:55:22 +08:00
|
|
|
c->scache.waybit = 0; /* does not matter */
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2021-01-06 04:34:56 +08:00
|
|
|
static void loongson2_sc_init(void)
|
2007-06-06 14:52:43 +08:00
|
|
|
{
|
|
|
|
struct cpuinfo_mips *c = ¤t_cpu_data;
|
|
|
|
|
|
|
|
scache_size = 512*1024;
|
|
|
|
c->scache.linesz = 32;
|
|
|
|
c->scache.ways = 4;
|
|
|
|
c->scache.waybit = 0;
|
|
|
|
c->scache.waysize = scache_size / (c->scache.ways);
|
|
|
|
c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
|
|
|
|
pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
|
|
|
|
scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
|
|
|
|
|
|
|
|
c->options |= MIPS_CPU_INCLUSIVE_CACHES;
|
|
|
|
}
|
|
|
|
|
2020-11-27 16:39:43 +08:00
|
|
|
static void loongson3_sc_init(void)
|
2014-03-21 18:44:00 +08:00
|
|
|
{
|
|
|
|
struct cpuinfo_mips *c = ¤t_cpu_data;
|
|
|
|
unsigned int config2, lsize;
|
|
|
|
|
|
|
|
config2 = read_c0_config2();
|
|
|
|
lsize = (config2 >> 4) & 15;
|
|
|
|
if (lsize)
|
|
|
|
c->scache.linesz = 2 << lsize;
|
|
|
|
else
|
|
|
|
c->scache.linesz = 0;
|
|
|
|
c->scache.sets = 64 << ((config2 >> 8) & 15);
|
|
|
|
c->scache.ways = 1 + (config2 & 15);
|
|
|
|
|
2020-04-22 22:43:44 +08:00
|
|
|
/* Loongson-3 has 4-Scache banks, while Loongson-2K have only 2 banks */
|
|
|
|
if ((c->processor_id & PRID_IMP_MASK) == PRID_IMP_LOONGSON_64R)
|
MIPS: Loongson64: Fix wrong scache size when execute lscpu
As the user manual and code comment said, Loongson-3 has 4-scache banks,
while Loongson-2K has only 2 banks, so we should multiply the number of
scache banks, this multiply operation should be done by c->scache.sets
instead of scache_size, otherwise we will get the wrong scache size when
execute lscpu. For example, the scache size should be 8192K instead of
2048K on the Loongson 3A3000 and 3A4000 platform, we can see the related
info in the following boot message:
[loongson@linux ~]$ dmesg | grep "Unified secondary cache"
[ 0.000000] Unified secondary cache 8192kB 16-way, linesize 64 bytes.
[ 4.061909] Unified secondary cache 8192kB 16-way, linesize 64 bytes.
[ 4.125629] Unified secondary cache 8192kB 16-way, linesize 64 bytes.
[ 4.188379] Unified secondary cache 8192kB 16-way, linesize 64 bytes.
E.g. without this patch:
[loongson@linux ~]$ cat /sys/devices/system/cpu/cpu*/cache/index2/size
2048K
2048K
2048K
2048K
[loongson@linux ~]$ lscpu | grep "L2 cache"
L2 cache: 2048K
With this patch:
[loongson@linux ~]$ cat /sys/devices/system/cpu/cpu*/cache/index2/size
8192K
8192K
8192K
8192K
[loongson@linux ~]$ lscpu | grep "L2 cache"
L2 cache: 8192K
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
2020-11-19 15:53:01 +08:00
|
|
|
c->scache.sets *= 2;
|
2020-04-22 22:43:44 +08:00
|
|
|
else
|
MIPS: Loongson64: Fix wrong scache size when execute lscpu
As the user manual and code comment said, Loongson-3 has 4-scache banks,
while Loongson-2K has only 2 banks, so we should multiply the number of
scache banks, this multiply operation should be done by c->scache.sets
instead of scache_size, otherwise we will get the wrong scache size when
execute lscpu. For example, the scache size should be 8192K instead of
2048K on the Loongson 3A3000 and 3A4000 platform, we can see the related
info in the following boot message:
[loongson@linux ~]$ dmesg | grep "Unified secondary cache"
[ 0.000000] Unified secondary cache 8192kB 16-way, linesize 64 bytes.
[ 4.061909] Unified secondary cache 8192kB 16-way, linesize 64 bytes.
[ 4.125629] Unified secondary cache 8192kB 16-way, linesize 64 bytes.
[ 4.188379] Unified secondary cache 8192kB 16-way, linesize 64 bytes.
E.g. without this patch:
[loongson@linux ~]$ cat /sys/devices/system/cpu/cpu*/cache/index2/size
2048K
2048K
2048K
2048K
[loongson@linux ~]$ lscpu | grep "L2 cache"
L2 cache: 2048K
With this patch:
[loongson@linux ~]$ cat /sys/devices/system/cpu/cpu*/cache/index2/size
8192K
8192K
8192K
8192K
[loongson@linux ~]$ lscpu | grep "L2 cache"
L2 cache: 8192K
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
2020-11-19 15:53:01 +08:00
|
|
|
c->scache.sets *= 4;
|
|
|
|
|
|
|
|
scache_size = c->scache.sets * c->scache.ways * c->scache.linesz;
|
2020-04-22 22:43:44 +08:00
|
|
|
|
2014-03-21 18:44:00 +08:00
|
|
|
c->scache.waybit = 0;
|
2017-03-16 21:00:29 +08:00
|
|
|
c->scache.waysize = scache_size / c->scache.ways;
|
2014-03-21 18:44:00 +08:00
|
|
|
pr_info("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
|
|
|
|
scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
|
|
|
|
if (scache_size)
|
|
|
|
c->options |= MIPS_CPU_INCLUSIVE_CACHES;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 21:38:59 +08:00
|
|
|
static void setup_scache(void)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct cpuinfo_mips *c = ¤t_cpu_data;
|
|
|
|
unsigned int config = read_c0_config();
|
|
|
|
int sc_present = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do the probing thing on R4000SC and R4400SC processors. Other
|
|
|
|
* processors don't have a S-cache that would be relevant to the
|
2008-02-03 22:54:53 +08:00
|
|
|
* Linux memory management.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2013-09-17 16:25:47 +08:00
|
|
|
switch (current_cpu_type()) {
|
2005-04-17 06:20:36 +08:00
|
|
|
case CPU_R4000SC:
|
|
|
|
case CPU_R4000MC:
|
|
|
|
case CPU_R4400SC:
|
|
|
|
case CPU_R4400MC:
|
2005-04-26 00:36:23 +08:00
|
|
|
sc_present = run_uncached(probe_scache);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (sc_present)
|
|
|
|
c->options |= MIPS_CPU_CACHE_CDEX_S;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CPU_R10000:
|
|
|
|
case CPU_R12000:
|
2006-05-17 10:23:59 +08:00
|
|
|
case CPU_R14000:
|
2015-01-21 20:59:45 +08:00
|
|
|
case CPU_R16000:
|
2005-04-17 06:20:36 +08:00
|
|
|
scache_size = 0x80000 << ((config & R10K_CONF_SS) >> 16);
|
|
|
|
c->scache.linesz = 64 << ((config >> 13) & 1);
|
|
|
|
c->scache.ways = 2;
|
|
|
|
c->scache.waybit= 0;
|
|
|
|
sc_present = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case CPU_R5000:
|
|
|
|
case CPU_NEVADA:
|
|
|
|
#ifdef CONFIG_R5000_CPU_SCACHE
|
|
|
|
r5k_sc_init();
|
|
|
|
#endif
|
2013-01-22 19:59:30 +08:00
|
|
|
return;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
case CPU_RM7000:
|
|
|
|
#ifdef CONFIG_RM7000_CPU_SCACHE
|
|
|
|
rm7k_sc_init();
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
|
2019-10-20 22:43:13 +08:00
|
|
|
case CPU_LOONGSON2EF:
|
2007-06-06 14:52:43 +08:00
|
|
|
loongson2_sc_init();
|
|
|
|
return;
|
2013-09-26 00:21:26 +08:00
|
|
|
|
2019-10-20 22:43:13 +08:00
|
|
|
case CPU_LOONGSON64:
|
2014-03-21 18:44:00 +08:00
|
|
|
loongson3_sc_init();
|
|
|
|
return;
|
|
|
|
|
2014-05-29 05:52:09 +08:00
|
|
|
case CPU_CAVIUM_OCTEON3:
|
2011-11-16 08:21:20 +08:00
|
|
|
/* don't need to worry about L2, fully coherent */
|
|
|
|
return;
|
2007-06-06 14:52:43 +08:00
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
default:
|
mips: Add MIPS Release 5 support
There are five MIPS32/64 architecture releases currently available:
from 1 to 6 except fourth one, which was intentionally skipped.
Three of them can be called as major: 1st, 2nd and 6th, that not only
have some system level alterations, but also introduced significant
core/ISA level updates. The rest of the MIPS architecture releases are
minor.
Even though they don't have as much ISA/system/core level changes
as the major ones with respect to the previous releases, they still
provide a set of updates (I'd say they were intended to be the
intermediate releases before a major one) that might be useful for the
kernel and user-level code, when activated by the kernel or compiler.
In particular the following features were introduced or ended up being
available at/after MIPS32/64 Release 5 architecture:
+ the last release of the misaligned memory access instructions,
+ virtualisation - VZ ASE - is optional component of the arch,
+ SIMD - MSA ASE - is optional component of the arch,
+ DSP ASE is optional component of the arch,
+ CP0.Status.FR=1 for CP1.FIR.F64=1 (pure 64-bit FPU general registers)
must be available if FPU is implemented,
+ CP1.FIR.Has2008 support is required so CP1.FCSR.{ABS2008,NAN2008} bits
are available.
+ UFR/UNFR aliases to access CP0.Status.FR from user-space by means of
ctc1/cfc1 instructions (enabled by CP0.Config5.UFR),
+ CP0.COnfig5.LLB=1 and eretnc instruction are implemented to without
accidentally clearing LL-bit when returning from an interrupt,
exception, or error trap,
+ XPA feature together with extended versions of CPx registers is
introduced, which needs to have mfhc0/mthc0 instructions available.
So due to these changes GNU GCC provides an extended instructions set
support for MIPS32/64 Release 5 by default like eretnc/mfhc0/mthc0. Even
though the architecture alteration isn't that big, it still worth to be
taken into account by the kernel software. Finally we can't deny that
some optimization/limitations might be found in future and implemented
on some level in kernel or compiler. In this case having even
intermediate MIPS architecture releases support would be more than
useful.
So the most of the changes provided by this commit can be split into
either compile- or runtime configs related. The compile-time related
changes are caused by adding the new CONFIG_CPU_MIPS32_R5/CONFIG_CPU_MIPSR5
configs and concern the code activating MIPSR2 or MIPSR6 already
implemented features (like eretnc/LLbit, mthc0/mfhc0). In addition
CPU_HAS_MSA can be now freely enabled for MIPS32/64 release 5 based
platforms as this is done for CPU_MIPS32_R6 CPUs. The runtime changes
concerns the features which are handled with respect to the MIPS ISA
revision detected at run-time by means of CP0.Config.{AT,AR} bits. Alas
these fields can be used to detect either r1 or r2 or r6 releases.
But since we know which CPUs in fact support the R5 arch, we can manually
set MIPS_CPU_ISA_M32R5/MIPS_CPU_ISA_M64R5 bit of c->isa_level and then
use cpu_has_mips32r5/cpu_has_mips64r5 where it's appropriate.
Since XPA/EVA provide too complex alterationss and to have them used with
MIPS32 Release 2 charged kernels (for compatibility with current platform
configs) they are left to be setup as a separate kernel configs.
Co-developed-by: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Signed-off-by: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
2020-05-21 22:07:14 +08:00
|
|
|
if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
|
|
|
|
MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
|
|
|
|
MIPS_CPU_ISA_M32R5 | MIPS_CPU_ISA_M64R5 |
|
|
|
|
MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) {
|
2006-06-21 00:15:20 +08:00
|
|
|
#ifdef CONFIG_MIPS_CPU_SCACHE
|
|
|
|
if (mips_sc_init ()) {
|
|
|
|
scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
|
|
|
|
printk("MIPS secondary cache %ldkB, %s, linesize %d bytes.\n",
|
|
|
|
scache_size >> 10,
|
|
|
|
way_string[c->scache.ways], c->scache.linesz);
|
2020-08-20 02:26:44 +08:00
|
|
|
|
|
|
|
if (current_cpu_type() == CPU_BMIPS5000)
|
|
|
|
c->options |= MIPS_CPU_INCLUSIVE_CACHES;
|
2006-06-21 00:15:20 +08:00
|
|
|
}
|
2020-08-20 02:26:44 +08:00
|
|
|
|
2006-06-21 00:15:20 +08:00
|
|
|
#else
|
|
|
|
if (!(c->scache.flags & MIPS_CACHE_NOT_PRESENT))
|
|
|
|
panic("Dunno how to handle MIPS32 / MIPS64 second level cache");
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
sc_present = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!sc_present)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* compute a couple of other cache variables */
|
|
|
|
c->scache.waysize = scache_size / c->scache.ways;
|
|
|
|
|
|
|
|
c->scache.sets = scache_size / (c->scache.linesz * c->scache.ways);
|
|
|
|
|
|
|
|
printk("Unified secondary cache %ldkB %s, linesize %d bytes.\n",
|
|
|
|
scache_size >> 10, way_string[c->scache.ways], c->scache.linesz);
|
|
|
|
|
2006-07-06 20:04:01 +08:00
|
|
|
c->options |= MIPS_CPU_INCLUSIVE_CACHES;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-05-26 23:44:54 +08:00
|
|
|
void au1x00_fixup_config_od(void)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* c0_config.od (bit 19) was write only (and read as 0)
|
|
|
|
* on the early revisions of Alchemy SOCs. It disables the bus
|
|
|
|
* transaction overlapping and needs to be set to fix various errata.
|
|
|
|
*/
|
|
|
|
switch (read_c0_prid()) {
|
|
|
|
case 0x00030100: /* Au1000 DA */
|
|
|
|
case 0x00030201: /* Au1000 HA */
|
|
|
|
case 0x00030202: /* Au1000 HB */
|
|
|
|
case 0x01030200: /* Au1500 AB */
|
|
|
|
/*
|
|
|
|
* Au1100 errata actually keeps silence about this bit, so we set it
|
|
|
|
* just in case for those revisions that require it to be set according
|
2009-03-26 00:49:28 +08:00
|
|
|
* to the (now gone) cpu table.
|
2006-05-26 23:44:54 +08:00
|
|
|
*/
|
|
|
|
case 0x02030200: /* Au1100 AB */
|
|
|
|
case 0x02030201: /* Au1100 BA */
|
|
|
|
case 0x02030202: /* Au1100 BC */
|
|
|
|
set_c0_config(1 << 19);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-06-13 00:26:02 +08:00
|
|
|
/* CP0 hazard avoidance. */
|
|
|
|
#define NXP_BARRIER() \
|
|
|
|
__asm__ __volatile__( \
|
|
|
|
".set noreorder\n\t" \
|
|
|
|
"nop; nop; nop; nop; nop; nop;\n\t" \
|
|
|
|
".set reorder\n\t")
|
|
|
|
|
|
|
|
static void nxp_pr4450_fixup_config(void)
|
|
|
|
{
|
|
|
|
unsigned long config0;
|
|
|
|
|
|
|
|
config0 = read_c0_config();
|
|
|
|
|
|
|
|
/* clear all three cache coherency fields */
|
|
|
|
config0 &= ~(0x7 | (7 << 25) | (7 << 28));
|
|
|
|
config0 |= (((_page_cachable_default >> _CACHE_SHIFT) << 0) |
|
|
|
|
((_page_cachable_default >> _CACHE_SHIFT) << 25) |
|
|
|
|
((_page_cachable_default >> _CACHE_SHIFT) << 28));
|
|
|
|
write_c0_config(config0);
|
|
|
|
NXP_BARRIER();
|
|
|
|
}
|
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 21:38:59 +08:00
|
|
|
static int cca = -1;
|
2007-09-19 07:58:24 +08:00
|
|
|
|
|
|
|
static int __init cca_setup(char *str)
|
|
|
|
{
|
|
|
|
get_option(&str, &cca);
|
|
|
|
|
2012-06-14 10:26:40 +08:00
|
|
|
return 0;
|
2007-09-19 07:58:24 +08:00
|
|
|
}
|
|
|
|
|
2012-06-14 10:26:40 +08:00
|
|
|
early_param("cca", cca_setup);
|
2007-09-19 07:58:24 +08:00
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 21:38:59 +08:00
|
|
|
static void coherency_setup(void)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2007-09-19 07:58:24 +08:00
|
|
|
if (cca < 0 || cca > 7)
|
|
|
|
cca = read_c0_config() & CONF_CM_CMASK;
|
|
|
|
_page_cachable_default = cca << _CACHE_SHIFT;
|
|
|
|
|
|
|
|
pr_debug("Using cache attribute %d\n", cca);
|
|
|
|
change_c0_config(CONF_CM_CMASK, cca);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* c0_status.cu=0 specifies that updates by the sc instruction use
|
2024-01-04 07:16:03 +08:00
|
|
|
* the coherency mode specified by the TLB; 1 means cacheable
|
2005-04-17 06:20:36 +08:00
|
|
|
* coherent update on write will be used. Not all processors have
|
|
|
|
* this bit and; some wire it to zero, others like Toshiba had the
|
|
|
|
* silly idea of putting something else there ...
|
|
|
|
*/
|
2007-10-12 06:46:15 +08:00
|
|
|
switch (current_cpu_type()) {
|
2005-04-17 06:20:36 +08:00
|
|
|
case CPU_R4000PC:
|
|
|
|
case CPU_R4000SC:
|
|
|
|
case CPU_R4000MC:
|
|
|
|
case CPU_R4400PC:
|
|
|
|
case CPU_R4400SC:
|
|
|
|
case CPU_R4400MC:
|
|
|
|
clear_c0_config(CONF_CU);
|
|
|
|
break;
|
2006-05-26 23:44:54 +08:00
|
|
|
/*
|
2006-08-02 06:42:30 +08:00
|
|
|
* We need to catch the early Alchemy SOCs with
|
2009-03-26 00:49:28 +08:00
|
|
|
* the write-only co_config.od bit and set it back to one on:
|
|
|
|
* Au1000 rev DA, HA, HB; Au1100 AB, BA, BC, Au1500 AB
|
2006-05-26 23:44:54 +08:00
|
|
|
*/
|
2009-03-26 00:49:28 +08:00
|
|
|
case CPU_ALCHEMY:
|
2006-05-26 23:44:54 +08:00
|
|
|
au1x00_fixup_config_od();
|
|
|
|
break;
|
2008-06-13 00:26:02 +08:00
|
|
|
|
|
|
|
case PRID_IMP_PR4450:
|
|
|
|
nxp_pr4450_fixup_config();
|
|
|
|
break;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 21:38:59 +08:00
|
|
|
static void r4k_cache_error_setup(void)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2007-10-12 06:46:05 +08:00
|
|
|
extern char __weak except_vec2_generic;
|
|
|
|
extern char __weak except_vec2_sb1;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2013-09-17 16:25:47 +08:00
|
|
|
switch (current_cpu_type()) {
|
2007-10-12 06:46:05 +08:00
|
|
|
case CPU_SB1:
|
|
|
|
case CPU_SB1A:
|
|
|
|
set_uncached_handler(0x100, &except_vec2_sb1, 0x80);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
set_uncached_handler(0x100, &except_vec2_generic, 0x80);
|
|
|
|
break;
|
|
|
|
}
|
2012-05-15 15:04:49 +08:00
|
|
|
}
|
|
|
|
|
MIPS: Delete __cpuinit/__CPUINIT usage from MIPS code
commit 3747069b25e419f6b51395f48127e9812abc3596 upstream.
The __cpuinit type of throwaway sections might have made sense
some time ago when RAM was more constrained, but now the savings
do not offset the cost and complications. For example, the fix in
commit 5e427ec2d0 ("x86: Fix bit corruption at CPU resume time")
is a good example of the nasty type of bugs that can be created
with improper use of the various __init prefixes.
After a discussion on LKML[1] it was decided that cpuinit should go
the way of devinit and be phased out. Once all the users are gone,
we can then finally remove the macros themselves from linux/init.h.
Note that some harmless section mismatch warnings may result, since
notify_cpu_starting() and cpu_up() are arch independent (kernel/cpu.c)
and are flagged as __cpuinit -- so if we remove the __cpuinit from
the arch specific callers, we will also get section mismatch warnings.
As an intermediate step, we intend to turn the linux/init.h cpuinit
related content into no-ops as early as possible, since that will get
rid of these warnings. In any case, they are temporary and harmless.
Here, we remove all the MIPS __cpuinit from C code and __CPUINIT
from asm files. MIPS is interesting in this respect, because there
are also uasm users hiding behind their own renamed versions of the
__cpuinit macros.
[1] https://lkml.org/lkml/2013/5/20/589
[ralf@linux-mips.org: Folded in Paul's followup fix.]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5494/
Patchwork: https://patchwork.linux-mips.org/patch/5495/
Patchwork: https://patchwork.linux-mips.org/patch/5509/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
2013-06-18 21:38:59 +08:00
|
|
|
void r4k_cache_init(void)
|
2012-05-15 15:04:49 +08:00
|
|
|
{
|
|
|
|
extern void build_clear_page(void);
|
|
|
|
extern void build_copy_page(void);
|
|
|
|
struct cpuinfo_mips *c = ¤t_cpu_data;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
probe_pcache();
|
2016-03-03 09:45:09 +08:00
|
|
|
probe_vcache();
|
2005-04-17 06:20:36 +08:00
|
|
|
setup_scache();
|
|
|
|
|
|
|
|
r4k_blast_dcache_page_setup();
|
|
|
|
r4k_blast_dcache_setup();
|
|
|
|
r4k_blast_icache_page_setup();
|
|
|
|
r4k_blast_icache_setup();
|
|
|
|
r4k_blast_scache_page_setup();
|
|
|
|
r4k_blast_scache_setup();
|
2018-11-15 15:53:53 +08:00
|
|
|
r4k_blast_scache_node_setup();
|
2014-01-15 22:47:28 +08:00
|
|
|
#ifdef CONFIG_EVA
|
|
|
|
r4k_blast_dcache_user_page_setup();
|
|
|
|
r4k_blast_icache_user_page_setup();
|
|
|
|
#endif
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Some MIPS32 and MIPS64 processors have physically indexed caches.
|
|
|
|
* This code supports virtually indexed processors and will be
|
|
|
|
* unnecessarily inefficient on physically indexed processors.
|
|
|
|
*/
|
2015-11-20 09:38:21 +08:00
|
|
|
if (c->dcache.linesz && cpu_has_dc_aliases)
|
2006-06-21 01:06:52 +08:00
|
|
|
shm_align_mask = max_t( unsigned long,
|
|
|
|
c->dcache.sets * c->dcache.linesz - 1,
|
|
|
|
PAGE_SIZE - 1);
|
|
|
|
else
|
|
|
|
shm_align_mask = PAGE_SIZE-1;
|
2008-04-05 22:13:23 +08:00
|
|
|
|
|
|
|
__flush_cache_vmap = r4k__flush_cache_vmap;
|
|
|
|
__flush_cache_vunmap = r4k__flush_cache_vunmap;
|
|
|
|
|
2007-09-28 01:26:43 +08:00
|
|
|
flush_cache_all = cache_noop;
|
2005-04-17 06:20:36 +08:00
|
|
|
__flush_cache_all = r4k___flush_cache_all;
|
|
|
|
flush_cache_mm = r4k_flush_cache_mm;
|
|
|
|
flush_cache_page = r4k_flush_cache_page;
|
|
|
|
flush_cache_range = r4k_flush_cache_range;
|
|
|
|
|
2011-06-17 23:20:28 +08:00
|
|
|
__flush_kernel_vmap_range = r4k_flush_kernel_vmap_range;
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
flush_icache_all = r4k_flush_icache_all;
|
|
|
|
flush_data_cache_page = r4k_flush_data_cache_page;
|
|
|
|
flush_icache_range = r4k_flush_icache_range;
|
2008-08-05 02:53:57 +08:00
|
|
|
local_flush_icache_range = local_r4k_flush_icache_range;
|
2016-09-02 00:30:15 +08:00
|
|
|
__flush_icache_user_range = r4k_flush_icache_user_range;
|
|
|
|
__local_flush_icache_user_range = local_r4k_flush_icache_user_range;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
2018-08-16 21:47:53 +08:00
|
|
|
#ifdef CONFIG_DMA_NONCOHERENT
|
2023-02-22 21:24:25 +08:00
|
|
|
_dma_cache_wback_inv = r4k_dma_cache_wback_inv;
|
|
|
|
_dma_cache_wback = r4k_dma_cache_wback_inv;
|
|
|
|
_dma_cache_inv = r4k_dma_cache_inv;
|
2018-08-16 21:47:53 +08:00
|
|
|
#endif /* CONFIG_DMA_NONCOHERENT */
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
build_clear_page();
|
|
|
|
build_copy_page();
|
2013-03-26 02:47:29 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We want to run CMP kernels on core with and without coherent
|
|
|
|
* caches. Therefore, do not use CONFIG_MIPS_CMP to decide whether
|
|
|
|
* or not to flush caches.
|
|
|
|
*/
|
2005-07-15 23:23:23 +08:00
|
|
|
local_r4k___flush_cache_all(NULL);
|
2013-03-26 02:47:29 +08:00
|
|
|
|
2005-07-15 23:23:23 +08:00
|
|
|
coherency_setup();
|
2012-05-15 15:04:49 +08:00
|
|
|
board_cache_error_setup = r4k_cache_error_setup;
|
2014-10-21 12:28:00 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Per-CPU overrides
|
|
|
|
*/
|
|
|
|
switch (current_cpu_type()) {
|
|
|
|
case CPU_BMIPS4350:
|
|
|
|
case CPU_BMIPS4380:
|
|
|
|
/* No IPI is needed because all CPUs share the same D$ */
|
|
|
|
flush_data_cache_page = r4k_blast_dcache_page;
|
|
|
|
break;
|
|
|
|
case CPU_BMIPS5000:
|
|
|
|
/* We lose our superpowers if L2 is disabled */
|
|
|
|
if (c->scache.flags & MIPS_CACHE_NOT_PRESENT)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* I$ fills from D$ just by emptying the write buffers */
|
|
|
|
flush_cache_page = (void *)b5k_instruction_hazard;
|
|
|
|
flush_cache_range = (void *)b5k_instruction_hazard;
|
|
|
|
flush_data_cache_page = (void *)b5k_instruction_hazard;
|
|
|
|
flush_icache_range = (void *)b5k_instruction_hazard;
|
|
|
|
local_flush_icache_range = (void *)b5k_instruction_hazard;
|
|
|
|
|
|
|
|
|
|
|
|
/* Optimization: an L2 flush implicitly flushes the L1 */
|
|
|
|
current_cpu_data.options |= MIPS_CPU_INCLUSIVE_CACHES;
|
|
|
|
break;
|
2019-10-20 22:43:13 +08:00
|
|
|
case CPU_LOONGSON64:
|
2016-03-03 09:45:10 +08:00
|
|
|
/* Loongson-3 maintains cache coherency by hardware */
|
|
|
|
__flush_cache_all = cache_noop;
|
|
|
|
__flush_cache_vmap = cache_noop;
|
|
|
|
__flush_cache_vunmap = cache_noop;
|
|
|
|
__flush_kernel_vmap_range = (void *)cache_noop;
|
|
|
|
flush_cache_mm = (void *)cache_noop;
|
|
|
|
flush_cache_page = (void *)cache_noop;
|
|
|
|
flush_cache_range = (void *)cache_noop;
|
|
|
|
flush_icache_all = (void *)cache_noop;
|
|
|
|
flush_data_cache_page = (void *)cache_noop;
|
|
|
|
break;
|
2014-10-21 12:28:00 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
2014-03-04 18:23:57 +08:00
|
|
|
|
|
|
|
static int r4k_cache_pm_notifier(struct notifier_block *self, unsigned long cmd,
|
|
|
|
void *v)
|
|
|
|
{
|
|
|
|
switch (cmd) {
|
|
|
|
case CPU_PM_ENTER_FAILED:
|
|
|
|
case CPU_PM_EXIT:
|
|
|
|
coherency_setup();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NOTIFY_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct notifier_block r4k_cache_pm_notifier_block = {
|
|
|
|
.notifier_call = r4k_cache_pm_notifier,
|
|
|
|
};
|
|
|
|
|
2023-12-04 19:56:56 +08:00
|
|
|
static int __init r4k_cache_init_pm(void)
|
2014-03-04 18:23:57 +08:00
|
|
|
{
|
|
|
|
return cpu_pm_register_notifier(&r4k_cache_pm_notifier_block);
|
|
|
|
}
|
|
|
|
arch_initcall(r4k_cache_init_pm);
|