]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
arm64: mpam: Initialise and context switch the MPAMSM_EL1 register
authorBen Horgan <ben.horgan@arm.com>
Fri, 13 Mar 2026 14:45:48 +0000 (14:45 +0000)
committerJames Morse <james.morse@arm.com>
Fri, 27 Mar 2026 15:29:02 +0000 (15:29 +0000)
The MPAMSM_EL1 sets the MPAM labels, PMG and PARTID, for loads and stores
generated by a shared SMCU. Disable the traps so the kernel can use it and
set it to the same configuration as the per-EL cpu MPAM configuration.

If an SMCU is not shared with other cpus then it is implementation
defined whether the configuration from MPAMSM_EL1 is used or that from
the appropriate MPAMy_ELx. As we set the same, PMG_D and PARTID_D,
configuration for MPAM0_EL1, MPAM1_EL1 and MPAMSM_EL1 the resulting
configuration is the same regardless.

The range of valid configurations for the PARTID and PMG in MPAMSM_EL1 is
not currently specified in Arm Architectural Reference Manual but the
architect has confirmed that it is intended to be the same as that for the
cpu configuration in the MPAMy_ELx registers.

Tested-by: Gavin Shan <gshan@redhat.com>
Tested-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com>
Tested-by: Peter Newman <peternewman@google.com>
Tested-by: Zeng Heng <zengheng4@huawei.com>
Tested-by: Punit Agrawal <punit.agrawal@oss.qualcomm.com>
Tested-by: Jesse Chick <jessechick@os.amperecomputing.com>
Reviewed-by: Zeng Heng <zengheng4@huawei.com>
Reviewed-by: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: Gavin Shan <gshan@redhat.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: James Morse <james.morse@arm.com>
Signed-off-by: Ben Horgan <ben.horgan@arm.com>
Signed-off-by: James Morse <james.morse@arm.com>
arch/arm64/include/asm/el2_setup.h
arch/arm64/include/asm/mpam.h
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/mpam.c

index 85f4c1615472d74b24df9c13dad2d338e235250e..4d15071a4f3fc162c1d76a2ff78e3112048d378c 100644 (file)
        check_override id_aa64pfr0, ID_AA64PFR0_EL1_MPAM_SHIFT, .Linit_mpam_\@, .Lskip_mpam_\@, x1, x2
 
 .Linit_mpam_\@:
-       msr_s   SYS_MPAM2_EL2, xzr              // use the default partition
+       mov     x0, #MPAM2_EL2_EnMPAMSM_MASK
+       msr_s   SYS_MPAM2_EL2, x0               // use the default partition,
                                                // and disable lower traps
        mrs_s   x0, SYS_MPAMIDR_EL1
        tbz     x0, #MPAMIDR_EL1_HAS_HCR_SHIFT, .Lskip_mpam_\@  // skip if no MPAMHCR reg
index 0747e0526927d6a37aea53a41ada87ec6c469361..6bccbfdccb87e0f729ade5c089d8a100f75527e1 100644 (file)
@@ -53,6 +53,8 @@ static inline void mpam_thread_switch(struct task_struct *tsk)
                return;
 
        write_sysreg_s(regval | MPAM1_EL1_MPAMEN, SYS_MPAM1_EL1);
+       if (system_supports_sme())
+               write_sysreg_s(regval & (MPAMSM_EL1_PARTID_D | MPAMSM_EL1_PMG_D), SYS_MPAMSM_EL1);
        isb();
 
        /* Synchronising the EL0 write is left until the ERET to EL0 */
index c3f900f81653faaf771d29cf958b09d8fd484943..4f34e7a76f6415fb0ce5a7d2841b43c533c13e4a 100644 (file)
@@ -2500,6 +2500,8 @@ cpu_enable_mpam(const struct arm64_cpu_capabilities *entry)
                regval = READ_ONCE(per_cpu(arm64_mpam_current, cpu));
 
        write_sysreg_s(regval | MPAM1_EL1_MPAMEN, SYS_MPAM1_EL1);
+       if (cpus_have_cap(ARM64_SME))
+               write_sysreg_s(regval & (MPAMSM_EL1_PARTID_D | MPAMSM_EL1_PMG_D), SYS_MPAMSM_EL1);
        isb();
 
        /* Synchronising the EL0 write is left until the ERET to EL0 */
index 48ec0ffd59997cb3670438fa65c779d1e09a531d..3a490de4fa12586ac7d1ab53884d68c1711c8e99 100644 (file)
@@ -28,6 +28,10 @@ static int mpam_pm_notifier(struct notifier_block *self,
                 */
                regval = READ_ONCE(per_cpu(arm64_mpam_current, cpu));
                write_sysreg_s(regval | MPAM1_EL1_MPAMEN, SYS_MPAM1_EL1);
+               if (system_supports_sme()) {
+                       write_sysreg_s(regval & (MPAMSM_EL1_PARTID_D | MPAMSM_EL1_PMG_D),
+                                      SYS_MPAMSM_EL1);
+               }
                isb();
 
                write_sysreg_s(regval, SYS_MPAM0_EL1);