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