Commit 2cf9ca3f authored by James Morse's avatar James Morse
Browse files

arm64: mpam: Add helpers to change a task or cpu's MPAM PARTID/PMG values



Care must be taken when modifying the PARTID and PMG of a task in any
per-task structure as writing these values may race with the task being
scheduled in, and reading the modified values.

Add helpers to set the task properties, and the CPU default value.  These
use WRITE_ONCE() that pairs with the READ_ONCE() in mpam_get_regval() to
avoid causing torn values.

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>
Cc: Dave Martin <Dave.Martin@arm.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 avatarCatalin Marinas <catalin.marinas@arm.com>
Reviewed-by: default avatarGavin Shan <gshan@redhat.com>
Co-developed-by: default avatarBen Horgan <ben.horgan@arm.com>
Signed-off-by: default avatarBen Horgan <ben.horgan@arm.com>
Signed-off-by: default avatarJames Morse <james.morse@arm.com>
parent 37fe0f98
Loading
Loading
Loading
Loading
+27 −1
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
#ifndef __ASM__MPAM_H
#define __ASM__MPAM_H

#include <linux/bitfield.h>
#include <linux/jump_label.h>
#include <linux/percpu.h>
#include <linux/sched.h>
@@ -22,6 +23,23 @@ DECLARE_PER_CPU(u64, arm64_mpam_current);
 */
extern u64 arm64_mpam_global_default;

#ifdef CONFIG_ARM64_MPAM
static inline u64 __mpam_regval(u16 partid_d, u16 partid_i, u8 pmg_d, u8 pmg_i)
{
	return FIELD_PREP(MPAM0_EL1_PARTID_D, partid_d) |
	       FIELD_PREP(MPAM0_EL1_PARTID_I, partid_i) |
	       FIELD_PREP(MPAM0_EL1_PMG_D, pmg_d) |
	       FIELD_PREP(MPAM0_EL1_PMG_I, pmg_i);
}

static inline void mpam_set_cpu_defaults(int cpu, u16 partid_d, u16 partid_i,
					 u8 pmg_d, u8 pmg_i)
{
	u64 default_val = __mpam_regval(partid_d, partid_i, pmg_d, pmg_i);

	WRITE_ONCE(per_cpu(arm64_mpam_default, cpu), default_val);
}

/*
 * The resctrl filesystem writes to the partid/pmg values for threads and CPUs,
 * which may race with reads in mpam_thread_switch(). Ensure only one of the old
@@ -30,12 +48,20 @@ extern u64 arm64_mpam_global_default;
 * value to be stored with cache allocations, despite being considered 'free' by
 * resctrl.
 */
#ifdef CONFIG_ARM64_MPAM
static inline u64 mpam_get_regval(struct task_struct *tsk)
{
	return READ_ONCE(task_thread_info(tsk)->mpam_partid_pmg);
}

static inline void mpam_set_task_partid_pmg(struct task_struct *tsk,
					    u16 partid_d, u16 partid_i,
					    u8 pmg_d, u8 pmg_i)
{
	u64 regval = __mpam_regval(partid_d, partid_i, pmg_d, pmg_i);

	WRITE_ONCE(task_thread_info(tsk)->mpam_partid_pmg, regval);
}

static inline void mpam_thread_switch(struct task_struct *tsk)
{
	u64 oldregval;