<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux.git/arch/arm64/kernel/mpam.c, branch master</title>
<subtitle>Linux kernel source tree</subtitle>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/'/>
<entry>
<title>arm64: mpam: Initialise and context switch the MPAMSM_EL1 register</title>
<updated>2026-03-27T15:29:02+00:00</updated>
<author>
<name>Ben Horgan</name>
<email>ben.horgan@arm.com</email>
</author>
<published>2026-03-13T14:45:48+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=37fe0f984d9ca60e8d95fc9a85d37f4300159625'/>
<id>37fe0f984d9ca60e8d95fc9a85d37f4300159625</id>
<content type='text'>
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 &lt;gshan@redhat.com&gt;
Tested-by: Shaopeng Tan &lt;tan.shaopeng@jp.fujitsu.com&gt;
Tested-by: Peter Newman &lt;peternewman@google.com&gt;
Tested-by: Zeng Heng &lt;zengheng4@huawei.com&gt;
Tested-by: Punit Agrawal &lt;punit.agrawal@oss.qualcomm.com&gt;
Tested-by: Jesse Chick &lt;jessechick@os.amperecomputing.com&gt;
Reviewed-by: Zeng Heng &lt;zengheng4@huawei.com&gt;
Reviewed-by: Shaopeng Tan &lt;tan.shaopeng@jp.fujitsu.com&gt;
Reviewed-by: Jonathan Cameron &lt;jonathan.cameron@huawei.com&gt;
Reviewed-by: Gavin Shan &lt;gshan@redhat.com&gt;
Reviewed-by: Catalin Marinas &lt;catalin.marinas@arm.com&gt;
Reviewed-by: James Morse &lt;james.morse@arm.com&gt;
Signed-off-by: Ben Horgan &lt;ben.horgan@arm.com&gt;
Signed-off-by: James Morse &lt;james.morse@arm.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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 &lt;gshan@redhat.com&gt;
Tested-by: Shaopeng Tan &lt;tan.shaopeng@jp.fujitsu.com&gt;
Tested-by: Peter Newman &lt;peternewman@google.com&gt;
Tested-by: Zeng Heng &lt;zengheng4@huawei.com&gt;
Tested-by: Punit Agrawal &lt;punit.agrawal@oss.qualcomm.com&gt;
Tested-by: Jesse Chick &lt;jessechick@os.amperecomputing.com&gt;
Reviewed-by: Zeng Heng &lt;zengheng4@huawei.com&gt;
Reviewed-by: Shaopeng Tan &lt;tan.shaopeng@jp.fujitsu.com&gt;
Reviewed-by: Jonathan Cameron &lt;jonathan.cameron@huawei.com&gt;
Reviewed-by: Gavin Shan &lt;gshan@redhat.com&gt;
Reviewed-by: Catalin Marinas &lt;catalin.marinas@arm.com&gt;
Reviewed-by: James Morse &lt;james.morse@arm.com&gt;
Signed-off-by: Ben Horgan &lt;ben.horgan@arm.com&gt;
Signed-off-by: James Morse &lt;james.morse@arm.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>arm64: mpam: Add cpu_pm notifier to restore MPAM sysregs</title>
<updated>2026-03-27T15:28:54+00:00</updated>
<author>
<name>James Morse</name>
<email>james.morse@arm.com</email>
</author>
<published>2026-03-13T14:45:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=735dad999905dfd246be1994bb8d203063aeb0d6'/>
<id>735dad999905dfd246be1994bb8d203063aeb0d6</id>
<content type='text'>
The MPAM system registers will be lost if the CPU is reset during PSCI's
CPU_SUSPEND.

Add a PM notifier to restore them.

mpam_thread_switch(current) can't be used as this won't make any changes if
the in-memory copy says the register already has the correct value. In
reality the system register is UNKNOWN out of reset.

Tested-by: Gavin Shan &lt;gshan@redhat.com&gt;
Tested-by: Shaopeng Tan &lt;tan.shaopeng@jp.fujitsu.com&gt;
Tested-by: Peter Newman &lt;peternewman@google.com&gt;
Tested-by: Zeng Heng &lt;zengheng4@huawei.com&gt;
Tested-by: Punit Agrawal &lt;punit.agrawal@oss.qualcomm.com&gt;
Tested-by: Jesse Chick &lt;jessechick@os.amperecomputing.com&gt;
Reviewed-by: Zeng Heng &lt;zengheng4@huawei.com&gt;
Reviewed-by: Shaopeng Tan &lt;tan.shaopeng@jp.fujitsu.com&gt;
Reviewed-by: Jonathan Cameron &lt;jonathan.cameron@huawei.com&gt;
Reviewed-by: Gavin Shan &lt;gshan@redhat.com&gt;
Reviewed-by: Catalin Marinas &lt;catalin.marinas@arm.com&gt;
Co-developed-by: Ben Horgan &lt;ben.horgan@arm.com&gt;
Signed-off-by: Ben Horgan &lt;ben.horgan@arm.com&gt;
Signed-off-by: James Morse &lt;james.morse@arm.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The MPAM system registers will be lost if the CPU is reset during PSCI's
CPU_SUSPEND.

Add a PM notifier to restore them.

mpam_thread_switch(current) can't be used as this won't make any changes if
the in-memory copy says the register already has the correct value. In
reality the system register is UNKNOWN out of reset.

Tested-by: Gavin Shan &lt;gshan@redhat.com&gt;
Tested-by: Shaopeng Tan &lt;tan.shaopeng@jp.fujitsu.com&gt;
Tested-by: Peter Newman &lt;peternewman@google.com&gt;
Tested-by: Zeng Heng &lt;zengheng4@huawei.com&gt;
Tested-by: Punit Agrawal &lt;punit.agrawal@oss.qualcomm.com&gt;
Tested-by: Jesse Chick &lt;jessechick@os.amperecomputing.com&gt;
Reviewed-by: Zeng Heng &lt;zengheng4@huawei.com&gt;
Reviewed-by: Shaopeng Tan &lt;tan.shaopeng@jp.fujitsu.com&gt;
Reviewed-by: Jonathan Cameron &lt;jonathan.cameron@huawei.com&gt;
Reviewed-by: Gavin Shan &lt;gshan@redhat.com&gt;
Reviewed-by: Catalin Marinas &lt;catalin.marinas@arm.com&gt;
Co-developed-by: Ben Horgan &lt;ben.horgan@arm.com&gt;
Signed-off-by: Ben Horgan &lt;ben.horgan@arm.com&gt;
Signed-off-by: James Morse &lt;james.morse@arm.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>arm64: mpam: Advertise the CPUs MPAM limits to the driver</title>
<updated>2026-03-27T15:28:42+00:00</updated>
<author>
<name>James Morse</name>
<email>james.morse@arm.com</email>
</author>
<published>2026-03-13T14:45:46+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=831a7f16728c5ceef04ab99a699c3d9e519dc4b8'/>
<id>831a7f16728c5ceef04ab99a699c3d9e519dc4b8</id>
<content type='text'>
Requesters need to populate the MPAM fields for any traffic they send on
the interconnect. For the CPUs these values are taken from the
corresponding MPAMy_ELx register. Each requester may have a limit on the
largest PARTID or PMG value that can be used. The MPAM driver has to
determine the system-wide minimum supported PARTID and PMG values.

To do this, the driver needs to be told what each requestor's limit is.

CPUs are special, but this infrastructure is also needed for the SMMU and
GIC ITS. Call the helper to tell the MPAM driver what the CPUs can do.

The return value can be ignored by the arch code as it runs well before the
MPAM driver starts probing.

Tested-by: Gavin Shan &lt;gshan@redhat.com&gt;
Tested-by: Shaopeng Tan &lt;tan.shaopeng@jp.fujitsu.com&gt;
Tested-by: Peter Newman &lt;peternewman@google.com&gt;
Tested-by: Zeng Heng &lt;zengheng4@huawei.com&gt;
Tested-by: Punit Agrawal &lt;punit.agrawal@oss.qualcomm.com&gt;
Tested-by: Jesse Chick &lt;jessechick@os.amperecomputing.com&gt;
Reviewed-by: Zeng Heng &lt;zengheng4@huawei.com&gt;
Reviewed-by: Shaopeng Tan &lt;tan.shaopeng@jp.fujitsu.com&gt;
Reviewed-by: Jonathan Cameron &lt;jonathan.cameron@huawei.com&gt;
Reviewed-by: Catalin Marinas &lt;catalin.marinas@arm.com&gt;
Reviewed-by: Gavin Shan &lt;gshan@redhat.com&gt;
Co-developed-by: Ben Horgan &lt;ben.horgan@arm.com&gt;
Signed-off-by: Ben Horgan &lt;ben.horgan@arm.com&gt;
[ morse: requestor-&gt;requester as argued by ispell ]
Signed-off-by: James Morse &lt;james.morse@arm.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Requesters need to populate the MPAM fields for any traffic they send on
the interconnect. For the CPUs these values are taken from the
corresponding MPAMy_ELx register. Each requester may have a limit on the
largest PARTID or PMG value that can be used. The MPAM driver has to
determine the system-wide minimum supported PARTID and PMG values.

To do this, the driver needs to be told what each requestor's limit is.

CPUs are special, but this infrastructure is also needed for the SMMU and
GIC ITS. Call the helper to tell the MPAM driver what the CPUs can do.

The return value can be ignored by the arch code as it runs well before the
MPAM driver starts probing.

Tested-by: Gavin Shan &lt;gshan@redhat.com&gt;
Tested-by: Shaopeng Tan &lt;tan.shaopeng@jp.fujitsu.com&gt;
Tested-by: Peter Newman &lt;peternewman@google.com&gt;
Tested-by: Zeng Heng &lt;zengheng4@huawei.com&gt;
Tested-by: Punit Agrawal &lt;punit.agrawal@oss.qualcomm.com&gt;
Tested-by: Jesse Chick &lt;jessechick@os.amperecomputing.com&gt;
Reviewed-by: Zeng Heng &lt;zengheng4@huawei.com&gt;
Reviewed-by: Shaopeng Tan &lt;tan.shaopeng@jp.fujitsu.com&gt;
Reviewed-by: Jonathan Cameron &lt;jonathan.cameron@huawei.com&gt;
Reviewed-by: Catalin Marinas &lt;catalin.marinas@arm.com&gt;
Reviewed-by: Gavin Shan &lt;gshan@redhat.com&gt;
Co-developed-by: Ben Horgan &lt;ben.horgan@arm.com&gt;
Signed-off-by: Ben Horgan &lt;ben.horgan@arm.com&gt;
[ morse: requestor-&gt;requester as argued by ispell ]
Signed-off-by: James Morse &lt;james.morse@arm.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>arm64: mpam: Context switch the MPAM registers</title>
<updated>2026-03-27T15:27:59+00:00</updated>
<author>
<name>James Morse</name>
<email>james.morse@arm.com</email>
</author>
<published>2026-03-13T14:45:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=8e06d04ff1cf764066c62e5677bfb0b0c1d1fbbc'/>
<id>8e06d04ff1cf764066c62e5677bfb0b0c1d1fbbc</id>
<content type='text'>
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 &lt;gshan@redhat.com&gt;
Tested-by: Shaopeng Tan &lt;tan.shaopeng@jp.fujitsu.com&gt;
Tested-by: Peter Newman &lt;peternewman@google.com&gt;
Tested-by: Zeng Heng &lt;zengheng4@huawei.com&gt;
Tested-by: Punit Agrawal &lt;punit.agrawal@oss.qualcomm.com&gt;
Tested-by: Jesse Chick &lt;jessechick@os.amperecomputing.com&gt;
CC: Amit Singh Tomar &lt;amitsinght@marvell.com&gt;
Reviewed-by: Zeng Heng &lt;zengheng4@huawei.com&gt;
Reviewed-by: Shaopeng Tan &lt;tan.shaopeng@jp.fujitsu.com&gt;
Reviewed-by: Jonathan Cameron &lt;jonathan.cameron@huawei.com&gt;
Reviewed-by: Gavin Shan &lt;gshan@redhat.com&gt;
Reviewed-by: Catalin Marinas &lt;catalin.marinas@arm.com&gt;
Co-developed-by: Ben Horgan &lt;ben.horgan@arm.com&gt;
Signed-off-by: Ben Horgan &lt;ben.horgan@arm.com&gt;
Signed-off-by: James Morse &lt;james.morse@arm.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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 &lt;gshan@redhat.com&gt;
Tested-by: Shaopeng Tan &lt;tan.shaopeng@jp.fujitsu.com&gt;
Tested-by: Peter Newman &lt;peternewman@google.com&gt;
Tested-by: Zeng Heng &lt;zengheng4@huawei.com&gt;
Tested-by: Punit Agrawal &lt;punit.agrawal@oss.qualcomm.com&gt;
Tested-by: Jesse Chick &lt;jessechick@os.amperecomputing.com&gt;
CC: Amit Singh Tomar &lt;amitsinght@marvell.com&gt;
Reviewed-by: Zeng Heng &lt;zengheng4@huawei.com&gt;
Reviewed-by: Shaopeng Tan &lt;tan.shaopeng@jp.fujitsu.com&gt;
Reviewed-by: Jonathan Cameron &lt;jonathan.cameron@huawei.com&gt;
Reviewed-by: Gavin Shan &lt;gshan@redhat.com&gt;
Reviewed-by: Catalin Marinas &lt;catalin.marinas@arm.com&gt;
Co-developed-by: Ben Horgan &lt;ben.horgan@arm.com&gt;
Signed-off-by: Ben Horgan &lt;ben.horgan@arm.com&gt;
Signed-off-by: James Morse &lt;james.morse@arm.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
