Tuesday, May 19, 2009

Booting Linux on ARM Processor in Depth

  • Kernel entry point is in arch/arm/kernel/head.S
    This file starts with a check (TEXT_ADDR & 0xffff) != 0x8000, this is because page tables are placed 16k below KERNEL_RAM_VADDR
    arch/arm/kernel/head.S: stext
    enable supervisor mode
    disable IRQ
    call __lookup_processor_type
    defined in arch/arm/kernel/head-common.S
    search list of supported processor types __proc_info_begin
    kernel may be built to support more than one processor type
    list of proc_info_list structs
    defined in arch/arm/mm/proc-arm926.S and other corresponding proc-*.S files
    linked into list by section declaration: .section ".proc.info.init"
    return pointer to proc_info_list struct corresponding to processor if found, or loop in
    error if not
    call __lookup_machine_type
    defined in arch/arm/kernel/head-common.S
    search list of supported machines (boards)
    kernel may be built to support more than one board
    list of machine_desc structs
    machine_desc struct for boards defined in board-specific file vx115_vep.c
    linked into list by section declaration that's part of MACHINE_DESC macro
    return pointer to machine_desc struct corresponding to machine (board)
    call __vet_atags

    defined in arch/arm/kernel/head-common.S
    validate the R2 reg, which locates to the structure that holds the parameters passed
    by the
    bootloader.
    Return either valid atags pointer or zero
    call __create_page_tables to set up initial MMU tables
    Return – R4 containing the physical page table address
    set lr to __enable_mmu, r13 to address of __switch_data
    lr and r13 used for jumps after the following calls
    __switch_data defined in arch/arm/kernel/head-common.S
    call the __cpu_flush function pointer in the previously returned proc_info_list struct
    offset is #PROCINFO_INITFUNC into struct
    this function is __arm926_setup for the ARM 926EJ-S, defined in arch/arm/mm/proc-arm926.S
    initialize caches, writebuffer jump to lr, previously set to address of __enable_mmu
    __enable_mmu
    set page table pointer (TTB) in MMU hardware so it knows where to start page-table walks
    enable MMU so running with virtual addresses
    jump to r13, previously set to address of __switch_data, whose first field is address of __mmap_switched
    __switch_data defined in arch/arm/kernel/head-common.S
    arch/arm/kernel/head-common.S: __mmap_switched
    . copy data segment to RAM
    . zero BSS
    . branch to start_kernel


    Start_kernel – (init/main.c)
    tick_init – (kernel/time/tick-common.c)
    setup_arch (arch/arm/kernel/setup.c)
    Locate processor in the list of supported processors and print CPU version and name
    Setup stack for exception handlers
    Setp page tables
    setup_command_line (init/main.c)
    Store the unmodified and modified command line parameters for future ref
    build_all_zonelists (mm/page_alloc)
    Construct zonelist for each memory zone(DMA, DMA32, NORMAL, HIGH_MEMORY, MOVABLE). Zonelist specifies the zones/nodes to visit when allocation request for a selected zone/node is not met. This is called overflow or fallback.
    setup_log_buf (kernel/printk.c)
    Allocate memory for log_buf, free early log_buf and copy early log buf to newly allocated log_buf
    mm_init (init/main.c)
    Initialize memory allocators. Calculate available, reserved and highmem.
    sched_init (kernel/sched.c)
    Setup the scheduler, note we still have not enabled preemption and interrupts.
    preempt_disable(include/linux/preempt.h)
    Preemption is enabled, and in the previous step scheduler is also initialized.
    init_IRQ (arch/arm/kernel/irq.c)
    init_timers (kernel/timer.c)
    hrtimers_init (kernel/hrtimer.c)
    softirq_init (kernel/softirq.c)
    local_irq_enable(include/linux/irqflags.h)
    console_init (drivers/char/tty_io.c)
    vfs_caches_init (fs/dcache.c)
    mnt_init (fs/namespace.c)
    init_rootfs (fs/ramfs/inode.c)
    init_mount_tree (fs/namespace.c)
    bdev_cache_init (fs/block_dev.c)
    chrdev_init (fs/char_dev.c:)
    signals_init (kernel/signal.c)
    rest_init (init/main.c)
    kernel_thread ( arch/arm/kernel/process.c)
    kernel_thread() creates a kernel init thread and control is given to kernel_init().
    Kthreadd
    Is a kernel thread deamon, all kthreads are forked off this thread
    kernel_init (init/main.c)
    smp_prepare_cpus (arch/arm/smp.c)
    smp_init(kernel/smp.c)
    do_basic_setup (init/main.c)
    driver_init (drivers/base/init.c)
    do_initcalls (init/main.c)
    Calls all subsytems init functions, __initcall_start doesn’t appear anywhere in *.c or *.h file, it is present in linker script (*.lds)
    prepare_namespace (init/do_mounts.c)
    Decides where to mount and mounts the ramdisk
    init_post (init/main.c)
    Initial boot is done clear all initmem segments

No comments: