Chinaunix首页 | 论坛 | 博客
  • 博客访问: 434447
  • 博文数量: 99
  • 博客积分: 65
  • 博客等级: 民兵
  • 技术积分: 1012
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-20 16:30
个人简介

linux kernel 工程师

文章分类

全部博文(99)

文章存档

2018年(5)

2017年(12)

2016年(27)

2015年(10)

2014年(43)

2012年(2)

我的朋友

分类: LINUX

2014-02-08 15:37:08

 在x86里面irq的入口函数是 do_irq()

在arm里面irq的入口函数是 asm_do_irq()

unsigned int __irq_entry do_IRQ(struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);

/* high bit used in ret_from_ code  */
unsigned vector = ~regs->orig_ax;
unsigned irq;

irq_enter();
exit_idle();

irq = __this_cpu_read(vector_irq[vector]);

msa_start_irq(irq);

if (!handle_irq(irq, regs)) {
/*  handle_irq最终会调用desc->handle_irq,desc->handle_irq最后又会调用handle_irq_event, 
handle_irq_event 又会调用desc->action->handler,  并根据返回结果
1. IRQ_WAKE_THREAD 通常是线程化的中断,这时需要唤醒该中断对应的内核线程
2. IRQ_HANDLED 表示中断已经处理完毕,通常是非线程化的中断返回该值
*/
  ack_APIC_irq();

  if (printk_ratelimit())
   pr_emerg("%s: %d.%d No irq handler for vector (irq %d)\n",
    __func__, smp_processor_id(), vector, irq);
}

msa_irq_exit(irq, regs->cs != __KERNEL_CS);

set_irq_regs(old_regs);
return 1;
}

handle_irq在x86_64 与x86_32中有不同的实现,但最终都是要调用desc->handle_irq

-----------------------handle_irq在x86_64的实现--------------------------

static inline void generic_handle_irq_desc(unsigned int irq, struct irq_desc *desc)
{
 desc->handle_irq(irq, desc);
}
arch\x86\kernel\irq_64.c

bool handle_irq(unsigned irq, struct pt_regs *regs)
{
 struct irq_desc *desc;

 stack_overflow_check(regs);

 desc = irq_to_desc(irq);
 if (unlikely(!desc))
  return false;

 generic_handle_irq_desc(irq, desc);
 return true;
}
 
-----------------------handle_irq在x86_32的实现--------------------------
bool handle_irq(unsigned irq, struct pt_regs *regs)
{
 struct irq_desc *desc;
 int overflow;

 overflow = check_stack_overflow();

 desc = irq_to_desc(irq);
 if (unlikely(!desc))
  return false;

 if (user_mode_vm(regs)  /* 如果在执行用户态代码时,发生中断,切换到内核态,内核态栈是空的,所以不需要切换的中断栈 */
 || !execute_on_irq_stack(overflow, desc, irq)) { 
 /* execute_on_irq_stack实现从内核栈到中断栈的切换
     如果已经在中断栈了,则不用切换,返回0,执行下面的desc->handle_irq
   如果不在中断栈,切换到中断栈,并且在中断栈上执行desc->handle_irq, 返回1,下面的desc->handle_irq不会再执行*/
  if (unlikely(overflow))
   print_stack_overflow();
  desc->handle_irq(irq, desc);
 }

 return true;
}
 

阅读(1459) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~