Skip to content

Commit b2ff717

Browse files
James Hoganralfbaechle
authored andcommitted
MIPS: c-r4k: Fix flush_icache_range() for EVA
flush_icache_range() flushes icache lines in a protected fashion for kernel addresses, however this isn't correct with EVA where protected cache ops only operate on user addresses, making flush_icache_range() ineffective. Split the implementations of __flush_icache_user_range() from flush_icache_range(), changing the normal flush_icache_range() to use unprotected normal cache ops. Signed-off-by: James Hogan <[email protected]> Cc: Leonid Yegoshin <[email protected]> Cc: [email protected] Patchwork: https://patchwork.linux-mips.org/patch/14156/ Signed-off-by: Ralf Baechle <[email protected]>
1 parent 24d1a6e commit b2ff717

File tree

1 file changed

+35
-8
lines changed

1 file changed

+35
-8
lines changed

arch/mips/mm/c-r4k.c

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -722,19 +722,24 @@ struct flush_icache_range_args {
722722
unsigned long start;
723723
unsigned long end;
724724
unsigned int type;
725+
bool user;
725726
};
726727

727728
static inline void __local_r4k_flush_icache_range(unsigned long start,
728729
unsigned long end,
729-
unsigned int type)
730+
unsigned int type,
731+
bool user)
730732
{
731733
if (!cpu_has_ic_fills_f_dc) {
732734
if (type == R4K_INDEX ||
733735
(type & R4K_INDEX && end - start >= dcache_size)) {
734736
r4k_blast_dcache();
735737
} else {
736738
R4600_HIT_CACHEOP_WAR_IMPL;
737-
protected_blast_dcache_range(start, end);
739+
if (user)
740+
protected_blast_dcache_range(start, end);
741+
else
742+
blast_dcache_range(start, end);
738743
}
739744
}
740745

@@ -748,7 +753,10 @@ static inline void __local_r4k_flush_icache_range(unsigned long start,
748753
break;
749754

750755
default:
751-
protected_blast_icache_range(start, end);
756+
if (user)
757+
protected_blast_icache_range(start, end);
758+
else
759+
blast_icache_range(start, end);
752760
break;
753761
}
754762
}
@@ -757,7 +765,13 @@ static inline void __local_r4k_flush_icache_range(unsigned long start,
757765
static inline void local_r4k_flush_icache_range(unsigned long start,
758766
unsigned long end)
759767
{
760-
__local_r4k_flush_icache_range(start, end, R4K_HIT | R4K_INDEX);
768+
__local_r4k_flush_icache_range(start, end, R4K_HIT | R4K_INDEX, false);
769+
}
770+
771+
static inline void local_r4k_flush_icache_user_range(unsigned long start,
772+
unsigned long end)
773+
{
774+
__local_r4k_flush_icache_range(start, end, R4K_HIT | R4K_INDEX, true);
761775
}
762776

763777
static inline void local_r4k_flush_icache_range_ipi(void *args)
@@ -766,18 +780,21 @@ static inline void local_r4k_flush_icache_range_ipi(void *args)
766780
unsigned long start = fir_args->start;
767781
unsigned long end = fir_args->end;
768782
unsigned int type = fir_args->type;
783+
bool user = fir_args->user;
769784

770-
__local_r4k_flush_icache_range(start, end, type);
785+
__local_r4k_flush_icache_range(start, end, type, user);
771786
}
772787

773-
static void r4k_flush_icache_range(unsigned long start, unsigned long end)
788+
static void __r4k_flush_icache_range(unsigned long start, unsigned long end,
789+
bool user)
774790
{
775791
struct flush_icache_range_args args;
776792
unsigned long size, cache_size;
777793

778794
args.start = start;
779795
args.end = end;
780796
args.type = R4K_HIT | R4K_INDEX;
797+
args.user = user;
781798

782799
/*
783800
* Indexed cache ops require an SMP call.
@@ -803,6 +820,16 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end)
803820
instruction_hazard();
804821
}
805822

823+
static void r4k_flush_icache_range(unsigned long start, unsigned long end)
824+
{
825+
return __r4k_flush_icache_range(start, end, false);
826+
}
827+
828+
static void r4k_flush_icache_user_range(unsigned long start, unsigned long end)
829+
{
830+
return __r4k_flush_icache_range(start, end, true);
831+
}
832+
806833
#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)
807834

808835
static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
@@ -1904,8 +1931,8 @@ void r4k_cache_init(void)
19041931
flush_data_cache_page = r4k_flush_data_cache_page;
19051932
flush_icache_range = r4k_flush_icache_range;
19061933
local_flush_icache_range = local_r4k_flush_icache_range;
1907-
__flush_icache_user_range = r4k_flush_icache_range;
1908-
__local_flush_icache_user_range = local_r4k_flush_icache_range;
1934+
__flush_icache_user_range = r4k_flush_icache_user_range;
1935+
__local_flush_icache_user_range = local_r4k_flush_icache_user_range;
19091936

19101937
#if defined(CONFIG_DMA_NONCOHERENT) || defined(CONFIG_DMA_MAYBE_COHERENT)
19111938
if (coherentio) {

0 commit comments

Comments
 (0)