[PATCH v6 14/18] KVM: arm64: Support SDEI_EVENT_SIGNAL hypercall

From: Gavin Shan
Date: Sun Apr 03 2022 - 11:41:38 EST


This supports SDEI_EVENT_SIGNAL hypercall. It's used by guest
to inject event, whose number must be zero to the specified
vCPU. As the shared event isn't supported, calling vCPU is
assumed to be the target.

Signed-off-by: Gavin Shan <gshan@xxxxxxxxxx>
---
arch/arm64/kvm/sdei.c | 45 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)

diff --git a/arch/arm64/kvm/sdei.c b/arch/arm64/kvm/sdei.c
index ebdbe7810cf0..e1f6ab9800ee 100644
--- a/arch/arm64/kvm/sdei.c
+++ b/arch/arm64/kvm/sdei.c
@@ -455,6 +455,48 @@ static unsigned long hypercall_mask(struct kvm_vcpu *vcpu, bool mask)
return ret;
}

+static unsigned long hypercall_signal(struct kvm_vcpu *vcpu)
+{
+ struct kvm_sdei_vcpu *vsdei = vcpu->arch.sdei;
+ struct kvm_sdei_event *event;
+ unsigned int num = smccc_get_arg(vcpu, 1);
+ unsigned long ret = SDEI_SUCCESS;
+
+ /*
+ * The event must be the software signaled one, whose number
+ * is zero.
+ */
+ if (!kvm_sdei_is_sw_signaled(num)) {
+ ret = SDEI_INVALID_PARAMETERS;
+ goto out;
+ }
+
+ spin_lock(&vsdei->lock);
+
+ /* Check if the vcpu has been masked */
+ if (vsdei->masked) {
+ ret = SDEI_INVALID_PARAMETERS;
+ goto unlock;
+ }
+
+ /* Check if the event exists */
+ event = find_event(vcpu, num);
+ if (!event) {
+ ret = SDEI_INVALID_PARAMETERS;
+ goto unlock;
+ }
+
+ if (inject_event(vcpu, event)) {
+ ret = SDEI_INVALID_PARAMETERS;
+ goto unlock;
+ }
+
+unlock:
+ spin_unlock(&vsdei->lock);
+out:
+ return ret;
+}
+
static unsigned long hypercall_reset(struct kvm_vcpu *vcpu, bool private)
{
struct kvm_sdei_vcpu *vsdei = vcpu->arch.sdei;
@@ -539,6 +581,9 @@ int kvm_sdei_call(struct kvm_vcpu *vcpu)
case SDEI_1_0_FN_SDEI_PE_UNMASK:
ret = hypercall_mask(vcpu, false);
break;
+ case SDEI_1_1_FN_SDEI_EVENT_SIGNAL:
+ ret = hypercall_signal(vcpu);
+ break;
case SDEI_1_0_FN_SDEI_PRIVATE_RESET:
ret = hypercall_reset(vcpu, true);
break;
--
2.23.0