From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=113.46.200.223 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1793881264; b=FJNqgdLJPQxVmpZPvIAv0BkncGkZ9FyM8IHV+zp3z9Su6iehHwRFwGym75yWYJY51IjT CYEotNvdl79z1NRrRdBU93SygWGXls/rIAA7xw8aYCuhfEflW90fFMsCpWb3vL9SO9e2b sC7sM53/PvGI66Hnpos7bj/ziHI1h9a/y3v8LBgT0vN4cuQciyYeOXBHObbtywOU4+pWo gU8bM1uNXztBYIKpLt8+wqCzGaOONOPTHxGBLIdEKfNY9AkCVLJq4OmpUS5h12VX9roFA K6ERmog+MCsZJrvkRHMeynAtiZHSAx9i6vtuklzRNrqCPa9jrls6yjwqHzr0E76jKIg== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793881264; h=DMARC-Filter:dkim-signature:Received:Received:Received:Message-ID: Date:MIME-Version:User-Agent:Subject:To:CC:References:From: In-Reply-To:Content-Type:Content-Transfer-Encoding:X-Originating-IP: X-ClientProxiedBy; bh=KoW9DJjnrzqP9I0+l+Pc/VE++4f01tBPwLkQyhjmVA0=; b=LJuwJTmm3H4nsurSn07LZNJ81wj815rydHNFmLc7lfXxPbLEPg6PIg7IMgJlUK+k68+h 6LLGUB5AcBu+iUjhWCCyjuumh9XJJ/DNAfpDuH6tcMjFWL5FBLWpoGLhlx8aJ4XsjzsKV bv7HijMQSluN+eVbxI9s6kStfsdJ0p4SBO+1MakMSMokqUlqt6eFfwz69vG9aK4/0b+F8 LiaIq5tB2llrdq3SRFW0ru0fnpSkwBPpGUfbsg61hZvgxVlk5y7/Mg4/it2p1bkA582H9 3Po/+IGbXB546c3FG0iZGP8UVyTkMJdXbdx+zCvcKiv2pXidI2sSe70+PS9is6g5eKw== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass header.d=huawei.com header.i=@huawei.com header.a=rsa-sha256 header.s=dkim header.b=uhn628jG; arc=none smtp.remote-ip=113.46.200.223 Received: from canpmsgout08.his.huawei.com (canpmsgout08.his.huawei.com [113.46.200.223]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 754CD606A32C; Thu, 5 Nov 2026 12:21:03 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 754CD606A32C Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key, unprotected) header.d=huawei.com header.i=@huawei.com header.a=rsa-sha256 header.s=dkim header.b=uhn628jG dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=KoW9DJjnrzqP9I0+l+Pc/VE++4f01tBPwLkQyhjmVA0=; b=uhn628jGcsP3vef2gLqMgu/DL/ieolPhOGb5xyCgo7VYl3vkX2Mc5AOeG8SV+gSwdp1jaSOig ixsZ40fVsh7X/qMiFKaJE/ThpKf/DbopPw5LNsngJBrHkdvezG1dNqkww10ZPHcrFp0iioUbOFS V7I900dwGWfWiCbUEbx8xHM= Received: from mail.maildlp.com (unknown [172.19.163.15]) by canpmsgout08.his.huawei.com (SkyGuard) with ESMTPS id 4jL1c62NZczmVCM; Thu, 5 Nov 2026 20:20:38 +0800 (CST) Received: from kwepemk200008.china.huawei.com (unknown [7.202.194.74]) by mail.maildlp.com (Postfix) with ESMTPS id B398940578; Thu, 5 Nov 2026 20:20:49 +0800 (CST) Received: from [10.67.110.68] (10.67.110.68) by kwepemk200008.china.huawei.com (7.202.194.74) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Thu, 5 Nov 2026 20:20:48 +0800 Message-ID: <145b3c09-ff33-4fd7-935a-fa4f4c3c07b2@huawei.com> Date: Thu, 5 Nov 2026 20:20:47 +0800 X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v6 06/40] arm64: mpam: Context switch the MPAM registers To: Ben Horgan CC: , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , Shaopeng Tan References: <20260313144617.3420416-1-ben.horgan@arm.com> <20260313144617.3420416-7-ben.horgan@arm.com> From: Jinjie Ruan In-Reply-To: <20260313144617.3420416-7-ben.horgan@arm.com> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8bit X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemk200008.china.huawei.com (7.202.194.74) 在 2026/3/13 22:45, Ben Horgan 写道: > From: James Morse > > MPAM allows traffic in the SoC to be labeled by the OS, these labels are > used to apply policy in caches and bandwidth regulators, and to monitor > traffic in the SoC. The label is made up of a PARTID and PMG value. The x86 > equivalent calls these CLOSID and RMID, but they don't map precisely. > > MPAM has two CPU system registers that is used to hold the PARTID and PMG > values that traffic generated at each exception level will use. These can > be set per-task by the resctrl file system. (resctrl is the defacto > interface for controlling this stuff). > > Add a helper to switch this. > > struct task_struct's separate CLOSID and RMID fields are insufficient to > implement resctrl using MPAM, as resctrl can change the PARTID (CLOSID) and > PMG (sort of like the RMID) separately. On x86, the rmid is an independent > number, so a race that writes a mismatched closid and rmid into hardware is > benign. On arm64, the pmg bits extend the partid. > (i.e. partid-5 has a pmg-0 that is not the same as partid-6's pmg-0). In > this case, mismatching the values will 'dirty' a pmg value that resctrl > believes is clean, and is not tracking with its 'limbo' code. > > To avoid this, the partid and pmg are always read and written as a > pair. This requires a new u64 field. In struct task_struct there are two > u32, rmid and closid for the x86 case, but as we can't use them here do > something else. Add this new field, mpam_partid_pmg, to struct thread_info > to avoid adding more architecture specific code to struct task_struct. > Always use READ_ONCE()/WRITE_ONCE() when accessing this field. > > Resctrl allows a per-cpu 'default' value to be set, this overrides the > values when scheduling a task in the default control-group, which has > PARTID 0. The way 'code data prioritisation' gets emulated means the > register value for the default group needs to be a variable. > > The current system register value is kept in a per-cpu variable to avoid > writing to the system register if the value isn't going to change. Writes > to this register may reset the hardware state for regulating bandwidth. > > Finally, there is no reason to context switch these registers unless there > is a driver changing the values in struct task_struct. Hide the whole thing > behind a static key. This also allows the driver to disable MPAM in > response to errors reported by hardware. Move the existing static key to > belong to the arch code, as in the future the MPAM driver may become a > loadable module. > > All this should depend on whether there is an MPAM driver, hide it behind > CONFIG_ARM64_MPAM. > > Tested-by: Gavin Shan > Tested-by: Shaopeng Tan > Tested-by: Peter Newman > Tested-by: Zeng Heng > Tested-by: Punit Agrawal > CC: Amit Singh Tomar > Reviewed-by: Zeng Heng > Reviewed-by: Shaopeng Tan > Reviewed-by: Jonathan Cameron > Reviewed-by: Gavin Shan > Reviewed-by: Catalin Marinas > Signed-off-by: James Morse > Signed-off-by: Ben Horgan > --- > Changes since rfc: > CONFIG_MPAM -> CONFIG_ARM64_MPAM in commit message > Remove extra DECLARE_STATIC_KEY_FALSE > Function name in comment, __mpam_sched_in() -> mpam_thread_switch() > Remove unused headers > Expand comment (Jonathan) > > Changes since v2: > Tidy up ifdefs > > Changes since v3: > Always set MPAMEN for MPAM1_EL1 rather than relying on it being read only. > --- > arch/arm64/Kconfig | 2 + > arch/arm64/include/asm/mpam.h | 67 ++++++++++++++++++++++++++++ > arch/arm64/include/asm/thread_info.h | 3 ++ > arch/arm64/kernel/Makefile | 1 + > arch/arm64/kernel/mpam.c | 13 ++++++ > arch/arm64/kernel/process.c | 7 +++ > drivers/resctrl/mpam_devices.c | 2 - > drivers/resctrl/mpam_internal.h | 4 +- > 8 files changed, 95 insertions(+), 4 deletions(-) > create mode 100644 arch/arm64/include/asm/mpam.h > create mode 100644 arch/arm64/kernel/mpam.c > > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig > index 38dba5f7e4d2..ecaaca13a969 100644 > --- a/arch/arm64/Kconfig > +++ b/arch/arm64/Kconfig > @@ -2039,6 +2039,8 @@ config ARM64_MPAM > > MPAM is exposed to user-space via the resctrl pseudo filesystem. > > + This option enables the extra context switch code. > + > endmenu # "ARMv8.4 architectural features" > > menu "ARMv8.5 architectural features" > diff --git a/arch/arm64/include/asm/mpam.h b/arch/arm64/include/asm/mpam.h > new file mode 100644 > index 000000000000..0747e0526927 > --- /dev/null > +++ b/arch/arm64/include/asm/mpam.h > @@ -0,0 +1,67 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* Copyright (C) 2025 Arm Ltd. */ > + > +#ifndef __ASM__MPAM_H > +#define __ASM__MPAM_H > + > +#include > +#include > +#include > + > +#include > + > +DECLARE_STATIC_KEY_FALSE(mpam_enabled); > +DECLARE_PER_CPU(u64, arm64_mpam_default); > +DECLARE_PER_CPU(u64, arm64_mpam_current); > + > +/* > + * The value of the MPAM0_EL1 sysreg when a task is in resctrl's default group. > + * This is used by the context switch code to use the resctrl CPU property > + * instead. The value is modified when CDP is enabled/disabled by mounting > + * the resctrl filesystem. > + */ > +extern u64 arm64_mpam_global_default; > + > +/* > + * 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 > + * or new values are used. Particular care should be taken with the pmg field as > + * mpam_thread_switch() may read a partid and pmg that don't match, causing this > + * 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_thread_switch(struct task_struct *tsk) > +{ > + u64 oldregval; > + int cpu = smp_processor_id(); > + u64 regval = mpam_get_regval(tsk); > + > + if (!static_branch_likely(&mpam_enabled)) > + return; > + > + if (regval == READ_ONCE(arm64_mpam_global_default)) > + regval = READ_ONCE(per_cpu(arm64_mpam_default, cpu)); > + > + oldregval = READ_ONCE(per_cpu(arm64_mpam_current, cpu)); > + if (oldregval == regval) > + return; > + > + write_sysreg_s(regval | MPAM1_EL1_MPAMEN, SYS_MPAM1_EL1); > + isb(); Hi, everyone, We found a problem as below: In an offline/online co-located setup, MPAM gives the offline group a smaller MBW share, a softirq serving an online service runs with the PARTID of the throttled offline task it interrupted and is throttled with it -- a priority inversion. Is this a known limitation? I see the following patchset uses a separate closid for kernel. https://lore.kernel.org/all/cover.1790867441.git.babu.moger@amd.com/ > + > + /* Synchronising the EL0 write is left until the ERET to EL0 */ > + write_sysreg_s(regval, SYS_MPAM0_EL1); > + > + WRITE_ONCE(per_cpu(arm64_mpam_current, cpu), regval); > +} > +#else > +static inline void mpam_thread_switch(struct task_struct *tsk) {} > +#endif /* CONFIG_ARM64_MPAM */ > + > +#endif /* __ASM__MPAM_H */ > diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h > index 7942478e4065..5d7fe3e153c8 100644 > --- a/arch/arm64/include/asm/thread_info.h > +++ b/arch/arm64/include/asm/thread_info.h > @@ -41,6 +41,9 @@ struct thread_info { > #ifdef CONFIG_SHADOW_CALL_STACK > void *scs_base; > void *scs_sp; > +#endif > +#ifdef CONFIG_ARM64_MPAM > + u64 mpam_partid_pmg; > #endif > u32 cpu; > }; > diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile > index 76f32e424065..15979f366519 100644 > --- a/arch/arm64/kernel/Makefile > +++ b/arch/arm64/kernel/Makefile > @@ -67,6 +67,7 @@ obj-$(CONFIG_CRASH_DUMP) += crash_dump.o > obj-$(CONFIG_VMCORE_INFO) += vmcore_info.o > obj-$(CONFIG_ARM_SDE_INTERFACE) += sdei.o > obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o > +obj-$(CONFIG_ARM64_MPAM) += mpam.o > obj-$(CONFIG_ARM64_MTE) += mte.o > obj-y += vdso-wrap.o > obj-$(CONFIG_COMPAT_VDSO) += vdso32-wrap.o > diff --git a/arch/arm64/kernel/mpam.c b/arch/arm64/kernel/mpam.c > new file mode 100644 > index 000000000000..9866d2ca0faa > --- /dev/null > +++ b/arch/arm64/kernel/mpam.c > @@ -0,0 +1,13 @@ > +// SPDX-License-Identifier: GPL-2.0 > +/* Copyright (C) 2025 Arm Ltd. */ > + > +#include > + > +#include > +#include > + > +DEFINE_STATIC_KEY_FALSE(mpam_enabled); > +DEFINE_PER_CPU(u64, arm64_mpam_default); > +DEFINE_PER_CPU(u64, arm64_mpam_current); > + > +u64 arm64_mpam_global_default; > diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c > index 489554931231..47698955fa1e 100644 > --- a/arch/arm64/kernel/process.c > +++ b/arch/arm64/kernel/process.c > @@ -51,6 +51,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -738,6 +739,12 @@ struct task_struct *__switch_to(struct task_struct *prev, > if (prev->thread.sctlr_user != next->thread.sctlr_user) > update_sctlr_el1(next->thread.sctlr_user); > > + /* > + * MPAM thread switch happens after the DSB to ensure prev's accesses > + * use prev's MPAM settings. > + */ > + mpam_thread_switch(next); > + > /* the actual thread switch */ > last = cpu_switch_to(prev, next); > > diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c > index ff861291bd4e..d50461d6ff3f 100644 > --- a/drivers/resctrl/mpam_devices.c > +++ b/drivers/resctrl/mpam_devices.c > @@ -29,8 +29,6 @@ > > #include "mpam_internal.h" > > -DEFINE_STATIC_KEY_FALSE(mpam_enabled); /* This moves to arch code */ > - > /* > * mpam_list_lock protects the SRCU lists when writing. Once the > * mpam_enabled key is enabled these lists are read-only, > diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h > index e8971842b124..4632985bcca6 100644 > --- a/drivers/resctrl/mpam_internal.h > +++ b/drivers/resctrl/mpam_internal.h > @@ -16,12 +16,12 @@ > #include > #include > > +#include > + > #define MPAM_MSC_MAX_NUM_RIS 16 > > struct platform_device; > > -DECLARE_STATIC_KEY_FALSE(mpam_enabled); > - > #ifdef CONFIG_MPAM_KUNIT_TEST > #define PACKED_FOR_KUNIT __packed > #else -- Best regards, Jinjie