Commit 37fe0f98 authored by Ben Horgan's avatar Ben Horgan Committed by James Morse
Browse files

arm64: mpam: Initialise and context switch the MPAMSM_EL1 register



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: default avatarGavin Shan <gshan@redhat.com>
Tested-by: default avatarShaopeng Tan <tan.shaopeng@jp.fujitsu.com>
Tested-by: default avatarPeter Newman <peternewman@google.com>
Tested-by: default avatarZeng Heng <zengheng4@huawei.com>
Tested-by: default avatarPunit Agrawal <punit.agrawal@oss.qualcomm.com>
Tested-by: default avatarJesse Chick <jessechick@os.amperecomputing.com>
Reviewed-by: default avatarZeng Heng <zengheng4@huawei.com>
Reviewed-by: default avatarShaopeng Tan <tan.shaopeng@jp.fujitsu.com>
Reviewed-by: default avatarJonathan Cameron <jonathan.cameron@huawei.com>
Reviewed-by: default avatarGavin Shan <gshan@redhat.com>
Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Reviewed-by: default avatarJames Morse <james.morse@arm.com>
Signed-off-by: default avatarBen Horgan <ben.horgan@arm.com>
Signed-off-by: default avatarJames Morse <james.morse@arm.com>
parent 735dad99
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -513,7 +513,8 @@
	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
+2 −0
Original line number Diff line number Diff line
@@ -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 */
+2 −0
Original line number Diff line number Diff line
@@ -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 */
+4 −0
Original line number Diff line number Diff line
@@ -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);