[RFC PATCH 1/2] lib: sbi: introduce INTC abstraction for wired interrupts
Raymond Mao
raymondmaoca at gmail.com
Fri Jan 30 07:00:47 PST 2026
Hi Anup,
On Fri, Jan 30, 2026 at 2:48 AM Anup Patel <anup at brainfault.org> wrote:
>
> On Tue, Jan 27, 2026 at 8:54 PM Raymond Mao <raymondmaoca at gmail.com> wrote:
> >
> > From: Raymond Mao <raymond.mao at riscstar.com>
> >
> > Add a wired interrupt-controller (INTC) abstraction to OpenSBI.
> > This introduces a small provider interface based on
> > claim/complete/mask/unmak semantics, allowing to register a wired
> > interrupt controller as a provider.
> > Plus, add virtual IRQ number mapping to avoid exposure of hwirq.
> >
> > Signed-off-by: Raymond Mao <raymond.mao at riscstar.com>
> > ---
> > sbi_intc.h | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 99 insertions(+)
> > create mode 100644 sbi_intc.h
> >
> > diff --git a/sbi_intc.h b/sbi_intc.h
> > new file mode 100644
> > index 00000000..f51974c9
> > --- /dev/null
> > +++ b/sbi_intc.h
> > @@ -0,0 +1,99 @@
> > +/*
> > + * SPDX-License-Identifier: BSD-2-Clause
> > + *
> > + * Copyright (c) 2026 RISCstar Solutions Corporation.
> > + *
> > + * Author: Raymond Mao <raymond.mao at riscstar.com>
> > + */
> > +
> > +#ifndef __SBI_INTC_H__
> > +#define __SBI_INTC_H__
> > +
> > +#include <sbi/sbi_types.h>
> > +
> > +/* Handler for a specified IRQ number */
> > +typedef int (*sbi_intc_irq_handler_t)(u32 irq, void *priv);
> > +
> > +/*
> > + * Provider capabilities, at the moment it contains the maximum valid source ID
> > + * but extensible in the future
> > + */
> > +struct sbi_intc_provider_caps {
> > + /*
> > + * Maximum supported wired source ID for this provider.
> > + *
> > + * For APLIC this corresponds to the highest valid source ID (1..N).
> > + * The INTC core treats this as an abstract provider source ID space.
> > + */
> > + u32 max_src;
> > +};
> > +
> > +/* Provider operations */
> > +struct sbi_intc_provider_ops {
> > + /*
> > + * Query provider capabilities.
> > + *
> > + * This avoids exposing provider-specific limits (such as APLIC
> > + * num_source) through the registration API.
> > + */
> > + int (*get_caps)(void *ctx, struct sbi_intc_provider_caps *caps);
>
> This callback is not needed instead you driver can pass max_src
> as parameter to sbi_intc_register_provider()
>
I think it will be more extensible for the future to have get_caps,
though currently it holds only the max source.
> > +
> > + /*
> > + * Claim a pending wired interrupt on current hart.
> > + * Returns:
> > + * SBI_OK : *hwirq is valid
> > + * SBI_ENOENT : no pending wired interrupt
> > + * <0 : error
> > + */
> > + int (*claim)(void *ctx, u32 *irq);
> > +
> > + /*
> > + * Complete/acknowledge a previously claimed wired interrupt
> > + * (if required by HW).
> > + * Some HW may not require an explicit completion.
> > + */
> > + void (*complete)(void *ctx, u32 irq);
>
> All provider callbacks should take hwirq as a parameter.
According to our last sync-up, you would like a virtual IRQ number
mapping, so do you prefer moving the hwirq mapping from INTC to VIRQ?
>
> > +
> > + /*
> > + * mask/unmask a wired interrupt line.
> > + *
> > + * These are required for reliable couriering of level-triggered device
> > + * interrupts to S-mode: mask in M-mode before enqueueing, and unmask
> > + * after S-mode has cleared the device interrupt source.
> > + */
> > + void (*mask)(void *ctx, u32 irq);
> > + void (*unmask)(void *ctx, u32 irq);
>
> Same as above.
>
> > +};
> > +
> > +/* Register the active wired interrupt provider, e.g. APLIC, via ops and ctx */
> > +int sbi_intc_register_provider(const struct sbi_intc_provider_ops *ops,
> > + void *ctx);
> > +
> > +/*
> > + * Optional: map a IRQ number (irq) to a hardware wired IRQ (hwirq).
> > + *
> > + * If no explicit mapping exists, 'irq==hwirq' is assumed.
> > + *
> > + * This allows upper layers (e.g. VIRQ courier/emulation) to use stable irq
> > + * identifiers without exposing the wired controller's hwirq numbering.
> > + */
> > +int sbi_intc_map_irq(u32 irq, u32 hwirq);
> > +int sbi_intc_unmap_irq(u32 irq);
>
> The virq courier/emulation will be an independent module
> so drop these functions.
>
> Also, the driver should have no control on how irq is mapped
> to hwirq. The INTC framework will internally manage irq to
> hwirq mapping for a particular provider.
>
> > +u32 sbi_intc_irq_to_hwirq(u32 irq);
> > +u32 sbi_intc_hwirq_to_irq(u32 hwirq);
> > +
> > +/* Set/clear handler for a specified IRQ number */
> > +int sbi_intc_set_handler(u32 irq, sbi_intc_irq_handler_t handler, void *priv);
> > +int sbi_intc_clear_handler(u32 irq);
> > +
> > +/*
> > + * Platform independent mask/unmak wrappers on top of platform registered
> > + * mask/unmask ops functions.
> > + */
> > +void sbi_intc_mask_irq(u32 irq);
> > +void sbi_intc_unmask_irq(u32 irq);
> > +
> > +/* External interrupt handler (for irqchip device hook 'irqchip.irq_handle') */
> > +int sbi_intc_handle_external_irq(void);
> > +
> > +#endif
>
> Also, introducing a new set of sbi_intc.c and sbi_intc.h is
> not going to fly.
>
> We had already created sbi_irqchip.c and sbi_irqchip.h to
> manage external interrupts so the goal should be to enhance
> these frameworks.
>
All right, I can move the implementation from INTC to sbi_irqchip.
Regards,
Raymond
> Regards,
> Anup
More information about the opensbi
mailing list