Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

74261
1501
219116


[Linux][Kernel] softirq - 호출되는 모듈 (h->action) [Linux][Kernel] IRQ(Interrupt)


softirq_vec 변수를 확인하면, __do_softirq() 에서 h->action로 호출되는 함수의 정체를 확인할 수 있습니다.
crash> p softirq_vec
softirq_vec = $2 =
 {{
    action = 0xc01289ac <tasklet_hi_action>
  }, {
    action = 0xc0180334 <run_timer_softirq>
  }, {
    action = 0xc0d55d7c <net_tx_action>
  }, {
    action = 0xc0d58238 <net_rx_action>
  }, {
    action = 0xc038123c <blk_done_softirq>
  }, {
    action = 0xc03817f8 <blk_iopoll_softirq>
  }, {
    action = 0xc0128a98 <tasklet_action>
  }, {
    action = 0xc015b198 <run_rebalance_domains>
  }, {
    action = 0xc0182c60 <run_hrtimer_softirq>
  }, {
    action = 0xc017a974 <rcu_process_callbacks>
  }}

아래 패치를 추가하고, "echo 1 > /d/tracing/events/irq/enable" 설정으로 soft irq ftrace log를 확인하면 실제 실행되는 함수를 tracing할 수 있습니다.
 diff --git a/kernel/softirq.c b/kernel/softirq.c
index 0c998ef..5d6dfa3 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -241,6 +241,7 @@ asmlinkage __visible void __do_softirq(void)
        __u32 pending;
        int softirq_bit;
+       void *cb_func;
        /*
         * Mask out PF_MEMALLOC s current task context is borrowed for the
         * softirq. A softirq handled such as network RX might set PF_MEMALLOC
@@ -274,6 +275,11 @@ restart:
                kstat_incr_softirqs_this_cpu(vec_nr);
                trace_softirq_entry(vec_nr);
+
+               cb_func = (void*)h->action;
+               trace_printk("[++][PompeiiGrace][%s][%s,%d]: caller: (%pS) h->action[%pF]\n",
+                               current->comm, __func__,__LINE__,  (void *)__builtin_return_address(0), cb_func);
+
                h->action(h);
                trace_softirq_exit(vec_nr);
                if (unlikely(prev_count != preempt_count())) {

ftrace log를 해석해보죠.
[1]: irq=20 name=arch_mem_timer IRQ가 Trigger됩니다.
[2]: soft irq(run_timer_softirq/run_rebalance_domains/rcu_process_callbacks)를 raise합니다.
[3]: @__handle_domain_irq, irq=20 name=arch_mem_timer IRQ가 종료됩니다.
[4]: @__handle_domain_irq: irq_exit를 호출하여 softirq가 시작됩니다.
[5]: [action=TIMER] run_timer_softirq 수행합니다.
[6]: [action=SCHED] run_rebalance_domains 수행합니다.
[7]: [action=RCU] rcu_process_callbacks 수행합니다.
 <idle>-0     [004] d.h2   107.990285: irq_handler_entry: irq=20 name=arch_mem_timer  //<<--[1]
  <idle>-0     [004] d.h3   107.990313: softirq_raise: vec=1 [action=TIMER]  //<<--[2]
  <idle>-0     [004] d.h3   107.990318: softirq_raise: vec=9 [action=RCU]   //<<--[2]
  <idle>-0     [004] d.h3   107.990327: softirq_raise: vec=7 [action=SCHED] //<<--[2]
  <idle>-0     [004] d.h2   107.990345: irq_handler_exit: irq=20 ret=handled //<<--[3]
  <idle>-0     [004] d.h1   107.990359: irq_exit: [+][Pompeii][swapper/4][irq_exit,398]: caller: (__handle_domain_irq+0x80/0xa0) //<<--[4]
  <idle>-0     [004] ..s2   107.990363: softirq_entry: vec=1 [action=TIMER] //<<--[5]
  <idle>-0     [004] ..s1   107.990367: __do_softirq: [++][PompeiiGrace][swapper/4][__do_softirq,281]: caller: (irq_exit+0xac/0x118) h->action[run_timer_softirq+0x0/0x5ac]
  <idle>-0     [004] .ns2   107.990398: softirq_exit: vec=1 [action=TIMER]
  <idle>-0     [004] .ns2   107.990400: softirq_entry: vec=7 [action=SCHED]  //<<--[6]
  <idle>-0     [004] .ns1   107.990403: __do_softirq: [++][PompeiiGrace][swapper/4][__do_softirq,281]: caller: (irq_exit+0xac/0x118) h->action[run_rebalance_domains+0x0/0x1d8]
  <idle>-0     [004] .ns2   107.990426: softirq_exit: vec=7 [action=SCHED]
  <idle>-0     [004] .ns2   107.990428: softirq_entry: vec=9 [action=RCU] //<<--[7]
  <idle>-0     [004] .ns1   107.990431: __do_softirq: [++][PompeiiGrace][swapper/4][__do_softirq,281]: caller: (irq_exit+0xac/0x118) h->action[rcu_process_callbacks+0x0/0x644]
  <idle>-0     [004] .ns2   107.990438: softirq_exit: vec=9 [action=RCU]

이후 raise_softirq-> raise_softirq_irqoff 순서로 API 호출이 이루어집니다.

 void raise_softirq(unsigned int nr)
{
        unsigned long flags;
        local_irq_save(flags);
        raise_softirq_irqoff(nr); //<<--
        local_irq_restore(flags);
}


inline void raise_softirq_irqoff(unsigned int nr)
{
 __raise_softirq_irqoff(nr); //<<--
 if (!in_interrupt())
 wakeup_softirqd();
}


void __raise_softirq_irqoff(unsigned int nr)
{
 trace_softirq_raise(nr);
 or_softirq_pending(1UL << nr); //<<--
}

덧글

댓글 입력 영역