riscv: sifive: Apply errata "cip-1200" patch

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>
This commit is contained in:
Vincent Chen 2021-03-22 22:26:06 +08:00 committed by Palmer Dabbelt
parent 800149a77c
commit bff3ff5254
No known key found for this signature in database
GPG Key ID: 2E1319F35FBB1889
4 changed files with 40 additions and 2 deletions

View File

@ -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

View File

@ -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)

View File

@ -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__
@ -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

View File

@ -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)
@ -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)