[PATCH v2 3/6] RISC-V: KVM: Make SBI uapi consistent with ISA uapi

Anup Patel anup at brainfault.org
Wed Dec 13 09:35:32 PST 2023


On Wed, Dec 13, 2023 at 10:39 PM Andrew Jones <ajones at ventanamicro.com> wrote:
>
> When an SBI extension cannot be enabled, that's a distinct state vs.
> enabled and disabled. Modify enum kvm_riscv_sbi_ext_status to
> accommodate it, which allows KVM userspace to tell the difference
> in state too, as the SBI extension register will disappear when it
> cannot be enabled, i.e. accesses to it return ENOENT. get-reg-list is
> updated as well to only add SBI extension registers to the list which
> may be enabled. Returning ENOENT for SBI extension registers which
> cannot be enabled makes them consistent with ISA extension registers.
> Any SBI extensions which were enabled by default are still enabled by
> default, if they can be enabled at all.
>
> Signed-off-by: Andrew Jones <ajones at ventanamicro.com>

Looks good to me.

Reviewed-by: Anup Patel <anup at brainfault.org>

Regards,
Anup

> ---
>  arch/riscv/include/asm/kvm_vcpu_sbi.h | 10 ++--
>  arch/riscv/kvm/vcpu_onereg.c          | 23 +++++---
>  arch/riscv/kvm/vcpu_sbi.c             | 75 +++++++++++++++------------
>  arch/riscv/kvm/vcpu_sbi_replace.c     |  2 +-
>  4 files changed, 65 insertions(+), 45 deletions(-)
>
> diff --git a/arch/riscv/include/asm/kvm_vcpu_sbi.h b/arch/riscv/include/asm/kvm_vcpu_sbi.h
> index 6a453f7f8b56..bffda0ac59b6 100644
> --- a/arch/riscv/include/asm/kvm_vcpu_sbi.h
> +++ b/arch/riscv/include/asm/kvm_vcpu_sbi.h
> @@ -15,9 +15,10 @@
>  #define KVM_SBI_VERSION_MINOR 0
>
>  enum kvm_riscv_sbi_ext_status {
> -       KVM_RISCV_SBI_EXT_UNINITIALIZED,
> -       KVM_RISCV_SBI_EXT_AVAILABLE,
> -       KVM_RISCV_SBI_EXT_UNAVAILABLE,
> +       KVM_RISCV_SBI_EXT_STATUS_UNINITIALIZED,
> +       KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE,
> +       KVM_RISCV_SBI_EXT_STATUS_ENABLED,
> +       KVM_RISCV_SBI_EXT_STATUS_DISABLED,
>  };
>
>  struct kvm_vcpu_sbi_context {
> @@ -36,7 +37,7 @@ struct kvm_vcpu_sbi_extension {
>         unsigned long extid_start;
>         unsigned long extid_end;
>
> -       bool default_unavail;
> +       bool default_disabled;
>
>         /**
>          * SBI extension handler. It can be defined for a given extension or group of
> @@ -61,6 +62,7 @@ int kvm_riscv_vcpu_get_reg_sbi_ext(struct kvm_vcpu *vcpu,
>                                    const struct kvm_one_reg *reg);
>  const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(
>                                 struct kvm_vcpu *vcpu, unsigned long extid);
> +bool riscv_vcpu_supports_sbi_ext(struct kvm_vcpu *vcpu, int idx);
>  int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run);
>  void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu);
>
> diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
> index f9bfa8a5db21..48262be73aa0 100644
> --- a/arch/riscv/kvm/vcpu_onereg.c
> +++ b/arch/riscv/kvm/vcpu_onereg.c
> @@ -931,27 +931,34 @@ static inline unsigned long num_isa_ext_regs(const struct kvm_vcpu *vcpu)
>         return copy_isa_ext_reg_indices(vcpu, NULL);;
>  }
>
> -static inline unsigned long num_sbi_ext_regs(void)
> +static int copy_sbi_ext_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
>  {
> -       return KVM_RISCV_SBI_EXT_MAX;
> -}
> +       unsigned int n = 0;
>
> -static int copy_sbi_ext_reg_indices(u64 __user *uindices)
> -{
>         for (int i = 0; i < KVM_RISCV_SBI_EXT_MAX; i++) {
>                 u64 size = IS_ENABLED(CONFIG_32BIT) ?
>                            KVM_REG_SIZE_U32 : KVM_REG_SIZE_U64;
>                 u64 reg = KVM_REG_RISCV | size | KVM_REG_RISCV_SBI_EXT |
>                           KVM_REG_RISCV_SBI_SINGLE | i;
>
> +               if (!riscv_vcpu_supports_sbi_ext(vcpu, i))
> +                       continue;
> +
>                 if (uindices) {
>                         if (put_user(reg, uindices))
>                                 return -EFAULT;
>                         uindices++;
>                 }
> +
> +               n++;
>         }
>
> -       return num_sbi_ext_regs();
> +       return n;
> +}
> +
> +static unsigned long num_sbi_ext_regs(struct kvm_vcpu *vcpu)
> +{
> +       return copy_sbi_ext_reg_indices(vcpu, NULL);
>  }
>
>  /*
> @@ -970,7 +977,7 @@ unsigned long kvm_riscv_vcpu_num_regs(struct kvm_vcpu *vcpu)
>         res += num_fp_f_regs(vcpu);
>         res += num_fp_d_regs(vcpu);
>         res += num_isa_ext_regs(vcpu);
> -       res += num_sbi_ext_regs();
> +       res += num_sbi_ext_regs(vcpu);
>
>         return res;
>  }
> @@ -1018,7 +1025,7 @@ int kvm_riscv_vcpu_copy_reg_indices(struct kvm_vcpu *vcpu,
>                 return ret;
>         uindices += ret;
>
> -       ret = copy_sbi_ext_reg_indices(uindices);
> +       ret = copy_sbi_ext_reg_indices(vcpu, uindices);
>         if (ret < 0)
>                 return ret;
>
> diff --git a/arch/riscv/kvm/vcpu_sbi.c b/arch/riscv/kvm/vcpu_sbi.c
> index a04ff98085d9..dcdff4458190 100644
> --- a/arch/riscv/kvm/vcpu_sbi.c
> +++ b/arch/riscv/kvm/vcpu_sbi.c
> @@ -80,6 +80,34 @@ static const struct kvm_riscv_sbi_extension_entry sbi_ext[] = {
>         },
>  };
>
> +static const struct kvm_riscv_sbi_extension_entry *
> +riscv_vcpu_get_sbi_ext(struct kvm_vcpu *vcpu, unsigned long idx)
> +{
> +       const struct kvm_riscv_sbi_extension_entry *sext = NULL;
> +
> +       if (idx >= KVM_RISCV_SBI_EXT_MAX)
> +               return NULL;
> +
> +       for (int i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
> +               if (sbi_ext[i].ext_idx == idx) {
> +                       sext = &sbi_ext[i];
> +                       break;
> +               }
> +       }
> +
> +       return sext;
> +}
> +
> +bool riscv_vcpu_supports_sbi_ext(struct kvm_vcpu *vcpu, int idx)
> +{
> +       struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
> +       const struct kvm_riscv_sbi_extension_entry *sext;
> +
> +       sext = riscv_vcpu_get_sbi_ext(vcpu, idx);
> +
> +       return sext && scontext->ext_status[sext->ext_idx] != KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE;
> +}
> +
>  void kvm_riscv_vcpu_sbi_forward(struct kvm_vcpu *vcpu, struct kvm_run *run)
>  {
>         struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
> @@ -140,28 +168,19 @@ static int riscv_vcpu_set_sbi_ext_single(struct kvm_vcpu *vcpu,
>                                          unsigned long reg_num,
>                                          unsigned long reg_val)
>  {
> -       unsigned long i;
> -       const struct kvm_riscv_sbi_extension_entry *sext = NULL;
>         struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
> -
> -       if (reg_num >= KVM_RISCV_SBI_EXT_MAX)
> -               return -ENOENT;
> +       const struct kvm_riscv_sbi_extension_entry *sext;
>
>         if (reg_val != 1 && reg_val != 0)
>                 return -EINVAL;
>
> -       for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
> -               if (sbi_ext[i].ext_idx == reg_num) {
> -                       sext = &sbi_ext[i];
> -                       break;
> -               }
> -       }
> -       if (!sext)
> +       sext = riscv_vcpu_get_sbi_ext(vcpu, reg_num);
> +       if (!sext || scontext->ext_status[sext->ext_idx] == KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE)
>                 return -ENOENT;
>
>         scontext->ext_status[sext->ext_idx] = (reg_val) ?
> -                       KVM_RISCV_SBI_EXT_AVAILABLE :
> -                       KVM_RISCV_SBI_EXT_UNAVAILABLE;
> +                       KVM_RISCV_SBI_EXT_STATUS_ENABLED :
> +                       KVM_RISCV_SBI_EXT_STATUS_DISABLED;
>
>         return 0;
>  }
> @@ -170,24 +189,16 @@ static int riscv_vcpu_get_sbi_ext_single(struct kvm_vcpu *vcpu,
>                                          unsigned long reg_num,
>                                          unsigned long *reg_val)
>  {
> -       unsigned long i;
> -       const struct kvm_riscv_sbi_extension_entry *sext = NULL;
>         struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
> +       const struct kvm_riscv_sbi_extension_entry *sext;
>
> -       if (reg_num >= KVM_RISCV_SBI_EXT_MAX)
> -               return -ENOENT;
> -
> -       for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
> -               if (sbi_ext[i].ext_idx == reg_num) {
> -                       sext = &sbi_ext[i];
> -                       break;
> -               }
> -       }
> -       if (!sext)
> +       sext = riscv_vcpu_get_sbi_ext(vcpu, reg_num);
> +       if (!sext || scontext->ext_status[sext->ext_idx] == KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE)
>                 return -ENOENT;
>
>         *reg_val = scontext->ext_status[sext->ext_idx] ==
> -                               KVM_RISCV_SBI_EXT_AVAILABLE;
> +                               KVM_RISCV_SBI_EXT_STATUS_ENABLED;
> +
>         return 0;
>  }
>
> @@ -325,7 +336,7 @@ const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(
>                 if (ext->extid_start <= extid && ext->extid_end >= extid) {
>                         if (entry->ext_idx >= KVM_RISCV_SBI_EXT_MAX ||
>                             scontext->ext_status[entry->ext_idx] ==
> -                                               KVM_RISCV_SBI_EXT_AVAILABLE)
> +                                               KVM_RISCV_SBI_EXT_STATUS_ENABLED)
>                                 return ext;
>
>                         return NULL;
> @@ -413,12 +424,12 @@ void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu)
>
>                 if (ext->probe && !ext->probe(vcpu)) {
>                         scontext->ext_status[entry->ext_idx] =
> -                               KVM_RISCV_SBI_EXT_UNAVAILABLE;
> +                               KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE;
>                         continue;
>                 }
>
> -               scontext->ext_status[entry->ext_idx] = ext->default_unavail ?
> -                                       KVM_RISCV_SBI_EXT_UNAVAILABLE :
> -                                       KVM_RISCV_SBI_EXT_AVAILABLE;
> +               scontext->ext_status[entry->ext_idx] = ext->default_disabled ?
> +                                       KVM_RISCV_SBI_EXT_STATUS_DISABLED :
> +                                       KVM_RISCV_SBI_EXT_STATUS_ENABLED;
>         }
>  }
> diff --git a/arch/riscv/kvm/vcpu_sbi_replace.c b/arch/riscv/kvm/vcpu_sbi_replace.c
> index 23b57c931b15..9c2ab3dfa93a 100644
> --- a/arch/riscv/kvm/vcpu_sbi_replace.c
> +++ b/arch/riscv/kvm/vcpu_sbi_replace.c
> @@ -204,6 +204,6 @@ static int kvm_sbi_ext_dbcn_handler(struct kvm_vcpu *vcpu,
>  const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_dbcn = {
>         .extid_start = SBI_EXT_DBCN,
>         .extid_end = SBI_EXT_DBCN,
> -       .default_unavail = true,
> +       .default_disabled = true,
>         .handler = kvm_sbi_ext_dbcn_handler,
>  };
> --
> 2.43.0
>



More information about the linux-riscv mailing list