4.8_中断流动的标识及场景总结

4.8 IPIPE中断流动的标识

4.8.1 传入__ipipe_dispatch_irq的flags

include/linux/ipipe.h:
#define IPIPE_IRQF_NOACK    0x1
#define IPIPE_IRQF_NOSYNC   0x2
void __ipipe_dispatch_irq(unsigned int irq, int flags);

传入__ipipe_dispatch_irq的flags,有三种可能性:0、1、2.

第一,传入0

在gic_handle_irq读到物理中断号irqnr后,如果是PPI/SPI/LPI中断,则调用 ipipe_handle_domain_irq。

ipipe_handle_domain_irq->__ipipe_grab_irq->__ipipe_dispatch_irq(irq, 0)总是向__ipipe_dispatch_irq传递flags=0。

在这里插入图片描述

在这里插入图片描述

第二,传入1(IPIPE_IRQF_NOACK)

IPIPE_IRQF_NOACK,代表在__ipipe_dispatch_irq中不需要执行ipd->irqs[irq].ackfn(desc)。ackfn在《4.4.2 timer中断的应答(__ipipe_dispatch_irq上半部)》有完整的阐述。

在这里插入图片描述

为什么flags设置了IPIPE_IRQF_NOACK,需要执行第1510行:IPIPE_WARN_ONCE(chained_irq)?

根据注释,chained中断绝大部分都有一个有效的ackfn(acknowledge handler),应该不要在chained中断处理过程中向__ipipe_dispatch_irq传入IPIPE_IRQF_NOACK。

什么时候可以合理的传入IPIPE_IRQF_NOACK?有两种情况:

  1. 调用__ipipe_grab_ipi处理SGI中断不需要调用ackfn

在gic_handle_irq读到物理中断号irqnr后,如果是SGI中断,则调用 ipipe_handle_multi_ipi。

ipipe_handle_multi_ipi-> __ipipe_grab_ipi-> __ipipe_dispatch_irq(irq, IPIPE_IRQF_NOACK)总是向__ipipe_dispatch_irq传递flags=IPIPE_IRQF_NOACK。

在这里插入图片描述

在这里插入图片描述

  1. ipipe_raise_irq,是软件模拟的中断,不需要ackfn

在没有硬件中断发生的情况下,可以直接调用__ipipe_dispatch_irq(irq, IPIPE_IRQF_NOACK)传入一个virq中断号,模拟一个中断的发生。

在这里插入图片描述

第三,传入2(IPIPE_IRQF_NOSYNC)

IPIPE_IRQF_NOSYNC 完全是服务于chained中断。参考《4.7 chained中断如何流动》。

4.8.2 Interrupt control bits

Interrupt control bits指的是如下标识位,服务于struct ipipe_domain的成员unsigned long control。

include/linux/ipipe_domain.h:

/* Interrupt control bits */
#define IPIPE_HANDLE_FLAG	0
#define IPIPE_STICKY_FLAG	1
#define IPIPE_LOCK_FLAG		2
#define IPIPE_HANDLE_MASK	(1 << IPIPE_HANDLE_FLAG)
#define IPIPE_STICKY_MASK	(1 << IPIPE_STICKY_FLAG)
#define IPIPE_LOCK_MASK		(1 << IPIPE_LOCK_FLAG)

struct ipipe_domain {
    int context_offset;
    struct ipipe_irqdesc {
        unsigned long control;
        ipipe_irq_ackfn_t ackfn;
        ipipe_irq_handler_t handler;
        void *cookie;
    } ____cacheline_aligned irqs[IPIPE_NR_IRQS];
    const char *name;
    struct mutex mutex;
};

第一种,IPIPE_HANDLE_MASK

IPIPE_HANDLE_MASK的意义就是代表是否在domain中已经注册了handler!在ipipe_request_irq会对control进行赋值IPIPE_HANDLE_MASK,ipipe_free_irq会对control赋值0。

在__ipipe_dispatch_irq中总是通过检查ipd->irqs[irq].control是否设置了IPIPE_HANDLE_MASK来判断是否注册了handler。

在这里插入图片描述

第二种,IPIPE_STICKY_MASK

根据注释,IPIPE_STICKY_MASK 代表立刻在当前域进行处理。

在这里插入图片描述

在IPIPE代码中,只有一个中断设置了此标识:head domain和root domain初始化过程中,都会调用init_stage->__ipipe_hook_critical_ipi->hook_internal_ipi为各自的中断IPIPE_CRITICAL_IPI设置相同的中断处理函数__ipipe_do_critical_sync。

在这里插入图片描述

所以,这个IPIPE_CRITICAL_IPI发生时,在__ipipe_dispatch_irq中会被记录到__ipipe_current_domain的interrupt log中。

第三种,IPIPE_LOCK_MASK

IPIPE_LOCK_MASK没有被__ipipe_dispatch_irq直接使用,是在__ipipe_dispatch_irq ->__ipipe_set_irq_pending间接使用。

在__ipipe_set_irq_pending,如果发现某个中断设置了IPIPE_LOCK_MASK,则把中断记录到irqheld_map中(interrupt held log)。

在这里插入图片描述

从gic_mask_irq ->ipipe_lock_irq->__ipipe_lock_irq调用过程中的细节可知,IPIPE_LOCK_MASK仅对root domain生效。__ipipe_lock_irq不仅会设置IPIPE_LOCK_MASK,还会把interrupt pend log中的中断标志位挪到interrupt held log中。__ipipe_unlock_irq是__ipipe_lock_irq的反向操作。

在这里插入图片描述


至此,已经完成第四章所有的内容!

在第四章分析过不同的场景下,走到__ipipe_dispatch_irq里面的逻辑:

  • IPI 中断如何复用:《3.5.1 __ipipe_init()之IPIPE_CRITICAL_IPI》
  • 同时在Head domain和Root domain注册的中断:《4.4 timer中断从Xenomai流向Linux》
  • 仅在head domain注册的设备中断:《4.5 仅在head domain注册的设备中断处理流程》
  • 仅在root domain注册的设备中断:《4.6 仅在root domain注册的设备中断》
  • chained中断如何流动:《4.7 chained中断如何流动》
  • 在IPIPE中涉及到的逻辑判断的标志位:《4.8 IPIPE中断流动的标识》

第一次感觉把__ipipe_dispatch_irq完完全全的看懂了,看透了!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值