Messages in this thread Patch in this message | | | From | Xu Lu <> | Subject | [RFC 06/12] riscv: Allow requesting irq as pseudo NMI | Date | Mon, 23 Oct 2023 16:29:05 +0800 |
| |
This commit implements pseudo NMI callbacks for riscv_intc_irq chip. We use an immediate macro to denote NMIs of each cpu. Each bit of it represents an irq. Bit 1 means corresponding irq is registered as NMI while bit 0 means not.
Signed-off-by: Xu Lu <luxu.kernel@bytedance.com> Signed-off-by: Hangjing Li <lihangjing@bytedance.com> Reviewed-by: Liang Deng <dengliang.1214@bytedance.com> Reviewed-by: Yu Li <liyu.yukiteru@bytedance.com> --- arch/riscv/include/asm/irqflags.h | 17 ++++++++++++++ drivers/irqchip/irq-riscv-intc.c | 38 +++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+)
diff --git a/arch/riscv/include/asm/irqflags.h b/arch/riscv/include/asm/irqflags.h index 60c19f8b57f0..9700a17a003a 100644 --- a/arch/riscv/include/asm/irqflags.h +++ b/arch/riscv/include/asm/irqflags.h @@ -12,6 +12,23 @@ #ifdef CONFIG_RISCV_PSEUDO_NMI +#define __ALLOWED_NMI_MASK 0 +#define ALLOWED_NMI_MASK (__ALLOWED_NMI_MASK & irqs_enabled_ie) + +static inline bool nmi_allowed(int irq) +{ + return (BIT(irq) & ALLOWED_NMI_MASK); +} + +static inline bool is_nmi(int irq) +{ + return (BIT(irq) & ALLOWED_NMI_MASK); +} + +static inline void set_nmi(int irq) {} + +static inline void unset_nmi(int irq) {} + static inline void local_irq_switch_on(void) { csr_set(CSR_STATUS, SR_IE); diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-intc.c index 7fad1ba37e5c..83a0a744fce6 100644 --- a/drivers/irqchip/irq-riscv-intc.c +++ b/drivers/irqchip/irq-riscv-intc.c @@ -67,11 +67,49 @@ static void riscv_intc_irq_eoi(struct irq_data *d) */ } +#ifdef CONFIG_RISCV_PSEUDO_NMI + +static int riscv_intc_irq_nmi_setup(struct irq_data *d) +{ + unsigned int hwirq = d->hwirq; + struct irq_desc *desc = irq_to_desc(d->irq); + + if (WARN_ON((hwirq >= BITS_PER_LONG) || !nmi_allowed(hwirq))) + return -EINVAL; + + desc->handle_irq = handle_percpu_devid_fasteoi_nmi; + set_nmi(hwirq); + + return 0; +} + +static void riscv_intc_irq_nmi_teardown(struct irq_data *d) +{ + unsigned int hwirq = d->hwirq; + struct irq_desc *desc = irq_to_desc(d->irq); + + if (WARN_ON(hwirq >= BITS_PER_LONG)) + return; + + if (WARN_ON(!is_nmi(hwirq))) + return; + + desc->handle_irq = handle_percpu_devid_irq; + unset_nmi(hwirq); +} + +#endif /* CONFIG_RISCV_PSEUDO_NMI */ + static struct irq_chip riscv_intc_chip = { .name = "RISC-V INTC", .irq_mask = riscv_intc_irq_mask, .irq_unmask = riscv_intc_irq_unmask, .irq_eoi = riscv_intc_irq_eoi, +#ifdef CONFIG_RISCV_PSEUDO_NMI + .irq_nmi_setup = riscv_intc_irq_nmi_setup, + .irq_nmi_teardown = riscv_intc_irq_nmi_teardown, + .flags = IRQCHIP_SUPPORTS_NMI, +#endif }; static int riscv_intc_domain_map(struct irq_domain *d, unsigned int irq, -- 2.20.1
| |