aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Kay <chris.kay@arm.com>2021-05-05 13:38:30 +0100
committerChris Kay <chris.kay@arm.com>2021-10-26 12:15:42 +0100
commit68120783d6d6f99c605e9f746ee0e91e2908feb1 (patch)
tree2b6298ff714fe1c0abda5f3a06dc9a12513e2c32
parent742ca2307f4e9f82cb2c21518819425e5bcc0f90 (diff)
downloadarm-trusted-firmware-68120783d6d6f99c605e9f746ee0e91e2908feb1.tar.gz
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>
-rw-r--r--Makefile4
-rw-r--r--bl31/bl31.mk5
-rw-r--r--docs/components/activity-monitors.rst2
-rw-r--r--docs/components/fconf/index.rst1
-rw-r--r--docs/components/fconf/mpmm-bindings.rst48
-rw-r--r--docs/components/index.rst1
-rw-r--r--docs/components/mpmm.rst30
-rw-r--r--docs/getting_started/build-options.rst10
-rw-r--r--docs/global_substitutions.txt1
-rw-r--r--docs/glossary.rst4
-rw-r--r--include/arch/aarch64/arch.h12
-rw-r--r--include/arch/aarch64/arch_helpers.h4
-rw-r--r--include/lib/fconf/fconf_mpmm_getter.h20
-rw-r--r--include/lib/mpmm/mpmm.h57
-rw-r--r--lib/extensions/amu/aarch64/amu.c47
-rw-r--r--lib/fconf/fconf.mk3
-rw-r--r--lib/fconf/fconf_mpmm_getter.c80
-rw-r--r--lib/mpmm/mpmm.c72
-rw-r--r--lib/mpmm/mpmm.mk29
-rw-r--r--make_helpers/defaults.mk6
20 files changed, 419 insertions, 17 deletions
diff --git a/Makefile b/Makefile
index 21de8625f..0caa9c08e 100644
--- a/Makefile
+++ b/Makefile
@@ -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)
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index 4e9e99f46..9baa0c27f 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -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
diff --git a/docs/components/activity-monitors.rst b/docs/components/activity-monitors.rst
index ee280e287..dd45c4353 100644
--- a/docs/components/activity-monitors.rst
+++ b/docs/components/activity-monitors.rst
@@ -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
------------------
diff --git a/docs/components/fconf/index.rst b/docs/components/fconf/index.rst
index 00a4e297b..029f324dc 100644
--- a/docs/components/fconf/index.rst
+++ b/docs/components/fconf/index.rst
@@ -146,3 +146,4 @@ Properties binding information
fconf_properties
amu-bindings
+ mpmm-bindings
diff --git a/docs/components/fconf/mpmm-bindings.rst b/docs/components/fconf/mpmm-bindings.rst
new file mode 100644
index 000000000..d3cc857a8
--- /dev/null
+++ b/docs/components/fconf/mpmm-bindings.rst
@@ -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 {
+ ...
+ };
+ }
diff --git a/docs/components/index.rst b/docs/components/index.rst
index e46751651..754526daf 100644
--- a/docs/components/index.rst
+++ b/docs/components/index.rst
@@ -14,6 +14,7 @@ Components
fconf/index
firmware-update
measured_boot/index
+ mpmm
platform-interrupt-controller-API
ras
romlib-design
diff --git a/docs/components/mpmm.rst b/docs/components/mpmm.rst
new file mode 100644
index 000000000..1b1c6d8c7
--- /dev/null
+++ b/docs/components/mpmm.rst
@@ -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.
diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst
index 8a0167b6d..da8d554db 100644
--- a/docs/getting_started/build-options.rst
+++ b/docs/getting_started/build-options.rst
@@ -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
diff --git a/docs/global_substitutions.txt b/docs/global_substitutions.txt
index a70f15e3d..af1514675 100644
--- a/docs/global_substitutions.txt
+++ b/docs/global_substitutions.txt
@@ -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`
diff --git a/docs/glossary.rst b/docs/glossary.rst
index a062319ce..aeeb133cb 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -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
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index 8b362f1cc..5408acf82 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -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 */
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index cae05dc2e..37fa047c3 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -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)
diff --git a/include/lib/fconf/fconf_mpmm_getter.h b/include/lib/fconf/fconf_mpmm_getter.h
new file mode 100644
index 000000000..50d991a2f
--- /dev/null
+++ b/include/lib/fconf/fconf_mpmm_getter.h
@@ -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 */
diff --git a/include/lib/mpmm/mpmm.h b/include/lib/mpmm/mpmm.h
new file mode 100644
index 000000000..955c530e8
--- /dev/null
+++ b/include/lib/mpmm/mpmm.h
@@ -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 */
diff --git a/lib/extensions/amu/aarch64/amu.c b/lib/extensions/amu/aarch64/amu.c
index f7125204a..35efd21e0 100644
--- a/lib/extensions/amu/aarch64/amu.c
+++ b/lib/extensions/amu/aarch64/amu.c
@@ -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;
}
diff --git a/lib/fconf/fconf.mk b/lib/fconf/fconf.mk
index 18bcb3590..fb8891031 100644
--- a/lib/fconf/fconf.mk
+++ b/lib/fconf/fconf.mk
@@ -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}
diff --git a/lib/fconf/fconf_mpmm_getter.c b/lib/fconf/fconf_mpmm_getter.c
new file mode 100644
index 000000000..02a566d5a
--- /dev/null
+++ b/lib/fconf/fconf_mpmm_getter.c
@@ -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);
diff --git a/lib/mpmm/mpmm.c b/lib/mpmm/mpmm.c
new file mode 100644
index 000000000..a66f2aad3
--- /dev/null
+++ b/lib/mpmm/mpmm.c
@@ -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);
+ }
+}
diff --git a/lib/mpmm/mpmm.mk b/lib/mpmm/mpmm.mk
new file mode 100644
index 000000000..826f9253b
--- /dev/null
+++ b/lib/mpmm/mpmm.mk
@@ -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
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index 8705d9247..45f5fa87f 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -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