1#include <linux/init.h> 2#include <linux/linkage.h> 3 4#include <asm/assembler.h> 5#include <asm/asm-offsets.h> 6#include <asm/errno.h> 7#include <asm/thread_info.h> 8 9@ Bad Abort numbers 10@ ----------------- 11@ 12#define BAD_PREFETCH 0 13#define BAD_DATA 1 14#define BAD_ADDREXCPTN 2 15#define BAD_IRQ 3 16#define BAD_UNDEFINSTR 4 17 18@ 19@ Most of the stack format comes from struct pt_regs, but with 20@ the addition of 8 bytes for storing syscall args 5 and 6. 21@ This _must_ remain a multiple of 8 for EABI. 22@ 23#define S_OFF 8 24 25/* 26 * The SWI code relies on the fact that R0 is at the bottom of the stack 27 * (due to slow/fast restore user regs). 28 */ 29#if S_R0 != 0 30#error "Please fix" 31#endif 32 33 .macro zero_fp 34#ifdef CONFIG_FRAME_POINTER 35 mov fp, #0 36#endif 37 .endm 38 39 .macro alignment_trap, rtemp 40#ifdef CONFIG_ALIGNMENT_TRAP 41 ldr \rtemp, .LCcralign 42 ldr \rtemp, [\rtemp] 43 mcr p15, 0, \rtemp, c1, c0 44#endif 45 .endm 46 47 @ 48 @ Store/load the USER SP and LR registers by switching to the SYS 49 @ mode. Useful in Thumb-2 mode where "stm/ldm rd, {sp, lr}^" is not 50 @ available. Should only be called from SVC mode 51 @ 52 .macro store_user_sp_lr, rd, rtemp, offset = 0 53 mrs \rtemp, cpsr 54 eor \rtemp, \rtemp, #(SVC_MODE ^ SYSTEM_MODE) 55 msr cpsr_c, \rtemp @ switch to the SYS mode 56 57 str sp, [\rd, #\offset] @ save sp_usr 58 str lr, [\rd, #\offset + 4] @ save lr_usr 59 60 eor \rtemp, \rtemp, #(SVC_MODE ^ SYSTEM_MODE) 61 msr cpsr_c, \rtemp @ switch back to the SVC mode 62 .endm 63 64 .macro load_user_sp_lr, rd, rtemp, offset = 0 65 mrs \rtemp, cpsr 66 eor \rtemp, \rtemp, #(SVC_MODE ^ SYSTEM_MODE) 67 msr cpsr_c, \rtemp @ switch to the SYS mode 68 69 ldr sp, [\rd, #\offset] @ load sp_usr 70 ldr lr, [\rd, #\offset + 4] @ load lr_usr 71 72 eor \rtemp, \rtemp, #(SVC_MODE ^ SYSTEM_MODE) 73 msr cpsr_c, \rtemp @ switch back to the SVC mode 74 .endm 75 76#ifndef CONFIG_THUMB2_KERNEL 77 .macro svc_exit, rpsr 78 msr spsr_cxsf, \rpsr 79 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr 80 .endm 81 82 .macro restore_user_regs, fast = 0, offset = 0 83 ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr 84 ldr lr, [sp, #\offset + S_PC]! @ get pc 85 msr spsr_cxsf, r1 @ save in spsr_svc 86 .if \fast 87 ldmdb sp, {r1 - lr}^ @ get calling r1 - lr 88 .else 89 ldmdb sp, {r0 - lr}^ @ get calling r0 - lr 90 .endif 91 add sp, sp, #S_FRAME_SIZE - S_PC 92 movs pc, lr @ return & move spsr_svc into cpsr 93 .endm 94 95 .macro get_thread_info, rd 96 mov \rd, sp, lsr #13 97 mov \rd, \rd, lsl #13 98 .endm 99#else /* CONFIG_THUMB2_KERNEL */ 100 .macro svc_exit, rpsr 101 ldr r0, [sp, #S_SP] @ top of the stack 102 ldr r1, [sp, #S_PC] @ return address 103 tst r0, #4 @ orig stack 8-byte aligned? 104 stmdb r0, {r1, \rpsr} @ rfe context 105 ldmia sp, {r0 - r12} 106 ldr lr, [sp, #S_LR] 107 addeq sp, sp, #S_FRAME_SIZE - 8 @ aligned 108 addne sp, sp, #S_FRAME_SIZE - 4 @ not aligned 109 rfeia sp! 110 .endm 111 112 .macro restore_user_regs, fast = 0, offset = 0 113 mov r2, sp 114 load_user_sp_lr r2, r3, \offset + S_SP @ calling sp, lr 115 ldr r1, [sp, #\offset + S_PSR] @ get calling cpsr 116 ldr lr, [sp, #\offset + S_PC] @ get pc 117 add sp, sp, #\offset + S_SP 118 msr spsr_cxsf, r1 @ save in spsr_svc 119 .if \fast 120 ldmdb sp, {r1 - r12} @ get calling r1 - r12 121 .else 122 ldmdb sp, {r0 - r12} @ get calling r0 - r12 123 .endif 124 add sp, sp, #S_FRAME_SIZE - S_SP 125 movs pc, lr @ return & move spsr_svc into cpsr 126 .endm 127 128 .macro get_thread_info, rd 129 mov \rd, sp 130 lsr \rd, \rd, #13 131 mov \rd, \rd, lsl #13 132 .endm 133#endif /* !CONFIG_THUMB2_KERNEL */ 134 135/* 136 * These are the registers used in the syscall handler, and allow us to 137 * have in theory up to 7 arguments to a function - r0 to r6. 138 * 139 * r7 is reserved for the system call number for thumb mode. 140 * 141 * Note that tbl == why is intentional. 142 * 143 * We must set at least "tsk" and "why" when calling ret_with_reschedule. 144 */ 145scno .req r7 @ syscall number 146tbl .req r8 @ syscall table pointer 147why .req r8 @ Linux syscall (!= 0) 148tsk .req r9 @ current thread_info 149