Backport patches from upstream to fix the issue I8K8XV of PMU. Signed-off-by: Yuan Zhang <zhangyuan162@huawei.com>
81 lines
2.9 KiB
Diff
81 lines
2.9 KiB
Diff
From a207eaeac98757a86cce704be6c4e097439503c5 Mon Sep 17 00:00:00 2001
|
|
From: Andrew Murray <andrew.murray@arm.com>
|
|
Date: Tue, 28 Nov 2023 15:46:32 +0800
|
|
Subject: [PATCH 1/2] arm64: cpufeature: Extract capped perfmon fields
|
|
|
|
mainline inclusion
|
|
from mainline-v5.7-rc1
|
|
commit 8e35aa642ee4dab01b16cc4b2df59d1936f3b3c2
|
|
category: bugfix
|
|
bugzilla: https://gitee.com/openeuler/kernel/issues/I8K8XV
|
|
CVE: NA
|
|
|
|
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8e35aa642ee4dab01b16cc4b2df59d1936f3b3c2
|
|
|
|
-----------------------------------
|
|
|
|
commit 8e35aa642ee4dab01b16cc4b2df59d1936f3b3c2 upstream.
|
|
|
|
When emulating ID registers there is often a need to cap the version
|
|
bits of a feature such that the guest will not use features that the
|
|
host is not aware of. For example, when KVM mediates access to the PMU
|
|
by emulating register accesses.
|
|
|
|
Let's add a helper that extracts a performance monitors ID field and
|
|
caps the version to a given value.
|
|
|
|
Fields that identify the version of the Performance Monitors Extension
|
|
do not follow the standard ID scheme, and instead follow the scheme
|
|
described in ARM DDI 0487E.a page D13-2825 "Alternative ID scheme used
|
|
for the Performance Monitors Extension version". The value 0xF means an
|
|
IMPLEMENTATION DEFINED PMU is present, and values 0x0-OxE can be treated
|
|
the same as an unsigned field with 0x0 meaning no PMU is present.
|
|
|
|
Signed-off-by: Andrew Murray <andrew.murray@arm.com>
|
|
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
|
|
[Mark: rework to handle perfmon fields]
|
|
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
|
|
Signed-off-by: Will Deacon <will@kernel.org>
|
|
Signed-off-by: zhangyuan <zhangyuan162@huawei.com>
|
|
---
|
|
arch/arm64/include/asm/cpufeature.h | 23 +++++++++++++++++++++++
|
|
1 file changed, 23 insertions(+)
|
|
|
|
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
|
|
index eef5a9c9b823..e2ba573644d5 100644
|
|
--- a/arch/arm64/include/asm/cpufeature.h
|
|
+++ b/arch/arm64/include/asm/cpufeature.h
|
|
@@ -449,6 +449,29 @@ cpuid_feature_extract_unsigned_field(u64 features, int field)
|
|
return cpuid_feature_extract_unsigned_field_width(features, field, 4);
|
|
}
|
|
|
|
+/*
|
|
+ * Fields that identify the version of the Performance Monitors Extension do
|
|
+ * not follow the standard ID scheme. See ARM DDI 0487E.a page D13-2825,
|
|
+ * "Alternative ID scheme used for the Performance Monitors Extension version".
|
|
+ */
|
|
+static inline u64 __attribute_const__
|
|
+cpuid_feature_cap_perfmon_field(u64 features, int field, u64 cap)
|
|
+{
|
|
+ u64 val = cpuid_feature_extract_unsigned_field(features, field);
|
|
+ u64 mask = GENMASK_ULL(field + 3, field);
|
|
+
|
|
+ /* Treat IMPLEMENTATION DEFINED functionality as unimplemented */
|
|
+ if (val == 0xf)
|
|
+ val = 0;
|
|
+
|
|
+ if (val > cap) {
|
|
+ features &= ~mask;
|
|
+ features |= (cap << field) & mask;
|
|
+ }
|
|
+
|
|
+ return features;
|
|
+}
|
|
+
|
|
static inline u64 arm64_ftr_mask(const struct arm64_ftr_bits *ftrp)
|
|
{
|
|
return (u64)GENMASK(ftrp->shift + ftrp->width - 1, ftrp->shift);
|
|
--
|
|
2.33.0
|
|
|