Skip to content

Commit 2c9d45b

Browse files
ionela-voinescuctmarinas
authored andcommitted
arm64: add support for the AMU extension v1
The activity monitors extension is an optional extension introduced by the ARMv8.4 CPU architecture. This implements basic support for version 1 of the activity monitors architecture, AMUv1. This support includes: - Extension detection on each CPU (boot, secondary, hotplugged) - Register interface for AMU aarch64 registers Signed-off-by: Ionela Voinescu <[email protected]> Reviewed-by: Valentin Schneider <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Marc Zyngier <[email protected]> Cc: Suzuki K Poulose <[email protected]> Cc: Will Deacon <[email protected]> Cc: Catalin Marinas <[email protected]> Signed-off-by: Catalin Marinas <[email protected]>
1 parent f8788d8 commit 2c9d45b

File tree

5 files changed

+138
-1
lines changed

5 files changed

+138
-1
lines changed

arch/arm64/Kconfig

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,6 +1517,33 @@ config ARM64_PTR_AUTH
15171517

15181518
endmenu
15191519

1520+
menu "ARMv8.4 architectural features"
1521+
1522+
config ARM64_AMU_EXTN
1523+
bool "Enable support for the Activity Monitors Unit CPU extension"
1524+
default y
1525+
help
1526+
The activity monitors extension is an optional extension introduced
1527+
by the ARMv8.4 CPU architecture. This enables support for version 1
1528+
of the activity monitors architecture, AMUv1.
1529+
1530+
To enable the use of this extension on CPUs that implement it, say Y.
1531+
1532+
Note that for architectural reasons, firmware _must_ implement AMU
1533+
support when running on CPUs that present the activity monitors
1534+
extension. The required support is present in:
1535+
* Version 1.5 and later of the ARM Trusted Firmware
1536+
1537+
For kernels that have this configuration enabled but boot with broken
1538+
firmware, you may need to say N here until the firmware is fixed.
1539+
Otherwise you may experience firmware panics or lockups when
1540+
accessing the counter registers. Even if you are not observing these
1541+
symptoms, the values returned by the register reads might not
1542+
correctly reflect reality. Most commonly, the value read will be 0,
1543+
indicating that the counter is not enabled.
1544+
1545+
endmenu
1546+
15201547
menu "ARMv8.5 architectural features"
15211548

15221549
config ARM64_E0PD

arch/arm64/include/asm/cpucaps.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@
5858
#define ARM64_WORKAROUND_SPECULATIVE_AT_NVHE 48
5959
#define ARM64_HAS_E0PD 49
6060
#define ARM64_HAS_RNG 50
61+
#define ARM64_HAS_AMU_EXTN 51
6162

62-
#define ARM64_NCAPS 51
63+
#define ARM64_NCAPS 52
6364

6465
#endif /* __ASM_CPUCAPS_H */

arch/arm64/include/asm/cpufeature.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,11 @@ static inline bool cpu_has_hw_af(void)
678678
ID_AA64MMFR1_HADBS_SHIFT);
679679
}
680680

681+
#ifdef CONFIG_ARM64_AMU_EXTN
682+
/* Check whether the cpu supports the Activity Monitors Unit (AMU) */
683+
extern bool cpu_has_amu_feat(int cpu);
684+
#endif
685+
681686
#endif /* __ASSEMBLY__ */
682687

683688
#endif

arch/arm64/include/asm/sysreg.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,42 @@
386386
#define SYS_TPIDR_EL0 sys_reg(3, 3, 13, 0, 2)
387387
#define SYS_TPIDRRO_EL0 sys_reg(3, 3, 13, 0, 3)
388388

389+
/* Definitions for system register interface to AMU for ARMv8.4 onwards */
390+
#define SYS_AM_EL0(crm, op2) sys_reg(3, 3, 13, (crm), (op2))
391+
#define SYS_AMCR_EL0 SYS_AM_EL0(2, 0)
392+
#define SYS_AMCFGR_EL0 SYS_AM_EL0(2, 1)
393+
#define SYS_AMCGCR_EL0 SYS_AM_EL0(2, 2)
394+
#define SYS_AMUSERENR_EL0 SYS_AM_EL0(2, 3)
395+
#define SYS_AMCNTENCLR0_EL0 SYS_AM_EL0(2, 4)
396+
#define SYS_AMCNTENSET0_EL0 SYS_AM_EL0(2, 5)
397+
#define SYS_AMCNTENCLR1_EL0 SYS_AM_EL0(3, 0)
398+
#define SYS_AMCNTENSET1_EL0 SYS_AM_EL0(3, 1)
399+
400+
/*
401+
* Group 0 of activity monitors (architected):
402+
* op0 op1 CRn CRm op2
403+
* Counter: 11 011 1101 010:n<3> n<2:0>
404+
* Type: 11 011 1101 011:n<3> n<2:0>
405+
* n: 0-15
406+
*
407+
* Group 1 of activity monitors (auxiliary):
408+
* op0 op1 CRn CRm op2
409+
* Counter: 11 011 1101 110:n<3> n<2:0>
410+
* Type: 11 011 1101 111:n<3> n<2:0>
411+
* n: 0-15
412+
*/
413+
414+
#define SYS_AMEVCNTR0_EL0(n) SYS_AM_EL0(4 + ((n) >> 3), (n) & 7)
415+
#define SYS_AMEVTYPE0_EL0(n) SYS_AM_EL0(6 + ((n) >> 3), (n) & 7)
416+
#define SYS_AMEVCNTR1_EL0(n) SYS_AM_EL0(12 + ((n) >> 3), (n) & 7)
417+
#define SYS_AMEVTYPE1_EL0(n) SYS_AM_EL0(14 + ((n) >> 3), (n) & 7)
418+
419+
/* AMU v1: Fixed (architecturally defined) activity monitors */
420+
#define SYS_AMEVCNTR0_CORE_EL0 SYS_AMEVCNTR0_EL0(0)
421+
#define SYS_AMEVCNTR0_CONST_EL0 SYS_AMEVCNTR0_EL0(1)
422+
#define SYS_AMEVCNTR0_INST_RET_EL0 SYS_AMEVCNTR0_EL0(2)
423+
#define SYS_AMEVCNTR0_MEM_STALL SYS_AMEVCNTR0_EL0(3)
424+
389425
#define SYS_CNTFRQ_EL0 sys_reg(3, 3, 14, 0, 0)
390426

391427
#define SYS_CNTP_TVAL_EL0 sys_reg(3, 3, 14, 2, 0)
@@ -598,6 +634,7 @@
598634
#define ID_AA64PFR0_CSV3_SHIFT 60
599635
#define ID_AA64PFR0_CSV2_SHIFT 56
600636
#define ID_AA64PFR0_DIT_SHIFT 48
637+
#define ID_AA64PFR0_AMU_SHIFT 44
601638
#define ID_AA64PFR0_SVE_SHIFT 32
602639
#define ID_AA64PFR0_RAS_SHIFT 28
603640
#define ID_AA64PFR0_GIC_SHIFT 24
@@ -608,6 +645,7 @@
608645
#define ID_AA64PFR0_EL1_SHIFT 4
609646
#define ID_AA64PFR0_EL0_SHIFT 0
610647

648+
#define ID_AA64PFR0_AMU 0x1
611649
#define ID_AA64PFR0_SVE 0x1
612650
#define ID_AA64PFR0_RAS_V1 0x1
613651
#define ID_AA64PFR0_FP_NI 0xf

arch/arm64/kernel/cpufeature.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
163163
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV3_SHIFT, 4, 0),
164164
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV2_SHIFT, 4, 0),
165165
ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_DIT_SHIFT, 4, 0),
166+
ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_AMU_SHIFT, 4, 0),
166167
ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SVE),
167168
FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_SVE_SHIFT, 4, 0),
168169
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_RAS_SHIFT, 4, 0),
@@ -1222,6 +1223,53 @@ static bool has_hw_dbm(const struct arm64_cpu_capabilities *cap,
12221223

12231224
#endif
12241225

1226+
#ifdef CONFIG_ARM64_AMU_EXTN
1227+
1228+
/*
1229+
* The "amu_cpus" cpumask only signals that the CPU implementation for the
1230+
* flagged CPUs supports the Activity Monitors Unit (AMU) but does not provide
1231+
* information regarding all the events that it supports. When a CPU bit is
1232+
* set in the cpumask, the user of this feature can only rely on the presence
1233+
* of the 4 fixed counters for that CPU. But this does not guarantee that the
1234+
* counters are enabled or access to these counters is enabled by code
1235+
* executed at higher exception levels (firmware).
1236+
*/
1237+
static struct cpumask amu_cpus __read_mostly;
1238+
1239+
bool cpu_has_amu_feat(int cpu)
1240+
{
1241+
return cpumask_test_cpu(cpu, &amu_cpus);
1242+
}
1243+
1244+
static void cpu_amu_enable(struct arm64_cpu_capabilities const *cap)
1245+
{
1246+
if (has_cpuid_feature(cap, SCOPE_LOCAL_CPU)) {
1247+
pr_info("detected CPU%d: Activity Monitors Unit (AMU)\n",
1248+
smp_processor_id());
1249+
cpumask_set_cpu(smp_processor_id(), &amu_cpus);
1250+
}
1251+
}
1252+
1253+
static bool has_amu(const struct arm64_cpu_capabilities *cap,
1254+
int __unused)
1255+
{
1256+
/*
1257+
* The AMU extension is a non-conflicting feature: the kernel can
1258+
* safely run a mix of CPUs with and without support for the
1259+
* activity monitors extension. Therefore, unconditionally enable
1260+
* the capability to allow any late CPU to use the feature.
1261+
*
1262+
* With this feature unconditionally enabled, the cpu_enable
1263+
* function will be called for all CPUs that match the criteria,
1264+
* including secondary and hotplugged, marking this feature as
1265+
* present on that respective CPU. The enable function will also
1266+
* print a detection message.
1267+
*/
1268+
1269+
return true;
1270+
}
1271+
#endif
1272+
12251273
#ifdef CONFIG_ARM64_VHE
12261274
static bool runs_at_el2(const struct arm64_cpu_capabilities *entry, int __unused)
12271275
{
@@ -1499,6 +1547,24 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
14991547
.cpu_enable = cpu_clear_disr,
15001548
},
15011549
#endif /* CONFIG_ARM64_RAS_EXTN */
1550+
#ifdef CONFIG_ARM64_AMU_EXTN
1551+
{
1552+
/*
1553+
* The feature is enabled by default if CONFIG_ARM64_AMU_EXTN=y.
1554+
* Therefore, don't provide .desc as we don't want the detection
1555+
* message to be shown until at least one CPU is detected to
1556+
* support the feature.
1557+
*/
1558+
.capability = ARM64_HAS_AMU_EXTN,
1559+
.type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
1560+
.matches = has_amu,
1561+
.sys_reg = SYS_ID_AA64PFR0_EL1,
1562+
.sign = FTR_UNSIGNED,
1563+
.field_pos = ID_AA64PFR0_AMU_SHIFT,
1564+
.min_field_value = ID_AA64PFR0_AMU,
1565+
.cpu_enable = cpu_amu_enable,
1566+
},
1567+
#endif /* CONFIG_ARM64_AMU_EXTN */
15021568
{
15031569
.desc = "Data cache clean to the PoU not required for I/D coherence",
15041570
.capability = ARM64_HAS_CACHE_IDC,

0 commit comments

Comments
 (0)