This supports SDEI_1_0_FN_SDEI_EVENT_ROUTING_SET hypercall by adding kvm_sdei_hypercall_route(). On success, the specified routing mode and affinity is set. Otherwise, errno is returned. The route mode or affinity is updated to the KVM SDEI event. Signed-off-by: Gavin Shan <gshan@xxxxxxxxxx> --- arch/arm64/kvm/sdei.c | 74 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/arch/arm64/kvm/sdei.c b/arch/arm64/kvm/sdei.c index 529505c4f0cf..1e7291acea0d 100644 --- a/arch/arm64/kvm/sdei.c +++ b/arch/arm64/kvm/sdei.c @@ -585,6 +585,78 @@ static unsigned long kvm_sdei_hypercall_info(struct kvm_vcpu *vcpu) return ret; } +static unsigned long kvm_sdei_hypercall_route(struct kvm_vcpu *vcpu) +{ + 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 route_mode = smccc_get_arg2(vcpu); + unsigned long route_affinity = smccc_get_arg3(vcpu); + unsigned long event_type; + int index = 0; + unsigned long ret = SDEI_SUCCESS; + + /* Validate the parameters */ + 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; + } + + if (!(route_mode == SDEI_EVENT_REGISTER_RM_ANY || + route_mode == SDEI_EVENT_REGISTER_RM_PE)) { + 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 (event_type != SDEI_EVENT_TYPE_SHARED) { + ret = SDEI_INVALID_PARAMETERS; + goto unlock_event; + } + + if (!test_bit(index, kevent->registered) || + test_bit(index, kevent->enabled) || + kevent->users) { + ret = SDEI_DENIED; + goto unlock_event; + } + + if (route_mode == kevent->route_mode && + route_affinity == kevent->route_affinity) { + ret = SDEI_DENIED; + goto unlock_event; + } + + /* Update status */ + kevent->route_mode = route_mode; + kevent->route_affinity = route_affinity; + +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; @@ -680,6 +752,8 @@ int kvm_sdei_hypercall(struct kvm_vcpu *vcpu) ret = kvm_sdei_hypercall_info(vcpu); break; case SDEI_1_0_FN_SDEI_EVENT_ROUTING_SET: + ret = kvm_sdei_hypercall_route(vcpu); + break; case SDEI_1_0_FN_SDEI_PE_MASK: case SDEI_1_0_FN_SDEI_PE_UNMASK: case SDEI_1_0_FN_SDEI_INTERRUPT_BIND: -- 2.23.0 _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/mailman/listinfo/kvmarm