diff options
author | Ji Sheng Teoh <jisheng.teoh@starfivetech.com> | 2024-01-11 04:40:00 +0300 |
---|---|---|
committer | Ji Sheng Teoh <jisheng.teoh@starfivetech.com> | 2024-01-16 12:57:38 +0300 |
commit | 53df07e6e2e9d83dc819094bd38a8bf119bcd7e3 (patch) | |
tree | b0155199e8c2a0187f982d64eb76f42e194c1c3b | |
parent | ef864ca40987bd93d83294d67826ea6723ce5046 (diff) | |
download | linux-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.c | 38 | ||||
-rw-r--r-- | arch/riscv/include/asm/errata_list.h | 2 | ||||
-rw-r--r-- | arch/riscv/kvm/vcpu.c | 15 |
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, |