diff mbox series

[2/2] irqchip/sifive-plic: Disable S-mode IRQs if running in M-mode

Message ID 20220301005142.3038702-3-Niklas.Cassel@wdc.com (mailing list archive)
State New, archived
Headers show
Series sifive-plic minor improvements | expand

Commit Message

Niklas Cassel March 1, 2022, 12:51 a.m. UTC
From: Niklas Cassel <niklas.cassel@wdc.com>

When detecting a hart context for a privilege mode different from the
current running privilege mode, we simply skip to the next hart context
register.

This means that we never clear the S-mode enable bits when running in
M-mode.

On canaan k210, a bunch of S-mode interrupts are enabled by the bootrom.
These S-mode specific interrupts should never trigger, since we never set
the mie.SEIE bit in the parent interrupt controller (riscv-intc).

However, we will be able to see the mip.SEIE bit set as pending.

This doesn't seem like a good default when CONFIG_RISCV_M_MODE is set,
since in that case we will never enter lower privilege mode (e.g. S-mode).

Let's clear the S-mode enable bits when running the kernel in M-mode, such
that we won't have a interrupt pending bit set, which we will never clear.

Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com>
---
 drivers/irqchip/irq-sifive-plic.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

Comments

Anup Patel March 1, 2022, 4:18 a.m. UTC | #1
On Tue, Mar 1, 2022 at 6:22 AM Niklas Cassel <Niklas.Cassel@wdc.com> wrote:
>
> From: Niklas Cassel <niklas.cassel@wdc.com>
>
> When detecting a hart context for a privilege mode different from the
> current running privilege mode, we simply skip to the next hart context
> register.
>
> This means that we never clear the S-mode enable bits when running in
> M-mode.
>
> On canaan k210, a bunch of S-mode interrupts are enabled by the bootrom.
> These S-mode specific interrupts should never trigger, since we never set
> the mie.SEIE bit in the parent interrupt controller (riscv-intc).
>
> However, we will be able to see the mip.SEIE bit set as pending.
>
> This doesn't seem like a good default when CONFIG_RISCV_M_MODE is set,
> since in that case we will never enter lower privilege mode (e.g. S-mode).
>
> Let's clear the S-mode enable bits when running the kernel in M-mode, such
> that we won't have a interrupt pending bit set, which we will never clear.
>
> Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com>
> ---
>  drivers/irqchip/irq-sifive-plic.c | 13 ++++++++++++-
>  1 file changed, 12 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
> index 211bcb10aa93..46caeb11a114 100644
> --- a/drivers/irqchip/irq-sifive-plic.c
> +++ b/drivers/irqchip/irq-sifive-plic.c
> @@ -326,8 +326,19 @@ static int __init plic_init(struct device_node *node,
>                  * Skip contexts other than external interrupts for our
>                  * privilege level.
>                  */
> -               if (parent.args[0] != RV_IRQ_EXT)
> +               if (parent.args[0] != RV_IRQ_EXT) {
> +                       /* Disable S-mode enable bits if running in M-mode. */
> +                       if (IS_ENABLED(CONFIG_RISCV_M_MODE)) {
> +                               struct plic_handler tmp_handler = {};
> +
> +                               raw_spin_lock_init(&tmp_handler.enable_lock);

Creating a dummy plic_handler over here is a strange work-around.

Please define and use
"void __plic_toggle(void __iomem *enable_base, int hwirq, int enable)"
over here and in the plic_toggle() function.

Regards,
Anup

> +                               tmp_handler.enable_base = priv->regs +
> +                                       ENABLE_BASE + i * ENABLE_PER_HART_CTX;
> +                               for (hwirq = 1; hwirq <= nr_irqs; hwirq++)
> +                                       plic_toggle(&tmp_handler, hwirq, 0);
> +                       }
>                         continue;
> +               }
>
>                 hartid = riscv_of_parent_hartid(parent.np);
>                 if (hartid < 0) {
> --
> 2.35.1
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv
Niklas Cassel March 1, 2022, 8:30 a.m. UTC | #2
On Tue, Mar 01, 2022 at 09:48:20AM +0530, Anup Patel wrote:
> On Tue, Mar 1, 2022 at 6:22 AM Niklas Cassel <Niklas.Cassel@wdc.com> wrote:
> >
> > From: Niklas Cassel <niklas.cassel@wdc.com>
> >
> > When detecting a hart context for a privilege mode different from the
> > current running privilege mode, we simply skip to the next hart context
> > register.
> >
> > This means that we never clear the S-mode enable bits when running in
> > M-mode.
> >
> > On canaan k210, a bunch of S-mode interrupts are enabled by the bootrom.
> > These S-mode specific interrupts should never trigger, since we never set
> > the mie.SEIE bit in the parent interrupt controller (riscv-intc).
> >
> > However, we will be able to see the mip.SEIE bit set as pending.
> >
> > This doesn't seem like a good default when CONFIG_RISCV_M_MODE is set,
> > since in that case we will never enter lower privilege mode (e.g. S-mode).
> >
> > Let's clear the S-mode enable bits when running the kernel in M-mode, such
> > that we won't have a interrupt pending bit set, which we will never clear.
> >
> > Signed-off-by: Niklas Cassel <niklas.cassel@wdc.com>
> > ---
> >  drivers/irqchip/irq-sifive-plic.c | 13 ++++++++++++-
> >  1 file changed, 12 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
> > index 211bcb10aa93..46caeb11a114 100644
> > --- a/drivers/irqchip/irq-sifive-plic.c
> > +++ b/drivers/irqchip/irq-sifive-plic.c
> > @@ -326,8 +326,19 @@ static int __init plic_init(struct device_node *node,
> >                  * Skip contexts other than external interrupts for our
> >                  * privilege level.
> >                  */
> > -               if (parent.args[0] != RV_IRQ_EXT)
> > +               if (parent.args[0] != RV_IRQ_EXT) {
> > +                       /* Disable S-mode enable bits if running in M-mode. */
> > +                       if (IS_ENABLED(CONFIG_RISCV_M_MODE)) {
> > +                               struct plic_handler tmp_handler = {};
> > +
> > +                               raw_spin_lock_init(&tmp_handler.enable_lock);
> 
> Creating a dummy plic_handler over here is a strange work-around.
> 
> Please define and use
> "void __plic_toggle(void __iomem *enable_base, int hwirq, int enable)"
> over here and in the plic_toggle() function.

Hello Anup,

Your suggestion sounds like a cleaner solution, will fix in V2.


Kind regards,
Niklas
diff mbox series

Patch

diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
index 211bcb10aa93..46caeb11a114 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -326,8 +326,19 @@  static int __init plic_init(struct device_node *node,
 		 * Skip contexts other than external interrupts for our
 		 * privilege level.
 		 */
-		if (parent.args[0] != RV_IRQ_EXT)
+		if (parent.args[0] != RV_IRQ_EXT) {
+			/* Disable S-mode enable bits if running in M-mode. */
+			if (IS_ENABLED(CONFIG_RISCV_M_MODE)) {
+				struct plic_handler tmp_handler = {};
+
+				raw_spin_lock_init(&tmp_handler.enable_lock);
+				tmp_handler.enable_base = priv->regs +
+					ENABLE_BASE + i * ENABLE_PER_HART_CTX;
+				for (hwirq = 1; hwirq <= nr_irqs; hwirq++)
+					plic_toggle(&tmp_handler, hwirq, 0);
+			}
 			continue;
+		}
 
 		hartid = riscv_of_parent_hartid(parent.np);
 		if (hartid < 0) {