From: Gavin Shan <gshan@redhat.com>
To: kvmarm@lists.cs.columbia.edu
Cc: maz@kernel.org, linux-kernel@vger.kernel.org, eauger@redhat.com,
oupton@google.com, Jonathan.Cameron@huawei.com,
pbonzini@redhat.com, vkuznets@redhat.com, will@kernel.org,
james.morse@arm.com, mark.rutland@arm.com,
shannon.zhaosl@gmail.com, shijie@amperemail.onmicrosoft.com,
shan.gavin@gmail.com
Subject: [PATCH v7 19/22] KVM: arm64: Support SDEI event migration
Date: Fri, 27 May 2022 16:02:50 +0800 [thread overview]
Message-ID: <20220527080253.1562538-20-gshan@redhat.com> (raw)
In-Reply-To: <20220527080253.1562538-1-gshan@redhat.com>
This supports migration for SDEI event handlers, states and context.
Several pseudo firmware registers are added to assist the migration
work.
* KVM_REG_ARM_SDEI_EVENT_HANDLER_0
KVM_REG_ARM_SDEI_EVENT_HANDLER_1
KVM_REG_ARM_SDEI_EVENT_HANDLER_2
KVM_REG_ARM_SDEI_EVENT_HANDLER_3
128-bits in length. They're mapped to the handler's address
and argument for Software Signaled event and Async PF event.
Additinal two events are reserved for future needs without
too much considerations to the compatible issue. Not too much
bandwidth needed to migrate those two additional registers.
* KVM_REG_ARM_SDEI_EVENT_REGISTERED
KVM_REG_ARM_SDEI_EVENT_ENABLED
KVM_REG_ARM_SDEI_EVENT_RUNNING
KVM_REG_ARM_SDEI_EVENT_PENDING
64-bits in length. They're mapped to registered, enabled,
running and pending bitmap.
* KVM_REG_ARM_SDEI_EVENT_CONTEXT
2048-bits in length. It's mapped to saved or interrupted
context.
* KVM_REG_ARM_SDEI_PE_STATE
64-bits in length. It's mapped to PE's states, which is masked
or unmasked.
Signed-off-by: Gavin Shan <gshan@redhat.com>
---
arch/arm64/include/asm/kvm_sdei.h | 2 +
arch/arm64/include/uapi/asm/kvm.h | 17 ++++
arch/arm64/kvm/hypercalls.c | 32 ++++++
arch/arm64/kvm/sdei.c | 161 ++++++++++++++++++++++++++++++
4 files changed, 212 insertions(+)
diff --git a/arch/arm64/include/asm/kvm_sdei.h b/arch/arm64/include/asm/kvm_sdei.h
index a68d40137a88..d11964b88b58 100644
--- a/arch/arm64/include/asm/kvm_sdei.h
+++ b/arch/arm64/include/asm/kvm_sdei.h
@@ -73,6 +73,8 @@ int kvm_sdei_inject_event(struct kvm_vcpu *vcpu,
unsigned int num, bool immediate);
int kvm_sdei_cancel_event(struct kvm_vcpu *vcpu, unsigned int num);
void kvm_sdei_deliver_event(struct kvm_vcpu *vcpu);
+int kvm_sdei_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
+int kvm_sdei_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg);
void kvm_sdei_create_vcpu(struct kvm_vcpu *vcpu);
void kvm_sdei_destroy_vcpu(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index cc3251381960..90247ce8de59 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -262,6 +262,11 @@ struct kvm_arm_copy_mte_tags {
#define KVM_REG_ARM_FW (0x0014 << KVM_REG_ARM_COPROC_SHIFT)
#define KVM_REG_ARM_FW_REG(r) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
KVM_REG_ARM_FW | ((r) & 0xffff))
+#define KVM_REG_ARM_FW_REG_128(r) (KVM_REG_ARM64 | KVM_REG_SIZE_U128 | \
+ KVM_REG_ARM_FW | ((r) & 0xffff))
+#define KVM_REG_ARM_FW_REG_2048(r) (KVM_REG_ARM64 | KVM_REG_SIZE_U2048 | \
+ KVM_REG_ARM_FW | ((r) & 0xffff))
+
#define KVM_REG_ARM_PSCI_VERSION KVM_REG_ARM_FW_REG(0)
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1 KVM_REG_ARM_FW_REG(1)
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL 0
@@ -288,6 +293,18 @@ struct kvm_arm_copy_mte_tags {
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_AVAIL 1
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_REQUIRED 2
+/* SDEI registers */
+#define KVM_REG_ARM_SDEI_EVENT_HANDLER_0 KVM_REG_ARM_FW_REG_128(4)
+#define KVM_REG_ARM_SDEI_EVENT_HANDLER_1 KVM_REG_ARM_FW_REG_128(5)
+#define KVM_REG_ARM_SDEI_EVENT_HANDLER_2 KVM_REG_ARM_FW_REG_128(6)
+#define KVM_REG_ARM_SDEI_EVENT_HANDLER_3 KVM_REG_ARM_FW_REG_128(7)
+#define KVM_REG_ARM_SDEI_EVENT_REGISTERED KVM_REG_ARM_FW_REG(8)
+#define KVM_REG_ARM_SDEI_EVENT_ENABLED KVM_REG_ARM_FW_REG(9)
+#define KVM_REG_ARM_SDEI_EVENT_RUNNING KVM_REG_ARM_FW_REG(10)
+#define KVM_REG_ARM_SDEI_EVENT_PENDING KVM_REG_ARM_FW_REG(11)
+#define KVM_REG_ARM_SDEI_EVENT_CONTEXT KVM_REG_ARM_FW_REG_2048(12)
+#define KVM_REG_ARM_SDEI_PE_STATE KVM_REG_ARM_FW_REG(13)
+
/* SVE registers */
#define KVM_REG_ARM64_SVE (0x15 << KVM_REG_ARM_COPROC_SHIFT)
diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c
index 8e0df54d1422..d330aee968a9 100644
--- a/arch/arm64/kvm/hypercalls.c
+++ b/arch/arm64/kvm/hypercalls.c
@@ -290,6 +290,16 @@ static const u64 kvm_arm_fw_reg_ids[] = {
KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1,
KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2,
KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3,
+ KVM_REG_ARM_SDEI_EVENT_HANDLER_0,
+ KVM_REG_ARM_SDEI_EVENT_HANDLER_1,
+ KVM_REG_ARM_SDEI_EVENT_HANDLER_2,
+ KVM_REG_ARM_SDEI_EVENT_HANDLER_3,
+ KVM_REG_ARM_SDEI_EVENT_REGISTERED,
+ KVM_REG_ARM_SDEI_EVENT_ENABLED,
+ KVM_REG_ARM_SDEI_EVENT_RUNNING,
+ KVM_REG_ARM_SDEI_EVENT_PENDING,
+ KVM_REG_ARM_SDEI_EVENT_CONTEXT,
+ KVM_REG_ARM_SDEI_PE_STATE,
KVM_REG_ARM_STD_BMAP,
KVM_REG_ARM_STD_HYP_BMAP,
KVM_REG_ARM_VENDOR_HYP_BMAP,
@@ -387,6 +397,17 @@ int kvm_arm_get_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3:
val = get_kernel_wa_level(reg->id) & KVM_REG_FEATURE_LEVEL_MASK;
break;
+ case KVM_REG_ARM_SDEI_EVENT_HANDLER_0:
+ case KVM_REG_ARM_SDEI_EVENT_HANDLER_1:
+ case KVM_REG_ARM_SDEI_EVENT_HANDLER_2:
+ case KVM_REG_ARM_SDEI_EVENT_HANDLER_3:
+ case KVM_REG_ARM_SDEI_EVENT_REGISTERED:
+ case KVM_REG_ARM_SDEI_EVENT_ENABLED:
+ case KVM_REG_ARM_SDEI_EVENT_RUNNING:
+ case KVM_REG_ARM_SDEI_EVENT_PENDING:
+ case KVM_REG_ARM_SDEI_EVENT_CONTEXT:
+ case KVM_REG_ARM_SDEI_PE_STATE:
+ return kvm_sdei_get_reg(vcpu, reg);
case KVM_REG_ARM_STD_BMAP:
val = READ_ONCE(smccc_feat->std_bmap);
break;
@@ -537,6 +558,17 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
return -EINVAL;
return 0;
+ case KVM_REG_ARM_SDEI_EVENT_HANDLER_0:
+ case KVM_REG_ARM_SDEI_EVENT_HANDLER_1:
+ case KVM_REG_ARM_SDEI_EVENT_HANDLER_2:
+ case KVM_REG_ARM_SDEI_EVENT_HANDLER_3:
+ case KVM_REG_ARM_SDEI_EVENT_REGISTERED:
+ case KVM_REG_ARM_SDEI_EVENT_ENABLED:
+ case KVM_REG_ARM_SDEI_EVENT_RUNNING:
+ case KVM_REG_ARM_SDEI_EVENT_PENDING:
+ case KVM_REG_ARM_SDEI_EVENT_CONTEXT:
+ case KVM_REG_ARM_SDEI_PE_STATE:
+ return kvm_sdei_set_reg(vcpu, reg);
case KVM_REG_ARM_STD_BMAP:
case KVM_REG_ARM_STD_HYP_BMAP:
case KVM_REG_ARM_VENDOR_HYP_BMAP:
diff --git a/arch/arm64/kvm/sdei.c b/arch/arm64/kvm/sdei.c
index f95b9bcce13c..c14532de48f5 100644
--- a/arch/arm64/kvm/sdei.c
+++ b/arch/arm64/kvm/sdei.c
@@ -498,6 +498,167 @@ void kvm_sdei_deliver_event(struct kvm_vcpu *vcpu)
set_bit(num, &vsdei->running);
}
+int kvm_sdei_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+ struct kvm_sdei_vcpu *vsdei = vcpu->arch.sdei;
+ struct kvm_sdei_event_context *ctxt = &vsdei->ctxt;
+ struct kvm_sdei_event_handler handler;
+ void __user *uaddr = (void __user *)(long)reg->addr;
+ unsigned int num, i;
+ unsigned long val, *pstate = NULL;
+
+ if (!vsdei)
+ return -EPERM;
+
+ switch (reg->id) {
+ case KVM_REG_ARM_SDEI_EVENT_HANDLER_0:
+ case KVM_REG_ARM_SDEI_EVENT_HANDLER_1:
+ case KVM_REG_ARM_SDEI_EVENT_HANDLER_2:
+ case KVM_REG_ARM_SDEI_EVENT_HANDLER_3:
+ num = (reg->id & 0xffff) -
+ (KVM_REG_ARM_SDEI_EVENT_HANDLER_0 & 0xffff);
+
+ if (num < KVM_NR_SDEI_EVENTS)
+ handler = vsdei->handlers[num];
+ else
+ memset(&handler, 0, sizeof(handler));
+
+ if (copy_to_user(uaddr, &handler, KVM_REG_SIZE(reg->id)))
+ return -EFAULT;
+
+ break;
+ case KVM_REG_ARM_SDEI_EVENT_REGISTERED:
+ pstate = &vsdei->registered;
+ fallthrough;
+ case KVM_REG_ARM_SDEI_EVENT_ENABLED:
+ pstate = pstate ? : &vsdei->enabled;
+ fallthrough;
+ case KVM_REG_ARM_SDEI_EVENT_RUNNING:
+ pstate = pstate ? : &vsdei->running;
+ fallthrough;
+ case KVM_REG_ARM_SDEI_EVENT_PENDING:
+ pstate = pstate ? : &vsdei->pending;
+ if (copy_to_user(uaddr, pstate, KVM_REG_SIZE(reg->id)))
+ return -EFAULT;
+
+ break;
+ case KVM_REG_ARM_SDEI_EVENT_CONTEXT:
+ if (copy_to_user(uaddr, &ctxt->pc, sizeof(ctxt->pc)))
+ return -EFAULT;
+
+ uaddr += sizeof(ctxt->pc);
+ if (copy_to_user(uaddr, &ctxt->pstate, sizeof(ctxt->pstate)))
+ return -EFAULT;
+
+ uaddr += sizeof(ctxt->pstate);
+ for (i = 0; i < ARRAY_SIZE(ctxt->regs); i++) {
+ if (copy_to_user(uaddr, &ctxt->regs[i],
+ sizeof(ctxt->regs[i])))
+ return -EFAULT;
+
+ uaddr += sizeof(ctxt->regs[i]);
+ }
+
+ break;
+ case KVM_REG_ARM_SDEI_PE_STATE:
+ val = (vcpu->arch.flags & KVM_ARM64_SDEI_MASKED) ? 1 : 0;
+ if (copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id)))
+ return -EFAULT;
+
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
+int kvm_sdei_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
+{
+ struct kvm_sdei_vcpu *vsdei = vcpu->arch.sdei;
+ struct kvm_sdei_event_context *ctxt = &vsdei->ctxt;
+ void __user *uaddr = (void __user *)(long)reg->addr;
+ unsigned int num, i;
+ unsigned long val, *pstate = NULL;
+
+ if (!vsdei)
+ return -EPERM;
+
+ switch (reg->id) {
+ case KVM_REG_ARM_SDEI_EVENT_HANDLER_0:
+ case KVM_REG_ARM_SDEI_EVENT_HANDLER_1:
+ case KVM_REG_ARM_SDEI_EVENT_HANDLER_2:
+ case KVM_REG_ARM_SDEI_EVENT_HANDLER_3:
+ num = (reg->id & 0xffff) -
+ (KVM_REG_ARM_SDEI_EVENT_HANDLER_0 & 0xffff);
+ if (num >= KVM_NR_SDEI_EVENTS)
+ break;
+
+ if (copy_from_user(&vsdei->handlers[num], uaddr,
+ sizeof(vsdei->handlers[num])))
+ return -EFAULT;
+
+ break;
+ case KVM_REG_ARM_SDEI_EVENT_REGISTERED:
+ pstate = &vsdei->registered;
+ fallthrough;
+ case KVM_REG_ARM_SDEI_EVENT_ENABLED:
+ pstate = pstate ? : &vsdei->enabled;
+ fallthrough;
+ case KVM_REG_ARM_SDEI_EVENT_RUNNING:
+ pstate = pstate ? : &vsdei->running;
+ fallthrough;
+ case KVM_REG_ARM_SDEI_EVENT_PENDING:
+ pstate = pstate ? : &vsdei->pending;
+ if (copy_from_user(&val, uaddr, sizeof(val)))
+ return -EFAULT;
+
+ *pstate = (val & GENMASK(KVM_NR_SDEI_EVENTS - 1, 0));
+ if (!(vcpu->arch.flags & KVM_ARM64_SDEI_MASKED) &&
+ pstate == &vsdei->pending &&
+ vsdei->pending)
+ kvm_make_request(KVM_REQ_SDEI, vcpu);
+
+ break;
+ case KVM_REG_ARM_SDEI_EVENT_CONTEXT:
+ if (copy_from_user(&ctxt->pc, uaddr, sizeof(ctxt->pc)))
+ return -EFAULT;
+
+ uaddr += sizeof(ctxt->pc);
+ if (copy_from_user(&ctxt->pstate, uaddr, sizeof(ctxt->pstate)))
+ return -EFAULT;
+
+ uaddr += sizeof(ctxt->pstate);
+ for (i = 0; i < ARRAY_SIZE(ctxt->regs); i++) {
+ if (copy_from_user(&ctxt->regs[i], uaddr,
+ sizeof(ctxt->regs[i])))
+ return -EFAULT;
+
+ uaddr += sizeof(ctxt->regs[i]);
+ }
+
+ break;
+ case KVM_REG_ARM_SDEI_PE_STATE:
+ if (copy_from_user(&val, uaddr, sizeof(val)))
+ return -EFAULT;
+
+ if (val) {
+ vcpu->arch.flags |= KVM_ARM64_SDEI_MASKED;
+ } else {
+ vcpu->arch.flags &= ~KVM_ARM64_SDEI_MASKED;
+ if (vsdei->pending)
+ kvm_make_request(KVM_REQ_SDEI, vcpu);
+ }
+
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return 0;
+
+}
+
void kvm_sdei_create_vcpu(struct kvm_vcpu *vcpu)
{
struct kvm_sdei_vcpu *vsdei;
--
2.23.0
next prev parent reply other threads:[~2022-05-27 8:07 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-27 8:02 [PATCH v7 00/22] Support SDEI Virtualization Gavin Shan
2022-05-27 8:02 ` [PATCH v7 01/22] KVM: arm64: Extend smccc_get_argx() Gavin Shan
2022-05-27 8:02 ` [PATCH v7 02/22] KVM: arm64: Route hypercalls based on their owner Gavin Shan
2022-05-27 8:02 ` [PATCH v7 03/22] KVM: arm64: Add SDEI virtualization infrastructure Gavin Shan
2022-05-27 8:02 ` [PATCH v7 04/22] KVM: arm64: Support EVENT_REGISTER hypercall Gavin Shan
2022-05-27 8:02 ` [PATCH v7 05/22] KVM: arm64: Support EVENT_{ENABLE, DISABLE} hypercall Gavin Shan
2022-05-27 8:02 ` [PATCH v7 06/22] KVM: arm64: Support EVENT_CONTEXT hypercall Gavin Shan
2022-05-27 8:02 ` [PATCH v7 07/22] KVM: arm64: Support EVENT_UNREGISTER hypercall Gavin Shan
2022-05-27 8:02 ` [PATCH v7 08/22] KVM: arm64: Support EVENT_STATUS hypercall Gavin Shan
2022-05-27 8:02 ` [PATCH v7 09/22] KVM: arm64: Support EVENT_GET_INFO hypercall Gavin Shan
2022-05-27 8:02 ` [PATCH v7 10/22] KVM: arm64: Support PE_{MASK, UNMASK} hypercall Gavin Shan
2022-05-27 8:02 ` [PATCH v7 11/22] KVM: arm64: Support {PRIVATE, SHARED}_RESET hypercall Gavin Shan
2022-05-27 8:02 ` [PATCH v7 12/22] KVM: arm64: Support event injection and delivery Gavin Shan
2022-05-27 8:02 ` [PATCH v7 13/22] KVM: arm64: Support EVENT_{COMPLETE, COMPLETE_AND_RESUME} hypercall Gavin Shan
2022-05-27 8:02 ` [PATCH v7 14/22] KVM: arm64: Support EVENT_SIGNAL hypercall Gavin Shan
2022-05-27 8:02 ` [PATCH v7 15/22] KVM: arm64: Support SDEI_FEATURES hypercall Gavin Shan
2022-05-27 8:02 ` [PATCH v7 16/22] KVM: arm64: Support SDEI_VERSION hypercall Gavin Shan
2022-05-27 8:02 ` [PATCH v7 17/22] KVM: arm64: Expose SDEI capbility and service Gavin Shan
2022-05-27 8:02 ` [PATCH v7 18/22] KVM: arm64: Allow large sized pseudo firmware registers Gavin Shan
2022-05-27 8:02 ` Gavin Shan [this message]
2022-05-27 8:02 ` [PATCH v7 20/22] KVM: arm64: Add SDEI document Gavin Shan
2022-05-27 8:02 ` [PATCH v7 21/22] selftests: KVM: aarch64: Add SDEI case in hypercall tests Gavin Shan
2022-05-27 8:02 ` [PATCH v7 22/22] selftests: KVM: aarch64: Add SDEI test case Gavin Shan
2022-05-30 6:47 ` [PATCH v7 00/22] Support SDEI Virtualization Shijie Huang
2022-05-30 6:57 ` Gavin Shan
[not found] ` <afa80e18-9b1f-170a-dc13-4dd194ed66c6@amperemail.onmicrosoft.com>
2023-06-04 7:09 ` Gavin Shan
2022-06-23 6:11 ` Gavin Shan
2022-06-24 13:12 ` Marc Zyngier
2022-06-27 3:18 ` Gavin Shan
2022-07-05 7:44 ` Paolo Bonzini
2022-07-07 17:08 ` Sean Christopherson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220527080253.1562538-20-gshan@redhat.com \
--to=gshan@redhat.com \
--cc=Jonathan.Cameron@huawei.com \
--cc=eauger@redhat.com \
--cc=james.morse@arm.com \
--cc=kvmarm@lists.cs.columbia.edu \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=maz@kernel.org \
--cc=oupton@google.com \
--cc=pbonzini@redhat.com \
--cc=shan.gavin@gmail.com \
--cc=shannon.zhaosl@gmail.com \
--cc=shijie@amperemail.onmicrosoft.com \
--cc=vkuznets@redhat.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®