zynq 軟中斷通訊AMP 1
kernel/arch/arm/kernel/smp.c
預設的系統軟中斷:
enum ipi_msg_type {
IPI_WAKEUP,
IPI_TIMER,
IPI_RESCHEDULE,
IPI_CALL_FUNC,
IPI_CPU_STOP,
IPI_IRQ_WORK,
IPI_COMPLETION,
IPI_CPU_BACKTRACE,
/*
* SGI8-15 can be reserved by secure firmware, and thus may
* not be usable by the kernel. Please keep the above limited
* to at most 8 entries.
*/
};
asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs) { handle_IPI(ipinr, regs); } void handle_IPI(int ipinr, struct pt_regs *regs) { unsigned int cpu = smp_processor_id(); struct pt_regs *old_regs = set_irq_regs(regs); if (ipi_types[ipinr].handler) { printk("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr); __inc_irq_stat(cpu, ipi_irqs[ipinr]); irq_enter(); (*ipi_types[ipinr].handler)(); irq_exit(); } else pr_debug("CPU%u: Unknown IPI message 0x%x\n", cpu, ipinr); set_irq_regs(old_regs); } /* * set_ipi_handler: * Interface provided for a kernel module to specify an IPI handler function. */ int set_ipi_handler(int ipinr, void *handler, char *desc) { unsigned int cpu = smp_processor_id(); if (ipi_types[ipinr].handler) { pr_crit("CPU%u: IPI handler 0x%x already registered to %pf\n", cpu, ipinr, ipi_types[ipinr].handler); return -1; } ipi_types[ipinr].handler = handler; ipi_types[ipinr].desc = desc; return 0; } EXPORT_SYMBOL(set_ipi_handler);
通過set_ipi_handler 函式注入軟體中斷回撥函式到內部中斷ipi_types 中斷回撥對映表中
int set_ipi_handler(int ipinr, void *handler, char *desc)
static struct ipi ipi_types[NR_IPI] = {
#define S(x, f) [x].desc = IPI_DESC_STR(x), [x].handler = f
S(IPI_WAKEUP, NULL),
#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
S(IPI_TIMER, tick_receive_broadcast_local),
#endif
S(IPI_RESCHEDULE, scheduler_ipi),
S(IPI_CALL_FUNC, generic_smp_call_function_interrupt),
S(IPI_CPU_STOP, ipi_cpu_stop),
#ifdef CONFIG_IRQ_WORK
S(IPI_IRQ_WORK, irq_work_run),
#endif
S(IPI_COMPLETION, ipi_complete),
};
zynq_remoteproc.c 暴力注入軟中斷和響應函式
/kernel/drivers/remoteproc/zynq_remoteproc.c:
367 }
368
369: ret = set_ipi_handler(local->ipis[0].irq, ipi_kick,
370 "Firmware kick");
371 if (ret) {