1/* 2 * Boot entry point and assembler functions for armv7 tests. 3 * 4 * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com> 5 * 6 * This work is licensed under the terms of the GNU LGPL, version 2. 7 */ 8#define __ASSEMBLY__ 9#include <asm/asm-offsets.h> 10#include <asm/ptrace.h> 11#include <asm/cp15.h> 12 13.arm 14 15.section .init 16 17.globl start 18start: 19 /* 20 * bootloader params are in r0-r2 21 * See the kernel doc Documentation/arm/Booting 22 * r0 = 0 23 * r1 = machine type number 24 * r2 = physical address of the dtb 25 * 26 * As we have no need for r0's nor r1's value, then 27 * put the dtb in r0. This allows setup to be consistent 28 * with arm64. 29 */ 30 ldr sp, =stackptr 31 mov r0, r2 32 push {r0-r1} 33 34 /* set up vector table and mode stacks */ 35 bl exceptions_init 36 37 /* complete setup */ 38 pop {r0-r1} 39 bl setup 40 41 /* run the test */ 42 ldr r0, =__argc 43 ldr r0, [r0] 44 ldr r1, =__argv 45 bl main 46 bl exit 47 b halt 48 49 50.macro set_mode_stack mode, stack 51 add \stack, #S_FRAME_SIZE 52 msr cpsr_c, #(\mode | PSR_I_BIT | PSR_F_BIT) 53 isb 54 mov sp, \stack 55.endm 56 57exceptions_init: 58 mrc p15, 0, r2, c1, c0, 0 @ read SCTLR 59 bic r2, #CR_V @ SCTLR.V := 0 60 mcr p15, 0, r2, c1, c0, 0 @ write SCTLR 61 ldr r2, =vector_table 62 mcr p15, 0, r2, c12, c0, 0 @ write VBAR 63 64 mrs r2, cpsr 65 ldr r1, =exception_stacks 66 67 /* first frame reserved for svc mode */ 68 set_mode_stack UND_MODE, r1 69 set_mode_stack ABT_MODE, r1 70 set_mode_stack IRQ_MODE, r1 71 set_mode_stack FIQ_MODE, r1 72 73 msr cpsr_cxsf, r2 @ back to svc mode 74 isb 75 mov pc, lr 76 77.text 78 79.globl halt 80halt: 811: wfi 82 b 1b 83 84/* 85 * asm_mmu_enable 86 * Inputs: 87 * (r0 - lo, r1 - hi) is the base address of the translation table 88 * Outputs: none 89 */ 90.equ PRRR, 0xeeaa4400 @ MAIR0 (from Linux kernel) 91.equ NMRR, 0xff000004 @ MAIR1 (from Linux kernel) 92.globl asm_mmu_enable 93asm_mmu_enable: 94 /* TTBCR */ 95 mrc p15, 0, r2, c2, c0, 2 96 orr r2, #(1 << 31) @ TTB_EAE 97 mcr p15, 0, r2, c2, c0, 2 98 99 /* MAIR */ 100 ldr r2, =PRRR 101 mcr p15, 0, r2, c10, c2, 0 102 ldr r2, =NMRR 103 mcr p15, 0, r2, c10, c2, 1 104 105 /* TTBR0 */ 106 mcrr p15, 0, r0, r1, c2 107 isb 108 109 /* SCTLR */ 110 mrc p15, 0, r2, c1, c0, 0 111 orr r2, #CR_C 112 orr r2, #CR_I 113 orr r2, #CR_M 114 mcr p15, 0, r2, c1, c0, 0 115 isb 116 117 mov pc, lr 118 119/* 120 * Vector stubs 121 * Simplified version of the Linux kernel implementation 122 * arch/arm/kernel/entry-armv.S 123 * 124 * Each mode has an S_FRAME_SIZE sized memory region, 125 * and the mode's stack pointer has been initialized 126 * to the base of that region in exceptions_init. 127 */ 128.macro vector_stub, name, vec, mode, correction=0 129.align 5 130vector_\name: 131.if \correction 132 sub lr, lr, #\correction 133.endif 134 /* 135 * Save r0, r1, lr_<exception> (parent PC) 136 * and spsr_<exception> (parent CPSR) 137 */ 138 str r0, [sp, #S_R0] 139 str r1, [sp, #S_R1] 140 str lr, [sp, #S_PC] 141 mrs r0, spsr 142 str r0, [sp, #S_PSR] 143 144 /* Prepare for SVC32 mode. */ 145 mrs r0, cpsr 146 bic r0, #MODE_MASK 147 orr r0, #SVC_MODE 148 msr spsr_cxsf, r0 149 150 /* Branch to handler in SVC mode */ 151 mov r0, #\vec 152 mov r1, sp 153 ldr lr, =vector_common 154 movs pc, lr 155.endm 156 157vector_stub rst, 0, UND_MODE 158vector_stub und, 1, UND_MODE 159vector_stub pabt, 3, ABT_MODE, 4 160vector_stub dabt, 4, ABT_MODE, 8 161vector_stub irq, 6, IRQ_MODE, 4 162vector_stub fiq, 7, FIQ_MODE, 4 163 164.align 5 165vector_svc: 166 /* 167 * Save r0, r1, lr_<exception> (parent PC) 168 * and spsr_<exception> (parent CPSR) 169 */ 170 push { r1 } 171 ldr r1, =exception_stacks 172 str r0, [r1, #S_R0] 173 pop { r0 } 174 str r0, [r1, #S_R1] 175 str lr, [r1, #S_PC] 176 mrs r0, spsr 177 str r0, [r1, #S_PSR] 178 179 /* 180 * Branch to handler, still in SVC mode. 181 * r0 := 2 is the svc vector number. 182 */ 183 mov r0, #2 184 ldr lr, =vector_common 185 mov pc, lr 186 187vector_common: 188 /* make room for pt_regs */ 189 sub sp, #S_FRAME_SIZE 190 tst sp, #4 @ check stack alignment 191 subne sp, #4 192 193 /* store registers r0-r12 */ 194 stmia sp, { r0-r12 } @ stored wrong r0 and r1, fix later 195 196 /* get registers saved in the stub */ 197 ldr r2, [r1, #S_R0] @ r0 198 ldr r3, [r1, #S_R1] @ r1 199 ldr r4, [r1, #S_PC] @ lr_<exception> (parent PC) 200 ldr r5, [r1, #S_PSR] @ spsr_<exception> (parent CPSR) 201 202 /* fix r0 and r1 */ 203 str r2, [sp, #S_R0] 204 str r3, [sp, #S_R1] 205 206 /* store sp_svc, if we were in usr mode we'll fix this later */ 207 add r6, sp, #S_FRAME_SIZE 208 addne r6, #4 @ stack wasn't aligned 209 str r6, [sp, #S_SP] 210 211 str lr, [sp, #S_LR] @ store lr_svc, fix later for usr mode 212 str r4, [sp, #S_PC] @ store lr_<exception> 213 str r5, [sp, #S_PSR] @ store spsr_<exception> 214 215 /* set ORIG_r0 */ 216 mov r2, #-1 217 str r2, [sp, #S_OLD_R0] 218 219 /* if we were in usr mode then we need sp_usr and lr_usr instead */ 220 and r1, r5, #MODE_MASK 221 cmp r1, #USR_MODE 222 bne 1f 223 add r1, sp, #S_SP 224 stmia r1, { sp,lr }^ 225 226 /* Call the handler. r0 is the vector number, r1 := pt_regs */ 2271: mov r1, sp 228 bl do_handle_exception 229 230 /* 231 * make sure we restore sp_svc on mode change. No need to 232 * worry about lr_svc though, as that gets clobbered on 233 * exception entry anyway. 234 */ 235 str r6, [sp, #S_SP] 236 237 /* return from exception */ 238 msr spsr_cxsf, r5 239 ldmia sp, { r0-pc }^ 240 241.align 5 242vector_addrexcptn: 243 b vector_addrexcptn 244 245.section .text.ex 246.align 5 247vector_table: 248 b vector_rst 249 b vector_und 250 b vector_svc 251 b vector_pabt 252 b vector_dabt 253 b vector_addrexcptn @ should never happen 254 b vector_irq 255 b vector_fiq 256