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/sysreg.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 ldr r2, =__environ 66 bl main 67 bl exit 68 b halt 69 70 71.macro set_mode_stack mode, stack 72 add \stack, #S_FRAME_SIZE 73 msr cpsr_c, #(\mode | PSR_I_BIT | PSR_F_BIT) 74 isb 75 mov sp, \stack 76.endm 77 78exceptions_init: 79 mrc p15, 0, r2, c1, c0, 0 @ read SCTLR 80 bic r2, #CR_V @ SCTLR.V := 0 81 mcr p15, 0, r2, c1, c0, 0 @ write SCTLR 82 ldr r2, =vector_table 83 mcr p15, 0, r2, c12, c0, 0 @ write VBAR 84 85 mrs r2, cpsr 86 87 /* first frame reserved for svc mode */ 88 set_mode_stack UND_MODE, r0 89 set_mode_stack ABT_MODE, r0 90 set_mode_stack IRQ_MODE, r0 91 set_mode_stack FIQ_MODE, r0 92 93 msr cpsr_cxsf, r2 @ back to svc mode 94 isb 95 mov pc, lr 96 97.text 98 99.global secondary_entry 100secondary_entry: 101 /* enable the MMU */ 102 mov r1, #0 103 ldr r0, =mmu_idmap 104 ldr r0, [r0] 105 bl asm_mmu_enable 106 107 /* 108 * Set the stack, and set up vector table 109 * and exception stacks. Exception stacks 110 * space starts at stack top and grows up. 111 */ 112 ldr r1, =secondary_data 113 ldr r0, [r1] 114 mov sp, r0 115 bl exceptions_init 116 117 /* finish init in C code */ 118 bl secondary_cinit 119 120 /* r0 is now the entry function, run it */ 121 blx r0 122 b do_idle 123 124.globl halt 125halt: 1261: wfi 127 b 1b 128 129/* 130 * asm_mmu_enable 131 * Inputs: 132 * (r0 - lo, r1 - hi) is the base address of the translation table 133 * Outputs: none 134 */ 135.equ PRRR, 0xeeaa4400 @ MAIR0 (from Linux kernel) 136.equ NMRR, 0xff000004 @ MAIR1 (from Linux kernel) 137.globl asm_mmu_enable 138asm_mmu_enable: 139 /* TTBCR */ 140 mrc p15, 0, r2, c2, c0, 2 141 orr r2, #(1 << 31) @ TTB_EAE 142 mcr p15, 0, r2, c2, c0, 2 143 144 /* MAIR */ 145 ldr r2, =PRRR 146 mcr p15, 0, r2, c10, c2, 0 147 ldr r2, =NMRR 148 mcr p15, 0, r2, c10, c2, 1 149 150 /* TTBR0 */ 151 mcrr p15, 0, r0, r1, c2 152 isb 153 154 /* SCTLR */ 155 mrc p15, 0, r2, c1, c0, 0 156 orr r2, #CR_C 157 orr r2, #CR_I 158 orr r2, #CR_M 159 mcr p15, 0, r2, c1, c0, 0 160 isb 161 162 mov pc, lr 163 164.globl asm_mmu_disable 165asm_mmu_disable: 166 /* SCTLR */ 167 mrc p15, 0, r0, c1, c0, 0 168 bic r0, #CR_M 169 mcr p15, 0, r0, c1, c0, 0 170 isb 171 mov pc, lr 172 173/* 174 * Vector stubs 175 * Simplified version of the Linux kernel implementation 176 * arch/arm/kernel/entry-armv.S 177 * 178 * Each mode has an S_FRAME_SIZE sized memory region, 179 * and the mode's stack pointer has been initialized 180 * to the base of that region in exceptions_init. 181 */ 182.macro vector_stub, name, vec, mode, correction=0 183.align 5 184vector_\name: 185.if \correction 186 sub lr, lr, #\correction 187.endif 188 /* 189 * Save r0, r1, lr_<exception> (parent PC) 190 * and spsr_<exception> (parent CPSR) 191 */ 192 str r0, [sp, #S_R0] 193 str r1, [sp, #S_R1] 194 str lr, [sp, #S_PC] 195 mrs r0, spsr 196 str r0, [sp, #S_PSR] 197 198 /* Prepare for SVC32 mode. */ 199 mrs r0, cpsr 200 bic r0, #MODE_MASK 201 orr r0, #SVC_MODE 202 msr spsr_cxsf, r0 203 204 /* Branch to handler in SVC mode */ 205 mov r0, #\vec 206 mov r1, sp 207 ldr lr, =vector_common 208 movs pc, lr 209.endm 210 211vector_stub rst, 0, UND_MODE 212vector_stub und, 1, UND_MODE 213vector_stub pabt, 3, ABT_MODE, 4 214vector_stub dabt, 4, ABT_MODE, 8 215vector_stub irq, 6, IRQ_MODE, 4 216vector_stub fiq, 7, FIQ_MODE, 4 217 218.align 5 219vector_svc: 220 /* 221 * Save r0, r1, lr_<exception> (parent PC) 222 * and spsr_<exception> (parent CPSR) 223 */ 224 push { r1 } 225 lsr r1, sp, #THREAD_SHIFT 226 lsl r1, #THREAD_SHIFT 227 add r1, #THREAD_START_SP 228 str r0, [r1, #S_R0] 229 pop { r0 } 230 str r0, [r1, #S_R1] 231 str lr, [r1, #S_PC] 232 mrs r0, spsr 233 str r0, [r1, #S_PSR] 234 235 /* 236 * Branch to handler, still in SVC mode. 237 * r0 := 2 is the svc vector number. 238 */ 239 mov r0, #2 240 ldr lr, =vector_common 241 mov pc, lr 242 243vector_common: 244 /* make room for pt_regs */ 245 sub sp, #S_FRAME_SIZE 246 tst sp, #4 @ check stack alignment 247 subne sp, #4 248 249 /* store registers r0-r12 */ 250 stmia sp, { r0-r12 } @ stored wrong r0 and r1, fix later 251 252 /* get registers saved in the stub */ 253 ldr r2, [r1, #S_R0] @ r0 254 ldr r3, [r1, #S_R1] @ r1 255 ldr r4, [r1, #S_PC] @ lr_<exception> (parent PC) 256 ldr r5, [r1, #S_PSR] @ spsr_<exception> (parent CPSR) 257 258 /* fix r0 and r1 */ 259 str r2, [sp, #S_R0] 260 str r3, [sp, #S_R1] 261 262 /* store sp_svc, if we were in usr mode we'll fix this later */ 263 add r6, sp, #S_FRAME_SIZE 264 addne r6, #4 @ stack wasn't aligned 265 str r6, [sp, #S_SP] 266 267 str lr, [sp, #S_LR] @ store lr_svc, fix later for usr mode 268 str r4, [sp, #S_PC] @ store lr_<exception> 269 str r5, [sp, #S_PSR] @ store spsr_<exception> 270 271 /* set ORIG_r0 */ 272 mov r2, #-1 273 str r2, [sp, #S_OLD_R0] 274 275 /* if we were in usr mode then we need sp_usr and lr_usr instead */ 276 and r1, r5, #MODE_MASK 277 cmp r1, #USR_MODE 278 bne 1f 279 add r1, sp, #S_SP 280 stmia r1, { sp,lr }^ 281 282 /* Call the handler. r0 is the vector number, r1 := pt_regs */ 2831: mov r1, sp 284 bl do_handle_exception 285 286 /* 287 * make sure we restore sp_svc on mode change. No need to 288 * worry about lr_svc though, as that gets clobbered on 289 * exception entry anyway. 290 */ 291 str r6, [sp, #S_SP] 292 293 /* return from exception */ 294 msr spsr_cxsf, r5 295 ldmia sp, { r0-pc }^ 296 297.align 5 298vector_addrexcptn: 299 b vector_addrexcptn 300 301.section .text.ex 302.align 5 303vector_table: 304 b vector_rst 305 b vector_und 306 b vector_svc 307 b vector_pabt 308 b vector_dabt 309 b vector_addrexcptn @ should never happen 310 b vector_irq 311 b vector_fiq 312