[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 15/16] xen/riscv: implement setup_irq()
Introduce support for IRQ setup on RISC-V by implementing setup_irq() and __setup_irq(), adapted and extended from an initial implementation by [1]. __setup_irq() does the following: - Sets up an IRQ action. - Validates that shared IRQs have non-NULL `dev_id` and are only used when existing handlers allow sharing. - Uses smp_wmb() to enforce memory ordering after assigning desc->action to ensure visibility before enabling the IRQ. - Supports multi-action setups via CONFIG_IRQ_HAS_MULTIPLE_ACTION. setup_irq() does the following: - Converts IRQ number to descriptor and acquires its lock. - Rejects registration if the IRQ is already assigned to a guest domain, printing an error. - Delegates the core setup to __setup_irq(). - On first-time setup, disables the IRQ, routes it to Xen using intc_route_irq_to_xen(), sets default CPU affinity (current CPU), calls the handler’s startup routine, and finally enables the IRQ. irq_set_affinity() invokes set_affinity() callback from the IRQ handler if present. Defined IRQ_NO_PRIORITY as default priority used when routing IRQs to Xen. [1] https://gitlab.com/xen-project/people/olkur/xen/-/commit/7390e2365828b83e27ead56b03114a56e3699dd5 Co-developed-by: Romain Caritey <Romain.Caritey@xxxxxxxxxxxxx> Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx> --- Changes in V2: - Added implenmtation of aplic_set_irq_type() as it is going to be used in this commit. And also, update the implementation of it. Make default case of switch to do panic(). - Move all forward declaration up in asm/irq.h. - s/__setup_irq/_setup_irq. - Code style fixes. - Update commit message. - use smp_wmb() instead of smp_mb() in _setup_irq(). - Drop irq_set_affinity(). - Use plain C operator instead if {clear,set}_bit() for desc->status as it is always used under spinlock(). - Drop set_bit(_IRQ_DISABLED, &desc->status) in setup_irq() as in the case when IRQ is setuped for a first time, desc->status should be already set to IRQ_DISABLED in init_one_irq_desc(). ---- xen/arch/riscv/include/asm/irq.h | 2 + xen/arch/riscv/irq.c | 84 ++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/xen/arch/riscv/include/asm/irq.h b/xen/arch/riscv/include/asm/irq.h index 1a05c5ff88..d35fac0a86 100644 --- a/xen/arch/riscv/include/asm/irq.h +++ b/xen/arch/riscv/include/asm/irq.h @@ -9,6 +9,8 @@ #define NR_IRQS 1024 +#define IRQ_NO_PRIORITY 0 + /* TODO */ #define nr_irqs 0U #define nr_static_irqs 0 diff --git a/xen/arch/riscv/irq.c b/xen/arch/riscv/irq.c index 056bdf3ca8..969e22395d 100644 --- a/xen/arch/riscv/irq.c +++ b/xen/arch/riscv/irq.c @@ -7,6 +7,7 @@ */ #include <xen/bug.h> +#include <xen/cpumask.h> #include <xen/device_tree.h> #include <xen/errno.h> #include <xen/init.h> @@ -58,6 +59,89 @@ int platform_get_irq(const struct dt_device_node *device, int index) return dt_irq.irq; } +static int _setup_irq(struct irq_desc *desc, unsigned int irqflags, + struct irqaction *new) +{ + bool shared = irqflags & IRQF_SHARED; + + ASSERT(new != NULL); + + /* + * Sanity checks: + * - if the IRQ is marked as shared + * - dev_id is not NULL when IRQF_SHARED is set + */ + if ( desc->action != NULL && (!(desc->status & IRQF_SHARED) || !shared) ) + return -EINVAL; + if ( shared && new->dev_id == NULL ) + return -EINVAL; + + if ( shared ) + desc->status |= IRQF_SHARED; + +#ifdef CONFIG_IRQ_HAS_MULTIPLE_ACTION + new->next = desc->action; +#endif + + desc->action = new; + smp_wmb(); + + return 0; +} + +int setup_irq(unsigned int irq, unsigned int irqflags, struct irqaction *new) +{ + int rc; + unsigned long flags; + struct irq_desc *desc = irq_to_desc(irq); + bool disabled; + + spin_lock_irqsave(&desc->lock, flags); + + disabled = (desc->action == NULL); + + if ( desc->status & IRQ_GUEST ) + { + spin_unlock_irqrestore(&desc->lock, flags); + /* + * TODO: would be nice to have functionality to print which domain owns + * an IRQ. + */ + printk(XENLOG_ERR "ERROR: IRQ %u is already in use by a domain\n", irq); + return -EBUSY; + } + + rc = _setup_irq(desc, irqflags, new); + if ( rc ) + goto err; + + /* First time the IRQ is setup */ + if ( disabled ) + { + /* Route interrupt to xen */ + intc_route_irq_to_xen(desc, IRQ_NO_PRIORITY); + + /* + * We don't care for now which CPU will receive the + * interrupt. + * + * TODO: Handle case where IRQ is setup on different CPU than + * the targeted CPU and the priority. + */ + desc->handler->set_affinity(desc, cpumask_of(smp_processor_id())); + + desc->handler->startup(desc); + + /* Enable irq */ + desc->status &= ~IRQ_DISABLED; + } + + err: + spin_unlock_irqrestore(&desc->lock, flags); + + return rc; +} + int arch_init_one_irq_desc(struct irq_desc *desc) { desc->arch.type = IRQ_TYPE_INVALID; -- 2.49.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |