summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJi Sheng Teoh <jisheng.teoh@starfivetech.com>2024-01-11 04:40:00 +0300
committerJi Sheng Teoh <jisheng.teoh@starfivetech.com>2024-01-16 12:57:38 +0300
commit53df07e6e2e9d83dc819094bd38a8bf119bcd7e3 (patch)
treeb0155199e8c2a0187f982d64eb76f42e194c1c3b
parentef864ca40987bd93d83294d67826ea6723ce5046 (diff)
downloadlinux-53df07e6e2e9d83dc819094bd38a8bf119bcd7e3.tar.xz
arch: riscv: errata: bypass envcfg CSR
CPU core that supports H-extension v0.6.1 does not have henvcfg and senvcfg CSR register support, accessing it will cause kernel to throw illegal access warning. This patch introduce errata for platform that does not support accessing the CSR by bypassing it through the usage of static key. Signed-off-by: Ji Sheng Teoh <jisheng.teoh@starfivetech.com> Signed-off-by: Tan En De <ende.tan@starfivetech.com>
-rw-r--r--arch/riscv/errata/starfive/errata.c38
-rw-r--r--arch/riscv/include/asm/errata_list.h2
-rw-r--r--arch/riscv/kvm/vcpu.c15
3 files changed, 43 insertions, 12 deletions
diff --git a/arch/riscv/errata/starfive/errata.c b/arch/riscv/errata/starfive/errata.c
index b7e757207d54..c774ec16d87d 100644
--- a/arch/riscv/errata/starfive/errata.c
+++ b/arch/riscv/errata/starfive/errata.c
@@ -23,26 +23,45 @@
#define STARFIVE_DUBHE80_MARCHID 0x80000000DB000080UL
#define STARFIVE_DUBHE80_MIMPID 0x0000000020230831UL
-static bool errata_probe_cmo(unsigned int stage, unsigned long arch_id,
- unsigned long impid)
+#define STARFIVE_DUBHE70_MARCHID 0x80000000DB000070UL
+#define STARFIVE_DUBHE70_MIMPID 0x0000000020240131UL
+
+DEFINE_STATIC_KEY_FALSE(bypass_envcfg_csr_key);
+
+static void errata_probe_cmo(unsigned int stage, unsigned long arch_id,
+ unsigned long impid)
{
if (!IS_ENABLED(CONFIG_ERRATA_STARFIVE_CMO))
- return false;
+ return;
if (arch_id == STARFIVE_DUBHE90_MARCHID) {
if (impid > STARFIVE_DUBHE90_MIMPID)
- return false;
+ return;
}
if (arch_id == STARFIVE_DUBHE80_MARCHID) {
if (impid > STARFIVE_DUBHE80_MIMPID)
- return false;
+ return;
}
riscv_cbom_block_size = L1_CACHE_BYTES;
riscv_noncoherent_supported();
+}
+
+static void errata_bypass_envcfg_csr(unsigned int stage, unsigned long arch_id,
+ unsigned long impid)
+{
+ if (arch_id == STARFIVE_DUBHE90_MARCHID) {
+ if (impid > STARFIVE_DUBHE90_MIMPID)
+ return;
+ }
- return true;
+ if (arch_id == STARFIVE_DUBHE80_MARCHID) {
+ if (impid > STARFIVE_DUBHE80_MIMPID)
+ return;
+ }
+
+ static_branch_enable(&bypass_envcfg_csr_key);
}
void starfive_errata_patch_func(struct alt_entry *begin,
@@ -51,6 +70,11 @@ void starfive_errata_patch_func(struct alt_entry *begin,
unsigned long impid,
unsigned int stage)
{
- if (stage == RISCV_ALTERNATIVES_BOOT)
+ if (archid == STARFIVE_DUBHE70_MARCHID)
+ return;
+
+ if (stage == RISCV_ALTERNATIVES_BOOT) {
errata_probe_cmo(stage, archid, impid);
+ errata_bypass_envcfg_csr(stage, archid, impid);
+ }
}
diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
index 6267b6407b6e..6bbb4bf643c0 100644
--- a/arch/riscv/include/asm/errata_list.h
+++ b/arch/riscv/include/asm/errata_list.h
@@ -164,6 +164,8 @@ asm volatile(ALTERNATIVE( \
: "=r" (__ovl) : \
: "memory")
+DECLARE_STATIC_KEY_FALSE(bypass_envcfg_csr_key);
+
#endif /* __ASSEMBLY__ */
#endif
diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
index c061a1c5fe98..8fe674a874dd 100644
--- a/arch/riscv/kvm/vcpu.c
+++ b/arch/riscv/kvm/vcpu.c
@@ -19,6 +19,7 @@
#include <linux/kvm_host.h>
#include <asm/csr.h>
#include <asm/cacheflush.h>
+#include <asm/errata_list.h>
#include <asm/kvm_vcpu_vector.h>
const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
@@ -513,9 +514,11 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
csr_write(CSR_VSTVAL, csr->vstval);
csr_write(CSR_HVIP, csr->hvip);
csr_write(CSR_VSATP, csr->vsatp);
- csr_write(CSR_HENVCFG, cfg->henvcfg);
- if (IS_ENABLED(CONFIG_32BIT))
- csr_write(CSR_HENVCFGH, cfg->henvcfg >> 32);
+ if (!static_branch_unlikely(&bypass_envcfg_csr_key)) {
+ csr_write(CSR_HENVCFG, cfg->henvcfg);
+ if (IS_ENABLED(CONFIG_32BIT))
+ csr_write(CSR_HENVCFGH, cfg->henvcfg >> 32);
+ }
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN)) {
csr_write(CSR_HSTATEEN0, cfg->hstateen0);
if (IS_ENABLED(CONFIG_32BIT))
@@ -625,7 +628,8 @@ static __always_inline void kvm_riscv_vcpu_swap_in_guest_state(struct kvm_vcpu *
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
- vcpu->arch.host_senvcfg = csr_swap(CSR_SENVCFG, csr->senvcfg);
+ if (!static_branch_unlikely(&bypass_envcfg_csr_key))
+ vcpu->arch.host_senvcfg = csr_swap(CSR_SENVCFG, csr->senvcfg);
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN) &&
(cfg->hstateen0 & SMSTATEEN0_SSTATEEN0))
vcpu->arch.host_sstateen0 = csr_swap(CSR_SSTATEEN0,
@@ -638,7 +642,8 @@ static __always_inline void kvm_riscv_vcpu_swap_in_host_state(struct kvm_vcpu *v
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
- csr->senvcfg = csr_swap(CSR_SENVCFG, vcpu->arch.host_senvcfg);
+ if (!static_branch_unlikely(&bypass_envcfg_csr_key))
+ csr->senvcfg = csr_swap(CSR_SENVCFG, vcpu->arch.host_senvcfg);
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN) &&
(cfg->hstateen0 & SMSTATEEN0_SSTATEEN0))
smcsr->sstateen0 = csr_swap(CSR_SSTATEEN0,