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) {

 

 

你可能感兴趣的:(zynq 软中断通信AMP 1)