1.2.1 lookup_processor_type
(1)vmlinux.lds.s
文件在arch\arm\kernel\ vmlinux.lds.s
__proc_info_begin = .; //include/asm-arm/procinfo.h中定义
*(.proc.info.init)
__proc_info_end = .;
__arch_info_begin = .; //include/asm-arm/mach/arch.h 中定义
*(.arch.info.init)
__arch_info_end = .;
(2)procinfo.h
文件在include/asm-arm/procinfo.h
struct proc_info_list { // pro-v7m.S对其实例化
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;
};
(3)pro-v7m.S
文件在arch\arm\mm\ pro-v7m.S,内容很多,核心就是.section ".proc.info.init",其它的都是它这个结构体中得成员,如__v7m_setup、cpu_arch_name、cpu_elf_name、cpu_v7m_name、v7m_processor_functions等。
cpu_v7m_name:
.ascii "ARMv7-M Processor"
.align
.section ".text.init", #alloc, #execinstr
.type v7m_processor_functions, #object
ENTRY(v7m_processor_functions)
.word v7m_early_abort
.word cpu_v7m_proc_init
.word cpu_v7m_proc_fin
.word cpu_v7m_reset
.word cpu_v7m_do_idle
.word cpu_v7m_dcache_clean_area
.word cpu_v7m_switch_mm
.word cpu_v7m_set_pte_ext
.word pabort_noifar
.size v7m_processor_functions, . - v7m_processor_functions
.type cpu_arch_name, #object
cpu_arch_name:
.asciz "armv7m"
.size cpu_arch_name, . - cpu_arch_name
.type cpu_elf_name, #object
cpu_elf_name:
.asciz "v7m"
.size cpu_elf_name, . - cpu_elf_name
.align
.section ".proc.info.init", #alloc, #execinstr
/*
* Match any ARMv7-M processor core.
*/
.type __v7m_proc_info, #object
__v7m_proc_info: //E000ED00是CPUID基址寄存器,其中[19:16]读作常量F
.long 0x000f0000 @ Required ID value
.long 0x000f0000 @ Mask for ID
.long 0 @ proc_info_list.__cpu_mm_mmu_flags
.long 0 @ proc_info_list.__cpu_io_mmu_flags
b __v7m_setup @ proc_info_list.__cpu_flush
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
.long cpu_v7m_name
.long v7m_processor_functions @ proc_info_list.proc
.long 0 @ proc_info_list.tlb
.long 0 @ proc_info_list.user
.long 0 @ proc_info_list.cache
.size __v7m_proc_info, . - __v7m_proc_info
1.2.2 lookup_machine_type
(1)arch.h
文件在include/asm-arm/mach/arch.h
struct machine_desc { //在stm3210e_eval.c中实例化
/*
* Note! The first four elements are used
* by assembler code in head.S, head-common.S
*/
unsigned int nr; /* architecture number */
unsigned int phys_io; /* start of physical io */
unsigned int io_pg_offst; /* byte offset for io
* page tabe entry */
const char *name; /* architecture name */
unsigned long boot_params; /* tagged list */
unsigned int video_start; /* start of video RAM */
unsigned int video_end; /* end of video RAM */
unsigned int reserve_lp0 :1; /* never has lp0 */
unsigned int reserve_lp1 :1; /* never has lp1 */
unsigned int reserve_lp2 :1; /* never has lp2 */
unsigned int soft_reboot :1; /* soft reboot */
void (*fixup)(struct machine_desc *,
struct tag *, char **,
struct meminfo *);
void (*map_io)(void);/* IO mapping function */
void (*init_irq)(void);
struct sys_timer *timer; /* system tick timer */
void (*init_machine)(void);
};
/*
* Set of macros to define architecture features. This is built into
* a table by the linker.
*/
#define MACHINE_START(_type,_name) \
static const struct machine_desc __mach_desc_##_type \
__used \
__attribute__((__section__(".arch.info.init"))) = { \
.nr = MACH_TYPE_##_type, \
.name = _name,
#define MACHINE_END \
};
(2)stm3210e_eval.c
文件在arch\arm\mach-stm3210e_eval\ stm3210e_eval.c
MACHINE_START(STM3210E_EVAL, "STM3210E-EVAL")
/* Maintainer: MCD Application TEAM */ /* Status */
.fixup = stm3210e_eval_fixup, //OK
.boot_params = CONFIG_EXTERNAL_RAM_BASE + 0x100, //OK
.init_irq = nvic_init_irq, //OK
.timer = &stm3210e_eval_timer, //OK
.init_machine = stm3210e_eval_init, //OK
MACHINE_END
(3)match-type.h
文件在include/asm-arm/mach-type.h
#define MACH_TYPE_STM3210E_EVAL 2189
1.3 __v7m_setup
文件在arch\arm\mm\ pro-v7m.S
/*
* __v7m_setup
*
* Initialise TLB, Caches, and MMU state ready to switch the MMU
* on. Return in r0 the new CP15 C1 control register setting.
*
* We automatically detect if we have a Harvard cache, and use the
* Harvard cache control instructions insead of the unified cache
* control instructions.
*
* This should be able to cover all ARMv7-M cores.
*
* It is assumed that:
* - cache type register is implemented
*/
__v7m_setup:
@ Configure the vector table base address //配置中断向量偏移
ldr r0, =0xe000ed08 @ vector table base address
ldr r12, =vector_table
str r12, [r0]
@ Lower the priority of the SVC and PendSV exceptions
ldr r0, =0xe000ed1c //设置SVC、PendSV的中断优先级都为128
mov r5, #0x80000000
str r5, [r0] @ set SVC priority
ldr r0, =0xe000ed20
mov r5, #0x00800000
str r5, [r0] @ set PendSV priority
@ SVC to run the kernel in this mode
badr r0, 1f
ldr r5, [r12, #11 * 4] @ read the SVC vector entry
str r0, [r12, #11 * 4] @ write the temporary SVC vector entry
mov r6, lr @ save LR
mov r7, sp @ save SP
#if !defined(CONFIG_XIP_KERNEL)
ldr sp, =__v7m_setup_stack_top
#endif
cpsie i
svc #0 //呼叫系统服务,权威指南-P182,暂时没找到?
1: cpsid i
str r5, [r12, #11 * 4] @ restore the original SVC vector entry
mov lr, r6 @ restore LR
mov sp, r7 @ restore SP
@ Special-purpose control register
mov r0, #1 //还是进入特权级的线程模式,主堆栈?
msr control, r0 @ Thread mode has unpriviledged access
@ Configure the System Control Register
ldr r0, =0xe000ed10 @ system control register
ldr r12, [r0] //不知道是干啥,不确定是否在E000 ED10上
orr r12, #1 << 9 @ STKALIGN
str r12, [r0] //E000 ED14的这个位倒是为了对齐双字节,指南-306
mov pc, lr //之前的lr值赋给PC,即PC转到那里执行
ENDPROC(__v7m_setup)
1.4 __switch_data
文件在arch\arm\kernel\head-common.S
.type __switch_data, %object
__switch_data:
.long __mmap_switched
.long __data_loc @ r4
.long __data_start @ r5
.long _edata_loc @ r6 //added to determine the size of data segment to be copied.
.long __bss_start @ r6
.long _end @ r7
.long processor_id @ r4
.long __machine_arch_type @ r5
.long __atags_pointer @ r6
#ifdef CONFIG_CPU_CP15
.long cr_alignment @ r7
#else
.long 0 @ r7
#endif
.long init_thread_union + THREAD_START_SP @ sp
/*
* The following fragment of code is executed with the MMU on in MMU mode,
* and uses absolute addresses; this is not position independent.
*
* r0 = cp#15 control register
* r1 = machine ID
* r2 = atags pointer
* r9 = processor ID
*/
__mmap_switched: //从__v7m_setup出来以后,转到这里
adr r3, __switch_data + 4
ldmia r3!, {r4, r5, r6}
cmp r4, r5 @ Copy data segment if needed
beq 2f
1: ldr fp, [r4], #4 //fp是r11
str fp, [r5], #4
cmp r4, r6
bne 1b
2: ldmia r3!,{r6,r7} @load __bss_start to r6 and _end to r7
mov fp, #0 @ Clear BSS (and zero fp)
1: cmp r6, r7
itt cc //itt相当于if-then
strcc fp, [r6],#4
bcc 1b
ARM( ldmia r3, {r4, r5, r6, r7, sp})
str r9, [r4] @ Save processor ID被赋值
str r1, [r5] @ Save machine type被赋值
str r2, [r6] @ Save atags pointer被赋值
bic r4, r0, #CR_A @ Clear 'A' bit 这句貌似没用?
#if !defined (CONFIG_CPU_V7M)
stmia r7, {r0, r4} @ Save control register values
#endif
@2: b 2b
b start_kernel //跳入C语言的函数
ENDPROC(__mmap_switched)
|