[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220403153911.12332-7-gshan@redhat.com>
Date: Sun, 3 Apr 2022 23:38:59 +0800
From: Gavin Shan <gshan@...hat.com>
To: kvmarm@...ts.cs.columbia.edu
Cc: linux-kernel@...r.kernel.org, eauger@...hat.com, oupton@...gle.com,
Jonathan.Cameron@...wei.com, vkuznets@...hat.com, will@...nel.org,
shannon.zhaosl@...il.com, james.morse@....com,
mark.rutland@....com, maz@...nel.org, pbonzini@...hat.com,
shan.gavin@...il.com
Subject: [PATCH v6 06/18] KVM: arm64: Support SDEI_EVENT_CONTEXT hypercall
This supports SDEI_EVENT_CONTEXT hypercall. It's used by the guest
to retrieve the registers (x0 - x17) from the interrupted or preempted
context in the event handler. The interrupted or preempted context
is saved prior to handling the event by executing its handler and
restored after that.
Signed-off-by: Gavin Shan <gshan@...hat.com>
---
arch/arm64/kvm/sdei.c | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/arch/arm64/kvm/sdei.c b/arch/arm64/kvm/sdei.c
index 941263578b30..af5d11b8eb2f 100644
--- a/arch/arm64/kvm/sdei.c
+++ b/arch/arm64/kvm/sdei.c
@@ -140,6 +140,37 @@ static unsigned long hypercall_enable(struct kvm_vcpu *vcpu, bool enable)
return ret;
}
+static unsigned long hypercall_context(struct kvm_vcpu *vcpu)
+{
+ struct kvm_sdei_vcpu *vsdei = vcpu->arch.sdei;
+ struct kvm_sdei_vcpu_context *context;
+ unsigned long param_id = smccc_get_arg(vcpu, 1);
+ unsigned long ret = SDEI_SUCCESS;
+
+ spin_lock(&vsdei->lock);
+
+ /* Check if we have events are being handled */
+ context = &vsdei->context[SDEI_EVENT_PRIORITY_CRITICAL];
+ context = context->event ? context : NULL;
+ context = context ? : &vsdei->context[SDEI_EVENT_PRIORITY_NORMAL];
+ context = context->event ? context : NULL;
+ if (!context) {
+ ret = SDEI_DENIED;
+ goto unlock;
+ }
+
+ /* Fetch the requested register */
+ if (param_id < ARRAY_SIZE(context->regs))
+ ret = context->regs[param_id];
+ else
+ ret = SDEI_INVALID_PARAMETERS;
+
+unlock:
+ spin_unlock(&vsdei->lock);
+
+ return ret;
+}
+
int kvm_sdei_call(struct kvm_vcpu *vcpu)
{
struct kvm_sdei_vcpu *vsdei = vcpu->arch.sdei;
@@ -170,6 +201,9 @@ int kvm_sdei_call(struct kvm_vcpu *vcpu)
case SDEI_1_0_FN_SDEI_EVENT_DISABLE:
ret = hypercall_enable(vcpu, false);
break;
+ case SDEI_1_0_FN_SDEI_EVENT_CONTEXT:
+ ret = hypercall_context(vcpu);
+ break;
default:
ret = SDEI_NOT_SUPPORTED;
}
--
2.23.0
Powered by blists - more mailing lists