https://elixir.bootlin.com/linux/v6.8-rc1/source/arch/riscv/kernel/entry.S
SYM_CODE_START(handle_exception)
/*
 * If coming from userspace, preserve the user thread pointer and load
 * the kernel thread pointer.  If we came from the kernel, the scratch
 * register will contain 0, and we should continue on the current TP.
 */
csrrw tp, CSR_SCRATCH, tp
bnez tp, .Lsave_context
...
/*
 * MSB of cause differentiates between
 * interrupts and exceptions
 */
bge s4, zero, 1f

/* Handle interrupts */
tail do_irq


https://elixir.bootlin.com/linux/v6.8-rc1/source/arch/riscv/kernel/traps.c#L366
asmlinkage void noinstr do_irq(struct pt_regs *regs)
{
irqentry_state_t state = irqentry_enter(regs);

if (IS_ENABLED(CONFIG_IRQ_STACKS) && on_thread_stack())
call_on_irq_stack(regs, handle_riscv_irq);
else
handle_riscv_irq(regs);

irqentry_exit(regs, state);
}

https://elixir.bootlin.com/linux/v6.8-rc1/source/arch/riscv/kernel/traps.c#L355
static void noinstr handle_riscv_irq(struct pt_regs *regs)
{
struct pt_regs *old_regs;

irq_enter_rcu();
old_regs = set_irq_regs(regs);
handle_arch_irq(regs);
set_irq_regs(old_regs);
irq_exit_rcu();
}

https://elixir.bootlin.com/linux/v6.8-rc1/source/drivers/irqchip/irq-riscv-intc.c#L127
(where)
static int __init riscv_intc_init_common(struct fwnode_handle *fn)
{
...
rc = set_handle_irq(&riscv_intc_irq);
if (rc) {
pr_err("failed to set irq handler\n");
return rc;
}

https://elixir.bootlin.com/linux/v6.8-rc1/source/drivers/irqchip/irq-riscv-intc.c#L23
static asmlinkage void riscv_intc_irq(struct pt_regs *regs)
{
unsigned long cause = regs->cause & ~CAUSE_IRQ_FLAG;

if (unlikely(cause >= BITS_PER_LONG))
panic("unexpected interrupt cause");

generic_handle_domain_irq(intc_domain, cause);
}

https://elixir.bootlin.com/linux/v6.8-rc1/source/kernel/irq/irqdesc.c#L726
int generic_handle_domain_irq(struct irq_domain *domain, unsigned int hwirq)
{
return handle_irq_desc(irq_resolve_mapping(domain, hwirq));
}

+ Recent posts