1/* 2 * Copyright (C) 2008 Google, Inc. 3 * 4 * This software is licensed under the terms of the GNU General Public 5 * License version 2, as published by the Free Software Foundation, and 6 * may be copied, distributed, and modified under those terms. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 */ 14 15#include <linux/linkage.h> 16#include <asm/assembler.h> 17 18 .text 19 20 .global fiq_glue_end 21 22 /* fiq stack: r0-r15,cpsr,spsr of interrupted mode */ 23 24ENTRY(fiq_glue) 25 /* store pc, cpsr from previous mode */ 26 mrs r12, spsr 27 sub r11, lr, #4 28 subs r10, #1 29 bne nested_fiq 30 31 stmfd sp!, {r11-r12, lr} 32 33 /* store r8-r14 from previous mode */ 34 sub sp, sp, #(7 * 4) 35 stmia sp, {r8-r14}^ 36 nop 37 38 /* store r0-r7 from previous mode */ 39 stmfd sp!, {r0-r7} 40 41 /* setup func(data,regs) arguments */ 42 mov r0, r9 43 mov r1, sp 44 mov r3, r8 45 46 mov r7, sp 47 48 /* Get sp and lr from non-user modes */ 49 and r4, r12, #MODE_MASK 50 cmp r4, #USR_MODE 51 beq fiq_from_usr_mode 52 53 mov r7, sp 54 orr r4, r4, #(PSR_I_BIT | PSR_F_BIT) 55 msr cpsr_c, r4 56 str sp, [r7, #(4 * 13)] 57 str lr, [r7, #(4 * 14)] 58 mrs r5, spsr 59 str r5, [r7, #(4 * 17)] 60 61 cmp r4, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT) 62 /* use fiq stack if we reenter this mode */ 63 subne sp, r7, #(4 * 3) 64 65fiq_from_usr_mode: 66 msr cpsr_c, #(SVC_MODE | PSR_I_BIT | PSR_F_BIT) 67 mov r2, sp 68 sub sp, r7, #12 69 stmfd sp!, {r2, ip, lr} 70 /* call func(data,regs) */ 71 blx r3 72 ldmfd sp, {r2, ip, lr} 73 mov sp, r2 74 75 /* restore/discard saved state */ 76 cmp r4, #USR_MODE 77 beq fiq_from_usr_mode_exit 78 79 msr cpsr_c, r4 80 ldr sp, [r7, #(4 * 13)] 81 ldr lr, [r7, #(4 * 14)] 82 msr spsr_cxsf, r5 83 84fiq_from_usr_mode_exit: 85 msr cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT) 86 87 ldmfd sp!, {r0-r7} 88 add sp, sp, #(7 * 4) 89 ldmfd sp!, {r11-r12, lr} 90exit_fiq: 91 msr spsr_cxsf, r12 92 add r10, #1 93 movs pc, r11 94 95nested_fiq: 96 orr r12, r12, #(PSR_F_BIT) 97 b exit_fiq 98 99fiq_glue_end: 100 101ENTRY(fiq_glue_setup) /* func, data, sp */ 102 mrs r3, cpsr 103 msr cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT) 104 movs r8, r0 105 mov r9, r1 106 mov sp, r2 107 moveq r10, #0 108 movne r10, #1 109 msr cpsr_c, r3 110 bx lr 111 112