Re: [PATCH v4 4/5] RISC-V: KVM: Add v0.1 replacement SBI extensions defined in v02

From: Anup Patel
Date: Sat Nov 06 2021 - 00:47:09 EST


On Sat, Nov 6, 2021 at 5:29 AM Atish Patra <atish.patra@xxxxxxx> wrote:
>
> The SBI v0.2 contains some of the improved versions of required v0.1
> extensions such as remote fence, timer and IPI.
>
> This patch implements those extensions.
>
> Signed-off-by: Atish Patra <atish.patra@xxxxxxx>
> ---
> arch/riscv/kvm/Makefile | 1 +
> arch/riscv/kvm/vcpu_sbi.c | 7 ++
> arch/riscv/kvm/vcpu_sbi_replace.c | 136 ++++++++++++++++++++++++++++++
> 3 files changed, 144 insertions(+)
> create mode 100644 arch/riscv/kvm/vcpu_sbi_replace.c
>
> diff --git a/arch/riscv/kvm/Makefile b/arch/riscv/kvm/Makefile
> index 84c02922a329..4757ae158bf3 100644
> --- a/arch/riscv/kvm/Makefile
> +++ b/arch/riscv/kvm/Makefile
> @@ -25,4 +25,5 @@ kvm-y += vcpu_switch.o
> kvm-y += vcpu_sbi.o
> kvm-$(CONFIG_RISCV_SBI_V01) += vcpu_sbi_v01.o
> kvm-y += vcpu_sbi_base.o
> +kvm-y += vcpu_sbi_replace.o
> kvm-y += vcpu_timer.o
> diff --git a/arch/riscv/kvm/vcpu_sbi.c b/arch/riscv/kvm/vcpu_sbi.c
> index 92b682f4f29e..3502c6166eba 100644
> --- a/arch/riscv/kvm/vcpu_sbi.c
> +++ b/arch/riscv/kvm/vcpu_sbi.c
> @@ -40,9 +40,16 @@ static const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_v01 = {
> };
> #endif
> extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_base;
> +extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_time;
> +extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_ipi;
> +extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_rfence;
> +
> static const struct kvm_vcpu_sbi_extension *sbi_ext[] = {
> &vcpu_sbi_ext_v01,
> &vcpu_sbi_ext_base,
> + &vcpu_sbi_ext_time,
> + &vcpu_sbi_ext_ipi,
> + &vcpu_sbi_ext_rfence,
> };
>
> void kvm_riscv_vcpu_sbi_forward(struct kvm_vcpu *vcpu, struct kvm_run *run)
> diff --git a/arch/riscv/kvm/vcpu_sbi_replace.c b/arch/riscv/kvm/vcpu_sbi_replace.c
> new file mode 100644
> index 000000000000..a80fa7691b14
> --- /dev/null
> +++ b/arch/riscv/kvm/vcpu_sbi_replace.c
> @@ -0,0 +1,136 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
> + *
> + * Authors:
> + * Atish Patra <atish.patra@xxxxxxx>
> + */
> +
> +#include <linux/errno.h>
> +#include <linux/err.h>
> +#include <linux/kvm_host.h>
> +#include <asm/csr.h>
> +#include <asm/sbi.h>
> +#include <asm/kvm_vcpu_timer.h>
> +#include <asm/kvm_vcpu_sbi.h>
> +
> +static int kvm_sbi_ext_time_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
> + unsigned long *out_val,
> + struct kvm_cpu_trap *utrap, bool *exit)
> +{
> + int ret = 0;
> + struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
> + u64 next_cycle;
> +
> + if (!cp || (cp->a6 != SBI_EXT_TIME_SET_TIMER))
> + return -EINVAL;
> +
> +#if __riscv_xlen == 32
> + next_cycle = ((u64)cp->a1 << 32) | (u64)cp->a0;
> +#else
> + next_cycle = (u64)cp->a0;
> +#endif
> + kvm_riscv_vcpu_timer_next_event(vcpu, next_cycle);
> +
> + return ret;
> +}
> +
> +const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_time = {
> + .extid_start = SBI_EXT_TIME,
> + .extid_end = SBI_EXT_TIME,
> + .handler = kvm_sbi_ext_time_handler,
> +};
> +
> +static int kvm_sbi_ext_ipi_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
> + unsigned long *out_val,
> + struct kvm_cpu_trap *utrap, bool *exit)
> +{
> + int i, ret = 0;
> + struct kvm_vcpu *tmp;
> + struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
> + unsigned long hmask = cp->a0;
> + unsigned long hbase = cp->a1;
> +
> + if (!cp || (cp->a6 != SBI_EXT_IPI_SEND_IPI))
> + return -EINVAL;
> +
> + kvm_for_each_vcpu(i, tmp, vcpu->kvm) {
> + if (hbase != -1UL) {
> + if (tmp->vcpu_id < hbase)
> + continue;
> + if (!(hmask & (1UL << (tmp->vcpu_id - hbase))))
> + continue;
> + }
> + ret = kvm_riscv_vcpu_set_interrupt(tmp, IRQ_VS_SOFT);
> + if (ret < 0)
> + break;
> + }
> +
> + return ret;
> +}
> +
> +const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_ipi = {
> + .extid_start = SBI_EXT_IPI,
> + .extid_end = SBI_EXT_IPI,
> + .handler = kvm_sbi_ext_ipi_handler,
> +};
> +
> +static int kvm_sbi_ext_rfence_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
> + unsigned long *out_val,
> + struct kvm_cpu_trap *utrap, bool *exit)
> +{
> + int i, ret = 0;
> + struct cpumask cm, hm;
> + struct kvm_vcpu *tmp;
> + struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
> + unsigned long hmask = cp->a0;
> + unsigned long hbase = cp->a1;
> + unsigned long funcid = cp->a6;
> +
> + if (!cp)
> + return -EINVAL;
> +
> + cpumask_clear(&cm);
> + cpumask_clear(&hm);
> + kvm_for_each_vcpu(i, tmp, vcpu->kvm) {
> + if (hbase != -1UL) {
> + if (tmp->vcpu_id < hbase)
> + continue;
> + if (!(hmask & (1UL << (tmp->vcpu_id - hbase))))
> + continue;
> + }
> + if (tmp->cpu < 0)
> + continue;
> + cpumask_set_cpu(tmp->cpu, &cm);
> + }
> +
> + riscv_cpuid_to_hartid_mask(&cm, &hm);
> +
> + switch (funcid) {
> + case SBI_EXT_RFENCE_REMOTE_FENCE_I:
> + ret = sbi_remote_fence_i(cpumask_bits(&hm));
> + break;
> + case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA:
> + ret = sbi_remote_hfence_vvma(cpumask_bits(&hm), cp->a2, cp->a3);
> + break;
> + case SBI_EXT_RFENCE_REMOTE_SFENCE_VMA_ASID:
> + ret = sbi_remote_hfence_vvma_asid(cpumask_bits(&hm), cp->a2,
> + cp->a3, cp->a4);
> + break;
> + case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA:
> + case SBI_EXT_RFENCE_REMOTE_HFENCE_GVMA_VMID:
> + case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA:
> + case SBI_EXT_RFENCE_REMOTE_HFENCE_VVMA_ASID:
> + /* TODO: implement for nested hypervisor case */
> + default:
> + ret = -EOPNOTSUPP;
> + }
> +
> + return ret;
> +}
> +
> +const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_rfence = {
> + .extid_start = SBI_EXT_RFENCE,
> + .extid_end = SBI_EXT_RFENCE,
> + .handler = kvm_sbi_ext_rfence_handler,
> +};
> --
> 2.31.1
>

Drop checks on "cp" pointer in various functions above.

Otherwise it looks good to me.

Reviewed-by: Anup Patel <anup.patel@xxxxxxx>

Regards,
Anup