Skip to content

Commit

Permalink
riscv: sifive: Apply errata "cip-1200" patch
Browse files Browse the repository at this point in the history
For certain SiFive CPUs, "sfence.vma addr" cannot exactly flush addr
from TLB in the particular cases. The details could be found here:
https://sifive.cdn.prismic.io/sifive/167a1a56-03f4-4615-a79e-b2a86153148f_FU740_errata_20210205.pdf
In order to ensure the functionality, this patch uses the Alternative
scheme to replace all "sfence.vma addr" with "sfence.vma" at runtime.

Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
  • Loading branch information
Vincent Chen authored and Palmer Dabbelt committed Apr 26, 2021
1 parent 800149a commit bff3ff5
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 2 deletions.
11 changes: 11 additions & 0 deletions arch/riscv/Kconfig.erratas
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,15 @@ config ERRATA_SIFIVE_CIP_453

If you don't know what to do here, say "Y".

config ERRATA_SIFIVE_CIP_1200
bool "Apply SiFive errata CIP-1200"
depends on ERRATA_SIFIVE
default y
help
This will apply the SiFive CIP-1200 errata to repalce all
"sfence.vma addr" with "sfence.vma" to ensure that the addr
has been flushed from TLB.

If you don't know what to do here, say "Y".

endmenu
18 changes: 18 additions & 0 deletions arch/riscv/errata/sifive/errata.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,29 @@ static bool errata_cip_453_check_func(unsigned long arch_id, unsigned long impi
return true;
}

static bool errata_cip_1200_check_func(unsigned long arch_id, unsigned long impid)
{
/*
* Affected cores:
* Architecture ID: 0x8000000000000007 or 0x1
* Implement ID: mimpid[23:0] <= 0x200630 and mimpid != 0x01200626
*/
if (arch_id != 0x8000000000000007 && arch_id != 0x1)
return false;
if ((impid & 0xffffff) > 0x200630 || impid == 0x1200626)
return false;
return true;
}

static struct errata_info_t errata_list[ERRATA_SIFIVE_NUMBER] = {
{
.name = "cip-453",
.check_func = errata_cip_453_check_func
},
{
.name = "cip-1200",
.check_func = errata_cip_1200_check_func
},
};

static u32 __init sifive_errata_probe(unsigned long archid, unsigned long impid)
Expand Down
10 changes: 9 additions & 1 deletion arch/riscv/include/asm/errata_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

#ifdef CONFIG_ERRATA_SIFIVE
#define ERRATA_SIFIVE_CIP_453 0
#define ERRATA_SIFIVE_NUMBER 1
#define ERRATA_SIFIVE_CIP_1200 1
#define ERRATA_SIFIVE_NUMBER 2
#endif

#ifdef __ASSEMBLY__
Expand All @@ -26,6 +27,13 @@ ALTERNATIVE(__stringify(RISCV_PTR do_page_fault), \
__stringify(RISCV_PTR sifive_cip_453_page_fault_trp), \
SIFIVE_VENDOR_ID, ERRATA_SIFIVE_CIP_453, \
CONFIG_ERRATA_SIFIVE_CIP_453)
#else /* !__ASSEMBLY__ */

#define ALT_FLUSH_TLB_PAGE(x) \
asm(ALTERNATIVE("sfence.vma %0", "sfence.vma", SIFIVE_VENDOR_ID, \
ERRATA_SIFIVE_CIP_1200, CONFIG_ERRATA_SIFIVE_CIP_1200) \
: : "r" (addr) : "memory")

#endif /* __ASSEMBLY__ */

#endif
3 changes: 2 additions & 1 deletion arch/riscv/include/asm/tlbflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include <linux/mm_types.h>
#include <asm/smp.h>
#include <asm/errata_list.h>

#ifdef CONFIG_MMU
static inline void local_flush_tlb_all(void)
Expand All @@ -19,7 +20,7 @@ static inline void local_flush_tlb_all(void)
/* Flush one page from local TLB */
static inline void local_flush_tlb_page(unsigned long addr)
{
__asm__ __volatile__ ("sfence.vma %0" : : "r" (addr) : "memory");
ALT_FLUSH_TLB_PAGE(__asm__ __volatile__ ("sfence.vma %0" : : "r" (addr) : "memory"));
}
#else /* CONFIG_MMU */
#define local_flush_tlb_all() do { } while (0)
Expand Down

0 comments on commit bff3ff5

Please sign in to comment.