feat(mpmm): add support for MPMM

MPMM - the Maximum Power Mitigation Mechanism - is an optional
microarchitectural feature present on some Armv9-A cores, introduced
with the Cortex-X2, Cortex-A710 and Cortex-A510 cores.

MPMM allows the SoC firmware to detect and limit high activity events
to assist in SoC processor power domain dynamic power budgeting and
limit the triggering of whole-rail (i.e. clock chopping) responses to
overcurrent conditions.

This feature is enabled via the `ENABLE_MPMM` build option.
Configuration can be done via FCONF by enabling `ENABLE_MPMM_FCONF`, or
by via the plaform-implemented `plat_mpmm_topology` function.

Change-Id: I77da82808ad4744ece8263f0bf215c5a091c3167
Signed-off-by: Chris Kay <chris.kay@arm.com>
This commit is contained in:
Chris Kay 2021-05-05 13:38:30 +01:00
parent 742ca2307f
commit 68120783d6
20 changed files with 419 additions and 17 deletions

View File

@ -1015,6 +1015,8 @@ $(eval $(call assert_booleans,\
ENABLE_SYS_REG_TRACE_FOR_NS \
ENABLE_TRF_FOR_NS \
ENABLE_FEAT_HCX \
ENABLE_MPMM \
ENABLE_MPMM_FCONF \
)))
$(eval $(call assert_numerics,\
@ -1123,6 +1125,8 @@ $(eval $(call add_defines,\
ENABLE_SYS_REG_TRACE_FOR_NS \
ENABLE_TRF_FOR_NS \
ENABLE_FEAT_HCX \
ENABLE_MPMM \
ENABLE_MPMM_FCONF \
)))
ifeq (${SANITIZE_UB},trap)

View File

@ -23,6 +23,7 @@ ifeq (${SPM_MM},1)
endif
include lib/extensions/amu/amu.mk
include lib/mpmm/mpmm.mk
include lib/psci/psci_lib.mk
BL31_SOURCES += bl31/bl31_main.c \
@ -82,6 +83,10 @@ ifeq (${ENABLE_AMU},1)
BL31_SOURCES += ${AMU_SOURCES}
endif
ifeq (${ENABLE_MPMM},1)
BL31_SOURCES += ${MPMM_SOURCES}
endif
ifeq (${ENABLE_SVE_FOR_NS},1)
BL31_SOURCES += lib/extensions/sve/sve.c
endif

View File

@ -10,6 +10,8 @@ When the ``ENABLE_AMU=1`` build option is provided, Trusted Firmware-A sets up
the |AMU| prior to its exit from EL3, and will save and restore architected
|AMU| counters as necessary upon suspend and resume.
.. _Activity Monitor Auxiliary Counters:
Auxiliary counters
------------------

View File

@ -146,3 +146,4 @@ Properties binding information
fconf_properties
amu-bindings
mpmm-bindings

View File

@ -0,0 +1,48 @@
Maximum Power Mitigation Mechanism (MPMM) Bindings
==================================================
|MPMM| support cannot be determined at runtime by the firmware. Instead, these
DTB bindings allow the platform to communicate per-core support for |MPMM| via
the ``HW_CONFIG`` device tree blob.
Bindings
^^^^^^^^
.. contents::
:local:
``/cpus/cpus/cpu*`` node properties
"""""""""""""""""""""""""""""""""""
The ``cpu`` node has been augmented to allow the platform to indicate support
for |MPMM| on a given core.
+-------------------+-------+-------------+------------------------------------+
| Property name | Usage | Value type | Description |
+===================+=======+=============+====================================+
| ``supports-mpmm`` | O | ``<empty>`` | If present, indicates that |MPMM| |
| | | | is available on this core. |
+-------------------+-------+-------------+------------------------------------+
Example
^^^^^^^
An example system offering two cores, one with support for |MPMM| and one
without, can be described as follows:
.. code-block::
cpus {
#address-cells = <2>;
#size-cells = <0>;
cpu0@00000 {
...
supports-mpmm;
};
cpu1@00100 {
...
};
}

View File

@ -14,6 +14,7 @@ Components
fconf/index
firmware-update
measured_boot/index
mpmm
platform-interrupt-controller-API
ras
romlib-design

30
docs/components/mpmm.rst Normal file
View File

@ -0,0 +1,30 @@
Maximum Power Mitigation Mechanism (MPMM)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|MPMM| is an optional microarchitectural power management mechanism supported by
some Arm Armv9-A cores, beginning with the Cortex-X2, Cortex-A710 and
Cortex-A510 cores. This mechanism detects and limits high-activity events to
assist in |SoC| processor power domain dynamic power budgeting and limit the
triggering of whole-rail (i.e. clock chopping) responses to overcurrent
conditions.
|MPMM| is enabled on a per-core basis by the EL3 runtime firmware. The presence
of |MPMM| cannot be determined at runtime by the firmware, and therefore the
platform must expose this information through one of two possible mechanisms:
- |FCONF|, controlled by the ``ENABLE_MPMM_FCONF`` build option.
- A platform implementation of the ``plat_mpmm_topology`` function (the
default).
See :ref:`Maximum Power Mitigation Mechanism (MPMM) Bindings` for documentation
on the |FCONF| device tree bindings.
.. warning::
|MPMM| exposes gear metrics through the auxiliary |AMU| counters. An
external power controller can use these metrics to budget SoC power by
limiting the number of cores that can execute higher-activity workloads or
switching to a different DVFS operating point. When this is the case, the
|AMU| counters that make up the |MPMM| gears must be enabled by the EL3
runtime firmware - please see :ref:`Activity Monitor Auxiliary Counters` for
documentation on enabling auxiliary |AMU| counters.

View File

@ -265,6 +265,16 @@ Common build options
partitioning in EL3, however. Platform initialisation code should configure
and use partitions in EL3 as required. This option defaults to ``0``.
- ``ENABLE_MPMM``: Boolean option to enable support for the Maximum Power
Mitigation Mechanism supported by certain Arm cores, which allows the SoC
firmware to detect and limit high activity events to assist in SoC processor
power domain dynamic power budgeting and limit the triggering of whole-rail
(i.e. clock chopping) responses to overcurrent conditions. Defaults to ``0``.
- ``ENABLE_MPMM_FCONF``: Enables configuration of MPMM through FCONF, which
allows platforms with cores supporting MPMM to describe them via the
``HW_CONFIG`` device tree blob. Default is 0.
- ``ENABLE_PIE``: Boolean option to enable Position Independent Executable(PIE)
support within generic code in TF-A. This option is currently only supported
in BL2_AT_EL3, BL31, and BL32 (TSP) for AARCH64 binaries, and in BL32

View File

@ -25,6 +25,7 @@
.. |Linaro| replace:: :term:`Linaro`
.. |MMU| replace:: :term:`MMU`
.. |MPAM| replace:: :term:`MPAM`
.. |MPMM| replace:: :term:`MPMM`
.. |MPIDR| replace:: :term:`MPIDR`
.. |MTE| replace:: :term:`MTE`
.. |OEN| replace:: :term:`OEN`

View File

@ -92,6 +92,10 @@ You can find additional definitions in the `Arm Glossary`_.
MPAM
Memory Partitioning And Monitoring. An optional Armv8.4 extension.
MPMM
Maximum Power Mitigation Mechanism, an optional power management mechanism
supported by some Arm Armv9-A cores.
MPIDR
Multiprocessor Affinity Register

View File

@ -1216,4 +1216,16 @@
#define DSU_CLUSTER_PWR_ON 1
#define DSU_CLUSTER_PWR_MASK U(1)
/*******************************************************************************
* Definitions for CPU Power/Performance Management registers
******************************************************************************/
#define CPUPPMCR_EL3 S3_6_C15_C2_0
#define CPUPPMCR_EL3_MPMMPINCTL_SHIFT UINT64_C(0)
#define CPUPPMCR_EL3_MPMMPINCTL_MASK UINT64_C(0x1)
#define CPUMPMMCR_EL3 S3_6_C15_C2_1
#define CPUMPMMCR_EL3_MPMM_EN_SHIFT UINT64_C(0)
#define CPUMPMMCR_EL3_MPMM_EN_MASK UINT64_C(0x1)
#endif /* ARCH_H */

View File

@ -542,6 +542,10 @@ DEFINE_RENAME_SYSREG_RW_FUNCS(hcrx_el2, HCRX_EL2)
/* DynamIQ Shared Unit power management */
DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpwrdn_el1, CLUSTERPWRDN_EL1)
/* CPU Power/Performance Management registers */
DEFINE_RENAME_SYSREG_RW_FUNCS(cpuppmcr_el3, CPUPPMCR_EL3)
DEFINE_RENAME_SYSREG_RW_FUNCS(cpumpmmcr_el3, CPUMPMMCR_EL3)
/* Armv9.2 RME Registers */
DEFINE_RENAME_SYSREG_RW_FUNCS(gptbr_el3, GPTBR_EL3)
DEFINE_RENAME_SYSREG_RW_FUNCS(gpccr_el3, GPCCR_EL3)

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef FCONF_MPMM_GETTER_H
#define FCONF_MPMM_GETTER_H
#include <lib/mpmm/mpmm.h>
#define mpmm__config_getter(id) fconf_mpmm_config.id
struct fconf_mpmm_config {
const struct mpmm_topology *topology;
};
extern struct fconf_mpmm_config fconf_mpmm_config;
#endif /* FCONF_MPMM_GETTER_H */

57
include/lib/mpmm/mpmm.h Normal file
View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MPMM_H
#define MPMM_H
#include <stdbool.h>
#include <platform_def.h>
/*
* Enable the Maximum Power Mitigation Mechanism.
*
* This function will enable MPMM for the current core. The AMU counters
* representing the MPMM gears must have been configured and enabled prior to
* calling this function.
*/
void mpmm_enable(void);
/*
* MPMM core data.
*
* This structure represents per-core data retrieved from the hardware
* configuration device tree.
*/
struct mpmm_core {
/*
* Whether MPMM is supported.
*
* Cores with support for MPMM offer one or more auxiliary AMU counters
* representing MPMM gears.
*/
bool supported;
};
/*
* MPMM topology.
*
* This topology structure describes the system-wide representation of the
* information retrieved from the hardware configuration device tree.
*/
struct mpmm_topology {
struct mpmm_core cores[PLATFORM_CORE_COUNT]; /* Per-core data */
};
#if !ENABLE_MPMM_FCONF
/*
* Retrieve the platform's MPMM topology. A `NULL` return value is treated as a
* non-fatal error, in which case MPMM will not be enabled for any core.
*/
const struct mpmm_topology *plat_mpmm_topology(void);
#endif /* ENABLE_MPMM_FCONF */
#endif /* MPMM_H */

View File

@ -23,6 +23,10 @@
# include <lib/fconf/fconf_amu_getter.h>
#endif
#if ENABLE_MPMM
# include <lib/mpmm/mpmm.h>
#endif
struct amu_ctx {
uint64_t group0_cnts[AMU_GROUP0_MAX_COUNTERS];
#if ENABLE_AMU_AUXILIARY_COUNTERS
@ -273,26 +277,31 @@ void amu_enable(bool el2_unused, cpu_context_t *ctx)
/* Initialize FEAT_AMUv1p1 features if present. */
if (id_aa64pfr0_el1_amu >= ID_AA64PFR0_AMU_V1P1) {
return;
}
if (el2_unused) {
/* Make sure virtual offsets are disabled if EL2 not used. */
write_hcr_el2_amvoffen(0U);
}
if (el2_unused) {
/*
* Make sure virtual offsets are disabled if EL2 not
* used.
*/
write_hcr_el2_amvoffen(0U);
}
#if AMU_RESTRICT_COUNTERS
/*
* FEAT_AMUv1p1 adds a register field to restrict access to group 1
* counters at all but the highest implemented EL. This is controlled
* with the AMU_RESTRICT_COUNTERS compile time flag, when set, system
* register reads at lower ELs return zero. Reads from the memory
* mapped view are unaffected.
*/
VERBOSE("AMU group 1 counter access restricted.\n");
write_amcr_el0_cg1rz(1U);
/*
* FEAT_AMUv1p1 adds a register field to restrict access to
* group 1 counters at all but the highest implemented EL. This
* is controlled with the `AMU_RESTRICT_COUNTERS` compile time
* flag, when set, system register reads at lower ELs return
* zero. Reads from the memory mapped view are unaffected.
*/
VERBOSE("AMU group 1 counter access restricted.\n");
write_amcr_el0_cg1rz(1U);
#else
write_amcr_el0_cg1rz(0U);
write_amcr_el0_cg1rz(0U);
#endif
}
#if ENABLE_MPMM
mpmm_enable();
#endif
}
@ -616,6 +625,10 @@ static void *amu_context_restore(const void *arg)
}
#endif
#if ENABLE_MPMM
mpmm_enable();
#endif
return (void *)0;
}

View File

@ -14,3 +14,6 @@ FCONF_DYN_SOURCES += ${FDT_WRAPPERS_SOURCES}
FCONF_AMU_SOURCES := lib/fconf/fconf_amu_getter.c
FCONF_AMU_SOURCES += ${FDT_WRAPPERS_SOURCES}
FCONF_MPMM_SOURCES := lib/fconf/fconf_mpmm_getter.c
FCONF_MPMM_SOURCES += ${FDT_WRAPPERS_SOURCES}

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stddef.h>
#include <stdint.h>
#include <common/debug.h>
#include <common/fdt_wrappers.h>
#include <lib/fconf/fconf.h>
#include <lib/fconf/fconf_mpmm_getter.h>
#include <libfdt.h>
#include <plat/common/platform.h>
struct fconf_mpmm_config fconf_mpmm_config;
static struct mpmm_topology fconf_mpmm_topology;
/*
* Within a `cpu` node, determine support for MPMM via the `supports-mpmm`
* property.
*
* Returns `0` on success, or a negative integer representing an error code.
*/
static int fconf_populate_mpmm_cpu(const void *fdt, int off, uintptr_t mpidr)
{
int ret, len;
int core_pos;
struct mpmm_core *core;
core_pos = plat_core_pos_by_mpidr(mpidr);
if (core_pos < 0) {
return -FDT_ERR_BADVALUE;
}
core = &fconf_mpmm_topology.cores[core_pos];
fdt_getprop(fdt, off, "supports-mpmm", &len);
if (len >= 0) {
core->supported = true;
ret = 0;
} else {
core->supported = false;
ret = len;
}
return ret;
}
/*
* Populates the global `fconf_mpmm_config` structure based on what's described
* by the hardware configuration device tree blob.
*
* The device tree is expected to provide a `supports-mpmm` property for each
* `cpu` node, like so:
*
* cpu@0 {
* supports-mpmm;
* };
*
* This property indicates whether the core implements MPMM, as we cannot detect
* support for it dynamically.
*/
static int fconf_populate_mpmm(uintptr_t config)
{
int ret = fdtw_for_each_cpu(
(const void *)config, fconf_populate_mpmm_cpu);
if (ret == 0) {
fconf_mpmm_config.topology = &fconf_mpmm_topology;
} else {
ERROR("FCONF: failed to configure MPMM: %d\n", ret);
}
return ret;
}
FCONF_REGISTER_POPULATOR(HW_CONFIG, mpmm, fconf_populate_mpmm);

72
lib/mpmm/mpmm.c Normal file
View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2021, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdbool.h>
#include <common/debug.h>
#include <lib/mpmm/mpmm.h>
#include <plat/common/platform.h>
#if ENABLE_MPMM_FCONF
# include <lib/fconf/fconf.h>
# include <lib/fconf/fconf_mpmm_getter.h>
#endif
static uint64_t read_cpuppmcr_el3_mpmmpinctl(void)
{
return (read_cpuppmcr_el3() >> CPUPPMCR_EL3_MPMMPINCTL_SHIFT) &
CPUPPMCR_EL3_MPMMPINCTL_MASK;
}
static void write_cpumpmmcr_el3_mpmm_en(uint64_t mpmm_en)
{
uint64_t value = read_cpumpmmcr_el3();
value &= ~(CPUMPMMCR_EL3_MPMM_EN_MASK << CPUMPMMCR_EL3_MPMM_EN_SHIFT);
value |= (mpmm_en & CPUMPMMCR_EL3_MPMM_EN_MASK) <<
CPUMPMMCR_EL3_MPMM_EN_SHIFT;
write_cpumpmmcr_el3(value);
}
static bool mpmm_supported(void)
{
bool supported = false;
const struct mpmm_topology *topology;
#if ENABLE_MPMM_FCONF
topology = FCONF_GET_PROPERTY(mpmm, config, topology);
#else
topology = plat_mpmm_topology();
#endif /* ENABLE_MPMM_FCONF */
/*
* For the current core firstly try to find out if the platform
* configuration has claimed support for MPMM, then make sure that MPMM
* is controllable through the system registers.
*/
if (topology != NULL) {
unsigned int core_pos = plat_my_core_pos();
supported = topology->cores[core_pos].supported &&
(read_cpuppmcr_el3_mpmmpinctl() == 0U);
} else {
ERROR("MPMM: failed to generate MPMM topology\n");
}
return supported;
}
void mpmm_enable(void)
{
bool supported = mpmm_supported();
if (supported) {
write_cpumpmmcr_el3_mpmm_en(1U);
}
}

29
lib/mpmm/mpmm.mk Normal file
View File

@ -0,0 +1,29 @@
#
# Copyright (c) 2021, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
include lib/extensions/amu/amu.mk
include lib/fconf/fconf.mk
ifneq (${ENABLE_MPMM},0)
ifneq ($(ARCH),aarch64)
$(error MPMM support (`ENABLE_MPMM`) can only be enabled in AArch64 images (`ARCH`))
endif
ifeq (${ENABLE_AMU_AUXILIARY_COUNTERS},0) # For MPMM gear AMU counters
$(error MPMM support (`ENABLE_MPM`) requires auxiliary AMU counter support (`ENABLE_AMU_AUXILIARY_COUNTERS`))
endif
endif
MPMM_SOURCES := lib/mpmm/mpmm.c
MPMM_SOURCES += ${AMU_SOURCES}
ifneq (${ENABLE_MPMM_FCONF},0)
ifeq (${ENABLE_MPMM},0)
$(error MPMM FCONF support (`ENABLE_MPMM_FCONF`) requires MPMM support (`ENABLE_MPMM`))
endif
MPMM_SOURCES += ${FCONF_MPMM_SOURCES}
endif

View File

@ -96,6 +96,12 @@ DYN_DISABLE_AUTH := 0
# Build option to enable MPAM for lower ELs
ENABLE_MPAM_FOR_LOWER_ELS := 0
# Enable the Maximum Power Mitigation Mechanism on supporting cores.
ENABLE_MPMM := 0
# Enable MPMM configuration via FCONF.
ENABLE_MPMM_FCONF := 0
# Flag to Enable Position Independant support (PIE)
ENABLE_PIE := 0