blob: ef936ae2f87490ac408a3cef980726731e0d2a1a [file] [log] [blame]
* Boot entry point and assembler functions for armv7 tests.
* Copyright (C) 2014, Red Hat Inc, Andrew Jones <>
* This work is licensed under the terms of the GNU LGPL, version 2.
#define __ASSEMBLY__
#include <auxinfo.h>
#include <asm/thread_info.h>
#include <asm/asm-offsets.h>
#include <asm/pgtable-hwdef.h>
#include <asm/ptrace.h>
#include <asm/sysreg.h>
.section .init
.globl start
* set stack, making room at top of stack for cpu0's
* exception stacks. Must start wtih stackptr, not
* stacktop, so the thread size masking (shifts) work.
ldr sp, =stackptr
* save sp before pushing anything on the stack
* lr makes a good temp register right now
mov lr, sp
* bootloader params are in r0-r2
* See the kernel doc Documentation/arm/Booting
* r0 = 0
* r1 = machine type number
* r2 = physical address of the dtb
* As we have no need for r0's nor r1's value, then
* put the dtb in r0. This allows setup to be consistent
* with arm64.
mov r0, r2
push {r0-r1}
/* set up vector table, mode stacks, and enable the VFP */
mov r0, lr @ lr is stack top (see above),
@ which is the exception stacks base
bl exceptions_init
bl enable_vfp
/* complete setup */
pop {r0-r1}
bl setup
bl get_mmu_off
cmp r0, #0
bne 1f
bl setup_vm
/* run the test */
ldr r0, =__argc
ldr r0, [r0]
ldr r1, =__argv
ldr r2, =__environ
bl main
bl exit
b halt
.macro set_mode_stack mode, stack
add \stack, #S_FRAME_SIZE
msr cpsr_c, #(\mode | PSR_I_BIT | PSR_F_BIT)
mov sp, \stack
mrc p15, 0, r2, c1, c0, 0 @ read SCTLR
bic r2, #CR_V @ SCTLR.V := 0
mcr p15, 0, r2, c1, c0, 0 @ write SCTLR
ldr r2, =vector_table
mcr p15, 0, r2, c12, c0, 0 @ write VBAR
mrs r2, cpsr
/* first frame reserved for svc mode */
set_mode_stack UND_MODE, r0
set_mode_stack ABT_MODE, r0
set_mode_stack IRQ_MODE, r0
set_mode_stack FIQ_MODE, r0
msr cpsr_cxsf, r2 @ back to svc mode
mov pc, lr
/* Enable full access to CP10 and CP11: */
mov r0, #(3 << 22 | 3 << 20)
mcr p15, 0, r0, c1, c0, 2
/* Set the FPEXC.EN bit to enable Advanced SIMD and VFP: */
mov r0, #(1 << 30)
vmsr fpexc, r0
mov pc, lr
.global get_mmu_off
ldr r0, =auxinfo
ldr r0, [r0, #4]
mov pc, lr
.global secondary_entry
/* enable the MMU unless requested off */
bl get_mmu_off
cmp r0, #0
bne 1f
mov r1, #0
ldr r0, =mmu_idmap
ldr r0, [r0]
bl asm_mmu_enable
* Set the stack, and set up vector table
* and exception stacks. Exception stacks
* space starts at stack top and grows up.
ldr r1, =secondary_data
ldr r0, [r1]
mov sp, r0
bl exceptions_init
bl enable_vfp
/* finish init in C code */
bl secondary_cinit
/* r0 is now the entry function, run it */
blx r0
b do_idle
.globl halt
1: wfi
b 1b
* asm_mmu_enable
* Inputs:
* (r0 - lo, r1 - hi) is the base address of the translation table
* Outputs: none
.equ PRRR, 0xeeaa4400 @ MAIR0 (from Linux kernel)
.equ NMRR, 0xff000004 @ MAIR1 (from Linux kernel)
.globl asm_mmu_enable
mcr p15, 0, r2, c8, c7, 0
dsb nsh
/* TTBCR */
ldr r2, =(TTBCR_EAE | \
mcr p15, 0, r2, c2, c0, 2
/* MAIR */
ldr r2, =PRRR
mcr p15, 0, r2, c10, c2, 0
ldr r2, =NMRR
mcr p15, 0, r2, c10, c2, 1
/* TTBR0 */
mcrr p15, 0, r0, r1, c2
/* SCTLR */
mrc p15, 0, r2, c1, c0, 0
orr r2, #CR_C
orr r2, #CR_I
orr r2, #CR_M
mcr p15, 0, r2, c1, c0, 0
mov pc, lr
.macro dcache_clean_inval domain, start, end, tmp1, tmp2
ldr \tmp1, =dcache_line_size
ldr \tmp1, [\tmp1]
sub \tmp2, \tmp1, #1
bic \start, \start, \tmp2
mcr p15, 0, \start, c7, c14, 1
add \start, \start, \tmp1
cmp \start, \end
blo 9998b
dsb \domain
.globl asm_mmu_disable
/* SCTLR */
mrc p15, 0, r0, c1, c0, 0
bic r0, #CR_M
mcr p15, 0, r0, c1, c0, 0
ldr r0, =__phys_offset
ldr r0, [r0]
ldr r1, =__phys_end
ldr r1, [r1]
dcache_clean_inval sy, r0, r1, r2, r3
mov pc, lr
* Vector stubs
* Simplified version of the Linux kernel implementation
* arch/arm/kernel/entry-armv.S
* Each mode has an S_FRAME_SIZE sized memory region,
* and the mode's stack pointer has been initialized
* to the base of that region in exceptions_init.
.macro vector_stub, name, vec, mode, correction=0
.align 5
.if \correction
sub lr, lr, #\correction
* Save r0, r1, lr_<exception> (parent PC)
* and spsr_<exception> (parent CPSR)
str r0, [sp, #S_R0]
str r1, [sp, #S_R1]
str lr, [sp, #S_PC]
mrs r0, spsr
str r0, [sp, #S_PSR]
/* Prepare for SVC32 mode. */
mrs r0, cpsr
bic r0, #MODE_MASK
orr r0, #SVC_MODE
msr spsr_cxsf, r0
/* Branch to handler in SVC mode */
mov r0, #\vec
mov r1, sp
ldr lr, =vector_common
movs pc, lr
vector_stub rst, 0, UND_MODE
vector_stub und, 1, UND_MODE
vector_stub pabt, 3, ABT_MODE, 4
vector_stub dabt, 4, ABT_MODE, 8
vector_stub irq, 6, IRQ_MODE, 4
vector_stub fiq, 7, FIQ_MODE, 4
.align 5
* Save r0, r1, lr_<exception> (parent PC)
* and spsr_<exception> (parent CPSR)
push { r1 }
lsr r1, sp, #THREAD_SHIFT
str r0, [r1, #S_R0]
pop { r0 }
str r0, [r1, #S_R1]
str lr, [r1, #S_PC]
mrs r0, spsr
str r0, [r1, #S_PSR]
* Branch to handler, still in SVC mode.
* r0 := 2 is the svc vector number.
mov r0, #2
ldr lr, =vector_common
mov pc, lr
/* make room for pt_regs */
sub sp, #S_FRAME_SIZE
tst sp, #4 @ check stack alignment
subne sp, #4
/* store registers r0-r12 */
stmia sp, { r0-r12 } @ stored wrong r0 and r1, fix later
/* get registers saved in the stub */
ldr r2, [r1, #S_R0] @ r0
ldr r3, [r1, #S_R1] @ r1
ldr r4, [r1, #S_PC] @ lr_<exception> (parent PC)
ldr r5, [r1, #S_PSR] @ spsr_<exception> (parent CPSR)
/* fix r0 and r1 */
str r2, [sp, #S_R0]
str r3, [sp, #S_R1]
/* store sp_svc, if we were in usr mode we'll fix this later */
add r6, sp, #S_FRAME_SIZE
addne r6, #4 @ stack wasn't aligned
str r6, [sp, #S_SP]
str lr, [sp, #S_LR] @ store lr_svc, fix later for usr mode
str r4, [sp, #S_PC] @ store lr_<exception>
str r5, [sp, #S_PSR] @ store spsr_<exception>
/* set ORIG_r0 */
mov r2, #-1
str r2, [sp, #S_OLD_R0]
/* if we were in usr mode then we need sp_usr and lr_usr instead */
and r1, r5, #MODE_MASK
cmp r1, #USR_MODE
bne 1f
add r1, sp, #S_SP
stmia r1, { sp,lr }^
/* Call the handler. r0 is the vector number, r1 := pt_regs */
1: mov r1, sp
bl do_handle_exception
* make sure we restore sp_svc on mode change. No need to
* worry about lr_svc though, as that gets clobbered on
* exception entry anyway.
str r6, [sp, #S_SP]
/* return from exception */
msr spsr_cxsf, r5
ldmia sp, { r0-pc }^
.align 5
b vector_addrexcptn
.section .text.ex
.align 5
b vector_rst
b vector_und
b vector_svc
b vector_pabt
b vector_dabt
b vector_addrexcptn @ should never happen
b vector_irq
b vector_fiq