Kernel 2 6 21 ftp ftp kernel orgpublinuxkernelv
준비 Kernel. 2. 6. 21 ftp: //ftp. kernel. org/pub/linux/kernel/v 2. 6/ Kernel 2. 6. 21 Patch http: //www. arm. com/products/os/linux_download. html Toolchain http: //www. codesourcery. com/gnu_toolchains/arm. html Written by B. LEE
build 압축해제 및 패치 $ tar jxvf linux-2. 6. 21. tar. bz 2 $ gzip -d patch-2. 6. 21 -arm 1. gz $ gzip -d patch-2. 6. 21 -arm 1 -t 2_1. gz $ cd linux-2. 6. 21 $ cat. . /patch-2. 6. 21 -arm 1 | patch -p 1 [x] $ cat. . /patch-2. 6. 21 -arm 1 -t 2_1 | patch -p 1 s 3 c 2410 설정 $ cp arch/arm/configs/s 3 c 2410_defconfig ARM 11(V 6), SMP 설정 $ cp arch/arm/configs/realview-smp_defconfig 컴파일 및 ctags, cscope 생성 $ make V=1 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- tags $ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- cscope $ arm-none-linux-gnueabi-objdump -d vmlinux > vmlinux. objdump Written by B. LEE
STMIA, STMIB, STMDA, STMDB R 13, {R 0, R 1, R 2} STMEA, STMFA, STMED, STMFD R 13, {R 0, R 1, R 2} STMIA, STMEA R 13! STMIB, STMFA R 13! R 2 R 1 R 0 R 13 R 2 R 13 N+C N+8 N+4 R 13 N N-4 N-8 N-C R 1 R 2 R 0 R 13! STMDA, STMED R 13! R 0 STMDB, STMFD Written by B. LEE
[ stext ] arch/arm/kernel/head. S FIQ, IRQ 를 Disable 하고, SVC 모드로 한다. CP 15 Register 0 에서 Process ID 를 읽어 온다. __lookup_processor_type 를 호출하고, 결과를 R 10 에 저장한다. 결과가 0 이라면, __error_p 로 분기한다. __loopup_machine_type 를 호출하고, 결과를 R 8 에 저장한다. 결과가 0 이라면, __error_a 로 분기한다. __create_page_table 를 호출하여, 페이지 테이블을 생성한다. R 13 에 __switch_data 주소를 저장하고, LR 에 __enalbe_mmu 주소를 저장하고, proc_info_list 구조체의 PROCINFO_INITFUNC 으로 PC 값을 바꾼다. arch 별로 proc-***. S 파일 형태로 구분되어 있는 setup 코드를 수행한다. ARM 920 T (arch/arm/mm/proc-arm 920. S) __arm 920_setup V 6 (arch/arm/mm/proc-v 6. S ) __v 6_setup Written by B. LEE
[ __lookup_machine_type ] arch/arm/kernel/head-common. S __arch_info_begin 부터 __arch_info_end 까지 ( 섹션. arch. info. init 영역 ) 저장된 machine_desc 구조체에서 MACHINFO_TYPE 값에 해당하는, 변수 nr 을 읽어 온다. 이 값이 부터로드에서 넘긴 arch 넘버(R 1)와 같은지 비교하고, 같으면 리턴하고, 다르면 machine_desc 구조체 만큼 증가하여 __arch_info_end 까지 반복하게 된다. 성공 하면, R 5 은 일치하는 machine_desc 구조체의 시작 주소를 가지게 되고, 실패하면 R 5에 0값을 대입한 다. 섹션. arch. info. init 영역은 컴파일 시에 MACHINE_START define 에 의해서 저장되게 된다. include/asm-arm/mach/arch. h 에 정의 되어 있다. #define MACHINE_START(_type, _name) static const struct machine_desc __mach_desc_##_type __attribute_used__ __attribute__((__section__(". arch. info. init"))) = { . nr = MACH_TYPE_##_type, . name = _name, MACH_TYPE_##_type 은 arch/arm/tools/mach-types 에 그 값들이 정의 되어 있다. 각 arch 별로 아래와 같은 정의가 존재한다. // arch/arm/mach-s 3 c 2410/mach-smdk 2410. c MACHINE_START(SMDK 2410, "SMDK 2410") // arch/arm/mach-realview/realview_eb. c MACHINE_START(REALVIEW_EB, "ARM-Real. View EB“) Written by B. LEE
[ __create_page_tables ] /arch/arm/kernel/head. S 페이지 테이블을 KERNEL_RAM_PADDR - 0 x 4000(16 K)에 만든다. 이 영역을 모두 0 으 로 초기화 하고, struct proc_info_list 의 PROCINFO_MM_MMUFLAGS 값에 해당하는 __cpu_mm_mmu_flags 값을 읽어 와서 적용한다. 현재 PC가 있는 1 Mbyte 영역과 MMU 가 enable 되었을 때를 대비한 커널영역에 대한 1차 페이지 테이블을 생성하게 된다. 부 트로더로 부터 전달되는 부트 파라미터에 대한 영역도 만들어 준다. SMDK 2410 일 경우, 물리메모리는 0 x 30000000 에서 시작, 커널은 0 x 30008000 에 있다. 이때 PC값은 0 x 30008000 보다 큰 어디를 가르키고 있을 것이다. offset swapper_pg_dir 0 x. C 0004000 Level 1 descriptor 0 x 000*4 : 0 x 300*4 0 x 300 __cpu_mm_mmu_flags 0 x. C 01*4 0 x 301 __cpu_mm_mmu_flags 0 x. C 02*4 0 x 302 __cpu_mm_mmu_flags : : 0 x. FFF*4 Written by B. LEE
[ __enable_mmu ] arch/arm/kernel/head. S kernel 설정에 따라 CP 15 Register 1 에 적용될 값을 설정한다. CP 15 Register 3, domain access control register 에 접근 권한을 설정한다. CP 15 Register 2, translation table base(TTB) register 에 페이지 테이블을 주 소를 설정한다. kernel 설정 비트 의미 CONFIG_ALIGNMENT_TRAP CR_A 데이터 주소 정렬 여부 검사 CONFIG_CPU_DCACHE_DISABLE CR_C D-Cache disable CONFIG_CPU_BPREDICT_DISABLE CR_Z 예약됨 CONFIG_CPU_ICACHE_DISABLE CR_I I-Cache disable No Domain Type 0 DOMAIN_KERNEL DOMAIN_MANAGER 0 DOMAIN_TABLE DOMAIN_MANAGER 1 DOMAIN_USER DOMAIN_MANAGER 2 DOMAIN_IO DOMAIN_CLIENT Written by B. LEE
[__mmap_switched ] /arch/arm/kernel/head-common. S __data_loc과 __data_start의 위치가 다를 경우 __data_start 부터 __bss_start 까 지 __data_loc에 위치한 데이터를 복사한다. XIP 커널은 ROM에 있는 data 섹션 (__data_loc)의 내용을 RAM(__data_start)으로 복사해야 한다. BSS 영역을 0으로 초기화한다. CP 15 Register 0 에서 읽어온 ID code (R 9)와 부트로더 에서 넘긴 ARCH 넘버(R 1) 를 arch/arm/kernel/setup. c의 processor_id와 __machine_arch_type 변수에 저장 한다. __enable_mmu에서 처리했던 CP 15 Register 1, control register 의 값(R 0)을 arch/arm/kernel/entry-armv. S의 cr_alignment에 저장하고, A bit(Alignment Fault Checking)을 클리어 한 값을 cr_no_alignment에 저장하고, 스택포인터(sp)를 init_thread_union + THREAD_START_SP 로 설정한다. start_kernel 로 분기한다. Written by B. LEE
[ __error_p ] CONFIG_DEBUG_LL Skip 한다. Written by B. LEE
[ __error_a ] CONFIG_DEBUG_LL Skip 한다. Written by B. LEE
[ __create_page_tables ] CONFIG_DEBUG_LL Skip 한다. Written by B. LEE
init_data init_task init_thread_union state = 0 flags = 0 thread_info = &init_thread_info preempt_count = 1 usage = ATOMIC_INIT(2) addr_limit = KERNEL_DS flag = 0 task = &init_task lock_depth = -1 exec_domain = &default_exec_domain prio = MAX_PRIO-20 cpu_domain = 0 x 1 f static_prio = MAX_PRIO-20 restart_block = normal_prio = MAX_PRIO-20 : policy = SCHED_NORMAL STACK default_exec_domain name = “Linux” handler = default_handler pers_low = 0 pers_high = 0 signal_map = ident_map signal_invmap = ident_map cpu_allowed = CPU_MASK_ALL : mm = NULL init_mm active_mm = &init_mm run_list = LIST_HEAD_INIT(run_list) mmap ioprio = 0 mm_rb = RB_ROOT time_slice = HZ pgd = swapper_pg_dir tasks = LIST_HEAD_INIT(tasks) mm_users = ATOMIC_INIT(2) ptrace_children = LIST_HEAD_INIT(ptrace_children) mm_count = ATOMIC_INIT(1) ptrace_list = LIST_HEAD_INIT(ptrace_list) mmap_sem = __RWSEM_INITIALIZER(mmap_sem) real_parent = &init_task page_table_lock = __SPIN_LOCK_UNLOCKED(page_table_lock) parent = &init_task mmlist = LIST_HEAD_INIT(mmlist) children = LIST_HEAD_INIT(children) cpu_vm_mask = CPU_MASK_ALL sibling = LIST_HEAD_INIT(sibling) : Written by B. LEE
init_data group_leader = &init_task init_groups group_info = &init_groups usage = ATOMIC_INIT(2) cap_effective = CAP_INIT_EFF_SET : cap_inheritable = CAP_INIT_INH_SET cap_permitted = CAP_FULL_SET init_fs keep_capabilities = 0 user = INIT_USER count = ATOMIC_INIT(1) comm = “swapper” lock = RW_LOCK_UNLOCKED thread = INIT_THREAD umask = 0022 fs = &init_fs : files = &init_files signal = &init_signals sighand = &init_sighand nsproxy = &init_nsproxy pending blocked alloc_lock = __SPIN_LOCK_UNLOCKED(allock_lock) journal_info = NULL cpu_timers = INIT_CPU_TIMERS(cpu_timers) fs_excl = ATOMIC_INIT(0) pi_lock = SPIN_LOCK_UNLOCKED count = ATOMIC_INIT(1) fdt = &fdtab = INIT_FDTABLE file_lock = __SPIN_LOCK_UNLOCKED(file_lock) next_fd = 0 close_on_exec_init open_fds_init fd_array : : Written by B. LEE
init_data init_signals count = ATOMIC_INIT(1) wait_chldexit = __WAIT_QUEUE_HEAD_INITIALIZER(wait_chldexit) shared_pending posix_timers = LIST_HEAD_INIT(posix_timers) cpu_timers = INIT_CPU_TIMERS(cpu_timers) rlim = INIT_RLIMITS pgrp = 1 tty_old_pg = NULL : init_sighand count = ATOMIC_INIT(1) action = siglock = __SPIN_LOCK_UNLOCKED(siglock) init_nsproxy count = ATOMIC_INIT(1) nslock = __SPIN_LOCK_UNLOCKED(nslock) uts_ns = &init_uts_ns ipc_ns = &init_ipc_ns mnt_ns = NULL pid_ns = &init_pid_ns Written by B. LEE
[ lockdep_init ] CONFIG_LOCKDEP 이 정의 되어 있지 않다. Written by B. LEE
[ local_irq_disable ] include/linux/irqflags. h local_irq_disable 에서 raw_local_irq_disable을 호출한다. __LINUX_ARM_ARCH__ >= 6 이면 새로운 명령어로 구현되고, 아니면, cpsr 를 읽고 / 쓰는 방법으로 구현된다. #define raw_local_irq_enable() __asm__("cpsie i" : : : "memory", "cc") #define raw_local_irq_disable() __asm__("cpsid i" : : : "memory", "cc") trace_hardirqs_off 는 CONFIG_TRACE_IRQFLAGS 가 정의 되어 있지 않다. Written by B. LEE
[ local_irq_disable ] include/linux/irqflags. h #define raw_local_irq_enable() ({ unsigned long temp; __asm__ __volatile__( "mrs %0, cpsr @ local_irq_enablen" " bic %0, #128n" " msr cpsr_c, %0" : "=r" (temp) : "memory", "cc"); }) #define raw_local_irq_disable() ({ unsigned long temp; __asm__ __volatile__( "mrs %0, cpsr @ local_irq_disablen" " orr %0, #128n" " msr cpsr_c, %0" : "=r" (temp) : "memory", "cc"); }) Written by B. LEE
[ lock_kernel ] lib/kernel_lock. c CONFIG_PREEMPT_BKL 정의 되어 있으면, Big Kernel Semaphore 로 구현되고, 정의 되어 있지 않다면, Big Kernel Lock 로 구현된다. Big Kernel Semaphore 는 세마포어로 구현되고, Big Kernel Lock 은 스핀락으로 구현된다. //--------------------// include/linux/spinlock_types. h //--------------------#if defined(CONFIG_SMP) # include <asm/spinlock_types. h> #else # include <linux/spinlock_types_up. h> #endif typedef struct { raw_spinlock_t raw_lock; #if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP) unsigned int break_lock; #endif #ifdef CONFIG_DEBUG_SPINLOCK unsigned int magic, owner_cpu; void *owner; #endif #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map; #endif } spinlock_t; //--------------------// include/asm-arm/spinlock_types. h //--------------------typedef struct { volatile unsigned int lock; } raw_spinlock_t; //--------------------// include/linux/spinlock_types_up. h //--------------------#if defined(CONFIG_DEBUG_SPINLOCK) || defined(CONFIG_DEBUG_LOCK_ALLOC) typedef struct { volatile unsigned int slock; #ifdef CONFIG_DEBUG_LOCK_ALLOC struct lockdep_map; #endif } raw_spinlock_t; #else typedef struct { } raw_spinlock_t; #endif Written by B. LEE
[ lock_kernel ] lib/kernel_lock. c lock_kernel() CONFIG_LOCK_KERNEL _raw_spin_lock, _raw_spin_trylock, _raw_spin_unlock NO nothing YES CONFIG_DEBUG_SPINLOCK CONFIG_PREEMPT_BKL NO NO YES down(&kernel_sem) __unlock_kernel() void _raw_spin_lock(spinlock_t *lock), int _raw_spin_trylock(spinlock_t *lock), void _raw_spin_unlock(spinlock_t *lock) CONFIG_PREEMPT NO YES _raw_spin_lock(&kernel_flag) preempt_disable() void __raw_spin_lock(raw_spinlock_t *lock), int __raw_spin_trylock(raw_spinlock_t *lock), void __raw_spin_unlock(raw_spinlock_t *lock) _raw_spin_trylock(&kernel_flag) _raw_spin_***(spinlock_t *lock)은 디버깅 정보를 포함하고, 결국 __raw_spin_***(raw_spinlock_t *lock) 을 호출한다. Written by B. LEE
[ tick_init ] CONFIG_GENERIC_CLOCKEVENTS 이 정의 되어 있지 않다. Written by B. LEE
[ boot_cpu_init ] init/main. c NO CONFIG_HOTPLUG_CPU YES cpu_possible_map - cpu is populatable cpu_present_map - cpu is populated cpu_online_map - cpu available to scheduler cpu_possible_map - cpu is populated cpu_present_map - copy of cpu_possible_map cpu_online_map - cpu available to scheduler Written by B. LEE
[ ____atomic_set_bit ] static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p) { unsigned long flags; unsigned long mask = 1 UL << (bit & 31); p += bit >> 5; raw_local_irq_save(flags); *p |= mask; raw_local_irq_restore(flags); } 6 5 4 3 2 1 0 범위 0 0 * * * 0 ~ 31 0 1 * * * 32~ 63 1 0 * * * 64~95 1 1 * * * 96~127 0~4 bit 는 32내 값을 나 타낸다. 5 bit 부터는 배열 p 의 포 인터를 증가 시킨다. Written by B. LEE
[ _set_bit_le ] arch/arm/lib/setbit. S ____atomic_set_bit 으로 분기 하는것 같았는데, objdump 결과는 _set_bit_le로 분기한다. macro 로 정의된 bitop 를 orr 명령어를 인자로 호출한다. 의문) _set_bit_le 는 비트맵의 단위가 8 bit 이다. 하지만, 정의된 비트맵은 32 bit 단위인데? #if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_32 v 6 K). macro bitop, instr @ r 0=cpu, r 1=bits[] mov r 2, #1 @ r 2 = 1 and r 3, r 0, #7 @ Get bit offset, r 3=r 0 & 0 b 111 add r 1, r 0, lsr #3 @ Get byte offset, 즉 bits[index], index 값 mov r 3, r 2, lsl r 3 @ r 3=해당비트(0~7) set 1: ldrexb r 2, [r 1] @ r 2=bits[index], 월래 값 byte 만큼 읽어옴 instr r 2, r 3 @ r 2=r 2|r 3 strexb r 0, r 2, [r 1] @ bits[index]=r 2, str 명령 결과 r 0 저장 cmp r 0, #0 @ 0 : 성공이냐? bne 1 b @ 1 : 실패면 반복 mov pc, lr @ return. endm #else. macro bitop, instr and r 2, r 0, #7 mov r 3, #1 mov r 3, lsl r 2 save_and_disable_irqs ip ldrb r 2, [r 1, r 0, lsr #3] instr r 2, r 3 strb r 2, [r 1, r 0, lsr #3] restore_irqs ip mov pc, lr. endm Written by B. LEE
[ page_address_init ] arch/arm/kernel/setup. c HASHED_PAGE_VIRTUAL 정의 되어 있지 않다. // include/linux/mm. h #if defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL) #define HASHED_PAGE_VIRTUAL #endif Written by B. LEE
[ setup_arch ] arch/arm/kernel/setup. c paging_init 를 호출하여 부트 메모리 allocator 를 초기화 한다. Written by B. LEE
[ setup_processor ] arch/arm/kernel/setup. c lookup_processor_type에 processor_id 를 인자로 전달하여 호출한다. processor_id 는 head. S 에서 저장한 CPU ID 값이며, 이 함수의 호출 결과로 구 조체 proc_info_list 에 대한 포인터를 얻는다. 각 전역 변수에 값을 대입한다. elf_hwcap 는 하드웨어 지원사항을 나타낸다. cpu_name = list->cpu_name; #ifdef MULTI_CPU processor = *list->proc; #endif #ifdef MULTI_TLB cpu_tlb = *list->tlb; #endif #ifdef MULTI_USER cpu_user = *list->user; #endif #ifdef MULTI_CACHE cpu_cache = *list->cache; #endif elf_hwcap = list>elf_hwcap; init_uts_ns. name. machine 를 arch_name, ENDIANNESS 스트링으로 저장한다. elf_platform 를 elf_name 과 ENDIANNESS 스트링으로 저장한다. cpu_proc_int 를 호출하는데, processor. _proc_init() 로 정의되어 있다. CPU별로 정의되어 있는 processor_function 내에 존재하는 초기화 코드를 수행한다. // arch/arm/mm/proc-arm 920. S arm 920_processor_functions // arch/arm/mm/proc-v 6. S v 6_processor_functions 두 코드 다 하는 일 없이 바로 리턴한다. Written by B. LEE
[ convert_to_tag_list ] arch/arm/kernel/setup. c 예전 전달 방식이라면, tag list 형식으로 고쳐준다. Written by B. LEE
[ parse_tags ] arch/arm/kernel/setup. c ATAG_NONE 일 때까지 루프 돌면서 parse_tag 에 태그(struct tag)를 인자로 넘겨 호출한다. parse_tag 는 넘겨온 tag 가 __tagtable_begin에서 __tagtable_end 까지 섹션. taglist. init 영역 안에 저장되어 있는 tagtable 구조체의 tag 값을 비교하여 같은 것이 있다면, tagtable 구조체의 parse 함수를 호출한다. tagtable 구조체 는 include/asm-arm/setup. h 정의되어 있다. struct tagtable { __u 32 tag; int (*parse)(const struct tag *); }; . taglist. init 영역에 값을 넣는 매크로는 __tagtable 로써 include/asm-arm/setup. h 에 정의되어 있다. #define __tag __attribute_used__ __attribute__((__section__(". taglist. init"))) #define __tagtable(tag, fn) static struct tagtable __tagtable_##fn __tag = { tag, fn } arch/arm/kernel/setup. c 에 다음과 같은 코드가 존재한다. __tagtable(ATAG_CORE, parse_tag_core); __tagtable(ATAG_MEM, parse_tag_mem 32); : __tagtable(ATAG_REVISION, parse_tag_revision); tagtable[0] ATAG_REVISION <-- __tagtable_begin parse_tag_revision : ATAG_MEM *. taglist. init parse_tag_mem 32 tagtable[n] ATAG_CORE parse_tag_core <-- __tagtable_end Written by B. LEE
[ parse_cmdline ] arch/arm/kernel/setup. c default_command_line 에 저장되어 있는 문자열을 분석한다. 이 값은 커널 옵션에서 지정한 값이며, 만약 부트로더에서 ATAG_CMDLINE 태그로 넘겼을 경우 부터로더에서 넘긴 값으로 대체된다. __early_begin 부터 __early_end 까지. early_param. init 영역에 저장되어 있는 early_params 구조체의 arg 값을 string를 처음부터 끝까지 memcmp 로 메모리 비교를 하고, 같으면 해당 함수에 일치하는 문자 다음부터 포인터를 인자 로 넘기며 호출한다. 그렇지 않으면 cmdline_p에 내용을 복사한다. early_params 구조체는 include/asm-arm/setup. h 에 정의되어 있다. ( cmdline_p=“ xxx=1234 yyy=1234” 형태로 저장된다. ”) struct early_params { const char *arg; void (*fn)(char **p); }; . early_param. init 영역에 값을 넣는 매크로는 __early_param 로써 include/asm-arm/setup. h 에 정의되어 있다. #define __early_param(name, fn) static struct early_params __early_##fn __attribute_used__ __attribute__((__section__(". early_param. init"))) = { name, fn } arch/arm/kernel/setup. c 에 다음과 같은 코드가 존재한다. __early_param("initrd=", early_initrd); __early_param("mem=", early_mem); <-- __early_begin arch/arm/mm/mmu. c 에 다음과 같은 코드가 존재한다. __early_param("cachepolicy=", early_cachepolicy); __early_param("nocache", early_nocache); __early_param("nowb", early_nowrite); __early_param("ecc=", early_ecc); “initrd=“ early_initrd : “nowb” . early_param. init early_nowrite “ecc=“ early_ecc <-- __early_end Written by B. LEE
[ paging_init ] arch/arm/mm/mmu. c sets up the page tables, initialises the zone memory maps, and sets up the zero page, bad page and bad page tables. Written by B. LEE
[ build_mem_type_table ] arch/arm/mm/mmu. c CPU 에 따라 Cache Policy, mem_types, protection_map 설정한다. smdk 2410 에서의 설정 내용으로 cache_policies[CPOLICY_WRITEBACK] 을 설정한다. . policy. cr_mask. pmd. pte = = "writeback", 0, PMD_SECT_WB, PTE_BUFFERABLE|PTE_CACHEABLE, #define PMD_SECT_WB (PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE) protection_map[0]=0 x 0000000 f L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_CACHEABLE | L_PTE_BUFFERABLE protection_map[1]=0 x 0000005 f L_PTE_USER | L_PTE_EXEC | L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_CACHEABLE | L_PTE_BUFFERABLE protection_map[2]=0 x 0000005 f protection_map[3]=0 x 0000005 f protection_map[4]=0 x 0000005 f protection_map[5]=0 x 0000005 f protection_map[6]=0 x 0000005 f protection_map[7]=0 x 0000005 f protection_map[8]=0 x 0000000 f protection_map[9]=0 x 0000005 f protection_map[10]=0 x 0000007 f L_PTE_USER | L_PTE_WRITE | L_PTE_EXEC | L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_CACHEABLE | L_PTE_BUFFERABLE protection_map[11]=0 x 0000007 f protection_map[12]=0 x 0000005 f protection_map[13]=0 x 0000005 f protection_map[14]=0 x 0000007 f protection_map[15]=0 x 0000007 f Written by B. LEE
[ build_mem_type_table ] arch/arm/mm/mmu. c [MT_DEVICE] prot_pte 0 x 000000 a 3 prot_l 1 0 x 00000011 prot_sect 0 x 00000412 domain 0 x 00000002 [MT_CACHECLEAN] prot_pte 0 x 0000 prot_l 1 0 x 0000 prot_sect 0 x 0000001 e domain 0 x 0000 [MT_MINICLEAN] prot_pte 0 x 0000 prot_l 1 0 x 0000 prot_sect 0 x 0000001 a domain 0 x 0000 [MT_LOW_VECTORS] prot_pte 0 x 000000 cf L_PTE_PRESENT prot_l 1 0 x 00000011 prot_sect 0 x 0000 domain 0 x 00000001 [MT_HIGH_VECTORS] prot_pte 0 x 000000 df | L_PTE_PRESENT prot_l 1 0 x 00000011 prot_sect 0 x 0000 domain 0 x 00000001 L_PTE_DIRTY | L_PTE_WRITE | L_PTE_YOUNG | L_PTE_PRESENT PMD_BIT 4 | PMD_TYPE_TABLE PMD_SECT_AP_WRITE | PMD_BIT 4 | PMD_TYPE_SECT | PMD_SECT_UNCACHED DOMAIN_IO PMD_BIT 4 | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE | PMD_TYPE_SECT DOMAIN_KERNEL PMD_SECT_TEX(1) | PMD_BIT 4 | PMD_SECT_CACHEABLE | PMD_TYPE_SECT DOMAIN_KERNEL L_PTE_DIRTY | L_PTE_EXEC | L_PTE_CACHEABLE | L_PTE_BUFFERABLE | L_PTE_YOUNG | PMD_BIT 4 | PMD_TYPE_TABLE DOMAIN_USER L_PTE_DIRTY | L_PTE_EXEC | L_PTE_USER | L_PTE_CACHEABLE | L_PTE_BUFFERABLE | L_PTE_YOUNG PMD_BIT 4 | PMD_TYPE_TABLE DOMAIN_USER Written by B. LEE
[ build_mem_type_table ] arch/arm/mm/mmu. c [MT_MEMORY] prot_pte 0 x 0000 prot_l 1 0 x 0000 prot_sect 0 x 0000041 e PMD_TYPE_SECT domain 0 x 0000 [MT_ROM] prot_pte 0 x 0000 prot_l 1 0 x 0000 prot_sect 0 x 0000001 e domain 0 x 0000 [MT_IXP 2000_DEVICE] prot_pte 0 x 000000 a 3 prot_l 1 0 x 00000011 prot_sect 0 x 00001416 | PMD_SECT_UNCACHED domain 0 x 00000002 [MT_NONSHARED_DEVICE] prot_pte 0 x 0000 prot_l 1 0 x 00000011 prot_sect 0 x 00002412 domain 0 x 00000002 PMD_SECT_AP_WRITE | PMD_BIT 4 | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE | DOMAIN_KERNEL PMD_BIT 4 | PMD_SECT_CACHEABLE | PMD_SECT_BUFFERABLE | PMD_TYPE_SECT DOMAIN_KERNEL L_PTE_DIRTY | L_PTE_WRITE | L_PTE_YOUNG | L_PTE_PRESENT PMD_BIT 4 | PMD_TYPE_TABLE PMD_SECT_TEX(1) | PMD_SECT_AP_WRITE | PMD_BIT 4 | PMD_SECT_BUFFERABLE | PMD_TYPE_SECT DOMAIN_IO PMD_BIT 4 | PMD_TYPE_TABLE PMD_SECT_TEX(2) | PMD_SECT_AP_WRITE | PMD_BIT 4 | PMD_TYPE_SECT DOMAIN_IO Written by B. LEE
[ cpu_architecture ] arch/arm/kernel/setup. c ID Code MRC p 15, 0, <Rd>, c 0, 0; reads Main ID register ARM 9 : 0 x 40129200 ARM 11 MPCore : 0 x 410 FB 024 Memory Model Feature Register 0 MRC p 15, 0, <Rd>, c 0, c 1, 4 ARM 11 MPCore : 0 x 01100103 ARM 920 T 은 CPU_ARCH_ARMv 4 T 를 ARM 11 MPCore 는 CPU_ARCH_ARMv 7 를 리턴 한다. ( 왜 CPU_ARCH_ARMv 6 인 것 같은데? ) Written by B. LEE
[ prepare_page_table ] arch/arm/mm/mmu. c 페이지 테이블에서 다음 영역을 0 으로 초기화 한다. 1. 0 ~ MODULE_START ( 0 ~ 0 xbee 00000 ) 2. MODULE_START ~ PAGE_OFFSET ( 0 xbf 000000 ~ 0 xbfe 00000 ) 3. 물리메모리의 끝 ~ VMALLOC_END ( 0 xc 4000000 ~ 0 xdfe 00000 ) MODULE_START = 0 x. BF 000000 PAGE_OFFSET = 0 x. C 0000000 VMALLOC_END = 0 x. E 0000000 ( s 3 c 2410 ), 0 x. D 0000000 ( integrator ) swapper_pg_dir 0 x. C 0004000 offset level 1 descriptor 0 x 000*4 0 : 0 0 x. C 00*4 0 x. C 01*4 : 0 x. C 40*4 0 : 0 0 x. DFE*4 0 : 0 x. FFF*4 Written by B. LEE
[ 부트 메모리 allocator ] struct pglist_data contig_page_data bootmem_data_t contig_bootmem_data struct zone node_zones[MAX_NR_ZONES] unsigned long node_boot_start struct zonelist node_zonelists[MAX_NR_ZONES] unsigned long node_low_pfn int nr_zones void *node_bootmem_map struct page *node_mem_map unsigned long last_offset struct bootmem_data *bdata unsigned long last_pos spinlock_t node_size_lock unsigned long last_success unsigned long node_start_pfn bdata_list struct list_head list unsigned long node_present_pages unsigned long node_spanned_pages int node_id wait_queue_head_t kswapd_wait struct task_struct *kswapd int kswapd_max_order Written by B. LEE
[ 부트 메모리 allocator – SMDK 2410 ] struct pglist_data contig_page_data bootmem_data_t contig_bootmem_data struct zone node_zones[MAX_NR_ZONES] unsigned long node_boot_start = 0 x 30000000 struct zonelist node_zonelists[MAX_NR_ZONES] unsigned long node_low_pfn = 0 x 34000 int nr_zones = 0 void *node_bootmem_map = 0 xc 0314000 struct page *node_mem_map = 0 xc 0315000 unsigned long last_offset struct bootmem_data *bdata unsigned long last_pos spinlock_t node_size_lock unsigned long last_success unsigned long node_start_pfn = 0 x 30000 bdata_list struct list_head list unsigned long node_present_pages = 0 x 4000 unsigned long node_spanned_pages = 0 x 4000 0 xc 0314000 ~0 xc 0314800 (0 x 800 int node_id = 0 1 wait_queue_head_t kswapd_wait struct task_struct *kswapd int kswapd_max_order Memory Bank = 0 x 4000/8 ), byte 단위로 비트맵 구성 1 . . . 1 0 xc 0315000 ~ 0 xc 095000( 0 x 80000 = 0 x 4000 * 32 ), 32=sizeof(struct page) struct page pfn=0 x 30000 0 xc 0315000 struct page pfn=0 x 30001 0 xc 0315020 . . . struct page pfn=0 x 33 fff 0 xc 0394 fe 0 mem_map meminfo. nr_banks = 1 bank[0]. start=0 x 30000000 bank[0]. size=0 x 4000000 bank[0]. node=0 Written by B. LEE
[ bootmem_init ] arch/arm/mm/init. c 물리 메모리 영역 만큼 부트 메모리 allocator 를 만들고 초기화 한다. meminfo 구조체에서 bank의 size 가 0 인 경우, node 가 MAX_NUMNODES 보다 큰 것은 node 를 -1 로 설정한 다. 잘 못 된 정보이며, 차 후 node 별로 bank의 정보를 참조 할 때 무시하게 만든다. check_initrd 를 호출하여, ramdisk image 가 어느 node 에 속하는지 판단한다. 노드별로 bootmem_init_node를 호출 하여, end_pfn 값을 갱신하게 되는데, 이 과정에서 memend_pfn 값도 결 정된다. memend_pfn 에 노드들 중에 가장 높은 메모리 pfn 를 저장한다. high_memory 는 memend_pfn 에서 PAGE_SHIFT 만큼 곱하여 물리 메모리의 끝을 가리킨다. max_pfn 는 총 pfn 의 갯수를 저장한다. // include/linux/nodemask. h #define for_each_node(node) for_each_node_mask((node), node_possible_map) #if MAX_NUMNODES > 1 #define for_each_node_mask(node, mask) for ((node) = first_node(mask); (node) < MAX_NUMNODES; (node) = next_node((node), (mask))) #else /* MAX_NUMNODES == 1 */ #define for_each_node_mask(node, mask) if (!nodes_empty(mask)) for ((node) = 0; (node) < 1; (node)++) #endif /* MAX_NUMNODES */ smdk 2410 에서는 MAX_NUMNODES 값은 1 이 된다. 결과로 저장되는 각 변수들의 값은 다음과 같다. high_memory = 0 x. C 4000000, max_pfn = 0 x 00004000, mamend_pfn=0 x 00034000 Written by B. LEE
[ bootmem_init_node ] arch/arm/mm/init. c meminfo 의 각 bank 대해 map_memory_bank, create_mapping, alloc_init_section 대한 페이지 테이블 맵핑을 한다. 를 차례로 호출하여 물리메모리에 SMDK 2410 에서 노드가 1개이고, meminfo 정보가 아래와 같다면, 다음과 같은 페이지 테이블을 생성한다. meminfo. nr_banks = 1 bank[0]. start=0 x 30000000 bank[0]. size=0 x 4000000 bank[0]. node=0 swapper_pg_dir 0 x. C 0004000 offset level 1 descriptor 0 x 000*4 0 : 0 0 x. C 00*4 0 x 3000041 e 0 x. C 01*4 0 x 3010041 e : : 0 x. C 3 F*4 0 x 33 f 0041 e 0 x. C 40*4 0 : 0 0 x. DFE*4 0 : 0 x. FFF*4 Written by B. LEE
[ map_memory_bank ] arch/arm/mm/init. c Skip 한다. Written by B. LEE
[ create_mapping ] arch/arm/mm/mmu. c 인자로 넘어온 struct map_desc *md 에 해당하는 영역에 대한 페이지 테이블 맵핑 작업을 한다. while (length >= (PGDIR_SIZE / 2)) { alloc_init_section(virt, virt + off, prot_sect); virt += (PGDIR_SIZE / 2); length -= (PGDIR_SIZE / 2); // + 0 x 100000 } while (length >= PAGE_SIZE) { alloc_init_page(virt, virt + off, prot_l 1, prot_pte); virt += PAGE_SIZE; length -= PAGE_SIZE; } length 를 0 x 100000 감소 시키고, virt 는 0 x 100000 를 증가 시키며, alloc_init_section 를 호출해서 section 에 대한 맵핑을 한다. length 가 0 x 100000 보다 작게 남는 경우엔, alloc_init_page 를 호출해서 1차 페이지 디스크립터 와 2차 페이지 디스 크립터를 생성한다. Written by B. LEE
[ alloc_init_section ] arch/arm/mm/mmu. c pmd_off_k 는 주어진 virtual address 의 page directory index ( 2048 엔트리중에서 ) 그리고, virtual address가 C 01*4, C 03*4 와 같이 홀수 이면, pmdp두번째 맴버에 값을 저장하도록 한다. flush_pmd_entry 를 호출한다. clear_pmd_entry, flush_pmd_entry 의 차이 Written by B. LEE
[ alloc_init_page ] arch/arm/mm/mmu. c 0 xffff 0000 주소를 페이지 테이블 맵핑하는 과정 alloc_init_page(0 xffff 0000, 0 x 30001000, 0 x 31, 0 xdf) alloc_bootmem_low_pages(2 * PTRS_PER_PTE * sizeof(pte_t)) virtual = 0 x. FFFF 0000 : 0 x. C 0002000 : : 0 x. FFE*4 0 x 30002031 0 x 30001 aae 0 x. FFF*4 0 x 30002431 : __pmd_populate(0 x. FFE*4, 0 x 30002031) 0 x. C 0002800 : 0 x. C 0002 FC 0 0 x 300010 df -2048 set_pte_ext : 0 x. C 0002800 + 0 x 1 F 0*4 pte_offset_kernel(0 x. FFE*4, 0 x. FFFF 0000) pmd_page_vaddr(0 x 30002031)=0 xc 0002800 __pte_index(0 x. FFFF 0000)=0 x 000001 f 0 Written by B. LEE
[ bootmem_bootmap_pages ] mm/bootmem. c 비트맵을 표시해 줄 page 몇 개가 필요한가? Written by B. LEE
[ find_bootmap_pfn ] arch/arm/mm/init. c 부트맵이 위치할 pfn 를 찾는다. Written by B. LEE
[ init_bootmem_core ] mm/bootmem. c contig_bootmem_data 를 초기화 한다. node_bootmem_map ( 부트맵 ) 을 모두 1 로 설정한다. Written by B. LEE
[ init_bootmem_core ] mm/bootmem. c start . . . 1 0 0. . . last_pos ADDRESS = start * PAGE_SIZE + node_boot_start PAGE_SIZE . . . size 가 PAGE_SIZE 보다 작을 때. . 다음 할당을 위해 last_offset 를 지정한다. PAGE_SIZE . . . size last_offset = ALIGN(last_offset, align) * last_offset, offset 은 같은 값을 가질 수 있다. Written by B. LEE
[ init_bootmem_core ] mm/bootmem. c start . . . 1 0 0. . . last_pos 1. 새로 할당 받을 size 가 remaining_size 보다 작을때. . remaining_size > size PAGE_SIZE last_offset = ALIGN(last_offset, align) ADDRESS = last_pos * PAGE_SIZE + offset + node_boot_start 2. last_offset 값만 변경된다. PAGE_SIZE last_offset * last_offset, offset 은 같은 값을 가질 수 있다. Written by B. LEE
[ init_bootmem_core ] mm/bootmem. c start . . . 1 0 0 0. . . last_pos 1. 새로 할당 받을 size 가 remaining_size 보다 클때. . remaining_size < size PAGE_SIZE last_offset = ALIGN(last_offset, align) ADDRESS = last_pos * PAGE_SIZE + offset + node_boot_start PAGE_SIZE start last_offset . . . 1 1 1 0. . . 2. last_offset, last_pos 값 변경하고, 비트맵에 늘어난 PAGE_SIZE 갯수 만큼 1 로 설정한다. * last_offset, offset 은 같은 값을 가질 수 있다. last_pos Written by B. LEE
[ devicemaps_init ] arch/arm/mm/mmu. c 페이지 테이블에서 VMALLOC_END ~ 끝까지 영역을 0 으로 초기화 한다. high-vectors ( 0 xffff 0000 ) 를 맵핑한다. mdesc->map_io() 를 호출하여, device 를 맵핑한다. SMDK 2410 의 경우엔 smdk 2410_map_io 를 호출한다. swapper_pg_dir 0 x. C 0004000 offset level 1 descriptor 0 x 000*4 0 : : 0 xf 00*4 0 x 4 a 000452 0 xf 01*4 0 x 48000452 0 xf 02*4 0 x 4 c 000452 0 xf 03*4 0 x 4 d 000452 0 xf 04*4 0 x 50000452 0 xf 05*4 0 x 51000452 0 xf 06*4 0 0 xf 07*4 0 x 53000452 : : 0 xf 64*4 0 x 56000452 : : 0 x. FFE*4 0 x 30002031 0 x. FFF*4 0 x 30002431 Written by B. LEE
[ free_area_init_node ] mm/page_alloc. c contig_page_data 의 node_id, node_start_pfn 값을 설정하고 calculate_node_totalpages() 를 호출하여, node_spanned_pages, node_present_pages 값을 계산한다. alloc_node_mem_map() 를 호출해서 page 배열을 할당하고, node_mem_map 에 시작 위치를 가리킨다. mem_map 값으로도 설정한다. free_area_init_core() 를 호출하여, 각 page 들을 초기화 한다. Written by B. LEE
[ free_area_init_core ] mm/page_alloc. c zone 를 초기화 한다. Written by B. LEE
[ devicemaps_init ] arch/arm/mm/mmu. c vectors 를 bootmem 에서 PAGE_SIZE 만큼 할당 받는다. 페이지 테이블 0 xffff 0000 에 등록한다. mdesc->map_io 를 호출한다. MACHINE_START(INTEGRATOR, "ARM-Integrator") /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */. phys_io = 0 x 16000000, . io_pg_offst = ((0 xf 1600000) >> 18) & 0 xfffc, . boot_params = 0 x 00000100, . map_io = ap_map_io, . init_irq = ap_init_irq, . timer = &ap_timer, . init_machine = ap_init, MACHINE_END Written by B. LEE
[ flush_dcache_page ] arch/arm/mm/flush. c. Written by B. LEE
[ request_standard_resources ] arch/arm/kernel/setup. c iomem_resource 에 resource 를 등록한다. start = _text end = _etext - 1 iomem_resource name = “Kernel text” start = 0 end = 0 xffff end = 0 x 04000000 name = “PCI mem” name = “System RAM” flag= IORESOURCE_MEM | IORESOURCE_BUSY parent sibling child flag= IORESOURCE_MEM parent sibling child start = __data_start end = _end - 1 name = “Kernel data” flag= IORESOURCE_MEM parent sibling child Written by B. LEE
[ cpu_init ] arch/arm/kernel/setup. c struct stack { u 32 irq[3]; u 32 abt[3]; u 32 und[3]; } ____cacheline_aligned; static struct stacks[NR_CPUS]; CPU 갯수만큼 stacks 이 만들어 진다. IRQ_MODE, ABT_MODE, UND_MODE 의 sp 를 지정한다. irq[0] irq[1] irq[2] abt[0] abt[1] abt[2] und[0] und[1] und[2] IRQ_MODE 의 sp 시작 ABT_MODE 의 sp 시작 UND_MODE 의 sp 시작 Written by B. LEE
[ setup_command_line ] init/main. c. Written by B. LEE
[ setup_per_cpu_areas ] init/main. c DEFINE_PER_CPU 로 정의된 것들이 컴파일 되면서, __per_cpu_start ~__per_cpu_end 사이의 영역에 들어간다. DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data); __per_cpu_start __per_cpu_end __per_cpu_offset[0] __per_cpu_offset[1] prt Written by B. LEE
[ smp_prepare_boot_cpu ] arch/arm/kernel/smp. c cpu_data. idle = current 를 저장한다. Written by B. LEE
[ sched_init ] kernel/sched. c cpu_rq(cpu) 는 해당 cpu의 struct rq자료를 리턴한다. 각 cpu 의 run queue 자료를 초기화 한다. Written by B. LEE
[ preempt_disable ] include/linux/preempt. h CONFIG_PREEMPT 가 정의 되어 있어야 한다. 정의 되어 있지 않다면, preempt_disable , preempt_enable 는 빈 함수 로 구현된다. // include/linux/preempt. h #define preempt_disable() do { inc_preempt_count(); barrier(); } while (0) #define preempt_enable() do { preempt_enable_no_resched(); barrier(); preempt_check_resched(); } while (0) #define add_preempt_count(val) do { preempt_count() += (val); } while (0) #define sub_preempt_count(val) do { preempt_count() -= (val); } while (0) #define inc_preempt_count() add_preempt_count(1) #define dec_preempt_count() sub_preempt_count(1) #define preempt_count() (current_thread_info()->preempt_count) Written by B. LEE
[ build_all_zonelists ] mm/page_alloc. c system_state = SYSTEM_BOOTING 이면 __build_all_zonelists(NULL); 를 호출한다. Written by B. LEE
[ page_alloc_init ] mm/page_alloc. c. Written by B. LEE
[ parse_early_param ] init/main. c. Written by B. LEE
[ sort_main_extable ] kernel/extable. c 섹션 __start___ex_table 부터 __stop___ex_table 에 까지 등록되어 있는 struct exception_table_entry 의 insn 값으로 정열한다. struct exception_table_entry { unsigned long insn, fixup; }; Written by B. LEE
[ trap_init ] arch/arm/kernel/traps. c 0 xffff 0000 에 __vectors_start 부터 __vectors_end 를 복사한다. 0 xffff 0000 + 0 x 200 에 __stubs_start 부터 __stubs_end 를 복사한다. 0 xffff 0000 + 0 x 1000 - kuser_sz 에 __kuser_helper_start 부터 kuser_sz 만큼 복사한다. kuser_sz = __kuser_helper_end - __kuser_helper_start Written by B. LEE
[ rcu_init ] kernel/rcupdate. c. Written by B. LEE
[ init_IRQ ] arch/arm/kernel/irq. c. Written by B. LEE
[ s 3 c_init_irq ] arch/arm/plat-s 3 c 24 xx/irq-pl 192. c smdk 6400 의 init_IRQ -> s 3 c_init_irq 로 점프하여 초기화 시킴 struct irq_desc[NR_IRQS]; [초기값] [IRQ_EINT 0_3] handle_irq = handle_bad_irq handle_irq = s 3 c_irq_demux_eint 0_3 chip = &no_irq_chip = &dummy_irq_chip msi_desc handler_data chip_data action status = IRQ_DISABLED status = IRQ_NOREQUEST | IRQ_NOPROBE depth = 1 depth = 0 wake_depth irq_count irqs_unhandled lock= __SPIN_LOCK_UNLOCKED(lock) dir name = NULL Written by B. LEE
[ s 3 c_init_irq ] arch/arm/plat-s 3 c 24 xx/irq-pl 192. c [IRQ_EINT 4_11] [IRQ_EINT 12_19] handle_irq = s 3 c_irq_demux_eint 4_11 handle_irq = s 3 c_irq_demux_eint 12_19 chip = &dummy_irq_chip msi_desc handler_data chip_data action status = IRQ_NOREQUEST | IRQ_NOPROBE depth = 0 wake_depth irq_count irqs_unhandled lock= __SPIN_LOCK_UNLOCKED(lock) dir name = NULL Written by B. LEE
[ s 3 c_init_irq ] arch/arm/plat-s 3 c 24 xx/irq-pl 192. c [IRQ_EINT 20_27] [그 외 0~63] handle_irq = s 3 c_irq_demux_eint 20_27 handle_irq = handle_level_irq chip = &dummy_irq_chip = &s 3 c_irq_level_chip msi_desc handler_data chip_data action status = IRQ_NOREQUEST | IRQ_NOPROBE status = IRQ_DISABLED | IRQ_NOPROBE | IRQ_NOAUTOEN depth = 0 wake_depth irq_count irqs_unhandled lock= __SPIN_LOCK_UNLOCKED(lock) dir name = NULL depth = 1 wake_depth irq_count irqs_unhandled lock= __SPIN_LOCK_UNLOCKED(lock) dir name =NULL Written by B. LEE
[ s 3 c_init_irq ] arch/arm/plat-s 3 c 24 xx/irq-pl 192. c [64~91] handle_irq = handle_level_irq chip = &s 3 c_irqext_chip msi_desc handler_data chip_data action status = IRQ_DISABLED| IRQ_NOPROBE | IRQ_NOAUTOEN depth = 1 wake_depth irq_count irqs_unhandled lock= __SPIN_LOCK_UNLOCKED(lock) dir name Written by B. LEE
[ s 3 c_init_irq ] drivers/video/s 3 cfb. c [struct s 3 c_fb_info[CONFIG_FB_NUM]; ] fb dev win_id = 0 max_bpp max_xres max_yres map_dma_f 1 = 0 x 50600000 map_cpu_f 1 = 0 xff 600000 map_size_f 1 = 800*480*2 = 768000 screen_cpu_f 1 screen_dma_f 1 = 0 x 50600000 map_dma_f 2 map_cpu_f 2 map_size_f 2 screen_cpu_f 2 screen_dma_f 2 palette_ready fb_change_ready palette_buffer[0~255] = PALETTE_BUFF_CLEAR pseudo_pal [struct fb_info ] node = 0 flags = FBINFO_FLAG_DEFAULT var fix monspecs = monspecs queue pixmap sprite cmap modelist mode fbops = &s 3 c_fb_ops device dev = fb 0 class_flag screen_base = 0 xff 600000 screen_size pseudo_palette = &finfo->pseudo_pal state fbcon_par Written by B. LEE
[ s 3 c_init_irq ] drivers/video/s 3 cfb. c [ struct fb_fix_screeninfo ] [ struct fb_var_screeninfo ] xres = 800 yres = 480 id = “s 3 c_fb” smem_start smem_len = 800*480*2 type = FB_TYPE_PACKED_PIXELS type_aux = 0 visual xpanstep = 0 ypanstep = 1 ywrapstep = 0 line_length = 800*2 mmio_start mmio_len accel = FB_ACCEL_NONE reserved xres_virtual = 800 yres_virtual = 480 xoffset = 0 yoffset = 0 bits_per_pixel = 16 grayscale red = s 3 c_fb_rgb_16. red green = s 3 c_fb_rgb_16. green blue = s 3 c_fb_rgb_16. blue transp = s 3 c_fb_rgb_16. transp nonstd = 0 activate = FB_ACTIVATE_NOW height = 480 width = 800 accel_flags = 0 pixclock = PIXEL_CLOCK left_margin = 8 right_margin = 13 upper_margin = 5 lower_margin = 7 hsync_len = 3 vsync_len = 1 sync = 0 vmode = FB_VMODE_NONINTERLACED rotate reserved Written by B. LEE
[ s 3 c 6400_init_clocks ] arch/arm/mach-s 3 c 6400/clock. c [ clk_xtal ] [ clk_mpll ] [ clk_upll ] [ clk_epll_uart_192 m ] name = “ xtal” name = “ mpll” name = “ upll” name = “ epll” name = “epll_clk_uart_192 m” id = -1 id = -1 rate = 12 Mhz rate = 533. 000 Mhz rate = 0 rate = 192. 000 MHz rate = 48*1000 parent = NULL parent = &clk_epll ctrlbit = 0; enable = s 3 c_epll_clk_uart_enable ctrlbit = S 3 C_CLKCON_SCLK_UART [ clk_f ] [ clk_h ] [ clk_p ] [ clk_27 m ] name = “ fclk” name = “ hclk” name = “ pclk” name = “ clk 27 m” id = -1 rate = 533. 000 Mhz rate = 133. 250 MHz rate = 66. 625 MHz rate = 27*1000 parent = &clk_mpll parent = NULL ctrlbit = 0; [ clk_hx 2 ] [ clk_s ] [ clk_u ] [ clk_48 m ] name = “ hclkx 2” name = “ sclk” name = “ uclk” name = “ clk 48 m” id = -1 rate = 266. 5 Mhz rate = 0 rate = 48*1000 parent = NULL ctrlbit = 0; set_rate = s 3 c 6400_setrate_epll_clk_192 m get_rate = s 3 c 6400_getrate_epll_clk_192 m [ clk_usb_bus ] name = “ usb-bus” id = -1 [ clock] clk_usb_bus 빼고 위의 있는것 모두 List 에 삽입 했다. init_clocks[] 또 삽입. rate = 0 parent = &clk_upll ctrlbit = 0; Written by B. LEE
[ kmem_cache_init ] mm/slab. c static struct kmem_cache_cache struct array_cache *array[0] &initarray_cache -> kmalloc 할당. unsigned int batchcount 1 unsigned int limit BOOT_CPUCACHE_ENTRIES unsigned int shared 1 unsigned int buffer_size 0 x 60 u 32 reciprocal_buffer_size 0 x 2 aaaaab struct kmem_list 3 *nodelists[0] NULL -> &initkmem_list 3[0] -> kmalloc 할당 unsigned int flags unsigned int num 0 x 28 unsigned int gfporder 0 gfp_t gfpflags size_t colour 0 x 2 unsigned int colour_off 32 struct kmem_cache *slabp_cache unsigned int slab_size 0 xc 0 unsigned int dflags void (*ctor) (void *, struct kmem_cache *, unsigned long) void (*dtor) (void *, struct kmem_cache *, unsigned long) const char *name struct list_head next "kmem_cache" cache_chain Written by B. LEE
[ kmem_cache_init ] mm/slab. c initarray_cache unsigned int avail 0 unsigned int limit BOOT_CPUCACHE_ENTRIES unsigned int batchcount 1 unsigned int touched 0 spinlock_t lock void *entry[0] struct cache_sizes malloc_sizes[0] INDEX_AC size_t cs_size ~0 UL struct kmem_cache *cs_cachep kmem_cache_create cs_cachep->array[0] = kmalloc 할당 struct kmem_cache cs_dmacachep static struct cache_names __initdata cache_names[] char *name “size-32” char *name_dma “size-32(DMA)” Written by B. LEE
[ kmem_cache_init ] mm/slab. c malloc_sizes[] cache_names[] 0 cs_size=0 x 20 1 cs_size=0 x 40 2 cs_size=0 x 60 3 cs_size=0 x 80 4 cs_size=0 xc 0 5 cs_size=0 x 100 6 cs_size=0 x 200 7 cs_size=0 x 400 8 cs_size=0 x 800 9 cs_size=0 x 1000 10 cs_size=0 x 2000 11 cs_size=0 x 4000 12 cs_size=0 x 8000 13 cs_size=0 x 10000 14 cs_size=0 x 20000 15 cs_size=0 xffff 0 names. name=size-32 1 names. name=size-64 2 names. name=size-96 3 names. name=size-128 4 names. name=size-192 5 names. name=size-256 6 names. name=size-512 7 names. name=size-1024 8 names. name=size-2048 9 names. name=size-4096 10 names. name=size-8192 11 names. name=size-16384 12 names. name=size-32768 13 names. name=size-65536 14 names. name=size-131072 15 names. name=<NULL> Written by B. LEE
[ kmem_cache_init ] mm/slab. c sizes[INDEX_AC]. cs_cachep = kmem_cache_create(names[INDEX_AC]. name, sizes[INDEX_AC]. cs_size, ARCH_KMALLOC_MINALIGN, ARCH_KMALLOC_FLAGS|SLAB_PANIC, NULL); sizes[INDEX_L 3]. cs_cachep = kmem_cache_create(names[INDEX_L 3]. name, sizes[INDEX_L 3]. cs_size, ARCH_KMALLOC_MINALIGN, ARCH_KMALLOC_FLAGS|SLAB_PANIC, NULL); 하고, 난뒤 sizes->cs_size != ULONG_MAX 일때까지 while 돌면서 나머지 생성 해 준다. sizes->cs_cachep, sizes->cs_dmacachep. . . Written by B. LEE
- Slides: 90