2014년 12월 6일 토요일

[Linux Kernel] 81주차(2014.12.06)

ARM10C 81주차 후기

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

81주차 진도

  • start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()

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);
}
  • 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);
  • call: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()
    • // desc: kmem_cache#30-o11 (cortex_a15_gic)
    • kfree(desc);

kmem.h::kfree()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()
    • // desc: kmem_cache#30-o11 (cortex_a15_gic)
    • kfree(desc);
// ARM10C 20141129
// _RET_IP_: __builtin_return_address(0), object: kmem_cache#30-o11
DEFINE_EVENT(kmem_free, kfree,

    TP_PROTO(unsigned long call_site, const void *ptr),

    TP_ARGS(call_site, ptr)
);
// ARM10C 20141129
// desc: kmem_cache#30-o11 (cortex_a15_gic)
void kfree(const void *x)
{
    struct page *page;

    // x: kmem_cache#30-o11
    void *object = (void *)x;
    // object: kmem_cache#30-o11

    // _RET_IP_: __builtin_return_address(0), object: kmem_cache#30-o11
    trace_kfree(_RET_IP_, x);

    // x: kmem_cache#30-o11, ZERO_OR_NULL_PTR(kmem_cache#30-o11): 0
    if (unlikely(ZERO_OR_NULL_PTR(x)))
        return;

    // x: kmem_cache#30-o11
    // virt_to_head_page(kmem_cache#30-o11): kmem_cache#30-o11의 page 주소
    page = virt_to_head_page(x);
    // page: kmem_cache#30-o11의 page 주소

    // page: kmem_cache#30-o11의 page 주소
    // PageSlab(kmem_cache#30-o11의 page 주소): 1
    if (unlikely(!PageSlab(page))) {
        BUG_ON(!PageCompound(page));
        kfree_hook(x);
        __free_memcg_kmem_pages(page, compound_order(page));
        return;
    }

    // page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
    // page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11
    slab_free(page->slab_cache, page, object, _RET_IP_);
  • call: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()
    • // page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
    • // page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11
    • slab_free(page->slab_cache, page, object, RET_IP);

slub.c::slab_free()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()
    • // page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
    • // page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11
    • slab_free(page->slab_cache, page, object, RET_IP);
// ARM10C 20141206
// page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
// page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11, _RET_IP_
static __always_inline void slab_free(struct kmem_cache *s,
            struct page *page, void *x, unsigned long addr)
{
    // x: kmem_cache#30-o11
    void **object = (void *)x;
    // object: kmem_cache#30-o11

    struct kmem_cache_cpu *c;
    unsigned long tid;

    // s: kmem_cache#30, x: kmem_cache#30-o11
    slab_free_hook(s, x);
  • call: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()->slab_free_hook()
    • // s: kmem_cache#30, x: kmem_cache#30-o11
    • slab_free_hook(s, x);

slub.c::slab_free_hook()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()->slab_free_hook()
    • // s: kmem_cache#30, x: kmem_cache#30-o11
    • slab_free_hook(s, x);
// ARM10C 20141206
// s: kmem_cache#30, x: kmem_cache#30-o11
static inline void slab_free_hook(struct kmem_cache *s, void *x)
{
    // x: kmem_cache#30-o11, s->flags: (kmem_cache#30)->flags
    kmemleak_free_recursive(x, s->flags); // null function

    /*
     * Trouble is that we may no longer disable interrupts in the fast path
     * So in order to make the debug calls that expect irqs to be
     * disabled we need to disable interrupts temporarily.
     */
#if defined(CONFIG_KMEMCHECK) || defined(CONFIG_LOCKDEP) // CONFIG_KMEMCHECK=n, CONFIG_LOCKDEP=n
    {
        unsigned long flags;

        local_irq_save(flags);
        kmemcheck_slab_free(s, x, s->object_size);
        debug_check_no_locks_freed(x, s->object_size);
        local_irq_restore(flags);
    }
#endif
    // s->flags: (kmem_cache#30)->flags: 0, SLAB_DEBUG_OBJECTS: 0x00000000UL
    if (!(s->flags & SLAB_DEBUG_OBJECTS))
        // x: kmem_cache#30-o11, s->object_size: (kmem_cache#30)->object_size
        debug_check_no_obj_freed(x, s->object_size); // null function
}
  • return: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()

slub.c::slab_free()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()
    • // page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
    • // page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11
    • slab_free(page->slab_cache, page, object, RET_IP);
  • return: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()
// ARM10C 20141206
// page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
// page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11, _RET_IP_
static __always_inline void slab_free(struct kmem_cache *s,
            struct page *page, void *x, unsigned long addr)
{
...
    // s: kmem_cache#30, x: kmem_cache#30-o11
    slab_free_hook(s, x);
redo:
    /*
     * Determine the currently cpus per cpu slab.
     * The cpu may change afterward. However that does not matter since
     * data is retrieved via this pointer. If we are on the same cpu
     * during the cmpxchg then the free will succedd.
     */
    preempt_disable();
    // 선점 비활성화 수행

    // NOTE:
    // s->cpu_slab: (kmem_cache#30)->cpu_slab:
    // struct kmem_cache_cpu 자료구조를 사용하기 위해 할당받은 pcp 16 byte 메모리 공간

    // s->cpu_slab: (kmem_cache#30)->cpu_slab
    // __this_cpu_ptr((kmem_cache#30)->cpu_slab):
    // (kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋
    c = __this_cpu_ptr(s->cpu_slab);
    // c: (kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋

    // c->tid: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->tid
    tid = c->tid;
    // tid: XX (추적불가)

    preempt_enable();
    // 선점 활성화 수행

    // NOTE:
    // likely(page == c->page)는 likely로 싸여 있는 것으로 보아
    // page == c->page 가 같을 확율이 높다고 판단됨. page, c->page 값이 같다고 보고 코드 분석 진행

    // page: kmem_cache#30-o11의 page 주소,
    // c->page: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->page
    if (likely(page == c->page)) {
        // s: kmem_cache#30, object: kmem_cache#30-o11,
        // c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist
        set_freepointer(s, object, c->freelist);
  • call: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()->set_freepointer()
    • // s: kmem_cache#30, object: kmem_cache#30-o11,
    • // c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist
    • set_freepointer(s, object, c->freelist);

slub.c::set_freepointer()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()->set_freepointer()
    • // s: kmem_cache#30, object: kmem_cache#30-o11,
    • // c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist
    • set_freepointer(s, object, c->freelist);
// ARM10C 20141206
// s: kmem_cache#30, object: kmem_cache#30-o11,
// c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist
static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)
{
    // object: UNMOVABLE인 page 의 virtual address
    // s->offset: (&boot_kmem_cache_node)->offset: 0
    // fp: UNMOVABLE인 page 의 virtual address
    // object: UNMOVABLE인 page 의 virtual address(boot_kmem_cache)
    // s->offset: (&boot_kmem_cache_node)->offset: 0
    // fp: UNMOVABLE인 page 의 virtual address(boot_kmem_cache)
    *(void **)(object + s->offset) = fp;
    // object: UNMOVABLE인 page 의 virtual address(boot_kmem_cache)
}
  • return: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()

slub.c::slab_free()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()
    • // page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
    • // page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11
    • slab_free(page->slab_cache, page, object, RET_IP);
  • return: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()
// ARM10C 20141206
// page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
// page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11, _RET_IP_
static __always_inline void slab_free(struct kmem_cache *s,
            struct page *page, void *x, unsigned long addr)
{
...
    // s: kmem_cache#30, x: kmem_cache#30-o11
    slab_free_hook(s, x);
redo:
...
    // page: kmem_cache#30-o11의 page 주소,
    // c->page: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->page
    if (likely(page == c->page)) {
        // s: kmem_cache#30, object: kmem_cache#30-o11,
        // c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist
        set_freepointer(s, object, c->freelist);
        // kmem_cache#30-o11의 freepointer의 값을
        // ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist 값으로 세팅

        // s->cpu_slab->freelist: (kmem_cache#30)->cpu_slab->freelist,
        // s->cpu_slab->tid: (kmem_cache#30)->cpu_slab->tid,
        // c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
        // tid: XX, object: kmem_cache#30-o11, next_tid(tid): XX
        // this_cpu_cmpxchg_double((kmem_cache#30)->cpu_slab->freelist, (kmem_cache#30)->cpu_slab->tid,
        // ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
        // XX, kmem_cache#30-o11, XX): 1
        if (unlikely(!this_cpu_cmpxchg_double(
                s->cpu_slab->freelist, s->cpu_slab->tid,
                c->freelist, tid,
                object, next_tid(tid)))) {

            note_cmpxchg_failure("slab_free", s, tid);
            goto redo;
        }
  • call: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()->this_cpu_cmpxchg_double()
    • // s->cpu_slab->freelist: (kmem_cache#30)->cpu_slab->freelist,
    • // s->cpu_slab->tid: (kmem_cache#30)->cpu_slab->tid,
    • // c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
    • // tid: XX, object: kmem_cache#30-o11, next_tid(tid): XX
    • // this_cpu_cmpxchg_double((kmem_cache#30)->cpu_slab->freelist, (kmem_cache#30)->cpu_slab->tid,
    • // ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
    • // XX, kmem_cache#30-o11, XX): 1
    • if (unlikely(!this_cpu_cmpxchg_double(s->cpu_slab->freelist, s->cpu_slab->tid,c->freelist, tid,object, next_tid(tid)))) 

percpu.h::this_cpu_cmpxchg_double()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()->this_cpu_cmpxchg_double()
    • // s->cpu_slab->freelist: (kmem_cache#30)->cpu_slab->freelist,
    • // s->cpu_slab->tid: (kmem_cache#30)->cpu_slab->tid,
    • // c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
    • // tid: XX, object: kmem_cache#30-o11, next_tid(tid): XX
    • // this_cpu_cmpxchg_double((kmem_cache#30)->cpu_slab->freelist, (kmem_cache#30)->cpu_slab->tid,
    • // ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
    • // XX, kmem_cache#30-o11, XX): 1
    • if (unlikely(!this_cpu_cmpxchg_double(s->cpu_slab->freelist, s->cpu_slab->tid,c->freelist, tid,object, next_tid(tid)))) 
// ARM10C 20141206
// s->cpu_slab->freelist: (kmem_cache#30)->cpu_slab->freelist,
// s->cpu_slab->tid: (kmem_cache#30)->cpu_slab->tid,
// c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
// tid: XX (추적불가), object: kmem_cache#30-o11, next_tid(tid): XX
# define this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)    \
    __pcpu_double_call_return_bool(this_cpu_cmpxchg_double_, (pcp1), (pcp2), (oval1), (oval2), (nval1), (nval2))
#endif

percpu.h::__pcpu_double_call_return_bool()

#define __pcpu_double_call_return_bool(stem, pcp1, pcp2, ...)       \
({                                  \
    bool pdcrb_ret__;                       \
    __verify_pcpu_ptr(&pcp1);                   \
    BUILD_BUG_ON(sizeof(pcp1) != sizeof(pcp2));         \
    VM_BUG_ON((unsigned long)(&pcp1) % (2 * sizeof(pcp1)));     \
    VM_BUG_ON((unsigned long)(&pcp2) !=             \
          (unsigned long)(&pcp1) + sizeof(pcp1));       \
    switch(sizeof(pcp1)) {                      \
    case 1: pdcrb_ret__ = stem##1(pcp1, pcp2, __VA_ARGS__); break;  \
    case 2: pdcrb_ret__ = stem##2(pcp1, pcp2, __VA_ARGS__); break;  \
    case 4: pdcrb_ret__ = stem##4(pcp1, pcp2, __VA_ARGS__); break;  \
    case 8: pdcrb_ret__ = stem##8(pcp1, pcp2, __VA_ARGS__); break;  \
    default:                            \
        __bad_size_call_parameter(); break;         \
    }                               \
    pdcrb_ret__;                            \
})
  • return: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()

slub.c::slab_free()

  • called: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()
    • // page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
    • // page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11
    • slab_free(page->slab_cache, page, object, RET_IP);
  • return: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()->slab_free()->this_cpu_cmpxchg_double()
// ARM10C 20141206
// page->slab_cache: (kmem_cache#30-o11의 page 주소)->slab_cache,
// page: kmem_cache#30-o11의 page 주소, object: kmem_cache#30-o11, _RET_IP_
static __always_inline void slab_free(struct kmem_cache *s,
            struct page *page, void *x, unsigned long addr)
{
...
    // s: kmem_cache#30, x: kmem_cache#30-o11
    slab_free_hook(s, x);
redo:
...
    // page: kmem_cache#30-o11의 page 주소,
    // c->page: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->page
    if (likely(page == c->page)) {
        // s: kmem_cache#30, object: kmem_cache#30-o11,
        // c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist
        set_freepointer(s, object, c->freelist);
        // kmem_cache#30-o11의 freepointer의 값을
        // ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist 값으로 세팅

        // s->cpu_slab->freelist: (kmem_cache#30)->cpu_slab->freelist,
        // s->cpu_slab->tid: (kmem_cache#30)->cpu_slab->tid,
        // c->freelist: ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
        // tid: XX, object: kmem_cache#30-o11, next_tid(tid): XX
        // this_cpu_cmpxchg_double((kmem_cache#30)->cpu_slab->freelist, (kmem_cache#30)->cpu_slab->tid,
        // ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist,
        // XX, kmem_cache#30-o11, XX): 1
        if (unlikely(!this_cpu_cmpxchg_double(
                s->cpu_slab->freelist, s->cpu_slab->tid,
                c->freelist, tid,
                object, next_tid(tid)))) {

            note_cmpxchg_failure("slab_free", s, tid);
            goto redo;
        }
        // this_cpu_cmpxchg_double에서 한일:
        // 값 s->cpu_slab->freelist와 c->freelist를 비교, 값 s->cpu_slab->tid와 tid을 비교 하여
        // 같을 경우에 s->cpu_slab->freelist와 s->cpu_slab->tid을 각각 object, next_tid(tid) 값으로 갱신하여
        // freelist와 tid 값을 변경함

        // s: kmem_cache#30, FREE_FASTPATH: 2
        stat(s, FREE_FASTPATH); // null function
    } else
        __slab_free(s, page, x, addr);

}
  • return: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()

kfree()에서 한일:

// (kmem_cache#30)->cpu_slab: struct kmem_cache_cpu 자료구조를 사용하기 위해 할당받은 pcp 16 byte 메모리 공간을 구하여 // kmem_cache#30-o11의 freepointer의 값을 // ((kmem_cache#30)->cpu_slab + (pcpu_unit_offsets[0] + __per_cpu_start에서의pcpu_base_addr의 옵셋)->freelist 값으로 세팅 // 값 s->cpu_slab->freelist와 c->freelist를 비교, 값 s->cpu_slab->tid와 tid을 비교 하여 // 같을 경우에 s->cpu_slab->freelist와 s->cpu_slab->tid을 각각 object, next_tid(tid) 값으로 갱신하여 // freelist와 tid 값을 변경함 // kmem_cache_cpu의 freelist, tid 의 값을 변경함

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);
  • return: start_kernel()->init_IRQ()->irqchip_init()->of_irq_init()->kfree()
void __init of_irq_init(const struct of_device_id *matches)
{
...
    // 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-o11 (cortex_a15_gic)
        kfree(desc);
    }

    list_for_each_entry_safe(desc, temp_desc, &intc_parent_list, list) {
        list_del(&desc->list);
        kfree(desc);
    }
err:
    list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
        list_del(&desc->list);
        kfree(desc);
    }
}

log

  • 1st log
   691ad42..e884ca4  master     -> origin/master
Updating 691ad42..e884ca4
Fast-forward
arch/arm/include/asm/bitops.h     |   2 +
arch/arm/include/asm/io.h         |   2 +
arch/arm/mm/ioremap.c             | 110 +++++++++++++++++-
drivers/irqchip/exynos-combiner.c |  42 ++++++-
drivers/of/address.c              |  16 +++
drivers/of/base.c                 |  13 +++
drivers/of/irq.c                  |  79 +++++++++----
include/asm-generic/percpu.h      |   1 +
include/linux/debugobjects.h      |   3 +-
include/linux/gfp.h               |   2 +
include/linux/irqdomain.h         |   1 +
include/linux/kernel.h            |   1 +
include/linux/kmemleak.h          |   1 +
include/linux/list.h              |   9 +-
include/linux/of.h                |   4 +
include/linux/percpu.h            |   5 +
include/linux/preempt.h           |   2 +
include/linux/rbtree.h            |  17 +--
include/linux/rculist.h           |   2 +
include/linux/slab.h              |  44 ++++++++
include/linux/slub_def.h          |   3 +
kernel/irq/irqdomain.c            |  64 +++++++++++
lib/ioremap.c                     |   3 +
lib/rbtree.c                      |  12 +-
mm/slab_common.c                  |   9 ++
mm/slub.c                         |  91 ++++++++++++++-
mm/vmalloc.c                      | 230 ++++++++++++++++++++++++++++++++++++--
27 files changed, 713 insertions(+), 55 deletions(-)
  • 2nd log
   e884ca4..2ed370b  master     -> origin/master
Updating e884ca4..2ed370b
Fast-forward
drivers/irqchip/exynos-combiner.c |  64 ++++++++++++++++++++++++++++++++++++--
drivers/of/base.c                 |   4 +--
drivers/of/irq.c                  | 233 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------------------------------------------
3 files changed, 185 insertions(+), 116 deletions(-)

2014년 12월 1일 월요일

OPNFV Initial Distribution

OPNFV Distribution

  • OPNFV Support mulitple distributions
    • Ubuntu
    • Redhat (CentOS)
    • Fedora
  • Initial kick start distribution
  • LTM (Long Term Evolution)

Initial Distribution selection

  • Several Project
    • OpenStack
    • ODL (Open Daylight)
    • Infra Set up language support (Puppet, Juju)
    • Plugins Availability
    • Virtual Enviroment
    • Bare metal platform support



Criteria
RHEL
CentOS
Ubuntu
Fedora
Devstack
Release
7
7
14.10
21
Latest
Installer
Packstack
Packstack
JuJu, Fuel
Packstack (RDO), DevStack
Devstack
Support
Yes
Community
Yes
Community
No
Resident Developer





Openstack Release
Juno (RDO), Icehouse (RHEL OSP)
Juno (RDO)
Juno
Icehouse (packaged), Juno (RDO)
Kilo
ODL Release



Hydrogen, Helium (not in repositories)

Installer Languages
Puppet
Puppet
Puppet
Puppet (RDO), bash (Devstack)

Plugins Availability





Ease of Development


Yes


Virtual Environment


Vagrant, Kvm, Docker, LXC etc
Qemu/kvm, Docker, lxc etc

Zero Touch including PXE Boot


Yes (JuJu/MaaS/Cobbler)


Troubleshooting Ease





Long Term Evolution


14.04


Automated Testing Framework Integration


OSTF


Kernel Version
3.10
3.10
3.14 (Realtime Patch)
3.17

Qemu version
2.0
2.0
2.0
2.1