Commit bff3ff52 authored by Vincent Chen's avatar Vincent Chen Committed by Palmer Dabbelt

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: default avatarVincent Chen <vincent.chen@sifive.com>
Signed-off-by: default avatarPalmer Dabbelt <palmerdabbelt@google.com>
parent 800149a7
...@@ -30,4 +30,15 @@ config ERRATA_SIFIVE_CIP_453 ...@@ -30,4 +30,15 @@ config ERRATA_SIFIVE_CIP_453
If you don't know what to do here, say "Y". 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 endmenu
...@@ -29,11 +29,29 @@ static bool errata_cip_453_check_func(unsigned long arch_id, unsigned long impi ...@@ -29,11 +29,29 @@ static bool errata_cip_453_check_func(unsigned long arch_id, unsigned long impi
return true; 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] = { static struct errata_info_t errata_list[ERRATA_SIFIVE_NUMBER] = {
{ {
.name = "cip-453", .name = "cip-453",
.check_func = errata_cip_453_check_func .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) static u32 __init sifive_errata_probe(unsigned long archid, unsigned long impid)
......
...@@ -10,7 +10,8 @@ ...@@ -10,7 +10,8 @@
#ifdef CONFIG_ERRATA_SIFIVE #ifdef CONFIG_ERRATA_SIFIVE
#define ERRATA_SIFIVE_CIP_453 0 #define ERRATA_SIFIVE_CIP_453 0
#define ERRATA_SIFIVE_NUMBER 1 #define ERRATA_SIFIVE_CIP_1200 1
#define ERRATA_SIFIVE_NUMBER 2
#endif #endif
#ifdef __ASSEMBLY__ #ifdef __ASSEMBLY__
...@@ -26,6 +27,13 @@ ALTERNATIVE(__stringify(RISCV_PTR do_page_fault), \ ...@@ -26,6 +27,13 @@ ALTERNATIVE(__stringify(RISCV_PTR do_page_fault), \
__stringify(RISCV_PTR sifive_cip_453_page_fault_trp), \ __stringify(RISCV_PTR sifive_cip_453_page_fault_trp), \
SIFIVE_VENDOR_ID, ERRATA_SIFIVE_CIP_453, \ SIFIVE_VENDOR_ID, ERRATA_SIFIVE_CIP_453, \
CONFIG_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 /* __ASSEMBLY__ */
#endif #endif
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/mm_types.h> #include <linux/mm_types.h>
#include <asm/smp.h> #include <asm/smp.h>
#include <asm/errata_list.h>
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
static inline void local_flush_tlb_all(void) static inline void local_flush_tlb_all(void)
...@@ -19,7 +20,7 @@ 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 */ /* Flush one page from local TLB */
static inline void local_flush_tlb_page(unsigned long addr) 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 */ #else /* CONFIG_MMU */
#define local_flush_tlb_all() do { } while (0) #define local_flush_tlb_all() do { } while (0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment