Skip to content

Commit d6dcdab

Browse files
SiFiveHollandpalmer-dabbelt
authored andcommitted
riscv: Avoid TLB flush loops when affected by SiFive CIP-1200
Implementations affected by SiFive errata CIP-1200 have a bug which forces the kernel to always use the global variant of the sfence.vma instruction. When affected by this errata, do not attempt to flush a range of addresses; each iteration of the loop would actually flush the whole TLB instead. Instead, minimize the overall number of sfence.vma instructions. Signed-off-by: Samuel Holland <[email protected]> Reviewed-by: Yunhui Cui <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 20e03d7 commit d6dcdab

File tree

3 files changed

+8
-1
lines changed

3 files changed

+8
-1
lines changed

arch/riscv/errata/sifive/errata.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ static bool errata_cip_1200_check_func(unsigned long arch_id, unsigned long imp
4242
return false;
4343
if ((impid & 0xffffff) > 0x200630 || impid == 0x1200626)
4444
return false;
45+
46+
#ifdef CONFIG_MMU
47+
tlb_flush_all_threshold = 0;
48+
#endif
49+
4550
return true;
4651
}
4752

arch/riscv/include/asm/tlbflush.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ void arch_tlbbatch_add_pending(struct arch_tlbflush_unmap_batch *batch,
6666
unsigned long uaddr);
6767
void arch_flush_tlb_batched_pending(struct mm_struct *mm);
6868
void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch);
69+
70+
extern unsigned long tlb_flush_all_threshold;
6971
#else /* CONFIG_MMU */
7072
#define local_flush_tlb_all() do { } while (0)
7173
#endif /* CONFIG_MMU */

arch/riscv/mm/tlbflush.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* Flush entire TLB if number of entries to be flushed is greater
1212
* than the threshold below.
1313
*/
14-
static unsigned long tlb_flush_all_threshold __read_mostly = 64;
14+
unsigned long tlb_flush_all_threshold __read_mostly = 64;
1515

1616
static void local_flush_tlb_range_threshold_asid(unsigned long start,
1717
unsigned long size,

0 commit comments

Comments
 (0)