ARM based Linux中断 (一)

7 篇文章 0 订阅
5 篇文章 0 订阅

在start_kernel会存在如下调用

start_kernel

       setup_arch

              early_trap_init

       early_irq_init

init_IRQ

local_irq_enable();

1      中断相关的初始化工作

内核配置选项关于中断子系统的配置如下:

CONFIG_GENERIC_HARDIRQS=y

CONFIG_HAVE_SPARSE_IRQ=y

CONFIG_GENERIC_IRQ_SHOW=y

CONFIG_SPARSE_IRQ=y  //support sparse irq numbering

1.1      中断向量表初始化

early_trap_init主要完成将中断向量表(__vectors_start, __vectors_end)和中断入口函数表(__stubs_start, __stubs_end)的相关代码copy到内存0xffff0000或者0x00000000处。

void __init early_trap_init(void)

{

#if defined(CONFIG_CPU_USE_DOMAINS)

       unsigned long vectors = CONFIG_VECTORS_BASE;

#else

       unsigned long vectors = (unsigned long)vectors_page;

#endif

       extern char __stubs_start[], __stubs_end[];

       extern char __vectors_start[], __vectors_end[];

       extern char __kuser_helper_start[], __kuser_helper_end[];

       int kuser_sz = __kuser_helper_end - __kuser_helper_start;

 

       /*

        * Copy the vectors, stubs and kuser helpers (in entry-armv.S)

        * into the vector page, mapped at 0xffff0000, and ensure these

        * are visible to the instruction stream.

        */

       memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);

       memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);

       memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);

 

       /*

        * Do processor specific fixups for the kuser helpers

        */

       kuser_get_tls_init(vectors);

 

       /*

        * Copy signal return handlers into the vector page, and

        * set sigreturn to be a pointer to these.

        */

       memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),

              sigreturn_codes, sizeof(sigreturn_codes));

       memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE),

              syscall_restart_code, sizeof(syscall_restart_code));

 

       flush_icache_range(vectors, vectors + PAGE_SIZE);

       modify_domain(DOMAIN_USER, DOMAIN_CLIENT);

}

1.2      irq_desc的初始化

内核支持sparse irq,因此early_irq_init对应的代码如下。该函数主要是用来初始化irq_desc结构,该结构使用radix tree组织起来。对不支持sparse irq的系统,irq_desc是以数组的形式组织起来的。

int __init early_irq_init(void)

{

       int i, initcnt, node = first_online_node;

       struct irq_desc *desc;

 

       init_irq_default_affinity();

 

       /* Let arch update nr_irqs and return the nr of preallocated irqs */

       initcnt = arch_probe_nr_irqs();

       printk(KERN_INFO "NR_IRQS:%d nr_irqs:%d %d\n", NR_IRQS, nr_irqs, initcnt);

 

       if (WARN_ON(nr_irqs > IRQ_BITMAP_BITS))

              nr_irqs = IRQ_BITMAP_BITS;

 

       if (WARN_ON(initcnt > IRQ_BITMAP_BITS))

              initcnt = IRQ_BITMAP_BITS;

 

       if (initcnt > nr_irqs)

              nr_irqs = initcnt;

       //完成irq_desc的初始化工作

       for (i = 0; i < initcnt; i++) {

              desc = alloc_desc(i, node);

              set_bit(i, allocated_irqs);

              irq_insert_desc(i, desc);

       }

       return arch_early_irq_init();  //直接返回为0

}

该函数完成irq的亲和性的初始化。

static void __init init_irq_default_affinity(void)

{

       alloc_cpumask_var(&irq_default_affinity, GFP_NOWAIT);

       cpumask_setall(irq_default_affinity);

}

 

static inline void cpumask_setall(struct cpumask *dstp)

{

       bitmap_fill(cpumask_bits(dstp), nr_cpumask_bits);

}

该函数完成的功能是设置相应的cpumask位为1。

1.3      中断控制器的初始化(GIC的初始化)

init_IRQ函数完成GIC(Generic Interrupt Controller)的初始化工作。

void __init init_IRQ(void)

{

       machine_desc->init_irq();

}

 

1.4      打开中断

local_irq_enable();

最终调用体系结构相关的代码完成中断的使能工作。针对arm v6以上的体系结构:

/arch/arm/include/asm/Irqflags.h

static inline void arch_local_irq_enable(void)

{

         asm volatile(

                   "        cpsie i                           @ arch_local_irq_enable"

                   :

                   :

                   : "memory", "cc");

}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值