From: Quan Zhou Add support in KVM SBI FWFT extension to allow VS-mode to request SBI_FWFT_{LANDING_PAD/SHADOW_STACK/PTE_AD_HW_UPDATING}. Signed-off-by: Quan Zhou --- arch/riscv/include/uapi/asm/kvm.h | 3 + arch/riscv/kvm/vcpu_sbi_fwft.c | 129 ++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+) diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h index 7ca087848a43..d93b70d89010 100644 --- a/arch/riscv/include/uapi/asm/kvm.h +++ b/arch/riscv/include/uapi/asm/kvm.h @@ -232,6 +232,9 @@ struct kvm_riscv_sbi_fwft_feature { struct kvm_riscv_sbi_fwft { struct kvm_riscv_sbi_fwft_feature misaligned_deleg; struct kvm_riscv_sbi_fwft_feature pointer_masking; + struct kvm_riscv_sbi_fwft_feature landing_pad; + struct kvm_riscv_sbi_fwft_feature shadow_stack; + struct kvm_riscv_sbi_fwft_feature pte_ad_hw_updating; }; /* Possible states for kvm_riscv_timer */ diff --git a/arch/riscv/kvm/vcpu_sbi_fwft.c b/arch/riscv/kvm/vcpu_sbi_fwft.c index 62cc9c3d5759..0dc0e70fc83b 100644 --- a/arch/riscv/kvm/vcpu_sbi_fwft.c +++ b/arch/riscv/kvm/vcpu_sbi_fwft.c @@ -213,6 +213,108 @@ static long kvm_sbi_fwft_get_pointer_masking_pmlen(struct kvm_vcpu *vcpu, return SBI_SUCCESS; } +static long kvm_sbi_fwft_set_henvcfg_flag(struct kvm_vcpu *vcpu, + struct kvm_sbi_fwft_config *conf, + bool one_reg_access, unsigned long value, + unsigned long flag) +{ + struct kvm_vcpu_config *cfg = &vcpu->arch.cfg; + + if (value == 1) + cfg->henvcfg |= flag; + else if (value == 0) + cfg->henvcfg &= ~flag; + else + return SBI_ERR_INVALID_PARAM; + + if (!one_reg_access) + csr_write(CSR_HENVCFG, cfg->henvcfg); + + return SBI_SUCCESS; +} + +static bool kvm_sbi_fwft_pointer_landing_pad_supported(struct kvm_vcpu *vcpu) +{ + return riscv_isa_extension_available(vcpu->arch.isa, ZICFILP); +} + +static void kvm_sbi_fwft_reset_landing_pad(struct kvm_vcpu *vcpu) +{ + vcpu->arch.cfg.henvcfg &= ~ENVCFG_LPE; +} + +static long kvm_sbi_fwft_set_landing_pad(struct kvm_vcpu *vcpu, + struct kvm_sbi_fwft_config *conf, + bool one_reg_access, unsigned long value) +{ + return kvm_sbi_fwft_set_henvcfg_flag(vcpu, conf, one_reg_access, value, ENVCFG_LPE); +} + +static long kvm_sbi_fwft_get_landing_pad(struct kvm_vcpu *vcpu, + struct kvm_sbi_fwft_config *conf, + bool one_reg_access, unsigned long *value) +{ + struct kvm_vcpu_config *cfg = &vcpu->arch.cfg; + + *value = (cfg->henvcfg & ENVCFG_LPE) == ENVCFG_LPE; + return SBI_SUCCESS; +} + +static bool kvm_sbi_fwft_pointer_shadow_stack_supported(struct kvm_vcpu *vcpu) +{ + return riscv_isa_extension_available(vcpu->arch.isa, ZICFISS); +} + +static void kvm_sbi_fwft_reset_shadow_stack(struct kvm_vcpu *vcpu) +{ + vcpu->arch.cfg.henvcfg &= ~ENVCFG_SSE; +} + +static long kvm_sbi_fwft_set_shadow_stack(struct kvm_vcpu *vcpu, + struct kvm_sbi_fwft_config *conf, + bool one_reg_access, unsigned long value) +{ + return kvm_sbi_fwft_set_henvcfg_flag(vcpu, conf, one_reg_access, value, ENVCFG_SSE); +} + +static long kvm_sbi_fwft_get_shadow_stack(struct kvm_vcpu *vcpu, + struct kvm_sbi_fwft_config *conf, + bool one_reg_access, unsigned long *value) +{ + struct kvm_vcpu_config *cfg = &vcpu->arch.cfg; + + *value = (cfg->henvcfg & ENVCFG_SSE) == ENVCFG_SSE; + return SBI_SUCCESS; +} + +static bool kvm_sbi_fwft_pointer_pte_ad_hw_updating_supported(struct kvm_vcpu *vcpu) +{ + return riscv_isa_extension_available(vcpu->arch.isa, SVADU) && + !riscv_isa_extension_available(vcpu->arch.isa, SVADE); +} + +static void kvm_sbi_fwft_reset_pte_ad_hw_updating(struct kvm_vcpu *vcpu) +{ + vcpu->arch.cfg.henvcfg &= ~ENVCFG_ADUE; +} + +static long kvm_sbi_fwft_set_pte_ad_hw_updating(struct kvm_vcpu *vcpu, + struct kvm_sbi_fwft_config *conf, + bool one_reg_access, unsigned long value) +{ + return kvm_sbi_fwft_set_henvcfg_flag(vcpu, conf, one_reg_access, value, ENVCFG_ADUE); +} + +static long kvm_sbi_fwft_get_pte_ad_hw_updating(struct kvm_vcpu *vcpu, + struct kvm_sbi_fwft_config *conf, + bool one_reg_access, unsigned long *value) +{ + struct kvm_vcpu_config *cfg = &vcpu->arch.cfg; + + *value = (cfg->henvcfg & ENVCFG_ADUE) == ENVCFG_ADUE; + return SBI_SUCCESS; +} + #endif static const struct kvm_sbi_fwft_feature features[] = { @@ -236,6 +338,33 @@ static const struct kvm_sbi_fwft_feature features[] = { .get = kvm_sbi_fwft_get_pointer_masking_pmlen, }, #endif + { + .id = SBI_FWFT_LANDING_PAD, + .first_reg_num = offsetof(struct kvm_riscv_sbi_fwft, landing_pad.enable) / + sizeof(unsigned long), + .supported = kvm_sbi_fwft_landing_pad_supported, + .reset = kvm_sbi_fwft_reset_landing_pad, + .set = kvm_sbi_fwft_set_landing_pad, + .get = kvm_sbi_fwft_get_landing_pad, + }, + { + .id = SBI_FWFT_SHADOW_STACK, + .first_reg_num = offsetof(struct kvm_riscv_sbi_fwft, shadow_stack.enable) / + sizeof(unsigned long), + .supported = kvm_sbi_fwft_shadow_stack_supported, + .reset = kvm_sbi_fwft_reset_shadow_stack, + .set = kvm_sbi_fwft_set_shadow_stack, + .get = kvm_sbi_fwft_get_shadow_stack, + }, + { + .id = SBI_FWFT_PTE_AD_HW_UPDATING, + .first_reg_num = offsetof(struct kvm_riscv_sbi_fwft, pte_ad_hw_updating.enable) / + sizeof(unsigned long), + .supported = kvm_sbi_fwft_pte_ad_hw_updating_supported, + .reset = kvm_sbi_fwft_reset_pte_ad_hw_updating, + .set = kvm_sbi_fwft_set_pte_ad_hw_updating, + .get = kvm_sbi_fwft_get_pte_ad_hw_updating, + }, }; static const struct kvm_sbi_fwft_feature *kvm_sbi_fwft_regnum_to_feature(unsigned long reg_num) -- 2.34.1