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 03/22] KVM: arm64: Add SDEI virtualization infrastructure
Date: Fri, 27 May 2022 16:02:34 +0800 [thread overview]
Message-ID: <20220527080253.1562538-4-gshan@redhat.com> (raw)
In-Reply-To: <20220527080253.1562538-1-gshan@redhat.com>
Software Delegated Exception Interface (SDEI) provides a mechanism
for registering and servicing system events, as defined by ARM DEN0054C
specification. One of these events will be used by Asynchronous Page
Fault (Async PF) to deliver notifications from host to guest.
The events are classified into shared and private ones according to
their scopes. The shared events are system or VM scoped, but the
private events are CPU or VCPU scoped. The shared events can be
registered, enabled, unregistered and reset through hypercalls
issued from any VCPU. However, the private events are registered,
enabled, unregistered and reset on the calling VCPU through
hypercalls. Besides, the events are also classified into critical
and normal events according their priority. During event delivery
and handling, the normal event can be preempted by another critical
event, but not in reverse way. The critical event can't be preempted
by another normal event.
In the implementation, both shared event and critical event aren't
supported. It means all supported events are private and normal.
There are several objects introduced to manage events and their
states.
* kvm_sdei_event_handler
SDEI event handler, which is provided through EVENT_REGISTER
hypercall, is called when the SDEI event is delivered from
host to guest.
* kvm_sdei_event_context
The saved (preempted) context when SDEI event is delivered
for handling.
* kvm_sdei_vcpu
SDEI events and their states.
The flag KVM_ARM64_SDEI_MASKED is set to mask vCPU from SDEI events
by default. Besides, SDEI_NOT_SUPPORTED is returned for all hypercalls
at present. The hypercalls will be supported one by one in subsequent
patches.
Link: Link: https://developer.arm.com/documentation/den0054/latest
Signed-off-by: Gavin Shan <gshan@redhat.com>
---
arch/arm64/include/asm/kvm_host.h | 2 +
arch/arm64/include/asm/kvm_sdei.h | 70 +++++++++++++++++++++++++++++++
arch/arm64/kvm/Makefile | 2 +-
arch/arm64/kvm/arm.c | 4 ++
arch/arm64/kvm/hypercalls.c | 3 ++
arch/arm64/kvm/sdei.c | 59 ++++++++++++++++++++++++++
include/linux/arm-smccc.h | 2 +
7 files changed, 141 insertions(+), 1 deletion(-)
create mode 100644 arch/arm64/include/asm/kvm_sdei.h
create mode 100644 arch/arm64/kvm/sdei.c
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 47a1e25e25bb..c9d053c2569e 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -366,6 +366,7 @@ struct kvm_vcpu_arch {
* Anything that is not used directly from assembly code goes
* here.
*/
+ struct kvm_sdei_vcpu *sdei;
/*
* Guest registers we preserve during guest debugging.
@@ -466,6 +467,7 @@ struct kvm_vcpu_arch {
#define KVM_ARM64_ON_UNSUPPORTED_CPU (1 << 15) /* Physical CPU not in supported_cpus */
#define KVM_ARM64_HOST_SME_ENABLED (1 << 16) /* SME enabled for EL0 */
#define KVM_ARM64_WFIT (1 << 17) /* WFIT instruction trapped */
+#define KVM_ARM64_SDEI_MASKED (1 << 18) /* SDEI is masked */
#define KVM_GUESTDBG_VALID_MASK (KVM_GUESTDBG_ENABLE | \
KVM_GUESTDBG_USE_SW_BP | \
diff --git a/arch/arm64/include/asm/kvm_sdei.h b/arch/arm64/include/asm/kvm_sdei.h
new file mode 100644
index 000000000000..609338b17478
--- /dev/null
+++ b/arch/arm64/include/asm/kvm_sdei.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Definitions of various KVM SDEI events.
+ *
+ * Copyright (C) 2022 Red Hat, Inc.
+ *
+ * Author(s): Gavin Shan <gshan@redhat.com>
+ */
+
+#ifndef __ARM64_KVM_SDEI_H__
+#define __ARM64_KVM_SDEI_H__
+
+#include <uapi/linux/arm_sdei.h>
+#include <linux/arm-smccc.h>
+#include <linux/bits.h>
+
+enum {
+ KVM_NR_SDEI_EVENTS,
+};
+
+/**
+ * struct kvm_sdei_event_handler - SDEI event handler
+ *
+ * @ep_addr: Address of SDEI event handler
+ * @ep_arg: Argument passed to SDEI event handler
+ */
+struct kvm_sdei_event_handler {
+ unsigned long ep_addr;
+ unsigned long ep_arg;
+};
+
+/**
+ * struct kvm_sdei_event_context - Saved context during SDEI event delivery
+ *
+ * @pc: PC of the saved context
+ * @pstate: PSTATE of the saved context
+ * @regs: x0 to x17 of the saved context
+ */
+struct kvm_sdei_event_context {
+ unsigned long pc;
+ unsigned long pstate;
+ unsigned long regs[18];
+};
+
+/**
+ * struct kvm_sdei_vcpu - SDEI events and their sates
+ *
+ * @registered: Bitmap of registration states for SDEI events
+ * @enabled: Bitmap of enablement states for SDEI events
+ * @running: Bitmap of running states for SDEI events
+ * @pending: Bitmap of pending states for SDEI events
+ * @handlers: Array of SDEI event handlers
+ * @ctxt: Saved context during SDEI event delivery
+ */
+struct kvm_sdei_vcpu {
+ unsigned long registered;
+ unsigned long enabled;
+ unsigned long running;
+ unsigned long pending;
+
+ struct kvm_sdei_event_handler handlers[KVM_NR_SDEI_EVENTS];
+ struct kvm_sdei_event_context ctxt;
+};
+
+/* APIs */
+int kvm_sdei_call(struct kvm_vcpu *vcpu);
+void kvm_sdei_create_vcpu(struct kvm_vcpu *vcpu);
+void kvm_sdei_destroy_vcpu(struct kvm_vcpu *vcpu);
+
+#endif /* __ARM64_KVM_SDEI_H__ */
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index aa127ae9f675..26e9d62875a8 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -14,7 +14,7 @@ kvm-y += arm.o mmu.o mmio.o psci.o hypercalls.o pvtime.o \
inject_fault.o va_layout.o handle_exit.o \
guest.o debug.o reset.o sys_regs.o \
vgic-sys-reg-v3.o fpsimd.o pkvm.o \
- arch_timer.o trng.o vmid.o \
+ arch_timer.o trng.o vmid.o sdei.o \
vgic/vgic.o vgic/vgic-init.o \
vgic/vgic-irqfd.o vgic/vgic-v2.o \
vgic/vgic-v3.o vgic/vgic-v4.o \
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 400bb0fe2745..e9516f951e7b 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -38,6 +38,7 @@
#include <asm/kvm_asm.h>
#include <asm/kvm_mmu.h>
#include <asm/kvm_emulate.h>
+#include <asm/kvm_sdei.h>
#include <asm/sections.h>
#include <kvm/arm_hypercalls.h>
@@ -337,6 +338,8 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
kvm_arm_pvtime_vcpu_init(&vcpu->arch);
+ kvm_sdei_create_vcpu(vcpu);
+
vcpu->arch.hw_mmu = &vcpu->kvm->arch.mmu;
err = kvm_vgic_vcpu_init(vcpu);
@@ -358,6 +361,7 @@ void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
kvm_mmu_free_memory_cache(&vcpu->arch.mmu_page_cache);
kvm_timer_vcpu_terminate(vcpu);
kvm_pmu_vcpu_destroy(vcpu);
+ kvm_sdei_destroy_vcpu(vcpu);
kvm_arm_vcpu_destroy(vcpu);
}
diff --git a/arch/arm64/kvm/hypercalls.c b/arch/arm64/kvm/hypercalls.c
index d66f464e0eb5..88561ac47301 100644
--- a/arch/arm64/kvm/hypercalls.c
+++ b/arch/arm64/kvm/hypercalls.c
@@ -5,6 +5,7 @@
#include <linux/kvm_host.h>
#include <asm/kvm_emulate.h>
+#include <asm/kvm_sdei.h>
#include <kvm/arm_hypercalls.h>
#include <kvm/arm_psci.h>
@@ -199,6 +200,8 @@ static int kvm_hvc_standard(struct kvm_vcpu *vcpu, u32 func)
switch (ARM_SMCCC_FUNC_NUM(func)) {
case ARM_SMCCC_STANDARD_PSCI_START ... ARM_SMCCC_STANDARD_PSCI_END:
return kvm_psci_call(vcpu);
+ case ARM_SMCCC_STANDARD_SDEI_START ... ARM_SMCCC_STANDARD_SDEI_END:
+ return kvm_sdei_call(vcpu);
case ARM_SMCCC_STANDARD_TRNG_START ... ARM_SMCCC_STANDARD_TRNG_END:
return kvm_trng_call(vcpu);
}
diff --git a/arch/arm64/kvm/sdei.c b/arch/arm64/kvm/sdei.c
new file mode 100644
index 000000000000..0c4415fcad16
--- /dev/null
+++ b/arch/arm64/kvm/sdei.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * SDEI virtualization support.
+ *
+ * Copyright (C) 2022 Red Hat, Inc.
+ *
+ * Author(s): Gavin Shan <gshan@redhat.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/kvm_host.h>
+#include <linux/slab.h>
+#include <kvm/arm_hypercalls.h>
+#include <asm/kvm_sdei.h>
+
+int kvm_sdei_call(struct kvm_vcpu *vcpu)
+{
+ struct kvm_sdei_vcpu *vsdei = vcpu->arch.sdei;
+ u32 func = smccc_get_function(vcpu);
+ bool has_result = true;
+ unsigned long ret;
+
+ /* No return value for COMPLETE or COMPLETE_AND_RESUME */
+ if (func == SDEI_1_0_FN_SDEI_EVENT_COMPLETE ||
+ func == SDEI_1_0_FN_SDEI_EVENT_COMPLETE_AND_RESUME)
+ has_result = false;
+
+ if (!vsdei) {
+ ret = SDEI_NOT_SUPPORTED;
+ goto out;
+ }
+
+ switch (func) {
+ default:
+ ret = SDEI_NOT_SUPPORTED;
+ }
+
+out:
+ if (has_result)
+ smccc_set_retval(vcpu, ret, 0, 0, 0);
+
+ return 1;
+}
+
+void kvm_sdei_create_vcpu(struct kvm_vcpu *vcpu)
+{
+ struct kvm_sdei_vcpu *vsdei;
+
+ vcpu->arch.sdei = kzalloc(sizeof(*vsdei), GFP_KERNEL_ACCOUNT);
+ if (vcpu->arch.sdei)
+ vcpu->arch.flags |= KVM_ARM64_SDEI_MASKED;
+}
+
+void kvm_sdei_destroy_vcpu(struct kvm_vcpu *vcpu)
+{
+ vcpu->arch.flags &= ~KVM_ARM64_SDEI_MASKED;
+ kfree(vcpu->arch.sdei);
+ vcpu->arch.sdei = NULL;
+}
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 834fb963a689..18159a9c6703 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -57,6 +57,8 @@
#define ARM_SMCCC_STANDARD_PSCI_START 0x0000
#define ARM_SMCCC_STANDARD_PSCI_END 0x001f
+#define ARM_SMCCC_STANDARD_SDEI_START 0x0020
+#define ARM_SMCCC_STANDARD_SDEI_END 0x003f
#define ARM_SMCCC_STANDARD_TRNG_START 0x0050
#define ARM_SMCCC_STANDARD_TRNG_END 0x005f
--
2.23.0
next prev parent reply other threads:[~2022-05-27 8:04 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 ` Gavin Shan [this message]
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 ` [PATCH v7 19/22] KVM: arm64: Support SDEI event migration Gavin Shan
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-4-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®