Re: [PATCH v3 30/47] arm_mpam: resctrl: Pre-allocate free running monitors

Gavin Shan
2026-01-19T11:57:55Z

Hi Ben,

On 1/13/26 12:58 AM, Ben Horgan wrote:
> From: James Morse <james.morse@arm.com>
>
> When there are enough monitors, the resctrl mbm local and total files can
> be exposed. These need all the monitors that resctrl may use to be
> allocated up front.
>
> Add helpers to do this.
>
> If a different candidate class is discovered, the old array should be
> free'd and the allocated monitors returned to the driver.
>
> Signed-off-by: James Morse <james.morse@arm.com>
> Signed-off-by: Ben Horgan <ben.horgan@arm.com>
> ---
> Changes since v2:
> Code flow tidying (Jonathan)
> ---
> drivers/resctrl/mpam_internal.h | 8 +++-
> drivers/resctrl/mpam_resctrl.c | 81 ++++++++++++++++++++++++++++++++-
> 2 files changed, 86 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h
> index 1c5492008fe8..89f9d374ded0 100644
> --- a/drivers/resctrl/mpam_internal.h
> +++ b/drivers/resctrl/mpam_internal.h
> @@ -360,7 +360,13 @@ struct mpam_resctrl_res {
> struct mpam_resctrl_mon {
> struct mpam_class *class;
>
> - /* per-class data that resctrl needs will live here */
> + /*
> + * Array of allocated MBWU monitors, indexed by (closid, rmid).
> + * When ABMC is not in use, this array directly maps (closid, rmid)
> + * to the allocated monitor. Otherwise this array is sparse, and
> + * un-assigned (closid, rmid) are -1.
> + */
> + int *mbwu_idx_to_mon;
> };
>
> static inline int mpam_alloc_csu_mon(struct mpam_class *class)
> diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
> index 14a8dcaf1366..3af12ad77fba 100644
> --- a/drivers/resctrl/mpam_resctrl.c
> +++ b/drivers/resctrl/mpam_resctrl.c
> @@ -572,10 +572,58 @@ static void mpam_resctrl_pick_mba(void)
> }
> }
>
> +static void __free_mbwu_mon(struct mpam_class *class, int *array,
> + u16 num_mbwu_mon)
> +{
> + for (int i = 0; i < num_mbwu_mon; i++) {
> + if (array[i] < 0)
> + continue;
> +
> + mpam_free_mbwu_mon(class, array[i]);
> + array[i] = ~0;
> + }
> +}
> +
> +static int __alloc_mbwu_mon(struct mpam_class *class, int *array,
> + u16 num_mbwu_mon)
> +{
> + for (int i = 0; i < num_mbwu_mon; i++) {
> + int mbwu_mon = mpam_alloc_mbwu_mon(class);
> +
> + if (mbwu_mon < 0) {
> + __free_mbwu_mon(class, array, num_mbwu_mon);
> + return mbwu_mon;
> + }
> + array[i] = mbwu_mon;
> + }
> +
> + return 0;
> +}
> +
> +static int *__alloc_mbwu_array(struct mpam_class *class, u16 num_mbwu_mon)
> +{
> + int err;
> + size_t array_size = num_mbwu_mon * sizeof(int);
> + int *array __free(kfree) = kmalloc(array_size, GFP_KERNEL);
> +

A warning reported by checkpatch.pl as below.

WARNING: Missing a blank line after declarations
#84: FILE: drivers/resctrl/mpam_resctrl.c:607:
+ size_t array_size = num_mbwu_mon * sizeof(int);
+ int *array __free(kfree) = kmalloc(array_size, GFP_KERNEL);

> + if (!array)
> + return ERR_PTR(-ENOMEM);
> +
> + memset(array, -1, array_size);
> +
> + err = __alloc_mbwu_mon(class, array, num_mbwu_mon);
> + if (err)
> + return ERR_PTR(err);
> + return_ptr(array);
> +}
> +
> static void counter_update_class(enum resctrl_event_id evt_id,
> struct mpam_class *class)
> {
> - struct mpam_class *existing_class = mpam_resctrl_counters[evt_id].class;
> + struct mpam_resctrl_mon *mon = &mpam_resctrl_counters[evt_id];
> + struct mpam_class *existing_class = mon->class;
> + u16 num_mbwu_mon = class->props.num_mbwu_mon;
> + int *new_array, *existing_array = mon->mbwu_idx_to_mon;
>
> if (existing_class) {
> if (class->level == 3) {
> @@ -590,8 +638,37 @@ static void counter_update_class(enum resctrl_event_id evt_id,
> }
> }
>
> - mpam_resctrl_counters[evt_id].class = class;
> + pr_debug("Updating event %u to use class %u\n", evt_id, class->level);
> +
> + /* Might not need all the monitors */
> + num_mbwu_mon = __mpam_monitors_free_running(num_mbwu_mon);
> +
> + if ((evt_id != QOS_L3_OCCUP_EVENT_ID) && num_mbwu_mon) {
> + /*
> + * This is the pre-allocated free-running monitors path. It always
> + * allocates one monitor per PARTID * PMG.
> + */
> + WARN_ON_ONCE(num_mbwu_mon != resctrl_arch_system_num_rmid_idx());
> +
> + new_array = __alloc_mbwu_array(class, num_mbwu_mon);
> + if (IS_ERR(new_array)) {
> + pr_debug("Failed to allocate MBWU array\n");
> + return;
> + }
> + mon->mbwu_idx_to_mon = new_array;
> +
> + if (existing_array) {
> + pr_debug("Releasing previous class %u's monitors\n",
> + existing_class->level);
> + __free_mbwu_mon(existing_class, existing_array, num_mbwu_mon);
> + kfree(existing_array);
> + }
> + } else if (evt_id != QOS_L3_OCCUP_EVENT_ID) {
> + pr_debug("Not pre-allocating free-running counters\n");
> + }
> +
> exposed_mon_capable = true;
> + mon->class = class;
> }
>
> static void mpam_resctrl_pick_counters(void)

Thanks,
Gavin