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 mov sp, \stack 54.endm 55 56exceptions_init: 57 mrc p15, 0, r2, c1, c0, 0 @ read SCTLR 58 bic r2, #CR_V @ SCTLR.V := 0 59 mcr p15, 0, r2, c1, c0, 0 @ write SCTLR 60 ldr r2, =vector_table 61 mcr p15, 0, r2, c12, c0, 0 @ write VBAR 62 63 mrs r2, cpsr 64 ldr r1, =exception_stacks 65 66 /* first frame reserved for svc mode */ 67 set_mode_stack UND_MODE, r1 68 set_mode_stack ABT_MODE, r1 69 set_mode_stack IRQ_MODE, r1 70 set_mode_stack FIQ_MODE, r1 71 72 msr cpsr_cxsf, r2 @ back to svc mode 73 mov pc, lr 74 75.text 76 77.globl halt 78halt: 791: wfi 80 b 1b 81 82/* 83 * asm_mmu_enable 84 * Inputs: 85 * (r0 - lo, r1 - hi) is the base address of the translation table 86 * Outputs: none 87 */ 88.equ PRRR, 0xeeaa4400 @ MAIR0 (from Linux kernel) 89.equ NMRR, 0xff000004 @ MAIR1 (from Linux kernel) 90.globl asm_mmu_enable 91asm_mmu_enable: 92 /* TTBCR */ 93 mrc p15, 0, r2, c2, c0, 2 94 orr r2, #(1 << 31) @ TTB_EAE 95 mcr p15, 0, r2, c2, c0, 2 96 97 /* MAIR */ 98 ldr r2, =PRRR 99 mrc p15, 0, r2, c10, c2, 0 100 ldr r2, =NMRR 101 mrc p15, 0, r2, c10, c2, 1 102 103 /* TTBR0 */ 104 mcrr p15, 0, r0, r1, c2 105 106 /* SCTLR */ 107 mrc p15, 0, r2, c1, c0, 0 108 orr r2, #CR_C 109 orr r2, #CR_I 110 orr r2, #CR_M 111 mcr p15, 0, r2, c1, c0, 0 112 113 mov pc, lr 114 115/* 116 * Vector stubs 117 * Simplified version of the Linux kernel implementation 118 * arch/arm/kernel/entry-armv.S 119 * 120 * Each mode has an S_FRAME_SIZE sized stack initialized 121 * in exceptions_init 122 */ 123.macro vector_stub, name, vec, mode, correction=0 124.align 5 125vector_\name: 126.if \correction 127 sub lr, lr, #\correction 128.endif 129 /* 130 * Save r0, r1, lr_<exception> (parent PC) 131 * and spsr_<exception> (parent CPSR) 132 */ 133 str r0, [sp, #S_R0] 134 str r1, [sp, #S_R1] 135 str lr, [sp, #S_PC] 136 mrs r0, spsr 137 str r0, [sp, #S_PSR] 138 139 /* Prepare for SVC32 mode. */ 140 mrs r0, cpsr 141 bic r0, #MODE_MASK 142 orr r0, #SVC_MODE 143 msr spsr_cxsf, r0 144 145 /* Branch to handler in SVC mode */ 146 mov r0, #\vec 147 mov r1, sp 148 ldr lr, =vector_common 149 movs pc, lr 150.endm 151 152vector_stub rst, 0, UND_MODE 153vector_stub und, 1, UND_MODE 154vector_stub pabt, 3, ABT_MODE, 4 155vector_stub dabt, 4, ABT_MODE, 8 156vector_stub irq, 6, IRQ_MODE, 4 157vector_stub fiq, 7, FIQ_MODE, 4 158 159.align 5 160vector_svc: 161 /* 162 * Save r0, r1, lr_<exception> (parent PC) 163 * and spsr_<exception> (parent CPSR) 164 */ 165 push { r1 } 166 ldr r1, =exception_stacks 167 str r0, [r1, #S_R0] 168 pop { r0 } 169 str r0, [r1, #S_R1] 170 str lr, [r1, #S_PC] 171 mrs r0, spsr 172 str r0, [r1, #S_PSR] 173 174 /* 175 * Branch to handler, still in SVC mode. 176 * r0 := 2 is the svc vector number. 177 */ 178 mov r0, #2 179 ldr lr, =vector_common 180 mov pc, lr 181 182vector_common: 183 /* make room for pt_regs */ 184 sub sp, #S_FRAME_SIZE 185 tst sp, #4 @ check stack alignment 186 subne sp, #4 187 188 /* store registers r0-r12 */ 189 stmia sp, { r0-r12 } @ stored wrong r0 and r1, fix later 190 191 /* get registers saved in the stub */ 192 ldr r2, [r1, #S_R0] @ r0 193 ldr r3, [r1, #S_R1] @ r1 194 ldr r4, [r1, #S_PC] @ lr_<exception> (parent PC) 195 ldr r5, [r1, #S_PSR] @ spsr_<exception> (parent CPSR) 196 197 /* fix r0 and r1 */ 198 str r2, [sp, #S_R0] 199 str r3, [sp, #S_R1] 200 201 /* store sp_svc, if we were in usr mode we'll fix this later */ 202 add r6, sp, #S_FRAME_SIZE 203 addne r6, #4 @ stack wasn't aligned 204 str r6, [sp, #S_SP] 205 206 str lr, [sp, #S_LR] @ store lr_svc, fix later for usr mode 207 str r4, [sp, #S_PC] @ store lr_<exception> 208 str r5, [sp, #S_PSR] @ store spsr_<exception> 209 210 /* set ORIG_r0 */ 211 mov r2, #-1 212 str r2, [sp, #S_OLD_R0] 213 214 /* if we were in usr mode then we need sp_usr and lr_usr instead */ 215 and r1, r5, #MODE_MASK 216 cmp r1, #USR_MODE 217 bne 1f 218 add r1, sp, #S_SP 219 stmia r1, { sp,lr }^ 220 221 /* Call the handler. r0 is the vector number, r1 := pt_regs */ 2221: mov r1, sp 223 bl do_handle_exception 224 225 /* 226 * make sure we restore sp_svc on mode change. No need to 227 * worry about lr_svc though, as that gets clobbered on 228 * exception entry anyway. 229 */ 230 str r6, [sp, #S_SP] 231 232 /* return from exception */ 233 msr spsr_cxsf, r5 234 ldmia sp, { r0-pc }^ 235 236.align 5 237vector_addrexcptn: 238 b vector_addrexcptn 239 240.section .text.ex 241.align 5 242vector_table: 243 b vector_rst 244 b vector_und 245 b vector_svc 246 b vector_pabt 247 b vector_dabt 248 b vector_addrexcptn @ should never happen 249 b vector_irq 250 b vector_fiq 251