2014년 12월 20일 토요일

[Linux Kernel] 83주차(2014.12.20)

ARM10C 83주차 후기

일시 : 2014.12.20 (83주차)
모임명 : NAVER개발자커뮤니티지원_IAMROOT.ORG_10차ARM-C
장소 : 토즈 타워점
장소지원 : NAVER 개발자 커뮤니티 지원 프로그램
참여인원 : 3명

83주차 진도

  • start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->combiner_init() a* of_irq_init()에서 2번째 루프인 combiner_init()을 진행합니다.

main.c::start_kernel()

asmlinkage void __init start_kernel(void)
{
...
    setup_arch(&command_line);
...
    mm_init();
    // buddy와 slab 을 활성화 하고 기존 할당 받은 bootmem 은 buddy,
    // pcpu 메모리, vmlist 는 slab으로 이관
...
    rcu_init();
    // rcu 자료구조 bh, sched, preempt 를 각각 초기화 수행함
...
    /* init some links before init_ISA_irqs() */
    early_irq_init();
    // irq_desc 0 ~ 15 까지의 object을 할당 받고 초기화를 수행
    // allocated_irqs에 bit를 1로 세팅하고 radix tree에 각 irq_desc를 노트로 추가

    init_IRQ();
  • call: start_kernel()->init_IRQ()
    • init_IRQ();

irq.c::init_IRQ()

  • called: start_kernel()->init_IRQ()
    • init_IRQ();
// ARM10C 20141004
void __init init_IRQ(void)
{
    // CONFIG_OF=y, machine_desc->init_irq: __mach_desc_EXYNOS5_DT.init_irq: 0
    if (IS_ENABLED(CONFIG_OF) && !machine_desc->init_irq)
        irqchip_init();
    else
        machine_desc->init_irq();
}
  • call: start_kernel()->init_IRQ()->irqchip_init()
    • irqchip_init();

irqchip.h::irqchip_init()

  • called: start_kernel()->init_IRQ()->irqchip_init()
    • irqchip_init();
// ARM10C 20141004
extern struct of_device_id __irqchip_begin[];

// ARM10C 20141004
void __init irqchip_init(void)
{
    // exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
    // __irqchip_begin: irqchip_of_match_exynos4210_combiner
    of_irq_init(__irqchip_begin);
}
#ifdef CONFIG_IRQCHIP // CONFIG_IRQCHIP=y
#define IRQCHIP_OF_MATCH_TABLE()            \
    . = ALIGN(8);                           \
    VMLINUX_SYMBOL(__irqchip_begin) = .;    \
    *(__irqchip_of_table)                   \
    *(__irqchip_of_end)
#else
#define IRQCHIP_OF_MATCH_TABLE()
#endif
  • call: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()
    • // exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
    • // __irqchip_begin: irqchip_of_match_exynos4210_combiner
    • of_irq_init(__irqchip_begin);

irqchip.h::irqchip_init()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()
    • // exynos-combiner.c 에 정의된 함수를 사용하여 초기화 수행
    • // __irqchip_begin: irqchip_of_match_exynos4210_combiner
    • of_irq_init(__irqchip_begin);
void __init of_irq_init(const struct of_device_id *matches)
{
    struct device_node *np, *parent = NULL;
    // parent: NULL
    struct intc_desc *desc, *temp_desc;
    struct list_head intc_desc_list, intc_parent_list;

    INIT_LIST_HEAD(&intc_desc_list);
    // intc_desc_list 리스트 초기화 수행

    INIT_LIST_HEAD(&intc_parent_list);
    // intc_parent_list 리스트 초기화 수행

    // matches: irqchip_of_match_exynos4210_combiner
    for_each_matching_node(np, matches) {
    // for (np = of_find_matching_node(NULL, matches); np; np = of_find_matching_node(np, matches))

        // np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
        // of_find_property(devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소, "interrupt-controller", NULL):
        // combiner node의 "interrupt-controller" property의 주소
        // np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
        // of_find_property(devtree에서 allnext로 순회 하면서 찾은 gic node의 주소, "interrupt-controller", NULL):
        // gic node의 "interrupt-controller" property의 주소
        if (!of_find_property(np, "interrupt-controller", NULL))
            continue;
        /*
         * Here, we allocate and populate an intc_desc with the node
         * pointer, interrupt-parent device_node etc.
         */
        // sizeof(struct intc_desc): 16 bytes, GFP_KERNEL: 0xD0
        // kzalloc(16, GFP_KERNEL: 0xD0): kmem_cache#30-o10
        // sizeof(struct intc_desc): 16 bytes, GFP_KERNEL: 0xD0
        // kzalloc(16, GFP_KERNEL: 0xD0): kmem_cache#30-o11
        desc = kzalloc(sizeof(*desc), GFP_KERNEL);
        // desc: kmem_cache#30-o10
        // desc: kmem_cache#30-o11

        // desc: kmem_cache#30-o10
        // desc: kmem_cache#30-o11
        if (WARN_ON(!desc))
            goto err;

        // desc->dev: (kmem_cache#30-o10)->dev, np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
        // desc->dev: (kmem_cache#30-o11)->dev, np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
        desc->dev = np;
        // desc->dev: (kmem_cache#30-o10)->dev: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
        // desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소

        // desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent, np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
        // of_irq_find_parent(devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소): gic node 주소
        // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent, np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
        // of_irq_find_parent(devtree에서 allnext로 순회 하면서 찾은 gic node의 주소): gic node 주소
        desc->interrupt_parent = of_irq_find_parent(np);
        // desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent: gic node 주소
        // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: gic node 주소

        // desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent: gic node 주소
        // np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
        // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: gic node 주소
        // np: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
        if (desc->interrupt_parent == np)
            // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: gic node 주소
            desc->interrupt_parent = NULL;
            // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL

        // &desc->list: &(kmem_cache#30-o10)->list
        // &desc->list: &(kmem_cache#30-o11)->list
        list_add_tail(&desc->list, &intc_desc_list);
        // intc_desc_list에 (kmem_cache#30-o10)->list를 tail에 추가
        // intc_desc_list에 (kmem_cache#30-o11)->list를 tail에 추가
    }

    // irqchip_of_match_exynos4210_combiner, irqchip_of_match_cortex_a15_gic 의
    // struct intc_desc 메모리 할당, intc_desc 맴버가 초기화 된 값이 intc_desc_list list의 tail로 추가됨

    // list_empty(&intc_desc_list): 0
    while (!list_empty(&intc_desc_list)) {
        list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
        // for (desc = list_first_entry(&intc_desc_list, typeof(*desc), list),
        //  temp_desc = list_next_entry(desc, list);
        //      &desc->list != (&intc_desc_list);
        //      desc = temp_desc, temp_desc = list_next_entry(temp_desc, list))

            // desc: kmem_cache#30-o10 (exynos4210_combiner), temp_desc: kmem_cache#30-o11 (cortex_a15_gic)
            // desc: kmem_cache#30-o11 (cortex_a15_gic), temp_desc: NULL

            const struct of_device_id *match;
            int ret;
            of_irq_init_cb_t irq_init_cb;

            // desc->interrupt_parent: (kmem_cache#30-o10)->interrupt_parent: gic node 주소, parent: NULL
            // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL, parent: NULL
            if (desc->interrupt_parent != parent)
                continue;
                // continue 수행 (exynos4210_combiner)

            // &desc->list: (kmem_cache#30-o11)->list
            list_del(&desc->list);
            // intc_desc_list에서 (kmem_cache#30-o11)->list를 삭제

            // matches: irqchip_of_match_cortex_a15_gic,
            // desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
            // of_match_node(cortex_a15_gic, devtree에서 allnext로 순회 하면서 찾은 gic node의 주소):
            // irqchip_of_match_cortex_a15_gic
            match = of_match_node(matches, desc->dev);
            // match: irqchip_of_match_cortex_a15_gic

            // match->data; irqchip_of_match_cortex_a15_gic.data: gic_of_init
            if (WARN(!match->data,
                "of_irq_init: no init function for %s\n",
                match->compatible)) {
                kfree(desc);
                continue;
            }

            // match->compatible: irqchip_of_match_cortex_a15_gic.compatible: "arm,cortex-a15-gic",
            // desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
            // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL
            pr_debug("of_irq_init: init %s @ %p, parent %p\n",
                 match->compatible,
                 desc->dev, desc->interrupt_parent);
            // "of_irq_init: init arm,cortex-a15-gic @ 0x(gic node의 주소), parent 0\n"

            // match->data; irqchip_of_match_cortex_a15_gic.data: gic_of_init
            irq_init_cb = (of_irq_init_cb_t)match->data;
            // irq_init_cb: gic_of_init

            // desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소,
            // desc->interrupt_parent: (kmem_cache#30-o11)->interrupt_parent: NULL
            // gic_of_init(devtree에서 allnext로 순회 하면서 찾은 gic node의 주소, NULL):
            ret = irq_init_cb(desc->dev, desc->interrupt_parent);

            // ret: 0
            if (ret) {
                kfree(desc);
                continue;
            }
            /*
             * This one is now set up; add it to the parent list so
             * its children can get processed in a subsequent pass.
             */
            // &desc->list: &(kmem_cache#30-o11)->list
            list_add_tail(&desc->list, &intc_parent_list);
            // intc_parent_list에 tail로 &(kmem_cache#30-o11)->list를 추가
        }
        // &desc->list: &intc_desc_list 이므로  loop 탈출

        /* Get the next pending parent that might have children */
        // typeof(*desc): struct intc_desc
        // list_first_entry_or_null(&intc_parent_list, struct intc_desc, list):
        // (!list_empty(&intc_parent_list) ? list_first_entry(&intc_parent_list, struct intc_desc, list) : NULL)
        // list_first_entry(&intc_parent_list, struct intc_desc, list): kmem_cache#30-o11 (cortex_a15_gic)
        desc = list_first_entry_or_null(&intc_parent_list,
                        typeof(*desc), list);
        // desc: kmem_cache#30-o11 (cortex_a15_gic)

        // desc: kmem_cache#30-o11 (cortex_a15_gic)
        if (!desc) {
            pr_err("of_irq_init: children remain, but no parents\n");
            break;
        }

        // &desc->list: &(kmem_cache#30-o11 (cortex_a15_gic))->list
        list_del(&desc->list);
        // &(kmem_cache#30-o11 (cortex_a15_gic))->list에 연결된 list 삭제

        // parent: NULL
        // desc->dev: (kmem_cache#30-o11)->dev: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소
        parent = desc->dev;
        // parent: devtree에서 allnext로 순회 하면서 찾은 gic node의 주소

        // desc: kmem_cache#30-o11 (cortex_a15_gic)
        kfree(desc);

exynos-combiner.c::combiner_init()

// ARM10C 20141206
// combiner_base: 0xf0004000, np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소,
// max_nr: 32, irq_base: 160
static void __init combiner_init(void __iomem *combiner_base,
                 struct device_node *np,
                 unsigned int max_nr,
                 int irq_base)
{
    int i, irq;
    unsigned int nr_irq;
    struct combiner_chip_data *combiner_data;

    // max_nr: 32, IRQ_IN_COMBINER: 8
    nr_irq = max_nr * IRQ_IN_COMBINER;
    // nr_irq: 256

    // max_nr: 32, sizeof(struct combiner_chip_data): 16 bytes, GFP_KERNEL: 0xD0
    // kcalloc(32, 16, GFP_KERNEL: 0xD0): kmem_cache#26-oX
    combiner_data = kcalloc(max_nr, sizeof (*combiner_data), GFP_KERNEL);
    // combiner_data: kmem_cache#26-oX

    // combiner_data: kmem_cache#26-oX
    if (!combiner_data) {
        pr_warning("%s: could not allocate combiner data\n", __func__);
        return;
    }

    // np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소,
    // nr_irq: 256, irq_base: 160, combiner_data: kmem_cache#26-oX
    // irq_domain_add_simple(devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소, 256
    // 160, &combiner_irq_domain_ops, kmem_cache#26-oX (combiner_data): kmem_cache#24-o0
    combiner_irq_domain = irq_domain_add_simple(np, nr_irq, irq_base,
                &combiner_irq_domain_ops, combiner_data);
    // combiner_irq_domain: kmem_cache#24-o0

    // irq_domain_add_simple에서 한일:
    // struct irq_domain를 위한 메모리 할당: kmem_cache#24-o0
    // (&(kmem_cache#24-o0)->revmap_tree)->height: 0
    // (&(kmem_cache#24-o0)->revmap_tree)->gfp_mask: (GFP_KERNEL: 0xD0)
    // (&(kmem_cache#24-o0)->revmap_tree)->rnode: NULL
    // (kmem_cache#24-o0)->ops: &combiner_irq_domain_ops
    // (kmem_cache#24-o0)->host_data: kmem_cache#26-oX (combiner_data)
    // (kmem_cache#24-o0)->of_node: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소
    // (kmem_cache#24-o0)->hwirq_max: 256
    // (kmem_cache#24-o0)->revmap_size: 256
    // (kmem_cache#24-o0)->revmap_direct_max_irq: 0
    //
    // irq_domain_list에 (kmem_cache#24-o0)->link를 추가
    /*
    // struct irq_desc의 자료 구조크기 만큼 256개의 메모리를 할당 받아
    // radix tree 구조로 구성
    //
    // radix tree의 root node: &irq_desc_tree 값을 변경
    // (&irq_desc_tree)->rnode: kmem_cache#20-o1 (RADIX_LSB: 1)
    // (&irq_desc_tree)->height: 2
    //
    // (kmem_cache#20-o1)->height: 2
    // (kmem_cache#20-o1)->count: 7
    // (kmem_cache#20-o1)->parent: NULL
    // (kmem_cache#20-o1)->slots[0]: kmem_cache#20-o0 (radix height 1 관리 주소)
    // (kmem_cache#20-o1)->slots[1]: kmem_cache#20-o2 (radix height 1 관리 주소)
    // (kmem_cache#20-o1)->slots[2]: kmem_cache#20-o3 (radix height 1 관리 주소)
    // (kmem_cache#20-o1)->slots[3]: kmem_cache#20-o4 (radix height 1 관리 주소)
    // (kmem_cache#20-o1)->slots[4]: kmem_cache#20-o5 (radix height 1 관리 주소)
    // (kmem_cache#20-o1)->slots[5]: kmem_cache#20-o6 (radix height 1 관리 주소)
    // (kmem_cache#20-o1)->slots[6]: kmem_cache#20-o7 (radix height 1 관리 주소)
    //
    // (kmem_cache#20-o0)->height: 1
    // (kmem_cache#20-o0)->count: 64
    // (kmem_cache#20-o0)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
    // (kmem_cache#20-o0)->slots[0...63]: kmem_cache#28-oX (irq 0...63)
    //
    // (kmem_cache#20-o2)->height: 1
    // (kmem_cache#20-o2)->count: 64
    // (kmem_cache#20-o2)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
    // (kmem_cache#20-o2)->slots[0...63]: kmem_cache#28-oX (irq 63...127)
    //
    // (kmem_cache#20-o3)->height: 1
    // (kmem_cache#20-o3)->count: 64
    // (kmem_cache#20-o3)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
    // (kmem_cache#20-o3)->slots[0...63]: kmem_cache#28-oX (irq 127...191)
    //
    // (kmem_cache#20-o4)->height: 1
    // (kmem_cache#20-o4)->count: 64
    // (kmem_cache#20-o4)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
    // (kmem_cache#20-o4)->slots[0...63]: kmem_cache#28-oX (irq 192...255)
    //
    // (kmem_cache#20-o5)->height: 1
    // (kmem_cache#20-o5)->count: 64
    // (kmem_cache#20-o5)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
    // (kmem_cache#20-o5)->slots[0...63]: kmem_cache#28-oX (irq 256...319)
    //
    // (kmem_cache#20-o6)->height: 1
    // (kmem_cache#20-o6)->count: 64
    // (kmem_cache#20-o6)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
    // (kmem_cache#20-o6)->slots[0...63]: kmem_cache#28-oX (irq 320...383)
    //
    // (kmem_cache#20-o7)->height: 1
    // (kmem_cache#20-o7)->count: 32
    // (kmem_cache#20-o7)->parent: kmem_cache#20-o1 (RADIX_LSB: 1)
    // (kmem_cache#20-o7)->slots[0...31]: kmem_cache#28-oX (irq 384...415)
    //
    // (&irq_desc_tree)->rnode -->  +-----------------------+
    //                              |    radix_tree_node    |
    //                              |   (kmem_cache#20-o1)  |
    //                              +-----------------------+
    //                              | height: 2 | count: 7  |
    //                              +-----------------------+
    //                              | radix_tree_node 0 ~ 6 | \
    //                            / +-----------------------+ \ \
    //                          /  /           |  |          \  \ \ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
    //  slot: 0               /   | slot: 1    |  |           |   \              slot: 2    |
    //  +-----------------------+ | +-----------------------+ | +-----------------------+   |
    //  |    radix_tree_node    | | |    radix_tree_node    | | |    radix_tree_node    |   |
    //  |   (kmem_cache#20-o0)  | | |   (kmem_cache#20-o2)  | | |   (kmem_cache#20-o3)  |   |
    //  +-----------------------+ | +-----------------------+ | +-----------------------+   |
    //  | height: 1 | count: 64 | | | height: 1 | count: 64 | | | height: 1 | count: 64 |   |
    //  +-----------------------+ | +-----------------------+ | +-----------------------+   |
    //  |    irq  0 ~ 63        | | |    irq 64 ~ 127       | | |    irq 128 ~ 191      |   |
    //  +-----------------------+ | +-----------------------+ | +-----------------------+   |
    //                           /                |            \                            |
    //  slot: 3                /    slot: 4       |              \                slot: 5    \                slot: 6
    //  +-----------------------+   +-----------------------+   +-----------------------+   +-----------------------+
    //  |    radix_tree_node    |   |    radix_tree_node    |   |    radix_tree_node    |   |    radix_tree_node    |
    //  |   (kmem_cache#20-o4)  |   |   (kmem_cache#20-o5)  |   |   (kmem_cache#20-o6)  |   |   (kmem_cache#20-o7)  |
    //  +-----------------------+   +-----------------------+   +-----------------------+   +-----------------------+
    //  | height: 1 | count: 64 |   | height: 1 | count: 64 |   | height: 1 | count: 64 |   | height: 1 | count: 32 |
    //  +-----------------------+   +-----------------------+   +-----------------------+   +-----------------------+
    //  |    irq  192 ~ 255     |   |    irq 256 ~ 319      |   |    irq 320 ~ 383      |   |    irq 384 ~ 415      |
    //  +-----------------------+   +-----------------------+   +-----------------------+   +-----------------------+
    */
    // irq 160...415까지의 struct irq_data에 값을 설정
    //
    // (&(kmem_cache#28-oX (irq 160...415))->irq_data)->hwirq: 0...255
    // (&(kmem_cache#28-oX (irq 160...415))->irq_data)->domain: kmem_cache#24-o0
    // (&(kmem_cache#28-oX (irq 160...415))->irq_data)->state_use_accessors: 0x10800
    //
    // (kmem_cache#28-oX (irq 160...415))->irq_data.chip: &combiner_chip
    // (kmem_cache#28-oX (irq 160...415))->handle_irq: handle_level_irq
    // (kmem_cache#28-oX (irq 160...415))->name: NULL
    //
    // (kmem_cache#28-oX (irq 160...167))->irq_data.chip_data: &(kmem_cache#26-oX)[0] (combiner_data)
    // (kmem_cache#28-oX (irq 168...175))->irq_data.chip_data: &(kmem_cache#26-oX)[1] (combiner_data)
    // ......
    // (kmem_cache#28-oX (irq 408...415))->irq_data.chip_data: &(kmem_cache#26-oX)[31] (combiner_data)
    //
    // (kmem_cache#28-oX (irq 160...415))->status_use_accessors: 0x31600
    //
    // (kmem_cache#24-o0)->name: "COMBINER"
    // (kmem_cache#24-o0)->linear_revmap[0...255]: 160...415

    // combiner_irq_domain: kmem_cache#24-o0
    if (WARN_ON(!combiner_irq_domain)) {
        pr_warning("%s: irq domain init failed\n", __func__);
        return;
    }

    // max_nr: 32
    for (i = 0; i < max_nr; i++) {
        // np: devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소, i: 0
        // irq_of_parse_and_map(devtree에서 allnext로 순회 하면서 찾은 combiner node의 주소, 0): 32
        irq = irq_of_parse_and_map(np, i);
        // irq: 32

        // i: 0, &combiner_data[0], combiner_base: 0xf0004000, irq: 32
        combiner_init_one(&combiner_data[i], i,
                  combiner_base + (i >> 2) * 0x10, irq);

        // combiner_init_one에서 한일:
        // (&combiner_data[0])->base: 0xf0004000
        // (&combiner_data[0])->hwirq_offset: 0
        // (&combiner_data[0])->irq_mask: 0xff
        // (&combiner_data[0])->parent_irq: 32
        // group 0 의 interrupt disable 설정

        // i: 0, &combiner_data[0], irq: 32
        combiner_cascade_irq(&combiner_data[i], irq);

        // combiner_cascade_irq에서 한일:
        // (kmem_cache#28-oX (irq 32))->irq_data.handler_data: &combiner_data[0]
        // (kmem_cache#28-oX (irq 32))->handle_irq: combiner_handle_cascade_irq
        // (kmem_cache#28-oX (irq 32))->status_use_accessors: 0x31e00
        // (kmem_cache#28-oX (irq 32))->depth: 0
        // (&(kmem_cache#28-oX (irq 32))->irq_data)->state_use_accessors: 0x800
        //
        // register GICD_ISENABLER1 의 값을 세팅 하여 irq 32의 interrupt를 enable 시킴
    }
    // 루프 수행결과:

}
  • 루프 실행결과를 정리해 보면.
    • // (&combiner_data[0])->base: 0xf0004000
    • // (&combiner_data[0])->hwirq_offset: 0
    • // (&combiner_data[0])->irq_mask: 0xff
    • // (&combiner_data[0])->parent_irq: 32
    • // group 0 의 interrupt disable 설정
  • trap.c에 보면 memcpy로 vector와 stubs를 복제했다. stubs에 0x1000을 이후 위치부터 복사했다.
// ARM10C 20131109
__vectors_start:
    W(b)    vector_rst
    W(b)    vector_und
    W(ldr)  pc, __vectors_start + 0x1000
    W(b)    vector_pabt
    W(b)    vector_dabt
    W(b)    vector_addrexcptn
    W(b)    vector_irq
    W(b)    vector_fiq
  • IRQ가 걸리면, __vectors_start:로 가서 *o W(b) vector_irq
  • vectors_base()에서 vectors_high()가 1이면 0xffff0000로 처리한다.
  • vectors_high()가 참조하는 cr_alignement는
  • cr_alignment: 0x10c5387d, CR_V: (1 << 13)
  • 이고 여기서 13번째 비트는???
irq_hander를 .macro irq_handler를 찾아서 gic와 combiner을 설정하면서 만든 init_IRQ에서 이 핸들러를 등록했었다. set_handle_irq()에서 등록을 했었다.
vector_stub은 vm
## log
* 1st log

c9e1c12..5ce95d8 master -> origin/master Updating c9e1c12..5ce95d8 Fast-forward drivers/irqchip/exynos-combiner.c | 37 +++++++++++ drivers/irqchip/irq-gic.c | 37 +++++++++++ include/linux/irq.h | 20 ++++++ include/linux/irqchip/arm-gic.h | 1 + include/linux/irqdesc.h | 1 + kernel/irq/chip.c | 125 ++++++++++++++++++++++++++++++++++++-- kernel/irq/internals.h | 18 ++++++ kernel/irq/resend.c | 11 +++- kernel/irq/settings.h | 21 +++++++ 9 files changed, 266 insertions(+), 5 deletions(-)

* 2nd Log
5ce95d8..84d1280 master -> origin/master Updating 5ce95d8..84d1280 Fast-forward arch/arm/kernel/entry-armv.S | 40 ++++ arch/arm/kernel/vmlinux.lds.S | 5 + drivers/irqchip/exynos-combiner.c | 367 ++++++++++++++++++++++++++++++ drivers/irqchip/irqchip.c | 455 ++++++++++++++++++++++++++++++++++++++ drivers/of/irq.c | 262 +++++++++++++++++++++- init/main.c | 3 + mm/slub.c | 2 + 7 files changed, 1132 insertions(+), 2 deletions(-)

* 3th log

84d1280..1342489 master -> origin/master Updating 84d1280..1342489 Fast-forward drivers/irqchip/exynos-combiner.c | 6 +++--- drivers/irqchip/irqchip.c | 2 +- drivers/of/irq.c | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-)

댓글 없음:

댓글 쓰기