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 */