diff mbox series

riscv: Fix local irq restore when flags indicates irq disabled

Message ID 20230725070549.89810-1-luxu.kernel@bytedance.com (mailing list archive)
State Superseded
Headers show
Series riscv: Fix local irq restore when flags indicates irq disabled | expand

Checks

Context Check Description
conchuod/cover_letter success Single patches do not need cover letters
conchuod/tree_selection success Guessed tree name to be fixes at HEAD ab2dbc7acced
conchuod/fixes_present success Fixes tag present in non-next series
conchuod/maintainers_pattern success MAINTAINERS pattern errors before the patch: 4 and now 4
conchuod/verify_signedoff success Signed-off-by tag matches author and committer
conchuod/kdoc success Errors and warnings before: 0 this patch: 0
conchuod/build_rv64_clang_allmodconfig success Errors and warnings before: 2810 this patch: 2810
conchuod/module_param success Was 0 now: 0
conchuod/build_rv64_gcc_allmodconfig fail Errors and warnings before: 15877 this patch: 15878
conchuod/build_rv32_defconfig success Build OK
conchuod/dtb_warn_rv64 success Errors and warnings before: 3 this patch: 3
conchuod/header_inline success No static functions without inline keyword in header files
conchuod/checkpatch success total: 0 errors, 0 warnings, 0 checks, 11 lines checked
conchuod/build_rv64_nommu_k210_defconfig success Build OK
conchuod/verify_fixes success Fixes tag looks correct
conchuod/build_rv64_nommu_virt_defconfig success Build OK

Commit Message

Xu Lu July 25, 2023, 7:05 a.m. UTC
When arch_local_irq_restore() is called with flags indicating irqs
disabled, we need to clear SR_IE bit in CSR_STATUS, whereas current
implementation based on csr_set() function only sets SR_IE bit of
CSR_STATUS when SR_IE bit of flags is high and does nothing when
SR_IE bit of flags is low.

This commit supplies csr clear operation when calling irq restore
function with flags indicating irq disabled.

Fixes: 6d60b6ee0c97 ("RISC-V: Device, timer, IRQs, and the SBI")
Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
---
 arch/riscv/include/asm/irqflags.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

Comments

Palmer Dabbelt Aug. 9, 2023, 6:05 a.m. UTC | #1
On Tue, 25 Jul 2023 00:05:49 PDT (-0700), luxu.kernel@bytedance.com wrote:
> When arch_local_irq_restore() is called with flags indicating irqs
> disabled, we need to clear SR_IE bit in CSR_STATUS, whereas current
> implementation based on csr_set() function only sets SR_IE bit of
> CSR_STATUS when SR_IE bit of flags is high and does nothing when
> SR_IE bit of flags is low.
>
> This commit supplies csr clear operation when calling irq restore
> function with flags indicating irq disabled.
>
> Fixes: 6d60b6ee0c97 ("RISC-V: Device, timer, IRQs, and the SBI")
> Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
> ---
>  arch/riscv/include/asm/irqflags.h | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/arch/riscv/include/asm/irqflags.h b/arch/riscv/include/asm/irqflags.h
> index 08d4d6a5b7e9..7c31fc3c3559 100644
> --- a/arch/riscv/include/asm/irqflags.h
> +++ b/arch/riscv/include/asm/irqflags.h
> @@ -49,7 +49,10 @@ static inline int arch_irqs_disabled(void)
>  /* set interrupt enabled status */
>  static inline void arch_local_irq_restore(unsigned long flags)
>  {
> -	csr_set(CSR_STATUS, flags & SR_IE);
> +	if (flags & SR_IE)
> +		csr_set(CSR_STATUS, SR_IE);
> +	else
> +		csr_clear(CSR_STATUS, SR_IE);

Unless I'm missing something, the original version is correct: 
local_irq_restore() must be paired with a local_irq_save(), so we can 
only get here with interrupts disabled.

>  }
>
>  #endif /* _ASM_RISCV_IRQFLAGS_H */
Xu Lu Aug. 9, 2023, 6:58 a.m. UTC | #2
On Wed, Aug 9, 2023 at 2:05 PM Palmer Dabbelt <palmer@dabbelt.com> wrote:
>
> On Tue, 25 Jul 2023 00:05:49 PDT (-0700), luxu.kernel@bytedance.com wrote:
> > When arch_local_irq_restore() is called with flags indicating irqs
> > disabled, we need to clear SR_IE bit in CSR_STATUS, whereas current
> > implementation based on csr_set() function only sets SR_IE bit of
> > CSR_STATUS when SR_IE bit of flags is high and does nothing when
> > SR_IE bit of flags is low.
> >
> > This commit supplies csr clear operation when calling irq restore
> > function with flags indicating irq disabled.
> >
> > Fixes: 6d60b6ee0c97 ("RISC-V: Device, timer, IRQs, and the SBI")
> > Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
> > ---
> >  arch/riscv/include/asm/irqflags.h | 5 ++++-
> >  1 file changed, 4 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/riscv/include/asm/irqflags.h b/arch/riscv/include/asm/irqflags.h
> > index 08d4d6a5b7e9..7c31fc3c3559 100644
> > --- a/arch/riscv/include/asm/irqflags.h
> > +++ b/arch/riscv/include/asm/irqflags.h
> > @@ -49,7 +49,10 @@ static inline int arch_irqs_disabled(void)
> >  /* set interrupt enabled status */
> >  static inline void arch_local_irq_restore(unsigned long flags)
> >  {
> > -     csr_set(CSR_STATUS, flags & SR_IE);
> > +     if (flags & SR_IE)
> > +             csr_set(CSR_STATUS, SR_IE);
> > +     else
> > +             csr_clear(CSR_STATUS, SR_IE);
>
> Unless I'm missing something, the original version is correct:
> local_irq_restore() must be paired with a local_irq_save(), so we can
> only get here with interrupts disabled.

Yes, it is correct if local_irq_save() is called when irq is enabled before.
The flags returned will be SR_IE. And it is safe to call local_irq_restore()
with flag SR_IE in any case.

However, if local_irq_save() is called when irq is disabled. The SR_IE bit of
flag returned is clear. If some code between local_irq_save() and
local_irq_restore() reenables irq, causing the SR_IE bit of CSR_STATUS
back to 1, then local_irq_restore() can not restore irq status back to disabled.

Here is an example in existing driver (may not belong to riscv arch) in
drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c. The pseudo code
behaves like:

int rtl8723e_hw_init(struct ieee80211_hw *hw)
{
     int err;
     unsigned long flags;
     ...
     local_irq_save_flags(flags);
     local_irq_enable();
     ...
     local_irq_restore(flags);
     ...
     return err;
}


>
> >  }
> >
> >  #endif /* _ASM_RISCV_IRQFLAGS_H */
Xu Lu Aug. 24, 2023, 12:08 p.m. UTC | #3
On Wed, Aug 9, 2023 at 2:58 PM 旭路 <luxu.kernel@bytedance.com> wrote:
>
> On Wed, Aug 9, 2023 at 2:05 PM Palmer Dabbelt <palmer@dabbelt.com> wrote:
> >
> > On Tue, 25 Jul 2023 00:05:49 PDT (-0700), luxu.kernel@bytedance.com wrote:
> > > When arch_local_irq_restore() is called with flags indicating irqs
> > > disabled, we need to clear SR_IE bit in CSR_STATUS, whereas current
> > > implementation based on csr_set() function only sets SR_IE bit of
> > > CSR_STATUS when SR_IE bit of flags is high and does nothing when
> > > SR_IE bit of flags is low.
> > >
> > > This commit supplies csr clear operation when calling irq restore
> > > function with flags indicating irq disabled.
> > >
> > > Fixes: 6d60b6ee0c97 ("RISC-V: Device, timer, IRQs, and the SBI")
> > > Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
> > > ---
> > >  arch/riscv/include/asm/irqflags.h | 5 ++++-
> > >  1 file changed, 4 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/arch/riscv/include/asm/irqflags.h b/arch/riscv/include/asm/irqflags.h
> > > index 08d4d6a5b7e9..7c31fc3c3559 100644
> > > --- a/arch/riscv/include/asm/irqflags.h
> > > +++ b/arch/riscv/include/asm/irqflags.h
> > > @@ -49,7 +49,10 @@ static inline int arch_irqs_disabled(void)
> > >  /* set interrupt enabled status */
> > >  static inline void arch_local_irq_restore(unsigned long flags)
> > >  {
> > > -     csr_set(CSR_STATUS, flags & SR_IE);
> > > +     if (flags & SR_IE)
> > > +             csr_set(CSR_STATUS, SR_IE);
> > > +     else
> > > +             csr_clear(CSR_STATUS, SR_IE);
> >
> > Unless I'm missing something, the original version is correct:
> > local_irq_restore() must be paired with a local_irq_save(), so we can
> > only get here with interrupts disabled.
>
> Yes, it is correct if local_irq_save() is called when irq is enabled before.
> The flags returned will be SR_IE. And it is safe to call local_irq_restore()
> with flag SR_IE in any case.
>
> However, if local_irq_save() is called when irq is disabled. The SR_IE bit of
> flag returned is clear. If some code between local_irq_save() and
> local_irq_restore() reenables irq, causing the SR_IE bit of CSR_STATUS
> back to 1, then local_irq_restore() can not restore irq status back to disabled.
>
> Here is an example in existing driver (may not belong to riscv arch) in
> drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c. The pseudo code
> behaves like:
>
> int rtl8723e_hw_init(struct ieee80211_hw *hw)
> {
>      int err;
>      unsigned long flags;
>      ...
>      local_irq_save_flags(flags);
>      local_irq_enable();
>      ...
>      local_irq_restore(flags);
>      ...
>      return err;
> }
>
>
> >
> > >  }
> > >
> > >  #endif /* _ASM_RISCV_IRQFLAGS_H */

A gentle ping.
Alexandre Ghiti June 18, 2024, 9:45 a.m. UTC | #4
Hi Xu Lu,

On 24/08/2023 14:08, Xu Lu wrote:
> On Wed, Aug 9, 2023 at 2:58 PM 旭路 <luxu.kernel@bytedance.com> wrote:
>> On Wed, Aug 9, 2023 at 2:05 PM Palmer Dabbelt <palmer@dabbelt.com> wrote:
>>> On Tue, 25 Jul 2023 00:05:49 PDT (-0700), luxu.kernel@bytedance.com wrote:
>>>> When arch_local_irq_restore() is called with flags indicating irqs
>>>> disabled, we need to clear SR_IE bit in CSR_STATUS, whereas current
>>>> implementation based on csr_set() function only sets SR_IE bit of
>>>> CSR_STATUS when SR_IE bit of flags is high and does nothing when
>>>> SR_IE bit of flags is low.
>>>>
>>>> This commit supplies csr clear operation when calling irq restore
>>>> function with flags indicating irq disabled.
>>>>
>>>> Fixes: 6d60b6ee0c97 ("RISC-V: Device, timer, IRQs, and the SBI")
>>>> Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
>>>> ---
>>>>   arch/riscv/include/asm/irqflags.h | 5 ++++-
>>>>   1 file changed, 4 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/arch/riscv/include/asm/irqflags.h b/arch/riscv/include/asm/irqflags.h
>>>> index 08d4d6a5b7e9..7c31fc3c3559 100644
>>>> --- a/arch/riscv/include/asm/irqflags.h
>>>> +++ b/arch/riscv/include/asm/irqflags.h
>>>> @@ -49,7 +49,10 @@ static inline int arch_irqs_disabled(void)
>>>>   /* set interrupt enabled status */
>>>>   static inline void arch_local_irq_restore(unsigned long flags)
>>>>   {
>>>> -     csr_set(CSR_STATUS, flags & SR_IE);
>>>> +     if (flags & SR_IE)
>>>> +             csr_set(CSR_STATUS, SR_IE);
>>>> +     else
>>>> +             csr_clear(CSR_STATUS, SR_IE);
>>> Unless I'm missing something, the original version is correct:
>>> local_irq_restore() must be paired with a local_irq_save(), so we can
>>> only get here with interrupts disabled.
>> Yes, it is correct if local_irq_save() is called when irq is enabled before.
>> The flags returned will be SR_IE. And it is safe to call local_irq_restore()
>> with flag SR_IE in any case.
>>
>> However, if local_irq_save() is called when irq is disabled. The SR_IE bit of
>> flag returned is clear. If some code between local_irq_save() and
>> local_irq_restore() reenables irq, causing the SR_IE bit of CSR_STATUS
>> back to 1, then local_irq_restore() can not restore irq status back to disabled.
>>
>> Here is an example in existing driver (may not belong to riscv arch) in
>> drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c. The pseudo code
>> behaves like:
>>
>> int rtl8723e_hw_init(struct ieee80211_hw *hw)
>> {
>>       int err;
>>       unsigned long flags;
>>       ...
>>       local_irq_save_flags(flags);
>>       local_irq_enable();
>>       ...
>>       local_irq_restore(flags);
>>       ...
>>       return err;
>> }
>>
>>
>>>>   }
>>>>
>>>>   #endif /* _ASM_RISCV_IRQFLAGS_H */
> A gentle ping.


This got lost but this is still correct and needed.

Do you think you can respin a new version? Otherwise, I'll do it and 
keep you SoB.

Thanks,

Alex


>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
Xu Lu June 18, 2024, 10 a.m. UTC | #5
Hi Alex,

I will send a new version later today.

Thanks,

Xu Lu

On Tue, Jun 18, 2024 at 5:45 PM Alexandre Ghiti <alex@ghiti.fr> wrote:
>
> Hi Xu Lu,
>
> On 24/08/2023 14:08, Xu Lu wrote:
> > On Wed, Aug 9, 2023 at 2:58 PM 旭路 <luxu.kernel@bytedance.com> wrote:
> >> On Wed, Aug 9, 2023 at 2:05 PM Palmer Dabbelt <palmer@dabbelt.com> wrote:
> >>> On Tue, 25 Jul 2023 00:05:49 PDT (-0700), luxu.kernel@bytedance.com wrote:
> >>>> When arch_local_irq_restore() is called with flags indicating irqs
> >>>> disabled, we need to clear SR_IE bit in CSR_STATUS, whereas current
> >>>> implementation based on csr_set() function only sets SR_IE bit of
> >>>> CSR_STATUS when SR_IE bit of flags is high and does nothing when
> >>>> SR_IE bit of flags is low.
> >>>>
> >>>> This commit supplies csr clear operation when calling irq restore
> >>>> function with flags indicating irq disabled.
> >>>>
> >>>> Fixes: 6d60b6ee0c97 ("RISC-V: Device, timer, IRQs, and the SBI")
> >>>> Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
> >>>> ---
> >>>>   arch/riscv/include/asm/irqflags.h | 5 ++++-
> >>>>   1 file changed, 4 insertions(+), 1 deletion(-)
> >>>>
> >>>> diff --git a/arch/riscv/include/asm/irqflags.h b/arch/riscv/include/asm/irqflags.h
> >>>> index 08d4d6a5b7e9..7c31fc3c3559 100644
> >>>> --- a/arch/riscv/include/asm/irqflags.h
> >>>> +++ b/arch/riscv/include/asm/irqflags.h
> >>>> @@ -49,7 +49,10 @@ static inline int arch_irqs_disabled(void)
> >>>>   /* set interrupt enabled status */
> >>>>   static inline void arch_local_irq_restore(unsigned long flags)
> >>>>   {
> >>>> -     csr_set(CSR_STATUS, flags & SR_IE);
> >>>> +     if (flags & SR_IE)
> >>>> +             csr_set(CSR_STATUS, SR_IE);
> >>>> +     else
> >>>> +             csr_clear(CSR_STATUS, SR_IE);
> >>> Unless I'm missing something, the original version is correct:
> >>> local_irq_restore() must be paired with a local_irq_save(), so we can
> >>> only get here with interrupts disabled.
> >> Yes, it is correct if local_irq_save() is called when irq is enabled before.
> >> The flags returned will be SR_IE. And it is safe to call local_irq_restore()
> >> with flag SR_IE in any case.
> >>
> >> However, if local_irq_save() is called when irq is disabled. The SR_IE bit of
> >> flag returned is clear. If some code between local_irq_save() and
> >> local_irq_restore() reenables irq, causing the SR_IE bit of CSR_STATUS
> >> back to 1, then local_irq_restore() can not restore irq status back to disabled.
> >>
> >> Here is an example in existing driver (may not belong to riscv arch) in
> >> drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c. The pseudo code
> >> behaves like:
> >>
> >> int rtl8723e_hw_init(struct ieee80211_hw *hw)
> >> {
> >>       int err;
> >>       unsigned long flags;
> >>       ...
> >>       local_irq_save_flags(flags);
> >>       local_irq_enable();
> >>       ...
> >>       local_irq_restore(flags);
> >>       ...
> >>       return err;
> >> }
> >>
> >>
> >>>>   }
> >>>>
> >>>>   #endif /* _ASM_RISCV_IRQFLAGS_H */
> > A gentle ping.
>
>
> This got lost but this is still correct and needed.
>
> Do you think you can respin a new version? Otherwise, I'll do it and
> keep you SoB.
>
> Thanks,
>
> Alex
>
>
> >
> > _______________________________________________
> > linux-riscv mailing list
> > linux-riscv@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-riscv
Alexandre Ghiti June 18, 2024, 10:02 a.m. UTC | #6
On 18/06/2024 12:00, Xu Lu wrote:
> Hi Alex,
>
> I will send a new version later today.


Great, thanks, I'll make sure it lands in -fixes.

Sorry it did not get merged sooner.

Thanks,

Alex


>
> Thanks,
>
> Xu Lu
>
> On Tue, Jun 18, 2024 at 5:45 PM Alexandre Ghiti <alex@ghiti.fr> wrote:
>> Hi Xu Lu,
>>
>> On 24/08/2023 14:08, Xu Lu wrote:
>>> On Wed, Aug 9, 2023 at 2:58 PM 旭路 <luxu.kernel@bytedance.com> wrote:
>>>> On Wed, Aug 9, 2023 at 2:05 PM Palmer Dabbelt <palmer@dabbelt.com> wrote:
>>>>> On Tue, 25 Jul 2023 00:05:49 PDT (-0700), luxu.kernel@bytedance.com wrote:
>>>>>> When arch_local_irq_restore() is called with flags indicating irqs
>>>>>> disabled, we need to clear SR_IE bit in CSR_STATUS, whereas current
>>>>>> implementation based on csr_set() function only sets SR_IE bit of
>>>>>> CSR_STATUS when SR_IE bit of flags is high and does nothing when
>>>>>> SR_IE bit of flags is low.
>>>>>>
>>>>>> This commit supplies csr clear operation when calling irq restore
>>>>>> function with flags indicating irq disabled.
>>>>>>
>>>>>> Fixes: 6d60b6ee0c97 ("RISC-V: Device, timer, IRQs, and the SBI")
>>>>>> Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
>>>>>> ---
>>>>>>    arch/riscv/include/asm/irqflags.h | 5 ++++-
>>>>>>    1 file changed, 4 insertions(+), 1 deletion(-)
>>>>>>
>>>>>> diff --git a/arch/riscv/include/asm/irqflags.h b/arch/riscv/include/asm/irqflags.h
>>>>>> index 08d4d6a5b7e9..7c31fc3c3559 100644
>>>>>> --- a/arch/riscv/include/asm/irqflags.h
>>>>>> +++ b/arch/riscv/include/asm/irqflags.h
>>>>>> @@ -49,7 +49,10 @@ static inline int arch_irqs_disabled(void)
>>>>>>    /* set interrupt enabled status */
>>>>>>    static inline void arch_local_irq_restore(unsigned long flags)
>>>>>>    {
>>>>>> -     csr_set(CSR_STATUS, flags & SR_IE);
>>>>>> +     if (flags & SR_IE)
>>>>>> +             csr_set(CSR_STATUS, SR_IE);
>>>>>> +     else
>>>>>> +             csr_clear(CSR_STATUS, SR_IE);
>>>>> Unless I'm missing something, the original version is correct:
>>>>> local_irq_restore() must be paired with a local_irq_save(), so we can
>>>>> only get here with interrupts disabled.
>>>> Yes, it is correct if local_irq_save() is called when irq is enabled before.
>>>> The flags returned will be SR_IE. And it is safe to call local_irq_restore()
>>>> with flag SR_IE in any case.
>>>>
>>>> However, if local_irq_save() is called when irq is disabled. The SR_IE bit of
>>>> flag returned is clear. If some code between local_irq_save() and
>>>> local_irq_restore() reenables irq, causing the SR_IE bit of CSR_STATUS
>>>> back to 1, then local_irq_restore() can not restore irq status back to disabled.
>>>>
>>>> Here is an example in existing driver (may not belong to riscv arch) in
>>>> drivers/net/wireless/realtek/rtlwifi/rtl8723ae/hw.c. The pseudo code
>>>> behaves like:
>>>>
>>>> int rtl8723e_hw_init(struct ieee80211_hw *hw)
>>>> {
>>>>        int err;
>>>>        unsigned long flags;
>>>>        ...
>>>>        local_irq_save_flags(flags);
>>>>        local_irq_enable();
>>>>        ...
>>>>        local_irq_restore(flags);
>>>>        ...
>>>>        return err;
>>>> }
>>>>
>>>>
>>>>>>    }
>>>>>>
>>>>>>    #endif /* _ASM_RISCV_IRQFLAGS_H */
>>> A gentle ping.
>>
>> This got lost but this is still correct and needed.
>>
>> Do you think you can respin a new version? Otherwise, I'll do it and
>> keep you SoB.
>>
>> Thanks,
>>
>> Alex
>>
>>
>>> _______________________________________________
>>> linux-riscv mailing list
>>> linux-riscv@lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-riscv
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
Andrea Parri June 18, 2024, 11:05 a.m. UTC | #7
(merging replies)

> > > However, if local_irq_save() is called when irq is disabled. The SR_IE bit of
> > > flag returned is clear. If some code between local_irq_save() and
> > > local_irq_restore() reenables irq, causing the SR_IE bit of CSR_STATUS
> > > back to 1, then local_irq_restore() can not restore irq status back to disabled.

But doesn't that represent some bogus manipulation of the irq flags? cf.

config DEBUG_IRQFLAGS
	bool "Debug IRQ flag manipulation"
	help
	  Enables checks for potentially unsafe enabling or disabling of
	  interrupts, such as calling raw_local_irq_restore() when interrupts
	  are enabled.

in particular, raw_check_bogus_irq_restore() in raw_local_irq_restore().


> This got lost but this is still correct and needed.

You mean because of the mentioned rtl8723e example? are there other such
instances?  IOW, why do you say that the changes in question are needed?

  Andrea
Alexandre Ghiti June 18, 2024, 11:52 a.m. UTC | #8
Hi Andrea,

On 18/06/2024 13:05, Andrea Parri wrote:
> (merging replies)
>
>>>> However, if local_irq_save() is called when irq is disabled. The SR_IE bit of
>>>> flag returned is clear. If some code between local_irq_save() and
>>>> local_irq_restore() reenables irq, causing the SR_IE bit of CSR_STATUS
>>>> back to 1, then local_irq_restore() can not restore irq status back to disabled.
> But doesn't that represent some bogus manipulation of the irq flags? cf.
>
> config DEBUG_IRQFLAGS
> 	bool "Debug IRQ flag manipulation"
> 	help
> 	  Enables checks for potentially unsafe enabling or disabling of
> 	  interrupts, such as calling raw_local_irq_restore() when interrupts
> 	  are enabled.
>
> in particular, raw_check_bogus_irq_restore() in raw_local_irq_restore().
>
>
>> This got lost but this is still correct and needed.
> You mean because of the mentioned rtl8723e example? are there other such
> instances?  IOW, why do you say that the changes in question are needed?


Simply because the scenario in this driver and I looked at the arm64 
implementation which restores flags unconditionally.

But if that's considered bogus, let's drop this. Sorry Xu for the noise, 
and thanks Andrea for pointing this.

Alex


>
>    Andrea
Xu Lu June 19, 2024, 3:53 a.m. UTC | #9
Hi Alex,

On Tue, Jun 18, 2024 at 7:52 PM Alexandre Ghiti <alex@ghiti.fr> wrote:
>
> Hi Andrea,
>
> On 18/06/2024 13:05, Andrea Parri wrote:
> > (merging replies)
> >
> >>>> However, if local_irq_save() is called when irq is disabled. The SR_IE bit of
> >>>> flag returned is clear. If some code between local_irq_save() and
> >>>> local_irq_restore() reenables irq, causing the SR_IE bit of CSR_STATUS
> >>>> back to 1, then local_irq_restore() can not restore irq status back to disabled.
> > But doesn't that represent some bogus manipulation of the irq flags? cf.
> >
> > config DEBUG_IRQFLAGS
> >       bool "Debug IRQ flag manipulation"
> >       help
> >         Enables checks for potentially unsafe enabling or disabling of
> >         interrupts, such as calling raw_local_irq_restore() when interrupts
> >         are enabled.
> >
> > in particular, raw_check_bogus_irq_restore() in raw_local_irq_restore().
> >
> >
> >> This got lost but this is still correct and needed.
> > You mean because of the mentioned rtl8723e example? are there other such
> > instances?  IOW, why do you say that the changes in question are needed?
>
>
> Simply because the scenario in this driver and I looked at the arm64
> implementation which restores flags unconditionally.

Indeed, ARM64 implementation restores flags unconditionally.

Actually in the beginning I found several drivers use
local_irq_restore after local_irq_enable.
Such drivers include 'scsi/arm/acornscsi.c',
'net/wireless/realtek/rtlwifi/rtlxxx/hw.c', etc.
I wonder whether the semantics of local_irq_restore should be
restoring irq flags unconditionally and thus I submitted this patch.

>
> But if that's considered bogus, let's drop this. Sorry Xu for the noise,
> and thanks Andrea for pointing this.

It's OK if we think this is not a problem. Just ignore this patch.

Thanks!

Xu Lu

>
> Alex
>
>
> >
> >    Andrea
diff mbox series

Patch

diff --git a/arch/riscv/include/asm/irqflags.h b/arch/riscv/include/asm/irqflags.h
index 08d4d6a5b7e9..7c31fc3c3559 100644
--- a/arch/riscv/include/asm/irqflags.h
+++ b/arch/riscv/include/asm/irqflags.h
@@ -49,7 +49,10 @@  static inline int arch_irqs_disabled(void)
 /* set interrupt enabled status */
 static inline void arch_local_irq_restore(unsigned long flags)
 {
-	csr_set(CSR_STATUS, flags & SR_IE);
+	if (flags & SR_IE)
+		csr_set(CSR_STATUS, SR_IE);
+	else
+		csr_clear(CSR_STATUS, SR_IE);
 }
 
 #endif /* _ASM_RISCV_IRQFLAGS_H */