On 8/15/21 2:13 AM, Gavin Shan wrote:
> This supports SDEI event injection by implementing kvm_sdei_inject().
> It's called by kernel directly or VMM through ioctl command to inject
> SDEI event to the specific vCPU.
> 
> Signed-off-by: Gavin Shan <gs...@redhat.com>
> ---
>  arch/arm64/include/asm/kvm_sdei.h      |   2 +
>  arch/arm64/include/uapi/asm/kvm_sdei.h |   1 +
>  arch/arm64/kvm/sdei.c                  | 108 +++++++++++++++++++++++++
>  3 files changed, 111 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/kvm_sdei.h 
> b/arch/arm64/include/asm/kvm_sdei.h
> index a997989bab77..51087fe971ba 100644
> --- a/arch/arm64/include/asm/kvm_sdei.h
> +++ b/arch/arm64/include/asm/kvm_sdei.h
> @@ -124,6 +124,8 @@ void kvm_sdei_create_vcpu(struct kvm_vcpu *vcpu);
>  int kvm_sdei_hypercall(struct kvm_vcpu *vcpu);
>  int kvm_sdei_register_notifier(struct kvm *kvm, unsigned long num,
>                              kvm_sdei_notifier notifier);
> +int kvm_sdei_inject(struct kvm_vcpu *vcpu,
> +                 unsigned long num, bool immediate);
>  void kvm_sdei_deliver(struct kvm_vcpu *vcpu);
>  long kvm_sdei_vm_ioctl(struct kvm *kvm, unsigned long arg);
>  long kvm_sdei_vcpu_ioctl(struct kvm_vcpu *vcpu, unsigned long arg);
> diff --git a/arch/arm64/include/uapi/asm/kvm_sdei.h 
> b/arch/arm64/include/uapi/asm/kvm_sdei.h
> index b916c3435646..f7a6b2b22b50 100644
> --- a/arch/arm64/include/uapi/asm/kvm_sdei.h
> +++ b/arch/arm64/include/uapi/asm/kvm_sdei.h
> @@ -67,6 +67,7 @@ struct kvm_sdei_vcpu_state {
>  #define KVM_SDEI_CMD_SET_VEVENT                      7
>  #define KVM_SDEI_CMD_GET_VCPU_STATE          8
>  #define KVM_SDEI_CMD_SET_VCPU_STATE          9
> +#define KVM_SDEI_CMD_INJECT_EVENT            10
>  
>  struct kvm_sdei_cmd {
>       __u32                                           cmd;
> diff --git a/arch/arm64/kvm/sdei.c b/arch/arm64/kvm/sdei.c
> index 79315b77f24b..7c2789cd1421 100644
> --- a/arch/arm64/kvm/sdei.c
> +++ b/arch/arm64/kvm/sdei.c
> @@ -802,6 +802,111 @@ int kvm_sdei_register_notifier(struct kvm *kvm,
>       return ret;
>  }
>  
> +int kvm_sdei_inject(struct kvm_vcpu *vcpu,
> +                 unsigned long num,
> +                 bool immediate)
don't get the immediate param.
> +{
> +     struct kvm *kvm = vcpu->kvm;
> +     struct kvm_sdei_kvm *ksdei = kvm->arch.sdei;
> +     struct kvm_sdei_vcpu *vsdei = vcpu->arch.sdei;
> +     struct kvm_sdei_event *kse = NULL;
> +     struct kvm_sdei_kvm_event *kske = NULL;
> +     struct kvm_sdei_vcpu_event *ksve = NULL;
> +     int index, ret = 0;
> +
> +     /* Sanity check */
> +     if (!(ksdei && vsdei)) {
> +             ret = -EPERM;
> +             goto out;
> +     }
> +
> +     if (!kvm_sdei_is_valid_event_num(num)) {
> +             ret = -EINVAL;
> +             goto out;
> +     }
> +
> +     /* Check the kvm event */
> +     spin_lock(&ksdei->lock);
> +     kske = kvm_sdei_find_kvm_event(kvm, num);
> +     if (!kske) {
> +             ret = -ENOENT;
> +             goto unlock_kvm;
> +     }
> +
> +     kse = kske->kse;
> +     index = (kse->state.type == SDEI_EVENT_TYPE_PRIVATE) ?
> +             vcpu->vcpu_idx : 0;
> +     if (!(kvm_sdei_is_registered(kske, index) &&
> +           kvm_sdei_is_enabled(kske, index))) {
> +             ret = -EPERM;
> +             goto unlock_kvm;
> +     }
> +
> +     /* Check the vcpu state */
> +     spin_lock(&vsdei->lock);
> +     if (vsdei->state.masked) {
> +             ret = -EPERM;
> +             goto unlock_vcpu;
> +     }
> +
> +     /* Check if the event can be delivered immediately */
> +     if (immediate) {
According to the dispatcher pseudo code this should be always checked?
> +             if (kse->state.priority == SDEI_EVENT_PRIORITY_CRITICAL &&
> +                 !list_empty(&vsdei->critical_events)) {
> +                     ret = -ENOSPC;
> +                     goto unlock_vcpu;
> +             }
> +
> +             if (kse->state.priority == SDEI_EVENT_PRIORITY_NORMAL &&
> +                 (!list_empty(&vsdei->critical_events) ||
> +                  !list_empty(&vsdei->normal_events))) {
> +                     ret = -ENOSPC;
> +                     goto unlock_vcpu;
> +             }
> +     }
What about shared event dispatching. I don't see the afficinity checked
anywhere?
> +
> +     /* Check if the vcpu event exists */
> +     ksve = kvm_sdei_find_vcpu_event(vcpu, num);
> +     if (ksve) {
> +             kske->state.refcount++;
> +             ksve->state.refcount++;
why this double refcount increment??
> +             kvm_make_request(KVM_REQ_SDEI, vcpu);
> +             goto unlock_vcpu;
> +     }
> +
> +     /* Allocate vcpu event */
> +     ksve = kzalloc(sizeof(*ksve), GFP_KERNEL);
> +     if (!ksve) {
> +             ret = -ENOMEM;
> +             goto unlock_vcpu;
> +     }
> +
> +     /*
> +      * We should take lock to update KVM event state because its
> +      * reference count might be zero. In that case, the KVM event
> +      * could be destroyed.
> +      */
> +     kske->state.refcount++;
> +     ksve->state.num      = num;
> +     ksve->state.refcount = 1;
> +     ksve->kske           = kske;
> +     ksve->vcpu           = vcpu;
> +
> +     if (kse->state.priority == SDEI_EVENT_PRIORITY_CRITICAL)
> +             list_add_tail(&ksve->link, &vsdei->critical_events);
> +     else
> +             list_add_tail(&ksve->link, &vsdei->normal_events);
> +
> +     kvm_make_request(KVM_REQ_SDEI, vcpu);
> +
> +unlock_vcpu:
> +     spin_unlock(&vsdei->lock);
> +unlock_kvm:
> +     spin_unlock(&ksdei->lock);
> +out:
> +     return ret;
> +}
> +
>  void kvm_sdei_deliver(struct kvm_vcpu *vcpu)
>  {
>       struct kvm *kvm = vcpu->kvm;
> @@ -1317,6 +1422,9 @@ long kvm_sdei_vcpu_ioctl(struct kvm_vcpu *vcpu, 
> unsigned long arg)
>       case KVM_SDEI_CMD_SET_VCPU_STATE:
>               ret = kvm_sdei_set_vcpu_state(vcpu, &cmd->ksv_state);
>               break;
> +     case KVM_SDEI_CMD_INJECT_EVENT:
> +             ret = kvm_sdei_inject(vcpu, cmd->num, false);
> +             break;
>       default:
>               ret = -EINVAL;
>       }
> 
Eric

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

Reply via email to