All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/15] KVM: arm64: PSCI SYSTEM_SUSPEND + SYSTEM_RESET2 bugfix
@ 2022-03-11 17:39 ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: alexandru.elisei, anup, atishp, james.morse, jingzhangos,
	jmattson, joro, kvm-riscv, kvm, maz, pbonzini, pshier, rananta,
	reijiw, ricarkol, seanjc, suzuki.poulose, vkuznets, wanpengli,
	Oliver Upton

**NOTE** Patch 2 is a bugfix for commit d43583b890e7 ("KVM: arm64:
Expose PSCI SYSTEM_RESET2 call to the guest") on kvmarm/next. Without
this patch, it is possible for the guest to call
PSCI_1_1_FN64_SYSTEM_RESET2 from AArch32.

The PSCI v1.0 specification describes a call, SYSTEM_SUSPEND, which
allows software to request that the system be placed into the lowest
possible power state and await an IMPLEMENTATION DEFINED wakeup event.
This call is optional in v1.0 and v1.1. KVM does not currently support
this optional call.

This series adds support for the PSCI SYSTEM_SUSPEND call to KVM/arm64.
For reasons best explained in PATCH 09/15, it is infeasible to correctly
implement PSCI SYSTEM_SUSPEND like the other system-wide PSCI calls,
wherein part of the implementation exists in the kernel and the rest in
userspace. To that end, this series affords userspace the ability to
trap SYSTEM_SUSPEND calls (with opt-in) and to optionally leverage
in-kernel emulation of a suspension by way of a new MP_STATE.

Patch 1 snags a useful change from Marc to use bits in an unsigned long
to indicate boolean properties of a VM instead of boolean fields. This
patch was lifted from [1] and modified to eliminate kvm_arch::ran_once.

Patches 2-3 rework some of the PSCI switch statements to make them a bit
more futureproof for later extension. Namely, eliminate dependence on
falling through to the default case. Additionally, reject any and all
SMC64 calls made from AArch32 instead of checking on a case-by-case
basis.

Patch 4 starts tracking the MP state of vCPUs explicitly, as subsequent
changes add additional states that cannot be otherwise represented.

Patch 5 is a renaming nit to clarify the KVM_REQ_SLEEP handler processes
(instead of makes) requests.

Patch 6 creates a helper for preparing kvm_run to do a system event
exit.

Patch 7 prepares for the case where a vCPU request could result in an
exit to userspace.

Patch 8 adds support for userspace to request in-kernel emulation of a
suspended vCPU as the architectural execution of a WFI instruction.
Userspace gets to decide when to resume the vCPU, so KVM will just exit
every time a wakeup event is recognized (unmasked pending interrupt).

Patch 9 adds a capability that allows userspace to trap the
SYSTEM_SUSPEND PSCI call. KVM does absolutely nothing besides exit to
avoid possible races when exiting to userspace.

Patches 10-14 rework some SMCCC handling in KVM selftests as well as
prepare the PSCI test for more test cases.

Lastly, patch 15 adds test cases for SYSTEM_SUSPEND, verifying that it
is discoverable with the PSCI_FEATURES call and results in exits to
userspace when directly called.

Given the conflicts/fixes for SYSTEM_RESET2 and conflicts with
Documentation changes, this series is based on kvmarm/next at commit:

  9872e6bc08d6 ("Merge branch kvm-arm64/psci-1.1 into kvmarm-master/next")

This series was tested with the included selftest as well as a kvmtool
series that instruments the userspace portion of SYSTEM_SUSPEND that
will be sent out soon.

[1]: https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git/commit/?h=kvm-arm64/mmu/guest-MMIO-guard&id=7dd0a13a4217b870f2e83cdc6045e5ce482a5340

v3: https://patchwork.kernel.org/project/kvm/cover/20220223041844.3984439-1-oupton@google.com/

v3 -> v4:
 - Rebase to kvmarm/next
 - Grab Marc's VM feature patch
 - Drop filtering for an invalid IPA. It is no longer directly relevant
   to this series and can be sent out separately.
 - Use the kvm_mp_state structure to store a vCPU's MP state (Marc)
 - Rename helper to better fit MP state mnemonic (Marc)
 - Don't even bother with an in-kernel implementation of the
   SYSTEM_SUSPEND call (Marc)
 - Add discoverability tests for SYSTEM_SUSPEND
 - Ack from Anup for RISC-V change.

Marc Zyngier (1):
  KVM: arm64: Generalise VM features into a set of flags

Oliver Upton (14):
  KVM: arm64: Generally disallow SMC64 for AArch32 guests
  KVM: arm64: Don't depend on fallthrough to hide SYSTEM_RESET2
  KVM: arm64: Dedupe vCPU power off helpers
  KVM: arm64: Track vCPU power state using MP state values
  KVM: arm64: Rename the KVM_REQ_SLEEP handler
  KVM: Create helper for setting a system event exit
  KVM: arm64: Return a value from check_vcpu_requests()
  KVM: arm64: Add support for userspace to suspend a vCPU
  KVM: arm64: Implement PSCI SYSTEM_SUSPEND
  selftests: KVM: Rename psci_cpu_on_test to psci_test
  selftests: KVM: Create helper for making SMCCC calls
  selftests: KVM: Use KVM_SET_MP_STATE to power off vCPU in psci_test
  selftests: KVM: Refactor psci_test to make it amenable to new tests
  selftests: KVM: Test SYSTEM_SUSPEND PSCI call

 Documentation/virt/kvm/api.rst                |  76 ++++++-
 arch/arm64/include/asm/kvm_host.h             |  25 +-
 arch/arm64/kvm/arm.c                          | 100 ++++++--
 arch/arm64/kvm/mmio.c                         |   3 +-
 arch/arm64/kvm/pmu-emul.c                     |   4 +-
 arch/arm64/kvm/psci.c                         |  80 ++++---
 arch/riscv/kvm/vcpu_sbi_v01.c                 |   4 +-
 arch/x86/kvm/x86.c                            |   6 +-
 include/linux/kvm_host.h                      |   2 +
 include/uapi/linux/kvm.h                      |   4 +
 tools/testing/selftests/kvm/.gitignore        |   2 +-
 tools/testing/selftests/kvm/Makefile          |   2 +-
 .../selftests/kvm/aarch64/psci_cpu_on_test.c  | 121 ----------
 .../testing/selftests/kvm/aarch64/psci_test.c | 213 ++++++++++++++++++
 .../selftests/kvm/include/aarch64/processor.h |  22 ++
 .../selftests/kvm/lib/aarch64/processor.c     |  25 ++
 tools/testing/selftests/kvm/steal_time.c      |  13 +-
 virt/kvm/kvm_main.c                           |   8 +
 18 files changed, 501 insertions(+), 209 deletions(-)
 delete mode 100644 tools/testing/selftests/kvm/aarch64/psci_cpu_on_test.c
 create mode 100644 tools/testing/selftests/kvm/aarch64/psci_test.c

-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v4 00/15] KVM: arm64: PSCI SYSTEM_SUSPEND + SYSTEM_RESET2 bugfix
@ 2022-03-11 17:39 ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: maz, wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

**NOTE** Patch 2 is a bugfix for commit d43583b890e7 ("KVM: arm64:
Expose PSCI SYSTEM_RESET2 call to the guest") on kvmarm/next. Without
this patch, it is possible for the guest to call
PSCI_1_1_FN64_SYSTEM_RESET2 from AArch32.

The PSCI v1.0 specification describes a call, SYSTEM_SUSPEND, which
allows software to request that the system be placed into the lowest
possible power state and await an IMPLEMENTATION DEFINED wakeup event.
This call is optional in v1.0 and v1.1. KVM does not currently support
this optional call.

This series adds support for the PSCI SYSTEM_SUSPEND call to KVM/arm64.
For reasons best explained in PATCH 09/15, it is infeasible to correctly
implement PSCI SYSTEM_SUSPEND like the other system-wide PSCI calls,
wherein part of the implementation exists in the kernel and the rest in
userspace. To that end, this series affords userspace the ability to
trap SYSTEM_SUSPEND calls (with opt-in) and to optionally leverage
in-kernel emulation of a suspension by way of a new MP_STATE.

Patch 1 snags a useful change from Marc to use bits in an unsigned long
to indicate boolean properties of a VM instead of boolean fields. This
patch was lifted from [1] and modified to eliminate kvm_arch::ran_once.

Patches 2-3 rework some of the PSCI switch statements to make them a bit
more futureproof for later extension. Namely, eliminate dependence on
falling through to the default case. Additionally, reject any and all
SMC64 calls made from AArch32 instead of checking on a case-by-case
basis.

Patch 4 starts tracking the MP state of vCPUs explicitly, as subsequent
changes add additional states that cannot be otherwise represented.

Patch 5 is a renaming nit to clarify the KVM_REQ_SLEEP handler processes
(instead of makes) requests.

Patch 6 creates a helper for preparing kvm_run to do a system event
exit.

Patch 7 prepares for the case where a vCPU request could result in an
exit to userspace.

Patch 8 adds support for userspace to request in-kernel emulation of a
suspended vCPU as the architectural execution of a WFI instruction.
Userspace gets to decide when to resume the vCPU, so KVM will just exit
every time a wakeup event is recognized (unmasked pending interrupt).

Patch 9 adds a capability that allows userspace to trap the
SYSTEM_SUSPEND PSCI call. KVM does absolutely nothing besides exit to
avoid possible races when exiting to userspace.

Patches 10-14 rework some SMCCC handling in KVM selftests as well as
prepare the PSCI test for more test cases.

Lastly, patch 15 adds test cases for SYSTEM_SUSPEND, verifying that it
is discoverable with the PSCI_FEATURES call and results in exits to
userspace when directly called.

Given the conflicts/fixes for SYSTEM_RESET2 and conflicts with
Documentation changes, this series is based on kvmarm/next at commit:

  9872e6bc08d6 ("Merge branch kvm-arm64/psci-1.1 into kvmarm-master/next")

This series was tested with the included selftest as well as a kvmtool
series that instruments the userspace portion of SYSTEM_SUSPEND that
will be sent out soon.

[1]: https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git/commit/?h=kvm-arm64/mmu/guest-MMIO-guard&id=7dd0a13a4217b870f2e83cdc6045e5ce482a5340

v3: https://patchwork.kernel.org/project/kvm/cover/20220223041844.3984439-1-oupton@google.com/

v3 -> v4:
 - Rebase to kvmarm/next
 - Grab Marc's VM feature patch
 - Drop filtering for an invalid IPA. It is no longer directly relevant
   to this series and can be sent out separately.
 - Use the kvm_mp_state structure to store a vCPU's MP state (Marc)
 - Rename helper to better fit MP state mnemonic (Marc)
 - Don't even bother with an in-kernel implementation of the
   SYSTEM_SUSPEND call (Marc)
 - Add discoverability tests for SYSTEM_SUSPEND
 - Ack from Anup for RISC-V change.

Marc Zyngier (1):
  KVM: arm64: Generalise VM features into a set of flags

Oliver Upton (14):
  KVM: arm64: Generally disallow SMC64 for AArch32 guests
  KVM: arm64: Don't depend on fallthrough to hide SYSTEM_RESET2
  KVM: arm64: Dedupe vCPU power off helpers
  KVM: arm64: Track vCPU power state using MP state values
  KVM: arm64: Rename the KVM_REQ_SLEEP handler
  KVM: Create helper for setting a system event exit
  KVM: arm64: Return a value from check_vcpu_requests()
  KVM: arm64: Add support for userspace to suspend a vCPU
  KVM: arm64: Implement PSCI SYSTEM_SUSPEND
  selftests: KVM: Rename psci_cpu_on_test to psci_test
  selftests: KVM: Create helper for making SMCCC calls
  selftests: KVM: Use KVM_SET_MP_STATE to power off vCPU in psci_test
  selftests: KVM: Refactor psci_test to make it amenable to new tests
  selftests: KVM: Test SYSTEM_SUSPEND PSCI call

 Documentation/virt/kvm/api.rst                |  76 ++++++-
 arch/arm64/include/asm/kvm_host.h             |  25 +-
 arch/arm64/kvm/arm.c                          | 100 ++++++--
 arch/arm64/kvm/mmio.c                         |   3 +-
 arch/arm64/kvm/pmu-emul.c                     |   4 +-
 arch/arm64/kvm/psci.c                         |  80 ++++---
 arch/riscv/kvm/vcpu_sbi_v01.c                 |   4 +-
 arch/x86/kvm/x86.c                            |   6 +-
 include/linux/kvm_host.h                      |   2 +
 include/uapi/linux/kvm.h                      |   4 +
 tools/testing/selftests/kvm/.gitignore        |   2 +-
 tools/testing/selftests/kvm/Makefile          |   2 +-
 .../selftests/kvm/aarch64/psci_cpu_on_test.c  | 121 ----------
 .../testing/selftests/kvm/aarch64/psci_test.c | 213 ++++++++++++++++++
 .../selftests/kvm/include/aarch64/processor.h |  22 ++
 .../selftests/kvm/lib/aarch64/processor.c     |  25 ++
 tools/testing/selftests/kvm/steal_time.c      |  13 +-
 virt/kvm/kvm_main.c                           |   8 +
 18 files changed, 501 insertions(+), 209 deletions(-)
 delete mode 100644 tools/testing/selftests/kvm/aarch64/psci_cpu_on_test.c
 create mode 100644 tools/testing/selftests/kvm/aarch64/psci_test.c

-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v4 01/15] KVM: arm64: Generalise VM features into a set of flags
  2022-03-11 17:39 ` Oliver Upton
@ 2022-03-11 17:39   ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: alexandru.elisei, anup, atishp, james.morse, jingzhangos,
	jmattson, joro, kvm-riscv, kvm, maz, pbonzini, pshier, rananta,
	reijiw, ricarkol, seanjc, suzuki.poulose, vkuznets, wanpengli,
	Oliver Upton

From: Marc Zyngier <maz@kernel.org>

We currently deal with a set of booleans for VM features,
while they could be better represented as set of flags
contained in an unsigned long, similarily to what we are
doing on the CPU side.

Signed-off-by: Marc Zyngier <maz@kernel.org>
[Oliver: Flag-ify the 'ran_once' boolean]
Signed-off-by: Oliver Upton <oupton@google.com>
---
 arch/arm64/include/asm/kvm_host.h | 15 +++++++++------
 arch/arm64/kvm/arm.c              |  7 ++++---
 arch/arm64/kvm/mmio.c             |  3 ++-
 arch/arm64/kvm/pmu-emul.c         |  4 ++--
 4 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 76f795b628f1..0e96087885fe 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -122,7 +122,12 @@ struct kvm_arch {
 	 * should) opt in to this feature if KVM_CAP_ARM_NISV_TO_USER is
 	 * supported.
 	 */
-	bool return_nisv_io_abort_to_user;
+#define KVM_ARCH_FLAG_RETURN_NISV_IO_ABORT_TO_USER	0
+	/* Memory Tagging Extension enabled for the guest */
+#define KVM_ARCH_FLAG_MTE_ENABLED			1
+	/* At least one vCPU has ran in the VM */
+#define KVM_ARCH_FLAG_HAS_RAN_ONCE			2
+	unsigned long flags;
 
 	/*
 	 * VM-wide PMU filter, implemented as a bitmap and big enough for
@@ -135,10 +140,6 @@ struct kvm_arch {
 
 	u8 pfr0_csv2;
 	u8 pfr0_csv3;
-
-	/* Memory Tagging Extension enabled for the guest */
-	bool mte_enabled;
-	bool ran_once;
 };
 
 struct kvm_vcpu_fault_info {
@@ -810,7 +811,9 @@ bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu);
 #define kvm_arm_vcpu_sve_finalized(vcpu) \
 	((vcpu)->arch.flags & KVM_ARM64_VCPU_SVE_FINALIZED)
 
-#define kvm_has_mte(kvm) (system_supports_mte() && (kvm)->arch.mte_enabled)
+#define kvm_has_mte(kvm)					\
+	(system_supports_mte() &&				\
+	 test_bit(KVM_ARCH_FLAG_MTE_ENABLED, &(kvm)->arch.flags))
 #define kvm_vcpu_has_pmu(vcpu)					\
 	(test_bit(KVM_ARM_VCPU_PMU_V3, (vcpu)->arch.features))
 
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index f49ebdd9c990..17021bc8ee2c 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -84,7 +84,8 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
 	switch (cap->cap) {
 	case KVM_CAP_ARM_NISV_TO_USER:
 		r = 0;
-		kvm->arch.return_nisv_io_abort_to_user = true;
+		set_bit(KVM_ARCH_FLAG_RETURN_NISV_IO_ABORT_TO_USER,
+			&kvm->arch.flags);
 		break;
 	case KVM_CAP_ARM_MTE:
 		mutex_lock(&kvm->lock);
@@ -92,7 +93,7 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
 			r = -EINVAL;
 		} else {
 			r = 0;
-			kvm->arch.mte_enabled = true;
+			set_bit(KVM_ARCH_FLAG_MTE_ENABLED, &kvm->arch.flags);
 		}
 		mutex_unlock(&kvm->lock);
 		break;
@@ -559,7 +560,7 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
 		kvm_call_hyp_nvhe(__pkvm_vcpu_init_traps, vcpu);
 
 	mutex_lock(&kvm->lock);
-	kvm->arch.ran_once = true;
+	set_bit(KVM_ARCH_FLAG_HAS_RAN_ONCE, &kvm->arch.flags);
 	mutex_unlock(&kvm->lock);
 
 	return ret;
diff --git a/arch/arm64/kvm/mmio.c b/arch/arm64/kvm/mmio.c
index 3e2d8ba11a02..3dd38a151d2a 100644
--- a/arch/arm64/kvm/mmio.c
+++ b/arch/arm64/kvm/mmio.c
@@ -135,7 +135,8 @@ int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
 	 * volunteered to do so, and bail out otherwise.
 	 */
 	if (!kvm_vcpu_dabt_isvalid(vcpu)) {
-		if (vcpu->kvm->arch.return_nisv_io_abort_to_user) {
+		if (test_bit(KVM_ARCH_FLAG_RETURN_NISV_IO_ABORT_TO_USER,
+			     &vcpu->kvm->arch.flags)) {
 			run->exit_reason = KVM_EXIT_ARM_NISV;
 			run->arm_nisv.esr_iss = kvm_vcpu_dabt_iss_nisv_sanitized(vcpu);
 			run->arm_nisv.fault_ipa = fault_ipa;
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 4526a5824dac..78fdc443adc7 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -961,7 +961,7 @@ static int kvm_arm_pmu_v3_set_pmu(struct kvm_vcpu *vcpu, int pmu_id)
 	list_for_each_entry(entry, &arm_pmus, entry) {
 		arm_pmu = entry->arm_pmu;
 		if (arm_pmu->pmu.type == pmu_id) {
-			if (kvm->arch.ran_once ||
+			if (test_bit(KVM_ARCH_FLAG_HAS_RAN_ONCE, &kvm->arch.flags) ||
 			    (kvm->arch.pmu_filter && kvm->arch.arm_pmu != arm_pmu)) {
 				ret = -EBUSY;
 				break;
@@ -1044,7 +1044,7 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 
 		mutex_lock(&kvm->lock);
 
-		if (kvm->arch.ran_once) {
+		if (test_bit(KVM_ARCH_FLAG_HAS_RAN_ONCE, &kvm->arch.flags)) {
 			mutex_unlock(&kvm->lock);
 			return -EBUSY;
 		}
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 01/15] KVM: arm64: Generalise VM features into a set of flags
@ 2022-03-11 17:39   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: maz, wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

From: Marc Zyngier <maz@kernel.org>

We currently deal with a set of booleans for VM features,
while they could be better represented as set of flags
contained in an unsigned long, similarily to what we are
doing on the CPU side.

Signed-off-by: Marc Zyngier <maz@kernel.org>
[Oliver: Flag-ify the 'ran_once' boolean]
Signed-off-by: Oliver Upton <oupton@google.com>
---
 arch/arm64/include/asm/kvm_host.h | 15 +++++++++------
 arch/arm64/kvm/arm.c              |  7 ++++---
 arch/arm64/kvm/mmio.c             |  3 ++-
 arch/arm64/kvm/pmu-emul.c         |  4 ++--
 4 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 76f795b628f1..0e96087885fe 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -122,7 +122,12 @@ struct kvm_arch {
 	 * should) opt in to this feature if KVM_CAP_ARM_NISV_TO_USER is
 	 * supported.
 	 */
-	bool return_nisv_io_abort_to_user;
+#define KVM_ARCH_FLAG_RETURN_NISV_IO_ABORT_TO_USER	0
+	/* Memory Tagging Extension enabled for the guest */
+#define KVM_ARCH_FLAG_MTE_ENABLED			1
+	/* At least one vCPU has ran in the VM */
+#define KVM_ARCH_FLAG_HAS_RAN_ONCE			2
+	unsigned long flags;
 
 	/*
 	 * VM-wide PMU filter, implemented as a bitmap and big enough for
@@ -135,10 +140,6 @@ struct kvm_arch {
 
 	u8 pfr0_csv2;
 	u8 pfr0_csv3;
-
-	/* Memory Tagging Extension enabled for the guest */
-	bool mte_enabled;
-	bool ran_once;
 };
 
 struct kvm_vcpu_fault_info {
@@ -810,7 +811,9 @@ bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu);
 #define kvm_arm_vcpu_sve_finalized(vcpu) \
 	((vcpu)->arch.flags & KVM_ARM64_VCPU_SVE_FINALIZED)
 
-#define kvm_has_mte(kvm) (system_supports_mte() && (kvm)->arch.mte_enabled)
+#define kvm_has_mte(kvm)					\
+	(system_supports_mte() &&				\
+	 test_bit(KVM_ARCH_FLAG_MTE_ENABLED, &(kvm)->arch.flags))
 #define kvm_vcpu_has_pmu(vcpu)					\
 	(test_bit(KVM_ARM_VCPU_PMU_V3, (vcpu)->arch.features))
 
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index f49ebdd9c990..17021bc8ee2c 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -84,7 +84,8 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
 	switch (cap->cap) {
 	case KVM_CAP_ARM_NISV_TO_USER:
 		r = 0;
-		kvm->arch.return_nisv_io_abort_to_user = true;
+		set_bit(KVM_ARCH_FLAG_RETURN_NISV_IO_ABORT_TO_USER,
+			&kvm->arch.flags);
 		break;
 	case KVM_CAP_ARM_MTE:
 		mutex_lock(&kvm->lock);
@@ -92,7 +93,7 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
 			r = -EINVAL;
 		} else {
 			r = 0;
-			kvm->arch.mte_enabled = true;
+			set_bit(KVM_ARCH_FLAG_MTE_ENABLED, &kvm->arch.flags);
 		}
 		mutex_unlock(&kvm->lock);
 		break;
@@ -559,7 +560,7 @@ int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
 		kvm_call_hyp_nvhe(__pkvm_vcpu_init_traps, vcpu);
 
 	mutex_lock(&kvm->lock);
-	kvm->arch.ran_once = true;
+	set_bit(KVM_ARCH_FLAG_HAS_RAN_ONCE, &kvm->arch.flags);
 	mutex_unlock(&kvm->lock);
 
 	return ret;
diff --git a/arch/arm64/kvm/mmio.c b/arch/arm64/kvm/mmio.c
index 3e2d8ba11a02..3dd38a151d2a 100644
--- a/arch/arm64/kvm/mmio.c
+++ b/arch/arm64/kvm/mmio.c
@@ -135,7 +135,8 @@ int io_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa)
 	 * volunteered to do so, and bail out otherwise.
 	 */
 	if (!kvm_vcpu_dabt_isvalid(vcpu)) {
-		if (vcpu->kvm->arch.return_nisv_io_abort_to_user) {
+		if (test_bit(KVM_ARCH_FLAG_RETURN_NISV_IO_ABORT_TO_USER,
+			     &vcpu->kvm->arch.flags)) {
 			run->exit_reason = KVM_EXIT_ARM_NISV;
 			run->arm_nisv.esr_iss = kvm_vcpu_dabt_iss_nisv_sanitized(vcpu);
 			run->arm_nisv.fault_ipa = fault_ipa;
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 4526a5824dac..78fdc443adc7 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -961,7 +961,7 @@ static int kvm_arm_pmu_v3_set_pmu(struct kvm_vcpu *vcpu, int pmu_id)
 	list_for_each_entry(entry, &arm_pmus, entry) {
 		arm_pmu = entry->arm_pmu;
 		if (arm_pmu->pmu.type == pmu_id) {
-			if (kvm->arch.ran_once ||
+			if (test_bit(KVM_ARCH_FLAG_HAS_RAN_ONCE, &kvm->arch.flags) ||
 			    (kvm->arch.pmu_filter && kvm->arch.arm_pmu != arm_pmu)) {
 				ret = -EBUSY;
 				break;
@@ -1044,7 +1044,7 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 
 		mutex_lock(&kvm->lock);
 
-		if (kvm->arch.ran_once) {
+		if (test_bit(KVM_ARCH_FLAG_HAS_RAN_ONCE, &kvm->arch.flags)) {
 			mutex_unlock(&kvm->lock);
 			return -EBUSY;
 		}
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 02/15] KVM: arm64: Generally disallow SMC64 for AArch32 guests
  2022-03-11 17:39 ` Oliver Upton
@ 2022-03-11 17:39   ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: alexandru.elisei, anup, atishp, james.morse, jingzhangos,
	jmattson, joro, kvm-riscv, kvm, maz, pbonzini, pshier, rananta,
	reijiw, ricarkol, seanjc, suzuki.poulose, vkuznets, wanpengli,
	Oliver Upton, Andrew Jones

The only valid calling SMC calling convention from an AArch32 state is
SMC32. Disallow any PSCI function that sets the SMC64 function ID bit
when called from AArch32 rather than comparing against known SMC64 PSCI
functions.

It is important to note that the SMC64 flavor of SYSTEM_RESET2
is unintentionally allowed for AArch32 guests without this change.

Signed-off-by: Oliver Upton <oupton@google.com>
Reviewed-by: Reiji Watanabe <reijiw@google.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
---
 arch/arm64/kvm/psci.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
index a433c3eac9b7..cd3ee947485f 100644
--- a/arch/arm64/kvm/psci.c
+++ b/arch/arm64/kvm/psci.c
@@ -216,15 +216,11 @@ static void kvm_psci_narrow_to_32bit(struct kvm_vcpu *vcpu)
 
 static unsigned long kvm_psci_check_allowed_function(struct kvm_vcpu *vcpu, u32 fn)
 {
-	switch(fn) {
-	case PSCI_0_2_FN64_CPU_SUSPEND:
-	case PSCI_0_2_FN64_CPU_ON:
-	case PSCI_0_2_FN64_AFFINITY_INFO:
-		/* Disallow these functions for 32bit guests */
-		if (vcpu_mode_is_32bit(vcpu))
-			return PSCI_RET_NOT_SUPPORTED;
-		break;
-	}
+	/*
+	 * Prevent 32 bit guests from calling 64 bit PSCI functions.
+	 */
+	if ((fn & PSCI_0_2_64BIT) && vcpu_mode_is_32bit(vcpu))
+		return PSCI_RET_NOT_SUPPORTED;
 
 	return 0;
 }
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 02/15] KVM: arm64: Generally disallow SMC64 for AArch32 guests
@ 2022-03-11 17:39   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: maz, wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

The only valid calling SMC calling convention from an AArch32 state is
SMC32. Disallow any PSCI function that sets the SMC64 function ID bit
when called from AArch32 rather than comparing against known SMC64 PSCI
functions.

It is important to note that the SMC64 flavor of SYSTEM_RESET2
is unintentionally allowed for AArch32 guests without this change.

Signed-off-by: Oliver Upton <oupton@google.com>
Reviewed-by: Reiji Watanabe <reijiw@google.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
---
 arch/arm64/kvm/psci.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
index a433c3eac9b7..cd3ee947485f 100644
--- a/arch/arm64/kvm/psci.c
+++ b/arch/arm64/kvm/psci.c
@@ -216,15 +216,11 @@ static void kvm_psci_narrow_to_32bit(struct kvm_vcpu *vcpu)
 
 static unsigned long kvm_psci_check_allowed_function(struct kvm_vcpu *vcpu, u32 fn)
 {
-	switch(fn) {
-	case PSCI_0_2_FN64_CPU_SUSPEND:
-	case PSCI_0_2_FN64_CPU_ON:
-	case PSCI_0_2_FN64_AFFINITY_INFO:
-		/* Disallow these functions for 32bit guests */
-		if (vcpu_mode_is_32bit(vcpu))
-			return PSCI_RET_NOT_SUPPORTED;
-		break;
-	}
+	/*
+	 * Prevent 32 bit guests from calling 64 bit PSCI functions.
+	 */
+	if ((fn & PSCI_0_2_64BIT) && vcpu_mode_is_32bit(vcpu))
+		return PSCI_RET_NOT_SUPPORTED;
 
 	return 0;
 }
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 03/15] KVM: arm64: Don't depend on fallthrough to hide SYSTEM_RESET2
  2022-03-11 17:39 ` Oliver Upton
@ 2022-03-11 17:39   ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: alexandru.elisei, anup, atishp, james.morse, jingzhangos,
	jmattson, joro, kvm-riscv, kvm, maz, pbonzini, pshier, rananta,
	reijiw, ricarkol, seanjc, suzuki.poulose, vkuznets, wanpengli,
	Oliver Upton

Depending on a fallthrough to the default case for hiding SYSTEM_RESET2
requires that any new case statements clean up the failure path for this
PSCI call.

Unhitch SYSTEM_RESET2 from the default case by setting val to
PSCI_RET_NOT_SUPPORTED outside of the switch statement. Apply the
cleanup to both the PSCI_1_1_FN_SYSTEM_RESET2 and
PSCI_1_0_FN_PSCI_FEATURES handlers.

No functional change intended.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 arch/arm64/kvm/psci.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
index cd3ee947485f..2a228744d0c4 100644
--- a/arch/arm64/kvm/psci.c
+++ b/arch/arm64/kvm/psci.c
@@ -310,9 +310,9 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 
 static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
 {
+	unsigned long val = PSCI_RET_NOT_SUPPORTED;
 	u32 psci_fn = smccc_get_function(vcpu);
 	u32 arg;
-	unsigned long val;
 	int ret = 1;
 
 	if (minor > 1)
@@ -328,6 +328,8 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
 		if (val)
 			break;
 
+		val = PSCI_RET_NOT_SUPPORTED;
+
 		switch(arg) {
 		case PSCI_0_2_FN_PSCI_VERSION:
 		case PSCI_0_2_FN_CPU_SUSPEND:
@@ -346,13 +348,8 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
 			break;
 		case PSCI_1_1_FN_SYSTEM_RESET2:
 		case PSCI_1_1_FN64_SYSTEM_RESET2:
-			if (minor >= 1) {
+			if (minor >= 1)
 				val = 0;
-				break;
-			}
-			fallthrough;
-		default:
-			val = PSCI_RET_NOT_SUPPORTED;
 			break;
 		}
 		break;
@@ -373,7 +370,7 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
 			val = PSCI_RET_INVALID_PARAMS;
 			break;
 		}
-		fallthrough;
+		break;
 	default:
 		return kvm_psci_0_2_call(vcpu);
 	}
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 03/15] KVM: arm64: Don't depend on fallthrough to hide SYSTEM_RESET2
@ 2022-03-11 17:39   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: maz, wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

Depending on a fallthrough to the default case for hiding SYSTEM_RESET2
requires that any new case statements clean up the failure path for this
PSCI call.

Unhitch SYSTEM_RESET2 from the default case by setting val to
PSCI_RET_NOT_SUPPORTED outside of the switch statement. Apply the
cleanup to both the PSCI_1_1_FN_SYSTEM_RESET2 and
PSCI_1_0_FN_PSCI_FEATURES handlers.

No functional change intended.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 arch/arm64/kvm/psci.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
index cd3ee947485f..2a228744d0c4 100644
--- a/arch/arm64/kvm/psci.c
+++ b/arch/arm64/kvm/psci.c
@@ -310,9 +310,9 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 
 static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
 {
+	unsigned long val = PSCI_RET_NOT_SUPPORTED;
 	u32 psci_fn = smccc_get_function(vcpu);
 	u32 arg;
-	unsigned long val;
 	int ret = 1;
 
 	if (minor > 1)
@@ -328,6 +328,8 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
 		if (val)
 			break;
 
+		val = PSCI_RET_NOT_SUPPORTED;
+
 		switch(arg) {
 		case PSCI_0_2_FN_PSCI_VERSION:
 		case PSCI_0_2_FN_CPU_SUSPEND:
@@ -346,13 +348,8 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
 			break;
 		case PSCI_1_1_FN_SYSTEM_RESET2:
 		case PSCI_1_1_FN64_SYSTEM_RESET2:
-			if (minor >= 1) {
+			if (minor >= 1)
 				val = 0;
-				break;
-			}
-			fallthrough;
-		default:
-			val = PSCI_RET_NOT_SUPPORTED;
 			break;
 		}
 		break;
@@ -373,7 +370,7 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
 			val = PSCI_RET_INVALID_PARAMS;
 			break;
 		}
-		fallthrough;
+		break;
 	default:
 		return kvm_psci_0_2_call(vcpu);
 	}
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 04/15] KVM: arm64: Dedupe vCPU power off helpers
  2022-03-11 17:39 ` Oliver Upton
@ 2022-03-11 17:39   ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: alexandru.elisei, anup, atishp, james.morse, jingzhangos,
	jmattson, joro, kvm-riscv, kvm, maz, pbonzini, pshier, rananta,
	reijiw, ricarkol, seanjc, suzuki.poulose, vkuznets, wanpengli,
	Oliver Upton

vcpu_power_off() and kvm_psci_vcpu_off() are equivalent; rename the
former and replace all callsites to the latter.

No functional change intended.

Signed-off-by: Oliver Upton <oupton@google.com>
Reviewed-by: Reiji Watanabe <reijiw@google.com>
---
 arch/arm64/include/asm/kvm_host.h |  2 ++
 arch/arm64/kvm/arm.c              |  6 +++---
 arch/arm64/kvm/psci.c             | 11 ++---------
 3 files changed, 7 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 0e96087885fe..a2e00129cf4b 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -826,4 +826,6 @@ void __init kvm_hyp_reserve(void);
 static inline void kvm_hyp_reserve(void) { }
 #endif
 
+void kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu);
+
 #endif /* __ARM64_KVM_HOST_H__ */
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 17021bc8ee2c..0b71c0a27a20 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -432,7 +432,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 	vcpu->cpu = -1;
 }
 
-static void vcpu_power_off(struct kvm_vcpu *vcpu)
+void kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu)
 {
 	vcpu->arch.power_off = true;
 	kvm_make_request(KVM_REQ_SLEEP, vcpu);
@@ -460,7 +460,7 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
 		vcpu->arch.power_off = false;
 		break;
 	case KVM_MP_STATE_STOPPED:
-		vcpu_power_off(vcpu);
+		kvm_arm_vcpu_power_off(vcpu);
 		break;
 	default:
 		ret = -EINVAL;
@@ -1124,7 +1124,7 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
 	 * Handle the "start in power-off" case.
 	 */
 	if (test_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features))
-		vcpu_power_off(vcpu);
+		kvm_arm_vcpu_power_off(vcpu);
 	else
 		vcpu->arch.power_off = false;
 
diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
index 2a228744d0c4..f5c865485f09 100644
--- a/arch/arm64/kvm/psci.c
+++ b/arch/arm64/kvm/psci.c
@@ -52,13 +52,6 @@ static unsigned long kvm_psci_vcpu_suspend(struct kvm_vcpu *vcpu)
 	return PSCI_RET_SUCCESS;
 }
 
-static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
-{
-	vcpu->arch.power_off = true;
-	kvm_make_request(KVM_REQ_SLEEP, vcpu);
-	kvm_vcpu_kick(vcpu);
-}
-
 static inline bool kvm_psci_valid_affinity(struct kvm_vcpu *vcpu,
 					   unsigned long affinity)
 {
@@ -249,7 +242,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 		val = kvm_psci_vcpu_suspend(vcpu);
 		break;
 	case PSCI_0_2_FN_CPU_OFF:
-		kvm_psci_vcpu_off(vcpu);
+		kvm_arm_vcpu_power_off(vcpu);
 		val = PSCI_RET_SUCCESS;
 		break;
 	case PSCI_0_2_FN_CPU_ON:
@@ -387,7 +380,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 
 	switch (psci_fn) {
 	case KVM_PSCI_FN_CPU_OFF:
-		kvm_psci_vcpu_off(vcpu);
+		kvm_arm_vcpu_power_off(vcpu);
 		val = PSCI_RET_SUCCESS;
 		break;
 	case KVM_PSCI_FN_CPU_ON:
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 04/15] KVM: arm64: Dedupe vCPU power off helpers
@ 2022-03-11 17:39   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: maz, wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

vcpu_power_off() and kvm_psci_vcpu_off() are equivalent; rename the
former and replace all callsites to the latter.

No functional change intended.

Signed-off-by: Oliver Upton <oupton@google.com>
Reviewed-by: Reiji Watanabe <reijiw@google.com>
---
 arch/arm64/include/asm/kvm_host.h |  2 ++
 arch/arm64/kvm/arm.c              |  6 +++---
 arch/arm64/kvm/psci.c             | 11 ++---------
 3 files changed, 7 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 0e96087885fe..a2e00129cf4b 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -826,4 +826,6 @@ void __init kvm_hyp_reserve(void);
 static inline void kvm_hyp_reserve(void) { }
 #endif
 
+void kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu);
+
 #endif /* __ARM64_KVM_HOST_H__ */
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 17021bc8ee2c..0b71c0a27a20 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -432,7 +432,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 	vcpu->cpu = -1;
 }
 
-static void vcpu_power_off(struct kvm_vcpu *vcpu)
+void kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu)
 {
 	vcpu->arch.power_off = true;
 	kvm_make_request(KVM_REQ_SLEEP, vcpu);
@@ -460,7 +460,7 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
 		vcpu->arch.power_off = false;
 		break;
 	case KVM_MP_STATE_STOPPED:
-		vcpu_power_off(vcpu);
+		kvm_arm_vcpu_power_off(vcpu);
 		break;
 	default:
 		ret = -EINVAL;
@@ -1124,7 +1124,7 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
 	 * Handle the "start in power-off" case.
 	 */
 	if (test_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features))
-		vcpu_power_off(vcpu);
+		kvm_arm_vcpu_power_off(vcpu);
 	else
 		vcpu->arch.power_off = false;
 
diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
index 2a228744d0c4..f5c865485f09 100644
--- a/arch/arm64/kvm/psci.c
+++ b/arch/arm64/kvm/psci.c
@@ -52,13 +52,6 @@ static unsigned long kvm_psci_vcpu_suspend(struct kvm_vcpu *vcpu)
 	return PSCI_RET_SUCCESS;
 }
 
-static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
-{
-	vcpu->arch.power_off = true;
-	kvm_make_request(KVM_REQ_SLEEP, vcpu);
-	kvm_vcpu_kick(vcpu);
-}
-
 static inline bool kvm_psci_valid_affinity(struct kvm_vcpu *vcpu,
 					   unsigned long affinity)
 {
@@ -249,7 +242,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu)
 		val = kvm_psci_vcpu_suspend(vcpu);
 		break;
 	case PSCI_0_2_FN_CPU_OFF:
-		kvm_psci_vcpu_off(vcpu);
+		kvm_arm_vcpu_power_off(vcpu);
 		val = PSCI_RET_SUCCESS;
 		break;
 	case PSCI_0_2_FN_CPU_ON:
@@ -387,7 +380,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
 
 	switch (psci_fn) {
 	case KVM_PSCI_FN_CPU_OFF:
-		kvm_psci_vcpu_off(vcpu);
+		kvm_arm_vcpu_power_off(vcpu);
 		val = PSCI_RET_SUCCESS;
 		break;
 	case KVM_PSCI_FN_CPU_ON:
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 05/15] KVM: arm64: Track vCPU power state using MP state values
  2022-03-11 17:39 ` Oliver Upton
@ 2022-03-11 17:39   ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: alexandru.elisei, anup, atishp, james.morse, jingzhangos,
	jmattson, joro, kvm-riscv, kvm, maz, pbonzini, pshier, rananta,
	reijiw, ricarkol, seanjc, suzuki.poulose, vkuznets, wanpengli,
	Oliver Upton

A subsequent change to KVM will add support for additional power states.
Store the MP state by value rather than keeping track of it as a
boolean.

No functional change intended.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 arch/arm64/include/asm/kvm_host.h |  5 +++--
 arch/arm64/kvm/arm.c              | 22 ++++++++++++----------
 arch/arm64/kvm/psci.c             | 12 ++++++------
 3 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index a2e00129cf4b..da58eb96d2a8 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -355,8 +355,8 @@ struct kvm_vcpu_arch {
 		u32	mdscr_el1;
 	} guest_debug_preserved;
 
-	/* vcpu power-off state */
-	bool power_off;
+	/* vcpu power state */
+	struct kvm_mp_state mp_state;
 
 	/* Don't run the guest (internal implementation need) */
 	bool pause;
@@ -827,5 +827,6 @@ static inline void kvm_hyp_reserve(void) { }
 #endif
 
 void kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu);
+bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu);
 
 #endif /* __ARM64_KVM_HOST_H__ */
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 0b71c0a27a20..3918d078fc4d 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -434,18 +434,20 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 
 void kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu)
 {
-	vcpu->arch.power_off = true;
+	vcpu->arch.mp_state.mp_state = KVM_MP_STATE_STOPPED;
 	kvm_make_request(KVM_REQ_SLEEP, vcpu);
 	kvm_vcpu_kick(vcpu);
 }
 
+bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_STOPPED;
+}
+
 int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
 				    struct kvm_mp_state *mp_state)
 {
-	if (vcpu->arch.power_off)
-		mp_state->mp_state = KVM_MP_STATE_STOPPED;
-	else
-		mp_state->mp_state = KVM_MP_STATE_RUNNABLE;
+	*mp_state = vcpu->arch.mp_state;
 
 	return 0;
 }
@@ -457,7 +459,7 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
 
 	switch (mp_state->mp_state) {
 	case KVM_MP_STATE_RUNNABLE:
-		vcpu->arch.power_off = false;
+		vcpu->arch.mp_state = *mp_state;
 		break;
 	case KVM_MP_STATE_STOPPED:
 		kvm_arm_vcpu_power_off(vcpu);
@@ -480,7 +482,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
 {
 	bool irq_lines = *vcpu_hcr(v) & (HCR_VI | HCR_VF);
 	return ((irq_lines || kvm_vgic_vcpu_pending_irq(v))
-		&& !v->arch.power_off && !v->arch.pause);
+		&& !kvm_arm_vcpu_stopped(v) && !v->arch.pause);
 }
 
 bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
@@ -597,10 +599,10 @@ static void vcpu_req_sleep(struct kvm_vcpu *vcpu)
 	struct rcuwait *wait = kvm_arch_vcpu_get_wait(vcpu);
 
 	rcuwait_wait_event(wait,
-			   (!vcpu->arch.power_off) &&(!vcpu->arch.pause),
+			   (!kvm_arm_vcpu_stopped(vcpu)) && (!vcpu->arch.pause),
 			   TASK_INTERRUPTIBLE);
 
-	if (vcpu->arch.power_off || vcpu->arch.pause) {
+	if (kvm_arm_vcpu_stopped(vcpu) || vcpu->arch.pause) {
 		/* Awaken to handle a signal, request we sleep again later. */
 		kvm_make_request(KVM_REQ_SLEEP, vcpu);
 	}
@@ -1126,7 +1128,7 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
 	if (test_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features))
 		kvm_arm_vcpu_power_off(vcpu);
 	else
-		vcpu->arch.power_off = false;
+		vcpu->arch.mp_state.mp_state = KVM_MP_STATE_RUNNABLE;
 
 	return 0;
 }
diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
index f5c865485f09..efd4428fda1c 100644
--- a/arch/arm64/kvm/psci.c
+++ b/arch/arm64/kvm/psci.c
@@ -77,7 +77,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 	 */
 	if (!vcpu)
 		return PSCI_RET_INVALID_PARAMS;
-	if (!vcpu->arch.power_off) {
+	if (!kvm_arm_vcpu_stopped(vcpu)) {
 		if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1)
 			return PSCI_RET_ALREADY_ON;
 		else
@@ -101,12 +101,12 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 	kvm_make_request(KVM_REQ_VCPU_RESET, vcpu);
 
 	/*
-	 * Make sure the reset request is observed if the change to
-	 * power_off is observed.
+	 * Make sure the reset request is observed if the RUNNABLE mp_state is
+	 * observed.
 	 */
 	smp_wmb();
 
-	vcpu->arch.power_off = false;
+	vcpu->arch.mp_state.mp_state = KVM_MP_STATE_RUNNABLE;
 	kvm_vcpu_wake_up(vcpu);
 
 	return PSCI_RET_SUCCESS;
@@ -144,7 +144,7 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)
 		mpidr = kvm_vcpu_get_mpidr_aff(tmp);
 		if ((mpidr & target_affinity_mask) == target_affinity) {
 			matching_cpus++;
-			if (!tmp->arch.power_off)
+			if (!kvm_arm_vcpu_stopped(tmp))
 				return PSCI_0_2_AFFINITY_LEVEL_ON;
 		}
 	}
@@ -170,7 +170,7 @@ static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type, u64 flags)
 	 * re-initialized.
 	 */
 	kvm_for_each_vcpu(i, tmp, vcpu->kvm)
-		tmp->arch.power_off = true;
+		tmp->arch.mp_state.mp_state = KVM_MP_STATE_STOPPED;
 	kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
 
 	memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 05/15] KVM: arm64: Track vCPU power state using MP state values
@ 2022-03-11 17:39   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: maz, wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

A subsequent change to KVM will add support for additional power states.
Store the MP state by value rather than keeping track of it as a
boolean.

No functional change intended.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 arch/arm64/include/asm/kvm_host.h |  5 +++--
 arch/arm64/kvm/arm.c              | 22 ++++++++++++----------
 arch/arm64/kvm/psci.c             | 12 ++++++------
 3 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index a2e00129cf4b..da58eb96d2a8 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -355,8 +355,8 @@ struct kvm_vcpu_arch {
 		u32	mdscr_el1;
 	} guest_debug_preserved;
 
-	/* vcpu power-off state */
-	bool power_off;
+	/* vcpu power state */
+	struct kvm_mp_state mp_state;
 
 	/* Don't run the guest (internal implementation need) */
 	bool pause;
@@ -827,5 +827,6 @@ static inline void kvm_hyp_reserve(void) { }
 #endif
 
 void kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu);
+bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu);
 
 #endif /* __ARM64_KVM_HOST_H__ */
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 0b71c0a27a20..3918d078fc4d 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -434,18 +434,20 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 
 void kvm_arm_vcpu_power_off(struct kvm_vcpu *vcpu)
 {
-	vcpu->arch.power_off = true;
+	vcpu->arch.mp_state.mp_state = KVM_MP_STATE_STOPPED;
 	kvm_make_request(KVM_REQ_SLEEP, vcpu);
 	kvm_vcpu_kick(vcpu);
 }
 
+bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_STOPPED;
+}
+
 int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
 				    struct kvm_mp_state *mp_state)
 {
-	if (vcpu->arch.power_off)
-		mp_state->mp_state = KVM_MP_STATE_STOPPED;
-	else
-		mp_state->mp_state = KVM_MP_STATE_RUNNABLE;
+	*mp_state = vcpu->arch.mp_state;
 
 	return 0;
 }
@@ -457,7 +459,7 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
 
 	switch (mp_state->mp_state) {
 	case KVM_MP_STATE_RUNNABLE:
-		vcpu->arch.power_off = false;
+		vcpu->arch.mp_state = *mp_state;
 		break;
 	case KVM_MP_STATE_STOPPED:
 		kvm_arm_vcpu_power_off(vcpu);
@@ -480,7 +482,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
 {
 	bool irq_lines = *vcpu_hcr(v) & (HCR_VI | HCR_VF);
 	return ((irq_lines || kvm_vgic_vcpu_pending_irq(v))
-		&& !v->arch.power_off && !v->arch.pause);
+		&& !kvm_arm_vcpu_stopped(v) && !v->arch.pause);
 }
 
 bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
@@ -597,10 +599,10 @@ static void vcpu_req_sleep(struct kvm_vcpu *vcpu)
 	struct rcuwait *wait = kvm_arch_vcpu_get_wait(vcpu);
 
 	rcuwait_wait_event(wait,
-			   (!vcpu->arch.power_off) &&(!vcpu->arch.pause),
+			   (!kvm_arm_vcpu_stopped(vcpu)) && (!vcpu->arch.pause),
 			   TASK_INTERRUPTIBLE);
 
-	if (vcpu->arch.power_off || vcpu->arch.pause) {
+	if (kvm_arm_vcpu_stopped(vcpu) || vcpu->arch.pause) {
 		/* Awaken to handle a signal, request we sleep again later. */
 		kvm_make_request(KVM_REQ_SLEEP, vcpu);
 	}
@@ -1126,7 +1128,7 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
 	if (test_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features))
 		kvm_arm_vcpu_power_off(vcpu);
 	else
-		vcpu->arch.power_off = false;
+		vcpu->arch.mp_state.mp_state = KVM_MP_STATE_RUNNABLE;
 
 	return 0;
 }
diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
index f5c865485f09..efd4428fda1c 100644
--- a/arch/arm64/kvm/psci.c
+++ b/arch/arm64/kvm/psci.c
@@ -77,7 +77,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 	 */
 	if (!vcpu)
 		return PSCI_RET_INVALID_PARAMS;
-	if (!vcpu->arch.power_off) {
+	if (!kvm_arm_vcpu_stopped(vcpu)) {
 		if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1)
 			return PSCI_RET_ALREADY_ON;
 		else
@@ -101,12 +101,12 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 	kvm_make_request(KVM_REQ_VCPU_RESET, vcpu);
 
 	/*
-	 * Make sure the reset request is observed if the change to
-	 * power_off is observed.
+	 * Make sure the reset request is observed if the RUNNABLE mp_state is
+	 * observed.
 	 */
 	smp_wmb();
 
-	vcpu->arch.power_off = false;
+	vcpu->arch.mp_state.mp_state = KVM_MP_STATE_RUNNABLE;
 	kvm_vcpu_wake_up(vcpu);
 
 	return PSCI_RET_SUCCESS;
@@ -144,7 +144,7 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)
 		mpidr = kvm_vcpu_get_mpidr_aff(tmp);
 		if ((mpidr & target_affinity_mask) == target_affinity) {
 			matching_cpus++;
-			if (!tmp->arch.power_off)
+			if (!kvm_arm_vcpu_stopped(tmp))
 				return PSCI_0_2_AFFINITY_LEVEL_ON;
 		}
 	}
@@ -170,7 +170,7 @@ static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type, u64 flags)
 	 * re-initialized.
 	 */
 	kvm_for_each_vcpu(i, tmp, vcpu->kvm)
-		tmp->arch.power_off = true;
+		tmp->arch.mp_state.mp_state = KVM_MP_STATE_STOPPED;
 	kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
 
 	memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 06/15] KVM: arm64: Rename the KVM_REQ_SLEEP handler
  2022-03-11 17:39 ` Oliver Upton
@ 2022-03-11 17:39   ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: alexandru.elisei, anup, atishp, james.morse, jingzhangos,
	jmattson, joro, kvm-riscv, kvm, maz, pbonzini, pshier, rananta,
	reijiw, ricarkol, seanjc, suzuki.poulose, vkuznets, wanpengli,
	Oliver Upton, Andrew Jones

The naming of the kvm_req_sleep function is confusing: the function
itself sleeps the vCPU, it does not request such an event. Rename the
function to make its purpose more clear.

No functional change intended.

Signed-off-by: Oliver Upton <oupton@google.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
---
 arch/arm64/kvm/arm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 3918d078fc4d..7c297ddc8177 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -594,7 +594,7 @@ void kvm_arm_resume_guest(struct kvm *kvm)
 	}
 }
 
-static void vcpu_req_sleep(struct kvm_vcpu *vcpu)
+static void kvm_vcpu_sleep(struct kvm_vcpu *vcpu)
 {
 	struct rcuwait *wait = kvm_arch_vcpu_get_wait(vcpu);
 
@@ -652,7 +652,7 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu)
 {
 	if (kvm_request_pending(vcpu)) {
 		if (kvm_check_request(KVM_REQ_SLEEP, vcpu))
-			vcpu_req_sleep(vcpu);
+			kvm_vcpu_sleep(vcpu);
 
 		if (kvm_check_request(KVM_REQ_VCPU_RESET, vcpu))
 			kvm_reset_vcpu(vcpu);
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 06/15] KVM: arm64: Rename the KVM_REQ_SLEEP handler
@ 2022-03-11 17:39   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: maz, wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

The naming of the kvm_req_sleep function is confusing: the function
itself sleeps the vCPU, it does not request such an event. Rename the
function to make its purpose more clear.

No functional change intended.

Signed-off-by: Oliver Upton <oupton@google.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
---
 arch/arm64/kvm/arm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 3918d078fc4d..7c297ddc8177 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -594,7 +594,7 @@ void kvm_arm_resume_guest(struct kvm *kvm)
 	}
 }
 
-static void vcpu_req_sleep(struct kvm_vcpu *vcpu)
+static void kvm_vcpu_sleep(struct kvm_vcpu *vcpu)
 {
 	struct rcuwait *wait = kvm_arch_vcpu_get_wait(vcpu);
 
@@ -652,7 +652,7 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu)
 {
 	if (kvm_request_pending(vcpu)) {
 		if (kvm_check_request(KVM_REQ_SLEEP, vcpu))
-			vcpu_req_sleep(vcpu);
+			kvm_vcpu_sleep(vcpu);
 
 		if (kvm_check_request(KVM_REQ_VCPU_RESET, vcpu))
 			kvm_reset_vcpu(vcpu);
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 07/15] KVM: Create helper for setting a system event exit
  2022-03-11 17:39 ` Oliver Upton
@ 2022-03-11 17:39   ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: alexandru.elisei, anup, atishp, james.morse, jingzhangos,
	jmattson, joro, kvm-riscv, kvm, maz, pbonzini, pshier, rananta,
	reijiw, ricarkol, seanjc, suzuki.poulose, vkuznets, wanpengli,
	Oliver Upton

Create a helper that appropriately configures kvm_run for a system event
exit.

No functional change intended.

Suggested-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Oliver Upton <oupton@google.com>
Acked-by: Anup Patel <anup@brainfault.org>
---
 arch/arm64/kvm/psci.c         | 5 +----
 arch/riscv/kvm/vcpu_sbi_v01.c | 4 +---
 arch/x86/kvm/x86.c            | 6 ++----
 include/linux/kvm_host.h      | 2 ++
 virt/kvm/kvm_main.c           | 8 ++++++++
 5 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
index efd4428fda1c..78266716165e 100644
--- a/arch/arm64/kvm/psci.c
+++ b/arch/arm64/kvm/psci.c
@@ -173,10 +173,7 @@ static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type, u64 flags)
 		tmp->arch.mp_state.mp_state = KVM_MP_STATE_STOPPED;
 	kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
 
-	memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
-	vcpu->run->system_event.type = type;
-	vcpu->run->system_event.flags = flags;
-	vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
+	kvm_vcpu_set_system_event_exit(vcpu, type, flags);
 }
 
 static void kvm_psci_system_off(struct kvm_vcpu *vcpu)
diff --git a/arch/riscv/kvm/vcpu_sbi_v01.c b/arch/riscv/kvm/vcpu_sbi_v01.c
index 07e2de14433a..c5581008dd88 100644
--- a/arch/riscv/kvm/vcpu_sbi_v01.c
+++ b/arch/riscv/kvm/vcpu_sbi_v01.c
@@ -24,9 +24,7 @@ static void kvm_sbi_system_shutdown(struct kvm_vcpu *vcpu,
 		tmp->arch.power_off = true;
 	kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
 
-	memset(&run->system_event, 0, sizeof(run->system_event));
-	run->system_event.type = type;
-	run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
+	kvm_vcpu_set_system_event_exit(vcpu, type, 0);
 }
 
 static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 7131d735b1ef..b3b94408cc61 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -9903,14 +9903,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 		if (kvm_check_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu))
 			kvm_vcpu_reload_apic_access_page(vcpu);
 		if (kvm_check_request(KVM_REQ_HV_CRASH, vcpu)) {
-			vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
-			vcpu->run->system_event.type = KVM_SYSTEM_EVENT_CRASH;
+			kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_CRASH, 0);
 			r = 0;
 			goto out;
 		}
 		if (kvm_check_request(KVM_REQ_HV_RESET, vcpu)) {
-			vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
-			vcpu->run->system_event.type = KVM_SYSTEM_EVENT_RESET;
+			kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_RESET, 0);
 			r = 0;
 			goto out;
 		}
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index f11039944c08..c2a4fd2382e2 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -2202,6 +2202,8 @@ static inline void kvm_handle_signal_exit(struct kvm_vcpu *vcpu)
 }
 #endif /* CONFIG_KVM_XFER_TO_GUEST_WORK */
 
+void kvm_vcpu_set_system_event_exit(struct kvm_vcpu *vcpu, u32 type, u64 flags);
+
 /*
  * This defines how many reserved entries we want to keep before we
  * kick the vcpu to the userspace to avoid dirty ring full.  This
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 58d31da8a2f7..197bae04ca34 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -3194,6 +3194,14 @@ void kvm_vcpu_mark_page_dirty(struct kvm_vcpu *vcpu, gfn_t gfn)
 }
 EXPORT_SYMBOL_GPL(kvm_vcpu_mark_page_dirty);
 
+void kvm_vcpu_set_system_event_exit(struct kvm_vcpu *vcpu, u32 type, u64 flags)
+{
+	memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
+	vcpu->run->system_event.type = type;
+	vcpu->run->system_event.flags = flags;
+	vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
+}
+
 void kvm_sigset_activate(struct kvm_vcpu *vcpu)
 {
 	if (!vcpu->sigset_active)
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 07/15] KVM: Create helper for setting a system event exit
@ 2022-03-11 17:39   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: maz, wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

Create a helper that appropriately configures kvm_run for a system event
exit.

No functional change intended.

Suggested-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Oliver Upton <oupton@google.com>
Acked-by: Anup Patel <anup@brainfault.org>
---
 arch/arm64/kvm/psci.c         | 5 +----
 arch/riscv/kvm/vcpu_sbi_v01.c | 4 +---
 arch/x86/kvm/x86.c            | 6 ++----
 include/linux/kvm_host.h      | 2 ++
 virt/kvm/kvm_main.c           | 8 ++++++++
 5 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
index efd4428fda1c..78266716165e 100644
--- a/arch/arm64/kvm/psci.c
+++ b/arch/arm64/kvm/psci.c
@@ -173,10 +173,7 @@ static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type, u64 flags)
 		tmp->arch.mp_state.mp_state = KVM_MP_STATE_STOPPED;
 	kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
 
-	memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
-	vcpu->run->system_event.type = type;
-	vcpu->run->system_event.flags = flags;
-	vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
+	kvm_vcpu_set_system_event_exit(vcpu, type, flags);
 }
 
 static void kvm_psci_system_off(struct kvm_vcpu *vcpu)
diff --git a/arch/riscv/kvm/vcpu_sbi_v01.c b/arch/riscv/kvm/vcpu_sbi_v01.c
index 07e2de14433a..c5581008dd88 100644
--- a/arch/riscv/kvm/vcpu_sbi_v01.c
+++ b/arch/riscv/kvm/vcpu_sbi_v01.c
@@ -24,9 +24,7 @@ static void kvm_sbi_system_shutdown(struct kvm_vcpu *vcpu,
 		tmp->arch.power_off = true;
 	kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
 
-	memset(&run->system_event, 0, sizeof(run->system_event));
-	run->system_event.type = type;
-	run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
+	kvm_vcpu_set_system_event_exit(vcpu, type, 0);
 }
 
 static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 7131d735b1ef..b3b94408cc61 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -9903,14 +9903,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 		if (kvm_check_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu))
 			kvm_vcpu_reload_apic_access_page(vcpu);
 		if (kvm_check_request(KVM_REQ_HV_CRASH, vcpu)) {
-			vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
-			vcpu->run->system_event.type = KVM_SYSTEM_EVENT_CRASH;
+			kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_CRASH, 0);
 			r = 0;
 			goto out;
 		}
 		if (kvm_check_request(KVM_REQ_HV_RESET, vcpu)) {
-			vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
-			vcpu->run->system_event.type = KVM_SYSTEM_EVENT_RESET;
+			kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_RESET, 0);
 			r = 0;
 			goto out;
 		}
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index f11039944c08..c2a4fd2382e2 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -2202,6 +2202,8 @@ static inline void kvm_handle_signal_exit(struct kvm_vcpu *vcpu)
 }
 #endif /* CONFIG_KVM_XFER_TO_GUEST_WORK */
 
+void kvm_vcpu_set_system_event_exit(struct kvm_vcpu *vcpu, u32 type, u64 flags);
+
 /*
  * This defines how many reserved entries we want to keep before we
  * kick the vcpu to the userspace to avoid dirty ring full.  This
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 58d31da8a2f7..197bae04ca34 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -3194,6 +3194,14 @@ void kvm_vcpu_mark_page_dirty(struct kvm_vcpu *vcpu, gfn_t gfn)
 }
 EXPORT_SYMBOL_GPL(kvm_vcpu_mark_page_dirty);
 
+void kvm_vcpu_set_system_event_exit(struct kvm_vcpu *vcpu, u32 type, u64 flags)
+{
+	memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
+	vcpu->run->system_event.type = type;
+	vcpu->run->system_event.flags = flags;
+	vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
+}
+
 void kvm_sigset_activate(struct kvm_vcpu *vcpu)
 {
 	if (!vcpu->sigset_active)
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 08/15] KVM: arm64: Return a value from check_vcpu_requests()
  2022-03-11 17:39 ` Oliver Upton
@ 2022-03-11 17:39   ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: alexandru.elisei, anup, atishp, james.morse, jingzhangos,
	jmattson, joro, kvm-riscv, kvm, maz, pbonzini, pshier, rananta,
	reijiw, ricarkol, seanjc, suzuki.poulose, vkuznets, wanpengli,
	Oliver Upton

A subsequent change to KVM will introduce a vCPU request that could
result in an exit to userspace. Change check_vcpu_requests() to return a
value and document the function. Unconditionally return 1 for now.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 arch/arm64/kvm/arm.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 7c297ddc8177..8eed0556ccaa 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -648,7 +648,16 @@ void kvm_vcpu_wfi(struct kvm_vcpu *vcpu)
 	preempt_enable();
 }
 
-static void check_vcpu_requests(struct kvm_vcpu *vcpu)
+/**
+ * check_vcpu_requests - check and handle pending vCPU requests
+ * @vcpu:	the VCPU pointer
+ *
+ * Return: 1 if we should enter the guest
+ *	   0 if we should exit to userspace
+ *	   <= 0 if we should exit to userspace, where the return value indicates
+ *	   an error
+ */
+static int check_vcpu_requests(struct kvm_vcpu *vcpu)
 {
 	if (kvm_request_pending(vcpu)) {
 		if (kvm_check_request(KVM_REQ_SLEEP, vcpu))
@@ -678,6 +687,8 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu)
 			kvm_pmu_handle_pmcr(vcpu,
 					    __vcpu_sys_reg(vcpu, PMCR_EL0));
 	}
+
+	return 1;
 }
 
 static bool vcpu_mode_is_bad_32bit(struct kvm_vcpu *vcpu)
@@ -793,7 +804,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
 		if (!ret)
 			ret = 1;
 
-		check_vcpu_requests(vcpu);
+		if (ret > 0)
+			ret = check_vcpu_requests(vcpu);
 
 		/*
 		 * Preparing the interrupts to be injected also
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 08/15] KVM: arm64: Return a value from check_vcpu_requests()
@ 2022-03-11 17:39   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: maz, wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

A subsequent change to KVM will introduce a vCPU request that could
result in an exit to userspace. Change check_vcpu_requests() to return a
value and document the function. Unconditionally return 1 for now.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 arch/arm64/kvm/arm.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 7c297ddc8177..8eed0556ccaa 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -648,7 +648,16 @@ void kvm_vcpu_wfi(struct kvm_vcpu *vcpu)
 	preempt_enable();
 }
 
-static void check_vcpu_requests(struct kvm_vcpu *vcpu)
+/**
+ * check_vcpu_requests - check and handle pending vCPU requests
+ * @vcpu:	the VCPU pointer
+ *
+ * Return: 1 if we should enter the guest
+ *	   0 if we should exit to userspace
+ *	   <= 0 if we should exit to userspace, where the return value indicates
+ *	   an error
+ */
+static int check_vcpu_requests(struct kvm_vcpu *vcpu)
 {
 	if (kvm_request_pending(vcpu)) {
 		if (kvm_check_request(KVM_REQ_SLEEP, vcpu))
@@ -678,6 +687,8 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu)
 			kvm_pmu_handle_pmcr(vcpu,
 					    __vcpu_sys_reg(vcpu, PMCR_EL0));
 	}
+
+	return 1;
 }
 
 static bool vcpu_mode_is_bad_32bit(struct kvm_vcpu *vcpu)
@@ -793,7 +804,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
 		if (!ret)
 			ret = 1;
 
-		check_vcpu_requests(vcpu);
+		if (ret > 0)
+			ret = check_vcpu_requests(vcpu);
 
 		/*
 		 * Preparing the interrupts to be injected also
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 09/15] KVM: arm64: Add support for userspace to suspend a vCPU
  2022-03-11 17:39 ` Oliver Upton
@ 2022-03-11 17:39   ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: alexandru.elisei, anup, atishp, james.morse, jingzhangos,
	jmattson, joro, kvm-riscv, kvm, maz, pbonzini, pshier, rananta,
	reijiw, ricarkol, seanjc, suzuki.poulose, vkuznets, wanpengli,
	Oliver Upton

Introduce a new MP state, KVM_MP_STATE_SUSPENDED, which indicates a vCPU
is in a suspended state. In the suspended state the vCPU will block
until a wakeup event (pending interrupt) is recognized.

Add a new system event type, KVM_SYSTEM_EVENT_WAKEUP, to indicate to
userspace that KVM has recognized one such wakeup event. It is the
responsibility of userspace to then make the vCPU runnable, or leave it
suspended until the next wakeup event.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 Documentation/virt/kvm/api.rst    | 37 +++++++++++++++++++++++++++++--
 arch/arm64/include/asm/kvm_host.h |  1 +
 arch/arm64/kvm/arm.c              | 35 +++++++++++++++++++++++++++++
 include/uapi/linux/kvm.h          |  2 ++
 4 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 5625c08b4a0e..426bcdc1216d 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -1482,14 +1482,43 @@ Possible values are:
                                  [s390]
    KVM_MP_STATE_LOAD             the vcpu is in a special load/startup state
                                  [s390]
+   KVM_MP_STATE_SUSPENDED        the vcpu is in a suspend state and is waiting
+                                 for a wakeup event [arm64]
    ==========================    ===============================================
 
 On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
 in-kernel irqchip, the multiprocessing state must be maintained by userspace on
 these architectures.
 
-For arm64/riscv:
-^^^^^^^^^^^^^^^^
+For arm64:
+^^^^^^^^^^
+
+If a vCPU is in the KVM_MP_STATE_SUSPENDED state, KVM will emulate the
+architectural execution of a WFI instruction.
+
+If a wakeup event is recognized, KVM will exit to userspace with a
+KVM_SYSTEM_EVENT exit, where the event type is KVM_SYSTEM_EVENT_WAKEUP. If
+userspace wants to honor the wakeup, it must set the vCPU's MP state to
+KVM_MP_STATE_RUNNABLE. If it does not, KVM will continue to await a wakeup
+event in subsequent calls to KVM_RUN.
+
+.. warning::
+
+     If userspace intends to keep the vCPU in a SUSPENDED state, it is
+     strongly recommended that userspace take action to suppress the
+     wakeup event (such as masking an interrupt). Otherwise, subsequent
+     calls to KVM_RUN will immediately exit with a KVM_SYSTEM_EVENT_WAKEUP
+     event and inadvertently waste CPU cycles.
+
+     Additionally, if userspace takes action to suppress a wakeup event,
+     it is strongly recommended that it also restore the vCPU to its
+     original state when the vCPU is made RUNNABLE again. For example,
+     if userspace masked a pending interrupt to suppress the wakeup,
+     the interrupt should be unmasked before returning control to the
+     guest.
+
+For riscv:
+^^^^^^^^^^
 
 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.
@@ -5914,6 +5943,7 @@ should put the acknowledged interrupt vector into the 'epr' field.
   #define KVM_SYSTEM_EVENT_SHUTDOWN       1
   #define KVM_SYSTEM_EVENT_RESET          2
   #define KVM_SYSTEM_EVENT_CRASH          3
+  #define KVM_SYSTEM_EVENT_WAKEUP         4
 			__u32 type;
 			__u64 flags;
 		} system_event;
@@ -5938,6 +5968,9 @@ Valid values for 'type' are:
    has requested a crash condition maintenance. Userspace can choose
    to ignore the request, or to gather VM memory core dump and/or
    reset/shutdown of the VM.
+ - KVM_SYSTEM_EVENT_WAKEUP -- the guest is in a suspended state and KVM
+   has recognized a wakeup event. Userspace may honor this event by marking
+   the exiting vCPU as runnable, or deny it and call KVM_RUN again.
 
 Valid flags are:
 
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index da58eb96d2a8..899f2c0b4c7b 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -46,6 +46,7 @@
 #define KVM_REQ_RECORD_STEAL	KVM_ARCH_REQ(3)
 #define KVM_REQ_RELOAD_GICv4	KVM_ARCH_REQ(4)
 #define KVM_REQ_RELOAD_PMU	KVM_ARCH_REQ(5)
+#define KVM_REQ_SUSPEND		KVM_ARCH_REQ(6)
 
 #define KVM_DIRTY_LOG_MANUAL_CAPS   (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
 				     KVM_DIRTY_LOG_INITIALLY_SET)
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 8eed0556ccaa..b94efa05d869 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -444,6 +444,18 @@ bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu)
 	return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_STOPPED;
 }
 
+static void kvm_arm_vcpu_suspend(struct kvm_vcpu *vcpu)
+{
+	vcpu->arch.mp_state.mp_state = KVM_MP_STATE_SUSPENDED;
+	kvm_make_request(KVM_REQ_SUSPEND, vcpu);
+	kvm_vcpu_kick(vcpu);
+}
+
+static bool kvm_arm_vcpu_suspended(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_SUSPENDED;
+}
+
 int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
 				    struct kvm_mp_state *mp_state)
 {
@@ -464,6 +476,9 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
 	case KVM_MP_STATE_STOPPED:
 		kvm_arm_vcpu_power_off(vcpu);
 		break;
+	case KVM_MP_STATE_SUSPENDED:
+		kvm_arm_vcpu_suspend(vcpu);
+		break;
 	default:
 		ret = -EINVAL;
 	}
@@ -648,6 +663,23 @@ void kvm_vcpu_wfi(struct kvm_vcpu *vcpu)
 	preempt_enable();
 }
 
+static int kvm_vcpu_suspend(struct kvm_vcpu *vcpu)
+{
+	if (!kvm_arm_vcpu_suspended(vcpu))
+		return 1;
+
+	kvm_vcpu_wfi(vcpu);
+
+	/*
+	 * The suspend state is sticky; we do not leave it until userspace
+	 * explicitly marks the vCPU as runnable. Request that we suspend again
+	 * later.
+	 */
+	kvm_make_request(KVM_REQ_SUSPEND, vcpu);
+	kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_WAKEUP, 0);
+	return 0;
+}
+
 /**
  * check_vcpu_requests - check and handle pending vCPU requests
  * @vcpu:	the VCPU pointer
@@ -686,6 +718,9 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
 		if (kvm_check_request(KVM_REQ_RELOAD_PMU, vcpu))
 			kvm_pmu_handle_pmcr(vcpu,
 					    __vcpu_sys_reg(vcpu, PMCR_EL0));
+
+		if (kvm_check_request(KVM_REQ_SUSPEND, vcpu))
+			return kvm_vcpu_suspend(vcpu);
 	}
 
 	return 1;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 5191b57e1562..babb16c2abe5 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -444,6 +444,7 @@ struct kvm_run {
 #define KVM_SYSTEM_EVENT_SHUTDOWN       1
 #define KVM_SYSTEM_EVENT_RESET          2
 #define KVM_SYSTEM_EVENT_CRASH          3
+#define KVM_SYSTEM_EVENT_WAKEUP         4
 			__u32 type;
 			__u64 flags;
 		} system_event;
@@ -634,6 +635,7 @@ struct kvm_vapic_addr {
 #define KVM_MP_STATE_OPERATING         7
 #define KVM_MP_STATE_LOAD              8
 #define KVM_MP_STATE_AP_RESET_HOLD     9
+#define KVM_MP_STATE_SUSPENDED         10
 
 struct kvm_mp_state {
 	__u32 mp_state;
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 09/15] KVM: arm64: Add support for userspace to suspend a vCPU
@ 2022-03-11 17:39   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: maz, wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

Introduce a new MP state, KVM_MP_STATE_SUSPENDED, which indicates a vCPU
is in a suspended state. In the suspended state the vCPU will block
until a wakeup event (pending interrupt) is recognized.

Add a new system event type, KVM_SYSTEM_EVENT_WAKEUP, to indicate to
userspace that KVM has recognized one such wakeup event. It is the
responsibility of userspace to then make the vCPU runnable, or leave it
suspended until the next wakeup event.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 Documentation/virt/kvm/api.rst    | 37 +++++++++++++++++++++++++++++--
 arch/arm64/include/asm/kvm_host.h |  1 +
 arch/arm64/kvm/arm.c              | 35 +++++++++++++++++++++++++++++
 include/uapi/linux/kvm.h          |  2 ++
 4 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 5625c08b4a0e..426bcdc1216d 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -1482,14 +1482,43 @@ Possible values are:
                                  [s390]
    KVM_MP_STATE_LOAD             the vcpu is in a special load/startup state
                                  [s390]
+   KVM_MP_STATE_SUSPENDED        the vcpu is in a suspend state and is waiting
+                                 for a wakeup event [arm64]
    ==========================    ===============================================
 
 On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
 in-kernel irqchip, the multiprocessing state must be maintained by userspace on
 these architectures.
 
-For arm64/riscv:
-^^^^^^^^^^^^^^^^
+For arm64:
+^^^^^^^^^^
+
+If a vCPU is in the KVM_MP_STATE_SUSPENDED state, KVM will emulate the
+architectural execution of a WFI instruction.
+
+If a wakeup event is recognized, KVM will exit to userspace with a
+KVM_SYSTEM_EVENT exit, where the event type is KVM_SYSTEM_EVENT_WAKEUP. If
+userspace wants to honor the wakeup, it must set the vCPU's MP state to
+KVM_MP_STATE_RUNNABLE. If it does not, KVM will continue to await a wakeup
+event in subsequent calls to KVM_RUN.
+
+.. warning::
+
+     If userspace intends to keep the vCPU in a SUSPENDED state, it is
+     strongly recommended that userspace take action to suppress the
+     wakeup event (such as masking an interrupt). Otherwise, subsequent
+     calls to KVM_RUN will immediately exit with a KVM_SYSTEM_EVENT_WAKEUP
+     event and inadvertently waste CPU cycles.
+
+     Additionally, if userspace takes action to suppress a wakeup event,
+     it is strongly recommended that it also restore the vCPU to its
+     original state when the vCPU is made RUNNABLE again. For example,
+     if userspace masked a pending interrupt to suppress the wakeup,
+     the interrupt should be unmasked before returning control to the
+     guest.
+
+For riscv:
+^^^^^^^^^^
 
 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.
@@ -5914,6 +5943,7 @@ should put the acknowledged interrupt vector into the 'epr' field.
   #define KVM_SYSTEM_EVENT_SHUTDOWN       1
   #define KVM_SYSTEM_EVENT_RESET          2
   #define KVM_SYSTEM_EVENT_CRASH          3
+  #define KVM_SYSTEM_EVENT_WAKEUP         4
 			__u32 type;
 			__u64 flags;
 		} system_event;
@@ -5938,6 +5968,9 @@ Valid values for 'type' are:
    has requested a crash condition maintenance. Userspace can choose
    to ignore the request, or to gather VM memory core dump and/or
    reset/shutdown of the VM.
+ - KVM_SYSTEM_EVENT_WAKEUP -- the guest is in a suspended state and KVM
+   has recognized a wakeup event. Userspace may honor this event by marking
+   the exiting vCPU as runnable, or deny it and call KVM_RUN again.
 
 Valid flags are:
 
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index da58eb96d2a8..899f2c0b4c7b 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -46,6 +46,7 @@
 #define KVM_REQ_RECORD_STEAL	KVM_ARCH_REQ(3)
 #define KVM_REQ_RELOAD_GICv4	KVM_ARCH_REQ(4)
 #define KVM_REQ_RELOAD_PMU	KVM_ARCH_REQ(5)
+#define KVM_REQ_SUSPEND		KVM_ARCH_REQ(6)
 
 #define KVM_DIRTY_LOG_MANUAL_CAPS   (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
 				     KVM_DIRTY_LOG_INITIALLY_SET)
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 8eed0556ccaa..b94efa05d869 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -444,6 +444,18 @@ bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu)
 	return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_STOPPED;
 }
 
+static void kvm_arm_vcpu_suspend(struct kvm_vcpu *vcpu)
+{
+	vcpu->arch.mp_state.mp_state = KVM_MP_STATE_SUSPENDED;
+	kvm_make_request(KVM_REQ_SUSPEND, vcpu);
+	kvm_vcpu_kick(vcpu);
+}
+
+static bool kvm_arm_vcpu_suspended(struct kvm_vcpu *vcpu)
+{
+	return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_SUSPENDED;
+}
+
 int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
 				    struct kvm_mp_state *mp_state)
 {
@@ -464,6 +476,9 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
 	case KVM_MP_STATE_STOPPED:
 		kvm_arm_vcpu_power_off(vcpu);
 		break;
+	case KVM_MP_STATE_SUSPENDED:
+		kvm_arm_vcpu_suspend(vcpu);
+		break;
 	default:
 		ret = -EINVAL;
 	}
@@ -648,6 +663,23 @@ void kvm_vcpu_wfi(struct kvm_vcpu *vcpu)
 	preempt_enable();
 }
 
+static int kvm_vcpu_suspend(struct kvm_vcpu *vcpu)
+{
+	if (!kvm_arm_vcpu_suspended(vcpu))
+		return 1;
+
+	kvm_vcpu_wfi(vcpu);
+
+	/*
+	 * The suspend state is sticky; we do not leave it until userspace
+	 * explicitly marks the vCPU as runnable. Request that we suspend again
+	 * later.
+	 */
+	kvm_make_request(KVM_REQ_SUSPEND, vcpu);
+	kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_WAKEUP, 0);
+	return 0;
+}
+
 /**
  * check_vcpu_requests - check and handle pending vCPU requests
  * @vcpu:	the VCPU pointer
@@ -686,6 +718,9 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
 		if (kvm_check_request(KVM_REQ_RELOAD_PMU, vcpu))
 			kvm_pmu_handle_pmcr(vcpu,
 					    __vcpu_sys_reg(vcpu, PMCR_EL0));
+
+		if (kvm_check_request(KVM_REQ_SUSPEND, vcpu))
+			return kvm_vcpu_suspend(vcpu);
 	}
 
 	return 1;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 5191b57e1562..babb16c2abe5 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -444,6 +444,7 @@ struct kvm_run {
 #define KVM_SYSTEM_EVENT_SHUTDOWN       1
 #define KVM_SYSTEM_EVENT_RESET          2
 #define KVM_SYSTEM_EVENT_CRASH          3
+#define KVM_SYSTEM_EVENT_WAKEUP         4
 			__u32 type;
 			__u64 flags;
 		} system_event;
@@ -634,6 +635,7 @@ struct kvm_vapic_addr {
 #define KVM_MP_STATE_OPERATING         7
 #define KVM_MP_STATE_LOAD              8
 #define KVM_MP_STATE_AP_RESET_HOLD     9
+#define KVM_MP_STATE_SUSPENDED         10
 
 struct kvm_mp_state {
 	__u32 mp_state;
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 10/15] KVM: arm64: Implement PSCI SYSTEM_SUSPEND
  2022-03-11 17:39 ` Oliver Upton
@ 2022-03-11 17:39   ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: alexandru.elisei, anup, atishp, james.morse, jingzhangos,
	jmattson, joro, kvm-riscv, kvm, maz, pbonzini, pshier, rananta,
	reijiw, ricarkol, seanjc, suzuki.poulose, vkuznets, wanpengli,
	Oliver Upton

ARM DEN0022D.b 5.19 "SYSTEM_SUSPEND" describes a PSCI call that allows
software to request that a system be placed in the deepest possible
low-power state. Effectively, software can use this to suspend itself to
RAM.

Unfortunately, there really is no good way to implement a system-wide
PSCI call in KVM. Any precondition checks done in the kernel will need
to be repeated by userspace since there is no good way to protect a
critical section that spans an exit to userspace. SYSTEM_RESET and
SYSTEM_OFF are equally plagued by this issue, although no users have
seemingly cared for the relatively long time these calls have been
supported.

The solution is to just make the whole implementation userspace's
problem. Introduce a new system event, KVM_SYSTEM_EVENT_SUSPEND, that
indicates to userspace a calling vCPU has invoked PSCI SYSTEM_SUSPEND.
Additionally, add a CAP to get buy-in from userspace for this new exit
type.

Only advertise the SYSTEM_SUSPEND PSCI call if userspace has opted in.
If a vCPU calls SYSTEM_SUSPEND, punt straight to userspace. Provide
explicit documentation of userspace's responsibilites for the exit and
point to the PSCI specification to describe the actual PSCI call.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 Documentation/virt/kvm/api.rst    | 39 +++++++++++++++++++++++++++++++
 arch/arm64/include/asm/kvm_host.h |  2 ++
 arch/arm64/kvm/arm.c              | 12 +++++++++-
 arch/arm64/kvm/psci.c             | 25 ++++++++++++++++++++
 include/uapi/linux/kvm.h          |  2 ++
 5 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 426bcdc1216d..396589e3b178 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -5944,6 +5944,7 @@ should put the acknowledged interrupt vector into the 'epr' field.
   #define KVM_SYSTEM_EVENT_RESET          2
   #define KVM_SYSTEM_EVENT_CRASH          3
   #define KVM_SYSTEM_EVENT_WAKEUP         4
+  #define KVM_SYSTEM_EVENT_SUSPENDED      5
 			__u32 type;
 			__u64 flags;
 		} system_event;
@@ -5971,6 +5972,34 @@ Valid values for 'type' are:
  - KVM_SYSTEM_EVENT_WAKEUP -- the guest is in a suspended state and KVM
    has recognized a wakeup event. Userspace may honor this event by marking
    the exiting vCPU as runnable, or deny it and call KVM_RUN again.
+ - KVM_SYSTEM_EVENT_SUSPENDED -- the guest has requested a suspension of
+   the VM.
+
+For arm/arm64:
+^^^^^^^^^^^^^^
+
+   KVM_SYSTEM_EVENT_SUSPENDED exits are enabled with the
+   KVM_CAP_ARM_SYSTEM_SUSPEND VM capability. If a guest invokes the PSCI
+   SYSTEM_SUSPEND function, KVM will exit to userspace with this event
+   type.
+
+   It is the sole responsibility of userspace to implement the PSCI
+   SYSTEM_SUSPEND call according to ARM DEN0022D.b 5.19 "SYSTEM_SUSPEND".
+   KVM does not change the vCPU's state before exiting to userspace, so
+   the call parameters are left in-place in the vCPU registers.
+
+   Userspace is _required_ to take action for such an exit. It must
+   either:
+
+    - Honor the guest request to suspend the VM. Userspace can request
+      in-kernel emulation of suspension by setting the calling vCPU's
+      state to KVM_MP_STATE_SUSPENDED. Userspace must configure the vCPU's
+      state according to the parameters passed to the PSCI function when
+      the calling vCPU is resumed. See ARM DEN0022D.b 5.19.1 "Intended use"
+      for details on the function parameters.
+
+    - Deny the guest request to suspend the VM. See ARM DEN0022D.b 5.19.2
+      "Caller responsibilities" for possible return values.
 
 Valid flags are:
 
@@ -7598,3 +7627,13 @@ The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
 of the result of KVM_CHECK_EXTENSION.  KVM will forward to userspace
 the hypercalls whose corresponding bit is in the argument, and return
 ENOSYS for the others.
+
+8.35 KVM_CAP_ARM_SYSTEM_SUSPEND
+-------------------------------
+
+:Capability: KVM_CAP_ARM_SYSTEM_SUSPEND
+:Architectures: arm64
+:Type: vm
+
+When enabled, KVM will exit to userspace with KVM_EXIT_SYSTEM_EVENT of
+type KVM_SYSTEM_EVENT_SUSPEND to process the guest suspend request.
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 899f2c0b4c7b..ca3ac32e40c8 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -128,6 +128,8 @@ struct kvm_arch {
 #define KVM_ARCH_FLAG_MTE_ENABLED			1
 	/* At least one vCPU has ran in the VM */
 #define KVM_ARCH_FLAG_HAS_RAN_ONCE			2
+	/* PSCI SYSTEM_SUSPEND enabled for the guest */
+#define KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED		3
 	unsigned long flags;
 
 	/*
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index b94efa05d869..c9b616ddb512 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -97,6 +97,10 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
 		}
 		mutex_unlock(&kvm->lock);
 		break;
+	case KVM_CAP_ARM_SYSTEM_SUSPEND:
+		r = 0;
+		set_bit(KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED, &kvm->arch.flags);
+		break;
 	default:
 		r = -EINVAL;
 		break;
@@ -210,6 +214,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_SYSTEM_SUSPEND:
 		r = 1;
 		break;
 	case KVM_CAP_SET_GUEST_DEBUG2:
@@ -447,8 +452,13 @@ bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu)
 static void kvm_arm_vcpu_suspend(struct kvm_vcpu *vcpu)
 {
 	vcpu->arch.mp_state.mp_state = KVM_MP_STATE_SUSPENDED;
+
+	/*
+	 * Since this is only called from the intended vCPU, the target vCPU is
+	 * guaranteed to not be running. As such there is no need to kick the
+	 * target to handle the request.
+	 */
 	kvm_make_request(KVM_REQ_SUSPEND, vcpu);
-	kvm_vcpu_kick(vcpu);
 }
 
 static bool kvm_arm_vcpu_suspended(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
index 78266716165e..2239143a9d6c 100644
--- a/arch/arm64/kvm/psci.c
+++ b/arch/arm64/kvm/psci.c
@@ -192,6 +192,11 @@ static void kvm_psci_system_reset2(struct kvm_vcpu *vcpu)
 				 KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2);
 }
 
+static void kvm_psci_system_suspend(struct kvm_vcpu *vcpu)
+{
+	kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_SUSPEND, 0);
+}
+
 static void kvm_psci_narrow_to_32bit(struct kvm_vcpu *vcpu)
 {
 	int i;
@@ -302,6 +307,7 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
 {
 	unsigned long val = PSCI_RET_NOT_SUPPORTED;
 	u32 psci_fn = smccc_get_function(vcpu);
+	struct kvm *kvm = vcpu->kvm;
 	u32 arg;
 	int ret = 1;
 
@@ -336,6 +342,11 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
 		case ARM_SMCCC_VERSION_FUNC_ID:
 			val = 0;
 			break;
+		case PSCI_1_0_FN_SYSTEM_SUSPEND:
+		case PSCI_1_0_FN64_SYSTEM_SUSPEND:
+			if (test_bit(KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED, &kvm->arch.flags))
+				val = 0;
+			break;
 		case PSCI_1_1_FN_SYSTEM_RESET2:
 		case PSCI_1_1_FN64_SYSTEM_RESET2:
 			if (minor >= 1)
@@ -343,6 +354,20 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
 			break;
 		}
 		break;
+	case PSCI_1_0_FN_SYSTEM_SUSPEND:
+		kvm_psci_narrow_to_32bit(vcpu);
+		fallthrough;
+	case PSCI_1_0_FN64_SYSTEM_SUSPEND:
+		/*
+		 * Return directly to userspace without changing the vCPU's
+		 * registers. Userspace depends on reading the SMCCC parameters
+		 * to implement SYSTEM_SUSPEND.
+		 */
+		if (test_bit(KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED, &kvm->arch.flags)) {
+			kvm_psci_system_suspend(vcpu);
+			return 0;
+		}
+		break;
 	case PSCI_1_1_FN_SYSTEM_RESET2:
 		kvm_psci_narrow_to_32bit(vcpu);
 		fallthrough;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index babb16c2abe5..e5bb5f15c0eb 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -445,6 +445,7 @@ struct kvm_run {
 #define KVM_SYSTEM_EVENT_RESET          2
 #define KVM_SYSTEM_EVENT_CRASH          3
 #define KVM_SYSTEM_EVENT_WAKEUP         4
+#define KVM_SYSTEM_EVENT_SUSPEND        5
 			__u32 type;
 			__u64 flags;
 		} system_event;
@@ -1136,6 +1137,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_VM_GPA_BITS 207
 #define KVM_CAP_XSAVE2 208
 #define KVM_CAP_SYS_ATTRIBUTES 209
+#define KVM_CAP_ARM_SYSTEM_SUSPEND 210
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 10/15] KVM: arm64: Implement PSCI SYSTEM_SUSPEND
@ 2022-03-11 17:39   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: maz, wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

ARM DEN0022D.b 5.19 "SYSTEM_SUSPEND" describes a PSCI call that allows
software to request that a system be placed in the deepest possible
low-power state. Effectively, software can use this to suspend itself to
RAM.

Unfortunately, there really is no good way to implement a system-wide
PSCI call in KVM. Any precondition checks done in the kernel will need
to be repeated by userspace since there is no good way to protect a
critical section that spans an exit to userspace. SYSTEM_RESET and
SYSTEM_OFF are equally plagued by this issue, although no users have
seemingly cared for the relatively long time these calls have been
supported.

The solution is to just make the whole implementation userspace's
problem. Introduce a new system event, KVM_SYSTEM_EVENT_SUSPEND, that
indicates to userspace a calling vCPU has invoked PSCI SYSTEM_SUSPEND.
Additionally, add a CAP to get buy-in from userspace for this new exit
type.

Only advertise the SYSTEM_SUSPEND PSCI call if userspace has opted in.
If a vCPU calls SYSTEM_SUSPEND, punt straight to userspace. Provide
explicit documentation of userspace's responsibilites for the exit and
point to the PSCI specification to describe the actual PSCI call.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 Documentation/virt/kvm/api.rst    | 39 +++++++++++++++++++++++++++++++
 arch/arm64/include/asm/kvm_host.h |  2 ++
 arch/arm64/kvm/arm.c              | 12 +++++++++-
 arch/arm64/kvm/psci.c             | 25 ++++++++++++++++++++
 include/uapi/linux/kvm.h          |  2 ++
 5 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 426bcdc1216d..396589e3b178 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -5944,6 +5944,7 @@ should put the acknowledged interrupt vector into the 'epr' field.
   #define KVM_SYSTEM_EVENT_RESET          2
   #define KVM_SYSTEM_EVENT_CRASH          3
   #define KVM_SYSTEM_EVENT_WAKEUP         4
+  #define KVM_SYSTEM_EVENT_SUSPENDED      5
 			__u32 type;
 			__u64 flags;
 		} system_event;
@@ -5971,6 +5972,34 @@ Valid values for 'type' are:
  - KVM_SYSTEM_EVENT_WAKEUP -- the guest is in a suspended state and KVM
    has recognized a wakeup event. Userspace may honor this event by marking
    the exiting vCPU as runnable, or deny it and call KVM_RUN again.
+ - KVM_SYSTEM_EVENT_SUSPENDED -- the guest has requested a suspension of
+   the VM.
+
+For arm/arm64:
+^^^^^^^^^^^^^^
+
+   KVM_SYSTEM_EVENT_SUSPENDED exits are enabled with the
+   KVM_CAP_ARM_SYSTEM_SUSPEND VM capability. If a guest invokes the PSCI
+   SYSTEM_SUSPEND function, KVM will exit to userspace with this event
+   type.
+
+   It is the sole responsibility of userspace to implement the PSCI
+   SYSTEM_SUSPEND call according to ARM DEN0022D.b 5.19 "SYSTEM_SUSPEND".
+   KVM does not change the vCPU's state before exiting to userspace, so
+   the call parameters are left in-place in the vCPU registers.
+
+   Userspace is _required_ to take action for such an exit. It must
+   either:
+
+    - Honor the guest request to suspend the VM. Userspace can request
+      in-kernel emulation of suspension by setting the calling vCPU's
+      state to KVM_MP_STATE_SUSPENDED. Userspace must configure the vCPU's
+      state according to the parameters passed to the PSCI function when
+      the calling vCPU is resumed. See ARM DEN0022D.b 5.19.1 "Intended use"
+      for details on the function parameters.
+
+    - Deny the guest request to suspend the VM. See ARM DEN0022D.b 5.19.2
+      "Caller responsibilities" for possible return values.
 
 Valid flags are:
 
@@ -7598,3 +7627,13 @@ The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
 of the result of KVM_CHECK_EXTENSION.  KVM will forward to userspace
 the hypercalls whose corresponding bit is in the argument, and return
 ENOSYS for the others.
+
+8.35 KVM_CAP_ARM_SYSTEM_SUSPEND
+-------------------------------
+
+:Capability: KVM_CAP_ARM_SYSTEM_SUSPEND
+:Architectures: arm64
+:Type: vm
+
+When enabled, KVM will exit to userspace with KVM_EXIT_SYSTEM_EVENT of
+type KVM_SYSTEM_EVENT_SUSPEND to process the guest suspend request.
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 899f2c0b4c7b..ca3ac32e40c8 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -128,6 +128,8 @@ struct kvm_arch {
 #define KVM_ARCH_FLAG_MTE_ENABLED			1
 	/* At least one vCPU has ran in the VM */
 #define KVM_ARCH_FLAG_HAS_RAN_ONCE			2
+	/* PSCI SYSTEM_SUSPEND enabled for the guest */
+#define KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED		3
 	unsigned long flags;
 
 	/*
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index b94efa05d869..c9b616ddb512 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -97,6 +97,10 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
 		}
 		mutex_unlock(&kvm->lock);
 		break;
+	case KVM_CAP_ARM_SYSTEM_SUSPEND:
+		r = 0;
+		set_bit(KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED, &kvm->arch.flags);
+		break;
 	default:
 		r = -EINVAL;
 		break;
@@ -210,6 +214,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_SYSTEM_SUSPEND:
 		r = 1;
 		break;
 	case KVM_CAP_SET_GUEST_DEBUG2:
@@ -447,8 +452,13 @@ bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu)
 static void kvm_arm_vcpu_suspend(struct kvm_vcpu *vcpu)
 {
 	vcpu->arch.mp_state.mp_state = KVM_MP_STATE_SUSPENDED;
+
+	/*
+	 * Since this is only called from the intended vCPU, the target vCPU is
+	 * guaranteed to not be running. As such there is no need to kick the
+	 * target to handle the request.
+	 */
 	kvm_make_request(KVM_REQ_SUSPEND, vcpu);
-	kvm_vcpu_kick(vcpu);
 }
 
 static bool kvm_arm_vcpu_suspended(struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
index 78266716165e..2239143a9d6c 100644
--- a/arch/arm64/kvm/psci.c
+++ b/arch/arm64/kvm/psci.c
@@ -192,6 +192,11 @@ static void kvm_psci_system_reset2(struct kvm_vcpu *vcpu)
 				 KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2);
 }
 
+static void kvm_psci_system_suspend(struct kvm_vcpu *vcpu)
+{
+	kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_SUSPEND, 0);
+}
+
 static void kvm_psci_narrow_to_32bit(struct kvm_vcpu *vcpu)
 {
 	int i;
@@ -302,6 +307,7 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
 {
 	unsigned long val = PSCI_RET_NOT_SUPPORTED;
 	u32 psci_fn = smccc_get_function(vcpu);
+	struct kvm *kvm = vcpu->kvm;
 	u32 arg;
 	int ret = 1;
 
@@ -336,6 +342,11 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
 		case ARM_SMCCC_VERSION_FUNC_ID:
 			val = 0;
 			break;
+		case PSCI_1_0_FN_SYSTEM_SUSPEND:
+		case PSCI_1_0_FN64_SYSTEM_SUSPEND:
+			if (test_bit(KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED, &kvm->arch.flags))
+				val = 0;
+			break;
 		case PSCI_1_1_FN_SYSTEM_RESET2:
 		case PSCI_1_1_FN64_SYSTEM_RESET2:
 			if (minor >= 1)
@@ -343,6 +354,20 @@ static int kvm_psci_1_x_call(struct kvm_vcpu *vcpu, u32 minor)
 			break;
 		}
 		break;
+	case PSCI_1_0_FN_SYSTEM_SUSPEND:
+		kvm_psci_narrow_to_32bit(vcpu);
+		fallthrough;
+	case PSCI_1_0_FN64_SYSTEM_SUSPEND:
+		/*
+		 * Return directly to userspace without changing the vCPU's
+		 * registers. Userspace depends on reading the SMCCC parameters
+		 * to implement SYSTEM_SUSPEND.
+		 */
+		if (test_bit(KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED, &kvm->arch.flags)) {
+			kvm_psci_system_suspend(vcpu);
+			return 0;
+		}
+		break;
 	case PSCI_1_1_FN_SYSTEM_RESET2:
 		kvm_psci_narrow_to_32bit(vcpu);
 		fallthrough;
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index babb16c2abe5..e5bb5f15c0eb 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -445,6 +445,7 @@ struct kvm_run {
 #define KVM_SYSTEM_EVENT_RESET          2
 #define KVM_SYSTEM_EVENT_CRASH          3
 #define KVM_SYSTEM_EVENT_WAKEUP         4
+#define KVM_SYSTEM_EVENT_SUSPEND        5
 			__u32 type;
 			__u64 flags;
 		} system_event;
@@ -1136,6 +1137,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_VM_GPA_BITS 207
 #define KVM_CAP_XSAVE2 208
 #define KVM_CAP_SYS_ATTRIBUTES 209
+#define KVM_CAP_ARM_SYSTEM_SUSPEND 210
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 11/15] selftests: KVM: Rename psci_cpu_on_test to psci_test
  2022-03-11 17:39 ` Oliver Upton
@ 2022-03-11 17:39   ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: alexandru.elisei, anup, atishp, james.morse, jingzhangos,
	jmattson, joro, kvm-riscv, kvm, maz, pbonzini, pshier, rananta,
	reijiw, ricarkol, seanjc, suzuki.poulose, vkuznets, wanpengli,
	Oliver Upton, Andrew Jones

There are other interactions with PSCI worth testing; rename the PSCI
test to make it more generic.

No functional change intended.

Signed-off-by: Oliver Upton <oupton@google.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
---
 tools/testing/selftests/kvm/.gitignore                          | 2 +-
 tools/testing/selftests/kvm/Makefile                            | 2 +-
 .../selftests/kvm/aarch64/{psci_cpu_on_test.c => psci_test.c}   | 0
 3 files changed, 2 insertions(+), 2 deletions(-)
 rename tools/testing/selftests/kvm/aarch64/{psci_cpu_on_test.c => psci_test.c} (100%)

diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore
index dce7de7755e6..ac69108d9ffd 100644
--- a/tools/testing/selftests/kvm/.gitignore
+++ b/tools/testing/selftests/kvm/.gitignore
@@ -2,7 +2,7 @@
 /aarch64/arch_timer
 /aarch64/debug-exceptions
 /aarch64/get-reg-list
-/aarch64/psci_cpu_on_test
+/aarch64/psci_test
 /aarch64/vgic_init
 /aarch64/vgic_irq
 /s390x/memop
diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
index 0e4926bc9a58..61e11e372366 100644
--- a/tools/testing/selftests/kvm/Makefile
+++ b/tools/testing/selftests/kvm/Makefile
@@ -103,7 +103,7 @@ TEST_GEN_PROGS_x86_64 += system_counter_offset_test
 TEST_GEN_PROGS_aarch64 += aarch64/arch_timer
 TEST_GEN_PROGS_aarch64 += aarch64/debug-exceptions
 TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list
-TEST_GEN_PROGS_aarch64 += aarch64/psci_cpu_on_test
+TEST_GEN_PROGS_aarch64 += aarch64/psci_test
 TEST_GEN_PROGS_aarch64 += aarch64/vgic_init
 TEST_GEN_PROGS_aarch64 += aarch64/vgic_irq
 TEST_GEN_PROGS_aarch64 += demand_paging_test
diff --git a/tools/testing/selftests/kvm/aarch64/psci_cpu_on_test.c b/tools/testing/selftests/kvm/aarch64/psci_test.c
similarity index 100%
rename from tools/testing/selftests/kvm/aarch64/psci_cpu_on_test.c
rename to tools/testing/selftests/kvm/aarch64/psci_test.c
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 11/15] selftests: KVM: Rename psci_cpu_on_test to psci_test
@ 2022-03-11 17:39   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: maz, wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

There are other interactions with PSCI worth testing; rename the PSCI
test to make it more generic.

No functional change intended.

Signed-off-by: Oliver Upton <oupton@google.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
---
 tools/testing/selftests/kvm/.gitignore                          | 2 +-
 tools/testing/selftests/kvm/Makefile                            | 2 +-
 .../selftests/kvm/aarch64/{psci_cpu_on_test.c => psci_test.c}   | 0
 3 files changed, 2 insertions(+), 2 deletions(-)
 rename tools/testing/selftests/kvm/aarch64/{psci_cpu_on_test.c => psci_test.c} (100%)

diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore
index dce7de7755e6..ac69108d9ffd 100644
--- a/tools/testing/selftests/kvm/.gitignore
+++ b/tools/testing/selftests/kvm/.gitignore
@@ -2,7 +2,7 @@
 /aarch64/arch_timer
 /aarch64/debug-exceptions
 /aarch64/get-reg-list
-/aarch64/psci_cpu_on_test
+/aarch64/psci_test
 /aarch64/vgic_init
 /aarch64/vgic_irq
 /s390x/memop
diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
index 0e4926bc9a58..61e11e372366 100644
--- a/tools/testing/selftests/kvm/Makefile
+++ b/tools/testing/selftests/kvm/Makefile
@@ -103,7 +103,7 @@ TEST_GEN_PROGS_x86_64 += system_counter_offset_test
 TEST_GEN_PROGS_aarch64 += aarch64/arch_timer
 TEST_GEN_PROGS_aarch64 += aarch64/debug-exceptions
 TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list
-TEST_GEN_PROGS_aarch64 += aarch64/psci_cpu_on_test
+TEST_GEN_PROGS_aarch64 += aarch64/psci_test
 TEST_GEN_PROGS_aarch64 += aarch64/vgic_init
 TEST_GEN_PROGS_aarch64 += aarch64/vgic_irq
 TEST_GEN_PROGS_aarch64 += demand_paging_test
diff --git a/tools/testing/selftests/kvm/aarch64/psci_cpu_on_test.c b/tools/testing/selftests/kvm/aarch64/psci_test.c
similarity index 100%
rename from tools/testing/selftests/kvm/aarch64/psci_cpu_on_test.c
rename to tools/testing/selftests/kvm/aarch64/psci_test.c
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 12/15] selftests: KVM: Create helper for making SMCCC calls
  2022-03-11 17:39 ` Oliver Upton
@ 2022-03-11 17:39   ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: alexandru.elisei, anup, atishp, james.morse, jingzhangos,
	jmattson, joro, kvm-riscv, kvm, maz, pbonzini, pshier, rananta,
	reijiw, ricarkol, seanjc, suzuki.poulose, vkuznets, wanpengli,
	Oliver Upton, Andrew Jones

The PSCI and PV stolen time tests both need to make SMCCC calls within
the guest. Create a helper for making SMCCC calls and rework the
existing tests to use the library function.

Signed-off-by: Oliver Upton <oupton@google.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
---
 .../testing/selftests/kvm/aarch64/psci_test.c | 25 ++++++-------------
 .../selftests/kvm/include/aarch64/processor.h | 22 ++++++++++++++++
 .../selftests/kvm/lib/aarch64/processor.c     | 25 +++++++++++++++++++
 tools/testing/selftests/kvm/steal_time.c      | 13 +++-------
 4 files changed, 58 insertions(+), 27 deletions(-)

diff --git a/tools/testing/selftests/kvm/aarch64/psci_test.c b/tools/testing/selftests/kvm/aarch64/psci_test.c
index 4c5f6814030f..8c998f0b802c 100644
--- a/tools/testing/selftests/kvm/aarch64/psci_test.c
+++ b/tools/testing/selftests/kvm/aarch64/psci_test.c
@@ -26,32 +26,23 @@
 static uint64_t psci_cpu_on(uint64_t target_cpu, uint64_t entry_addr,
 			    uint64_t context_id)
 {
-	register uint64_t x0 asm("x0") = PSCI_0_2_FN64_CPU_ON;
-	register uint64_t x1 asm("x1") = target_cpu;
-	register uint64_t x2 asm("x2") = entry_addr;
-	register uint64_t x3 asm("x3") = context_id;
+	struct arm_smccc_res res;
 
-	asm("hvc #0"
-	    : "=r"(x0)
-	    : "r"(x0), "r"(x1), "r"(x2), "r"(x3)
-	    : "memory");
+	smccc_hvc(PSCI_0_2_FN64_CPU_ON, target_cpu, entry_addr, context_id,
+		  0, 0, 0, 0, &res);
 
-	return x0;
+	return res.a0;
 }
 
 static uint64_t psci_affinity_info(uint64_t target_affinity,
 				   uint64_t lowest_affinity_level)
 {
-	register uint64_t x0 asm("x0") = PSCI_0_2_FN64_AFFINITY_INFO;
-	register uint64_t x1 asm("x1") = target_affinity;
-	register uint64_t x2 asm("x2") = lowest_affinity_level;
+	struct arm_smccc_res res;
 
-	asm("hvc #0"
-	    : "=r"(x0)
-	    : "r"(x0), "r"(x1), "r"(x2)
-	    : "memory");
+	smccc_hvc(PSCI_0_2_FN64_AFFINITY_INFO, target_affinity, lowest_affinity_level,
+		  0, 0, 0, 0, 0, &res);
 
-	return x0;
+	return res.a0;
 }
 
 static void guest_main(uint64_t target_cpu)
diff --git a/tools/testing/selftests/kvm/include/aarch64/processor.h b/tools/testing/selftests/kvm/include/aarch64/processor.h
index 8f9f46979a00..59ece9d4e0d1 100644
--- a/tools/testing/selftests/kvm/include/aarch64/processor.h
+++ b/tools/testing/selftests/kvm/include/aarch64/processor.h
@@ -185,4 +185,26 @@ static inline void local_irq_disable(void)
 	asm volatile("msr daifset, #3" : : : "memory");
 }
 
+/**
+ * struct arm_smccc_res - Result from SMC/HVC call
+ * @a0-a3 result values from registers 0 to 3
+ */
+struct arm_smccc_res {
+	unsigned long a0;
+	unsigned long a1;
+	unsigned long a2;
+	unsigned long a3;
+};
+
+/**
+ * smccc_hvc - Invoke a SMCCC function using the hvc conduit
+ * @function_id: the SMCCC function to be called
+ * @arg0-arg6: SMCCC function arguments, corresponding to registers x1-x7
+ * @res: pointer to write the return values from registers x0-x3
+ *
+ */
+void smccc_hvc(uint32_t function_id, uint64_t arg0, uint64_t arg1,
+	       uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5,
+	       uint64_t arg6, struct arm_smccc_res *res);
+
 #endif /* SELFTEST_KVM_PROCESSOR_H */
diff --git a/tools/testing/selftests/kvm/lib/aarch64/processor.c b/tools/testing/selftests/kvm/lib/aarch64/processor.c
index 9343d82519b4..6a041289fa80 100644
--- a/tools/testing/selftests/kvm/lib/aarch64/processor.c
+++ b/tools/testing/selftests/kvm/lib/aarch64/processor.c
@@ -500,3 +500,28 @@ void __attribute__((constructor)) init_guest_modes(void)
 {
        guest_modes_append_default();
 }
+
+void smccc_hvc(uint32_t function_id, uint64_t arg0, uint64_t arg1,
+	       uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5,
+	       uint64_t arg6, struct arm_smccc_res *res)
+{
+	asm volatile("mov   w0, %w[function_id]\n"
+		     "mov   x1, %[arg0]\n"
+		     "mov   x2, %[arg1]\n"
+		     "mov   x3, %[arg2]\n"
+		     "mov   x4, %[arg3]\n"
+		     "mov   x5, %[arg4]\n"
+		     "mov   x6, %[arg5]\n"
+		     "mov   x7, %[arg6]\n"
+		     "hvc   #0\n"
+		     "mov   %[res0], x0\n"
+		     "mov   %[res1], x1\n"
+		     "mov   %[res2], x2\n"
+		     "mov   %[res3], x3\n"
+		     : [res0] "=r"(res->a0), [res1] "=r"(res->a1),
+		       [res2] "=r"(res->a2), [res3] "=r"(res->a3)
+		     : [function_id] "r"(function_id), [arg0] "r"(arg0),
+		       [arg1] "r"(arg1), [arg2] "r"(arg2), [arg3] "r"(arg3),
+		       [arg4] "r"(arg4), [arg5] "r"(arg5), [arg6] "r"(arg6)
+		     : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7");
+}
diff --git a/tools/testing/selftests/kvm/steal_time.c b/tools/testing/selftests/kvm/steal_time.c
index 62f2eb9ee3d5..8c4e811bd586 100644
--- a/tools/testing/selftests/kvm/steal_time.c
+++ b/tools/testing/selftests/kvm/steal_time.c
@@ -118,17 +118,10 @@ struct st_time {
 
 static int64_t smccc(uint32_t func, uint64_t arg)
 {
-	unsigned long ret;
+	struct arm_smccc_res res;
 
-	asm volatile(
-		"mov	w0, %w1\n"
-		"mov	x1, %2\n"
-		"hvc	#0\n"
-		"mov	%0, x0\n"
-	: "=r" (ret) : "r" (func), "r" (arg) :
-	  "x0", "x1", "x2", "x3");
-
-	return ret;
+	smccc_hvc(func, arg, 0, 0, 0, 0, 0, 0, &res);
+	return res.a0;
 }
 
 static void check_status(struct st_time *st)
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 12/15] selftests: KVM: Create helper for making SMCCC calls
@ 2022-03-11 17:39   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: maz, wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

The PSCI and PV stolen time tests both need to make SMCCC calls within
the guest. Create a helper for making SMCCC calls and rework the
existing tests to use the library function.

Signed-off-by: Oliver Upton <oupton@google.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
---
 .../testing/selftests/kvm/aarch64/psci_test.c | 25 ++++++-------------
 .../selftests/kvm/include/aarch64/processor.h | 22 ++++++++++++++++
 .../selftests/kvm/lib/aarch64/processor.c     | 25 +++++++++++++++++++
 tools/testing/selftests/kvm/steal_time.c      | 13 +++-------
 4 files changed, 58 insertions(+), 27 deletions(-)

diff --git a/tools/testing/selftests/kvm/aarch64/psci_test.c b/tools/testing/selftests/kvm/aarch64/psci_test.c
index 4c5f6814030f..8c998f0b802c 100644
--- a/tools/testing/selftests/kvm/aarch64/psci_test.c
+++ b/tools/testing/selftests/kvm/aarch64/psci_test.c
@@ -26,32 +26,23 @@
 static uint64_t psci_cpu_on(uint64_t target_cpu, uint64_t entry_addr,
 			    uint64_t context_id)
 {
-	register uint64_t x0 asm("x0") = PSCI_0_2_FN64_CPU_ON;
-	register uint64_t x1 asm("x1") = target_cpu;
-	register uint64_t x2 asm("x2") = entry_addr;
-	register uint64_t x3 asm("x3") = context_id;
+	struct arm_smccc_res res;
 
-	asm("hvc #0"
-	    : "=r"(x0)
-	    : "r"(x0), "r"(x1), "r"(x2), "r"(x3)
-	    : "memory");
+	smccc_hvc(PSCI_0_2_FN64_CPU_ON, target_cpu, entry_addr, context_id,
+		  0, 0, 0, 0, &res);
 
-	return x0;
+	return res.a0;
 }
 
 static uint64_t psci_affinity_info(uint64_t target_affinity,
 				   uint64_t lowest_affinity_level)
 {
-	register uint64_t x0 asm("x0") = PSCI_0_2_FN64_AFFINITY_INFO;
-	register uint64_t x1 asm("x1") = target_affinity;
-	register uint64_t x2 asm("x2") = lowest_affinity_level;
+	struct arm_smccc_res res;
 
-	asm("hvc #0"
-	    : "=r"(x0)
-	    : "r"(x0), "r"(x1), "r"(x2)
-	    : "memory");
+	smccc_hvc(PSCI_0_2_FN64_AFFINITY_INFO, target_affinity, lowest_affinity_level,
+		  0, 0, 0, 0, 0, &res);
 
-	return x0;
+	return res.a0;
 }
 
 static void guest_main(uint64_t target_cpu)
diff --git a/tools/testing/selftests/kvm/include/aarch64/processor.h b/tools/testing/selftests/kvm/include/aarch64/processor.h
index 8f9f46979a00..59ece9d4e0d1 100644
--- a/tools/testing/selftests/kvm/include/aarch64/processor.h
+++ b/tools/testing/selftests/kvm/include/aarch64/processor.h
@@ -185,4 +185,26 @@ static inline void local_irq_disable(void)
 	asm volatile("msr daifset, #3" : : : "memory");
 }
 
+/**
+ * struct arm_smccc_res - Result from SMC/HVC call
+ * @a0-a3 result values from registers 0 to 3
+ */
+struct arm_smccc_res {
+	unsigned long a0;
+	unsigned long a1;
+	unsigned long a2;
+	unsigned long a3;
+};
+
+/**
+ * smccc_hvc - Invoke a SMCCC function using the hvc conduit
+ * @function_id: the SMCCC function to be called
+ * @arg0-arg6: SMCCC function arguments, corresponding to registers x1-x7
+ * @res: pointer to write the return values from registers x0-x3
+ *
+ */
+void smccc_hvc(uint32_t function_id, uint64_t arg0, uint64_t arg1,
+	       uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5,
+	       uint64_t arg6, struct arm_smccc_res *res);
+
 #endif /* SELFTEST_KVM_PROCESSOR_H */
diff --git a/tools/testing/selftests/kvm/lib/aarch64/processor.c b/tools/testing/selftests/kvm/lib/aarch64/processor.c
index 9343d82519b4..6a041289fa80 100644
--- a/tools/testing/selftests/kvm/lib/aarch64/processor.c
+++ b/tools/testing/selftests/kvm/lib/aarch64/processor.c
@@ -500,3 +500,28 @@ void __attribute__((constructor)) init_guest_modes(void)
 {
        guest_modes_append_default();
 }
+
+void smccc_hvc(uint32_t function_id, uint64_t arg0, uint64_t arg1,
+	       uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5,
+	       uint64_t arg6, struct arm_smccc_res *res)
+{
+	asm volatile("mov   w0, %w[function_id]\n"
+		     "mov   x1, %[arg0]\n"
+		     "mov   x2, %[arg1]\n"
+		     "mov   x3, %[arg2]\n"
+		     "mov   x4, %[arg3]\n"
+		     "mov   x5, %[arg4]\n"
+		     "mov   x6, %[arg5]\n"
+		     "mov   x7, %[arg6]\n"
+		     "hvc   #0\n"
+		     "mov   %[res0], x0\n"
+		     "mov   %[res1], x1\n"
+		     "mov   %[res2], x2\n"
+		     "mov   %[res3], x3\n"
+		     : [res0] "=r"(res->a0), [res1] "=r"(res->a1),
+		       [res2] "=r"(res->a2), [res3] "=r"(res->a3)
+		     : [function_id] "r"(function_id), [arg0] "r"(arg0),
+		       [arg1] "r"(arg1), [arg2] "r"(arg2), [arg3] "r"(arg3),
+		       [arg4] "r"(arg4), [arg5] "r"(arg5), [arg6] "r"(arg6)
+		     : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7");
+}
diff --git a/tools/testing/selftests/kvm/steal_time.c b/tools/testing/selftests/kvm/steal_time.c
index 62f2eb9ee3d5..8c4e811bd586 100644
--- a/tools/testing/selftests/kvm/steal_time.c
+++ b/tools/testing/selftests/kvm/steal_time.c
@@ -118,17 +118,10 @@ struct st_time {
 
 static int64_t smccc(uint32_t func, uint64_t arg)
 {
-	unsigned long ret;
+	struct arm_smccc_res res;
 
-	asm volatile(
-		"mov	w0, %w1\n"
-		"mov	x1, %2\n"
-		"hvc	#0\n"
-		"mov	%0, x0\n"
-	: "=r" (ret) : "r" (func), "r" (arg) :
-	  "x0", "x1", "x2", "x3");
-
-	return ret;
+	smccc_hvc(func, arg, 0, 0, 0, 0, 0, 0, &res);
+	return res.a0;
 }
 
 static void check_status(struct st_time *st)
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 13/15] selftests: KVM: Use KVM_SET_MP_STATE to power off vCPU in psci_test
  2022-03-11 17:39 ` Oliver Upton
@ 2022-03-11 17:39   ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: alexandru.elisei, anup, atishp, james.morse, jingzhangos,
	jmattson, joro, kvm-riscv, kvm, maz, pbonzini, pshier, rananta,
	reijiw, ricarkol, seanjc, suzuki.poulose, vkuznets, wanpengli,
	Oliver Upton

Setting a vCPU's MP state to KVM_MP_STATE_STOPPED has the effect of
powering off the vCPU. Rather than using the vCPU init feature flag, use
the KVM_SET_MP_STATE ioctl to power off the target vCPU.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 tools/testing/selftests/kvm/aarch64/psci_test.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/kvm/aarch64/psci_test.c b/tools/testing/selftests/kvm/aarch64/psci_test.c
index 8c998f0b802c..fe1d5d343a2f 100644
--- a/tools/testing/selftests/kvm/aarch64/psci_test.c
+++ b/tools/testing/selftests/kvm/aarch64/psci_test.c
@@ -60,6 +60,15 @@ static void guest_main(uint64_t target_cpu)
 	GUEST_DONE();
 }
 
+static void vcpu_power_off(struct kvm_vm *vm, uint32_t vcpuid)
+{
+	struct kvm_mp_state mp_state = {
+		.mp_state = KVM_MP_STATE_STOPPED,
+	};
+
+	vcpu_set_mp_state(vm, vcpuid, &mp_state);
+}
+
 int main(void)
 {
 	uint64_t target_mpidr, obs_pc, obs_x0;
@@ -75,12 +84,12 @@ int main(void)
 	init.features[0] |= (1 << KVM_ARM_VCPU_PSCI_0_2);
 
 	aarch64_vcpu_add_default(vm, VCPU_ID_SOURCE, &init, guest_main);
+	aarch64_vcpu_add_default(vm, VCPU_ID_TARGET, &init, guest_main);
 
 	/*
 	 * make sure the target is already off when executing the test.
 	 */
-	init.features[0] |= (1 << KVM_ARM_VCPU_POWER_OFF);
-	aarch64_vcpu_add_default(vm, VCPU_ID_TARGET, &init, guest_main);
+	vcpu_power_off(vm, VCPU_ID_TARGET);
 
 	get_reg(vm, VCPU_ID_TARGET, KVM_ARM64_SYS_REG(SYS_MPIDR_EL1), &target_mpidr);
 	vcpu_args_set(vm, VCPU_ID_SOURCE, 1, target_mpidr & MPIDR_HWID_BITMASK);
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 13/15] selftests: KVM: Use KVM_SET_MP_STATE to power off vCPU in psci_test
@ 2022-03-11 17:39   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:39 UTC (permalink / raw)
  To: kvmarm
  Cc: maz, wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

Setting a vCPU's MP state to KVM_MP_STATE_STOPPED has the effect of
powering off the vCPU. Rather than using the vCPU init feature flag, use
the KVM_SET_MP_STATE ioctl to power off the target vCPU.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 tools/testing/selftests/kvm/aarch64/psci_test.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/tools/testing/selftests/kvm/aarch64/psci_test.c b/tools/testing/selftests/kvm/aarch64/psci_test.c
index 8c998f0b802c..fe1d5d343a2f 100644
--- a/tools/testing/selftests/kvm/aarch64/psci_test.c
+++ b/tools/testing/selftests/kvm/aarch64/psci_test.c
@@ -60,6 +60,15 @@ static void guest_main(uint64_t target_cpu)
 	GUEST_DONE();
 }
 
+static void vcpu_power_off(struct kvm_vm *vm, uint32_t vcpuid)
+{
+	struct kvm_mp_state mp_state = {
+		.mp_state = KVM_MP_STATE_STOPPED,
+	};
+
+	vcpu_set_mp_state(vm, vcpuid, &mp_state);
+}
+
 int main(void)
 {
 	uint64_t target_mpidr, obs_pc, obs_x0;
@@ -75,12 +84,12 @@ int main(void)
 	init.features[0] |= (1 << KVM_ARM_VCPU_PSCI_0_2);
 
 	aarch64_vcpu_add_default(vm, VCPU_ID_SOURCE, &init, guest_main);
+	aarch64_vcpu_add_default(vm, VCPU_ID_TARGET, &init, guest_main);
 
 	/*
 	 * make sure the target is already off when executing the test.
 	 */
-	init.features[0] |= (1 << KVM_ARM_VCPU_POWER_OFF);
-	aarch64_vcpu_add_default(vm, VCPU_ID_TARGET, &init, guest_main);
+	vcpu_power_off(vm, VCPU_ID_TARGET);
 
 	get_reg(vm, VCPU_ID_TARGET, KVM_ARM64_SYS_REG(SYS_MPIDR_EL1), &target_mpidr);
 	vcpu_args_set(vm, VCPU_ID_SOURCE, 1, target_mpidr & MPIDR_HWID_BITMASK);
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 14/15] selftests: KVM: Refactor psci_test to make it amenable to new tests
  2022-03-11 17:39 ` Oliver Upton
@ 2022-03-11 17:40   ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:40 UTC (permalink / raw)
  To: kvmarm
  Cc: alexandru.elisei, anup, atishp, james.morse, jingzhangos,
	jmattson, joro, kvm-riscv, kvm, maz, pbonzini, pshier, rananta,
	reijiw, ricarkol, seanjc, suzuki.poulose, vkuznets, wanpengli,
	Oliver Upton, Andrew Jones

Split up the current test into several helpers that will be useful to
subsequent test cases added to the PSCI test suite.

Signed-off-by: Oliver Upton <oupton@google.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
---
 .../testing/selftests/kvm/aarch64/psci_test.c | 97 ++++++++++++-------
 1 file changed, 60 insertions(+), 37 deletions(-)

diff --git a/tools/testing/selftests/kvm/aarch64/psci_test.c b/tools/testing/selftests/kvm/aarch64/psci_test.c
index fe1d5d343a2f..535130d5e97f 100644
--- a/tools/testing/selftests/kvm/aarch64/psci_test.c
+++ b/tools/testing/selftests/kvm/aarch64/psci_test.c
@@ -45,21 +45,6 @@ static uint64_t psci_affinity_info(uint64_t target_affinity,
 	return res.a0;
 }
 
-static void guest_main(uint64_t target_cpu)
-{
-	GUEST_ASSERT(!psci_cpu_on(target_cpu, CPU_ON_ENTRY_ADDR, CPU_ON_CONTEXT_ID));
-	uint64_t target_state;
-
-	do {
-		target_state = psci_affinity_info(target_cpu, 0);
-
-		GUEST_ASSERT((target_state == PSCI_0_2_AFFINITY_LEVEL_ON) ||
-			     (target_state == PSCI_0_2_AFFINITY_LEVEL_OFF));
-	} while (target_state != PSCI_0_2_AFFINITY_LEVEL_ON);
-
-	GUEST_DONE();
-}
-
 static void vcpu_power_off(struct kvm_vm *vm, uint32_t vcpuid)
 {
 	struct kvm_mp_state mp_state = {
@@ -69,12 +54,10 @@ static void vcpu_power_off(struct kvm_vm *vm, uint32_t vcpuid)
 	vcpu_set_mp_state(vm, vcpuid, &mp_state);
 }
 
-int main(void)
+static struct kvm_vm *setup_vm(void *guest_code)
 {
-	uint64_t target_mpidr, obs_pc, obs_x0;
 	struct kvm_vcpu_init init;
 	struct kvm_vm *vm;
-	struct ucall uc;
 
 	vm = vm_create(VM_MODE_DEFAULT, DEFAULT_GUEST_PHY_PAGES, O_RDWR);
 	kvm_vm_elf_load(vm, program_invocation_name);
@@ -83,31 +66,28 @@ int main(void)
 	vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &init);
 	init.features[0] |= (1 << KVM_ARM_VCPU_PSCI_0_2);
 
-	aarch64_vcpu_add_default(vm, VCPU_ID_SOURCE, &init, guest_main);
-	aarch64_vcpu_add_default(vm, VCPU_ID_TARGET, &init, guest_main);
+	aarch64_vcpu_add_default(vm, VCPU_ID_SOURCE, &init, guest_code);
+	aarch64_vcpu_add_default(vm, VCPU_ID_TARGET, &init, guest_code);
 
-	/*
-	 * make sure the target is already off when executing the test.
-	 */
-	vcpu_power_off(vm, VCPU_ID_TARGET);
+	return vm;
+}
 
-	get_reg(vm, VCPU_ID_TARGET, KVM_ARM64_SYS_REG(SYS_MPIDR_EL1), &target_mpidr);
-	vcpu_args_set(vm, VCPU_ID_SOURCE, 1, target_mpidr & MPIDR_HWID_BITMASK);
-	vcpu_run(vm, VCPU_ID_SOURCE);
+static void enter_guest(struct kvm_vm *vm, uint32_t vcpuid)
+{
+	struct ucall uc;
 
-	switch (get_ucall(vm, VCPU_ID_SOURCE, &uc)) {
-	case UCALL_DONE:
-		break;
-	case UCALL_ABORT:
+	vcpu_run(vm, vcpuid);
+	if (get_ucall(vm, vcpuid, &uc) == UCALL_ABORT)
 		TEST_FAIL("%s at %s:%ld", (const char *)uc.args[0], __FILE__,
 			  uc.args[1]);
-		break;
-	default:
-		TEST_FAIL("Unhandled ucall: %lu", uc.cmd);
-	}
+}
+
+static void assert_vcpu_reset(struct kvm_vm *vm, uint32_t vcpuid)
+{
+	uint64_t obs_pc, obs_x0;
 
-	get_reg(vm, VCPU_ID_TARGET, ARM64_CORE_REG(regs.pc), &obs_pc);
-	get_reg(vm, VCPU_ID_TARGET, ARM64_CORE_REG(regs.regs[0]), &obs_x0);
+	get_reg(vm, vcpuid, ARM64_CORE_REG(regs.pc), &obs_pc);
+	get_reg(vm, vcpuid, ARM64_CORE_REG(regs.regs[0]), &obs_x0);
 
 	TEST_ASSERT(obs_pc == CPU_ON_ENTRY_ADDR,
 		    "unexpected target cpu pc: %lx (expected: %lx)",
@@ -115,7 +95,50 @@ int main(void)
 	TEST_ASSERT(obs_x0 == CPU_ON_CONTEXT_ID,
 		    "unexpected target context id: %lx (expected: %lx)",
 		    obs_x0, CPU_ON_CONTEXT_ID);
+}
+
+static void guest_test_cpu_on(uint64_t target_cpu)
+{
+	uint64_t target_state;
+
+	GUEST_ASSERT(!psci_cpu_on(target_cpu, CPU_ON_ENTRY_ADDR, CPU_ON_CONTEXT_ID));
+
+	do {
+		target_state = psci_affinity_info(target_cpu, 0);
+
+		GUEST_ASSERT((target_state == PSCI_0_2_AFFINITY_LEVEL_ON) ||
+			     (target_state == PSCI_0_2_AFFINITY_LEVEL_OFF));
+	} while (target_state != PSCI_0_2_AFFINITY_LEVEL_ON);
+
+	GUEST_DONE();
+}
+
+static void host_test_cpu_on(void)
+{
+	uint64_t target_mpidr;
+	struct kvm_vm *vm;
+	struct ucall uc;
+
+	vm = setup_vm(guest_test_cpu_on);
+
+	/*
+	 * make sure the target is already off when executing the test.
+	 */
+	vcpu_power_off(vm, VCPU_ID_TARGET);
+
+	get_reg(vm, VCPU_ID_TARGET, KVM_ARM64_SYS_REG(SYS_MPIDR_EL1), &target_mpidr);
+	vcpu_args_set(vm, VCPU_ID_SOURCE, 1, target_mpidr & MPIDR_HWID_BITMASK);
+	enter_guest(vm, VCPU_ID_SOURCE);
+
+	if (get_ucall(vm, VCPU_ID_SOURCE, &uc) != UCALL_DONE)
+		TEST_FAIL("Unhandled ucall: %lu", uc.cmd);
 
+	assert_vcpu_reset(vm, VCPU_ID_TARGET);
 	kvm_vm_free(vm);
+}
+
+int main(void)
+{
+	host_test_cpu_on();
 	return 0;
 }
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 14/15] selftests: KVM: Refactor psci_test to make it amenable to new tests
@ 2022-03-11 17:40   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:40 UTC (permalink / raw)
  To: kvmarm
  Cc: maz, wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

Split up the current test into several helpers that will be useful to
subsequent test cases added to the PSCI test suite.

Signed-off-by: Oliver Upton <oupton@google.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
---
 .../testing/selftests/kvm/aarch64/psci_test.c | 97 ++++++++++++-------
 1 file changed, 60 insertions(+), 37 deletions(-)

diff --git a/tools/testing/selftests/kvm/aarch64/psci_test.c b/tools/testing/selftests/kvm/aarch64/psci_test.c
index fe1d5d343a2f..535130d5e97f 100644
--- a/tools/testing/selftests/kvm/aarch64/psci_test.c
+++ b/tools/testing/selftests/kvm/aarch64/psci_test.c
@@ -45,21 +45,6 @@ static uint64_t psci_affinity_info(uint64_t target_affinity,
 	return res.a0;
 }
 
-static void guest_main(uint64_t target_cpu)
-{
-	GUEST_ASSERT(!psci_cpu_on(target_cpu, CPU_ON_ENTRY_ADDR, CPU_ON_CONTEXT_ID));
-	uint64_t target_state;
-
-	do {
-		target_state = psci_affinity_info(target_cpu, 0);
-
-		GUEST_ASSERT((target_state == PSCI_0_2_AFFINITY_LEVEL_ON) ||
-			     (target_state == PSCI_0_2_AFFINITY_LEVEL_OFF));
-	} while (target_state != PSCI_0_2_AFFINITY_LEVEL_ON);
-
-	GUEST_DONE();
-}
-
 static void vcpu_power_off(struct kvm_vm *vm, uint32_t vcpuid)
 {
 	struct kvm_mp_state mp_state = {
@@ -69,12 +54,10 @@ static void vcpu_power_off(struct kvm_vm *vm, uint32_t vcpuid)
 	vcpu_set_mp_state(vm, vcpuid, &mp_state);
 }
 
-int main(void)
+static struct kvm_vm *setup_vm(void *guest_code)
 {
-	uint64_t target_mpidr, obs_pc, obs_x0;
 	struct kvm_vcpu_init init;
 	struct kvm_vm *vm;
-	struct ucall uc;
 
 	vm = vm_create(VM_MODE_DEFAULT, DEFAULT_GUEST_PHY_PAGES, O_RDWR);
 	kvm_vm_elf_load(vm, program_invocation_name);
@@ -83,31 +66,28 @@ int main(void)
 	vm_ioctl(vm, KVM_ARM_PREFERRED_TARGET, &init);
 	init.features[0] |= (1 << KVM_ARM_VCPU_PSCI_0_2);
 
-	aarch64_vcpu_add_default(vm, VCPU_ID_SOURCE, &init, guest_main);
-	aarch64_vcpu_add_default(vm, VCPU_ID_TARGET, &init, guest_main);
+	aarch64_vcpu_add_default(vm, VCPU_ID_SOURCE, &init, guest_code);
+	aarch64_vcpu_add_default(vm, VCPU_ID_TARGET, &init, guest_code);
 
-	/*
-	 * make sure the target is already off when executing the test.
-	 */
-	vcpu_power_off(vm, VCPU_ID_TARGET);
+	return vm;
+}
 
-	get_reg(vm, VCPU_ID_TARGET, KVM_ARM64_SYS_REG(SYS_MPIDR_EL1), &target_mpidr);
-	vcpu_args_set(vm, VCPU_ID_SOURCE, 1, target_mpidr & MPIDR_HWID_BITMASK);
-	vcpu_run(vm, VCPU_ID_SOURCE);
+static void enter_guest(struct kvm_vm *vm, uint32_t vcpuid)
+{
+	struct ucall uc;
 
-	switch (get_ucall(vm, VCPU_ID_SOURCE, &uc)) {
-	case UCALL_DONE:
-		break;
-	case UCALL_ABORT:
+	vcpu_run(vm, vcpuid);
+	if (get_ucall(vm, vcpuid, &uc) == UCALL_ABORT)
 		TEST_FAIL("%s at %s:%ld", (const char *)uc.args[0], __FILE__,
 			  uc.args[1]);
-		break;
-	default:
-		TEST_FAIL("Unhandled ucall: %lu", uc.cmd);
-	}
+}
+
+static void assert_vcpu_reset(struct kvm_vm *vm, uint32_t vcpuid)
+{
+	uint64_t obs_pc, obs_x0;
 
-	get_reg(vm, VCPU_ID_TARGET, ARM64_CORE_REG(regs.pc), &obs_pc);
-	get_reg(vm, VCPU_ID_TARGET, ARM64_CORE_REG(regs.regs[0]), &obs_x0);
+	get_reg(vm, vcpuid, ARM64_CORE_REG(regs.pc), &obs_pc);
+	get_reg(vm, vcpuid, ARM64_CORE_REG(regs.regs[0]), &obs_x0);
 
 	TEST_ASSERT(obs_pc == CPU_ON_ENTRY_ADDR,
 		    "unexpected target cpu pc: %lx (expected: %lx)",
@@ -115,7 +95,50 @@ int main(void)
 	TEST_ASSERT(obs_x0 == CPU_ON_CONTEXT_ID,
 		    "unexpected target context id: %lx (expected: %lx)",
 		    obs_x0, CPU_ON_CONTEXT_ID);
+}
+
+static void guest_test_cpu_on(uint64_t target_cpu)
+{
+	uint64_t target_state;
+
+	GUEST_ASSERT(!psci_cpu_on(target_cpu, CPU_ON_ENTRY_ADDR, CPU_ON_CONTEXT_ID));
+
+	do {
+		target_state = psci_affinity_info(target_cpu, 0);
+
+		GUEST_ASSERT((target_state == PSCI_0_2_AFFINITY_LEVEL_ON) ||
+			     (target_state == PSCI_0_2_AFFINITY_LEVEL_OFF));
+	} while (target_state != PSCI_0_2_AFFINITY_LEVEL_ON);
+
+	GUEST_DONE();
+}
+
+static void host_test_cpu_on(void)
+{
+	uint64_t target_mpidr;
+	struct kvm_vm *vm;
+	struct ucall uc;
+
+	vm = setup_vm(guest_test_cpu_on);
+
+	/*
+	 * make sure the target is already off when executing the test.
+	 */
+	vcpu_power_off(vm, VCPU_ID_TARGET);
+
+	get_reg(vm, VCPU_ID_TARGET, KVM_ARM64_SYS_REG(SYS_MPIDR_EL1), &target_mpidr);
+	vcpu_args_set(vm, VCPU_ID_SOURCE, 1, target_mpidr & MPIDR_HWID_BITMASK);
+	enter_guest(vm, VCPU_ID_SOURCE);
+
+	if (get_ucall(vm, VCPU_ID_SOURCE, &uc) != UCALL_DONE)
+		TEST_FAIL("Unhandled ucall: %lu", uc.cmd);
 
+	assert_vcpu_reset(vm, VCPU_ID_TARGET);
 	kvm_vm_free(vm);
+}
+
+int main(void)
+{
+	host_test_cpu_on();
 	return 0;
 }
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 15/15] selftests: KVM: Test SYSTEM_SUSPEND PSCI call
  2022-03-11 17:39 ` Oliver Upton
@ 2022-03-11 17:40   ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:40 UTC (permalink / raw)
  To: kvmarm
  Cc: alexandru.elisei, anup, atishp, james.morse, jingzhangos,
	jmattson, joro, kvm-riscv, kvm, maz, pbonzini, pshier, rananta,
	reijiw, ricarkol, seanjc, suzuki.poulose, vkuznets, wanpengli,
	Oliver Upton

Assert that the vCPU exits to userspace with KVM_SYSTEM_EVENT_SUSPEND if
the guest calls PSCI SYSTEM_SUSPEND. Additionally, guarantee that the
SMC32 and SMC64 flavors of this call are discoverable with the
PSCI_FEATURES call.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 .../testing/selftests/kvm/aarch64/psci_test.c | 69 +++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/tools/testing/selftests/kvm/aarch64/psci_test.c b/tools/testing/selftests/kvm/aarch64/psci_test.c
index 535130d5e97f..88541de21c41 100644
--- a/tools/testing/selftests/kvm/aarch64/psci_test.c
+++ b/tools/testing/selftests/kvm/aarch64/psci_test.c
@@ -45,6 +45,25 @@ static uint64_t psci_affinity_info(uint64_t target_affinity,
 	return res.a0;
 }
 
+static uint64_t psci_system_suspend(uint64_t entry_addr, uint64_t context_id)
+{
+	struct arm_smccc_res res;
+
+	smccc_hvc(PSCI_1_0_FN64_SYSTEM_SUSPEND, entry_addr, context_id,
+		  0, 0, 0, 0, 0, &res);
+
+	return res.a0;
+}
+
+static uint64_t psci_features(uint32_t func_id)
+{
+	struct arm_smccc_res res;
+
+	smccc_hvc(PSCI_1_0_FN_PSCI_FEATURES, func_id, 0, 0, 0, 0, 0, 0, &res);
+
+	return res.a0;
+}
+
 static void vcpu_power_off(struct kvm_vm *vm, uint32_t vcpuid)
 {
 	struct kvm_mp_state mp_state = {
@@ -137,8 +156,58 @@ static void host_test_cpu_on(void)
 	kvm_vm_free(vm);
 }
 
+static void enable_system_suspend(struct kvm_vm *vm)
+{
+	struct kvm_enable_cap cap = {
+		.cap = KVM_CAP_ARM_SYSTEM_SUSPEND,
+	};
+
+	vm_enable_cap(vm, &cap);
+}
+
+static void guest_test_system_suspend(void)
+{
+	uint64_t ret;
+
+	/* assert that SYSTEM_SUSPEND is discoverable */
+	GUEST_ASSERT(!psci_features(PSCI_1_0_FN_SYSTEM_SUSPEND));
+	GUEST_ASSERT(!psci_features(PSCI_1_0_FN64_SYSTEM_SUSPEND));
+
+	ret = psci_system_suspend(CPU_ON_ENTRY_ADDR, CPU_ON_CONTEXT_ID);
+	GUEST_SYNC(ret);
+}
+
+static void host_test_system_suspend(void)
+{
+	struct kvm_run *run;
+	struct kvm_vm *vm;
+
+	vm = setup_vm(guest_test_system_suspend);
+	enable_system_suspend(vm);
+
+	vcpu_power_off(vm, VCPU_ID_TARGET);
+	run = vcpu_state(vm, VCPU_ID_SOURCE);
+
+	enter_guest(vm, VCPU_ID_SOURCE);
+
+	TEST_ASSERT(run->exit_reason == KVM_EXIT_SYSTEM_EVENT,
+		    "Unhandled exit reason: %u (%s)",
+		    run->exit_reason, exit_reason_str(run->exit_reason));
+	TEST_ASSERT(run->system_event.type == KVM_SYSTEM_EVENT_SUSPEND,
+		    "Unhandled system event: %u (expected: %u)",
+		    run->system_event.type, KVM_SYSTEM_EVENT_SUSPEND);
+
+	kvm_vm_free(vm);
+}
+
 int main(void)
 {
+	if (!kvm_check_cap(KVM_CAP_ARM_SYSTEM_SUSPEND)) {
+		print_skip("KVM_CAP_ARM_SYSTEM_SUSPEND not supported");
+		exit(KSFT_SKIP);
+	}
+
 	host_test_cpu_on();
+	host_test_system_suspend();
 	return 0;
 }
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v4 15/15] selftests: KVM: Test SYSTEM_SUSPEND PSCI call
@ 2022-03-11 17:40   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:40 UTC (permalink / raw)
  To: kvmarm
  Cc: maz, wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

Assert that the vCPU exits to userspace with KVM_SYSTEM_EVENT_SUSPEND if
the guest calls PSCI SYSTEM_SUSPEND. Additionally, guarantee that the
SMC32 and SMC64 flavors of this call are discoverable with the
PSCI_FEATURES call.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 .../testing/selftests/kvm/aarch64/psci_test.c | 69 +++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/tools/testing/selftests/kvm/aarch64/psci_test.c b/tools/testing/selftests/kvm/aarch64/psci_test.c
index 535130d5e97f..88541de21c41 100644
--- a/tools/testing/selftests/kvm/aarch64/psci_test.c
+++ b/tools/testing/selftests/kvm/aarch64/psci_test.c
@@ -45,6 +45,25 @@ static uint64_t psci_affinity_info(uint64_t target_affinity,
 	return res.a0;
 }
 
+static uint64_t psci_system_suspend(uint64_t entry_addr, uint64_t context_id)
+{
+	struct arm_smccc_res res;
+
+	smccc_hvc(PSCI_1_0_FN64_SYSTEM_SUSPEND, entry_addr, context_id,
+		  0, 0, 0, 0, 0, &res);
+
+	return res.a0;
+}
+
+static uint64_t psci_features(uint32_t func_id)
+{
+	struct arm_smccc_res res;
+
+	smccc_hvc(PSCI_1_0_FN_PSCI_FEATURES, func_id, 0, 0, 0, 0, 0, 0, &res);
+
+	return res.a0;
+}
+
 static void vcpu_power_off(struct kvm_vm *vm, uint32_t vcpuid)
 {
 	struct kvm_mp_state mp_state = {
@@ -137,8 +156,58 @@ static void host_test_cpu_on(void)
 	kvm_vm_free(vm);
 }
 
+static void enable_system_suspend(struct kvm_vm *vm)
+{
+	struct kvm_enable_cap cap = {
+		.cap = KVM_CAP_ARM_SYSTEM_SUSPEND,
+	};
+
+	vm_enable_cap(vm, &cap);
+}
+
+static void guest_test_system_suspend(void)
+{
+	uint64_t ret;
+
+	/* assert that SYSTEM_SUSPEND is discoverable */
+	GUEST_ASSERT(!psci_features(PSCI_1_0_FN_SYSTEM_SUSPEND));
+	GUEST_ASSERT(!psci_features(PSCI_1_0_FN64_SYSTEM_SUSPEND));
+
+	ret = psci_system_suspend(CPU_ON_ENTRY_ADDR, CPU_ON_CONTEXT_ID);
+	GUEST_SYNC(ret);
+}
+
+static void host_test_system_suspend(void)
+{
+	struct kvm_run *run;
+	struct kvm_vm *vm;
+
+	vm = setup_vm(guest_test_system_suspend);
+	enable_system_suspend(vm);
+
+	vcpu_power_off(vm, VCPU_ID_TARGET);
+	run = vcpu_state(vm, VCPU_ID_SOURCE);
+
+	enter_guest(vm, VCPU_ID_SOURCE);
+
+	TEST_ASSERT(run->exit_reason == KVM_EXIT_SYSTEM_EVENT,
+		    "Unhandled exit reason: %u (%s)",
+		    run->exit_reason, exit_reason_str(run->exit_reason));
+	TEST_ASSERT(run->system_event.type == KVM_SYSTEM_EVENT_SUSPEND,
+		    "Unhandled system event: %u (expected: %u)",
+		    run->system_event.type, KVM_SYSTEM_EVENT_SUSPEND);
+
+	kvm_vm_free(vm);
+}
+
 int main(void)
 {
+	if (!kvm_check_cap(KVM_CAP_ARM_SYSTEM_SUSPEND)) {
+		print_skip("KVM_CAP_ARM_SYSTEM_SUSPEND not supported");
+		exit(KSFT_SKIP);
+	}
+
 	host_test_cpu_on();
+	host_test_system_suspend();
 	return 0;
 }
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 0/5] ARM: Implement PSCI SYSTEM_SUSPEND
  2022-03-11 17:39 ` Oliver Upton
  (?)
@ 2022-03-11 17:57   ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, Marc Zyngier, James Morse, Alexandru Elisei,
	Suzuki K Poulose, linux-arm-kernel, Peter Shier, Ricardo Koller,
	Reiji Watanabe, Will Deacon, Julien Thierry, Oliver Upton

This is a prototype for supporting KVM_CAP_ARM_SYSTEM_SUSPEND on
kvmtool. The capability allows userspace to expose the SYSTEM_SUSPEND
PSCI call to its guests.

Implement SYSTEM_SUSPEND using KVM_MP_STATE_SUSPENDED, which emulates
the execution of a WFI instruction in the kernel. Resume the guest when
a wakeup event is recognized and reset it to the requested entry address
and context ID.

Patches 2-4 are small reworks to more easily shoehorn PSCI support into
kvmtool.

Patch 5 adds some SMCCC handlers and makes use of them to implement PSCI
SYSTEM_SUSPEND. For now, just check the bare-minimum, that all vCPUs
besides the caller have stopped. There are also checks that can be made
against the requested entry address, but they are at the discretion of
the implementation.

Tested with 'echo mem > /sys/power/state' to see that the vCPU is in
fact placed in a suspended state for the PSCI call. Hacked the switch
statement to fall through to WAKEUP immediately after to verify the vCPU
is set up correctly for resume.

It would be nice if kvmtool actually provided a device good for wakeups,
since the RTC implementation has omitted any interrupt support.

kernel changes: http://lore.kernel.org/r/20220311174001.605719-1-oupton@google.com

Oliver Upton (5):
  TESTONLY: Sync KVM headers with pending changes
  Allow architectures to hook KVM_EXIT_SYSTEM_EVENT
  ARM: Stash vcpu_init in the vCPU structure
  ARM: Add a helper to re-init a vCPU
  ARM: Implement PSCI SYSTEM_SUSPEND

 arm/aarch32/kvm-cpu.c                 | 72 ++++++++++++++++++++
 arm/aarch64/kvm-cpu.c                 | 66 +++++++++++++++++++
 arm/include/arm-common/kvm-cpu-arch.h | 23 ++++---
 arm/kvm-cpu.c                         | 95 ++++++++++++++++++++++++++-
 arm/kvm.c                             |  9 +++
 include/kvm/kvm-cpu.h                 |  1 +
 include/linux/kvm.h                   | 21 ++++++
 kvm-cpu.c                             |  8 +++
 8 files changed, 283 insertions(+), 12 deletions(-)

-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 0/5] ARM: Implement PSCI SYSTEM_SUSPEND
@ 2022-03-11 17:57   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm; +Cc: kvm, Will Deacon, Marc Zyngier, Peter Shier, linux-arm-kernel

This is a prototype for supporting KVM_CAP_ARM_SYSTEM_SUSPEND on
kvmtool. The capability allows userspace to expose the SYSTEM_SUSPEND
PSCI call to its guests.

Implement SYSTEM_SUSPEND using KVM_MP_STATE_SUSPENDED, which emulates
the execution of a WFI instruction in the kernel. Resume the guest when
a wakeup event is recognized and reset it to the requested entry address
and context ID.

Patches 2-4 are small reworks to more easily shoehorn PSCI support into
kvmtool.

Patch 5 adds some SMCCC handlers and makes use of them to implement PSCI
SYSTEM_SUSPEND. For now, just check the bare-minimum, that all vCPUs
besides the caller have stopped. There are also checks that can be made
against the requested entry address, but they are at the discretion of
the implementation.

Tested with 'echo mem > /sys/power/state' to see that the vCPU is in
fact placed in a suspended state for the PSCI call. Hacked the switch
statement to fall through to WAKEUP immediately after to verify the vCPU
is set up correctly for resume.

It would be nice if kvmtool actually provided a device good for wakeups,
since the RTC implementation has omitted any interrupt support.

kernel changes: http://lore.kernel.org/r/20220311174001.605719-1-oupton@google.com

Oliver Upton (5):
  TESTONLY: Sync KVM headers with pending changes
  Allow architectures to hook KVM_EXIT_SYSTEM_EVENT
  ARM: Stash vcpu_init in the vCPU structure
  ARM: Add a helper to re-init a vCPU
  ARM: Implement PSCI SYSTEM_SUSPEND

 arm/aarch32/kvm-cpu.c                 | 72 ++++++++++++++++++++
 arm/aarch64/kvm-cpu.c                 | 66 +++++++++++++++++++
 arm/include/arm-common/kvm-cpu-arch.h | 23 ++++---
 arm/kvm-cpu.c                         | 95 ++++++++++++++++++++++++++-
 arm/kvm.c                             |  9 +++
 include/kvm/kvm-cpu.h                 |  1 +
 include/linux/kvm.h                   | 21 ++++++
 kvm-cpu.c                             |  8 +++
 8 files changed, 283 insertions(+), 12 deletions(-)

-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 0/5] ARM: Implement PSCI SYSTEM_SUSPEND
@ 2022-03-11 17:57   ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, Marc Zyngier, James Morse, Alexandru Elisei,
	Suzuki K Poulose, linux-arm-kernel, Peter Shier, Ricardo Koller,
	Reiji Watanabe, Will Deacon, Julien Thierry, Oliver Upton

This is a prototype for supporting KVM_CAP_ARM_SYSTEM_SUSPEND on
kvmtool. The capability allows userspace to expose the SYSTEM_SUSPEND
PSCI call to its guests.

Implement SYSTEM_SUSPEND using KVM_MP_STATE_SUSPENDED, which emulates
the execution of a WFI instruction in the kernel. Resume the guest when
a wakeup event is recognized and reset it to the requested entry address
and context ID.

Patches 2-4 are small reworks to more easily shoehorn PSCI support into
kvmtool.

Patch 5 adds some SMCCC handlers and makes use of them to implement PSCI
SYSTEM_SUSPEND. For now, just check the bare-minimum, that all vCPUs
besides the caller have stopped. There are also checks that can be made
against the requested entry address, but they are at the discretion of
the implementation.

Tested with 'echo mem > /sys/power/state' to see that the vCPU is in
fact placed in a suspended state for the PSCI call. Hacked the switch
statement to fall through to WAKEUP immediately after to verify the vCPU
is set up correctly for resume.

It would be nice if kvmtool actually provided a device good for wakeups,
since the RTC implementation has omitted any interrupt support.

kernel changes: http://lore.kernel.org/r/20220311174001.605719-1-oupton@google.com

Oliver Upton (5):
  TESTONLY: Sync KVM headers with pending changes
  Allow architectures to hook KVM_EXIT_SYSTEM_EVENT
  ARM: Stash vcpu_init in the vCPU structure
  ARM: Add a helper to re-init a vCPU
  ARM: Implement PSCI SYSTEM_SUSPEND

 arm/aarch32/kvm-cpu.c                 | 72 ++++++++++++++++++++
 arm/aarch64/kvm-cpu.c                 | 66 +++++++++++++++++++
 arm/include/arm-common/kvm-cpu-arch.h | 23 ++++---
 arm/kvm-cpu.c                         | 95 ++++++++++++++++++++++++++-
 arm/kvm.c                             |  9 +++
 include/kvm/kvm-cpu.h                 |  1 +
 include/linux/kvm.h                   | 21 ++++++
 kvm-cpu.c                             |  8 +++
 8 files changed, 283 insertions(+), 12 deletions(-)

-- 
2.35.1.723.g4982287a31-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 1/5] TESTONLY: Sync KVM headers with pending changes
  2022-03-11 17:57   ` Oliver Upton
  (?)
@ 2022-03-11 17:57     ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, Marc Zyngier, James Morse, Alexandru Elisei,
	Suzuki K Poulose, linux-arm-kernel, Peter Shier, Ricardo Koller,
	Reiji Watanabe, Will Deacon, Julien Thierry, Oliver Upton

Signed-off-by: Oliver Upton <oupton@google.com>
---
 include/linux/kvm.h | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 1daa452..e5bb5f1 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -444,6 +444,8 @@ struct kvm_run {
 #define KVM_SYSTEM_EVENT_SHUTDOWN       1
 #define KVM_SYSTEM_EVENT_RESET          2
 #define KVM_SYSTEM_EVENT_CRASH          3
+#define KVM_SYSTEM_EVENT_WAKEUP         4
+#define KVM_SYSTEM_EVENT_SUSPEND        5
 			__u32 type;
 			__u64 flags;
 		} system_event;
@@ -634,6 +636,7 @@ struct kvm_vapic_addr {
 #define KVM_MP_STATE_OPERATING         7
 #define KVM_MP_STATE_LOAD              8
 #define KVM_MP_STATE_AP_RESET_HOLD     9
+#define KVM_MP_STATE_SUSPENDED         10
 
 struct kvm_mp_state {
 	__u32 mp_state;
@@ -1131,6 +1134,10 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204
 #define KVM_CAP_ARM_MTE 205
 #define KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM 206
+#define KVM_CAP_VM_GPA_BITS 207
+#define KVM_CAP_XSAVE2 208
+#define KVM_CAP_SYS_ATTRIBUTES 209
+#define KVM_CAP_ARM_SYSTEM_SUSPEND 210
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1162,11 +1169,20 @@ struct kvm_irq_routing_hv_sint {
 	__u32 sint;
 };
 
+struct kvm_irq_routing_xen_evtchn {
+	__u32 port;
+	__u32 vcpu;
+	__u32 priority;
+};
+
+#define KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL ((__u32)(-1))
+
 /* gsi routing entry types */
 #define KVM_IRQ_ROUTING_IRQCHIP 1
 #define KVM_IRQ_ROUTING_MSI 2
 #define KVM_IRQ_ROUTING_S390_ADAPTER 3
 #define KVM_IRQ_ROUTING_HV_SINT 4
+#define KVM_IRQ_ROUTING_XEN_EVTCHN 5
 
 struct kvm_irq_routing_entry {
 	__u32 gsi;
@@ -1178,6 +1194,7 @@ struct kvm_irq_routing_entry {
 		struct kvm_irq_routing_msi msi;
 		struct kvm_irq_routing_s390_adapter adapter;
 		struct kvm_irq_routing_hv_sint hv_sint;
+		struct kvm_irq_routing_xen_evtchn xen_evtchn;
 		__u32 pad[8];
 	} u;
 };
@@ -1208,6 +1225,7 @@ struct kvm_x86_mce {
 #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL	(1 << 1)
 #define KVM_XEN_HVM_CONFIG_SHARED_INFO		(1 << 2)
 #define KVM_XEN_HVM_CONFIG_RUNSTATE		(1 << 3)
+#define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL	(1 << 4)
 
 struct kvm_xen_hvm_config {
 	__u32 flags;
@@ -2031,4 +2049,7 @@ struct kvm_stats_desc {
 
 #define KVM_GET_STATS_FD  _IO(KVMIO,  0xce)
 
+/* Available with KVM_CAP_XSAVE2 */
+#define KVM_GET_XSAVE2		  _IOR(KVMIO,  0xcf, struct kvm_xsave)
+
 #endif /* __LINUX_KVM_H */
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 1/5] TESTONLY: Sync KVM headers with pending changes
@ 2022-03-11 17:57     ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm; +Cc: kvm, Will Deacon, Marc Zyngier, Peter Shier, linux-arm-kernel

Signed-off-by: Oliver Upton <oupton@google.com>
---
 include/linux/kvm.h | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 1daa452..e5bb5f1 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -444,6 +444,8 @@ struct kvm_run {
 #define KVM_SYSTEM_EVENT_SHUTDOWN       1
 #define KVM_SYSTEM_EVENT_RESET          2
 #define KVM_SYSTEM_EVENT_CRASH          3
+#define KVM_SYSTEM_EVENT_WAKEUP         4
+#define KVM_SYSTEM_EVENT_SUSPEND        5
 			__u32 type;
 			__u64 flags;
 		} system_event;
@@ -634,6 +636,7 @@ struct kvm_vapic_addr {
 #define KVM_MP_STATE_OPERATING         7
 #define KVM_MP_STATE_LOAD              8
 #define KVM_MP_STATE_AP_RESET_HOLD     9
+#define KVM_MP_STATE_SUSPENDED         10
 
 struct kvm_mp_state {
 	__u32 mp_state;
@@ -1131,6 +1134,10 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204
 #define KVM_CAP_ARM_MTE 205
 #define KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM 206
+#define KVM_CAP_VM_GPA_BITS 207
+#define KVM_CAP_XSAVE2 208
+#define KVM_CAP_SYS_ATTRIBUTES 209
+#define KVM_CAP_ARM_SYSTEM_SUSPEND 210
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1162,11 +1169,20 @@ struct kvm_irq_routing_hv_sint {
 	__u32 sint;
 };
 
+struct kvm_irq_routing_xen_evtchn {
+	__u32 port;
+	__u32 vcpu;
+	__u32 priority;
+};
+
+#define KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL ((__u32)(-1))
+
 /* gsi routing entry types */
 #define KVM_IRQ_ROUTING_IRQCHIP 1
 #define KVM_IRQ_ROUTING_MSI 2
 #define KVM_IRQ_ROUTING_S390_ADAPTER 3
 #define KVM_IRQ_ROUTING_HV_SINT 4
+#define KVM_IRQ_ROUTING_XEN_EVTCHN 5
 
 struct kvm_irq_routing_entry {
 	__u32 gsi;
@@ -1178,6 +1194,7 @@ struct kvm_irq_routing_entry {
 		struct kvm_irq_routing_msi msi;
 		struct kvm_irq_routing_s390_adapter adapter;
 		struct kvm_irq_routing_hv_sint hv_sint;
+		struct kvm_irq_routing_xen_evtchn xen_evtchn;
 		__u32 pad[8];
 	} u;
 };
@@ -1208,6 +1225,7 @@ struct kvm_x86_mce {
 #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL	(1 << 1)
 #define KVM_XEN_HVM_CONFIG_SHARED_INFO		(1 << 2)
 #define KVM_XEN_HVM_CONFIG_RUNSTATE		(1 << 3)
+#define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL	(1 << 4)
 
 struct kvm_xen_hvm_config {
 	__u32 flags;
@@ -2031,4 +2049,7 @@ struct kvm_stats_desc {
 
 #define KVM_GET_STATS_FD  _IO(KVMIO,  0xce)
 
+/* Available with KVM_CAP_XSAVE2 */
+#define KVM_GET_XSAVE2		  _IOR(KVMIO,  0xcf, struct kvm_xsave)
+
 #endif /* __LINUX_KVM_H */
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 1/5] TESTONLY: Sync KVM headers with pending changes
@ 2022-03-11 17:57     ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, Marc Zyngier, James Morse, Alexandru Elisei,
	Suzuki K Poulose, linux-arm-kernel, Peter Shier, Ricardo Koller,
	Reiji Watanabe, Will Deacon, Julien Thierry, Oliver Upton

Signed-off-by: Oliver Upton <oupton@google.com>
---
 include/linux/kvm.h | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 1daa452..e5bb5f1 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -444,6 +444,8 @@ struct kvm_run {
 #define KVM_SYSTEM_EVENT_SHUTDOWN       1
 #define KVM_SYSTEM_EVENT_RESET          2
 #define KVM_SYSTEM_EVENT_CRASH          3
+#define KVM_SYSTEM_EVENT_WAKEUP         4
+#define KVM_SYSTEM_EVENT_SUSPEND        5
 			__u32 type;
 			__u64 flags;
 		} system_event;
@@ -634,6 +636,7 @@ struct kvm_vapic_addr {
 #define KVM_MP_STATE_OPERATING         7
 #define KVM_MP_STATE_LOAD              8
 #define KVM_MP_STATE_AP_RESET_HOLD     9
+#define KVM_MP_STATE_SUSPENDED         10
 
 struct kvm_mp_state {
 	__u32 mp_state;
@@ -1131,6 +1134,10 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204
 #define KVM_CAP_ARM_MTE 205
 #define KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM 206
+#define KVM_CAP_VM_GPA_BITS 207
+#define KVM_CAP_XSAVE2 208
+#define KVM_CAP_SYS_ATTRIBUTES 209
+#define KVM_CAP_ARM_SYSTEM_SUSPEND 210
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1162,11 +1169,20 @@ struct kvm_irq_routing_hv_sint {
 	__u32 sint;
 };
 
+struct kvm_irq_routing_xen_evtchn {
+	__u32 port;
+	__u32 vcpu;
+	__u32 priority;
+};
+
+#define KVM_IRQ_ROUTING_XEN_EVTCHN_PRIO_2LEVEL ((__u32)(-1))
+
 /* gsi routing entry types */
 #define KVM_IRQ_ROUTING_IRQCHIP 1
 #define KVM_IRQ_ROUTING_MSI 2
 #define KVM_IRQ_ROUTING_S390_ADAPTER 3
 #define KVM_IRQ_ROUTING_HV_SINT 4
+#define KVM_IRQ_ROUTING_XEN_EVTCHN 5
 
 struct kvm_irq_routing_entry {
 	__u32 gsi;
@@ -1178,6 +1194,7 @@ struct kvm_irq_routing_entry {
 		struct kvm_irq_routing_msi msi;
 		struct kvm_irq_routing_s390_adapter adapter;
 		struct kvm_irq_routing_hv_sint hv_sint;
+		struct kvm_irq_routing_xen_evtchn xen_evtchn;
 		__u32 pad[8];
 	} u;
 };
@@ -1208,6 +1225,7 @@ struct kvm_x86_mce {
 #define KVM_XEN_HVM_CONFIG_INTERCEPT_HCALL	(1 << 1)
 #define KVM_XEN_HVM_CONFIG_SHARED_INFO		(1 << 2)
 #define KVM_XEN_HVM_CONFIG_RUNSTATE		(1 << 3)
+#define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL	(1 << 4)
 
 struct kvm_xen_hvm_config {
 	__u32 flags;
@@ -2031,4 +2049,7 @@ struct kvm_stats_desc {
 
 #define KVM_GET_STATS_FD  _IO(KVMIO,  0xce)
 
+/* Available with KVM_CAP_XSAVE2 */
+#define KVM_GET_XSAVE2		  _IOR(KVMIO,  0xcf, struct kvm_xsave)
+
 #endif /* __LINUX_KVM_H */
-- 
2.35.1.723.g4982287a31-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 2/5] Allow architectures to hook KVM_EXIT_SYSTEM_EVENT
  2022-03-11 17:57   ` Oliver Upton
  (?)
@ 2022-03-11 17:57     ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, Marc Zyngier, James Morse, Alexandru Elisei,
	Suzuki K Poulose, linux-arm-kernel, Peter Shier, Ricardo Koller,
	Reiji Watanabe, Will Deacon, Julien Thierry, Oliver Upton

Certain system events require architecture-specific handling. Allow
architectures to intervene for exits unhandled by the default exit
handler.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 include/kvm/kvm-cpu.h | 1 +
 kvm-cpu.c             | 8 ++++++++
 2 files changed, 9 insertions(+)

diff --git a/include/kvm/kvm-cpu.h b/include/kvm/kvm-cpu.h
index 0f16f8d..75e42d8 100644
--- a/include/kvm/kvm-cpu.h
+++ b/include/kvm/kvm-cpu.h
@@ -20,6 +20,7 @@ void kvm_cpu__run(struct kvm_cpu *vcpu);
 int kvm_cpu__start(struct kvm_cpu *cpu);
 bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu);
 int kvm_cpu__get_endianness(struct kvm_cpu *vcpu);
+bool kvm_cpu__arch_handle_system_event(struct kvm_cpu *vcpu);
 
 int kvm_cpu__get_debug_fd(void);
 void kvm_cpu__set_debug_fd(int fd);
diff --git a/kvm-cpu.c b/kvm-cpu.c
index 7dec088..d615c37 100644
--- a/kvm-cpu.c
+++ b/kvm-cpu.c
@@ -23,6 +23,11 @@ int __attribute__((weak)) kvm_cpu__get_endianness(struct kvm_cpu *vcpu)
 	return VIRTIO_ENDIAN_HOST;
 }
 
+bool __attribute__((weak)) kvm_cpu__arch_handle_system_event(struct kvm_cpu *vcpu)
+{
+	return false;
+}
+
 void kvm_cpu__enable_singlestep(struct kvm_cpu *vcpu)
 {
 	struct kvm_guest_debug debug = {
@@ -224,6 +229,9 @@ int kvm_cpu__start(struct kvm_cpu *cpu)
 			 */
 			switch (cpu->kvm_run->system_event.type) {
 			default:
+				if (kvm_cpu__arch_handle_system_event(cpu))
+					break;
+
 				pr_warning("unknown system event type %d",
 					   cpu->kvm_run->system_event.type);
 				/* fall through for now */
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 2/5] Allow architectures to hook KVM_EXIT_SYSTEM_EVENT
@ 2022-03-11 17:57     ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm; +Cc: kvm, Will Deacon, Marc Zyngier, Peter Shier, linux-arm-kernel

Certain system events require architecture-specific handling. Allow
architectures to intervene for exits unhandled by the default exit
handler.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 include/kvm/kvm-cpu.h | 1 +
 kvm-cpu.c             | 8 ++++++++
 2 files changed, 9 insertions(+)

diff --git a/include/kvm/kvm-cpu.h b/include/kvm/kvm-cpu.h
index 0f16f8d..75e42d8 100644
--- a/include/kvm/kvm-cpu.h
+++ b/include/kvm/kvm-cpu.h
@@ -20,6 +20,7 @@ void kvm_cpu__run(struct kvm_cpu *vcpu);
 int kvm_cpu__start(struct kvm_cpu *cpu);
 bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu);
 int kvm_cpu__get_endianness(struct kvm_cpu *vcpu);
+bool kvm_cpu__arch_handle_system_event(struct kvm_cpu *vcpu);
 
 int kvm_cpu__get_debug_fd(void);
 void kvm_cpu__set_debug_fd(int fd);
diff --git a/kvm-cpu.c b/kvm-cpu.c
index 7dec088..d615c37 100644
--- a/kvm-cpu.c
+++ b/kvm-cpu.c
@@ -23,6 +23,11 @@ int __attribute__((weak)) kvm_cpu__get_endianness(struct kvm_cpu *vcpu)
 	return VIRTIO_ENDIAN_HOST;
 }
 
+bool __attribute__((weak)) kvm_cpu__arch_handle_system_event(struct kvm_cpu *vcpu)
+{
+	return false;
+}
+
 void kvm_cpu__enable_singlestep(struct kvm_cpu *vcpu)
 {
 	struct kvm_guest_debug debug = {
@@ -224,6 +229,9 @@ int kvm_cpu__start(struct kvm_cpu *cpu)
 			 */
 			switch (cpu->kvm_run->system_event.type) {
 			default:
+				if (kvm_cpu__arch_handle_system_event(cpu))
+					break;
+
 				pr_warning("unknown system event type %d",
 					   cpu->kvm_run->system_event.type);
 				/* fall through for now */
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 2/5] Allow architectures to hook KVM_EXIT_SYSTEM_EVENT
@ 2022-03-11 17:57     ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, Marc Zyngier, James Morse, Alexandru Elisei,
	Suzuki K Poulose, linux-arm-kernel, Peter Shier, Ricardo Koller,
	Reiji Watanabe, Will Deacon, Julien Thierry, Oliver Upton

Certain system events require architecture-specific handling. Allow
architectures to intervene for exits unhandled by the default exit
handler.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 include/kvm/kvm-cpu.h | 1 +
 kvm-cpu.c             | 8 ++++++++
 2 files changed, 9 insertions(+)

diff --git a/include/kvm/kvm-cpu.h b/include/kvm/kvm-cpu.h
index 0f16f8d..75e42d8 100644
--- a/include/kvm/kvm-cpu.h
+++ b/include/kvm/kvm-cpu.h
@@ -20,6 +20,7 @@ void kvm_cpu__run(struct kvm_cpu *vcpu);
 int kvm_cpu__start(struct kvm_cpu *cpu);
 bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu);
 int kvm_cpu__get_endianness(struct kvm_cpu *vcpu);
+bool kvm_cpu__arch_handle_system_event(struct kvm_cpu *vcpu);
 
 int kvm_cpu__get_debug_fd(void);
 void kvm_cpu__set_debug_fd(int fd);
diff --git a/kvm-cpu.c b/kvm-cpu.c
index 7dec088..d615c37 100644
--- a/kvm-cpu.c
+++ b/kvm-cpu.c
@@ -23,6 +23,11 @@ int __attribute__((weak)) kvm_cpu__get_endianness(struct kvm_cpu *vcpu)
 	return VIRTIO_ENDIAN_HOST;
 }
 
+bool __attribute__((weak)) kvm_cpu__arch_handle_system_event(struct kvm_cpu *vcpu)
+{
+	return false;
+}
+
 void kvm_cpu__enable_singlestep(struct kvm_cpu *vcpu)
 {
 	struct kvm_guest_debug debug = {
@@ -224,6 +229,9 @@ int kvm_cpu__start(struct kvm_cpu *cpu)
 			 */
 			switch (cpu->kvm_run->system_event.type) {
 			default:
+				if (kvm_cpu__arch_handle_system_event(cpu))
+					break;
+
 				pr_warning("unknown system event type %d",
 					   cpu->kvm_run->system_event.type);
 				/* fall through for now */
-- 
2.35.1.723.g4982287a31-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 3/5] ARM: Stash vcpu_init in the vCPU structure
  2022-03-11 17:57   ` Oliver Upton
  (?)
@ 2022-03-11 17:57     ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, Marc Zyngier, James Morse, Alexandru Elisei,
	Suzuki K Poulose, linux-arm-kernel, Peter Shier, Ricardo Koller,
	Reiji Watanabe, Will Deacon, Julien Thierry, Oliver Upton

A subsequent change to kvmtool will require that a vCPU be reset more
than once. Derive a valid target/feature set exactly once and stash that
for later use.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 arm/include/arm-common/kvm-cpu-arch.h | 18 +++++++++---------
 arm/kvm-cpu.c                         |  2 +-
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/arm/include/arm-common/kvm-cpu-arch.h b/arm/include/arm-common/kvm-cpu-arch.h
index 923d2c4..4027afe 100644
--- a/arm/include/arm-common/kvm-cpu-arch.h
+++ b/arm/include/arm-common/kvm-cpu-arch.h
@@ -10,18 +10,18 @@ struct kvm;
 struct kvm_cpu {
 	pthread_t	thread;
 
-	unsigned long	cpu_id;
-	unsigned long	cpu_type;
-	const char	*cpu_compatible;
+	unsigned long		cpu_id;
+	struct kvm_vcpu_init	init;
+	const char		*cpu_compatible;
 
-	struct kvm	*kvm;
-	int		vcpu_fd;
-	struct kvm_run	*kvm_run;
+	struct kvm		*kvm;
+	int			vcpu_fd;
+	struct kvm_run		*kvm_run;
 	struct kvm_cpu_task	*task;
 
-	u8		is_running;
-	u8		paused;
-	u8		needs_nmi;
+	u8			is_running;
+	u8			paused;
+	u8			needs_nmi;
 
 	struct kvm_coalesced_mmio_ring	*ring;
 
diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c
index 6a2408c..1ea56bb 100644
--- a/arm/kvm-cpu.c
+++ b/arm/kvm-cpu.c
@@ -128,7 +128,7 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 	/* Populate the vcpu structure. */
 	vcpu->kvm		= kvm;
 	vcpu->cpu_id		= cpu_id;
-	vcpu->cpu_type		= vcpu_init.target;
+	vcpu->init		= vcpu_init;
 	vcpu->cpu_compatible	= target->compatible;
 	vcpu->is_running	= true;
 
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 3/5] ARM: Stash vcpu_init in the vCPU structure
@ 2022-03-11 17:57     ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm; +Cc: kvm, Will Deacon, Marc Zyngier, Peter Shier, linux-arm-kernel

A subsequent change to kvmtool will require that a vCPU be reset more
than once. Derive a valid target/feature set exactly once and stash that
for later use.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 arm/include/arm-common/kvm-cpu-arch.h | 18 +++++++++---------
 arm/kvm-cpu.c                         |  2 +-
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/arm/include/arm-common/kvm-cpu-arch.h b/arm/include/arm-common/kvm-cpu-arch.h
index 923d2c4..4027afe 100644
--- a/arm/include/arm-common/kvm-cpu-arch.h
+++ b/arm/include/arm-common/kvm-cpu-arch.h
@@ -10,18 +10,18 @@ struct kvm;
 struct kvm_cpu {
 	pthread_t	thread;
 
-	unsigned long	cpu_id;
-	unsigned long	cpu_type;
-	const char	*cpu_compatible;
+	unsigned long		cpu_id;
+	struct kvm_vcpu_init	init;
+	const char		*cpu_compatible;
 
-	struct kvm	*kvm;
-	int		vcpu_fd;
-	struct kvm_run	*kvm_run;
+	struct kvm		*kvm;
+	int			vcpu_fd;
+	struct kvm_run		*kvm_run;
 	struct kvm_cpu_task	*task;
 
-	u8		is_running;
-	u8		paused;
-	u8		needs_nmi;
+	u8			is_running;
+	u8			paused;
+	u8			needs_nmi;
 
 	struct kvm_coalesced_mmio_ring	*ring;
 
diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c
index 6a2408c..1ea56bb 100644
--- a/arm/kvm-cpu.c
+++ b/arm/kvm-cpu.c
@@ -128,7 +128,7 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 	/* Populate the vcpu structure. */
 	vcpu->kvm		= kvm;
 	vcpu->cpu_id		= cpu_id;
-	vcpu->cpu_type		= vcpu_init.target;
+	vcpu->init		= vcpu_init;
 	vcpu->cpu_compatible	= target->compatible;
 	vcpu->is_running	= true;
 
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 3/5] ARM: Stash vcpu_init in the vCPU structure
@ 2022-03-11 17:57     ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, Marc Zyngier, James Morse, Alexandru Elisei,
	Suzuki K Poulose, linux-arm-kernel, Peter Shier, Ricardo Koller,
	Reiji Watanabe, Will Deacon, Julien Thierry, Oliver Upton

A subsequent change to kvmtool will require that a vCPU be reset more
than once. Derive a valid target/feature set exactly once and stash that
for later use.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 arm/include/arm-common/kvm-cpu-arch.h | 18 +++++++++---------
 arm/kvm-cpu.c                         |  2 +-
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/arm/include/arm-common/kvm-cpu-arch.h b/arm/include/arm-common/kvm-cpu-arch.h
index 923d2c4..4027afe 100644
--- a/arm/include/arm-common/kvm-cpu-arch.h
+++ b/arm/include/arm-common/kvm-cpu-arch.h
@@ -10,18 +10,18 @@ struct kvm;
 struct kvm_cpu {
 	pthread_t	thread;
 
-	unsigned long	cpu_id;
-	unsigned long	cpu_type;
-	const char	*cpu_compatible;
+	unsigned long		cpu_id;
+	struct kvm_vcpu_init	init;
+	const char		*cpu_compatible;
 
-	struct kvm	*kvm;
-	int		vcpu_fd;
-	struct kvm_run	*kvm_run;
+	struct kvm		*kvm;
+	int			vcpu_fd;
+	struct kvm_run		*kvm_run;
 	struct kvm_cpu_task	*task;
 
-	u8		is_running;
-	u8		paused;
-	u8		needs_nmi;
+	u8			is_running;
+	u8			paused;
+	u8			needs_nmi;
 
 	struct kvm_coalesced_mmio_ring	*ring;
 
diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c
index 6a2408c..1ea56bb 100644
--- a/arm/kvm-cpu.c
+++ b/arm/kvm-cpu.c
@@ -128,7 +128,7 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 	/* Populate the vcpu structure. */
 	vcpu->kvm		= kvm;
 	vcpu->cpu_id		= cpu_id;
-	vcpu->cpu_type		= vcpu_init.target;
+	vcpu->init		= vcpu_init;
 	vcpu->cpu_compatible	= target->compatible;
 	vcpu->is_running	= true;
 
-- 
2.35.1.723.g4982287a31-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 4/5] ARM: Add a helper to re-init a vCPU
  2022-03-11 17:57   ` Oliver Upton
  (?)
@ 2022-03-11 17:57     ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, Marc Zyngier, James Morse, Alexandru Elisei,
	Suzuki K Poulose, linux-arm-kernel, Peter Shier, Ricardo Koller,
	Reiji Watanabe, Will Deacon, Julien Thierry, Oliver Upton

Create a helper that can be called to reinitialize a particular vCPU, or
in other words issue the KVM_ARM_VCPU_INIT and KVM_ARM_VCPU_FINALIZE
ioctls accordingly.

Make use of the helper from kvm_cpu__arch_init() after the correct
target/feature set have been identified. Calling KVM_ARM_VCPU_INIT with
the same target more than once is benign.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 arm/kvm-cpu.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c
index 1ea56bb..164e399 100644
--- a/arm/kvm-cpu.c
+++ b/arm/kvm-cpu.c
@@ -35,6 +35,15 @@ int kvm_cpu__register_kvm_arm_target(struct kvm_arm_target *target)
 	return -ENOSPC;
 }
 
+static void kvm_cpu__arch_reinit(struct kvm_cpu *vcpu)
+{
+	if (ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_INIT, &vcpu->init) < 0)
+		die("KVM_ARM_VCPU_INIT failed");
+
+	if (kvm_cpu__configure_features(vcpu))
+		die("Unable to configure requested vcpu features");
+}
+
 struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 {
 	struct kvm_arm_target *target;
@@ -132,8 +141,7 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 	vcpu->cpu_compatible	= target->compatible;
 	vcpu->is_running	= true;
 
-	if (kvm_cpu__configure_features(vcpu))
-		die("Unable to configure requested vcpu features");
+	kvm_cpu__arch_reinit(vcpu);
 
 	return vcpu;
 }
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 4/5] ARM: Add a helper to re-init a vCPU
@ 2022-03-11 17:57     ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm; +Cc: kvm, Will Deacon, Marc Zyngier, Peter Shier, linux-arm-kernel

Create a helper that can be called to reinitialize a particular vCPU, or
in other words issue the KVM_ARM_VCPU_INIT and KVM_ARM_VCPU_FINALIZE
ioctls accordingly.

Make use of the helper from kvm_cpu__arch_init() after the correct
target/feature set have been identified. Calling KVM_ARM_VCPU_INIT with
the same target more than once is benign.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 arm/kvm-cpu.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c
index 1ea56bb..164e399 100644
--- a/arm/kvm-cpu.c
+++ b/arm/kvm-cpu.c
@@ -35,6 +35,15 @@ int kvm_cpu__register_kvm_arm_target(struct kvm_arm_target *target)
 	return -ENOSPC;
 }
 
+static void kvm_cpu__arch_reinit(struct kvm_cpu *vcpu)
+{
+	if (ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_INIT, &vcpu->init) < 0)
+		die("KVM_ARM_VCPU_INIT failed");
+
+	if (kvm_cpu__configure_features(vcpu))
+		die("Unable to configure requested vcpu features");
+}
+
 struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 {
 	struct kvm_arm_target *target;
@@ -132,8 +141,7 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 	vcpu->cpu_compatible	= target->compatible;
 	vcpu->is_running	= true;
 
-	if (kvm_cpu__configure_features(vcpu))
-		die("Unable to configure requested vcpu features");
+	kvm_cpu__arch_reinit(vcpu);
 
 	return vcpu;
 }
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 4/5] ARM: Add a helper to re-init a vCPU
@ 2022-03-11 17:57     ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, Marc Zyngier, James Morse, Alexandru Elisei,
	Suzuki K Poulose, linux-arm-kernel, Peter Shier, Ricardo Koller,
	Reiji Watanabe, Will Deacon, Julien Thierry, Oliver Upton

Create a helper that can be called to reinitialize a particular vCPU, or
in other words issue the KVM_ARM_VCPU_INIT and KVM_ARM_VCPU_FINALIZE
ioctls accordingly.

Make use of the helper from kvm_cpu__arch_init() after the correct
target/feature set have been identified. Calling KVM_ARM_VCPU_INIT with
the same target more than once is benign.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 arm/kvm-cpu.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c
index 1ea56bb..164e399 100644
--- a/arm/kvm-cpu.c
+++ b/arm/kvm-cpu.c
@@ -35,6 +35,15 @@ int kvm_cpu__register_kvm_arm_target(struct kvm_arm_target *target)
 	return -ENOSPC;
 }
 
+static void kvm_cpu__arch_reinit(struct kvm_cpu *vcpu)
+{
+	if (ioctl(vcpu->vcpu_fd, KVM_ARM_VCPU_INIT, &vcpu->init) < 0)
+		die("KVM_ARM_VCPU_INIT failed");
+
+	if (kvm_cpu__configure_features(vcpu))
+		die("Unable to configure requested vcpu features");
+}
+
 struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 {
 	struct kvm_arm_target *target;
@@ -132,8 +141,7 @@ struct kvm_cpu *kvm_cpu__arch_init(struct kvm *kvm, unsigned long cpu_id)
 	vcpu->cpu_compatible	= target->compatible;
 	vcpu->is_running	= true;
 
-	if (kvm_cpu__configure_features(vcpu))
-		die("Unable to configure requested vcpu features");
+	kvm_cpu__arch_reinit(vcpu);
 
 	return vcpu;
 }
-- 
2.35.1.723.g4982287a31-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 5/5] ARM: Implement PSCI SYSTEM_SUSPEND
  2022-03-11 17:57   ` Oliver Upton
  (?)
@ 2022-03-11 17:57     ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, Marc Zyngier, James Morse, Alexandru Elisei,
	Suzuki K Poulose, linux-arm-kernel, Peter Shier, Ricardo Koller,
	Reiji Watanabe, Will Deacon, Julien Thierry, Oliver Upton

KVM_CAP_ARM_SYSTEM_SUSPEND allows VMMs to trap guest attempts to use the
PSCI SYSTEM_SUSPEND hypercall. Make use of that capability in KVM tool
to implement guest suspend support.

Add some minimal SMCCC register handling (params, return values) for
AArch32 and AArch64. Perform only the required sanity check before
suspending the VM by ensuring all other vCPUs besides the caller are
powered off. Leverage KVM_MP_STATE_SUSPENDED to emulate the suspend as
an architectural WFI.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 arm/aarch32/kvm-cpu.c                 | 72 ++++++++++++++++++++++++
 arm/aarch64/kvm-cpu.c                 | 66 ++++++++++++++++++++++
 arm/include/arm-common/kvm-cpu-arch.h |  5 ++
 arm/kvm-cpu.c                         | 81 +++++++++++++++++++++++++++
 arm/kvm.c                             |  9 +++
 5 files changed, 233 insertions(+)

diff --git a/arm/aarch32/kvm-cpu.c b/arm/aarch32/kvm-cpu.c
index 95fb1da..dd5f70f 100644
--- a/arm/aarch32/kvm-cpu.c
+++ b/arm/aarch32/kvm-cpu.c
@@ -130,3 +130,75 @@ void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
 		die("KVM_GET_ONE_REG failed (LR_svc)");
 	dprintf(debug_fd, " LR_svc:  0x%x\n", data);
 }
+
+u64 kvm_cpu__smccc_get_arg1(struct kvm_vcpu *vcpu)
+{
+	struct kvm_one_reg reg;
+	u32 data;
+
+	reg.addr = (u64)&data;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r1);
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
+		die("KVM_GET_ONE_REG failed (r1)");
+
+	return data;
+}
+
+u64 kvm_cpu__smccc_get_arg2(struct kvm_vcpu *vcpu)
+{
+	struct kvm_one_reg reg;
+	u32 data;
+
+	reg.addr = (u64)&data;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r2);
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
+		die("KVM_GET_ONE_REG failed (r2)");
+
+	return data;
+}
+
+void kvm_cpu__smccc_return(struct kvm_cpu *vcpu, u64 a0, u64 a1, u64 a2, u64 a3)
+{
+	struct kvm_one_reg reg;
+	u32 data;
+
+	reg.addr = (u64)&data;
+
+	data = (u32)a0;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r0);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (r0)");
+
+	data = (u32)a1;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r1);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (r1)");
+
+	data = (u32)a2;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r2);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (r2)");
+
+	data = (u32)a3;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r3);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (r3)");
+}
+
+void kvm_cpu__psci_set_entry(struct kvm_cpu *vcpu, u64 entry_addr, u64 context_id)
+{
+	struct kvm_one_reg reg;
+	u32 data;
+
+	reg.addr = (u64)&data;
+
+	data = (u32)entry_addr;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_pc);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (pc)");
+
+	data = (u32)context_id;
+	reg.id = ARM64_CORE_REG(usr_regs.ARM_r0);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (r0)");
+}
diff --git a/arm/aarch64/kvm-cpu.c b/arm/aarch64/kvm-cpu.c
index 9f3e858..3118c54 100644
--- a/arm/aarch64/kvm-cpu.c
+++ b/arm/aarch64/kvm-cpu.c
@@ -254,3 +254,69 @@ void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
 		die("KVM_GET_ONE_REG failed (lr)");
 	dprintf(debug_fd, " LR:    0x%lx\n", data);
 }
+
+u64 kvm_cpu__smccc_get_arg1(struct kvm_cpu *vcpu)
+{
+	struct kvm_one_reg reg;
+	u64 data;
+
+	reg.addr = (u64)&data;
+	reg.id = ARM64_CORE_REG(regs.regs[1]);
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
+		die("KVM_GET_ONE_REG failed (x1)");
+
+	return data;
+}
+
+u64 kvm_cpu__smccc_get_arg2(struct kvm_cpu *vcpu)
+{
+	struct kvm_one_reg reg;
+	u64 data;
+
+	reg.addr = (u64)&data;
+	reg.id = ARM64_CORE_REG(regs.regs[2]);
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
+		die("KVM_GET_ONE_REG failed (x2)");
+
+	return data;
+}
+
+void kvm_cpu__smccc_return(struct kvm_cpu *vcpu, u64 a0, u64 a1, u64 a2, u64 a3)
+{
+	struct kvm_one_reg reg;
+
+	reg.addr = (u64)&a0;
+	reg.id = ARM64_CORE_REG(regs.regs[0]);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (x0)");
+
+	reg.addr = (u64)&a1;
+	reg.id = ARM64_CORE_REG(regs.regs[1]);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (x1)");
+
+	reg.addr = (u64)&a2;
+	reg.id = ARM64_CORE_REG(regs.regs[2]);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (x2)");
+
+	reg.addr = (u64)&a3;
+	reg.id = ARM64_CORE_REG(regs.regs[3]);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (x3)");
+}
+
+void kvm_cpu__psci_set_entry(struct kvm_cpu *vcpu, u64 entry_addr, u64 context_id)
+{
+	struct kvm_one_reg reg;
+
+	reg.addr = (u64)&entry_addr;
+	reg.id = ARM64_CORE_REG(regs.pc);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (pc)");
+
+	reg.addr = (u64)&context_id;
+	reg.id = ARM64_CORE_REG(regs.regs[0]);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (x0)");
+}
diff --git a/arm/include/arm-common/kvm-cpu-arch.h b/arm/include/arm-common/kvm-cpu-arch.h
index 4027afe..17179c2 100644
--- a/arm/include/arm-common/kvm-cpu-arch.h
+++ b/arm/include/arm-common/kvm-cpu-arch.h
@@ -59,4 +59,9 @@ static inline bool kvm_cpu__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr,
 
 unsigned long kvm_cpu__get_vcpu_mpidr(struct kvm_cpu *vcpu);
 
+u64 kvm_cpu__smccc_get_arg1(struct kvm_cpu *vcpu);
+u64 kvm_cpu__smccc_get_arg2(struct kvm_cpu *vcpu);
+void kvm_cpu__smccc_return(struct kvm_cpu *vcpu, u64 a0, u64 a1, u64 a2, u64 a3);
+void kvm_cpu__psci_set_entry(struct kvm_cpu *vcpu, u64 entry_addr, u64 context_id);
+
 #endif /* ARM_COMMON__KVM_CPU_ARCH_H */
diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c
index 164e399..677f8bb 100644
--- a/arm/kvm-cpu.c
+++ b/arm/kvm-cpu.c
@@ -163,3 +163,84 @@ bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu)
 void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
 {
 }
+
+static void kvm_cpu__arm_suspend(struct kvm_cpu *vcpu)
+{
+	struct kvm_mp_state mp_state = {
+		.mp_state = KVM_MP_STATE_SUSPENDED,
+	};
+
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_MP_STATE, &mp_state) < 0)
+		die("KVM_SET_MP_STATE failed");
+}
+
+static void kvm_cpu__wakeup(struct kvm_cpu *vcpu)
+{
+	u64 entry_addr, context_id;
+
+	entry_addr = kvm_cpu__smccc_get_arg1(vcpu);
+	context_id = kvm_cpu__smccc_get_arg2(vcpu);
+
+	/*
+	 * The resuming CPU could have been a secondary CPU at boot. Ensure the
+	 * vCPU is made runnable.
+	 */
+	vcpu->init.features[0] &= ~(1ul << KVM_ARM_VCPU_POWER_OFF);
+
+	kvm_cpu__arch_reinit(vcpu);
+	kvm_cpu__reset_vcpu(vcpu);
+	kvm_cpu__psci_set_entry(vcpu, entry_addr, context_id);
+}
+
+static void kvm_cpu__psci_system_suspend(struct kvm_cpu *vcpu)
+{
+	struct kvm *kvm = vcpu->kvm;
+	bool denied = false;
+	int i;
+
+	/*
+	 * Mark the caller as paused before actually pausing the VM. This avoids
+	 * the hazard of attempting to acquire the pause_lock in the SIGKVMPAUSE
+	 * handler from the thread that already holds it.
+	 */
+	vcpu->paused = 1;
+
+	kvm__pause(kvm);
+	for (i = 0; i < kvm->nrcpus; i++) {
+		struct kvm_cpu *tmp = kvm->cpus[i];
+		struct kvm_mp_state mp_state;
+
+		if (vcpu == tmp)
+			continue;
+
+		if (ioctl(tmp->vcpu_fd, KVM_GET_MP_STATE, &mp_state) < 0)
+			die("KVM_GET_MP_STATE failed");
+
+		if (mp_state.mp_state != KVM_MP_STATE_STOPPED) {
+			denied = true;
+			break;
+		}
+	}
+
+	if (!denied)
+		kvm_cpu__arm_suspend(vcpu);
+	else
+		kvm_cpu__smccc_return(vcpu, PSCI_RET_DENIED, 0, 0, 0);
+
+	vcpu->paused = 0;
+	kvm__continue(kvm);
+}
+
+bool kvm_cpu__arch_handle_system_event(struct kvm_cpu *vcpu)
+{
+	switch (vcpu->kvm_run->system_event.type) {
+	case KVM_SYSTEM_EVENT_SUSPEND:
+		kvm_cpu__psci_system_suspend(vcpu);
+		return true;
+	case KVM_SYSTEM_EVENT_WAKEUP:
+		kvm_cpu__wakeup(vcpu);
+		return true;
+	default:
+		return false;
+	}
+}
diff --git a/arm/kvm.c b/arm/kvm.c
index 80d233f..8ae4711 100644
--- a/arm/kvm.c
+++ b/arm/kvm.c
@@ -86,6 +86,15 @@ void kvm__arch_init(struct kvm *kvm, const char *hugetlbfs_path, u64 ram_size)
 	/* Create the virtual GIC. */
 	if (gic__create(kvm, kvm->cfg.arch.irqchip))
 		die("Failed to create virtual GIC");
+
+	if (kvm__supports_extension(kvm, KVM_CAP_ARM_SYSTEM_SUSPEND)) {
+		struct kvm_enable_cap cap = {
+			.cap = KVM_CAP_ARM_SYSTEM_SUSPEND,
+		};
+
+		if (ioctl(kvm->vm_fd, KVM_ENABLE_CAP, &cap) < 0)
+			die("Enabling KVM_CAP_ARM_SYSTEM_SUSPEND failed");
+	}
 }
 
 #define FDT_ALIGN	SZ_2M
-- 
2.35.1.723.g4982287a31-goog


^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 5/5] ARM: Implement PSCI SYSTEM_SUSPEND
@ 2022-03-11 17:57     ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm; +Cc: kvm, Will Deacon, Marc Zyngier, Peter Shier, linux-arm-kernel

KVM_CAP_ARM_SYSTEM_SUSPEND allows VMMs to trap guest attempts to use the
PSCI SYSTEM_SUSPEND hypercall. Make use of that capability in KVM tool
to implement guest suspend support.

Add some minimal SMCCC register handling (params, return values) for
AArch32 and AArch64. Perform only the required sanity check before
suspending the VM by ensuring all other vCPUs besides the caller are
powered off. Leverage KVM_MP_STATE_SUSPENDED to emulate the suspend as
an architectural WFI.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 arm/aarch32/kvm-cpu.c                 | 72 ++++++++++++++++++++++++
 arm/aarch64/kvm-cpu.c                 | 66 ++++++++++++++++++++++
 arm/include/arm-common/kvm-cpu-arch.h |  5 ++
 arm/kvm-cpu.c                         | 81 +++++++++++++++++++++++++++
 arm/kvm.c                             |  9 +++
 5 files changed, 233 insertions(+)

diff --git a/arm/aarch32/kvm-cpu.c b/arm/aarch32/kvm-cpu.c
index 95fb1da..dd5f70f 100644
--- a/arm/aarch32/kvm-cpu.c
+++ b/arm/aarch32/kvm-cpu.c
@@ -130,3 +130,75 @@ void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
 		die("KVM_GET_ONE_REG failed (LR_svc)");
 	dprintf(debug_fd, " LR_svc:  0x%x\n", data);
 }
+
+u64 kvm_cpu__smccc_get_arg1(struct kvm_vcpu *vcpu)
+{
+	struct kvm_one_reg reg;
+	u32 data;
+
+	reg.addr = (u64)&data;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r1);
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
+		die("KVM_GET_ONE_REG failed (r1)");
+
+	return data;
+}
+
+u64 kvm_cpu__smccc_get_arg2(struct kvm_vcpu *vcpu)
+{
+	struct kvm_one_reg reg;
+	u32 data;
+
+	reg.addr = (u64)&data;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r2);
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
+		die("KVM_GET_ONE_REG failed (r2)");
+
+	return data;
+}
+
+void kvm_cpu__smccc_return(struct kvm_cpu *vcpu, u64 a0, u64 a1, u64 a2, u64 a3)
+{
+	struct kvm_one_reg reg;
+	u32 data;
+
+	reg.addr = (u64)&data;
+
+	data = (u32)a0;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r0);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (r0)");
+
+	data = (u32)a1;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r1);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (r1)");
+
+	data = (u32)a2;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r2);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (r2)");
+
+	data = (u32)a3;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r3);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (r3)");
+}
+
+void kvm_cpu__psci_set_entry(struct kvm_cpu *vcpu, u64 entry_addr, u64 context_id)
+{
+	struct kvm_one_reg reg;
+	u32 data;
+
+	reg.addr = (u64)&data;
+
+	data = (u32)entry_addr;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_pc);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (pc)");
+
+	data = (u32)context_id;
+	reg.id = ARM64_CORE_REG(usr_regs.ARM_r0);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (r0)");
+}
diff --git a/arm/aarch64/kvm-cpu.c b/arm/aarch64/kvm-cpu.c
index 9f3e858..3118c54 100644
--- a/arm/aarch64/kvm-cpu.c
+++ b/arm/aarch64/kvm-cpu.c
@@ -254,3 +254,69 @@ void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
 		die("KVM_GET_ONE_REG failed (lr)");
 	dprintf(debug_fd, " LR:    0x%lx\n", data);
 }
+
+u64 kvm_cpu__smccc_get_arg1(struct kvm_cpu *vcpu)
+{
+	struct kvm_one_reg reg;
+	u64 data;
+
+	reg.addr = (u64)&data;
+	reg.id = ARM64_CORE_REG(regs.regs[1]);
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
+		die("KVM_GET_ONE_REG failed (x1)");
+
+	return data;
+}
+
+u64 kvm_cpu__smccc_get_arg2(struct kvm_cpu *vcpu)
+{
+	struct kvm_one_reg reg;
+	u64 data;
+
+	reg.addr = (u64)&data;
+	reg.id = ARM64_CORE_REG(regs.regs[2]);
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
+		die("KVM_GET_ONE_REG failed (x2)");
+
+	return data;
+}
+
+void kvm_cpu__smccc_return(struct kvm_cpu *vcpu, u64 a0, u64 a1, u64 a2, u64 a3)
+{
+	struct kvm_one_reg reg;
+
+	reg.addr = (u64)&a0;
+	reg.id = ARM64_CORE_REG(regs.regs[0]);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (x0)");
+
+	reg.addr = (u64)&a1;
+	reg.id = ARM64_CORE_REG(regs.regs[1]);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (x1)");
+
+	reg.addr = (u64)&a2;
+	reg.id = ARM64_CORE_REG(regs.regs[2]);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (x2)");
+
+	reg.addr = (u64)&a3;
+	reg.id = ARM64_CORE_REG(regs.regs[3]);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (x3)");
+}
+
+void kvm_cpu__psci_set_entry(struct kvm_cpu *vcpu, u64 entry_addr, u64 context_id)
+{
+	struct kvm_one_reg reg;
+
+	reg.addr = (u64)&entry_addr;
+	reg.id = ARM64_CORE_REG(regs.pc);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (pc)");
+
+	reg.addr = (u64)&context_id;
+	reg.id = ARM64_CORE_REG(regs.regs[0]);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (x0)");
+}
diff --git a/arm/include/arm-common/kvm-cpu-arch.h b/arm/include/arm-common/kvm-cpu-arch.h
index 4027afe..17179c2 100644
--- a/arm/include/arm-common/kvm-cpu-arch.h
+++ b/arm/include/arm-common/kvm-cpu-arch.h
@@ -59,4 +59,9 @@ static inline bool kvm_cpu__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr,
 
 unsigned long kvm_cpu__get_vcpu_mpidr(struct kvm_cpu *vcpu);
 
+u64 kvm_cpu__smccc_get_arg1(struct kvm_cpu *vcpu);
+u64 kvm_cpu__smccc_get_arg2(struct kvm_cpu *vcpu);
+void kvm_cpu__smccc_return(struct kvm_cpu *vcpu, u64 a0, u64 a1, u64 a2, u64 a3);
+void kvm_cpu__psci_set_entry(struct kvm_cpu *vcpu, u64 entry_addr, u64 context_id);
+
 #endif /* ARM_COMMON__KVM_CPU_ARCH_H */
diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c
index 164e399..677f8bb 100644
--- a/arm/kvm-cpu.c
+++ b/arm/kvm-cpu.c
@@ -163,3 +163,84 @@ bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu)
 void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
 {
 }
+
+static void kvm_cpu__arm_suspend(struct kvm_cpu *vcpu)
+{
+	struct kvm_mp_state mp_state = {
+		.mp_state = KVM_MP_STATE_SUSPENDED,
+	};
+
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_MP_STATE, &mp_state) < 0)
+		die("KVM_SET_MP_STATE failed");
+}
+
+static void kvm_cpu__wakeup(struct kvm_cpu *vcpu)
+{
+	u64 entry_addr, context_id;
+
+	entry_addr = kvm_cpu__smccc_get_arg1(vcpu);
+	context_id = kvm_cpu__smccc_get_arg2(vcpu);
+
+	/*
+	 * The resuming CPU could have been a secondary CPU at boot. Ensure the
+	 * vCPU is made runnable.
+	 */
+	vcpu->init.features[0] &= ~(1ul << KVM_ARM_VCPU_POWER_OFF);
+
+	kvm_cpu__arch_reinit(vcpu);
+	kvm_cpu__reset_vcpu(vcpu);
+	kvm_cpu__psci_set_entry(vcpu, entry_addr, context_id);
+}
+
+static void kvm_cpu__psci_system_suspend(struct kvm_cpu *vcpu)
+{
+	struct kvm *kvm = vcpu->kvm;
+	bool denied = false;
+	int i;
+
+	/*
+	 * Mark the caller as paused before actually pausing the VM. This avoids
+	 * the hazard of attempting to acquire the pause_lock in the SIGKVMPAUSE
+	 * handler from the thread that already holds it.
+	 */
+	vcpu->paused = 1;
+
+	kvm__pause(kvm);
+	for (i = 0; i < kvm->nrcpus; i++) {
+		struct kvm_cpu *tmp = kvm->cpus[i];
+		struct kvm_mp_state mp_state;
+
+		if (vcpu == tmp)
+			continue;
+
+		if (ioctl(tmp->vcpu_fd, KVM_GET_MP_STATE, &mp_state) < 0)
+			die("KVM_GET_MP_STATE failed");
+
+		if (mp_state.mp_state != KVM_MP_STATE_STOPPED) {
+			denied = true;
+			break;
+		}
+	}
+
+	if (!denied)
+		kvm_cpu__arm_suspend(vcpu);
+	else
+		kvm_cpu__smccc_return(vcpu, PSCI_RET_DENIED, 0, 0, 0);
+
+	vcpu->paused = 0;
+	kvm__continue(kvm);
+}
+
+bool kvm_cpu__arch_handle_system_event(struct kvm_cpu *vcpu)
+{
+	switch (vcpu->kvm_run->system_event.type) {
+	case KVM_SYSTEM_EVENT_SUSPEND:
+		kvm_cpu__psci_system_suspend(vcpu);
+		return true;
+	case KVM_SYSTEM_EVENT_WAKEUP:
+		kvm_cpu__wakeup(vcpu);
+		return true;
+	default:
+		return false;
+	}
+}
diff --git a/arm/kvm.c b/arm/kvm.c
index 80d233f..8ae4711 100644
--- a/arm/kvm.c
+++ b/arm/kvm.c
@@ -86,6 +86,15 @@ void kvm__arch_init(struct kvm *kvm, const char *hugetlbfs_path, u64 ram_size)
 	/* Create the virtual GIC. */
 	if (gic__create(kvm, kvm->cfg.arch.irqchip))
 		die("Failed to create virtual GIC");
+
+	if (kvm__supports_extension(kvm, KVM_CAP_ARM_SYSTEM_SUSPEND)) {
+		struct kvm_enable_cap cap = {
+			.cap = KVM_CAP_ARM_SYSTEM_SUSPEND,
+		};
+
+		if (ioctl(kvm->vm_fd, KVM_ENABLE_CAP, &cap) < 0)
+			die("Enabling KVM_CAP_ARM_SYSTEM_SUSPEND failed");
+	}
 }
 
 #define FDT_ALIGN	SZ_2M
-- 
2.35.1.723.g4982287a31-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [RFC PATCH kvmtool 5/5] ARM: Implement PSCI SYSTEM_SUSPEND
@ 2022-03-11 17:57     ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-11 17:57 UTC (permalink / raw)
  To: kvmarm
  Cc: kvm, Marc Zyngier, James Morse, Alexandru Elisei,
	Suzuki K Poulose, linux-arm-kernel, Peter Shier, Ricardo Koller,
	Reiji Watanabe, Will Deacon, Julien Thierry, Oliver Upton

KVM_CAP_ARM_SYSTEM_SUSPEND allows VMMs to trap guest attempts to use the
PSCI SYSTEM_SUSPEND hypercall. Make use of that capability in KVM tool
to implement guest suspend support.

Add some minimal SMCCC register handling (params, return values) for
AArch32 and AArch64. Perform only the required sanity check before
suspending the VM by ensuring all other vCPUs besides the caller are
powered off. Leverage KVM_MP_STATE_SUSPENDED to emulate the suspend as
an architectural WFI.

Signed-off-by: Oliver Upton <oupton@google.com>
---
 arm/aarch32/kvm-cpu.c                 | 72 ++++++++++++++++++++++++
 arm/aarch64/kvm-cpu.c                 | 66 ++++++++++++++++++++++
 arm/include/arm-common/kvm-cpu-arch.h |  5 ++
 arm/kvm-cpu.c                         | 81 +++++++++++++++++++++++++++
 arm/kvm.c                             |  9 +++
 5 files changed, 233 insertions(+)

diff --git a/arm/aarch32/kvm-cpu.c b/arm/aarch32/kvm-cpu.c
index 95fb1da..dd5f70f 100644
--- a/arm/aarch32/kvm-cpu.c
+++ b/arm/aarch32/kvm-cpu.c
@@ -130,3 +130,75 @@ void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
 		die("KVM_GET_ONE_REG failed (LR_svc)");
 	dprintf(debug_fd, " LR_svc:  0x%x\n", data);
 }
+
+u64 kvm_cpu__smccc_get_arg1(struct kvm_vcpu *vcpu)
+{
+	struct kvm_one_reg reg;
+	u32 data;
+
+	reg.addr = (u64)&data;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r1);
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
+		die("KVM_GET_ONE_REG failed (r1)");
+
+	return data;
+}
+
+u64 kvm_cpu__smccc_get_arg2(struct kvm_vcpu *vcpu)
+{
+	struct kvm_one_reg reg;
+	u32 data;
+
+	reg.addr = (u64)&data;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r2);
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
+		die("KVM_GET_ONE_REG failed (r2)");
+
+	return data;
+}
+
+void kvm_cpu__smccc_return(struct kvm_cpu *vcpu, u64 a0, u64 a1, u64 a2, u64 a3)
+{
+	struct kvm_one_reg reg;
+	u32 data;
+
+	reg.addr = (u64)&data;
+
+	data = (u32)a0;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r0);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (r0)");
+
+	data = (u32)a1;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r1);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (r1)");
+
+	data = (u32)a2;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r2);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (r2)");
+
+	data = (u32)a3;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_r3);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (r3)");
+}
+
+void kvm_cpu__psci_set_entry(struct kvm_cpu *vcpu, u64 entry_addr, u64 context_id)
+{
+	struct kvm_one_reg reg;
+	u32 data;
+
+	reg.addr = (u64)&data;
+
+	data = (u32)entry_addr;
+	reg.id = ARM_CORE_REG(usr_regs.ARM_pc);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (pc)");
+
+	data = (u32)context_id;
+	reg.id = ARM64_CORE_REG(usr_regs.ARM_r0);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (r0)");
+}
diff --git a/arm/aarch64/kvm-cpu.c b/arm/aarch64/kvm-cpu.c
index 9f3e858..3118c54 100644
--- a/arm/aarch64/kvm-cpu.c
+++ b/arm/aarch64/kvm-cpu.c
@@ -254,3 +254,69 @@ void kvm_cpu__show_registers(struct kvm_cpu *vcpu)
 		die("KVM_GET_ONE_REG failed (lr)");
 	dprintf(debug_fd, " LR:    0x%lx\n", data);
 }
+
+u64 kvm_cpu__smccc_get_arg1(struct kvm_cpu *vcpu)
+{
+	struct kvm_one_reg reg;
+	u64 data;
+
+	reg.addr = (u64)&data;
+	reg.id = ARM64_CORE_REG(regs.regs[1]);
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
+		die("KVM_GET_ONE_REG failed (x1)");
+
+	return data;
+}
+
+u64 kvm_cpu__smccc_get_arg2(struct kvm_cpu *vcpu)
+{
+	struct kvm_one_reg reg;
+	u64 data;
+
+	reg.addr = (u64)&data;
+	reg.id = ARM64_CORE_REG(regs.regs[2]);
+	if (ioctl(vcpu->vcpu_fd, KVM_GET_ONE_REG, &reg) < 0)
+		die("KVM_GET_ONE_REG failed (x2)");
+
+	return data;
+}
+
+void kvm_cpu__smccc_return(struct kvm_cpu *vcpu, u64 a0, u64 a1, u64 a2, u64 a3)
+{
+	struct kvm_one_reg reg;
+
+	reg.addr = (u64)&a0;
+	reg.id = ARM64_CORE_REG(regs.regs[0]);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (x0)");
+
+	reg.addr = (u64)&a1;
+	reg.id = ARM64_CORE_REG(regs.regs[1]);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (x1)");
+
+	reg.addr = (u64)&a2;
+	reg.id = ARM64_CORE_REG(regs.regs[2]);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (x2)");
+
+	reg.addr = (u64)&a3;
+	reg.id = ARM64_CORE_REG(regs.regs[3]);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (x3)");
+}
+
+void kvm_cpu__psci_set_entry(struct kvm_cpu *vcpu, u64 entry_addr, u64 context_id)
+{
+	struct kvm_one_reg reg;
+
+	reg.addr = (u64)&entry_addr;
+	reg.id = ARM64_CORE_REG(regs.pc);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (pc)");
+
+	reg.addr = (u64)&context_id;
+	reg.id = ARM64_CORE_REG(regs.regs[0]);
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_ONE_REG, &reg) < 0)
+		die("KVM_SET_ONE_REG failed (x0)");
+}
diff --git a/arm/include/arm-common/kvm-cpu-arch.h b/arm/include/arm-common/kvm-cpu-arch.h
index 4027afe..17179c2 100644
--- a/arm/include/arm-common/kvm-cpu-arch.h
+++ b/arm/include/arm-common/kvm-cpu-arch.h
@@ -59,4 +59,9 @@ static inline bool kvm_cpu__emulate_mmio(struct kvm_cpu *vcpu, u64 phys_addr,
 
 unsigned long kvm_cpu__get_vcpu_mpidr(struct kvm_cpu *vcpu);
 
+u64 kvm_cpu__smccc_get_arg1(struct kvm_cpu *vcpu);
+u64 kvm_cpu__smccc_get_arg2(struct kvm_cpu *vcpu);
+void kvm_cpu__smccc_return(struct kvm_cpu *vcpu, u64 a0, u64 a1, u64 a2, u64 a3);
+void kvm_cpu__psci_set_entry(struct kvm_cpu *vcpu, u64 entry_addr, u64 context_id);
+
 #endif /* ARM_COMMON__KVM_CPU_ARCH_H */
diff --git a/arm/kvm-cpu.c b/arm/kvm-cpu.c
index 164e399..677f8bb 100644
--- a/arm/kvm-cpu.c
+++ b/arm/kvm-cpu.c
@@ -163,3 +163,84 @@ bool kvm_cpu__handle_exit(struct kvm_cpu *vcpu)
 void kvm_cpu__show_page_tables(struct kvm_cpu *vcpu)
 {
 }
+
+static void kvm_cpu__arm_suspend(struct kvm_cpu *vcpu)
+{
+	struct kvm_mp_state mp_state = {
+		.mp_state = KVM_MP_STATE_SUSPENDED,
+	};
+
+	if (ioctl(vcpu->vcpu_fd, KVM_SET_MP_STATE, &mp_state) < 0)
+		die("KVM_SET_MP_STATE failed");
+}
+
+static void kvm_cpu__wakeup(struct kvm_cpu *vcpu)
+{
+	u64 entry_addr, context_id;
+
+	entry_addr = kvm_cpu__smccc_get_arg1(vcpu);
+	context_id = kvm_cpu__smccc_get_arg2(vcpu);
+
+	/*
+	 * The resuming CPU could have been a secondary CPU at boot. Ensure the
+	 * vCPU is made runnable.
+	 */
+	vcpu->init.features[0] &= ~(1ul << KVM_ARM_VCPU_POWER_OFF);
+
+	kvm_cpu__arch_reinit(vcpu);
+	kvm_cpu__reset_vcpu(vcpu);
+	kvm_cpu__psci_set_entry(vcpu, entry_addr, context_id);
+}
+
+static void kvm_cpu__psci_system_suspend(struct kvm_cpu *vcpu)
+{
+	struct kvm *kvm = vcpu->kvm;
+	bool denied = false;
+	int i;
+
+	/*
+	 * Mark the caller as paused before actually pausing the VM. This avoids
+	 * the hazard of attempting to acquire the pause_lock in the SIGKVMPAUSE
+	 * handler from the thread that already holds it.
+	 */
+	vcpu->paused = 1;
+
+	kvm__pause(kvm);
+	for (i = 0; i < kvm->nrcpus; i++) {
+		struct kvm_cpu *tmp = kvm->cpus[i];
+		struct kvm_mp_state mp_state;
+
+		if (vcpu == tmp)
+			continue;
+
+		if (ioctl(tmp->vcpu_fd, KVM_GET_MP_STATE, &mp_state) < 0)
+			die("KVM_GET_MP_STATE failed");
+
+		if (mp_state.mp_state != KVM_MP_STATE_STOPPED) {
+			denied = true;
+			break;
+		}
+	}
+
+	if (!denied)
+		kvm_cpu__arm_suspend(vcpu);
+	else
+		kvm_cpu__smccc_return(vcpu, PSCI_RET_DENIED, 0, 0, 0);
+
+	vcpu->paused = 0;
+	kvm__continue(kvm);
+}
+
+bool kvm_cpu__arch_handle_system_event(struct kvm_cpu *vcpu)
+{
+	switch (vcpu->kvm_run->system_event.type) {
+	case KVM_SYSTEM_EVENT_SUSPEND:
+		kvm_cpu__psci_system_suspend(vcpu);
+		return true;
+	case KVM_SYSTEM_EVENT_WAKEUP:
+		kvm_cpu__wakeup(vcpu);
+		return true;
+	default:
+		return false;
+	}
+}
diff --git a/arm/kvm.c b/arm/kvm.c
index 80d233f..8ae4711 100644
--- a/arm/kvm.c
+++ b/arm/kvm.c
@@ -86,6 +86,15 @@ void kvm__arch_init(struct kvm *kvm, const char *hugetlbfs_path, u64 ram_size)
 	/* Create the virtual GIC. */
 	if (gic__create(kvm, kvm->cfg.arch.irqchip))
 		die("Failed to create virtual GIC");
+
+	if (kvm__supports_extension(kvm, KVM_CAP_ARM_SYSTEM_SUSPEND)) {
+		struct kvm_enable_cap cap = {
+			.cap = KVM_CAP_ARM_SYSTEM_SUSPEND,
+		};
+
+		if (ioctl(kvm->vm_fd, KVM_ENABLE_CAP, &cap) < 0)
+			die("Enabling KVM_CAP_ARM_SYSTEM_SUSPEND failed");
+	}
 }
 
 #define FDT_ALIGN	SZ_2M
-- 
2.35.1.723.g4982287a31-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* Re: (subset) [PATCH v4 00/15] KVM: arm64: PSCI SYSTEM_SUSPEND + SYSTEM_RESET2 bugfix
  2022-03-11 17:39 ` Oliver Upton
@ 2022-03-18 14:07   ` Marc Zyngier
  -1 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2022-03-18 14:07 UTC (permalink / raw)
  To: kvmarm, Oliver Upton
  Cc: wanpengli, jmattson, pbonzini, vkuznets, pshier, atishp, kvm,
	kvm-riscv, joro

On Fri, 11 Mar 2022 17:39:46 +0000, Oliver Upton wrote:
> **NOTE** Patch 2 is a bugfix for commit d43583b890e7 ("KVM: arm64:
> Expose PSCI SYSTEM_RESET2 call to the guest") on kvmarm/next. Without
> this patch, it is possible for the guest to call
> PSCI_1_1_FN64_SYSTEM_RESET2 from AArch32.
> 
> The PSCI v1.0 specification describes a call, SYSTEM_SUSPEND, which
> allows software to request that the system be placed into the lowest
> possible power state and await an IMPLEMENTATION DEFINED wakeup event.
> This call is optional in v1.0 and v1.1. KVM does not currently support
> this optional call.
> 
> [...]

Applied to next, thanks!

[01/15] KVM: arm64: Generalise VM features into a set of flags
        commit: 06394531b425794dc56f3d525b7994d25b8072f7

Cheers,

	M.
-- 
Without deviation from the norm, progress is not possible.



^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: (subset) [PATCH v4 00/15] KVM: arm64: PSCI SYSTEM_SUSPEND + SYSTEM_RESET2 bugfix
@ 2022-03-18 14:07   ` Marc Zyngier
  0 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2022-03-18 14:07 UTC (permalink / raw)
  To: kvmarm, Oliver Upton
  Cc: wanpengli, kvm, joro, pshier, kvm-riscv, atishp, pbonzini,
	vkuznets, jmattson

On Fri, 11 Mar 2022 17:39:46 +0000, Oliver Upton wrote:
> **NOTE** Patch 2 is a bugfix for commit d43583b890e7 ("KVM: arm64:
> Expose PSCI SYSTEM_RESET2 call to the guest") on kvmarm/next. Without
> this patch, it is possible for the guest to call
> PSCI_1_1_FN64_SYSTEM_RESET2 from AArch32.
> 
> The PSCI v1.0 specification describes a call, SYSTEM_SUSPEND, which
> allows software to request that the system be placed into the lowest
> possible power state and await an IMPLEMENTATION DEFINED wakeup event.
> This call is optional in v1.0 and v1.1. KVM does not currently support
> this optional call.
> 
> [...]

Applied to next, thanks!

[01/15] KVM: arm64: Generalise VM features into a set of flags
        commit: 06394531b425794dc56f3d525b7994d25b8072f7

Cheers,

	M.
-- 
Without deviation from the norm, progress is not possible.


_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 07/15] KVM: Create helper for setting a system event exit
  2022-03-11 17:39   ` Oliver Upton
@ 2022-03-19  7:28     ` Anup Patel
  -1 siblings, 0 replies; 72+ messages in thread
From: Anup Patel @ 2022-03-19  7:28 UTC (permalink / raw)
  To: Oliver Upton
  Cc: moderated list:KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64),
	Alexandru Elisei, Atish Patra, James Morse, Jing Zhang,
	Jim Mattson, Joerg Roedel,
	open list:KERNEL VIRTUAL MACHINE FOR RISC-V (KVM/riscv),
	KVM General, Marc Zyngier, Paolo Bonzini, Peter Shier,
	Raghavendra Rao Ananta, Reiji Watanabe, Ricardo Koller,
	Sean Christopherson, Suzuki K Poulose, Vitaly Kuznetsov,
	Wanpeng Li

On Fri, Mar 11, 2022 at 11:11 PM Oliver Upton <oupton@google.com> wrote:
>
> Create a helper that appropriately configures kvm_run for a system event
> exit.
>
> No functional change intended.
>
> Suggested-by: Marc Zyngier <maz@kernel.org>
> Signed-off-by: Oliver Upton <oupton@google.com>
> Acked-by: Anup Patel <anup@brainfault.org>
> ---
>  arch/arm64/kvm/psci.c         | 5 +----
>  arch/riscv/kvm/vcpu_sbi_v01.c | 4 +---
>  arch/x86/kvm/x86.c            | 6 ++----
>  include/linux/kvm_host.h      | 2 ++
>  virt/kvm/kvm_main.c           | 8 ++++++++
>  5 files changed, 14 insertions(+), 11 deletions(-)
>
> diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
> index efd4428fda1c..78266716165e 100644
> --- a/arch/arm64/kvm/psci.c
> +++ b/arch/arm64/kvm/psci.c
> @@ -173,10 +173,7 @@ static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type, u64 flags)
>                 tmp->arch.mp_state.mp_state = KVM_MP_STATE_STOPPED;
>         kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
>
> -       memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
> -       vcpu->run->system_event.type = type;
> -       vcpu->run->system_event.flags = flags;
> -       vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
> +       kvm_vcpu_set_system_event_exit(vcpu, type, flags);
>  }
>
>  static void kvm_psci_system_off(struct kvm_vcpu *vcpu)
> diff --git a/arch/riscv/kvm/vcpu_sbi_v01.c b/arch/riscv/kvm/vcpu_sbi_v01.c
> index 07e2de14433a..c5581008dd88 100644
> --- a/arch/riscv/kvm/vcpu_sbi_v01.c
> +++ b/arch/riscv/kvm/vcpu_sbi_v01.c
> @@ -24,9 +24,7 @@ static void kvm_sbi_system_shutdown(struct kvm_vcpu *vcpu,
>                 tmp->arch.power_off = true;
>         kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
>
> -       memset(&run->system_event, 0, sizeof(run->system_event));
> -       run->system_event.type = type;
> -       run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
> +       kvm_vcpu_set_system_event_exit(vcpu, type, 0);

This patch needs to be rebased on the latest kvm/next because we have
done some refactoring to support SBI v0.3 SRST extension.

Thanks,
Anup

>  }
>
>  static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 7131d735b1ef..b3b94408cc61 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -9903,14 +9903,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
>                 if (kvm_check_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu))
>                         kvm_vcpu_reload_apic_access_page(vcpu);
>                 if (kvm_check_request(KVM_REQ_HV_CRASH, vcpu)) {
> -                       vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
> -                       vcpu->run->system_event.type = KVM_SYSTEM_EVENT_CRASH;
> +                       kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_CRASH, 0);
>                         r = 0;
>                         goto out;
>                 }
>                 if (kvm_check_request(KVM_REQ_HV_RESET, vcpu)) {
> -                       vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
> -                       vcpu->run->system_event.type = KVM_SYSTEM_EVENT_RESET;
> +                       kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_RESET, 0);
>                         r = 0;
>                         goto out;
>                 }
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index f11039944c08..c2a4fd2382e2 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -2202,6 +2202,8 @@ static inline void kvm_handle_signal_exit(struct kvm_vcpu *vcpu)
>  }
>  #endif /* CONFIG_KVM_XFER_TO_GUEST_WORK */
>
> +void kvm_vcpu_set_system_event_exit(struct kvm_vcpu *vcpu, u32 type, u64 flags);
> +
>  /*
>   * This defines how many reserved entries we want to keep before we
>   * kick the vcpu to the userspace to avoid dirty ring full.  This
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 58d31da8a2f7..197bae04ca34 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -3194,6 +3194,14 @@ void kvm_vcpu_mark_page_dirty(struct kvm_vcpu *vcpu, gfn_t gfn)
>  }
>  EXPORT_SYMBOL_GPL(kvm_vcpu_mark_page_dirty);
>
> +void kvm_vcpu_set_system_event_exit(struct kvm_vcpu *vcpu, u32 type, u64 flags)
> +{
> +       memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
> +       vcpu->run->system_event.type = type;
> +       vcpu->run->system_event.flags = flags;
> +       vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
> +}
> +
>  void kvm_sigset_activate(struct kvm_vcpu *vcpu)
>  {
>         if (!vcpu->sigset_active)
> --
> 2.35.1.723.g4982287a31-goog
>

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 07/15] KVM: Create helper for setting a system event exit
@ 2022-03-19  7:28     ` Anup Patel
  0 siblings, 0 replies; 72+ messages in thread
From: Anup Patel @ 2022-03-19  7:28 UTC (permalink / raw)
  To: Oliver Upton
  Cc: Wanpeng Li, KVM General, Marc Zyngier, Joerg Roedel, Peter Shier,
	open list:KERNEL VIRTUAL MACHINE FOR RISC-V (KVM/riscv),
	Atish Patra, Paolo Bonzini, Vitaly Kuznetsov,
	moderated list:KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64),
	Jim Mattson

On Fri, Mar 11, 2022 at 11:11 PM Oliver Upton <oupton@google.com> wrote:
>
> Create a helper that appropriately configures kvm_run for a system event
> exit.
>
> No functional change intended.
>
> Suggested-by: Marc Zyngier <maz@kernel.org>
> Signed-off-by: Oliver Upton <oupton@google.com>
> Acked-by: Anup Patel <anup@brainfault.org>
> ---
>  arch/arm64/kvm/psci.c         | 5 +----
>  arch/riscv/kvm/vcpu_sbi_v01.c | 4 +---
>  arch/x86/kvm/x86.c            | 6 ++----
>  include/linux/kvm_host.h      | 2 ++
>  virt/kvm/kvm_main.c           | 8 ++++++++
>  5 files changed, 14 insertions(+), 11 deletions(-)
>
> diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
> index efd4428fda1c..78266716165e 100644
> --- a/arch/arm64/kvm/psci.c
> +++ b/arch/arm64/kvm/psci.c
> @@ -173,10 +173,7 @@ static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type, u64 flags)
>                 tmp->arch.mp_state.mp_state = KVM_MP_STATE_STOPPED;
>         kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
>
> -       memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
> -       vcpu->run->system_event.type = type;
> -       vcpu->run->system_event.flags = flags;
> -       vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
> +       kvm_vcpu_set_system_event_exit(vcpu, type, flags);
>  }
>
>  static void kvm_psci_system_off(struct kvm_vcpu *vcpu)
> diff --git a/arch/riscv/kvm/vcpu_sbi_v01.c b/arch/riscv/kvm/vcpu_sbi_v01.c
> index 07e2de14433a..c5581008dd88 100644
> --- a/arch/riscv/kvm/vcpu_sbi_v01.c
> +++ b/arch/riscv/kvm/vcpu_sbi_v01.c
> @@ -24,9 +24,7 @@ static void kvm_sbi_system_shutdown(struct kvm_vcpu *vcpu,
>                 tmp->arch.power_off = true;
>         kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
>
> -       memset(&run->system_event, 0, sizeof(run->system_event));
> -       run->system_event.type = type;
> -       run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
> +       kvm_vcpu_set_system_event_exit(vcpu, type, 0);

This patch needs to be rebased on the latest kvm/next because we have
done some refactoring to support SBI v0.3 SRST extension.

Thanks,
Anup

>  }
>
>  static int kvm_sbi_ext_v01_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 7131d735b1ef..b3b94408cc61 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -9903,14 +9903,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
>                 if (kvm_check_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu))
>                         kvm_vcpu_reload_apic_access_page(vcpu);
>                 if (kvm_check_request(KVM_REQ_HV_CRASH, vcpu)) {
> -                       vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
> -                       vcpu->run->system_event.type = KVM_SYSTEM_EVENT_CRASH;
> +                       kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_CRASH, 0);
>                         r = 0;
>                         goto out;
>                 }
>                 if (kvm_check_request(KVM_REQ_HV_RESET, vcpu)) {
> -                       vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
> -                       vcpu->run->system_event.type = KVM_SYSTEM_EVENT_RESET;
> +                       kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_RESET, 0);
>                         r = 0;
>                         goto out;
>                 }
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index f11039944c08..c2a4fd2382e2 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -2202,6 +2202,8 @@ static inline void kvm_handle_signal_exit(struct kvm_vcpu *vcpu)
>  }
>  #endif /* CONFIG_KVM_XFER_TO_GUEST_WORK */
>
> +void kvm_vcpu_set_system_event_exit(struct kvm_vcpu *vcpu, u32 type, u64 flags);
> +
>  /*
>   * This defines how many reserved entries we want to keep before we
>   * kick the vcpu to the userspace to avoid dirty ring full.  This
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 58d31da8a2f7..197bae04ca34 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -3194,6 +3194,14 @@ void kvm_vcpu_mark_page_dirty(struct kvm_vcpu *vcpu, gfn_t gfn)
>  }
>  EXPORT_SYMBOL_GPL(kvm_vcpu_mark_page_dirty);
>
> +void kvm_vcpu_set_system_event_exit(struct kvm_vcpu *vcpu, u32 type, u64 flags)
> +{
> +       memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
> +       vcpu->run->system_event.type = type;
> +       vcpu->run->system_event.flags = flags;
> +       vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
> +}
> +
>  void kvm_sigset_activate(struct kvm_vcpu *vcpu)
>  {
>         if (!vcpu->sigset_active)
> --
> 2.35.1.723.g4982287a31-goog
>
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 09/15] KVM: arm64: Add support for userspace to suspend a vCPU
  2022-03-11 17:39   ` Oliver Upton
@ 2022-03-22  6:19     ` Reiji Watanabe
  -1 siblings, 0 replies; 72+ messages in thread
From: Reiji Watanabe @ 2022-03-22  6:19 UTC (permalink / raw)
  To: Oliver Upton
  Cc: kvmarm, Alexandru Elisei, Anup Patel, Atish Patra, James Morse,
	Jing Zhang, Jim Mattson, Joerg Roedel, kvm-riscv, kvm,
	Marc Zyngier, Paolo Bonzini, Peter Shier, Raghavendra Rao Ananta,
	Ricardo Koller, Sean Christopherson, Suzuki K Poulose,
	Vitaly Kuznetsov, Wanpeng Li

Hi Oliver,

On Fri, Mar 11, 2022 at 9:41 AM Oliver Upton <oupton@google.com> wrote:
>
> Introduce a new MP state, KVM_MP_STATE_SUSPENDED, which indicates a vCPU
> is in a suspended state. In the suspended state the vCPU will block
> until a wakeup event (pending interrupt) is recognized.
>
> Add a new system event type, KVM_SYSTEM_EVENT_WAKEUP, to indicate to
> userspace that KVM has recognized one such wakeup event. It is the
> responsibility of userspace to then make the vCPU runnable, or leave it
> suspended until the next wakeup event.
>
> Signed-off-by: Oliver Upton <oupton@google.com>
> ---
>  Documentation/virt/kvm/api.rst    | 37 +++++++++++++++++++++++++++++--
>  arch/arm64/include/asm/kvm_host.h |  1 +
>  arch/arm64/kvm/arm.c              | 35 +++++++++++++++++++++++++++++
>  include/uapi/linux/kvm.h          |  2 ++
>  4 files changed, 73 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> index 5625c08b4a0e..426bcdc1216d 100644
> --- a/Documentation/virt/kvm/api.rst
> +++ b/Documentation/virt/kvm/api.rst
> @@ -1482,14 +1482,43 @@ Possible values are:
>                                   [s390]
>     KVM_MP_STATE_LOAD             the vcpu is in a special load/startup state
>                                   [s390]
> +   KVM_MP_STATE_SUSPENDED        the vcpu is in a suspend state and is waiting
> +                                 for a wakeup event [arm64]
>     ==========================    ===============================================
>
>  On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
>  in-kernel irqchip, the multiprocessing state must be maintained by userspace on
>  these architectures.
>
> -For arm64/riscv:
> -^^^^^^^^^^^^^^^^
> +For arm64:
> +^^^^^^^^^^
> +
> +If a vCPU is in the KVM_MP_STATE_SUSPENDED state, KVM will emulate the
> +architectural execution of a WFI instruction.
> +
> +If a wakeup event is recognized, KVM will exit to userspace with a
> +KVM_SYSTEM_EVENT exit, where the event type is KVM_SYSTEM_EVENT_WAKEUP. If
> +userspace wants to honor the wakeup, it must set the vCPU's MP state to
> +KVM_MP_STATE_RUNNABLE. If it does not, KVM will continue to await a wakeup
> +event in subsequent calls to KVM_RUN.
> +
> +.. warning::
> +
> +     If userspace intends to keep the vCPU in a SUSPENDED state, it is
> +     strongly recommended that userspace take action to suppress the
> +     wakeup event (such as masking an interrupt). Otherwise, subsequent
> +     calls to KVM_RUN will immediately exit with a KVM_SYSTEM_EVENT_WAKEUP
> +     event and inadvertently waste CPU cycles.
> +
> +     Additionally, if userspace takes action to suppress a wakeup event,
> +     it is strongly recommended that it also restore the vCPU to its

Nit: s/restore/restores/ ?


> +     original state when the vCPU is made RUNNABLE again. For example,
> +     if userspace masked a pending interrupt to suppress the wakeup,
> +     the interrupt should be unmasked before returning control to the
> +     guest.
> +
> +For riscv:
> +^^^^^^^^^^
>
>  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.
> @@ -5914,6 +5943,7 @@ should put the acknowledged interrupt vector into the 'epr' field.
>    #define KVM_SYSTEM_EVENT_SHUTDOWN       1
>    #define KVM_SYSTEM_EVENT_RESET          2
>    #define KVM_SYSTEM_EVENT_CRASH          3
> +  #define KVM_SYSTEM_EVENT_WAKEUP         4
>                         __u32 type;
>                         __u64 flags;
>                 } system_event;
> @@ -5938,6 +5968,9 @@ Valid values for 'type' are:
>     has requested a crash condition maintenance. Userspace can choose
>     to ignore the request, or to gather VM memory core dump and/or
>     reset/shutdown of the VM.
> + - KVM_SYSTEM_EVENT_WAKEUP -- the guest is in a suspended state and KVM

Nit: Shouldn't 'the guest' be 'the vcpu' ?

> +   has recognized a wakeup event. Userspace may honor this event by marking
> +   the exiting vCPU as runnable, or deny it and call KVM_RUN again.
>
>  Valid flags are:
>
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index da58eb96d2a8..899f2c0b4c7b 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -46,6 +46,7 @@
>  #define KVM_REQ_RECORD_STEAL   KVM_ARCH_REQ(3)
>  #define KVM_REQ_RELOAD_GICv4   KVM_ARCH_REQ(4)
>  #define KVM_REQ_RELOAD_PMU     KVM_ARCH_REQ(5)
> +#define KVM_REQ_SUSPEND                KVM_ARCH_REQ(6)
>
>  #define KVM_DIRTY_LOG_MANUAL_CAPS   (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
>                                      KVM_DIRTY_LOG_INITIALLY_SET)
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 8eed0556ccaa..b94efa05d869 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -444,6 +444,18 @@ bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu)
>         return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_STOPPED;
>  }
>
> +static void kvm_arm_vcpu_suspend(struct kvm_vcpu *vcpu)
> +{
> +       vcpu->arch.mp_state.mp_state = KVM_MP_STATE_SUSPENDED;
> +       kvm_make_request(KVM_REQ_SUSPEND, vcpu);
> +       kvm_vcpu_kick(vcpu);
> +}
> +
> +static bool kvm_arm_vcpu_suspended(struct kvm_vcpu *vcpu)
> +{
> +       return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_SUSPENDED;
> +}
> +
>  int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
>                                     struct kvm_mp_state *mp_state)
>  {
> @@ -464,6 +476,9 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
>         case KVM_MP_STATE_STOPPED:
>                 kvm_arm_vcpu_power_off(vcpu);
>                 break;
> +       case KVM_MP_STATE_SUSPENDED:
> +               kvm_arm_vcpu_suspend(vcpu);
> +               break;
>         default:
>                 ret = -EINVAL;
>         }
> @@ -648,6 +663,23 @@ void kvm_vcpu_wfi(struct kvm_vcpu *vcpu)
>         preempt_enable();
>  }
>
> +static int kvm_vcpu_suspend(struct kvm_vcpu *vcpu)
> +{
> +       if (!kvm_arm_vcpu_suspended(vcpu))
> +               return 1;
> +
> +       kvm_vcpu_wfi(vcpu);
> +
> +       /*
> +        * The suspend state is sticky; we do not leave it until userspace
> +        * explicitly marks the vCPU as runnable. Request that we suspend again
> +        * later.
> +        */
> +       kvm_make_request(KVM_REQ_SUSPEND, vcpu);
> +       kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_WAKEUP, 0);
> +       return 0;
> +}
> +
>  /**
>   * check_vcpu_requests - check and handle pending vCPU requests
>   * @vcpu:      the VCPU pointer
> @@ -686,6 +718,9 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
>                 if (kvm_check_request(KVM_REQ_RELOAD_PMU, vcpu))
>                         kvm_pmu_handle_pmcr(vcpu,
>                                             __vcpu_sys_reg(vcpu, PMCR_EL0));
> +
> +               if (kvm_check_request(KVM_REQ_SUSPEND, vcpu))
> +                       return kvm_vcpu_suspend(vcpu);

It appears that one of the cases that kvm_vcpu_suspend() returns
is when a pending signal is detected, and the exit reason will be
KVM_EXIT_SYSTEM_EVENT in this case.  On the other hand, when a
pending signal is detected earlier in xfer_to_guest_mode_handle_work(),
KVM_RUN returns -EINTR even if the vCPU is in KVM_MP_STATE_SUSPENDED
state. Shouldn't those behaviors be consistent ? (Perhaps -EINTR?)

Thanks,
Reiji

>         }
>
>         return 1;
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 5191b57e1562..babb16c2abe5 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -444,6 +444,7 @@ struct kvm_run {
>  #define KVM_SYSTEM_EVENT_SHUTDOWN       1
>  #define KVM_SYSTEM_EVENT_RESET          2
>  #define KVM_SYSTEM_EVENT_CRASH          3
> +#define KVM_SYSTEM_EVENT_WAKEUP         4
>                         __u32 type;
>                         __u64 flags;
>                 } system_event;
> @@ -634,6 +635,7 @@ struct kvm_vapic_addr {
>  #define KVM_MP_STATE_OPERATING         7
>  #define KVM_MP_STATE_LOAD              8
>  #define KVM_MP_STATE_AP_RESET_HOLD     9
> +#define KVM_MP_STATE_SUSPENDED         10
>
>  struct kvm_mp_state {
>         __u32 mp_state;
> --
> 2.35.1.723.g4982287a31-goog
>

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 09/15] KVM: arm64: Add support for userspace to suspend a vCPU
@ 2022-03-22  6:19     ` Reiji Watanabe
  0 siblings, 0 replies; 72+ messages in thread
From: Reiji Watanabe @ 2022-03-22  6:19 UTC (permalink / raw)
  To: Oliver Upton
  Cc: Marc Zyngier, Wanpeng Li, kvm, Joerg Roedel, Peter Shier,
	kvm-riscv, Atish Patra, Paolo Bonzini, Vitaly Kuznetsov, kvmarm,
	Jim Mattson

Hi Oliver,

On Fri, Mar 11, 2022 at 9:41 AM Oliver Upton <oupton@google.com> wrote:
>
> Introduce a new MP state, KVM_MP_STATE_SUSPENDED, which indicates a vCPU
> is in a suspended state. In the suspended state the vCPU will block
> until a wakeup event (pending interrupt) is recognized.
>
> Add a new system event type, KVM_SYSTEM_EVENT_WAKEUP, to indicate to
> userspace that KVM has recognized one such wakeup event. It is the
> responsibility of userspace to then make the vCPU runnable, or leave it
> suspended until the next wakeup event.
>
> Signed-off-by: Oliver Upton <oupton@google.com>
> ---
>  Documentation/virt/kvm/api.rst    | 37 +++++++++++++++++++++++++++++--
>  arch/arm64/include/asm/kvm_host.h |  1 +
>  arch/arm64/kvm/arm.c              | 35 +++++++++++++++++++++++++++++
>  include/uapi/linux/kvm.h          |  2 ++
>  4 files changed, 73 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> index 5625c08b4a0e..426bcdc1216d 100644
> --- a/Documentation/virt/kvm/api.rst
> +++ b/Documentation/virt/kvm/api.rst
> @@ -1482,14 +1482,43 @@ Possible values are:
>                                   [s390]
>     KVM_MP_STATE_LOAD             the vcpu is in a special load/startup state
>                                   [s390]
> +   KVM_MP_STATE_SUSPENDED        the vcpu is in a suspend state and is waiting
> +                                 for a wakeup event [arm64]
>     ==========================    ===============================================
>
>  On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
>  in-kernel irqchip, the multiprocessing state must be maintained by userspace on
>  these architectures.
>
> -For arm64/riscv:
> -^^^^^^^^^^^^^^^^
> +For arm64:
> +^^^^^^^^^^
> +
> +If a vCPU is in the KVM_MP_STATE_SUSPENDED state, KVM will emulate the
> +architectural execution of a WFI instruction.
> +
> +If a wakeup event is recognized, KVM will exit to userspace with a
> +KVM_SYSTEM_EVENT exit, where the event type is KVM_SYSTEM_EVENT_WAKEUP. If
> +userspace wants to honor the wakeup, it must set the vCPU's MP state to
> +KVM_MP_STATE_RUNNABLE. If it does not, KVM will continue to await a wakeup
> +event in subsequent calls to KVM_RUN.
> +
> +.. warning::
> +
> +     If userspace intends to keep the vCPU in a SUSPENDED state, it is
> +     strongly recommended that userspace take action to suppress the
> +     wakeup event (such as masking an interrupt). Otherwise, subsequent
> +     calls to KVM_RUN will immediately exit with a KVM_SYSTEM_EVENT_WAKEUP
> +     event and inadvertently waste CPU cycles.
> +
> +     Additionally, if userspace takes action to suppress a wakeup event,
> +     it is strongly recommended that it also restore the vCPU to its

Nit: s/restore/restores/ ?


> +     original state when the vCPU is made RUNNABLE again. For example,
> +     if userspace masked a pending interrupt to suppress the wakeup,
> +     the interrupt should be unmasked before returning control to the
> +     guest.
> +
> +For riscv:
> +^^^^^^^^^^
>
>  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.
> @@ -5914,6 +5943,7 @@ should put the acknowledged interrupt vector into the 'epr' field.
>    #define KVM_SYSTEM_EVENT_SHUTDOWN       1
>    #define KVM_SYSTEM_EVENT_RESET          2
>    #define KVM_SYSTEM_EVENT_CRASH          3
> +  #define KVM_SYSTEM_EVENT_WAKEUP         4
>                         __u32 type;
>                         __u64 flags;
>                 } system_event;
> @@ -5938,6 +5968,9 @@ Valid values for 'type' are:
>     has requested a crash condition maintenance. Userspace can choose
>     to ignore the request, or to gather VM memory core dump and/or
>     reset/shutdown of the VM.
> + - KVM_SYSTEM_EVENT_WAKEUP -- the guest is in a suspended state and KVM

Nit: Shouldn't 'the guest' be 'the vcpu' ?

> +   has recognized a wakeup event. Userspace may honor this event by marking
> +   the exiting vCPU as runnable, or deny it and call KVM_RUN again.
>
>  Valid flags are:
>
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index da58eb96d2a8..899f2c0b4c7b 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -46,6 +46,7 @@
>  #define KVM_REQ_RECORD_STEAL   KVM_ARCH_REQ(3)
>  #define KVM_REQ_RELOAD_GICv4   KVM_ARCH_REQ(4)
>  #define KVM_REQ_RELOAD_PMU     KVM_ARCH_REQ(5)
> +#define KVM_REQ_SUSPEND                KVM_ARCH_REQ(6)
>
>  #define KVM_DIRTY_LOG_MANUAL_CAPS   (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
>                                      KVM_DIRTY_LOG_INITIALLY_SET)
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 8eed0556ccaa..b94efa05d869 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -444,6 +444,18 @@ bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu)
>         return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_STOPPED;
>  }
>
> +static void kvm_arm_vcpu_suspend(struct kvm_vcpu *vcpu)
> +{
> +       vcpu->arch.mp_state.mp_state = KVM_MP_STATE_SUSPENDED;
> +       kvm_make_request(KVM_REQ_SUSPEND, vcpu);
> +       kvm_vcpu_kick(vcpu);
> +}
> +
> +static bool kvm_arm_vcpu_suspended(struct kvm_vcpu *vcpu)
> +{
> +       return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_SUSPENDED;
> +}
> +
>  int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
>                                     struct kvm_mp_state *mp_state)
>  {
> @@ -464,6 +476,9 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
>         case KVM_MP_STATE_STOPPED:
>                 kvm_arm_vcpu_power_off(vcpu);
>                 break;
> +       case KVM_MP_STATE_SUSPENDED:
> +               kvm_arm_vcpu_suspend(vcpu);
> +               break;
>         default:
>                 ret = -EINVAL;
>         }
> @@ -648,6 +663,23 @@ void kvm_vcpu_wfi(struct kvm_vcpu *vcpu)
>         preempt_enable();
>  }
>
> +static int kvm_vcpu_suspend(struct kvm_vcpu *vcpu)
> +{
> +       if (!kvm_arm_vcpu_suspended(vcpu))
> +               return 1;
> +
> +       kvm_vcpu_wfi(vcpu);
> +
> +       /*
> +        * The suspend state is sticky; we do not leave it until userspace
> +        * explicitly marks the vCPU as runnable. Request that we suspend again
> +        * later.
> +        */
> +       kvm_make_request(KVM_REQ_SUSPEND, vcpu);
> +       kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_WAKEUP, 0);
> +       return 0;
> +}
> +
>  /**
>   * check_vcpu_requests - check and handle pending vCPU requests
>   * @vcpu:      the VCPU pointer
> @@ -686,6 +718,9 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
>                 if (kvm_check_request(KVM_REQ_RELOAD_PMU, vcpu))
>                         kvm_pmu_handle_pmcr(vcpu,
>                                             __vcpu_sys_reg(vcpu, PMCR_EL0));
> +
> +               if (kvm_check_request(KVM_REQ_SUSPEND, vcpu))
> +                       return kvm_vcpu_suspend(vcpu);

It appears that one of the cases that kvm_vcpu_suspend() returns
is when a pending signal is detected, and the exit reason will be
KVM_EXIT_SYSTEM_EVENT in this case.  On the other hand, when a
pending signal is detected earlier in xfer_to_guest_mode_handle_work(),
KVM_RUN returns -EINTR even if the vCPU is in KVM_MP_STATE_SUSPENDED
state. Shouldn't those behaviors be consistent ? (Perhaps -EINTR?)

Thanks,
Reiji

>         }
>
>         return 1;
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 5191b57e1562..babb16c2abe5 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -444,6 +444,7 @@ struct kvm_run {
>  #define KVM_SYSTEM_EVENT_SHUTDOWN       1
>  #define KVM_SYSTEM_EVENT_RESET          2
>  #define KVM_SYSTEM_EVENT_CRASH          3
> +#define KVM_SYSTEM_EVENT_WAKEUP         4
>                         __u32 type;
>                         __u64 flags;
>                 } system_event;
> @@ -634,6 +635,7 @@ struct kvm_vapic_addr {
>  #define KVM_MP_STATE_OPERATING         7
>  #define KVM_MP_STATE_LOAD              8
>  #define KVM_MP_STATE_AP_RESET_HOLD     9
> +#define KVM_MP_STATE_SUSPENDED         10
>
>  struct kvm_mp_state {
>         __u32 mp_state;
> --
> 2.35.1.723.g4982287a31-goog
>
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 08/15] KVM: arm64: Return a value from check_vcpu_requests()
  2022-03-11 17:39   ` Oliver Upton
@ 2022-03-22  6:21     ` Reiji Watanabe
  -1 siblings, 0 replies; 72+ messages in thread
From: Reiji Watanabe @ 2022-03-22  6:21 UTC (permalink / raw)
  To: Oliver Upton
  Cc: kvmarm, Alexandru Elisei, Anup Patel, Atish Patra, James Morse,
	Jing Zhang, Jim Mattson, Joerg Roedel, kvm-riscv, kvm,
	Marc Zyngier, Paolo Bonzini, Peter Shier, Raghavendra Rao Ananta,
	Ricardo Koller, Sean Christopherson, Suzuki K Poulose,
	Vitaly Kuznetsov, Wanpeng Li

Hi Oliver,

On Fri, Mar 11, 2022 at 9:41 AM Oliver Upton <oupton@google.com> wrote:
>
> A subsequent change to KVM will introduce a vCPU request that could
> result in an exit to userspace. Change check_vcpu_requests() to return a
> value and document the function. Unconditionally return 1 for now.
>
> Signed-off-by: Oliver Upton <oupton@google.com>
> ---
>  arch/arm64/kvm/arm.c | 16 ++++++++++++++--
>  1 file changed, 14 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 7c297ddc8177..8eed0556ccaa 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -648,7 +648,16 @@ void kvm_vcpu_wfi(struct kvm_vcpu *vcpu)
>         preempt_enable();
>  }
>
> -static void check_vcpu_requests(struct kvm_vcpu *vcpu)
> +/**
> + * check_vcpu_requests - check and handle pending vCPU requests
> + * @vcpu:      the VCPU pointer
> + *
> + * Return: 1 if we should enter the guest
> + *        0 if we should exit to userspace
> + *        <= 0 if we should exit to userspace, where the return value indicates
> + *        an error

Nit: Shouldn't "<= 0" be "< 0" ?

Thanks,
Reiji


> + */
> +static int check_vcpu_requests(struct kvm_vcpu *vcpu)
>  {
>         if (kvm_request_pending(vcpu)) {
>                 if (kvm_check_request(KVM_REQ_SLEEP, vcpu))
> @@ -678,6 +687,8 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu)
>                         kvm_pmu_handle_pmcr(vcpu,
>                                             __vcpu_sys_reg(vcpu, PMCR_EL0));
>         }
> +
> +       return 1;
>  }
>
>  static bool vcpu_mode_is_bad_32bit(struct kvm_vcpu *vcpu)
> @@ -793,7 +804,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
>                 if (!ret)
>                         ret = 1;
>
> -               check_vcpu_requests(vcpu);
> +               if (ret > 0)
> +                       ret = check_vcpu_requests(vcpu);
>
>                 /*
>                  * Preparing the interrupts to be injected also
> --
> 2.35.1.723.g4982287a31-goog
>

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 08/15] KVM: arm64: Return a value from check_vcpu_requests()
@ 2022-03-22  6:21     ` Reiji Watanabe
  0 siblings, 0 replies; 72+ messages in thread
From: Reiji Watanabe @ 2022-03-22  6:21 UTC (permalink / raw)
  To: Oliver Upton
  Cc: Marc Zyngier, Wanpeng Li, kvm, Joerg Roedel, Peter Shier,
	kvm-riscv, Atish Patra, Paolo Bonzini, Vitaly Kuznetsov, kvmarm,
	Jim Mattson

Hi Oliver,

On Fri, Mar 11, 2022 at 9:41 AM Oliver Upton <oupton@google.com> wrote:
>
> A subsequent change to KVM will introduce a vCPU request that could
> result in an exit to userspace. Change check_vcpu_requests() to return a
> value and document the function. Unconditionally return 1 for now.
>
> Signed-off-by: Oliver Upton <oupton@google.com>
> ---
>  arch/arm64/kvm/arm.c | 16 ++++++++++++++--
>  1 file changed, 14 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> index 7c297ddc8177..8eed0556ccaa 100644
> --- a/arch/arm64/kvm/arm.c
> +++ b/arch/arm64/kvm/arm.c
> @@ -648,7 +648,16 @@ void kvm_vcpu_wfi(struct kvm_vcpu *vcpu)
>         preempt_enable();
>  }
>
> -static void check_vcpu_requests(struct kvm_vcpu *vcpu)
> +/**
> + * check_vcpu_requests - check and handle pending vCPU requests
> + * @vcpu:      the VCPU pointer
> + *
> + * Return: 1 if we should enter the guest
> + *        0 if we should exit to userspace
> + *        <= 0 if we should exit to userspace, where the return value indicates
> + *        an error

Nit: Shouldn't "<= 0" be "< 0" ?

Thanks,
Reiji


> + */
> +static int check_vcpu_requests(struct kvm_vcpu *vcpu)
>  {
>         if (kvm_request_pending(vcpu)) {
>                 if (kvm_check_request(KVM_REQ_SLEEP, vcpu))
> @@ -678,6 +687,8 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu)
>                         kvm_pmu_handle_pmcr(vcpu,
>                                             __vcpu_sys_reg(vcpu, PMCR_EL0));
>         }
> +
> +       return 1;
>  }
>
>  static bool vcpu_mode_is_bad_32bit(struct kvm_vcpu *vcpu)
> @@ -793,7 +804,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
>                 if (!ret)
>                         ret = 1;
>
> -               check_vcpu_requests(vcpu);
> +               if (ret > 0)
> +                       ret = check_vcpu_requests(vcpu);
>
>                 /*
>                  * Preparing the interrupts to be injected also
> --
> 2.35.1.723.g4982287a31-goog
>
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 09/15] KVM: arm64: Add support for userspace to suspend a vCPU
  2022-03-22  6:19     ` Reiji Watanabe
@ 2022-03-22  6:49       ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-22  6:49 UTC (permalink / raw)
  To: Reiji Watanabe
  Cc: kvmarm, Alexandru Elisei, Anup Patel, Atish Patra, James Morse,
	Jing Zhang, Jim Mattson, Joerg Roedel, kvm-riscv, kvm,
	Marc Zyngier, Paolo Bonzini, Peter Shier, Raghavendra Rao Ananta,
	Ricardo Koller, Sean Christopherson, Suzuki K Poulose,
	Vitaly Kuznetsov, Wanpeng Li

On Mon, Mar 21, 2022 at 11:19:33PM -0700, Reiji Watanabe wrote:
> Hi Oliver,
> 
> On Fri, Mar 11, 2022 at 9:41 AM Oliver Upton <oupton@google.com> wrote:
> >
> > Introduce a new MP state, KVM_MP_STATE_SUSPENDED, which indicates a vCPU
> > is in a suspended state. In the suspended state the vCPU will block
> > until a wakeup event (pending interrupt) is recognized.
> >
> > Add a new system event type, KVM_SYSTEM_EVENT_WAKEUP, to indicate to
> > userspace that KVM has recognized one such wakeup event. It is the
> > responsibility of userspace to then make the vCPU runnable, or leave it
> > suspended until the next wakeup event.
> >
> > Signed-off-by: Oliver Upton <oupton@google.com>
> > ---
> >  Documentation/virt/kvm/api.rst    | 37 +++++++++++++++++++++++++++++--
> >  arch/arm64/include/asm/kvm_host.h |  1 +
> >  arch/arm64/kvm/arm.c              | 35 +++++++++++++++++++++++++++++
> >  include/uapi/linux/kvm.h          |  2 ++
> >  4 files changed, 73 insertions(+), 2 deletions(-)
> >
> > diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> > index 5625c08b4a0e..426bcdc1216d 100644
> > --- a/Documentation/virt/kvm/api.rst
> > +++ b/Documentation/virt/kvm/api.rst
> > @@ -1482,14 +1482,43 @@ Possible values are:
> >                                   [s390]
> >     KVM_MP_STATE_LOAD             the vcpu is in a special load/startup state
> >                                   [s390]
> > +   KVM_MP_STATE_SUSPENDED        the vcpu is in a suspend state and is waiting
> > +                                 for a wakeup event [arm64]
> >     ==========================    ===============================================
> >
> >  On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
> >  in-kernel irqchip, the multiprocessing state must be maintained by userspace on
> >  these architectures.
> >
> > -For arm64/riscv:
> > -^^^^^^^^^^^^^^^^
> > +For arm64:
> > +^^^^^^^^^^
> > +
> > +If a vCPU is in the KVM_MP_STATE_SUSPENDED state, KVM will emulate the
> > +architectural execution of a WFI instruction.
> > +
> > +If a wakeup event is recognized, KVM will exit to userspace with a
> > +KVM_SYSTEM_EVENT exit, where the event type is KVM_SYSTEM_EVENT_WAKEUP. If
> > +userspace wants to honor the wakeup, it must set the vCPU's MP state to
> > +KVM_MP_STATE_RUNNABLE. If it does not, KVM will continue to await a wakeup
> > +event in subsequent calls to KVM_RUN.
> > +
> > +.. warning::
> > +
> > +     If userspace intends to keep the vCPU in a SUSPENDED state, it is
> > +     strongly recommended that userspace take action to suppress the
> > +     wakeup event (such as masking an interrupt). Otherwise, subsequent
> > +     calls to KVM_RUN will immediately exit with a KVM_SYSTEM_EVENT_WAKEUP
> > +     event and inadvertently waste CPU cycles.
> > +
> > +     Additionally, if userspace takes action to suppress a wakeup event,
> > +     it is strongly recommended that it also restore the vCPU to its
> 
> Nit: s/restore/restores/ ?
> 
> 
> > +     original state when the vCPU is made RUNNABLE again. For example,
> > +     if userspace masked a pending interrupt to suppress the wakeup,
> > +     the interrupt should be unmasked before returning control to the
> > +     guest.
> > +
> > +For riscv:
> > +^^^^^^^^^^
> >
> >  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.
> > @@ -5914,6 +5943,7 @@ should put the acknowledged interrupt vector into the 'epr' field.
> >    #define KVM_SYSTEM_EVENT_SHUTDOWN       1
> >    #define KVM_SYSTEM_EVENT_RESET          2
> >    #define KVM_SYSTEM_EVENT_CRASH          3
> > +  #define KVM_SYSTEM_EVENT_WAKEUP         4
> >                         __u32 type;
> >                         __u64 flags;
> >                 } system_event;
> > @@ -5938,6 +5968,9 @@ Valid values for 'type' are:
> >     has requested a crash condition maintenance. Userspace can choose
> >     to ignore the request, or to gather VM memory core dump and/or
> >     reset/shutdown of the VM.
> > + - KVM_SYSTEM_EVENT_WAKEUP -- the guest is in a suspended state and KVM
> 
> Nit: Shouldn't 'the guest' be 'the vcpu' ?
> 
> > +   has recognized a wakeup event. Userspace may honor this event by marking
> > +   the exiting vCPU as runnable, or deny it and call KVM_RUN again.
> >
> >  Valid flags are:
> >
> > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > index da58eb96d2a8..899f2c0b4c7b 100644
> > --- a/arch/arm64/include/asm/kvm_host.h
> > +++ b/arch/arm64/include/asm/kvm_host.h
> > @@ -46,6 +46,7 @@
> >  #define KVM_REQ_RECORD_STEAL   KVM_ARCH_REQ(3)
> >  #define KVM_REQ_RELOAD_GICv4   KVM_ARCH_REQ(4)
> >  #define KVM_REQ_RELOAD_PMU     KVM_ARCH_REQ(5)
> > +#define KVM_REQ_SUSPEND                KVM_ARCH_REQ(6)
> >
> >  #define KVM_DIRTY_LOG_MANUAL_CAPS   (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
> >                                      KVM_DIRTY_LOG_INITIALLY_SET)
> > diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> > index 8eed0556ccaa..b94efa05d869 100644
> > --- a/arch/arm64/kvm/arm.c
> > +++ b/arch/arm64/kvm/arm.c
> > @@ -444,6 +444,18 @@ bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu)
> >         return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_STOPPED;
> >  }
> >
> > +static void kvm_arm_vcpu_suspend(struct kvm_vcpu *vcpu)
> > +{
> > +       vcpu->arch.mp_state.mp_state = KVM_MP_STATE_SUSPENDED;
> > +       kvm_make_request(KVM_REQ_SUSPEND, vcpu);
> > +       kvm_vcpu_kick(vcpu);
> > +}
> > +
> > +static bool kvm_arm_vcpu_suspended(struct kvm_vcpu *vcpu)
> > +{
> > +       return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_SUSPENDED;
> > +}
> > +
> >  int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
> >                                     struct kvm_mp_state *mp_state)
> >  {
> > @@ -464,6 +476,9 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
> >         case KVM_MP_STATE_STOPPED:
> >                 kvm_arm_vcpu_power_off(vcpu);
> >                 break;
> > +       case KVM_MP_STATE_SUSPENDED:
> > +               kvm_arm_vcpu_suspend(vcpu);
> > +               break;
> >         default:
> >                 ret = -EINVAL;
> >         }
> > @@ -648,6 +663,23 @@ void kvm_vcpu_wfi(struct kvm_vcpu *vcpu)
> >         preempt_enable();
> >  }
> >
> > +static int kvm_vcpu_suspend(struct kvm_vcpu *vcpu)
> > +{
> > +       if (!kvm_arm_vcpu_suspended(vcpu))
> > +               return 1;
> > +
> > +       kvm_vcpu_wfi(vcpu);
> > +
> > +       /*
> > +        * The suspend state is sticky; we do not leave it until userspace
> > +        * explicitly marks the vCPU as runnable. Request that we suspend again
> > +        * later.
> > +        */
> > +       kvm_make_request(KVM_REQ_SUSPEND, vcpu);
> > +       kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_WAKEUP, 0);
> > +       return 0;
> > +}
> > +
> >  /**
> >   * check_vcpu_requests - check and handle pending vCPU requests
> >   * @vcpu:      the VCPU pointer
> > @@ -686,6 +718,9 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
> >                 if (kvm_check_request(KVM_REQ_RELOAD_PMU, vcpu))
> >                         kvm_pmu_handle_pmcr(vcpu,
> >                                             __vcpu_sys_reg(vcpu, PMCR_EL0));
> > +
> > +               if (kvm_check_request(KVM_REQ_SUSPEND, vcpu))
> > +                       return kvm_vcpu_suspend(vcpu);
> 
> It appears that one of the cases that kvm_vcpu_suspend() returns
> is when a pending signal is detected, and the exit reason will be
> KVM_EXIT_SYSTEM_EVENT in this case.  On the other hand, when a
> pending signal is detected earlier in xfer_to_guest_mode_handle_work(),
> KVM_RUN returns -EINTR even if the vCPU is in KVM_MP_STATE_SUSPENDED
> state. Shouldn't those behaviors be consistent ? (Perhaps -EINTR?)

Great catch!

I should probably check that the vCPU is actually runnable with
kvm_arch_vcpu_runnable() before setting up a system event exit. That is
after all what the documentation of this whole API says it does, right?
:)

If the vCPU thread were poked for any other reason this should return 1
and let the kvm_vcpu_exit_request()/xfer_to_guest_mode_handle_work()
pairing clean up anything else.

Appreciate the review, other comments noted and will be addressed.

--
Thanks,
Oliver

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 09/15] KVM: arm64: Add support for userspace to suspend a vCPU
@ 2022-03-22  6:49       ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-22  6:49 UTC (permalink / raw)
  To: Reiji Watanabe
  Cc: Marc Zyngier, Wanpeng Li, kvm, Joerg Roedel, Peter Shier,
	kvm-riscv, Atish Patra, Paolo Bonzini, Vitaly Kuznetsov, kvmarm,
	Jim Mattson

On Mon, Mar 21, 2022 at 11:19:33PM -0700, Reiji Watanabe wrote:
> Hi Oliver,
> 
> On Fri, Mar 11, 2022 at 9:41 AM Oliver Upton <oupton@google.com> wrote:
> >
> > Introduce a new MP state, KVM_MP_STATE_SUSPENDED, which indicates a vCPU
> > is in a suspended state. In the suspended state the vCPU will block
> > until a wakeup event (pending interrupt) is recognized.
> >
> > Add a new system event type, KVM_SYSTEM_EVENT_WAKEUP, to indicate to
> > userspace that KVM has recognized one such wakeup event. It is the
> > responsibility of userspace to then make the vCPU runnable, or leave it
> > suspended until the next wakeup event.
> >
> > Signed-off-by: Oliver Upton <oupton@google.com>
> > ---
> >  Documentation/virt/kvm/api.rst    | 37 +++++++++++++++++++++++++++++--
> >  arch/arm64/include/asm/kvm_host.h |  1 +
> >  arch/arm64/kvm/arm.c              | 35 +++++++++++++++++++++++++++++
> >  include/uapi/linux/kvm.h          |  2 ++
> >  4 files changed, 73 insertions(+), 2 deletions(-)
> >
> > diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> > index 5625c08b4a0e..426bcdc1216d 100644
> > --- a/Documentation/virt/kvm/api.rst
> > +++ b/Documentation/virt/kvm/api.rst
> > @@ -1482,14 +1482,43 @@ Possible values are:
> >                                   [s390]
> >     KVM_MP_STATE_LOAD             the vcpu is in a special load/startup state
> >                                   [s390]
> > +   KVM_MP_STATE_SUSPENDED        the vcpu is in a suspend state and is waiting
> > +                                 for a wakeup event [arm64]
> >     ==========================    ===============================================
> >
> >  On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
> >  in-kernel irqchip, the multiprocessing state must be maintained by userspace on
> >  these architectures.
> >
> > -For arm64/riscv:
> > -^^^^^^^^^^^^^^^^
> > +For arm64:
> > +^^^^^^^^^^
> > +
> > +If a vCPU is in the KVM_MP_STATE_SUSPENDED state, KVM will emulate the
> > +architectural execution of a WFI instruction.
> > +
> > +If a wakeup event is recognized, KVM will exit to userspace with a
> > +KVM_SYSTEM_EVENT exit, where the event type is KVM_SYSTEM_EVENT_WAKEUP. If
> > +userspace wants to honor the wakeup, it must set the vCPU's MP state to
> > +KVM_MP_STATE_RUNNABLE. If it does not, KVM will continue to await a wakeup
> > +event in subsequent calls to KVM_RUN.
> > +
> > +.. warning::
> > +
> > +     If userspace intends to keep the vCPU in a SUSPENDED state, it is
> > +     strongly recommended that userspace take action to suppress the
> > +     wakeup event (such as masking an interrupt). Otherwise, subsequent
> > +     calls to KVM_RUN will immediately exit with a KVM_SYSTEM_EVENT_WAKEUP
> > +     event and inadvertently waste CPU cycles.
> > +
> > +     Additionally, if userspace takes action to suppress a wakeup event,
> > +     it is strongly recommended that it also restore the vCPU to its
> 
> Nit: s/restore/restores/ ?
> 
> 
> > +     original state when the vCPU is made RUNNABLE again. For example,
> > +     if userspace masked a pending interrupt to suppress the wakeup,
> > +     the interrupt should be unmasked before returning control to the
> > +     guest.
> > +
> > +For riscv:
> > +^^^^^^^^^^
> >
> >  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.
> > @@ -5914,6 +5943,7 @@ should put the acknowledged interrupt vector into the 'epr' field.
> >    #define KVM_SYSTEM_EVENT_SHUTDOWN       1
> >    #define KVM_SYSTEM_EVENT_RESET          2
> >    #define KVM_SYSTEM_EVENT_CRASH          3
> > +  #define KVM_SYSTEM_EVENT_WAKEUP         4
> >                         __u32 type;
> >                         __u64 flags;
> >                 } system_event;
> > @@ -5938,6 +5968,9 @@ Valid values for 'type' are:
> >     has requested a crash condition maintenance. Userspace can choose
> >     to ignore the request, or to gather VM memory core dump and/or
> >     reset/shutdown of the VM.
> > + - KVM_SYSTEM_EVENT_WAKEUP -- the guest is in a suspended state and KVM
> 
> Nit: Shouldn't 'the guest' be 'the vcpu' ?
> 
> > +   has recognized a wakeup event. Userspace may honor this event by marking
> > +   the exiting vCPU as runnable, or deny it and call KVM_RUN again.
> >
> >  Valid flags are:
> >
> > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > index da58eb96d2a8..899f2c0b4c7b 100644
> > --- a/arch/arm64/include/asm/kvm_host.h
> > +++ b/arch/arm64/include/asm/kvm_host.h
> > @@ -46,6 +46,7 @@
> >  #define KVM_REQ_RECORD_STEAL   KVM_ARCH_REQ(3)
> >  #define KVM_REQ_RELOAD_GICv4   KVM_ARCH_REQ(4)
> >  #define KVM_REQ_RELOAD_PMU     KVM_ARCH_REQ(5)
> > +#define KVM_REQ_SUSPEND                KVM_ARCH_REQ(6)
> >
> >  #define KVM_DIRTY_LOG_MANUAL_CAPS   (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
> >                                      KVM_DIRTY_LOG_INITIALLY_SET)
> > diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> > index 8eed0556ccaa..b94efa05d869 100644
> > --- a/arch/arm64/kvm/arm.c
> > +++ b/arch/arm64/kvm/arm.c
> > @@ -444,6 +444,18 @@ bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu)
> >         return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_STOPPED;
> >  }
> >
> > +static void kvm_arm_vcpu_suspend(struct kvm_vcpu *vcpu)
> > +{
> > +       vcpu->arch.mp_state.mp_state = KVM_MP_STATE_SUSPENDED;
> > +       kvm_make_request(KVM_REQ_SUSPEND, vcpu);
> > +       kvm_vcpu_kick(vcpu);
> > +}
> > +
> > +static bool kvm_arm_vcpu_suspended(struct kvm_vcpu *vcpu)
> > +{
> > +       return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_SUSPENDED;
> > +}
> > +
> >  int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
> >                                     struct kvm_mp_state *mp_state)
> >  {
> > @@ -464,6 +476,9 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
> >         case KVM_MP_STATE_STOPPED:
> >                 kvm_arm_vcpu_power_off(vcpu);
> >                 break;
> > +       case KVM_MP_STATE_SUSPENDED:
> > +               kvm_arm_vcpu_suspend(vcpu);
> > +               break;
> >         default:
> >                 ret = -EINVAL;
> >         }
> > @@ -648,6 +663,23 @@ void kvm_vcpu_wfi(struct kvm_vcpu *vcpu)
> >         preempt_enable();
> >  }
> >
> > +static int kvm_vcpu_suspend(struct kvm_vcpu *vcpu)
> > +{
> > +       if (!kvm_arm_vcpu_suspended(vcpu))
> > +               return 1;
> > +
> > +       kvm_vcpu_wfi(vcpu);
> > +
> > +       /*
> > +        * The suspend state is sticky; we do not leave it until userspace
> > +        * explicitly marks the vCPU as runnable. Request that we suspend again
> > +        * later.
> > +        */
> > +       kvm_make_request(KVM_REQ_SUSPEND, vcpu);
> > +       kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_WAKEUP, 0);
> > +       return 0;
> > +}
> > +
> >  /**
> >   * check_vcpu_requests - check and handle pending vCPU requests
> >   * @vcpu:      the VCPU pointer
> > @@ -686,6 +718,9 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
> >                 if (kvm_check_request(KVM_REQ_RELOAD_PMU, vcpu))
> >                         kvm_pmu_handle_pmcr(vcpu,
> >                                             __vcpu_sys_reg(vcpu, PMCR_EL0));
> > +
> > +               if (kvm_check_request(KVM_REQ_SUSPEND, vcpu))
> > +                       return kvm_vcpu_suspend(vcpu);
> 
> It appears that one of the cases that kvm_vcpu_suspend() returns
> is when a pending signal is detected, and the exit reason will be
> KVM_EXIT_SYSTEM_EVENT in this case.  On the other hand, when a
> pending signal is detected earlier in xfer_to_guest_mode_handle_work(),
> KVM_RUN returns -EINTR even if the vCPU is in KVM_MP_STATE_SUSPENDED
> state. Shouldn't those behaviors be consistent ? (Perhaps -EINTR?)

Great catch!

I should probably check that the vCPU is actually runnable with
kvm_arch_vcpu_runnable() before setting up a system event exit. That is
after all what the documentation of this whole API says it does, right?
:)

If the vCPU thread were poked for any other reason this should return 1
and let the kvm_vcpu_exit_request()/xfer_to_guest_mode_handle_work()
pairing clean up anything else.

Appreciate the review, other comments noted and will be addressed.

--
Thanks,
Oliver
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 08/15] KVM: arm64: Return a value from check_vcpu_requests()
  2022-03-22  6:21     ` Reiji Watanabe
@ 2022-03-22  6:51       ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-22  6:51 UTC (permalink / raw)
  To: Reiji Watanabe
  Cc: kvmarm, Alexandru Elisei, Anup Patel, Atish Patra, James Morse,
	Jing Zhang, Jim Mattson, Joerg Roedel, kvm-riscv, kvm,
	Marc Zyngier, Paolo Bonzini, Peter Shier, Raghavendra Rao Ananta,
	Ricardo Koller, Sean Christopherson, Suzuki K Poulose,
	Vitaly Kuznetsov, Wanpeng Li

On Mon, Mar 21, 2022 at 11:21:15PM -0700, Reiji Watanabe wrote:
> Hi Oliver,
> 
> On Fri, Mar 11, 2022 at 9:41 AM Oliver Upton <oupton@google.com> wrote:
> >
> > A subsequent change to KVM will introduce a vCPU request that could
> > result in an exit to userspace. Change check_vcpu_requests() to return a
> > value and document the function. Unconditionally return 1 for now.
> >
> > Signed-off-by: Oliver Upton <oupton@google.com>
> > ---
> >  arch/arm64/kvm/arm.c | 16 ++++++++++++++--
> >  1 file changed, 14 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> > index 7c297ddc8177..8eed0556ccaa 100644
> > --- a/arch/arm64/kvm/arm.c
> > +++ b/arch/arm64/kvm/arm.c
> > @@ -648,7 +648,16 @@ void kvm_vcpu_wfi(struct kvm_vcpu *vcpu)
> >         preempt_enable();
> >  }
> >
> > -static void check_vcpu_requests(struct kvm_vcpu *vcpu)
> > +/**
> > + * check_vcpu_requests - check and handle pending vCPU requests
> > + * @vcpu:      the VCPU pointer
> > + *
> > + * Return: 1 if we should enter the guest
> > + *        0 if we should exit to userspace
> > + *        <= 0 if we should exit to userspace, where the return value indicates
> > + *        an error
> 
> Nit: Shouldn't "<= 0" be "< 0" ?

It definitely should. I'll fold this in to the next spin.

--
Thanks,
Oliver

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 08/15] KVM: arm64: Return a value from check_vcpu_requests()
@ 2022-03-22  6:51       ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-22  6:51 UTC (permalink / raw)
  To: Reiji Watanabe
  Cc: Marc Zyngier, Wanpeng Li, kvm, Joerg Roedel, Peter Shier,
	kvm-riscv, Atish Patra, Paolo Bonzini, Vitaly Kuznetsov, kvmarm,
	Jim Mattson

On Mon, Mar 21, 2022 at 11:21:15PM -0700, Reiji Watanabe wrote:
> Hi Oliver,
> 
> On Fri, Mar 11, 2022 at 9:41 AM Oliver Upton <oupton@google.com> wrote:
> >
> > A subsequent change to KVM will introduce a vCPU request that could
> > result in an exit to userspace. Change check_vcpu_requests() to return a
> > value and document the function. Unconditionally return 1 for now.
> >
> > Signed-off-by: Oliver Upton <oupton@google.com>
> > ---
> >  arch/arm64/kvm/arm.c | 16 ++++++++++++++--
> >  1 file changed, 14 insertions(+), 2 deletions(-)
> >
> > diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> > index 7c297ddc8177..8eed0556ccaa 100644
> > --- a/arch/arm64/kvm/arm.c
> > +++ b/arch/arm64/kvm/arm.c
> > @@ -648,7 +648,16 @@ void kvm_vcpu_wfi(struct kvm_vcpu *vcpu)
> >         preempt_enable();
> >  }
> >
> > -static void check_vcpu_requests(struct kvm_vcpu *vcpu)
> > +/**
> > + * check_vcpu_requests - check and handle pending vCPU requests
> > + * @vcpu:      the VCPU pointer
> > + *
> > + * Return: 1 if we should enter the guest
> > + *        0 if we should exit to userspace
> > + *        <= 0 if we should exit to userspace, where the return value indicates
> > + *        an error
> 
> Nit: Shouldn't "<= 0" be "< 0" ?

It definitely should. I'll fold this in to the next spin.

--
Thanks,
Oliver
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 07/15] KVM: Create helper for setting a system event exit
  2022-03-19  7:28     ` Anup Patel
@ 2022-03-22  6:52       ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-22  6:52 UTC (permalink / raw)
  To: Anup Patel
  Cc: moderated list:KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64),
	Alexandru Elisei, Atish Patra, James Morse, Jing Zhang,
	Jim Mattson, Joerg Roedel,
	open list:KERNEL VIRTUAL MACHINE FOR RISC-V (KVM/riscv),
	KVM General, Marc Zyngier, Paolo Bonzini, Peter Shier,
	Raghavendra Rao Ananta, Reiji Watanabe, Ricardo Koller,
	Sean Christopherson, Suzuki K Poulose, Vitaly Kuznetsov,
	Wanpeng Li

On Sat, Mar 19, 2022 at 12:58:28PM +0530, Anup Patel wrote:
> On Fri, Mar 11, 2022 at 11:11 PM Oliver Upton <oupton@google.com> wrote:
> >
> > Create a helper that appropriately configures kvm_run for a system event
> > exit.
> >
> > No functional change intended.
> >
> > Suggested-by: Marc Zyngier <maz@kernel.org>
> > Signed-off-by: Oliver Upton <oupton@google.com>
> > Acked-by: Anup Patel <anup@brainfault.org>
> > ---
> >  arch/arm64/kvm/psci.c         | 5 +----
> >  arch/riscv/kvm/vcpu_sbi_v01.c | 4 +---
> >  arch/x86/kvm/x86.c            | 6 ++----
> >  include/linux/kvm_host.h      | 2 ++
> >  virt/kvm/kvm_main.c           | 8 ++++++++
> >  5 files changed, 14 insertions(+), 11 deletions(-)
> >
> > diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
> > index efd4428fda1c..78266716165e 100644
> > --- a/arch/arm64/kvm/psci.c
> > +++ b/arch/arm64/kvm/psci.c
> > @@ -173,10 +173,7 @@ static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type, u64 flags)
> >                 tmp->arch.mp_state.mp_state = KVM_MP_STATE_STOPPED;
> >         kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
> >
> > -       memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
> > -       vcpu->run->system_event.type = type;
> > -       vcpu->run->system_event.flags = flags;
> > -       vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
> > +       kvm_vcpu_set_system_event_exit(vcpu, type, flags);
> >  }
> >
> >  static void kvm_psci_system_off(struct kvm_vcpu *vcpu)
> > diff --git a/arch/riscv/kvm/vcpu_sbi_v01.c b/arch/riscv/kvm/vcpu_sbi_v01.c
> > index 07e2de14433a..c5581008dd88 100644
> > --- a/arch/riscv/kvm/vcpu_sbi_v01.c
> > +++ b/arch/riscv/kvm/vcpu_sbi_v01.c
> > @@ -24,9 +24,7 @@ static void kvm_sbi_system_shutdown(struct kvm_vcpu *vcpu,
> >                 tmp->arch.power_off = true;
> >         kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
> >
> > -       memset(&run->system_event, 0, sizeof(run->system_event));
> > -       run->system_event.type = type;
> > -       run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
> > +       kvm_vcpu_set_system_event_exit(vcpu, type, 0);
> 
> This patch needs to be rebased on the latest kvm/next because we have
> done some refactoring to support SBI v0.3 SRST extension.

Sure thing, I've already picked up some fixes anyhow so not a problem.
Thank you for letting me know directly about the conflict though :)

--
Thanks,
Oliver

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 07/15] KVM: Create helper for setting a system event exit
@ 2022-03-22  6:52       ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-03-22  6:52 UTC (permalink / raw)
  To: Anup Patel
  Cc: Wanpeng Li, KVM General, Marc Zyngier, Joerg Roedel, Peter Shier,
	open list:KERNEL VIRTUAL MACHINE FOR RISC-V (KVM/riscv),
	Atish Patra, Paolo Bonzini, Vitaly Kuznetsov,
	moderated list:KERNEL VIRTUAL MACHINE FOR ARM64 (KVM/arm64),
	Jim Mattson

On Sat, Mar 19, 2022 at 12:58:28PM +0530, Anup Patel wrote:
> On Fri, Mar 11, 2022 at 11:11 PM Oliver Upton <oupton@google.com> wrote:
> >
> > Create a helper that appropriately configures kvm_run for a system event
> > exit.
> >
> > No functional change intended.
> >
> > Suggested-by: Marc Zyngier <maz@kernel.org>
> > Signed-off-by: Oliver Upton <oupton@google.com>
> > Acked-by: Anup Patel <anup@brainfault.org>
> > ---
> >  arch/arm64/kvm/psci.c         | 5 +----
> >  arch/riscv/kvm/vcpu_sbi_v01.c | 4 +---
> >  arch/x86/kvm/x86.c            | 6 ++----
> >  include/linux/kvm_host.h      | 2 ++
> >  virt/kvm/kvm_main.c           | 8 ++++++++
> >  5 files changed, 14 insertions(+), 11 deletions(-)
> >
> > diff --git a/arch/arm64/kvm/psci.c b/arch/arm64/kvm/psci.c
> > index efd4428fda1c..78266716165e 100644
> > --- a/arch/arm64/kvm/psci.c
> > +++ b/arch/arm64/kvm/psci.c
> > @@ -173,10 +173,7 @@ static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type, u64 flags)
> >                 tmp->arch.mp_state.mp_state = KVM_MP_STATE_STOPPED;
> >         kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
> >
> > -       memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
> > -       vcpu->run->system_event.type = type;
> > -       vcpu->run->system_event.flags = flags;
> > -       vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
> > +       kvm_vcpu_set_system_event_exit(vcpu, type, flags);
> >  }
> >
> >  static void kvm_psci_system_off(struct kvm_vcpu *vcpu)
> > diff --git a/arch/riscv/kvm/vcpu_sbi_v01.c b/arch/riscv/kvm/vcpu_sbi_v01.c
> > index 07e2de14433a..c5581008dd88 100644
> > --- a/arch/riscv/kvm/vcpu_sbi_v01.c
> > +++ b/arch/riscv/kvm/vcpu_sbi_v01.c
> > @@ -24,9 +24,7 @@ static void kvm_sbi_system_shutdown(struct kvm_vcpu *vcpu,
> >                 tmp->arch.power_off = true;
> >         kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_SLEEP);
> >
> > -       memset(&run->system_event, 0, sizeof(run->system_event));
> > -       run->system_event.type = type;
> > -       run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
> > +       kvm_vcpu_set_system_event_exit(vcpu, type, 0);
> 
> This patch needs to be rebased on the latest kvm/next because we have
> done some refactoring to support SBI v0.3 SRST extension.

Sure thing, I've already picked up some fixes anyhow so not a problem.
Thank you for letting me know directly about the conflict though :)

--
Thanks,
Oliver
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 09/15] KVM: arm64: Add support for userspace to suspend a vCPU
  2022-03-22  6:49       ` Oliver Upton
@ 2022-03-24  6:44         ` Reiji Watanabe
  -1 siblings, 0 replies; 72+ messages in thread
From: Reiji Watanabe @ 2022-03-24  6:44 UTC (permalink / raw)
  To: Oliver Upton
  Cc: kvmarm, Alexandru Elisei, Anup Patel, Atish Patra, James Morse,
	Jing Zhang, Jim Mattson, Joerg Roedel, kvm-riscv, kvm,
	Marc Zyngier, Paolo Bonzini, Peter Shier, Raghavendra Rao Ananta,
	Ricardo Koller, Sean Christopherson, Suzuki K Poulose,
	Vitaly Kuznetsov, Wanpeng Li

Hi Oliver,

On Mon, Mar 21, 2022 at 11:49 PM Oliver Upton <oupton@google.com> wrote:
>
> On Mon, Mar 21, 2022 at 11:19:33PM -0700, Reiji Watanabe wrote:
> > Hi Oliver,
> >
> > On Fri, Mar 11, 2022 at 9:41 AM Oliver Upton <oupton@google.com> wrote:
> > >
> > > Introduce a new MP state, KVM_MP_STATE_SUSPENDED, which indicates a vCPU
> > > is in a suspended state. In the suspended state the vCPU will block
> > > until a wakeup event (pending interrupt) is recognized.
> > >
> > > Add a new system event type, KVM_SYSTEM_EVENT_WAKEUP, to indicate to
> > > userspace that KVM has recognized one such wakeup event. It is the
> > > responsibility of userspace to then make the vCPU runnable, or leave it
> > > suspended until the next wakeup event.
> > >
> > > Signed-off-by: Oliver Upton <oupton@google.com>
> > > ---
> > >  Documentation/virt/kvm/api.rst    | 37 +++++++++++++++++++++++++++++--
> > >  arch/arm64/include/asm/kvm_host.h |  1 +
> > >  arch/arm64/kvm/arm.c              | 35 +++++++++++++++++++++++++++++
> > >  include/uapi/linux/kvm.h          |  2 ++
> > >  4 files changed, 73 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> > > index 5625c08b4a0e..426bcdc1216d 100644
> > > --- a/Documentation/virt/kvm/api.rst
> > > +++ b/Documentation/virt/kvm/api.rst
> > > @@ -1482,14 +1482,43 @@ Possible values are:
> > >                                   [s390]
> > >     KVM_MP_STATE_LOAD             the vcpu is in a special load/startup state
> > >                                   [s390]
> > > +   KVM_MP_STATE_SUSPENDED        the vcpu is in a suspend state and is waiting
> > > +                                 for a wakeup event [arm64]
> > >     ==========================    ===============================================
> > >
> > >  On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
> > >  in-kernel irqchip, the multiprocessing state must be maintained by userspace on
> > >  these architectures.
> > >
> > > -For arm64/riscv:
> > > -^^^^^^^^^^^^^^^^
> > > +For arm64:
> > > +^^^^^^^^^^
> > > +
> > > +If a vCPU is in the KVM_MP_STATE_SUSPENDED state, KVM will emulate the
> > > +architectural execution of a WFI instruction.
> > > +
> > > +If a wakeup event is recognized, KVM will exit to userspace with a
> > > +KVM_SYSTEM_EVENT exit, where the event type is KVM_SYSTEM_EVENT_WAKEUP. If
> > > +userspace wants to honor the wakeup, it must set the vCPU's MP state to
> > > +KVM_MP_STATE_RUNNABLE. If it does not, KVM will continue to await a wakeup
> > > +event in subsequent calls to KVM_RUN.
> > > +
> > > +.. warning::
> > > +
> > > +     If userspace intends to keep the vCPU in a SUSPENDED state, it is
> > > +     strongly recommended that userspace take action to suppress the
> > > +     wakeup event (such as masking an interrupt). Otherwise, subsequent
> > > +     calls to KVM_RUN will immediately exit with a KVM_SYSTEM_EVENT_WAKEUP
> > > +     event and inadvertently waste CPU cycles.
> > > +
> > > +     Additionally, if userspace takes action to suppress a wakeup event,
> > > +     it is strongly recommended that it also restore the vCPU to its
> >
> > Nit: s/restore/restores/ ?
> >
> >
> > > +     original state when the vCPU is made RUNNABLE again. For example,
> > > +     if userspace masked a pending interrupt to suppress the wakeup,
> > > +     the interrupt should be unmasked before returning control to the
> > > +     guest.
> > > +
> > > +For riscv:
> > > +^^^^^^^^^^
> > >
> > >  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.
> > > @@ -5914,6 +5943,7 @@ should put the acknowledged interrupt vector into the 'epr' field.
> > >    #define KVM_SYSTEM_EVENT_SHUTDOWN       1
> > >    #define KVM_SYSTEM_EVENT_RESET          2
> > >    #define KVM_SYSTEM_EVENT_CRASH          3
> > > +  #define KVM_SYSTEM_EVENT_WAKEUP         4
> > >                         __u32 type;
> > >                         __u64 flags;
> > >                 } system_event;
> > > @@ -5938,6 +5968,9 @@ Valid values for 'type' are:
> > >     has requested a crash condition maintenance. Userspace can choose
> > >     to ignore the request, or to gather VM memory core dump and/or
> > >     reset/shutdown of the VM.
> > > + - KVM_SYSTEM_EVENT_WAKEUP -- the guest is in a suspended state and KVM
> >
> > Nit: Shouldn't 'the guest' be 'the vcpu' ?
> >
> > > +   has recognized a wakeup event. Userspace may honor this event by marking
> > > +   the exiting vCPU as runnable, or deny it and call KVM_RUN again.
> > >
> > >  Valid flags are:
> > >
> > > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > > index da58eb96d2a8..899f2c0b4c7b 100644
> > > --- a/arch/arm64/include/asm/kvm_host.h
> > > +++ b/arch/arm64/include/asm/kvm_host.h
> > > @@ -46,6 +46,7 @@
> > >  #define KVM_REQ_RECORD_STEAL   KVM_ARCH_REQ(3)
> > >  #define KVM_REQ_RELOAD_GICv4   KVM_ARCH_REQ(4)
> > >  #define KVM_REQ_RELOAD_PMU     KVM_ARCH_REQ(5)
> > > +#define KVM_REQ_SUSPEND                KVM_ARCH_REQ(6)
> > >
> > >  #define KVM_DIRTY_LOG_MANUAL_CAPS   (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
> > >                                      KVM_DIRTY_LOG_INITIALLY_SET)
> > > diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> > > index 8eed0556ccaa..b94efa05d869 100644
> > > --- a/arch/arm64/kvm/arm.c
> > > +++ b/arch/arm64/kvm/arm.c
> > > @@ -444,6 +444,18 @@ bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu)
> > >         return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_STOPPED;
> > >  }
> > >
> > > +static void kvm_arm_vcpu_suspend(struct kvm_vcpu *vcpu)
> > > +{
> > > +       vcpu->arch.mp_state.mp_state = KVM_MP_STATE_SUSPENDED;
> > > +       kvm_make_request(KVM_REQ_SUSPEND, vcpu);
> > > +       kvm_vcpu_kick(vcpu);
> > > +}
> > > +
> > > +static bool kvm_arm_vcpu_suspended(struct kvm_vcpu *vcpu)
> > > +{
> > > +       return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_SUSPENDED;
> > > +}
> > > +
> > >  int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
> > >                                     struct kvm_mp_state *mp_state)
> > >  {
> > > @@ -464,6 +476,9 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
> > >         case KVM_MP_STATE_STOPPED:
> > >                 kvm_arm_vcpu_power_off(vcpu);
> > >                 break;
> > > +       case KVM_MP_STATE_SUSPENDED:
> > > +               kvm_arm_vcpu_suspend(vcpu);
> > > +               break;
> > >         default:
> > >                 ret = -EINVAL;
> > >         }
> > > @@ -648,6 +663,23 @@ void kvm_vcpu_wfi(struct kvm_vcpu *vcpu)
> > >         preempt_enable();
> > >  }
> > >
> > > +static int kvm_vcpu_suspend(struct kvm_vcpu *vcpu)
> > > +{
> > > +       if (!kvm_arm_vcpu_suspended(vcpu))
> > > +               return 1;
> > > +
> > > +       kvm_vcpu_wfi(vcpu);
> > > +
> > > +       /*
> > > +        * The suspend state is sticky; we do not leave it until userspace
> > > +        * explicitly marks the vCPU as runnable. Request that we suspend again
> > > +        * later.
> > > +        */
> > > +       kvm_make_request(KVM_REQ_SUSPEND, vcpu);
> > > +       kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_WAKEUP, 0);
> > > +       return 0;
> > > +}
> > > +
> > >  /**
> > >   * check_vcpu_requests - check and handle pending vCPU requests
> > >   * @vcpu:      the VCPU pointer
> > > @@ -686,6 +718,9 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
> > >                 if (kvm_check_request(KVM_REQ_RELOAD_PMU, vcpu))
> > >                         kvm_pmu_handle_pmcr(vcpu,
> > >                                             __vcpu_sys_reg(vcpu, PMCR_EL0));
> > > +
> > > +               if (kvm_check_request(KVM_REQ_SUSPEND, vcpu))
> > > +                       return kvm_vcpu_suspend(vcpu);
> >
> > It appears that one of the cases that kvm_vcpu_suspend() returns
> > is when a pending signal is detected, and the exit reason will be
> > KVM_EXIT_SYSTEM_EVENT in this case.  On the other hand, when a
> > pending signal is detected earlier in xfer_to_guest_mode_handle_work(),
> > KVM_RUN returns -EINTR even if the vCPU is in KVM_MP_STATE_SUSPENDED
> > state. Shouldn't those behaviors be consistent ? (Perhaps -EINTR?)
>
> Great catch!
>
> I should probably check that the vCPU is actually runnable with
> kvm_arch_vcpu_runnable() before setting up a system event exit. That is
> after all what the documentation of this whole API says it does, right?
> :)
>
> If the vCPU thread were poked for any other reason this should return 1
> and let the kvm_vcpu_exit_request()/xfer_to_guest_mode_handle_work()
> pairing clean up anything else.

Yes, that sounds good.

Thanks,
Reiji

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v4 09/15] KVM: arm64: Add support for userspace to suspend a vCPU
@ 2022-03-24  6:44         ` Reiji Watanabe
  0 siblings, 0 replies; 72+ messages in thread
From: Reiji Watanabe @ 2022-03-24  6:44 UTC (permalink / raw)
  To: Oliver Upton
  Cc: Marc Zyngier, Wanpeng Li, kvm, Joerg Roedel, Peter Shier,
	kvm-riscv, Atish Patra, Paolo Bonzini, Vitaly Kuznetsov, kvmarm,
	Jim Mattson

Hi Oliver,

On Mon, Mar 21, 2022 at 11:49 PM Oliver Upton <oupton@google.com> wrote:
>
> On Mon, Mar 21, 2022 at 11:19:33PM -0700, Reiji Watanabe wrote:
> > Hi Oliver,
> >
> > On Fri, Mar 11, 2022 at 9:41 AM Oliver Upton <oupton@google.com> wrote:
> > >
> > > Introduce a new MP state, KVM_MP_STATE_SUSPENDED, which indicates a vCPU
> > > is in a suspended state. In the suspended state the vCPU will block
> > > until a wakeup event (pending interrupt) is recognized.
> > >
> > > Add a new system event type, KVM_SYSTEM_EVENT_WAKEUP, to indicate to
> > > userspace that KVM has recognized one such wakeup event. It is the
> > > responsibility of userspace to then make the vCPU runnable, or leave it
> > > suspended until the next wakeup event.
> > >
> > > Signed-off-by: Oliver Upton <oupton@google.com>
> > > ---
> > >  Documentation/virt/kvm/api.rst    | 37 +++++++++++++++++++++++++++++--
> > >  arch/arm64/include/asm/kvm_host.h |  1 +
> > >  arch/arm64/kvm/arm.c              | 35 +++++++++++++++++++++++++++++
> > >  include/uapi/linux/kvm.h          |  2 ++
> > >  4 files changed, 73 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> > > index 5625c08b4a0e..426bcdc1216d 100644
> > > --- a/Documentation/virt/kvm/api.rst
> > > +++ b/Documentation/virt/kvm/api.rst
> > > @@ -1482,14 +1482,43 @@ Possible values are:
> > >                                   [s390]
> > >     KVM_MP_STATE_LOAD             the vcpu is in a special load/startup state
> > >                                   [s390]
> > > +   KVM_MP_STATE_SUSPENDED        the vcpu is in a suspend state and is waiting
> > > +                                 for a wakeup event [arm64]
> > >     ==========================    ===============================================
> > >
> > >  On x86, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an
> > >  in-kernel irqchip, the multiprocessing state must be maintained by userspace on
> > >  these architectures.
> > >
> > > -For arm64/riscv:
> > > -^^^^^^^^^^^^^^^^
> > > +For arm64:
> > > +^^^^^^^^^^
> > > +
> > > +If a vCPU is in the KVM_MP_STATE_SUSPENDED state, KVM will emulate the
> > > +architectural execution of a WFI instruction.
> > > +
> > > +If a wakeup event is recognized, KVM will exit to userspace with a
> > > +KVM_SYSTEM_EVENT exit, where the event type is KVM_SYSTEM_EVENT_WAKEUP. If
> > > +userspace wants to honor the wakeup, it must set the vCPU's MP state to
> > > +KVM_MP_STATE_RUNNABLE. If it does not, KVM will continue to await a wakeup
> > > +event in subsequent calls to KVM_RUN.
> > > +
> > > +.. warning::
> > > +
> > > +     If userspace intends to keep the vCPU in a SUSPENDED state, it is
> > > +     strongly recommended that userspace take action to suppress the
> > > +     wakeup event (such as masking an interrupt). Otherwise, subsequent
> > > +     calls to KVM_RUN will immediately exit with a KVM_SYSTEM_EVENT_WAKEUP
> > > +     event and inadvertently waste CPU cycles.
> > > +
> > > +     Additionally, if userspace takes action to suppress a wakeup event,
> > > +     it is strongly recommended that it also restore the vCPU to its
> >
> > Nit: s/restore/restores/ ?
> >
> >
> > > +     original state when the vCPU is made RUNNABLE again. For example,
> > > +     if userspace masked a pending interrupt to suppress the wakeup,
> > > +     the interrupt should be unmasked before returning control to the
> > > +     guest.
> > > +
> > > +For riscv:
> > > +^^^^^^^^^^
> > >
> > >  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.
> > > @@ -5914,6 +5943,7 @@ should put the acknowledged interrupt vector into the 'epr' field.
> > >    #define KVM_SYSTEM_EVENT_SHUTDOWN       1
> > >    #define KVM_SYSTEM_EVENT_RESET          2
> > >    #define KVM_SYSTEM_EVENT_CRASH          3
> > > +  #define KVM_SYSTEM_EVENT_WAKEUP         4
> > >                         __u32 type;
> > >                         __u64 flags;
> > >                 } system_event;
> > > @@ -5938,6 +5968,9 @@ Valid values for 'type' are:
> > >     has requested a crash condition maintenance. Userspace can choose
> > >     to ignore the request, or to gather VM memory core dump and/or
> > >     reset/shutdown of the VM.
> > > + - KVM_SYSTEM_EVENT_WAKEUP -- the guest is in a suspended state and KVM
> >
> > Nit: Shouldn't 'the guest' be 'the vcpu' ?
> >
> > > +   has recognized a wakeup event. Userspace may honor this event by marking
> > > +   the exiting vCPU as runnable, or deny it and call KVM_RUN again.
> > >
> > >  Valid flags are:
> > >
> > > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> > > index da58eb96d2a8..899f2c0b4c7b 100644
> > > --- a/arch/arm64/include/asm/kvm_host.h
> > > +++ b/arch/arm64/include/asm/kvm_host.h
> > > @@ -46,6 +46,7 @@
> > >  #define KVM_REQ_RECORD_STEAL   KVM_ARCH_REQ(3)
> > >  #define KVM_REQ_RELOAD_GICv4   KVM_ARCH_REQ(4)
> > >  #define KVM_REQ_RELOAD_PMU     KVM_ARCH_REQ(5)
> > > +#define KVM_REQ_SUSPEND                KVM_ARCH_REQ(6)
> > >
> > >  #define KVM_DIRTY_LOG_MANUAL_CAPS   (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
> > >                                      KVM_DIRTY_LOG_INITIALLY_SET)
> > > diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
> > > index 8eed0556ccaa..b94efa05d869 100644
> > > --- a/arch/arm64/kvm/arm.c
> > > +++ b/arch/arm64/kvm/arm.c
> > > @@ -444,6 +444,18 @@ bool kvm_arm_vcpu_stopped(struct kvm_vcpu *vcpu)
> > >         return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_STOPPED;
> > >  }
> > >
> > > +static void kvm_arm_vcpu_suspend(struct kvm_vcpu *vcpu)
> > > +{
> > > +       vcpu->arch.mp_state.mp_state = KVM_MP_STATE_SUSPENDED;
> > > +       kvm_make_request(KVM_REQ_SUSPEND, vcpu);
> > > +       kvm_vcpu_kick(vcpu);
> > > +}
> > > +
> > > +static bool kvm_arm_vcpu_suspended(struct kvm_vcpu *vcpu)
> > > +{
> > > +       return vcpu->arch.mp_state.mp_state == KVM_MP_STATE_SUSPENDED;
> > > +}
> > > +
> > >  int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
> > >                                     struct kvm_mp_state *mp_state)
> > >  {
> > > @@ -464,6 +476,9 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
> > >         case KVM_MP_STATE_STOPPED:
> > >                 kvm_arm_vcpu_power_off(vcpu);
> > >                 break;
> > > +       case KVM_MP_STATE_SUSPENDED:
> > > +               kvm_arm_vcpu_suspend(vcpu);
> > > +               break;
> > >         default:
> > >                 ret = -EINVAL;
> > >         }
> > > @@ -648,6 +663,23 @@ void kvm_vcpu_wfi(struct kvm_vcpu *vcpu)
> > >         preempt_enable();
> > >  }
> > >
> > > +static int kvm_vcpu_suspend(struct kvm_vcpu *vcpu)
> > > +{
> > > +       if (!kvm_arm_vcpu_suspended(vcpu))
> > > +               return 1;
> > > +
> > > +       kvm_vcpu_wfi(vcpu);
> > > +
> > > +       /*
> > > +        * The suspend state is sticky; we do not leave it until userspace
> > > +        * explicitly marks the vCPU as runnable. Request that we suspend again
> > > +        * later.
> > > +        */
> > > +       kvm_make_request(KVM_REQ_SUSPEND, vcpu);
> > > +       kvm_vcpu_set_system_event_exit(vcpu, KVM_SYSTEM_EVENT_WAKEUP, 0);
> > > +       return 0;
> > > +}
> > > +
> > >  /**
> > >   * check_vcpu_requests - check and handle pending vCPU requests
> > >   * @vcpu:      the VCPU pointer
> > > @@ -686,6 +718,9 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
> > >                 if (kvm_check_request(KVM_REQ_RELOAD_PMU, vcpu))
> > >                         kvm_pmu_handle_pmcr(vcpu,
> > >                                             __vcpu_sys_reg(vcpu, PMCR_EL0));
> > > +
> > > +               if (kvm_check_request(KVM_REQ_SUSPEND, vcpu))
> > > +                       return kvm_vcpu_suspend(vcpu);
> >
> > It appears that one of the cases that kvm_vcpu_suspend() returns
> > is when a pending signal is detected, and the exit reason will be
> > KVM_EXIT_SYSTEM_EVENT in this case.  On the other hand, when a
> > pending signal is detected earlier in xfer_to_guest_mode_handle_work(),
> > KVM_RUN returns -EINTR even if the vCPU is in KVM_MP_STATE_SUSPENDED
> > state. Shouldn't those behaviors be consistent ? (Perhaps -EINTR?)
>
> Great catch!
>
> I should probably check that the vCPU is actually runnable with
> kvm_arch_vcpu_runnable() before setting up a system event exit. That is
> after all what the documentation of this whole API says it does, right?
> :)
>
> If the vCPU thread were poked for any other reason this should return 1
> and let the kvm_vcpu_exit_request()/xfer_to_guest_mode_handle_work()
> pairing clean up anything else.

Yes, that sounds good.

Thanks,
Reiji
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC PATCH kvmtool 0/5] ARM: Implement PSCI SYSTEM_SUSPEND
  2022-03-11 17:57   ` Oliver Upton
  (?)
@ 2022-05-06 13:01     ` Will Deacon
  -1 siblings, 0 replies; 72+ messages in thread
From: Will Deacon @ 2022-05-06 13:01 UTC (permalink / raw)
  To: Oliver Upton
  Cc: kvmarm, kvm, Marc Zyngier, James Morse, Alexandru Elisei,
	Suzuki K Poulose, linux-arm-kernel, Peter Shier, Ricardo Koller,
	Reiji Watanabe, Julien Thierry

On Fri, Mar 11, 2022 at 05:57:12PM +0000, Oliver Upton wrote:
> This is a prototype for supporting KVM_CAP_ARM_SYSTEM_SUSPEND on
> kvmtool. The capability allows userspace to expose the SYSTEM_SUSPEND
> PSCI call to its guests.
> 
> Implement SYSTEM_SUSPEND using KVM_MP_STATE_SUSPENDED, which emulates
> the execution of a WFI instruction in the kernel. Resume the guest when
> a wakeup event is recognized and reset it to the requested entry address
> and context ID.
> 
> Patches 2-4 are small reworks to more easily shoehorn PSCI support into
> kvmtool.
> 
> Patch 5 adds some SMCCC handlers and makes use of them to implement PSCI
> SYSTEM_SUSPEND. For now, just check the bare-minimum, that all vCPUs
> besides the caller have stopped. There are also checks that can be made
> against the requested entry address, but they are at the discretion of
> the implementation.
> 
> Tested with 'echo mem > /sys/power/state' to see that the vCPU is in
> fact placed in a suspended state for the PSCI call. Hacked the switch
> statement to fall through to WAKEUP immediately after to verify the vCPU
> is set up correctly for resume.
> 
> It would be nice if kvmtool actually provided a device good for wakeups,
> since the RTC implementation has omitted any interrupt support.
> 
> kernel changes: http://lore.kernel.org/r/20220311174001.605719-1-oupton@google.com
> 
> Oliver Upton (5):
>   TESTONLY: Sync KVM headers with pending changes
>   Allow architectures to hook KVM_EXIT_SYSTEM_EVENT
>   ARM: Stash vcpu_init in the vCPU structure
>   ARM: Add a helper to re-init a vCPU
>   ARM: Implement PSCI SYSTEM_SUSPEND
> 
>  arm/aarch32/kvm-cpu.c                 | 72 ++++++++++++++++++++
>  arm/aarch64/kvm-cpu.c                 | 66 +++++++++++++++++++
>  arm/include/arm-common/kvm-cpu-arch.h | 23 ++++---
>  arm/kvm-cpu.c                         | 95 ++++++++++++++++++++++++++-
>  arm/kvm.c                             |  9 +++
>  include/kvm/kvm-cpu.h                 |  1 +
>  include/linux/kvm.h                   | 21 ++++++
>  kvm-cpu.c                             |  8 +++
>  8 files changed, 283 insertions(+), 12 deletions(-)

Looks like the kernel-side changes are queued now, so please can you resend
this series? I also think you can drop the AArch32 support, unless you see a
compelling reason for it?

Will

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC PATCH kvmtool 0/5] ARM: Implement PSCI SYSTEM_SUSPEND
@ 2022-05-06 13:01     ` Will Deacon
  0 siblings, 0 replies; 72+ messages in thread
From: Will Deacon @ 2022-05-06 13:01 UTC (permalink / raw)
  To: Oliver Upton; +Cc: kvm, Marc Zyngier, Peter Shier, kvmarm, linux-arm-kernel

On Fri, Mar 11, 2022 at 05:57:12PM +0000, Oliver Upton wrote:
> This is a prototype for supporting KVM_CAP_ARM_SYSTEM_SUSPEND on
> kvmtool. The capability allows userspace to expose the SYSTEM_SUSPEND
> PSCI call to its guests.
> 
> Implement SYSTEM_SUSPEND using KVM_MP_STATE_SUSPENDED, which emulates
> the execution of a WFI instruction in the kernel. Resume the guest when
> a wakeup event is recognized and reset it to the requested entry address
> and context ID.
> 
> Patches 2-4 are small reworks to more easily shoehorn PSCI support into
> kvmtool.
> 
> Patch 5 adds some SMCCC handlers and makes use of them to implement PSCI
> SYSTEM_SUSPEND. For now, just check the bare-minimum, that all vCPUs
> besides the caller have stopped. There are also checks that can be made
> against the requested entry address, but they are at the discretion of
> the implementation.
> 
> Tested with 'echo mem > /sys/power/state' to see that the vCPU is in
> fact placed in a suspended state for the PSCI call. Hacked the switch
> statement to fall through to WAKEUP immediately after to verify the vCPU
> is set up correctly for resume.
> 
> It would be nice if kvmtool actually provided a device good for wakeups,
> since the RTC implementation has omitted any interrupt support.
> 
> kernel changes: http://lore.kernel.org/r/20220311174001.605719-1-oupton@google.com
> 
> Oliver Upton (5):
>   TESTONLY: Sync KVM headers with pending changes
>   Allow architectures to hook KVM_EXIT_SYSTEM_EVENT
>   ARM: Stash vcpu_init in the vCPU structure
>   ARM: Add a helper to re-init a vCPU
>   ARM: Implement PSCI SYSTEM_SUSPEND
> 
>  arm/aarch32/kvm-cpu.c                 | 72 ++++++++++++++++++++
>  arm/aarch64/kvm-cpu.c                 | 66 +++++++++++++++++++
>  arm/include/arm-common/kvm-cpu-arch.h | 23 ++++---
>  arm/kvm-cpu.c                         | 95 ++++++++++++++++++++++++++-
>  arm/kvm.c                             |  9 +++
>  include/kvm/kvm-cpu.h                 |  1 +
>  include/linux/kvm.h                   | 21 ++++++
>  kvm-cpu.c                             |  8 +++
>  8 files changed, 283 insertions(+), 12 deletions(-)

Looks like the kernel-side changes are queued now, so please can you resend
this series? I also think you can drop the AArch32 support, unless you see a
compelling reason for it?

Will
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC PATCH kvmtool 0/5] ARM: Implement PSCI SYSTEM_SUSPEND
@ 2022-05-06 13:01     ` Will Deacon
  0 siblings, 0 replies; 72+ messages in thread
From: Will Deacon @ 2022-05-06 13:01 UTC (permalink / raw)
  To: Oliver Upton
  Cc: kvmarm, kvm, Marc Zyngier, James Morse, Alexandru Elisei,
	Suzuki K Poulose, linux-arm-kernel, Peter Shier, Ricardo Koller,
	Reiji Watanabe, Julien Thierry

On Fri, Mar 11, 2022 at 05:57:12PM +0000, Oliver Upton wrote:
> This is a prototype for supporting KVM_CAP_ARM_SYSTEM_SUSPEND on
> kvmtool. The capability allows userspace to expose the SYSTEM_SUSPEND
> PSCI call to its guests.
> 
> Implement SYSTEM_SUSPEND using KVM_MP_STATE_SUSPENDED, which emulates
> the execution of a WFI instruction in the kernel. Resume the guest when
> a wakeup event is recognized and reset it to the requested entry address
> and context ID.
> 
> Patches 2-4 are small reworks to more easily shoehorn PSCI support into
> kvmtool.
> 
> Patch 5 adds some SMCCC handlers and makes use of them to implement PSCI
> SYSTEM_SUSPEND. For now, just check the bare-minimum, that all vCPUs
> besides the caller have stopped. There are also checks that can be made
> against the requested entry address, but they are at the discretion of
> the implementation.
> 
> Tested with 'echo mem > /sys/power/state' to see that the vCPU is in
> fact placed in a suspended state for the PSCI call. Hacked the switch
> statement to fall through to WAKEUP immediately after to verify the vCPU
> is set up correctly for resume.
> 
> It would be nice if kvmtool actually provided a device good for wakeups,
> since the RTC implementation has omitted any interrupt support.
> 
> kernel changes: http://lore.kernel.org/r/20220311174001.605719-1-oupton@google.com
> 
> Oliver Upton (5):
>   TESTONLY: Sync KVM headers with pending changes
>   Allow architectures to hook KVM_EXIT_SYSTEM_EVENT
>   ARM: Stash vcpu_init in the vCPU structure
>   ARM: Add a helper to re-init a vCPU
>   ARM: Implement PSCI SYSTEM_SUSPEND
> 
>  arm/aarch32/kvm-cpu.c                 | 72 ++++++++++++++++++++
>  arm/aarch64/kvm-cpu.c                 | 66 +++++++++++++++++++
>  arm/include/arm-common/kvm-cpu-arch.h | 23 ++++---
>  arm/kvm-cpu.c                         | 95 ++++++++++++++++++++++++++-
>  arm/kvm.c                             |  9 +++
>  include/kvm/kvm-cpu.h                 |  1 +
>  include/linux/kvm.h                   | 21 ++++++
>  kvm-cpu.c                             |  8 +++
>  8 files changed, 283 insertions(+), 12 deletions(-)

Looks like the kernel-side changes are queued now, so please can you resend
this series? I also think you can drop the AArch32 support, unless you see a
compelling reason for it?

Will

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC PATCH kvmtool 0/5] ARM: Implement PSCI SYSTEM_SUSPEND
  2022-05-06 13:01     ` Will Deacon
  (?)
@ 2022-05-06 19:18       ` Oliver Upton
  -1 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-05-06 19:18 UTC (permalink / raw)
  To: Will Deacon
  Cc: kvmarm, kvm, Marc Zyngier, James Morse, Alexandru Elisei,
	Suzuki K Poulose, linux-arm-kernel, Peter Shier, Ricardo Koller,
	Reiji Watanabe, Julien Thierry

Hi Will,

On Fri, May 6, 2022 at 6:01 AM Will Deacon <will@kernel.org> wrote:
>
> Looks like the kernel-side changes are queued now, so please can you resend
> this series? I also think you can drop the AArch32 support, unless you see a
> compelling reason for it?

You bet. I was going to wait for 5.19-rc1 just for the dust to settle
and get a stable number for the UAPI bits. I think the ARM changes
have some light conflicts with SEV work in Paolo's tree.

All for dropping AArch32, means less work for me :-P

--
Thanks,
Oliver

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC PATCH kvmtool 0/5] ARM: Implement PSCI SYSTEM_SUSPEND
@ 2022-05-06 19:18       ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-05-06 19:18 UTC (permalink / raw)
  To: Will Deacon; +Cc: kvm, Marc Zyngier, Peter Shier, kvmarm, linux-arm-kernel

Hi Will,

On Fri, May 6, 2022 at 6:01 AM Will Deacon <will@kernel.org> wrote:
>
> Looks like the kernel-side changes are queued now, so please can you resend
> this series? I also think you can drop the AArch32 support, unless you see a
> compelling reason for it?

You bet. I was going to wait for 5.19-rc1 just for the dust to settle
and get a stable number for the UAPI bits. I think the ARM changes
have some light conflicts with SEV work in Paolo's tree.

All for dropping AArch32, means less work for me :-P

--
Thanks,
Oliver
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [RFC PATCH kvmtool 0/5] ARM: Implement PSCI SYSTEM_SUSPEND
@ 2022-05-06 19:18       ` Oliver Upton
  0 siblings, 0 replies; 72+ messages in thread
From: Oliver Upton @ 2022-05-06 19:18 UTC (permalink / raw)
  To: Will Deacon
  Cc: kvmarm, kvm, Marc Zyngier, James Morse, Alexandru Elisei,
	Suzuki K Poulose, linux-arm-kernel, Peter Shier, Ricardo Koller,
	Reiji Watanabe, Julien Thierry

Hi Will,

On Fri, May 6, 2022 at 6:01 AM Will Deacon <will@kernel.org> wrote:
>
> Looks like the kernel-side changes are queued now, so please can you resend
> this series? I also think you can drop the AArch32 support, unless you see a
> compelling reason for it?

You bet. I was going to wait for 5.19-rc1 just for the dust to settle
and get a stable number for the UAPI bits. I think the ARM changes
have some light conflicts with SEV work in Paolo's tree.

All for dropping AArch32, means less work for me :-P

--
Thanks,
Oliver

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 72+ messages in thread

end of thread, other threads:[~2022-05-06 19:19 UTC | newest]

Thread overview: 72+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-11 17:39 [PATCH v4 00/15] KVM: arm64: PSCI SYSTEM_SUSPEND + SYSTEM_RESET2 bugfix Oliver Upton
2022-03-11 17:39 ` Oliver Upton
2022-03-11 17:39 ` [PATCH v4 01/15] KVM: arm64: Generalise VM features into a set of flags Oliver Upton
2022-03-11 17:39   ` Oliver Upton
2022-03-11 17:39 ` [PATCH v4 02/15] KVM: arm64: Generally disallow SMC64 for AArch32 guests Oliver Upton
2022-03-11 17:39   ` Oliver Upton
2022-03-11 17:39 ` [PATCH v4 03/15] KVM: arm64: Don't depend on fallthrough to hide SYSTEM_RESET2 Oliver Upton
2022-03-11 17:39   ` Oliver Upton
2022-03-11 17:39 ` [PATCH v4 04/15] KVM: arm64: Dedupe vCPU power off helpers Oliver Upton
2022-03-11 17:39   ` Oliver Upton
2022-03-11 17:39 ` [PATCH v4 05/15] KVM: arm64: Track vCPU power state using MP state values Oliver Upton
2022-03-11 17:39   ` Oliver Upton
2022-03-11 17:39 ` [PATCH v4 06/15] KVM: arm64: Rename the KVM_REQ_SLEEP handler Oliver Upton
2022-03-11 17:39   ` Oliver Upton
2022-03-11 17:39 ` [PATCH v4 07/15] KVM: Create helper for setting a system event exit Oliver Upton
2022-03-11 17:39   ` Oliver Upton
2022-03-19  7:28   ` Anup Patel
2022-03-19  7:28     ` Anup Patel
2022-03-22  6:52     ` Oliver Upton
2022-03-22  6:52       ` Oliver Upton
2022-03-11 17:39 ` [PATCH v4 08/15] KVM: arm64: Return a value from check_vcpu_requests() Oliver Upton
2022-03-11 17:39   ` Oliver Upton
2022-03-22  6:21   ` Reiji Watanabe
2022-03-22  6:21     ` Reiji Watanabe
2022-03-22  6:51     ` Oliver Upton
2022-03-22  6:51       ` Oliver Upton
2022-03-11 17:39 ` [PATCH v4 09/15] KVM: arm64: Add support for userspace to suspend a vCPU Oliver Upton
2022-03-11 17:39   ` Oliver Upton
2022-03-22  6:19   ` Reiji Watanabe
2022-03-22  6:19     ` Reiji Watanabe
2022-03-22  6:49     ` Oliver Upton
2022-03-22  6:49       ` Oliver Upton
2022-03-24  6:44       ` Reiji Watanabe
2022-03-24  6:44         ` Reiji Watanabe
2022-03-11 17:39 ` [PATCH v4 10/15] KVM: arm64: Implement PSCI SYSTEM_SUSPEND Oliver Upton
2022-03-11 17:39   ` Oliver Upton
2022-03-11 17:39 ` [PATCH v4 11/15] selftests: KVM: Rename psci_cpu_on_test to psci_test Oliver Upton
2022-03-11 17:39   ` Oliver Upton
2022-03-11 17:39 ` [PATCH v4 12/15] selftests: KVM: Create helper for making SMCCC calls Oliver Upton
2022-03-11 17:39   ` Oliver Upton
2022-03-11 17:39 ` [PATCH v4 13/15] selftests: KVM: Use KVM_SET_MP_STATE to power off vCPU in psci_test Oliver Upton
2022-03-11 17:39   ` Oliver Upton
2022-03-11 17:40 ` [PATCH v4 14/15] selftests: KVM: Refactor psci_test to make it amenable to new tests Oliver Upton
2022-03-11 17:40   ` Oliver Upton
2022-03-11 17:40 ` [PATCH v4 15/15] selftests: KVM: Test SYSTEM_SUSPEND PSCI call Oliver Upton
2022-03-11 17:40   ` Oliver Upton
2022-03-11 17:57 ` [RFC PATCH kvmtool 0/5] ARM: Implement PSCI SYSTEM_SUSPEND Oliver Upton
2022-03-11 17:57   ` Oliver Upton
2022-03-11 17:57   ` Oliver Upton
2022-03-11 17:57   ` [RFC PATCH kvmtool 1/5] TESTONLY: Sync KVM headers with pending changes Oliver Upton
2022-03-11 17:57     ` Oliver Upton
2022-03-11 17:57     ` Oliver Upton
2022-03-11 17:57   ` [RFC PATCH kvmtool 2/5] Allow architectures to hook KVM_EXIT_SYSTEM_EVENT Oliver Upton
2022-03-11 17:57     ` Oliver Upton
2022-03-11 17:57     ` Oliver Upton
2022-03-11 17:57   ` [RFC PATCH kvmtool 3/5] ARM: Stash vcpu_init in the vCPU structure Oliver Upton
2022-03-11 17:57     ` Oliver Upton
2022-03-11 17:57     ` Oliver Upton
2022-03-11 17:57   ` [RFC PATCH kvmtool 4/5] ARM: Add a helper to re-init a vCPU Oliver Upton
2022-03-11 17:57     ` Oliver Upton
2022-03-11 17:57     ` Oliver Upton
2022-03-11 17:57   ` [RFC PATCH kvmtool 5/5] ARM: Implement PSCI SYSTEM_SUSPEND Oliver Upton
2022-03-11 17:57     ` Oliver Upton
2022-03-11 17:57     ` Oliver Upton
2022-05-06 13:01   ` [RFC PATCH kvmtool 0/5] " Will Deacon
2022-05-06 13:01     ` Will Deacon
2022-05-06 13:01     ` Will Deacon
2022-05-06 19:18     ` Oliver Upton
2022-05-06 19:18       ` Oliver Upton
2022-05-06 19:18       ` Oliver Upton
2022-03-18 14:07 ` (subset) [PATCH v4 00/15] KVM: arm64: PSCI SYSTEM_SUSPEND + SYSTEM_RESET2 bugfix Marc Zyngier
2022-03-18 14:07   ` Marc Zyngier

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.