[v7,10/24] x86/resctrl: Allocate the cleanest CLOSID by searching closid_num_dirty_rmid
Commit Message
MPAM's PMG bits extend its PARTID space, meaning the same PMG value can be
used for different control groups.
This means once a CLOSID is allocated, all its monitoring ids may still be
dirty, and held in limbo.
Instead of allocating the first free CLOSID, on architectures where
CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID is enabled, search
closid_num_dirty_rmid[] to find the cleanest CLOSID.
The CLOSID found is returned to closid_alloc() for the free list
to be updated.
Tested-by: Shaopeng Tan <tan.shaopeng@fujitsu.com>
Tested-by: Peter Newman <peternewman@google.com>
Reviewed-by: Shaopeng Tan <tan.shaopeng@fujitsu.com>
Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: James Morse <james.morse@arm.com>
---
Changes since v4:
* Dropped stale section from comment
Changes since v5:
* Renamed some variables.
No changes since v6
---
arch/x86/kernel/cpu/resctrl/internal.h | 2 ++
arch/x86/kernel/cpu/resctrl/monitor.c | 45 ++++++++++++++++++++++++++
arch/x86/kernel/cpu/resctrl/rdtgroup.c | 19 ++++++++---
3 files changed, 61 insertions(+), 5 deletions(-)
Comments
Hi James,
On 10/25/2023 11:03 AM, James Morse wrote:
> MPAM's PMG bits extend its PARTID space, meaning the same PMG value can be
> used for different control groups.
>
> This means once a CLOSID is allocated, all its monitoring ids may still be
> dirty, and held in limbo.
>
> Instead of allocating the first free CLOSID, on architectures where
> CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID is enabled, search
> closid_num_dirty_rmid[] to find the cleanest CLOSID.
>
> The CLOSID found is returned to closid_alloc() for the free list
> to be updated.
>
> Tested-by: Shaopeng Tan <tan.shaopeng@fujitsu.com>
> Tested-by: Peter Newman <peternewman@google.com>
> Reviewed-by: Shaopeng Tan <tan.shaopeng@fujitsu.com>
> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
> Signed-off-by: James Morse <james.morse@arm.com>
> ---
> Changes since v4:
> * Dropped stale section from comment
>
> Changes since v5:
> * Renamed some variables.
>
> No changes since v6
I use these patch changelogs to determine if I need to look at a
patch for which I already provided a review tag. At first this
patch appears to not deserve a second glance because I already provided a
review tag and the above states "No changes since v6". Unfortunately
this is false. I counted four changes. Now I cannot trust these
"No changes since v6" and I need to dig out v6 to diff patches I already
reviewed to determine if I need to look at them again. False patch
changelogs make a patch series harder to review.
Reinette
Hi James,
On 10/25/23 13:03, James Morse wrote:
> MPAM's PMG bits extend its PARTID space, meaning the same PMG value can be
> used for different control groups.
>
> This means once a CLOSID is allocated, all its monitoring ids may still be
> dirty, and held in limbo.
>
> Instead of allocating the first free CLOSID, on architectures where
> CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID is enabled, search
> closid_num_dirty_rmid[] to find the cleanest CLOSID.
>
> The CLOSID found is returned to closid_alloc() for the free list
> to be updated.
>
> Tested-by: Shaopeng Tan <tan.shaopeng@fujitsu.com>
> Tested-by: Peter Newman <peternewman@google.com>
> Reviewed-by: Shaopeng Tan <tan.shaopeng@fujitsu.com>
> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
> Signed-off-by: James Morse <james.morse@arm.com>
Reviewed-by: Babu Moger <babu.moger@amd.com>
> ---
> Changes since v4:
> * Dropped stale section from comment
>
> Changes since v5:
> * Renamed some variables.
>
> No changes since v6
> ---
> arch/x86/kernel/cpu/resctrl/internal.h | 2 ++
> arch/x86/kernel/cpu/resctrl/monitor.c | 45 ++++++++++++++++++++++++++
> arch/x86/kernel/cpu/resctrl/rdtgroup.c | 19 ++++++++---
> 3 files changed, 61 insertions(+), 5 deletions(-)
>
> diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h
> index 2f1d4f141dab..521afa016b05 100644
> --- a/arch/x86/kernel/cpu/resctrl/internal.h
> +++ b/arch/x86/kernel/cpu/resctrl/internal.h
> @@ -568,5 +568,7 @@ void rdt_domain_reconfigure_cdp(struct rdt_resource *r);
> void __init thread_throttle_mode_init(void);
> void __init mbm_config_rftype_init(const char *config);
> void rdt_staged_configs_clear(void);
> +bool closid_allocated(unsigned int closid);
> +int resctrl_find_cleanest_closid(void);
>
> #endif /* _ASM_X86_RESCTRL_INTERNAL_H */
> diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c
> index 9a07707d3eb4..cf512d4d383e 100644
> --- a/arch/x86/kernel/cpu/resctrl/monitor.c
> +++ b/arch/x86/kernel/cpu/resctrl/monitor.c
> @@ -386,6 +386,51 @@ static struct rmid_entry *resctrl_find_free_rmid(u32 closid)
> return ERR_PTR(-ENOSPC);
> }
>
> +/**
> + * resctrl_find_cleanest_closid() - Find a CLOSID where all the associated
> + * RMID are clean, or the CLOSID that has
> + * the most clean RMID.
> + *
> + * MPAM's equivalent of RMID are per-CLOSID, meaning a freshly allocated CLOSID
> + * may not be able to allocate clean RMID. To avoid this the allocator will
> + * choose the CLOSID with the most clean RMID.
> + *
> + * When the CLOSID and RMID are independent numbers, the first free CLOSID will
> + * be returned.
> + */
> +int resctrl_find_cleanest_closid(void)
> +{
> + u32 cleanest_closid = ~0;
> + int i = 0;
> +
> + lockdep_assert_held(&rdtgroup_mutex);
> +
> + if (!IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID))
> + return -EIO;
> +
> + for (i = 0; i < closids_supported(); i++) {
> + int num_dirty;
> +
> + if (closid_allocated(i))
> + continue;
> +
> + num_dirty = closid_num_dirty_rmid[i];
> + if (num_dirty == 0)
> + return i;
> +
> + if (cleanest_closid == ~0)
> + cleanest_closid = i;
> +
> + if (num_dirty < closid_num_dirty_rmid[cleanest_closid])
> + cleanest_closid = i;
> + }
> +
> + if (cleanest_closid == ~0)
> + return -ENOSPC;
> +
> + return cleanest_closid;
> +}
> +
> /*
> * For MPAM the RMID value is not unique, and has to be considered with
> * the CLOSID. The (CLOSID, RMID) pair is allocated on all domains, which
> diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
> index f6051a3e7262..0b9bd5f0f60d 100644
> --- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
> +++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
> @@ -137,13 +137,22 @@ static void closid_init(void)
>
> static int closid_alloc(void)
> {
> - u32 closid = ffs(closid_free_map);
> + int cleanest_closid;
> + u32 closid;
>
> lockdep_assert_held(&rdtgroup_mutex);
>
> - if (closid == 0)
> - return -ENOSPC;
> - closid--;
> + if (IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID)) {
> + cleanest_closid = resctrl_find_cleanest_closid();
> + if (cleanest_closid < 0)
> + return cleanest_closid;
> + closid = cleanest_closid;
> + } else {
> + closid = ffs(closid_free_map);
> + if (closid == 0)
> + return -ENOSPC;
> + closid--;
> + }
> __clear_bit(closid, &closid_free_map);
>
> return closid;
> @@ -163,7 +172,7 @@ void closid_free(int closid)
> * Return: true if @closid is currently associated with a resource group,
> * false if @closid is free
> */
> -static bool closid_allocated(unsigned int closid)
> +bool closid_allocated(unsigned int closid)
> {
> lockdep_assert_held(&rdtgroup_mutex);
>
On 09/11/2023 17:46, Reinette Chatre wrote:
> Hi James,
>
> On 10/25/2023 11:03 AM, James Morse wrote:
>> MPAM's PMG bits extend its PARTID space, meaning the same PMG value can be
>> used for different control groups.
>>
>> This means once a CLOSID is allocated, all its monitoring ids may still be
>> dirty, and held in limbo.
>>
>> Instead of allocating the first free CLOSID, on architectures where
>> CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID is enabled, search
>> closid_num_dirty_rmid[] to find the cleanest CLOSID.
>>
>> The CLOSID found is returned to closid_alloc() for the free list
>> to be updated.
>>
>> Tested-by: Shaopeng Tan <tan.shaopeng@fujitsu.com>
>> Tested-by: Peter Newman <peternewman@google.com>
>> Reviewed-by: Shaopeng Tan <tan.shaopeng@fujitsu.com>
>> Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
>> Signed-off-by: James Morse <james.morse@arm.com>
>> ---
>> Changes since v4:
>> * Dropped stale section from comment
>>
>> Changes since v5:
>> * Renamed some variables.
>>
>> No changes since v6
>
> I use these patch changelogs to determine if I need to look at a
> patch for which I already provided a review tag. At first this
> patch appears to not deserve a second glance because I already provided a
> review tag and the above states "No changes since v6". Unfortunately
> this is false. I counted four changes. Now I cannot trust these
> "No changes since v6" and I need to dig out v6 to diff patches I already
> reviewed to determine if I need to look at them again. False patch
> changelogs make a patch series harder to review.
Sorry, looks like I applied the changes suggested by Babu, but didn't update this bit of
text that doesn't get committed. I added this 'No changes' text to any patch that didn't
have any entries.
You should be able to rely on people dropping Reviewed-by tags if there are substantial
changes. This is the normal threshold for re-reviewing a patch.
James
Hi Babu,
On 09/11/2023 20:39, Moger, Babu wrote:
> On 10/25/23 13:03, James Morse wrote:
>> MPAM's PMG bits extend its PARTID space, meaning the same PMG value can be
>> used for different control groups.
>>
>> This means once a CLOSID is allocated, all its monitoring ids may still be
>> dirty, and held in limbo.
>>
>> Instead of allocating the first free CLOSID, on architectures where
>> CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID is enabled, search
>> closid_num_dirty_rmid[] to find the cleanest CLOSID.
>>
>> The CLOSID found is returned to closid_alloc() for the free list
>> to be updated.
> Reviewed-by: Babu Moger <babu.moger@amd.com>
Thanks!
James
@@ -568,5 +568,7 @@ void rdt_domain_reconfigure_cdp(struct rdt_resource *r);
void __init thread_throttle_mode_init(void);
void __init mbm_config_rftype_init(const char *config);
void rdt_staged_configs_clear(void);
+bool closid_allocated(unsigned int closid);
+int resctrl_find_cleanest_closid(void);
#endif /* _ASM_X86_RESCTRL_INTERNAL_H */
@@ -386,6 +386,51 @@ static struct rmid_entry *resctrl_find_free_rmid(u32 closid)
return ERR_PTR(-ENOSPC);
}
+/**
+ * resctrl_find_cleanest_closid() - Find a CLOSID where all the associated
+ * RMID are clean, or the CLOSID that has
+ * the most clean RMID.
+ *
+ * MPAM's equivalent of RMID are per-CLOSID, meaning a freshly allocated CLOSID
+ * may not be able to allocate clean RMID. To avoid this the allocator will
+ * choose the CLOSID with the most clean RMID.
+ *
+ * When the CLOSID and RMID are independent numbers, the first free CLOSID will
+ * be returned.
+ */
+int resctrl_find_cleanest_closid(void)
+{
+ u32 cleanest_closid = ~0;
+ int i = 0;
+
+ lockdep_assert_held(&rdtgroup_mutex);
+
+ if (!IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID))
+ return -EIO;
+
+ for (i = 0; i < closids_supported(); i++) {
+ int num_dirty;
+
+ if (closid_allocated(i))
+ continue;
+
+ num_dirty = closid_num_dirty_rmid[i];
+ if (num_dirty == 0)
+ return i;
+
+ if (cleanest_closid == ~0)
+ cleanest_closid = i;
+
+ if (num_dirty < closid_num_dirty_rmid[cleanest_closid])
+ cleanest_closid = i;
+ }
+
+ if (cleanest_closid == ~0)
+ return -ENOSPC;
+
+ return cleanest_closid;
+}
+
/*
* For MPAM the RMID value is not unique, and has to be considered with
* the CLOSID. The (CLOSID, RMID) pair is allocated on all domains, which
@@ -137,13 +137,22 @@ static void closid_init(void)
static int closid_alloc(void)
{
- u32 closid = ffs(closid_free_map);
+ int cleanest_closid;
+ u32 closid;
lockdep_assert_held(&rdtgroup_mutex);
- if (closid == 0)
- return -ENOSPC;
- closid--;
+ if (IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID)) {
+ cleanest_closid = resctrl_find_cleanest_closid();
+ if (cleanest_closid < 0)
+ return cleanest_closid;
+ closid = cleanest_closid;
+ } else {
+ closid = ffs(closid_free_map);
+ if (closid == 0)
+ return -ENOSPC;
+ closid--;
+ }
__clear_bit(closid, &closid_free_map);
return closid;
@@ -163,7 +172,7 @@ void closid_free(int closid)
* Return: true if @closid is currently associated with a resource group,
* false if @closid is free
*/
-static bool closid_allocated(unsigned int closid)
+bool closid_allocated(unsigned int closid)
{
lockdep_assert_held(&rdtgroup_mutex);