This supports SDEI_EVENT_GET_INFO hypercall. It's used by the guest to retrieve various information about the supported (exported) events, including type, signaled, route mode and affinity for the shared events.
Signed-off-by: Gavin Shan <gs...@redhat.com> --- arch/arm64/kvm/sdei.c | 76 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/arch/arm64/kvm/sdei.c b/arch/arm64/kvm/sdei.c index b95b8c4455e1..5dfa74b093f1 100644 --- a/arch/arm64/kvm/sdei.c +++ b/arch/arm64/kvm/sdei.c @@ -415,6 +415,80 @@ static unsigned long kvm_sdei_hypercall_status(struct kvm_vcpu *vcpu) return ret; } +static unsigned long kvm_sdei_hypercall_info(struct kvm_vcpu *vcpu) +{ + 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; + unsigned long event_num = smccc_get_arg1(vcpu); + unsigned long event_info = smccc_get_arg2(vcpu); + unsigned long ret = SDEI_SUCCESS; + + /* Sanity check */ + if (!(ksdei && vsdei)) { + ret = SDEI_NOT_SUPPORTED; + goto out; + } + + if (!kvm_sdei_is_valid_event_num(event_num)) { + ret = SDEI_INVALID_PARAMETERS; + goto out; + } + + /* + * Check if the KVM event exists. The event might have been + * registered, we need fetch the information from the registered + * event in that case. + */ + spin_lock(&ksdei->lock); + kske = kvm_sdei_find_kvm_event(kvm, event_num); + kse = kske ? kske->kse : NULL; + if (!kse) { + kse = kvm_sdei_find_event(kvm, event_num); + if (!kse) { + ret = SDEI_INVALID_PARAMETERS; + goto unlock; + } + } + + /* Retrieve the requested information */ + switch (event_info) { + case SDEI_EVENT_INFO_EV_TYPE: + ret = kse->state.type; + break; + case SDEI_EVENT_INFO_EV_SIGNALED: + ret = kse->state.signaled; + break; + case SDEI_EVENT_INFO_EV_PRIORITY: + ret = kse->state.priority; + break; + case SDEI_EVENT_INFO_EV_ROUTING_MODE: + case SDEI_EVENT_INFO_EV_ROUTING_AFF: + if (kse->state.type != SDEI_EVENT_TYPE_SHARED) { + ret = SDEI_INVALID_PARAMETERS; + break; + } + + if (event_info == SDEI_EVENT_INFO_EV_ROUTING_MODE) { + ret = kske ? kske->state.route_mode : + SDEI_EVENT_REGISTER_RM_ANY; + } else { + ret = kske ? kske->state.route_affinity : 0; + } + + break; + default: + ret = SDEI_INVALID_PARAMETERS; + } + +unlock: + spin_unlock(&ksdei->lock); +out: + return ret; +} + int kvm_sdei_hypercall(struct kvm_vcpu *vcpu) { u32 func = smccc_get_function(vcpu); @@ -446,6 +520,8 @@ int kvm_sdei_hypercall(struct kvm_vcpu *vcpu) ret = kvm_sdei_hypercall_status(vcpu); break; case SDEI_1_0_FN_SDEI_EVENT_GET_INFO: + ret = kvm_sdei_hypercall_info(vcpu); + break; case SDEI_1_0_FN_SDEI_EVENT_ROUTING_SET: case SDEI_1_0_FN_SDEI_PE_MASK: case SDEI_1_0_FN_SDEI_PE_UNMASK: -- 2.23.0 _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm