diff mbox series

[2/3] lib: sbi_ipi: Process self-IPIs in sbi_ipi_send()

Message ID 20231208212301.3649930-3-samuel.holland@sifive.com
State Accepted
Headers show
Series sbi_ipi bug fixes and optimizations | expand

Commit Message

Samuel Holland Dec. 8, 2023, 9:22 p.m. UTC
An IPI sent to the local hart can be processed directly instead of
triggering the IPI device. This is more efficient, and it avoids a
deadlock when the .sync callback is defined. Since interrupts are
disabled while handling an ecall, the IPI would not get delivered
until the next mret, but sbi_ipi_sync() is called before then.

Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
---

 lib/sbi/sbi_ipi.c | 8 ++++++++
 1 file changed, 8 insertions(+)

Comments

Anup Patel Dec. 10, 2023, 5:12 a.m. UTC | #1
On Sat, Dec 9, 2023 at 2:53 AM Samuel Holland <samuel.holland@sifive.com> wrote:
>
> An IPI sent to the local hart can be processed directly instead of
> triggering the IPI device. This is more efficient, and it avoids a
> deadlock when the .sync callback is defined. Since interrupts are
> disabled while handling an ecall, the IPI would not get delivered
> until the next mret, but sbi_ipi_sync() is called before then.
>
> Signed-off-by: Samuel Holland <samuel.holland@sifive.com>

Looks good to me.

Reviewed-by: Anup Patel <anup@brainfault.org>

Regards,
Anup

> ---
>
>  lib/sbi/sbi_ipi.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/lib/sbi/sbi_ipi.c b/lib/sbi/sbi_ipi.c
> index 1fd24228..ac31cd94 100644
> --- a/lib/sbi/sbi_ipi.c
> +++ b/lib/sbi/sbi_ipi.c
> @@ -60,6 +60,14 @@ static int sbi_ipi_send(struct sbi_scratch *scratch, u32 remote_hartindex,
>                                       remote_hartindex, data);
>                 if (ret != SBI_IPI_UPDATE_SUCCESS)
>                         return ret;
> +       } else if (scratch == remote_scratch) {
> +               /*
> +                * IPI events with an update() callback are expected to return
> +                * SBI_IPI_UPDATE_BREAK for self-IPIs. For other events, check
> +                * for self-IPI and execute the callback directly here.
> +                */
> +               ipi_ops->process(scratch);
> +               return 0;
>         }
>
>         /*
> --
> 2.42.0
>
>
> --
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
Xiang W Dec. 11, 2023, 7:24 a.m. UTC | #2
在 2023-12-08星期五的 13:22 -0800,Samuel Holland写道:
> An IPI sent to the local hart can be processed directly instead of
> triggering the IPI device. This is more efficient, and it avoids a
> deadlock when the .sync callback is defined. Since interrupts are
> disabled while handling an ecall, the IPI would not get delivered
> until the next mret, but sbi_ipi_sync() is called before then.
> 
> Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
> ---
> 
>  lib/sbi/sbi_ipi.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/lib/sbi/sbi_ipi.c b/lib/sbi/sbi_ipi.c
> index 1fd24228..ac31cd94 100644
> --- a/lib/sbi/sbi_ipi.c
> +++ b/lib/sbi/sbi_ipi.c
> @@ -60,6 +60,14 @@ static int sbi_ipi_send(struct sbi_scratch *scratch, u32 remote_hartindex,
>  				      remote_hartindex, data);
>  		if (ret != SBI_IPI_UPDATE_SUCCESS)
>  			return ret;
> +	} else if (scratch == remote_scratch) {
> +		/*
> +		 * IPI events with an update() callback are expected to return
> +		 * SBI_IPI_UPDATE_BREAK for self-IPIs. For other events, check
> +		 * for self-IPI and execute the callback directly here.
> +		 */
> +		ipi_ops->process(scratch);
> +		return 0;
This modification will affect sbi_tlb.c. tlb_update has already called
tinfo->local_fn(tinfo) when returning SBI_IPI_UPDATE_BREAK. And the 
synchronization variable is only updated when SBI_IPI_UPDATE_SUCCESS is 
returned. If tlb_process is called, the synchronization variable will be 
affected.

Regards,
Xiang W

>  	}
>  
>  	/*
> -- 
> 2.42.0
> 
>
Xiang W Dec. 11, 2023, 7:34 a.m. UTC | #3
在 2023-12-11星期一的 15:24 +0800,Xiang W写道:
> 在 2023-12-08星期五的 13:22 -0800,Samuel Holland写道:
> > An IPI sent to the local hart can be processed directly instead of
> > triggering the IPI device. This is more efficient, and it avoids a
> > deadlock when the .sync callback is defined. Since interrupts are
> > disabled while handling an ecall, the IPI would not get delivered
> > until the next mret, but sbi_ipi_sync() is called before then.
> > 
> > Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
> > ---
> > 
> >  lib/sbi/sbi_ipi.c | 8 ++++++++
> >  1 file changed, 8 insertions(+)
> > 
> > diff --git a/lib/sbi/sbi_ipi.c b/lib/sbi/sbi_ipi.c
> > index 1fd24228..ac31cd94 100644
> > --- a/lib/sbi/sbi_ipi.c
> > +++ b/lib/sbi/sbi_ipi.c
> > @@ -60,6 +60,14 @@ static int sbi_ipi_send(struct sbi_scratch *scratch, u32 remote_hartindex,
> >  				      remote_hartindex, data);
> >  		if (ret != SBI_IPI_UPDATE_SUCCESS)
> >  			return ret;
> > +	} else if (scratch == remote_scratch) {
> > +		/*
> > +		 * IPI events with an update() callback are expected to return
> > +		 * SBI_IPI_UPDATE_BREAK for self-IPIs. For other events, check
> > +		 * for self-IPI and execute the callback directly here.
> > +		 */
> > +		ipi_ops->process(scratch);
> > +		return 0;
> This modification will affect sbi_tlb.c. tlb_update has already called
> tinfo->local_fn(tinfo) when returning SBI_IPI_UPDATE_BREAK. And the 
> synchronization variable is only updated when SBI_IPI_UPDATE_SUCCESS is 
> returned. If tlb_process is called, the synchronization variable will be 
> affected.
> 
> Regards,
> Xiang W

I made a mistake! I thought ipi_ops->process(scratch) was called when 
SBI_IPI_UPDATE_BREAK was returned. I ignored that there is no ipi_ops->update
when it doesn't exist.

Look good to me.

Reviewed-by: Xiang W <wxjstz@126.com>
> 
> >  	}
> >  
> >  	/*
> > -- 
> > 2.42.0
> > 
> > 
> 
>
Anup Patel Dec. 18, 2023, 5:15 p.m. UTC | #4
On Sat, Dec 9, 2023 at 2:53 AM Samuel Holland <samuel.holland@sifive.com> wrote:
>
> An IPI sent to the local hart can be processed directly instead of
> triggering the IPI device. This is more efficient, and it avoids a
> deadlock when the .sync callback is defined. Since interrupts are
> disabled while handling an ecall, the IPI would not get delivered
> until the next mret, but sbi_ipi_sync() is called before then.
>
> Signed-off-by: Samuel Holland <samuel.holland@sifive.com>

Applied this patch to the riscv/opensbi repo.

Thanks,
Anup


> ---
>
>  lib/sbi/sbi_ipi.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/lib/sbi/sbi_ipi.c b/lib/sbi/sbi_ipi.c
> index 1fd24228..ac31cd94 100644
> --- a/lib/sbi/sbi_ipi.c
> +++ b/lib/sbi/sbi_ipi.c
> @@ -60,6 +60,14 @@ static int sbi_ipi_send(struct sbi_scratch *scratch, u32 remote_hartindex,
>                                       remote_hartindex, data);
>                 if (ret != SBI_IPI_UPDATE_SUCCESS)
>                         return ret;
> +       } else if (scratch == remote_scratch) {
> +               /*
> +                * IPI events with an update() callback are expected to return
> +                * SBI_IPI_UPDATE_BREAK for self-IPIs. For other events, check
> +                * for self-IPI and execute the callback directly here.
> +                */
> +               ipi_ops->process(scratch);
> +               return 0;
>         }
>
>         /*
> --
> 2.42.0
>
>
> --
> opensbi mailing list
> opensbi@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
diff mbox series

Patch

diff --git a/lib/sbi/sbi_ipi.c b/lib/sbi/sbi_ipi.c
index 1fd24228..ac31cd94 100644
--- a/lib/sbi/sbi_ipi.c
+++ b/lib/sbi/sbi_ipi.c
@@ -60,6 +60,14 @@  static int sbi_ipi_send(struct sbi_scratch *scratch, u32 remote_hartindex,
 				      remote_hartindex, data);
 		if (ret != SBI_IPI_UPDATE_SUCCESS)
 			return ret;
+	} else if (scratch == remote_scratch) {
+		/*
+		 * IPI events with an update() callback are expected to return
+		 * SBI_IPI_UPDATE_BREAK for self-IPIs. For other events, check
+		 * for self-IPI and execute the callback directly here.
+		 */
+		ipi_ops->process(scratch);
+		return 0;
 	}
 
 	/*