arch/arm/kernel

pandroid 取得はどうも時間がかかるみたいなので linux-linaro-2.6.35 の中身を確認してます。あてずっぽうで head.S 開いたらここがエントリポイントらしい。

/*
 * Kernel startup entry point.
 * ---------------------------
 *
 * This is normally called from the decompressor code.  The requirements
 * are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
 * r1 = machine nr, r2 = atags pointer.
 *
 * This code is mostly position independent, so if you link the kernel at
 * 0xc0008000, you call this at __pa(0xc0008000).
 *
 * See linux/arch/arm/tools/mach-types for the complete list of machine
 * numbers for r1.
 *
 * We're trying to keep crap to a minimum; DO NOT add any machine specific
 * crap here - that's what the boot loader (or in extreme, well justified
 * circumstances, zImage) is for.
 */
	__HEAD
ENTRY(stext)

ええと System.map 見たら記述ありますね。

c0008000 T stext

てかこんな微妙なあたりを穿らなくても、と自分でも思うんですがorz

mm 配下

確認してみたら proc-arm926.S がコンパイル対象な模様。以下なカンジのポインタ配列っぽいナニが定義されてます。

	.align

	.section ".proc.info.init", #alloc, #execinstr

	.type	__arm926_proc_info,#object
__arm926_proc_info:
	.long	0x41069260			@ ARM926EJ-S (v5TEJ)
	.long	0xff0ffff0
	.long   PMD_TYPE_SECT | \
		PMD_SECT_BUFFERABLE | \
		PMD_SECT_CACHEABLE | \
		PMD_BIT4 | \
		PMD_SECT_AP_WRITE | \
		PMD_SECT_AP_READ
	.long   PMD_TYPE_SECT | \
		PMD_BIT4 | \
		PMD_SECT_AP_WRITE | \
		PMD_SECT_AP_READ
	b	__arm926_setup
	.long	cpu_arch_name
	.long	cpu_elf_name
	.long	HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA
	.long	cpu_arm926_name
	.long	arm926_processor_functions

引用部分のいっちゃん下の arm926_processor_functions が手続きポインタな配列。配置されるのは ".proc.info.init" とのことなのでリンカスクリプトなソレを確認してみる。arch/arm/kernel/vmlinux.lds にて以下。

OUTPUT_ARCH(arm)
ENTRY(stext)
jiffies = jiffies_64;
SECTIONS
{
 . = 0xC0000000 + 0x00008000;
 .init : { /* Init code and data		*/
  _stext = .;
  _sinittext = .;
   *(.head.text)
   *(.init.text) *(.cpuinit.text) *(.meminit.text)
  _einittext = .;
  __proc_info_begin = .;
   *(.proc.info.init)
  __proc_info_end = .;

なんか書き方というか読み方忘れてますorz
てゆーか、このポインタ配列をどこで使っているのですか、なソレが知りたい。

むむ

__proc_info_begin で grep したら当たった。

$ find|xargs grep __proc_info_begin
./kernel/vmlinux.lds.S:         __proc_info_begin = .;
./kernel/vmlinux.lds.S:ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
./kernel/vmlinux.lds:  __proc_info_begin = .;
./kernel/vmlinux.lds:ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
./kernel/head-common.S:3:       .long   __proc_info_begin
Binary file ./kernel/head.o matches
$

ええと arch/arm/kernel/head-common.S か。

/*
 * Look in <asm/procinfo.h> and arch/arm/kernel/arch.[ch] for
 * more information about the __proc_info and __arch_info structures.
 */
	.align	2
3:	.long	__proc_info_begin
	.long	__proc_info_end
4:	.long	.
	.long	__arch_info_begin
	.long	__arch_info_end

ええと、上記コメントの通り、arch/arm/include/asm/procinfo.h にて __proc_info_begin から始まる領域な構造体の定義があるな。

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;

asm926_processor_function なソレは struct processor 型で参照する模様。この構造体の名前で grep してみるか。

$ find|xargs grep proc_info_list
./kernel/asm-offsets.s:->PROC_INFO_SZ #52 sizeof(struct proc_info_list) @
./kernel/asm-offsets.s:->PROCINFO_INITFUNC #16 offsetof(struct proc_info_list, __cpu_flush)     @
./kernel/asm-offsets.s:->PROCINFO_MM_MMUFLAGS #8 offsetof(struct proc_info_list, __cpu_mm_mmu_flags)    @
./kernel/asm-offsets.s:->PROCINFO_IO_MMUFLAGS #12 offsetof(struct proc_info_list, __cpu_io_mmu_flags)   @
./kernel/setup.c:extern struct proc_info_list *lookup_processor_type(unsigned int);
./kernel/setup.c:       struct proc_info_list *list;
./kernel/asm-offsets.c:  DEFINE(PROC_INFO_SZ,           sizeof(struct proc_info_list));
./kernel/asm-offsets.c:  DEFINE(PROCINFO_INITFUNC,      offsetof(struct proc_info_list, __cpu_flush));
./kernel/asm-offsets.c:  DEFINE(PROCINFO_MM_MMUFLAGS,   offsetof(struct proc_info_list, __cpu_mm_mmu_flags));
./kernel/asm-offsets.c:  DEFINE(PROCINFO_IO_MMUFLAGS,   offsetof(struct proc_info_list, __cpu_io_mmu_flags));
./kernel/head-common.S: add     r5, r5, #PROC_INFO_SZ           @ sizeof(proc_info_list)
./include/asm/procinfo.h:struct proc_info_list {
$

で、手続きの名前で grep してみるに以下。

$ find|xargs grep lookup_processor_type
Binary file ./kernel/built-in.o matches
./kernel/head-nommu.S:  bl      __lookup_processor_type         @ r5=procinfo r9=cpuid
Binary file ./kernel/setup.o matches
./kernel/head.S:        bl      __lookup_processor_type         @ r5=procinfo r9=cpuid
./kernel/head.S:        bl      __lookup_processor_type
./kernel/setup.c:extern struct proc_info_list *lookup_processor_type(unsigned int);
./kernel/setup.c:       list = lookup_processor_type(read_cpuid_id());
./kernel/head-common.S:__lookup_processor_type:
./kernel/head-common.S:ENDPROC(__lookup_processor_type)
./kernel/head-common.S:ENTRY(lookup_processor_type)
./kernel/head-common.S: bl      __lookup_processor_type
./kernel/head-common.S:ENDPROC(lookup_processor_type)
Binary file ./kernel/head.o matches
$

で、arch/arm/kernel/head-common.S の中見たらありますね。

/*
 * This provides a C-API version of the above function.
 */
ENTRY(lookup_processor_type)
	stmfd	sp!, {r4 - r7, r9, lr}
	mov	r9, r0
	bl	__lookup_processor_type
	mov	r0, r5
	ldmfd	sp!, {r4 - r7, r9, pc}
ENDPROC(lookup_processor_type)

_ で始まる方も直上にて定義されてます。arm の命令慣れてないので何してるのかを直感的にイメージません。ちょっと ARM のマニュアル流して確認入れた方が良いな。