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, =stacktop 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 stack initialized 125 * in exceptions_init 126 */ 127.macro vector_stub, name, vec, mode, correction=0 128.align 5 129vector_\name: 130.if \correction 131 sub lr, lr, #\correction 132.endif 133 /* 134 * Save r0, r1, lr_<exception> (parent PC) 135 * and spsr_<exception> (parent CPSR) 136 */ 137 str r0, [sp, #S_R0] 138 str r1, [sp, #S_R1] 139 str lr, [sp, #S_PC] 140 mrs r0, spsr 141 str r0, [sp, #S_PSR] 142 143 /* Prepare for SVC32 mode. */ 144 mrs r0, cpsr 145 bic r0, #MODE_MASK 146 orr r0, #SVC_MODE 147 msr spsr_cxsf, r0 148 149 /* Branch to handler in SVC mode */ 150 mov r0, #\vec 151 mov r1, sp 152 ldr lr, =vector_common 153 movs pc, lr 154.endm 155 156vector_stub rst, 0, UND_MODE 157vector_stub und, 1, UND_MODE 158vector_stub pabt, 3, ABT_MODE, 4 159vector_stub dabt, 4, ABT_MODE, 8 160vector_stub irq, 6, IRQ_MODE, 4 161vector_stub fiq, 7, FIQ_MODE, 4 162 163.align 5 164vector_svc: 165 /* 166 * Save r0, r1, lr_<exception> (parent PC) 167 * and spsr_<exception> (parent CPSR) 168 */ 169 push { r1 } 170 ldr r1, =exception_stacks 171 str r0, [r1, #S_R0] 172 pop { r0 } 173 str r0, [r1, #S_R1] 174 str lr, [r1, #S_PC] 175 mrs r0, spsr 176 str r0, [r1, #S_PSR] 177 178 /* 179 * Branch to handler, still in SVC mode. 180 * r0 := 2 is the svc vector number. 181 */ 182 mov r0, #2 183 ldr lr, =vector_common 184 mov pc, lr 185 186vector_common: 187 /* make room for pt_regs */ 188 sub sp, #S_FRAME_SIZE 189 tst sp, #4 @ check stack alignment 190 subne sp, #4 191 192 /* store registers r0-r12 */ 193 stmia sp, { r0-r12 } @ stored wrong r0 and r1, fix later 194 195 /* get registers saved in the stub */ 196 ldr r2, [r1, #S_R0] @ r0 197 ldr r3, [r1, #S_R1] @ r1 198 ldr r4, [r1, #S_PC] @ lr_<exception> (parent PC) 199 ldr r5, [r1, #S_PSR] @ spsr_<exception> (parent CPSR) 200 201 /* fix r0 and r1 */ 202 str r2, [sp, #S_R0] 203 str r3, [sp, #S_R1] 204 205 /* store sp_svc, if we were in usr mode we'll fix this later */ 206 add r6, sp, #S_FRAME_SIZE 207 addne r6, #4 @ stack wasn't aligned 208 str r6, [sp, #S_SP] 209 210 str lr, [sp, #S_LR] @ store lr_svc, fix later for usr mode 211 str r4, [sp, #S_PC] @ store lr_<exception> 212 str r5, [sp, #S_PSR] @ store spsr_<exception> 213 214 /* set ORIG_r0 */ 215 mov r2, #-1 216 str r2, [sp, #S_OLD_R0] 217 218 /* if we were in usr mode then we need sp_usr and lr_usr instead */ 219 and r1, r5, #MODE_MASK 220 cmp r1, #USR_MODE 221 bne 1f 222 add r1, sp, #S_SP 223 stmia r1, { sp,lr }^ 224 225 /* Call the handler. r0 is the vector number, r1 := pt_regs */ 2261: mov r1, sp 227 bl do_handle_exception 228 229 /* 230 * make sure we restore sp_svc on mode change. No need to 231 * worry about lr_svc though, as that gets clobbered on 232 * exception entry anyway. 233 */ 234 str r6, [sp, #S_SP] 235 236 /* return from exception */ 237 msr spsr_cxsf, r5 238 ldmia sp, { r0-pc }^ 239 240.align 5 241vector_addrexcptn: 242 b vector_addrexcptn 243 244.section .text.ex 245.align 5 246vector_table: 247 b vector_rst 248 b vector_und 249 b vector_svc 250 b vector_pabt 251 b vector_dabt 252 b vector_addrexcptn @ should never happen 253 b vector_irq 254 b vector_fiq 255