diff mbox series

[3/5] irqchip/riscv-imsic: Use wmb() to order normal writes and IPI writes

Message ID 20250113150933.65121-4-luxu.kernel@bytedance.com (mailing list archive)
State New
Headers show
Series riscv: irqchip: Optimization of interrupt handling | expand

Checks

Context Check Description
conchuod/vmtest-for-next-PR success PR summary
conchuod/patch-3-test-1 success .github/scripts/patches/tests/build_rv32_defconfig.sh took 104.14s
conchuod/patch-3-test-2 success .github/scripts/patches/tests/build_rv64_clang_allmodconfig.sh took 1066.59s
conchuod/patch-3-test-3 success .github/scripts/patches/tests/build_rv64_gcc_allmodconfig.sh took 1260.20s
conchuod/patch-3-test-4 success .github/scripts/patches/tests/build_rv64_nommu_k210_defconfig.sh took 15.92s
conchuod/patch-3-test-5 success .github/scripts/patches/tests/build_rv64_nommu_virt_defconfig.sh took 17.62s
conchuod/patch-3-test-6 success .github/scripts/patches/tests/checkpatch.sh took 0.38s
conchuod/patch-3-test-7 success .github/scripts/patches/tests/dtb_warn_rv64.sh took 36.61s
conchuod/patch-3-test-8 success .github/scripts/patches/tests/header_inline.sh took 0.00s
conchuod/patch-3-test-9 success .github/scripts/patches/tests/kdoc.sh took 0.44s
conchuod/patch-3-test-10 success .github/scripts/patches/tests/module_param.sh took 0.01s
conchuod/patch-3-test-11 success .github/scripts/patches/tests/verify_fixes.sh took 0.00s
conchuod/patch-3-test-12 success .github/scripts/patches/tests/verify_signedoff.sh took 0.02s

Commit Message

Xu Lu Jan. 13, 2025, 3:09 p.m. UTC
During an IPI procedure, we need to ensure all previous write operations
are visible to other CPUs before sending a real IPI. We use wmb() barrier
to ensure this as IMSIC issues IPI via mmio writes.

Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
---
 drivers/irqchip/irq-riscv-imsic-early.c | 6 ++++++
 1 file changed, 6 insertions(+)

Comments

Anup Patel Jan. 14, 2025, 4:34 a.m. UTC | #1
On Mon, Jan 13, 2025 at 8:39 PM Xu Lu <luxu.kernel@bytedance.com> wrote:
>
> During an IPI procedure, we need to ensure all previous write operations
> are visible to other CPUs before sending a real IPI. We use wmb() barrier
> to ensure this as IMSIC issues IPI via mmio writes.
>
> Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
> ---
>  drivers/irqchip/irq-riscv-imsic-early.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/drivers/irqchip/irq-riscv-imsic-early.c b/drivers/irqchip/irq-riscv-imsic-early.c
> index 63097f2bbadf..c6317cb557fb 100644
> --- a/drivers/irqchip/irq-riscv-imsic-early.c
> +++ b/drivers/irqchip/irq-riscv-imsic-early.c
> @@ -29,6 +29,12 @@ static void imsic_ipi_send(unsigned int cpu)
>  {
>         struct imsic_local_config *local = per_cpu_ptr(imsic->global.local, cpu);
>
> +       /*
> +        * Ensure that stores to normal memory are visible to the other CPUs
> +        * before issuing IPI.
> +        */
> +       wmb();
> +

The imsic_ipi_send() is called through ipi_mux_send_mask()
which does smp_mb__after_atomic() before calling so no need
for any barrier here. Also, barriers need to be in-pair so adding
a single barrier at random location is inappropriate.
(Refer, https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/irq/ipi-mux.c?h=v6.13-rc7#n78)

Based on the above, this patch is not needed.

Regards,
Anup
Xu Lu Jan. 14, 2025, 6:39 a.m. UTC | #2
Hi Anup,

I want to ensure when the receiver CPU traps into interrupt, it can
see all memory updates made by the sender before.

The smp_mb__after_atomic() uses 'fence rw, rw' which orders normal
memory reads/writes. The IMSIC write is actually IO writes and is not
ordered by it.

So I worry in extreme cases, the receiver CPU can receive the IPI
first, see no updates to ipi_mux_pcpu->bits and return immediately.
Then this IPI will not be handled until another IPI comes.

Best Regards,

Xu Lu

On Tue, Jan 14, 2025 at 12:34 PM Anup Patel <anup@brainfault.org> wrote:
>
> On Mon, Jan 13, 2025 at 8:39 PM Xu Lu <luxu.kernel@bytedance.com> wrote:
> >
> > During an IPI procedure, we need to ensure all previous write operations
> > are visible to other CPUs before sending a real IPI. We use wmb() barrier
> > to ensure this as IMSIC issues IPI via mmio writes.
> >
> > Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
> > ---
> >  drivers/irqchip/irq-riscv-imsic-early.c | 6 ++++++
> >  1 file changed, 6 insertions(+)
> >
> > diff --git a/drivers/irqchip/irq-riscv-imsic-early.c b/drivers/irqchip/irq-riscv-imsic-early.c
> > index 63097f2bbadf..c6317cb557fb 100644
> > --- a/drivers/irqchip/irq-riscv-imsic-early.c
> > +++ b/drivers/irqchip/irq-riscv-imsic-early.c
> > @@ -29,6 +29,12 @@ static void imsic_ipi_send(unsigned int cpu)
> >  {
> >         struct imsic_local_config *local = per_cpu_ptr(imsic->global.local, cpu);
> >
> > +       /*
> > +        * Ensure that stores to normal memory are visible to the other CPUs
> > +        * before issuing IPI.
> > +        */
> > +       wmb();
> > +
>
> The imsic_ipi_send() is called through ipi_mux_send_mask()
> which does smp_mb__after_atomic() before calling so no need
> for any barrier here. Also, barriers need to be in-pair so adding
> a single barrier at random location is inappropriate.
> (Refer, https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/irq/ipi-mux.c?h=v6.13-rc7#n78)
>
> Based on the above, this patch is not needed.
>
> Regards,
> Anup
Anup Patel Jan. 14, 2025, 8:58 a.m. UTC | #3
On Tue, Jan 14, 2025 at 12:09 PM Xu Lu <luxu.kernel@bytedance.com> wrote:
>
> Hi Anup,
>
> I want to ensure when the receiver CPU traps into interrupt, it can
> see all memory updates made by the sender before.
>
> The smp_mb__after_atomic() uses 'fence rw, rw' which orders normal
> memory reads/writes. The IMSIC write is actually IO writes and is not
> ordered by it.
>
> So I worry in extreme cases, the receiver CPU can receive the IPI
> first, see no updates to ipi_mux_pcpu->bits and return immediately.
> Then this IPI will not be handled until another IPI comes.

Using wmb() is still inappropriate because if you want to simply
ensure IO writes are not ordered before the normal memory writes
then just convert writel_relaxed() to write().

Regards,
Anup

>
> Best Regards,
>
> Xu Lu
>
> On Tue, Jan 14, 2025 at 12:34 PM Anup Patel <anup@brainfault.org> wrote:
> >
> > On Mon, Jan 13, 2025 at 8:39 PM Xu Lu <luxu.kernel@bytedance.com> wrote:
> > >
> > > During an IPI procedure, we need to ensure all previous write operations
> > > are visible to other CPUs before sending a real IPI. We use wmb() barrier
> > > to ensure this as IMSIC issues IPI via mmio writes.
> > >
> > > Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
> > > ---
> > >  drivers/irqchip/irq-riscv-imsic-early.c | 6 ++++++
> > >  1 file changed, 6 insertions(+)
> > >
> > > diff --git a/drivers/irqchip/irq-riscv-imsic-early.c b/drivers/irqchip/irq-riscv-imsic-early.c
> > > index 63097f2bbadf..c6317cb557fb 100644
> > > --- a/drivers/irqchip/irq-riscv-imsic-early.c
> > > +++ b/drivers/irqchip/irq-riscv-imsic-early.c
> > > @@ -29,6 +29,12 @@ static void imsic_ipi_send(unsigned int cpu)
> > >  {
> > >         struct imsic_local_config *local = per_cpu_ptr(imsic->global.local, cpu);
> > >
> > > +       /*
> > > +        * Ensure that stores to normal memory are visible to the other CPUs
> > > +        * before issuing IPI.
> > > +        */
> > > +       wmb();
> > > +
> >
> > The imsic_ipi_send() is called through ipi_mux_send_mask()
> > which does smp_mb__after_atomic() before calling so no need
> > for any barrier here. Also, barriers need to be in-pair so adding
> > a single barrier at random location is inappropriate.
> > (Refer, https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/irq/ipi-mux.c?h=v6.13-rc7#n78)
> >
> > Based on the above, this patch is not needed.
> >
> > Regards,
> > Anup
Xu Lu Jan. 14, 2025, 9:07 a.m. UTC | #4
On Tue, Jan 14, 2025 at 4:59 PM Anup Patel <anup@brainfault.org> wrote:
>
> On Tue, Jan 14, 2025 at 12:09 PM Xu Lu <luxu.kernel@bytedance.com> wrote:
> >
> > Hi Anup,
> >
> > I want to ensure when the receiver CPU traps into interrupt, it can
> > see all memory updates made by the sender before.
> >
> > The smp_mb__after_atomic() uses 'fence rw, rw' which orders normal
> > memory reads/writes. The IMSIC write is actually IO writes and is not
> > ordered by it.
> >
> > So I worry in extreme cases, the receiver CPU can receive the IPI
> > first, see no updates to ipi_mux_pcpu->bits and return immediately.
> > Then this IPI will not be handled until another IPI comes.
>
> Using wmb() is still inappropriate because if you want to simply
> ensure IO writes are not ordered before the normal memory writes
> then just convert writel_relaxed() to write().

Got it. I will use writel() instead.

Thanks!

Xu Lu

>
> Regards,
> Anup
>
> >
> > Best Regards,
> >
> > Xu Lu
> >
> > On Tue, Jan 14, 2025 at 12:34 PM Anup Patel <anup@brainfault.org> wrote:
> > >
> > > On Mon, Jan 13, 2025 at 8:39 PM Xu Lu <luxu.kernel@bytedance.com> wrote:
> > > >
> > > > During an IPI procedure, we need to ensure all previous write operations
> > > > are visible to other CPUs before sending a real IPI. We use wmb() barrier
> > > > to ensure this as IMSIC issues IPI via mmio writes.
> > > >
> > > > Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
> > > > ---
> > > >  drivers/irqchip/irq-riscv-imsic-early.c | 6 ++++++
> > > >  1 file changed, 6 insertions(+)
> > > >
> > > > diff --git a/drivers/irqchip/irq-riscv-imsic-early.c b/drivers/irqchip/irq-riscv-imsic-early.c
> > > > index 63097f2bbadf..c6317cb557fb 100644
> > > > --- a/drivers/irqchip/irq-riscv-imsic-early.c
> > > > +++ b/drivers/irqchip/irq-riscv-imsic-early.c
> > > > @@ -29,6 +29,12 @@ static void imsic_ipi_send(unsigned int cpu)
> > > >  {
> > > >         struct imsic_local_config *local = per_cpu_ptr(imsic->global.local, cpu);
> > > >
> > > > +       /*
> > > > +        * Ensure that stores to normal memory are visible to the other CPUs
> > > > +        * before issuing IPI.
> > > > +        */
> > > > +       wmb();
> > > > +
> > >
> > > The imsic_ipi_send() is called through ipi_mux_send_mask()
> > > which does smp_mb__after_atomic() before calling so no need
> > > for any barrier here. Also, barriers need to be in-pair so adding
> > > a single barrier at random location is inappropriate.
> > > (Refer, https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/irq/ipi-mux.c?h=v6.13-rc7#n78)
> > >
> > > Based on the above, this patch is not needed.
> > >
> > > Regards,
> > > Anup
diff mbox series

Patch

diff --git a/drivers/irqchip/irq-riscv-imsic-early.c b/drivers/irqchip/irq-riscv-imsic-early.c
index 63097f2bbadf..c6317cb557fb 100644
--- a/drivers/irqchip/irq-riscv-imsic-early.c
+++ b/drivers/irqchip/irq-riscv-imsic-early.c
@@ -29,6 +29,12 @@  static void imsic_ipi_send(unsigned int cpu)
 {
 	struct imsic_local_config *local = per_cpu_ptr(imsic->global.local, cpu);
 
+	/*
+	 * Ensure that stores to normal memory are visible to the other CPUs
+	 * before issuing IPI.
+	 */
+	wmb();
+
 	writel_relaxed(IMSIC_IPI_ID, local->msi_va);
 }