点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-优快云博客
原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!
4.4.2.1 timer中断的应答之ipipe_end
什么时候调用irq_desc.ipipe_end?
1) head domain的中断流控函数,xnintr_irq_handler,如果处理完毕,不再PROPAGATE给root domain,则会调用ipipe_end_irq函数,回调irq_desc->ipipe_end。
2) 假设中断到达了root domain
a. handle_percpu_devid_irq/handle_percpu_irq会显示的调用desc->ipipe_end(desc);
b. handle_fasteoi_irq: 调用cond_release_fasteoi_irq达到了desc->ipipe_end(desc)相同的效果。
针对timer中断,有个奇怪的点:
在__ipipe_ack_hrtimer_irq 已经调用过一次了irq_desc->ipipe_end。
timer中断到达了root domain handle_percpu_devid_irq/会显示的调用desc->ipipe_end(desc);
这个地方是不是在root域可以省掉一次desc->ipipe_end(desc)?
写了个patch来fix这个问题。在每个时钟中断中,都可以节省一次desc->ipipe_end操作,实际是减少了一次写GIC寄存器。
实测可以正常跑!
diff --git a/include/linux/ipipe_tickdev.h b/include/linux/ipipe_tickdev.h
index 54d1e2daad6e..7906e3d9f301 100644
--- a/include/linux/ipipe_tickdev.h
+++ b/include/linux/ipipe_tickdev.h
@@ -138,6 +138,8 @@ int ipipe_timer_start(void (*tick_handler)(void),
*/
void ipipe_timer_stop(unsigned cpu);
+bool timer_irq_ipipe_stolen(unsigned int irq);
+
/*
* Program the timer
*/
diff --git a/kernel/ipipe/timer.c b/kernel/ipipe/timer.c
index 5354cddb643d..236a81a8d002 100644
--- a/kernel/ipipe/timer.c
+++ b/kernel/ipipe/timer.c
@@ -438,6 +438,26 @@ struct grab_timer_data {
int retval;
};
+bool timer_irq_ipipe_stolen(unsigned int irq)
+{
+ struct clock_event_device *evtdev;
+ struct ipipe_timer *timer;
+
+ timer = this_cpu_read(percpu_timer);
+ if (!timer)
+ return false;
+
+ if (!timer->host_timer)
+ return false;
+
+ evtdev = timer->host_timer;
+
+ if(irq == timer->irq && evtdev->ipipe_stolen == 1)
+ return true;
+ else
+ return false;
+}
+
static void grab_timer(void *arg)
{
struct grab_timer_data *data = arg;
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index d4791b5dfe99..412bec17fbc7 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -15,6 +15,7 @@
#include <linux/kernel_stat.h>
#include <linux/irqdomain.h>
#include <linux/ipipe.h>
+#include <linux/ipipe_tickdev.h>
#include <trace/events/irq.h>
@@ -962,8 +963,10 @@ void handle_percpu_devid_irq(struct irq_desc *desc)
res = action->handler(irq, raw_cpu_ptr(action->percpu_dev_id));
trace_irq_handler_exit(irq, action, res);
#ifdef CONFIG_IPIPE
- (void)chip;
- desc->ipipe_end(desc);
+ if(!timer_irq_ipipe_stolen(irq) && desc->ipipe_end){
+ (void)chip;
+ desc->ipipe_end(desc);
+ }
return;
#endif
} else {
点击查看系列文章 =》 Interrupt Pipeline系列文章大纲-优快云博客
原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!