__lookup_processor_type:
processor id를 사용하여 링커가 만들어내는 별도의 섹션 공간에서 지원되는 프로세서 리스트를 검색하여 찾아낸다. MMU를 사용하지 않으므로 여기서 절대주소로 __proc_info 리스트를 사용할 수 없어서 offset을 계산하여 사용해야 한다.
arch/arm/kernel/head-common.S
__FINIT
.text
/*
* Read processor ID register (CP#15, CR0), and look up in the linker-built
* supported processor list. Note that we can't use the absolute addresses
* for the __proc_info lists since we aren't running with the MMU on
* (and therefore, we are not in the correct address space). We have to
* calculate the offset.
*
* r9 = cpuid
* Returns:
* r3, r4, r6 corrupted
* r5 = proc_info pointer in physical address space
* r9 = cpuid (preserved)
*/
__lookup_processor_type:
adr r3, __lookup_processor_type_data
ldmia r3, {r4 - r6}
sub r3, r3, r4 @ get offset between virt&phys
add r5, r5, r3 @ convert virt addresses to
add r6, r6, r3 @ physical address space
1: ldmia r5, {r3, r4} @ value, mask
and r4, r4, r9 @ mask wanted bits
teq r3, r4
beq 2f
add r5, r5, #PROC_INFO_SZ @ sizeof(proc_info_list)
cmp r5, r6
blo 1b
mov r5, #0 @ unknown processor
2: ret lr
ENDPROC(__lookup_processor_type)
- __FINIT
- 해당 매크로엔 .previous 지시자가 담겨있다.
- 현재 사용하고 있는 섹션 이전에 사용했던 섹션으로 변경된다.
- r3를 사용하여 offset을 계산한다.
- rpi2: 0x8000_0000 (물리 주소 – 가상 주소)
- r5: __proc_info_begin 물리 주소
- r6: __proc_info_end 물리 주소
- ldmia r5, {r3, r4}
- 루프의 시작으로 proc_info_list 구조체의 첫 부분에 있는 cpu value와 cpu mask를 읽어서 r3, r4에 잃어온다.
- beq 2f
- cpu를 판별하여 일치하면 2f 레이블로 이동하고 리턴한다.
- add r5, r5, #PROC_INFO_SZ
- r5를 구조체 사이즈만큼 증가시킨다.
- #PROC_INFO_SZ = 52
- 구조체 proc_info_list와 동일한 사이즈
- cmp r5, r6
- r5가 아직 r6보다 작으면 1f 레이블로 이동하여 루프를 돈다.
프로세서 정보 리스트(proc_info_list)가 저장되는 곳
- 지원되는 각종 프로세서 정보들은 .init.proc.info 섹션에 저장된다.
- rpi2:
- 이 위치에 저장된 정보는 ARMv7 관련된 것만 약 520여 바이트로 구성되어 있다.
- arch/arm/mm/proc-v7.S – __v7_ca7mp_proc_info: 레이블 위치
- 저장되는 섹션 위치를 기술한 소스
arch/arm/kernel/vmlinux.lds
.init.proc.info : {
. = ALIGN(4); __proc_info_begin = .; *(.proc.info.init) __proc_info_end = .;
}
__lookup_processor_type_data: 객체
arch/arm/kernel/head-common.S
/*
* Look in <asm/procinfo.h> for information about the __proc_info structure.
*/
.align 2
.type __lookup_processor_type_data, %object
__lookup_processor_type_data:
.long .
.long __proc_info_begin
.long __proc_info_end
.size __lookup_processor_type_data, . - __lookup_processor_type_data
__v7_ca7mp_proc_info: 객체
아래는 ARM Cortex-A7 아키텍처가 사용하는 프로세서 정보 리스트로 proc_info_list 구조체와 동일하다.
arch/arm/mm/proc-v7.S
/*
* ARM Ltd. Cortex A7 processor.
*/
.type __v7_ca7mp_proc_info, #object
__v7_ca7mp_proc_info:
.long 0x410fc070
.long 0xff0ffff0
__v7_proc __v7_ca7mp_setup
.size __v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info
- __v7_proc __v7_ca7mp_setup
- __v7_proc 매크로
- ARMv7 아키텍처는 모두 공통적으로 사용된다.
- 현재 소스에는 11개 프로세서 정보 리스트가 등록되어 있다.
- ARMv7 아키텍처는 모두 공통적으로 사용된다.
- __v7_ca7mp_setup
- ARM Cortex-A7의 설정 함수가 __v7_proc 매크로의 인수로 사용된다.
- proc_info_list->__cpu_flush와 동일하다.
- __v7_proc 매크로
__v7_proc 매크로
arch/arm/mm/proc-v7.S
.section ".rodata"
string cpu_arch_name, "armv7"
string cpu_elf_name, "v7"
.align
.section ".proc.info.init", #alloc, #execinstr
/*
* Standard v7 proc info content
*/
.macro __v7_proc initfunc, mm_mmuflags = 0, io_mmuflags = 0, hwcaps = 0, proc_fns = v7_processor_functions
ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \
PMD_SECT_AF | PMD_FLAGS_SMP | \mm_mmuflags)
ALT_UP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | \
PMD_SECT_AF | PMD_FLAGS_UP | \mm_mmuflags)
.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | \
PMD_SECT_AP_READ | PMD_SECT_AF | \io_mmuflags
W(b) \initfunc
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP | HWCAP_HALF | HWCAP_THUMB | HWCAP_FAST_MULT | \
HWCAP_EDSP | HWCAP_TLS | \hwcaps
.long cpu_v7_name
.long \proc_fns
.long v7wbi_tlb_fns
.long v6_user_fns
.long v7_cache_fns
.endm
- 44 바이트로 구성되어 있고 proc_info_list(56 바이트)에서 cpu value와 mask 정보 이후의 중간을 구성하는 정보이다.
- 참고: start_kernel() – setup_arch() – setup_processor() | 문c
proc_info_list 구조체
arch/arm/include/asm/procinfo.h
/*
* Note! struct processor is always defined if we're
* using MULTI_CPU, otherwise this entry is unused,
* but still exists.
*
* NOTE! The following structure is defined by assembly
* language, NOT C code. For more information, check:
* arch/arm/mm/proc-*.S and arch/arm/kernel/head.S
*/
struct proc_info_list {
unsigned int cpu_val;
unsigned int cpu_mask;
unsigned long __cpu_mm_mmu_flags; /* used by head.S */
unsigned long __cpu_io_mmu_flags; /* used by head.S */
unsigned long __cpu_flush; /* used by head.S */
const char *arch_name;
const char *elf_name;
unsigned int elf_hwcap;
const char *cpu_name;
struct processor *proc;
struct cpu_tlb_fns *tlb;
struct cpu_user_fns *user;
struct cpu_cache_fns *cache;
};
compressed 커널의 내부를 hexdump하여 분석

