[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <abffe9bc-4c2b-4d44-b521-f138179033e3@intel.com>
Date: Mon, 16 Sep 2024 09:56:01 -0700
From: Reinette Chatre <reinette.chatre@...el.com>
To: Martin Kletzander <nert.pinx@...il.com>, Fenghua Yu
<fenghua.yu@...el.com>, Thomas Gleixner <tglx@...utronix.de>, Ingo Molnar
<mingo@...hat.com>, Borislav Petkov <bp@...en8.de>, Dave Hansen
<dave.hansen@...ux.intel.com>, <x86@...nel.org>, "H. Peter Anvin"
<hpa@...or.com>, <linux-kernel@...r.kernel.org>
Subject: Re: [PATCH v2] x86/resctrl: Avoid overflow in MB settings in
bw_validate()
Hi Martin,
On 9/16/24 6:07 AM, Martin Kletzander wrote:
> When resctrl is mounted with the "mba_MBps" option the default (maximum)
> bandwidth is the maximum unsigned value for the type. However when
> using the same value that already exists in the schemata file it is then
> rounded up to the bandwidth granularity and overflows to a small number
> instead, making it difficult to reset memory bandwidth allocation value
> back to its default.
>
> Since the granularity and minimum bandwidth are not used when the
> software controller is used (resctrl is mounted with the "mba_MBps"),
> skip the rounding up as well and return early from bw_validate().
Thank you very much for finding the issue and proposing a fix.
>
> Signed-off-by: Martin Kletzander <nert.pinx@...il.com>
> ---
> Changes in v2:
> - actually save the value in the output parameter @data
>
> arch/x86/kernel/cpu/resctrl/ctrlmondata.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
> index 50fa1fe9a073..702b1a372e9c 100644
> --- a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
> +++ b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
> @@ -48,8 +48,13 @@ static bool bw_validate(char *buf, unsigned long *data, struct rdt_resource *r)
> return false;
> }
>
> - if ((bw < r->membw.min_bw || bw > r->default_ctrl) &&
> - !is_mba_sc(r)) {
> + /* Nothing else to do if software controller is enabled */
> + if (is_mba_sc(r)) {
> + *data = bw;
> + return true;
While this would fix the scenario tested I do not believe this fully addresses the
overflow issue. As I understand the test wrote U32_MAX to the schemata file,
which triggered the overflow because of the rounding and is fixed by this patch. Looks like,
after this patch, writing "U32_MAX + 1" will still trigger the overflow.
The overflow appears to result from some inconsistent type use and not using
appropriate parsing API that is able to detect overflow.
How about something like below:
diff --git a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
index 50fa1fe9a073..53defc5a6784 100644
--- a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
+++ b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
@@ -29,10 +29,10 @@
* hardware. The allocated bandwidth percentage is rounded to the next
* control step available on the hardware.
*/
-static bool bw_validate(char *buf, unsigned long *data, struct rdt_resource *r)
+static bool bw_validate(char *buf, u32 *data, struct rdt_resource *r)
{
- unsigned long bw;
int ret;
+ u32 bw;
/*
* Only linear delay values is supported for current Intel SKUs.
@@ -42,14 +42,19 @@ static bool bw_validate(char *buf, unsigned long *data, struct rdt_resource *r)
return false;
}
- ret = kstrtoul(buf, 10, &bw);
+ ret = kstrtou32(buf, 10, &bw);
if (ret) {
- rdt_last_cmd_printf("Non-decimal digit in MB value %s\n", buf);
+ rdt_last_cmd_printf("Invalid MB value %s\n", buf);
return false;
}
- if ((bw < r->membw.min_bw || bw > r->default_ctrl) &&
- !is_mba_sc(r)) {
+ /* Nothing else to do if software controller is enabled. */
+ if (is_mba_sc(r)) {
+ *data = bw;
+ return true;
+ }
+
+ if (bw < r->membw.min_bw || bw > r->default_ctrl) {
rdt_last_cmd_printf("MB value %ld out of range [%d,%d]\n", bw,
r->membw.min_bw, r->default_ctrl);
return false;
@@ -65,7 +70,7 @@ int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s,
struct resctrl_staged_config *cfg;
u32 closid = data->rdtgrp->closid;
struct rdt_resource *r = s->res;
- unsigned long bw_val;
+ u32 bw_val;
cfg = &d->staged_config[s->conf_type];
if (cfg->have_new_ctrl) {
> + }
> +
> + if (bw < r->membw.min_bw || bw > r->default_ctrl) {
> rdt_last_cmd_printf("MB value %ld out of range [%d,%d]\n", bw,
> r->membw.min_bw, r->default_ctrl);
> return false;
Reinette
Powered by blists - more mailing lists