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: