1#include <linux/config.h> /* for CONFIG_ARCH_xxxx */ 2#include <linux/linkage.h> 3 4#include <asm/assembler.h> 5#include <asm/constants.h> 6#include <asm/errno.h> 7#include <asm/hardware.h> 8#include <asm/arch/irqs.h> 9#include <asm/proc-fns.h> 10 11#ifndef MODE_SVC 12#define MODE_SVC 0x13 13#endif 14 15 .macro zero_fp 16#ifdef CONFIG_FRAME_POINTER 17 mov fp, #0 18#endif 19 .endm 20 21 .text 22 23@ Bad Abort numbers 24@ ----------------- 25@ 26#define BAD_PREFETCH 0 27#define BAD_DATA 1 28#define BAD_ADDREXCPTN 2 29#define BAD_IRQ 3 30#define BAD_UNDEFINSTR 4 31 32#define PT_TRACESYS 0x00000002 33 34@ OS version number used in SWIs 35@ RISC OS is 0 36@ RISC iX is 8 37@ 38#define OS_NUMBER 9 39#define ARMSWI_OFFSET 0x000f0000 40 41@ 42@ Stack format (ensured by USER_* and SVC_*) 43@ 44#ifdef CONFIG_CPU_32 45#define S_FRAME_SIZE 72 46#define S_OLD_R0 68 47#define S_PSR 64 48#else 49#define S_FRAME_SIZE 68 50#define S_OLD_R0 64 51#define S_PSR 60 52#endif 53 54#define S_PC 60 55#define S_LR 56 56#define S_SP 52 57#define S_IP 48 58#define S_FP 44 59#define S_R10 40 60#define S_R9 36 61#define S_R8 32 62#define S_R7 28 63#define S_R6 24 64#define S_R5 20 65#define S_R4 16 66#define S_R3 12 67#define S_R2 8 68#define S_R1 4 69#define S_R0 0 70#define S_OFF 8 71 72#ifdef CONFIG_CPU_32 73 .macro set_cpsr_c, reg, mode 74#if 1 75 /* broken binutils */ 76 mov \reg, \mode 77 msr cpsr_c, \reg 78#else 79 msr cpsr_c, \mode 80#endif 81 .endm 82 83 .macro disable_irq, temp 84 set_cpsr_c \temp, #I_BIT | MODE_SVC 85 .endm 86 87 .macro enable_irq, temp 88 set_cpsr_c \temp, #MODE_SVC 89 .endm 90 91 .macro save_user_regs 92 sub sp, sp, #S_FRAME_SIZE 93 stmia sp, {r0 - r12} @ Calling r0 - r12 94 add r8, sp, #S_PC 95 stmdb r8, {sp, lr}^ @ Calling sp, lr 96 mrs r8, spsr @ called from non-FIQ mode, so ok. 97 str lr, [sp, #S_PC] @ Save calling PC 98 str r8, [sp, #S_PSR] @ Save CPSR 99 str r0, [sp, #S_OLD_R0] @ Save OLD_R0 100 .endm 101 102/* 103 * Must be called with IRQs already disabled. 104 */ 105 .macro restore_user_regs 106 ldr r1, [sp, #S_PSR] @ Get calling cpsr 107 ldr lr, [sp, #S_PC]! @ Get PC 108 msr spsr, r1 @ save in spsr_svc 109 ldmdb sp, {r0 - lr}^ @ Get calling r0 - lr 110 mov r0, r0 111 add sp, sp, #S_FRAME_SIZE - S_PC 112 movs pc, lr @ return & move spsr_svc into cpsr 113 .endm 114 115/* 116 * Must be called with IRQs already disabled. 117 */ 118 .macro fast_restore_user_regs 119 ldr r1, [sp, #S_OFF + S_PSR] @ get calling cpsr 120 ldr lr, [sp, #S_OFF + S_PC]! @ get pc 121 msr spsr, r1 @ save in spsr_svc 122 ldmdb sp, {r1 - lr}^ @ get calling r1 - lr 123 mov r0, r0 124 add sp, sp, #S_FRAME_SIZE - S_PC 125 movs pc, lr @ return & move spsr_svc into cpsr 126 .endm 127 128 .macro mask_pc, rd, rm 129 .endm 130 131 .macro get_current_task, rd 132 mov \rd, sp, lsr #13 133 mov \rd, \rd, lsl #13 134 .endm 135 136 /* 137 * Like adr, but force SVC mode (if required) 138 */ 139 .macro adrsvc, cond, reg, label 140 adr\cond \reg, \label 141 .endm 142 143 .macro alignment_trap, rbase, rtemp, sym 144#ifdef CONFIG_ALIGNMENT_TRAP 145#define OFF_CR_ALIGNMENT(x) cr_alignment - x 146 147 ldr \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)] 148 mcr p15, 0, \rtemp, c1, c0 149#endif 150 .endm 151 152#else 153 .macro save_user_regs 154 sub sp, sp, #S_FRAME_SIZE 155 str r0, [sp, #S_OLD_R0] 156 str lr, [sp, #S_PC] 157 stmia sp, {r0 - lr}^ 158 mov r0, r0 159 .endm 160 161 .macro restore_user_regs 162 ldmia sp, {r0 - lr}^ 163 mov r0, r0 164 ldr lr, [sp, #S_PC] 165 add sp, sp, #S_FRAME_SIZE 166 movs pc, lr 167 .endm 168 169 .macro fast_restore_user_regs 170 add sp, sp, #S_OFF + S_PC 171 ldmdb sp, {r1 - lr}^ 172 mov r0, r0 173 ldr lr, [sp], #S_FRAME_SIZE - S_PC 174 movs pc, lr 175 .endm 176 177 .macro mask_pc, rd, rm 178 bic \rd, \rm, #PCMASK 179 .endm 180 181 .macro disable_irq, temp 182 teqp pc, #0x08000003 183 .endm 184 185 .macro enable_irq, temp 186 teqp pc, #0x00000003 187 .endm 188 189 .macro initialise_traps_extra 190 .endm 191 192 .macro get_current_task, rd 193 mov \rd, sp, lsr #13 194 mov \rd, \rd, lsl #13 195 .endm 196 197 /* 198 * Like adr, but force SVC mode (if required) 199 */ 200 .macro adrsvc, cond, reg, label 201 adr\cond \reg, \label 202 orr\cond \reg, \reg, #0x08000003 203 .endm 204 205#endif 206 207 208/* 209 * These are the registers used in the syscall handler, and allow us to 210 * have in theory up to 7 arguments to a function - r0 to r6. 211 * 212 * r7 is reserved for the system call number for thumb mode. 213 * 214 * Note that tbl == why is intentional. 215 * 216 * We must set at least "tsk" and "why" when calling ret_with_reschedule. 217 */ 218scno .req r7 @ syscall number 219tbl .req r8 @ syscall table pointer 220why .req r8 @ Linux syscall (!= 0) 221tsk .req r9 @ current task 222 223/* 224 * Get the system call number. 225 */ 226 .macro get_scno 227#ifdef CONFIG_ARM_THUMB 228 tst r8, #T_BIT @ this is SPSR from save_user_regs 229 addne scno, r7, #OS_NUMBER << 20 @ put OS number in 230 ldreq scno, [lr, #-4] 231 232#else 233 mask_pc lr, lr 234 ldr scno, [lr, #-4] @ get SWI instruction 235#endif 236 .endm 237 238