All of lore.kernel.org
 help / color / mirror / Atom feed
From: Reiji Watanabe <reijiw@google.com>
To: Marc Zyngier <maz@kernel.org>, kvmarm@lists.linux.dev
Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	James Morse <james.morse@arm.com>,
	Alexandru Elisei <alexandru.elisei@arm.com>,
	Zenghui Yu <yuzenghui@huawei.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Ricardo Koller <ricarkol@google.com>,
	Oliver Upton <oliver.upton@linux.dev>,
	Jing Zhang <jingzhangos@google.com>,
	Raghavendra Rao Anata <rananta@google.com>,
	Shaoqin Huang <shahuang@redhat.com>,
	Reiji Watanabe <reijiw@google.com>
Subject: [PATCH v3 02/14] KVM: arm64: PMU: Set the default PMU for the guest on vCPU reset
Date: Thu,  2 Feb 2023 20:20:44 -0800	[thread overview]
Message-ID: <20230203042056.1794649-1-reijiw@google.com> (raw)

For vCPUs with PMU configured, KVM uses the sanitized value
(returned from read_sanitised_ftr_reg()) of ID_AA64DFR0_EL1.PMUVer
as the default value and the limit value of that field.
The sanitized value could be inappropriate for these on some
heterogeneous PMU systems, as only one of PMUs on the system
can be associated with the guest.  Also, since the PMUVer
is defined as FTR_EXACT with safe_val == 0 (in cpufeature.c),
it will be zero when any PEs on the system have a different
PMUVer value than the other PEs (i.e. the guest with PMU
configured might see PMUVer == 0).

As a guest with PMU configured is associated with one of
PMUs on the system, the default and the limit PMUVer value for
the guest should be set based on that PMU.  Since the PMU
won't be associated with the guest until some vcpu device
attribute for PMU is set, KVM doesn't have that information
until then though.

Set the default PMU for the guest on the first vCPU reset.
The following patches will use the PMUVer of the PMU as the
default value of the ID_AA64DFR0_EL1.PMUVer for vCPUs with
PMU configured.

Signed-off-by: Reiji Watanabe <reijiw@google.com>
---
 arch/arm64/kvm/pmu-emul.c | 14 +-------------
 arch/arm64/kvm/reset.c    | 21 ++++++++++++++-------
 include/kvm/arm_pmu.h     |  6 ++++++
 3 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index f2a89f414297..c98020ca427e 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -867,7 +867,7 @@ static bool pmu_irq_is_valid(struct kvm *kvm, int irq)
 	return true;
 }
 
-static int kvm_arm_set_vm_pmu(struct kvm *kvm, struct arm_pmu *arm_pmu)
+int kvm_arm_set_vm_pmu(struct kvm *kvm, struct arm_pmu *arm_pmu)
 {
 	lockdep_assert_held(&kvm->lock);
 
@@ -923,18 +923,6 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 	if (vcpu->arch.pmu.created)
 		return -EBUSY;
 
-	mutex_lock(&kvm->lock);
-	if (!kvm->arch.arm_pmu) {
-		/* No PMU set, get the default one */
-		int ret = kvm_arm_set_vm_pmu(kvm, NULL);
-
-		if (ret) {
-			mutex_unlock(&kvm->lock);
-			return ret;
-		}
-	}
-	mutex_unlock(&kvm->lock);
-
 	switch (attr->attr) {
 	case KVM_ARM_VCPU_PMU_V3_IRQ: {
 		int __user *uaddr = (int __user *)(long)attr->addr;
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index e0267f672b8a..5d1e1acfe6ce 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -248,18 +248,30 @@ static int kvm_set_vm_width(struct kvm_vcpu *vcpu)
  */
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 {
+	struct kvm *kvm = vcpu->kvm;
 	struct vcpu_reset_state reset_state;
 	int ret;
 	bool loaded;
 	u32 pstate;
 
-	mutex_lock(&vcpu->kvm->lock);
+	mutex_lock(&kvm->lock);
 	ret = kvm_set_vm_width(vcpu);
 	if (!ret) {
 		reset_state = vcpu->arch.reset_state;
 		WRITE_ONCE(vcpu->arch.reset_state.reset, false);
+
+		/*
+		 * When the vCPU has a PMU, but no PMU is set for the guest
+		 * yet, set the default one.
+		 */
+		if (kvm_vcpu_has_pmu(vcpu) && unlikely(!kvm->arch.arm_pmu)) {
+			if (kvm_arm_support_pmu_v3())
+				ret = kvm_arm_set_vm_pmu(kvm, NULL);
+			else
+				ret = -EINVAL;
+		}
 	}
-	mutex_unlock(&vcpu->kvm->lock);
+	mutex_unlock(&kvm->lock);
 
 	if (ret)
 		return ret;
@@ -297,11 +309,6 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 		} else {
 			pstate = VCPU_RESET_PSTATE_EL1;
 		}
-
-		if (kvm_vcpu_has_pmu(vcpu) && !kvm_arm_support_pmu_v3()) {
-			ret = -EINVAL;
-			goto out;
-		}
 		break;
 	}
 
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
index 628775334d5e..7b5c5c8c634b 100644
--- a/include/kvm/arm_pmu.h
+++ b/include/kvm/arm_pmu.h
@@ -96,6 +96,7 @@ void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu);
 	(vcpu->kvm->arch.dfr0_pmuver.imp >= ID_AA64DFR0_EL1_PMUVer_V3P5)
 
 u8 kvm_arm_pmu_get_pmuver_limit(void);
+int kvm_arm_set_vm_pmu(struct kvm *kvm, struct arm_pmu *arm_pmu);
 
 #else
 struct kvm_pmu {
@@ -168,6 +169,11 @@ static inline u8 kvm_arm_pmu_get_pmuver_limit(void)
 	return 0;
 }
 
+static inline int kvm_arm_set_vm_pmu(struct kvm *kvm, struct arm_pmu *arm_pmu)
+{
+	return 0;
+}
+
 #endif
 
 #endif
-- 
2.39.1.519.gcb327c4b5f-goog


WARNING: multiple messages have this Message-ID (diff)
From: Reiji Watanabe <reijiw@google.com>
To: Marc Zyngier <maz@kernel.org>, kvmarm@lists.linux.dev
Cc: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	 James Morse <james.morse@arm.com>,
	Alexandru Elisei <alexandru.elisei@arm.com>,
	 Zenghui Yu <yuzenghui@huawei.com>,
	Suzuki K Poulose <suzuki.poulose@arm.com>,
	 Paolo Bonzini <pbonzini@redhat.com>,
	Ricardo Koller <ricarkol@google.com>,
	 Oliver Upton <oliver.upton@linux.dev>,
	Jing Zhang <jingzhangos@google.com>,
	 Raghavendra Rao Anata <rananta@google.com>,
	Shaoqin Huang <shahuang@redhat.com>,
	 Reiji Watanabe <reijiw@google.com>
Subject: [PATCH v3 02/14] KVM: arm64: PMU: Set the default PMU for the guest on vCPU reset
Date: Thu,  2 Feb 2023 20:20:44 -0800	[thread overview]
Message-ID: <20230203042056.1794649-1-reijiw@google.com> (raw)

For vCPUs with PMU configured, KVM uses the sanitized value
(returned from read_sanitised_ftr_reg()) of ID_AA64DFR0_EL1.PMUVer
as the default value and the limit value of that field.
The sanitized value could be inappropriate for these on some
heterogeneous PMU systems, as only one of PMUs on the system
can be associated with the guest.  Also, since the PMUVer
is defined as FTR_EXACT with safe_val == 0 (in cpufeature.c),
it will be zero when any PEs on the system have a different
PMUVer value than the other PEs (i.e. the guest with PMU
configured might see PMUVer == 0).

As a guest with PMU configured is associated with one of
PMUs on the system, the default and the limit PMUVer value for
the guest should be set based on that PMU.  Since the PMU
won't be associated with the guest until some vcpu device
attribute for PMU is set, KVM doesn't have that information
until then though.

Set the default PMU for the guest on the first vCPU reset.
The following patches will use the PMUVer of the PMU as the
default value of the ID_AA64DFR0_EL1.PMUVer for vCPUs with
PMU configured.

Signed-off-by: Reiji Watanabe <reijiw@google.com>
---
 arch/arm64/kvm/pmu-emul.c | 14 +-------------
 arch/arm64/kvm/reset.c    | 21 ++++++++++++++-------
 include/kvm/arm_pmu.h     |  6 ++++++
 3 files changed, 21 insertions(+), 20 deletions(-)

diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index f2a89f414297..c98020ca427e 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -867,7 +867,7 @@ static bool pmu_irq_is_valid(struct kvm *kvm, int irq)
 	return true;
 }
 
-static int kvm_arm_set_vm_pmu(struct kvm *kvm, struct arm_pmu *arm_pmu)
+int kvm_arm_set_vm_pmu(struct kvm *kvm, struct arm_pmu *arm_pmu)
 {
 	lockdep_assert_held(&kvm->lock);
 
@@ -923,18 +923,6 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
 	if (vcpu->arch.pmu.created)
 		return -EBUSY;
 
-	mutex_lock(&kvm->lock);
-	if (!kvm->arch.arm_pmu) {
-		/* No PMU set, get the default one */
-		int ret = kvm_arm_set_vm_pmu(kvm, NULL);
-
-		if (ret) {
-			mutex_unlock(&kvm->lock);
-			return ret;
-		}
-	}
-	mutex_unlock(&kvm->lock);
-
 	switch (attr->attr) {
 	case KVM_ARM_VCPU_PMU_V3_IRQ: {
 		int __user *uaddr = (int __user *)(long)attr->addr;
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index e0267f672b8a..5d1e1acfe6ce 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -248,18 +248,30 @@ static int kvm_set_vm_width(struct kvm_vcpu *vcpu)
  */
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 {
+	struct kvm *kvm = vcpu->kvm;
 	struct vcpu_reset_state reset_state;
 	int ret;
 	bool loaded;
 	u32 pstate;
 
-	mutex_lock(&vcpu->kvm->lock);
+	mutex_lock(&kvm->lock);
 	ret = kvm_set_vm_width(vcpu);
 	if (!ret) {
 		reset_state = vcpu->arch.reset_state;
 		WRITE_ONCE(vcpu->arch.reset_state.reset, false);
+
+		/*
+		 * When the vCPU has a PMU, but no PMU is set for the guest
+		 * yet, set the default one.
+		 */
+		if (kvm_vcpu_has_pmu(vcpu) && unlikely(!kvm->arch.arm_pmu)) {
+			if (kvm_arm_support_pmu_v3())
+				ret = kvm_arm_set_vm_pmu(kvm, NULL);
+			else
+				ret = -EINVAL;
+		}
 	}
-	mutex_unlock(&vcpu->kvm->lock);
+	mutex_unlock(&kvm->lock);
 
 	if (ret)
 		return ret;
@@ -297,11 +309,6 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 		} else {
 			pstate = VCPU_RESET_PSTATE_EL1;
 		}
-
-		if (kvm_vcpu_has_pmu(vcpu) && !kvm_arm_support_pmu_v3()) {
-			ret = -EINVAL;
-			goto out;
-		}
 		break;
 	}
 
diff --git a/include/kvm/arm_pmu.h b/include/kvm/arm_pmu.h
index 628775334d5e..7b5c5c8c634b 100644
--- a/include/kvm/arm_pmu.h
+++ b/include/kvm/arm_pmu.h
@@ -96,6 +96,7 @@ void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu);
 	(vcpu->kvm->arch.dfr0_pmuver.imp >= ID_AA64DFR0_EL1_PMUVer_V3P5)
 
 u8 kvm_arm_pmu_get_pmuver_limit(void);
+int kvm_arm_set_vm_pmu(struct kvm *kvm, struct arm_pmu *arm_pmu);
 
 #else
 struct kvm_pmu {
@@ -168,6 +169,11 @@ static inline u8 kvm_arm_pmu_get_pmuver_limit(void)
 	return 0;
 }
 
+static inline int kvm_arm_set_vm_pmu(struct kvm *kvm, struct arm_pmu *arm_pmu)
+{
+	return 0;
+}
+
 #endif
 
 #endif
-- 
2.39.1.519.gcb327c4b5f-goog


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

             reply	other threads:[~2023-02-03  4:22 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-03  4:20 Reiji Watanabe [this message]
2023-02-03  4:20 ` [PATCH v3 02/14] KVM: arm64: PMU: Set the default PMU for the guest on vCPU reset Reiji Watanabe
2023-02-03  4:20 ` [PATCH v3 03/14] KVM: arm64: PMU: Don't use the sanitized value for PMUVer Reiji Watanabe
2023-02-03  4:20   ` Reiji Watanabe
2023-02-03  4:20 ` [PATCH v3 04/14] KVM: arm64: PMU: Don't use the PMUVer of the PMU set for the guest Reiji Watanabe
2023-02-03  4:20   ` Reiji Watanabe
2023-02-03  4:20 ` [PATCH v3 05/14] KVM: arm64: PMU: Clear PM{C,I}NTEN{SET,CLR} and PMOVS{SET,CLR} on vCPU reset Reiji Watanabe
2023-02-03  4:20   ` Reiji Watanabe
2023-02-03  4:20 ` [PATCH v3 06/14] KVM: arm64: PMU: Don't define the sysreg reset() for PM{USERENR,CCFILTR}_EL0 Reiji Watanabe
2023-02-03  4:20   ` Reiji Watanabe
2023-02-03  4:20 ` [PATCH v3 07/14] KVM: arm64: PMU: Simplify extracting PMCR_EL0.N Reiji Watanabe
2023-02-03  4:20   ` Reiji Watanabe
2023-02-03  4:20 ` [PATCH v3 08/14] KVM: arm64: PMU: Add a helper to read a vCPU's PMCR_EL0 Reiji Watanabe
2023-02-03  4:20   ` Reiji Watanabe
2023-02-03  4:20 ` [PATCH v3 09/14] KVM: arm64: PMU: Set PMCR_EL0.N for vCPU based on the associated PMU Reiji Watanabe
2023-02-03  4:20   ` Reiji Watanabe
2023-02-03  4:20 ` [PATCH v3 10/14] KVM: arm64: PMU: Allow userspace to limit PMCR_EL0.N for the guest Reiji Watanabe
2023-02-03  4:20   ` Reiji Watanabe
2023-02-03  4:20 ` [PATCH v3 11/14] tools: arm64: Import perf_event.h Reiji Watanabe
2023-02-03  4:20   ` Reiji Watanabe
2023-02-03  4:20 ` [PATCH v3 12/14] KVM: selftests: aarch64: Introduce vpmu_counter_access test Reiji Watanabe
2023-02-03  4:20   ` Reiji Watanabe
2023-02-03  4:20 ` [PATCH v3 13/14] KVM: selftests: aarch64: vPMU register test for implemented counters Reiji Watanabe
2023-02-03  4:20   ` Reiji Watanabe
2023-02-03  4:20 ` [PATCH v3 14/14] KVM: selftests: aarch64: vPMU register test for unimplemented counters Reiji Watanabe
2023-02-03  4:20   ` Reiji Watanabe

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230203042056.1794649-1-reijiw@google.com \
    --to=reijiw@google.com \
    --cc=alexandru.elisei@arm.com \
    --cc=james.morse@arm.com \
    --cc=jingzhangos@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=kvmarm@lists.linux.dev \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=maz@kernel.org \
    --cc=oliver.upton@linux.dev \
    --cc=pbonzini@redhat.com \
    --cc=rananta@google.com \
    --cc=ricarkol@google.com \
    --cc=shahuang@redhat.com \
    --cc=suzuki.poulose@arm.com \
    --cc=yuzenghui@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is 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.