This supports SDEI_1_0_FN_SDEI_EVENT_{ENABLE, DISABLE} hypercall by implementing function sdei_kvm_hypercall_enable(). On success, the event is enabled globally or on the local CPU. Otherwise, errno is returned. For the passthrou event, it's not enabled or disabled from the underly firmware. What we need is to update the enabled bits, which will be serving as filters during the event delivery to the target VMs and vCPUs. Signed-off-by: Gavin Shan <gshan@xxxxxxxxxx> --- arch/arm64/kvm/sdei.c | 68 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/arch/arm64/kvm/sdei.c b/arch/arm64/kvm/sdei.c index 740694d7f0ff..320b79528211 100644 --- a/arch/arm64/kvm/sdei.c +++ b/arch/arm64/kvm/sdei.c @@ -279,6 +279,70 @@ static unsigned long kvm_sdei_hypercall_register(struct kvm_vcpu *vcpu) return ret; } +static unsigned long kvm_sdei_hypercall_enable(struct kvm_vcpu *vcpu, + bool enabled) +{ + struct kvm *kvm = vcpu->kvm; + struct kvm_sdei_event *event = NULL; + struct kvm_sdei_kvm_event *kevent = NULL; + unsigned long event_num = smccc_get_arg1(vcpu); + unsigned long event_type; + int index = 0; + unsigned long ret = SDEI_SUCCESS; + + /* Validate event number */ + if (!kvm_sdei_num_is_valid(event_num)) { + ret = SDEI_INVALID_PARAMETERS; + goto out; + } + + if (!(kvm_sdei_data && kvm_sdei_data->supported) && + kvm_sdei_num_is_virt(event_num)) { + ret = SDEI_INVALID_PARAMETERS; + goto out; + } + + /* Find the event */ + spin_lock(&kvm_sdei_lock); + event = kvm_sdei_find_event(kvm, event_num, &kevent, NULL, NULL); + if (!kevent) { + ret = SDEI_INVALID_PARAMETERS; + goto unlock; + } + + /* Sanity check */ + spin_lock(&event->lock); + event_type = event->priv ? event->priv->type : event->event->type; + index = (event_type == SDEI_EVENT_TYPE_PRIVATE) ? vcpu->vcpu_idx : 0; + if (kevent->users) { + ret = SDEI_PENDING; + goto unlock_event; + } + + if (!test_bit(index, kevent->registered)) { + ret = SDEI_DENIED; + goto unlock_event; + } + + if (enabled == test_bit(index, kevent->enabled)) { + ret = SDEI_DENIED; + goto unlock_event; + } + + /* Update status */ + if (enabled) + set_bit(index, kevent->enabled); + else + clear_bit(index, kevent->enabled); + +unlock_event: + spin_unlock(&event->lock); +unlock: + spin_unlock(&kvm_sdei_lock); +out: + return ret; +} + static unsigned long kvm_sdei_reset(struct kvm *kvm, unsigned int types) { struct kvm_sdei_event *e, *event = NULL; @@ -356,7 +420,11 @@ int kvm_sdei_hypercall(struct kvm_vcpu *vcpu) ret = kvm_sdei_hypercall_register(vcpu); break; case SDEI_1_0_FN_SDEI_EVENT_ENABLE: + ret = kvm_sdei_hypercall_enable(vcpu, true); + break; case SDEI_1_0_FN_SDEI_EVENT_DISABLE: + ret = kvm_sdei_hypercall_enable(vcpu, false); + break; case SDEI_1_0_FN_SDEI_EVENT_CONTEXT: case SDEI_1_0_FN_SDEI_EVENT_COMPLETE: case SDEI_1_0_FN_SDEI_EVENT_COMPLETE_AND_RESUME: -- 2.23.0 _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/mailman/listinfo/kvmarm