Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8d1a0ae7 authored by Martin Fuzzey's avatar Martin Fuzzey Committed by Will Deacon
Browse files

ARM: perf: Set ARMv7 SDER SUNIDEN bit



ARMv7 counters other than the CPU cycle counter only work if the Secure
Debug Enable Register (SDER) SUNIDEN bit is set.

Since access to the SDER is only possible in secure state, it will
only be done if the device tree property "secure-reg-access" is set.

Without this:

 Performance counter stats for 'sleep 1':

          14606094 cycles                    #    0.000 GHz
                 0 instructions              #    0.00  insns per cycle

After applying:

 Performance counter stats for 'sleep 1':

           5843809 cycles
           2566484 instructions              #    0.44  insns per cycle

       1.020144000 seconds time elapsed

Some platforms (eg i.MX53) may also need additional platform specific
setup.

Acked-by: default avatarRob Herring <robh@kernel.org>
Signed-off-by: default avatarMartin Fuzzey <mfuzzey@parkeon.com>
Signed-off-by: default avatarPooya Keshavarzi <Pooya.Keshavarzi@de.bosch.com>
Signed-off-by: default avatarGeorge G. Davis <george_davis@mentor.com>
[will: add warning if property is found on arm64]
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent 92e963f5
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -46,6 +46,16 @@ Optional properties:
- qcom,no-pc-write : Indicates that this PMU doesn't support the 0xc and 0xd
                     events.

- secure-reg-access : Indicates that the ARMv7 Secure Debug Enable Register
		      (SDER) is accessible. This will cause the driver to do
		      any setup required that is only possible in ARMv7 secure
		      state. If not present the ARMv7 SDER will not be touched,
		      which means the PMU may fail to operate unless external
		      code (bootloader or security monitor) has performed the
		      appropriate initialisation. Note that this property is
		      not valid for non-ARMv7 CPUs or ARMv7 CPUs booting Linux
		      in Non-secure state.

Example:

pmu {
+12 −1
Original line number Diff line number Diff line
@@ -712,6 +712,11 @@ static const struct attribute_group *armv7_pmuv2_attr_groups[] = {
#define	ARMV7_EXCLUDE_USER	(1 << 30)
#define	ARMV7_INCLUDE_HYP	(1 << 27)

/*
 * Secure debug enable reg
 */
#define ARMV7_SDER_SUNIDEN	BIT(1) /* Permit non-invasive debug */

static inline u32 armv7_pmnc_read(void)
{
	u32 val;
@@ -1094,7 +1099,13 @@ static int armv7pmu_set_event_filter(struct hw_perf_event *event,
static void armv7pmu_reset(void *info)
{
	struct arm_pmu *cpu_pmu = (struct arm_pmu *)info;
	u32 idx, nb_cnt = cpu_pmu->num_events;
	u32 idx, nb_cnt = cpu_pmu->num_events, val;

	if (cpu_pmu->secure_access) {
		asm volatile("mrc p15, 0, %0, c1, c1, 1" : "=r" (val));
		val |= ARMV7_SDER_SUNIDEN;
		asm volatile("mcr p15, 0, %0, c1, c1, 1" : : "r" (val));
	}

	/* The counter and interrupt enable registers are unknown at reset. */
	for (idx = ARMV7_IDX_CYCLE_COUNTER; idx < nb_cnt; ++idx) {
+9 −0
Original line number Diff line number Diff line
@@ -889,6 +889,15 @@ int arm_pmu_device_probe(struct platform_device *pdev,
	if (node && (of_id = of_match_node(of_table, pdev->dev.of_node))) {
		init_fn = of_id->data;

		pmu->secure_access = of_property_read_bool(pdev->dev.of_node,
							   "secure-reg-access");

		/* arm64 systems boot only as non-secure */
		if (IS_ENABLED(CONFIG_ARM64) && pmu->secure_access) {
			pr_warn("ignoring \"secure-reg-access\" property for arm64\n");
			pmu->secure_access = false;
		}

		ret = of_pmu_irq_cfg(pmu);
		if (!ret)
			ret = init_fn(pmu);
+1 −0
Original line number Diff line number Diff line
@@ -104,6 +104,7 @@ struct arm_pmu {
	atomic_t	active_events;
	struct mutex	reserve_mutex;
	u64		max_period;
	bool		secure_access; /* 32-bit ARM only */
	struct platform_device	*plat_device;
	struct pmu_hw_events	__percpu *hw_events;
	struct notifier_block	hotplug_nb;