博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
__proc_info_begin->__proc_info_end
阅读量:2443 次
发布时间:2019-05-10

本文共 5828 字,大约阅读时间需要 19 分钟。

/arch/arm/kernel/head.S

/* * Look in 
for information about the __proc_info structure. */ .align 2 .type __lookup_processor_type_data, %object__lookup_processor_type_data: .long . @ “.”表示当前这行代码编译连接后的虚拟地址 .long __proc_info_begin @ proc_info_list结构的开始地址,这是链接地址,也是虚拟地址 .long __proc_info_end @ @proc_info_list结构的结束地址,这是链接地址,也是虚拟地址 .size __lookup_processor_type_data, . - __lookup_processor_type_data

/arch/arm/kernel/vmlinux.lds.S

#define PROC_INFO							\	. = ALIGN(4);							\	VMLINUX_SYMBOL(__proc_info_begin) = .;				\	*(.proc.info.init)						\	VMLINUX_SYMBOL(__proc_info_end) = .;

/arch/arm/mm/Makefile

obj-$(CONFIG_CPU_V7)                              += proc-v7.o

/arch/arm/mm/proc-v7.S

.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
/*	 * ARM Ltd. Cortex A9 processor.	 */	.type   __v7_ca9mp_proc_info, #object__v7_ca9mp_proc_info:	.long	0x410fc090	.long	0xff0ffff0	__v7_proc __v7_ca9mp_setup	.size	__v7_ca9mp_proc_info, . - __v7_ca9mp_proc_info
/*	 * Match any ARMv7 processor core.	 */	.type	__v7_proc_info, #object__v7_proc_info:	.long	0x000f0000		@ Required ID value	.long	0x000f0000		@ Mask for ID	__v7_proc __v7_setup	.size	__v7_proc_info, . - __v7_proc_info

通过使用__v7_proc_info宏定义初始化了一些processerproc info

proc_info structure的定义在/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;};

 不同的proc_info_list结构被用来支持不同的CPU,它们都是定义在“.proc.info.init”段中,在连接内核时,这些结构体被组织在一起,开始地址为__proc_info_begin,结束地址为__proc_info_end。这可以从链接脚本文件arch/arm/kernel/vmlinux.lds.S中看出来

  __proc_info_begin = .;   //proc_info_list结构的开始地址

     *(.proc.info.init)    

   __proc_info_end = .;     //proc_info_list结构的结束地址

 在使能MMU前使用的都是物理地址,而内核却是以虚拟地址连接的,所以在访问proc_init_list结构前,需要先将它的虚拟地址转换为物理地址。

NOTE

/arch/arm/include/asm/assembler.h

#ifdef CONFIG_SMP#define ALT_SMP(instr...)					\9998:	instr/* * Note: if you get assembler errors from ALT_UP() when building with * CONFIG_THUMB2_KERNEL, you almost certainly need to use * ALT_SMP( W(instr) ... ) */#define ALT_UP(instr...)					\	.pushsection ".alt.smp.init", "a"			;\ //放到".alt.smp.init section	.long	9998b						;\9997:	instr							;\	.if . - 9997b != 4					;\ //4byte对齐		.error "ALT_UP() content must assemble to exactly 4 bytes";\	.endif							;\	.popsection#define ALT_UP_B(label)					\	.equ	up_b_offset, label - 9998b			;\	.pushsection ".alt.smp.init", "a"			;\	.long	9998b						;\	W(b)	. + up_b_offset					;\	.popsection#else#define ALT_SMP(instr...)#define ALT_UP(instr...) instr#define ALT_UP_B(label) b label#endif

 

      SMP=y,表示支持SMP;否则,只支持单核。CONFIG_SMP_ON_UP=y,在启动时,在线检测SMP或者单核,并自我修正不能在non-SMP运行的指令。因此,我们可以根据单核和SMP的差异,通过ALT_SMPALT_UP把两种版本的代码放在同一函数中。

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)

      对于设置了SMPSMP_ON_UP的情况,属于SMP的情况会被编译在原本执行函数的内容中,而属于单核的情况会被编译到section ".alt.smp.init中,并且在每4bytes地址后,记录对应4bytes单核版本指令集,以便修正时参考。如下例子:

0xc001858c <__smpalt_begin>:

…..

0xc0018634: c0029fd8     .word 0xc0029fd8 //4 bytes 要取代的目標記憶體位址

0xc0018638: ee080f37     mcr    15, 0, r0, cr8, cr7, {1} //4bytes UniProcessor版本指令

0xc001863c: c0029fec     .word 0xc0029fec

0xc0018640: ee07cfd5     mcr    15, 0, ip, cr7, cr5, {6}

0xc0018644: c002a00c    .word 0xc002a00c

0xc0018648: ee080f37     mcr    15, 0, r0, cr8, cr7, {1}

…..

在最後的Link階段,會把Section .alt.smp.init放在Symbol __smpalt_begin與__smpalt_end之中,因此在程式碼執行階段,就可以透過這兩個Symbol取得 Section .alt.smp.init中所包含單核心程式碼的內容與記憶體範圍.

在Linux Kernel啟動後會呼叫函式__fixup_smp,如果判斷目前是在單核心平台上,就會把在__smpalt_begin到__smpalt_end記憶體範圍的單核心程式碼依據其對應的記憶體位址,進行修正動作.

運作概念如下圖所示

__fixup_smp_on_up:	adr	r0, 1f @ 标号1处的地址	ldmia	r0, {r3 - r5} @ 虚拟地址和物理地址的转换	sub	r3, r0, r3	add	r4, r4, r3	add	r5, r5, r3	b	__do_fixup_smp_on_upENDPROC(__fixup_smp)	.align1:	.word	.	.word	__smpalt_begin	.word	__smpalt_end	.pushsection .data	.globl	smp_on_upsmp_on_up:	ALT_SMP(.long	1)	ALT_UP(.long	0)	.popsection#endif	.text__do_fixup_smp_on_up:	cmp	r4, r5	@ 如果已经end([r4] > [r5])就跳回	movhs	pc, lr	ldmia	r4!, {r0, r6}     @ r0:需要修正的指令地址,r6单核指令,[r4] = [r4] + 8 ARM(	str	r6, [r0, r3]	) @ 用单核指令覆盖原指令,[r0+r3] = [r6],r0+r3是虚拟和物理的转换 THUMB(	add	r0, r0, r3	)#ifdef __ARMEB__ THUMB(	mov	r6, r6, ror #16	)	@ Convert word order for big-endian.#endif THUMB(	strh	r6, [r0], #2	)	@ For Thumb-2, store as two halfwords THUMB(	mov	r6, r6, lsr #16	)	@ to be robust against misaligned r3. THUMB(	strh	r6, [r0]	)	b	__do_fixup_smp_on_upENDPROC(__do_fixup_smp_on_up)

转载地址:http://ldsqb.baihongyu.com/

你可能感兴趣的文章
gmail_如何登出Gmail
查看>>
iPhone正在iOS 12中获得分组通知
查看>>
如何修复Windows 7中的“无法访问Windows Installer服务”错误
查看>>
微软word如何插入页码_如何在Microsoft Word中插入,删除和管理超链接
查看>>
ubuntu中如何启用仓库_如何在Ubuntu中启用本地菜单
查看>>
outlook密码更改_如何更改您的Outlook.com密码
查看>>
如何在Ubuntu 14.04中管理启动应用程序
查看>>
如何在Ubuntu 14.04中读取MOBI文件
查看>>
计算两张图片是否完全相同_您如何分辨两张DVD是否完全相同?
查看>>
如何在Windows 10中连接到无线网络
查看>>
proxies中的机密信息_新机密模式在Gmail中的工作方式
查看>>
如何检查MacBook的电池状况
查看>>
2k分辨率显示器 浏览器_如何使浏览器使用显示器的完整分辨率?
查看>>
ubuntu lts 版本_最新的Ubuntu LTS版本是什么?
查看>>
苹果收集到月中蜂窝数据满_苹果不会收集有关您的大量数据
查看>>
redis发布订阅数据太大_一切现在都是订阅,而且太多了
查看>>
android alexa_如何将Alexa设置为Android上的默认数字助理
查看>>
2018年4月13日_如何立即获取Windows 10的2018年4月更新
查看>>
电报机器人 gmail_如何在新的Gmail中查找联系人
查看>>
硬盘未分配空间变为可用空间_使用Windows 10的新“可用空间”工具清理硬盘
查看>>