[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210608154805.216869-4-jean-philippe@linaro.org>
Date: Tue, 8 Jun 2021 17:48:04 +0200
From: Jean-Philippe Brucker <jean-philippe@...aro.org>
To: maz@...nel.org
Cc: kvm@...r.kernel.org, kvmarm@...ts.cs.columbia.edu,
linux-arm-kernel@...ts.infradead.org, linux-kernel@...r.kernel.org,
pbonzini@...hat.com, corbet@....net, james.morse@....com,
alexandru.elisei@....com, suzuki.poulose@....com,
catalin.marinas@....com, will@...nel.org,
lorenzo.pieralisi@....com, salil.mehta@...wei.com,
shameerali.kolothum.thodi@...wei.com, jonathan.cameron@...wei.com,
Jean-Philippe Brucker <jean-philippe@...aro.org>
Subject: [RFC PATCH 3/5] KVM: arm64: Allow userspace to request WFI
To help userspace implement PSCI CPU_SUSPEND, allow setting the "HALTED"
MP state to request a WFI before returning to the guest.
Userspace won't obtain a HALTED mp_state from a KVM_GET_MP_STATE call
unless they set it themselves. When set by KVM, to handle wfi or
CPU_SUSPEND, it is consumed before returning to userspace.
Signed-off-by: Jean-Philippe Brucker <jean-philippe@...aro.org>
---
Documentation/virt/kvm/api.rst | 15 +++++++++------
include/uapi/linux/kvm.h | 1 +
arch/arm64/kvm/arm.c | 11 ++++++++++-
3 files changed, 20 insertions(+), 7 deletions(-)
diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 7fcb2fd38f42..e4fe7fb60d5d 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -1416,8 +1416,8 @@ Possible values are:
which has not yet received an INIT signal [x86]
KVM_MP_STATE_INIT_RECEIVED the vcpu has received an INIT signal, and is
now ready for a SIPI [x86]
- KVM_MP_STATE_HALTED the vcpu has executed a HLT instruction and
- is waiting for an interrupt [x86]
+ KVM_MP_STATE_HALTED the vcpu has executed a HLT/WFI instruction
+ and is waiting for an interrupt [x86,arm64]
KVM_MP_STATE_SIPI_RECEIVED the vcpu has just received a SIPI (vector
accessible via KVM_GET_VCPU_EVENTS) [x86]
KVM_MP_STATE_STOPPED the vcpu is stopped [s390,arm/arm64]
@@ -1435,8 +1435,9 @@ these architectures.
For arm/arm64:
^^^^^^^^^^^^^^
-The only states that are valid are KVM_MP_STATE_STOPPED and
-KVM_MP_STATE_RUNNABLE which reflect if the vcpu is paused or not.
+Valid states are KVM_MP_STATE_STOPPED and KVM_MP_STATE_RUNNABLE which reflect
+if the vcpu is paused or not. If KVM_CAP_ARM_MP_HALTED is present, state
+KVM_MP_STATE_HALTED is also valid.
4.39 KVM_SET_MP_STATE
---------------------
@@ -1457,8 +1458,10 @@ these architectures.
For arm/arm64:
^^^^^^^^^^^^^^
-The only states that are valid are KVM_MP_STATE_STOPPED and
-KVM_MP_STATE_RUNNABLE which reflect if the vcpu should be paused or not.
+Valid states are KVM_MP_STATE_STOPPED and KVM_MP_STATE_RUNNABLE which reflect
+if the vcpu should be paused or not. If KVM_CAP_ARM_MP_HALTED is present,
+KVM_MP_STATE_HALTED can be set, to wait for interrupts targeted at the vcpu
+before running it.
4.40 KVM_SET_IDENTITY_MAP_ADDR
------------------------------
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 79d9c44d1ad7..06ba64c49737 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1083,6 +1083,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_SGX_ATTRIBUTE 196
#define KVM_CAP_VM_COPY_ENC_CONTEXT_FROM 197
#define KVM_CAP_PTP_KVM 198
+#define KVM_CAP_ARM_MP_HALTED 199
#ifdef KVM_CAP_IRQ_ROUTING
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index d8cbaa0373c7..d6ad977fea5f 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -207,6 +207,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_SET_GUEST_DEBUG:
case KVM_CAP_VCPU_ATTRIBUTES:
case KVM_CAP_PTP_KVM:
+ case KVM_CAP_ARM_MP_HALTED:
r = 1;
break;
case KVM_CAP_SET_GUEST_DEBUG2:
@@ -469,6 +470,9 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
case KVM_MP_STATE_RUNNABLE:
vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
break;
+ case KVM_MP_STATE_HALTED:
+ kvm_arm_vcpu_suspend(vcpu);
+ break;
case KVM_MP_STATE_STOPPED:
kvm_arm_vcpu_power_off(vcpu);
break;
@@ -699,7 +703,12 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu)
preempt_enable();
}
- if (kvm_check_request(KVM_REQ_SUSPEND, vcpu)) {
+ /*
+ * Check mp_state again in case userspace changed their mind
+ * after requesting suspend.
+ */
+ if (kvm_check_request(KVM_REQ_SUSPEND, vcpu) &&
+ vcpu->arch.mp_state == KVM_MP_STATE_HALTED) {
if (!irq_pending) {
kvm_vcpu_block(vcpu);
kvm_clear_request(KVM_REQ_UNHALT, vcpu);
--
2.31.1
Powered by blists - more mailing lists