linux中的SGI(核间中断)IPI_RESCHEDULE详解
2021/6/22 7:29:59
本文主要是介绍linux中的SGI(核间中断)IPI_RESCHEDULE详解,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1、SGI中断(核间通信中断)
在gicv2/gicv3中,SGI中断(中断号0-15)是software generate interrupt,用户核间中断。
我们一般将0-7划分给linux中使用,8-15给TEE使用。在smp.c定义了linux中使用的SGI中断。
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,
/*
* CPU_BACKTRACE is special and not included in NR_IPI
* or tracable with trace_ipi_*
/
IPI_CPU_BACKTRACE,
#ifdef CONFIG_TRUSTY
IPI_CUSTOM_FIRST,
IPI_CUSTOM_LAST = 15,
#endif
/
* 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.
*/
};
2、SGI中断的调用流程
(1)、CPU收到IRQ后的处理
当ARM core收到IRQ后,会触发cpu的irq异常,会跳转到linux kernel的irq异常向量表,在该向量表中,会调用gicv2/gicv3的gic_handle_irq函数,在kernel/drivers/irqchip/irq-gic-v3.c中
- irqnr = gic_read_iar() 读gic寄存器获取硬件中断号
- likely(irqnr > 15 && irqnr < 1020) || irqnr >= 8192 这这个条件下处理PPI中断和SPI中断
- if (irqnr < 16) 在这个条件下调用handle_IPI(irqnr, regs)来处理SGI中断
static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) { u32 irqnr; do { irqnr = gic_read_iar(); if (likely(irqnr > 15 && irqnr < 1020) || irqnr >= 8192) { int err; if (static_key_true(&supports_deactivate)) gic_write_eoir(irqnr); err = handle_domain_irq(gic_data.domain, irqnr, regs); if (err) { WARN_ONCE(true, "Unexpected interrupt received!\n"); if (static_key_true(&supports_deactivate)) { if (irqnr < 8192) gic_write_dir(irqnr); } else { gic_write_eoir(irqnr); } } continue; } if (irqnr < 16) { gic_write_eoir(irqnr); if (static_key_true(&supports_deactivate)) gic_write_dir(irqnr); #ifdef CONFIG_SMP /* * Unlike GICv2, we don't need an smp_rmb() here. * The control dependency from gic_read_iar to * the ISB in gic_write_eoir is enough to ensure * that any shared data read by handle_IPI will * be read after the ACK. */ handle_IPI(irqnr, regs); #else WARN_ONCE(true, "Unexpected SGI received!\n"); #endif continue; } } while (irqnr != ICC_IAR1_EL1_SPURIOUS); }
(2)、处理SGI中断(也叫核间通信中断)
void handle_IPI(int ipinr, struct pt_regs *regs) { ...... case IPI_RESCHEDULE: scheduler_ipi(); break; ...... }
(3)、处理IPI_RESCHEDULE中断的操作
void scheduler_ipi(void) { int cpu = smp_processor_id(); /* * Fold TIF_NEED_RESCHED into the preempt_count; anybody setting * TIF_NEED_RESCHED remotely (for the first time) will also send * this IPI. */ preempt_fold_need_resched(); if (llist_empty(&this_rq()->wake_list) && !got_nohz_idle_kick()) { #ifdef CONFIG_MTK_SCHED_MONITOR mt_trace_IPI_start(IPI_RESCHEDULE); mt_trace_IPI_end(IPI_RESCHEDULE); #endif return; } /* * Not all reschedule IPI handlers call irq_enter/irq_exit, since * traditionally all their work was done from the interrupt return * path. Now that we actually do some work, we need to make sure * we do call them. * * Some archs already do call them, luckily irq_enter/exit nest * properly. * * Arguably we should visit all archs and update all handlers, * however a fair share of IPIs are still resched only so this would * somewhat pessimize the simple resched case. */ irq_enter(); #ifdef CONFIG_MTK_SCHED_MONITOR mt_trace_IPI_start(IPI_RESCHEDULE); #endif sched_ttwu_pending(); /* * Check if someone kicked us for doing the nohz idle load balance. */ if (unlikely(got_nohz_idle_kick()) && !cpu_isolated(cpu)) { this_rq()->idle_balance = 1; raise_softirq_irqoff(SCHED_SOFTIRQ); } #ifdef CONFIG_MTK_SCHED_MONITOR mt_trace_IPI_end(IPI_RESCHEDULE); #endif irq_exit(); }
这篇关于linux中的SGI(核间中断)IPI_RESCHEDULE详解的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-18git仓库有更新,jenkins 自动触发拉代码怎么配置的?-icode9专业技术文章分享
- 2024-12-18Jenkins webhook 方式怎么配置指定的分支?-icode9专业技术文章分享
- 2024-12-13Linux C++项目实战入门教程
- 2024-12-13Linux C++编程项目实战入门教程
- 2024-12-11Linux部署Scrapy教程:新手入门指南
- 2024-12-11怎么将在本地创建的 Maven 仓库迁移到 Linux 服务器上?-icode9专业技术文章分享
- 2024-12-10Linux常用命令
- 2024-12-06谁看谁服! Linux 创始人对于进程和线程的理解是…
- 2024-12-04操作系统教程:新手入门及初级技巧详解
- 2024-12-04操作系统入门:新手必学指南