x86 kernel 中断机制分析二——irq_desc

本文介绍了x86系统中irq_desc数据结构在中断处理中的作用,包括它如何存储中断信息、中断处理函数及中断嵌套深度等。文章详细讨论了在系统启动时如何初始化irq_desc,特别是CONFIG_SPARSE_IRQ配置下采用的Radix tree管理和全局数组两种方式,并探讨了init_IRQ阶段的irq_desc初始化过程。
摘要由CSDN通过智能技术生成

简介

irq_desc数据结构用于描述一个irq对应的各种信息,主要有以下方面:
irq_data,描述该irq的irq number,irq chip,irq domain,处理器亲和力等等
handle_irq,highlevel irq-events handler,流处理函数
irq_action,一个链表,每个成员包含该irq中断处理函数等信息
depth,中断嵌套深度
name,cat /proc/interrupts时显示的名称
等等

每个irq对应一个irq_desc,kernel中管理irq_descs有两种方式:
1、如果定义 CONFIG_SPARSE_IRQ,则所有irq_descs以radix tree的形式管理
2、否则所有irq_descs放在一个全局数组中,并对某些成员进行初始化,如下

  260 struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
  261     [0 ... NR_IRQS-1] = {
  262         .handle_irq = handle_bad_irq,
  263         .depth      = 1,
  264         .lock       = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
  265     }
  266 };

系统启动时初始化irq_descs

1、early_irq_init

1.1 Radix tree形式

只对系统的16个legacy中断进行irq_desc的初始化

229 int __init early_irq_init(void)
  230 {
  231     int i, initcnt, node = first_online_node;
  232     struct irq_desc *desc;
  233
  234     init_irq_default_affinity();  //默认的中断亲和力是所有CPU,如果想绑定cpu到某个cpu上该怎么做?http://blog.csdn.net/kingmax26/article/details/5788732
  235
  236     /* Let arch update nr_irqs and return the nr of preallocated irqs */
  237     initcnt = arch_probe_nr_irqs();       //不同架构的preallocated irq数目不同,x86是16
~ 238     printk(KERN_ERR "yin_test NR_IRQS:%d nr_irqs:%d initcnt %d\n",
+ 239             NR_IRQS, nr_irqs, initcnt);
  240
  241     if (WARN_ON(nr_irqs > IRQ_BITMAP_BITS))
  242         nr_irqs = IRQ_BITMAP_BITS;
  243
  244     if (WARN_ON(initcnt > IRQ_BITMAP_BITS))
  245         initcnt = IRQ_BITMAP_BITS;
  246
  247     if (initcnt > nr_irqs)
  248         nr_irqs = initcnt;
  249
  250     for (i = 0; i < initcnt; i++) {             //对以上的16个irq进行irq_desc的初始化
  251         desc = alloc_desc(i, node, NULL);   //分配irq_desc并对其中某些成员进行初始化
  252         set_bit(i, allocated_irqs);            //set bit in allocated_irqs
  253         irq_insert_desc(i, desc);                          //插入到radix tree中
  254     }
  255     return arch_early_irq_init();     //设置以上16个legacy irq的chip_data,void类型
  256 }
1.2 全局数组
260 struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {
  261     [0 ... NR_IRQS-1] = {
  262         .handle_irq = handle_bad_irq,
  263         .depth      = 1,
  264         .lock       = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),
  265     }
  266 };
  267
  268 int __init early_irq_init(void)
  269 {
  270     int count, i, node = first_online_node;
  271     struct irq_desc *desc;
  272
  273     init_irq_default_affinity();
  274
~ 275     printk(KERN_INFO "NR_IRQS:%d, adasda\n", NR_IRQS);
+ 276     13131
  277
  278     desc = irq_desc;
  279     count = ARRAY_SIZE(irq_desc);
  280
  281     for (i = 0; i < count; i++) { //遍历数组,对成员进行初始化
  282         desc[i].kstat_irqs = alloc_percpu(unsigned int);
  283         alloc_masks(&desc[i], GFP_KERNEL, node);
  284         raw_spin_lock_init(&desc[i].lock);
  285         lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
  286         desc_set_defaults(i, &desc[i], node, NULL);
  287     }
  288     return arch_early_irq_init();
  289 }

可以看到,这种方法就比较简单粗暴了,直接静态定义,然后依次对数组元素初始化。

2.init_IRQ

init_IRQ不仅对IDT进行初始化,也对irq_desc进行了初始化

85 void __init init_IRQ(void)
 86 {
 87     int i;
 88
 89     /*
 90      * We probably need a better place for this, but it works for
 91      * now ...
 92      */
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值