diff mbox series

[2/2] drivers/perf: riscv: Do not allow invalid raw event config

Message ID 20241209-pmu_event_fixes-v1-2-d9525e90072c@rivosinc.com (mailing list archive)
State Superseded
Headers show
Series SBI PMU event related fixes | expand

Checks

Context Check Description
conchuod/vmtest-for-next-PR fail PR summary
conchuod/patch-2-test-1 success .github/scripts/patches/tests/build_rv32_defconfig.sh took 169.15s
conchuod/patch-2-test-2 success .github/scripts/patches/tests/build_rv64_clang_allmodconfig.sh took 1086.08s
conchuod/patch-2-test-3 success .github/scripts/patches/tests/build_rv64_gcc_allmodconfig.sh took 1261.30s
conchuod/patch-2-test-4 success .github/scripts/patches/tests/build_rv64_nommu_k210_defconfig.sh took 66.26s
conchuod/patch-2-test-5 success .github/scripts/patches/tests/build_rv64_nommu_virt_defconfig.sh took 67.62s
conchuod/patch-2-test-6 success .github/scripts/patches/tests/checkpatch.sh took 0.40s
conchuod/patch-2-test-7 success .github/scripts/patches/tests/dtb_warn_rv64.sh took 41.15s
conchuod/patch-2-test-8 success .github/scripts/patches/tests/header_inline.sh took 0.00s
conchuod/patch-2-test-9 success .github/scripts/patches/tests/kdoc.sh took 0.52s
conchuod/patch-2-test-10 success .github/scripts/patches/tests/module_param.sh took 0.01s
conchuod/patch-2-test-11 success .github/scripts/patches/tests/verify_fixes.sh took 0.00s
conchuod/patch-2-test-12 success .github/scripts/patches/tests/verify_signedoff.sh took 0.02s

Commit Message

Atish Patra Dec. 10, 2024, 12:04 a.m. UTC
The SBI specification allows only lower 48bits of hpmeventX to be
configured via SBI PMU. Currently, the driver masks of the higher
bits but doesn't return an error. This will lead to an additional
SBI call for config matching which should return for an invalid
event error in most of the cases.

However, if a platform(i.e Rocket and sifive cores) implements a
bitmap of all bits in the event encoding this will lead to an
incorrect event being programmed leading to user confusion.

Report the error to the user if higher bits are set during the
event mapping itself to avoid the confusion and save an additional
SBI call.

Suggested-by: Samuel Holland <samuel.holland@sifive.com>
Signed-off-by: Atish Patra <atishp@rivosinc.com>
---
 drivers/perf/riscv_pmu_sbi.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

Comments

Palmer Dabbelt Dec. 11, 2024, 7:46 p.m. UTC | #1
On Mon, 09 Dec 2024 16:04:46 PST (-0800), Atish Patra wrote:
> The SBI specification allows only lower 48bits of hpmeventX to be
> configured via SBI PMU. Currently, the driver masks of the higher
> bits but doesn't return an error. This will lead to an additional
> SBI call for config matching which should return for an invalid
> event error in most of the cases.
>
> However, if a platform(i.e Rocket and sifive cores) implements a
> bitmap of all bits in the event encoding this will lead to an
> incorrect event being programmed leading to user confusion.
>
> Report the error to the user if higher bits are set during the
> event mapping itself to avoid the confusion and save an additional
> SBI call.
>
> Suggested-by: Samuel Holland <samuel.holland@sifive.com>
> Signed-off-by: Atish Patra <atishp@rivosinc.com>
> ---
>  drivers/perf/riscv_pmu_sbi.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
> index 3473ba02abf3..fb6eda90f771 100644
> --- a/drivers/perf/riscv_pmu_sbi.c
> +++ b/drivers/perf/riscv_pmu_sbi.c
> @@ -507,7 +507,7 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
>  {
>  	u32 type = event->attr.type;
>  	u64 config = event->attr.config;
> -	int ret;
> +	int ret = -ENOENT;
>
>  	/*
>  	 * Ensure we are finished checking standard hardware events for
> @@ -536,8 +536,11 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
>
>  		switch (config >> 62) {
>  		case 0:
> -			ret = RISCV_PMU_RAW_EVENT_IDX;
> -			*econfig = config & RISCV_PMU_RAW_EVENT_MASK;
> +			/* Return error any bits [48-63] is set  as it is not allowed by the spec */
> +			if (!(config & ~RISCV_PMU_RAW_EVENT_MASK)) {
> +				*econfig = config & RISCV_PMU_RAW_EVENT_MASK;
> +				ret = RISCV_PMU_RAW_EVENT_IDX;
> +			}
>  			break;
>  		case 2:
>  			ret = (config & 0xFFFF) | (SBI_PMU_EVENT_TYPE_FW << 16);
> @@ -554,7 +557,6 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
>  		}
>  		break;
>  	default:
> -		ret = -ENOENT;
>  		break;
>  	}

This doesn't have a Fixes, is it 

    Fixes: f0c9363db2dd ("perf/riscv-sbi: Add platform specific firmware event handling")

?
Atish Patra Dec. 11, 2024, 9:10 p.m. UTC | #2
On Wed, Dec 11, 2024 at 11:46 AM Palmer Dabbelt <palmer@dabbelt.com> wrote:
>
> On Mon, 09 Dec 2024 16:04:46 PST (-0800), Atish Patra wrote:
> > The SBI specification allows only lower 48bits of hpmeventX to be
> > configured via SBI PMU. Currently, the driver masks of the higher
> > bits but doesn't return an error. This will lead to an additional
> > SBI call for config matching which should return for an invalid
> > event error in most of the cases.
> >
> > However, if a platform(i.e Rocket and sifive cores) implements a
> > bitmap of all bits in the event encoding this will lead to an
> > incorrect event being programmed leading to user confusion.
> >
> > Report the error to the user if higher bits are set during the
> > event mapping itself to avoid the confusion and save an additional
> > SBI call.
> >
> > Suggested-by: Samuel Holland <samuel.holland@sifive.com>
> > Signed-off-by: Atish Patra <atishp@rivosinc.com>
> > ---
> >  drivers/perf/riscv_pmu_sbi.c | 10 ++++++----
> >  1 file changed, 6 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
> > index 3473ba02abf3..fb6eda90f771 100644
> > --- a/drivers/perf/riscv_pmu_sbi.c
> > +++ b/drivers/perf/riscv_pmu_sbi.c
> > @@ -507,7 +507,7 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
> >  {
> >       u32 type = event->attr.type;
> >       u64 config = event->attr.config;
> > -     int ret;
> > +     int ret = -ENOENT;
> >
> >       /*
> >        * Ensure we are finished checking standard hardware events for
> > @@ -536,8 +536,11 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
> >
> >               switch (config >> 62) {
> >               case 0:
> > -                     ret = RISCV_PMU_RAW_EVENT_IDX;
> > -                     *econfig = config & RISCV_PMU_RAW_EVENT_MASK;
> > +                     /* Return error any bits [48-63] is set  as it is not allowed by the spec */
> > +                     if (!(config & ~RISCV_PMU_RAW_EVENT_MASK)) {
> > +                             *econfig = config & RISCV_PMU_RAW_EVENT_MASK;
> > +                             ret = RISCV_PMU_RAW_EVENT_IDX;
> > +                     }
> >                       break;
> >               case 2:
> >                       ret = (config & 0xFFFF) | (SBI_PMU_EVENT_TYPE_FW << 16);
> > @@ -554,7 +557,6 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
> >               }
> >               break;
> >       default:
> > -             ret = -ENOENT;
> >               break;
> >       }
>
> This doesn't have a Fixes, is it
>
>     Fixes: f0c9363db2dd ("perf/riscv-sbi: Add platform specific firmware event handling")
>

I was not sure if a Fixes tag was worth it as the current
behavior(masking off the higher bits) is there from the beginning of
the driver.
perf tool throws a warning as well if a user tries to set any of the
upper 16 bits as event attributes is set to 0-47.

If it should be backported, this is the correct fixes tag.
Fixes: e9991434596f ("RISC-V: Add perf platform driver based on SBI
PMU extension")


> ?
Samuel Holland Dec. 12, 2024, 4:06 a.m. UTC | #3
Hi Atish,

On 2024-12-11 3:10 PM, Atish Kumar Patra wrote:
> On Wed, Dec 11, 2024 at 11:46 AM Palmer Dabbelt <palmer@dabbelt.com> wrote:
>>
>> On Mon, 09 Dec 2024 16:04:46 PST (-0800), Atish Patra wrote:
>>> The SBI specification allows only lower 48bits of hpmeventX to be
>>> configured via SBI PMU. Currently, the driver masks of the higher
>>> bits but doesn't return an error. This will lead to an additional
>>> SBI call for config matching which should return for an invalid
>>> event error in most of the cases.
>>>
>>> However, if a platform(i.e Rocket and sifive cores) implements a
>>> bitmap of all bits in the event encoding this will lead to an
>>> incorrect event being programmed leading to user confusion.
>>>
>>> Report the error to the user if higher bits are set during the
>>> event mapping itself to avoid the confusion and save an additional
>>> SBI call.
>>>
>>> Suggested-by: Samuel Holland <samuel.holland@sifive.com>
>>> Signed-off-by: Atish Patra <atishp@rivosinc.com>
>>> ---
>>>  drivers/perf/riscv_pmu_sbi.c | 10 ++++++----
>>>  1 file changed, 6 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
>>> index 3473ba02abf3..fb6eda90f771 100644
>>> --- a/drivers/perf/riscv_pmu_sbi.c
>>> +++ b/drivers/perf/riscv_pmu_sbi.c
>>> @@ -507,7 +507,7 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
>>>  {
>>>       u32 type = event->attr.type;
>>>       u64 config = event->attr.config;
>>> -     int ret;
>>> +     int ret = -ENOENT;
>>>
>>>       /*
>>>        * Ensure we are finished checking standard hardware events for
>>> @@ -536,8 +536,11 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
>>>
>>>               switch (config >> 62) {
>>>               case 0:
>>> -                     ret = RISCV_PMU_RAW_EVENT_IDX;
>>> -                     *econfig = config & RISCV_PMU_RAW_EVENT_MASK;
>>> +                     /* Return error any bits [48-63] is set  as it is not allowed by the spec */
>>> +                     if (!(config & ~RISCV_PMU_RAW_EVENT_MASK)) {
>>> +                             *econfig = config & RISCV_PMU_RAW_EVENT_MASK;
>>> +                             ret = RISCV_PMU_RAW_EVENT_IDX;
>>> +                     }
>>>                       break;
>>>               case 2:
>>>                       ret = (config & 0xFFFF) | (SBI_PMU_EVENT_TYPE_FW << 16);
>>> @@ -554,7 +557,6 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
>>>               }
>>>               break;
>>>       default:
>>> -             ret = -ENOENT;
>>>               break;
>>>       }
>>
>> This doesn't have a Fixes, is it
>>
>>     Fixes: f0c9363db2dd ("perf/riscv-sbi: Add platform specific firmware event handling")
>>
> 
> I was not sure if a Fixes tag was worth it as the current
> behavior(masking off the higher bits) is there from the beginning of
> the driver.
> perf tool throws a warning as well if a user tries to set any of the
> upper 16 bits as event attributes is set to 0-47.
> 
> If it should be backported, this is the correct fixes tag.
> Fixes: e9991434596f ("RISC-V: Add perf platform driver based on SBI
> PMU extension")

I would agree the masking isn't a real issue before changing the event attribute
from 48 to 56 bits wide. However, this patch also does a drive-by fix of a
different bug introduced by f0c9363db2dd: there is no "case 1" or default case,
so the function would return an uninitialized value if the high bits are 01.
Maybe that should be a separate patch, with a Fixes tag?

Regards,
Samuel
Atish Patra Dec. 12, 2024, 7:26 p.m. UTC | #4
On Wed, Dec 11, 2024 at 8:06 PM Samuel Holland
<samuel.holland@sifive.com> wrote:
>
> Hi Atish,
>
> On 2024-12-11 3:10 PM, Atish Kumar Patra wrote:
> > On Wed, Dec 11, 2024 at 11:46 AM Palmer Dabbelt <palmer@dabbelt.com> wrote:
> >>
> >> On Mon, 09 Dec 2024 16:04:46 PST (-0800), Atish Patra wrote:
> >>> The SBI specification allows only lower 48bits of hpmeventX to be
> >>> configured via SBI PMU. Currently, the driver masks of the higher
> >>> bits but doesn't return an error. This will lead to an additional
> >>> SBI call for config matching which should return for an invalid
> >>> event error in most of the cases.
> >>>
> >>> However, if a platform(i.e Rocket and sifive cores) implements a
> >>> bitmap of all bits in the event encoding this will lead to an
> >>> incorrect event being programmed leading to user confusion.
> >>>
> >>> Report the error to the user if higher bits are set during the
> >>> event mapping itself to avoid the confusion and save an additional
> >>> SBI call.
> >>>
> >>> Suggested-by: Samuel Holland <samuel.holland@sifive.com>
> >>> Signed-off-by: Atish Patra <atishp@rivosinc.com>
> >>> ---
> >>>  drivers/perf/riscv_pmu_sbi.c | 10 ++++++----
> >>>  1 file changed, 6 insertions(+), 4 deletions(-)
> >>>
> >>> diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
> >>> index 3473ba02abf3..fb6eda90f771 100644
> >>> --- a/drivers/perf/riscv_pmu_sbi.c
> >>> +++ b/drivers/perf/riscv_pmu_sbi.c
> >>> @@ -507,7 +507,7 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
> >>>  {
> >>>       u32 type = event->attr.type;
> >>>       u64 config = event->attr.config;
> >>> -     int ret;
> >>> +     int ret = -ENOENT;
> >>>
> >>>       /*
> >>>        * Ensure we are finished checking standard hardware events for
> >>> @@ -536,8 +536,11 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
> >>>
> >>>               switch (config >> 62) {
> >>>               case 0:
> >>> -                     ret = RISCV_PMU_RAW_EVENT_IDX;
> >>> -                     *econfig = config & RISCV_PMU_RAW_EVENT_MASK;
> >>> +                     /* Return error any bits [48-63] is set  as it is not allowed by the spec */
> >>> +                     if (!(config & ~RISCV_PMU_RAW_EVENT_MASK)) {
> >>> +                             *econfig = config & RISCV_PMU_RAW_EVENT_MASK;
> >>> +                             ret = RISCV_PMU_RAW_EVENT_IDX;
> >>> +                     }
> >>>                       break;
> >>>               case 2:
> >>>                       ret = (config & 0xFFFF) | (SBI_PMU_EVENT_TYPE_FW << 16);
> >>> @@ -554,7 +557,6 @@ static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
> >>>               }
> >>>               break;
> >>>       default:
> >>> -             ret = -ENOENT;
> >>>               break;
> >>>       }
> >>
> >> This doesn't have a Fixes, is it
> >>
> >>     Fixes: f0c9363db2dd ("perf/riscv-sbi: Add platform specific firmware event handling")
> >>
> >
> > I was not sure if a Fixes tag was worth it as the current
> > behavior(masking off the higher bits) is there from the beginning of
> > the driver.
> > perf tool throws a warning as well if a user tries to set any of the
> > upper 16 bits as event attributes is set to 0-47.
> >
> > If it should be backported, this is the correct fixes tag.
> > Fixes: e9991434596f ("RISC-V: Add perf platform driver based on SBI
> > PMU extension")
>
> I would agree the masking isn't a real issue before changing the event attribute
> from 48 to 56 bits wide. However, this patch also does a drive-by fix of a
> different bug introduced by f0c9363db2dd: there is no "case 1" or default case,
> so the function would return an uninitialized value if the high bits are 01.
> Maybe that should be a separate patch, with a Fixes tag?
>

Good eye ;). I will split this one into two with a fixes tag for the
switch case.

> Regards,
> Samuel
>
diff mbox series

Patch

diff --git a/drivers/perf/riscv_pmu_sbi.c b/drivers/perf/riscv_pmu_sbi.c
index 3473ba02abf3..fb6eda90f771 100644
--- a/drivers/perf/riscv_pmu_sbi.c
+++ b/drivers/perf/riscv_pmu_sbi.c
@@ -507,7 +507,7 @@  static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
 {
 	u32 type = event->attr.type;
 	u64 config = event->attr.config;
-	int ret;
+	int ret = -ENOENT;
 
 	/*
 	 * Ensure we are finished checking standard hardware events for
@@ -536,8 +536,11 @@  static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
 
 		switch (config >> 62) {
 		case 0:
-			ret = RISCV_PMU_RAW_EVENT_IDX;
-			*econfig = config & RISCV_PMU_RAW_EVENT_MASK;
+			/* Return error any bits [48-63] is set  as it is not allowed by the spec */
+			if (!(config & ~RISCV_PMU_RAW_EVENT_MASK)) {
+				*econfig = config & RISCV_PMU_RAW_EVENT_MASK;
+				ret = RISCV_PMU_RAW_EVENT_IDX;
+			}
 			break;
 		case 2:
 			ret = (config & 0xFFFF) | (SBI_PMU_EVENT_TYPE_FW << 16);
@@ -554,7 +557,6 @@  static int pmu_sbi_event_map(struct perf_event *event, u64 *econfig)
 		}
 		break;
 	default:
-		ret = -ENOENT;
 		break;
 	}