wzero3_start.S

LinuxLoader.exe 経由の起動ならスタートアップはこんな感じなんかね。良く知らんけど。

#include <machine/asm.h>
#include <arm/armreg.h>
#include <arm/arm32/pte.h>
#include <arm/arm32/pmap.h>		/* for PMAP_DOMAIN_KERNEL */

/*
 * Size of the XScale core D-cache.
 *
 * copied from arm/arm/cpufunc_asm_xscale.S
 * XXX: better be in a common header file.
 */
#define	DCACHE_SIZE		0x00008000
#define	DCACHE_LINESIZE		32

/*
 * CPWAIT -- Canonical method to wait for CP15 update.
 * From: Intel 80200 manual, section 2.3.3.
 *
 * NOTE: Clobbers the specified temp reg.
 *
 * copied from arm/arm/cpufunc_asm_xscale.S
 * XXX: better be in a common header file.
 */
#define	CPWAIT_BRANCH							 \
	sub	pc, pc, #4

#define	CPWAIT(tmp)							 \
	mrc	p15, 0, tmp, c2, c0, 0	/* arbitrary read of CP15 */	;\
	mov	tmp, tmp		/* wait for it to complete */	;\
	CPWAIT_BRANCH			/* branch to next insn */


/*
 * Kernel start routine
 */
	.section .start,"ax",%progbits

	.global	_C_LABEL(wzero3_start)
_C_LABEL(wzero3_start):
	/* Disable IRQ/FIQ */
	mrs	r2, cpsr
	orr	r2, r2, #(I32_bit|F32_bit)
	msr	cpsr_all, r2

	/* Clean and Invalidaet I/D-Cache */
	bic	r2, pc, #(DCACHE_LINESIZE - 1)
1:	add	r3, r2, #(DCACHE_SIZE * 2)	/* XXX */
	ldr	r0, [r2], #DCACHE_LINESIZE
	teq	r3, r2
	bne	1b
	CPWAIT(r0)
	mov	r2, #0
	mcr	p15, 0, r2, c7, c10, 4	/* drain write buffer */
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	CPWAIT(r0)
	mcr	p15, 0, r2, c7, c7, 0	/* flush I+D cache */
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	CPWAIT(r0)

	/* Disable I/D-Cache */
	mrc	p15, 0, r2, c1, c0, 0
	bic	r2, r2, #CPU_CONTROL_DC_ENABLE
	bic	r2, r2, #CPU_CONTROL_IC_ENABLE
	mcr	p15, 0, r2, c1, c0, 0
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	CPWAIT(r0)

	/* Disable MMU */
	mrc	p15, 0, r2, c1, c0, 0
	bic	r2, r2, #CPU_CONTROL_MMU_ENABLE
	mcr	p15, 0, r2, c1, c0, 0

	/* reloc */
	adr	r1, _C_LABEL(hoge_start)
	adr	r0, .Lstart
	ldmia	r0, {r0, r2}
	bic	r0, r0, #0xff000000
	orr	r0, r0, #0xa0000000
	bic	r2, r2, #0xff000000
	orr	r2, r2, #0xa0000000
	sub	r2, r2, r0	/* size = _edata - start */
	cmp	r1, r0
	beq	.Lreloc_done	/* if (dst == src) */

2:	ldrb	r3, [r1], #1
	strb	r3, [r0], #1
	subs	r2, r2, #1
	bne	2b

	ldr	r0, .Lreloc_done
	bic	r0, r0, #0xff000000
	orr	r0, r0, #0xa0000000
	mov	pc, r0		/* Jump! */

.Lstart:
	.word	_C_LABEL(hoge_start)
	.word	_edata

.Lreloc_done:
	.word	Lreloc_done

Lreloc_done:
	/*
	 *  Kernel is loaded in SDRAM (0xa0200000..), and is expected to run
	 *  in VA 0xc0200000..  
	 */

	/* build page table from scratch */
	ldr	r0, .Lstartup_pagetable
	adr	r4, .Lmmu_init_table
	b	4f

3:	str	r3, [r0, r2]
	add	r2, r2, #4
	add	r3, r3, #(L1_S_SIZE)
	adds	r1, r1, #-1
	bhi	3b
4:
	ldmia	r4!, {r1, r2, r3}	/* # of sections, PA|attr, VA */
	cmp	r1, #0
	bne	3b

	mcr	p15, 0, r0, c2, c0, 0	/* Set TTB */
	mcr	p15, 0, r0, c8, c7, 0	/* Flush TLB */

	/* Set the Domain Access register.  Very important! */
	mov	r0, #((DOMAIN_CLIENT<<(PMAP_DOMAIN_KERNEL*2))|DOMAIN_CLIENT)
	mcr	p15, 0, r0, c3, c0, 0

	/* Enable MMU */
	mrc	p15, 0, r0, c1, c0, 0
	orr	r0, r0, #CPU_CONTROL_MMU_ENABLE
	mcr	p15, 0, r0, c1, c0, 0
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	CPWAIT(r0)

	/* Jump to kernel code in TRUE VA */
	adr	r0, Lstart
	ldr	pc, [r0]

Lstart:
	.word	start

#define MMU_INIT(va,pa,n_sec,attr)					\
	.word	(n_sec);						\
	.word	4 * ((va) >> L1_S_SHIFT);				\
	.word	(pa)|(attr);

.Lstartup_pagetable:
	.word	0xa0004000

.Lmmu_init_table:
	/* fill all table VA==PA */
	MMU_INIT(0x00000000, 0x00000000, 1<<(32-L1_S_SHIFT), L1_TYPE_S|L1_S_AP(AP_KRW))
	/* map SDRAM VA==PA, WT cacheable */
	MMU_INIT(0xa0000000, 0xa0000000, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))
	/* map VA 0xc0000000..0xc3ffffff to PA 0xa0000000..0xa3ffffff */
	MMU_INIT(0xc0000000, 0xa0000000, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW))

	.word	0,0,0	/* end of table */