Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: entry: data abort: tail-call the main data abort handler

Tail-call the main C data abort handler code from the per-CPU helper
code. Update the comments in the code wrt the new calling and return
register state.

Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>

+73 -99
+4 -10
arch/arm/kernel/entry-armv.S
··· 60 60 @ 61 61 @ Call the processor-specific abort handler: 62 62 @ 63 + @ r2 - pt_regs 63 64 @ r4 - aborted context pc 64 65 @ r5 - aborted context psr 65 66 @ ··· 187 186 .align 5 188 187 __dabt_svc: 189 188 svc_entry 190 - dabt_helper 191 - 192 - @ 193 - @ call main handler 194 - @ 195 189 mov r2, sp 196 - bl do_DataAbort 190 + dabt_helper 197 191 198 192 @ 199 193 @ IRQs off again before pulling preserved data off the stack ··· 403 407 __dabt_usr: 404 408 usr_entry 405 409 kuser_cmpxchg_check 406 - dabt_helper 407 - 408 410 mov r2, sp 409 - adr lr, BSYM(ret_from_exception) 410 - b do_DataAbort 411 + dabt_helper 412 + b ret_from_exception 411 413 UNWIND(.fnend ) 412 414 ENDPROC(__dabt_usr) 413 415
+4 -7
arch/arm/mm/abort-ev4.S
··· 3 3 /* 4 4 * Function: v4_early_abort 5 5 * 6 - * Params : r4 = aborted context pc 6 + * Params : r2 = pt_regs 7 + * : r4 = aborted context pc 7 8 * : r5 = aborted context psr 8 9 * 9 - * Returns : r0 = address of abort 10 - * : r1 = FSR, bit 11 = write 11 - * : r2-r8 = corrupted 12 - * : r9 = preserved 13 - * : sp = pointer to registers 10 + * Returns : r4 - r11, r13 preserved 14 11 * 15 12 * Purpose : obtain information about current aborted instruction. 16 13 * Note: we read user space. This means we might cause a data ··· 22 25 bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR 23 26 tst r3, #1 << 20 @ L = 1 -> write? 24 27 orreq r1, r1, #1 << 11 @ yes. 25 - mov pc, lr 28 + b do_DataAbort
+4 -7
arch/arm/mm/abort-ev4t.S
··· 4 4 /* 5 5 * Function: v4t_early_abort 6 6 * 7 - * Params : r4 = aborted context pc 7 + * Params : r2 = pt_regs 8 + * : r4 = aborted context pc 8 9 * : r5 = aborted context psr 9 10 * 10 - * Returns : r0 = address of abort 11 - * : r1 = FSR, bit 11 = write 12 - * : r2-r8 = corrupted 13 - * : r9 = preserved 14 - * : sp = pointer to registers 11 + * Returns : r4 - r11, r13 preserved 15 12 * 16 13 * Purpose : obtain information about current aborted instruction. 17 14 * Note: we read user space. This means we might cause a data ··· 24 27 bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR 25 28 tst r3, #1 << 20 @ check write 26 29 orreq r1, r1, #1 << 11 27 - mov pc, lr 30 + b do_DataAbort
+4 -7
arch/arm/mm/abort-ev5t.S
··· 4 4 /* 5 5 * Function: v5t_early_abort 6 6 * 7 - * Params : r4 = aborted context pc 7 + * Params : r2 = pt_regs 8 + * : r4 = aborted context pc 8 9 * : r5 = aborted context psr 9 10 * 10 - * Returns : r0 = address of abort 11 - * : r1 = FSR, bit 11 = write 12 - * : r2-r8 = corrupted 13 - * : r9 = preserved 14 - * : sp = pointer to registers 11 + * Returns : r4 - r11, r13 preserved 15 12 * 16 13 * Purpose : obtain information about current aborted instruction. 17 14 * Note: we read user space. This means we might cause a data ··· 25 28 do_ldrd_abort tmp=ip, insn=r3 26 29 tst r3, #1 << 20 @ check write 27 30 orreq r1, r1, #1 << 11 28 - mov pc, lr 31 + b do_DataAbort
+5 -8
arch/arm/mm/abort-ev5tj.S
··· 4 4 /* 5 5 * Function: v5tj_early_abort 6 6 * 7 - * Params : r4 = aborted context pc 7 + * Params : r2 = pt_regs 8 + * : r4 = aborted context pc 8 9 * : r5 = aborted context psr 9 10 * 10 - * Returns : r0 = address of abort 11 - * : r1 = FSR, bit 11 = write 12 - * : r2-r8 = corrupted 13 - * : r9 = preserved 14 - * : sp = pointer to registers 11 + * Returns : r4 - r11, r13 preserved 15 12 * 16 13 * Purpose : obtain information about current aborted instruction. 17 14 * Note: we read user space. This means we might cause a data ··· 21 24 mrc p15, 0, r0, c6, c0, 0 @ get FAR 22 25 bic r1, r1, #1 << 11 | 1 << 10 @ clear bits 11 and 10 of FSR 23 26 tst r5, #PSR_J_BIT @ Java? 24 - movne pc, lr 27 + bne do_DataAbort 25 28 do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3 26 29 ldreq r3, [r4] @ read aborted ARM instruction 27 30 do_ldrd_abort tmp=ip, insn=r3 28 31 tst r3, #1 << 20 @ L = 0 -> write 29 32 orreq r1, r1, #1 << 11 @ yes. 30 - mov pc, lr 33 + b do_DataAbort
+5 -8
arch/arm/mm/abort-ev6.S
··· 4 4 /* 5 5 * Function: v6_early_abort 6 6 * 7 - * Params : r4 = aborted context pc 7 + * Params : r2 = pt_regs 8 + * : r4 = aborted context pc 8 9 * : r5 = aborted context psr 9 10 * 10 - * Returns : r0 = address of abort 11 - * : r1 = FSR, bit 11 = write 12 - * : r2-r8 = corrupted 13 - * : r9 = preserved 14 - * : sp = pointer to registers 11 + * Returns : r4 - r11, r13 preserved 15 12 * 16 13 * Purpose : obtain information about current aborted instruction. 17 14 * Note: we read user space. This means we might cause a data ··· 31 34 */ 32 35 bic r1, r1, #1 << 11 @ clear bit 11 of FSR 33 36 tst r5, #PSR_J_BIT @ Java? 34 - movne pc, lr 37 + bne do_DataAbort 35 38 do_thumb_abort fsr=r1, pc=r4, psr=r5, tmp=r3 36 39 ldreq r3, [r4] @ read aborted ARM instruction 37 40 #ifdef CONFIG_CPU_ENDIAN_BE8 ··· 40 43 do_ldrd_abort tmp=ip, insn=r3 41 44 tst r3, #1 << 20 @ L = 0 -> write 42 45 orreq r1, r1, #1 << 11 @ yes. 43 - mov pc, lr 46 + b do_DataAbort
+6 -9
arch/arm/mm/abort-ev7.S
··· 3 3 /* 4 4 * Function: v7_early_abort 5 5 * 6 - * Params : r4 = aborted context pc 6 + * Params : r2 = pt_regs 7 + * : r4 = aborted context pc 7 8 * : r5 = aborted context psr 8 9 * 9 - * Returns : r0 = address of abort 10 - * : r1 = FSR, bit 11 = write 11 - * : r2-r8 = corrupted 12 - * : r9 = preserved 13 - * : sp = pointer to registers 10 + * Returns : r4 - r11, r13 preserved 14 11 * 15 12 * Purpose : obtain information about current aborted instruction. 16 13 */ ··· 34 37 ldr r3, =0x40d @ On permission fault 35 38 and r3, r1, r3 36 39 cmp r3, #0x0d 37 - movne pc, lr 40 + bne do_DataAbort 38 41 39 42 mcr p15, 0, r0, c7, c8, 0 @ Retranslate FAR 40 43 isb 41 44 mrc p15, 0, ip, c7, c4, 0 @ Read the PAR 42 45 and r3, ip, #0x7b @ On translation fault 43 46 cmp r3, #0x0b 44 - movne pc, lr 47 + bne do_DataAbort 45 48 bic r1, r1, #0xf @ Fix up FSR FS[5:0] 46 49 and ip, ip, #0x7e 47 50 orr r1, r1, ip, LSR #1 48 51 #endif 49 52 50 - mov pc, lr 53 + b do_DataAbort 51 54 ENDPROC(v7_early_abort)
+21 -22
arch/arm/mm/abort-lv4t.S
··· 3 3 /* 4 4 * Function: v4t_late_abort 5 5 * 6 - * Params : r4 = aborted context pc 6 + * Params : r2 = pt_regs 7 + * : r4 = aborted context pc 7 8 * : r5 = aborted context psr 8 9 * 9 10 * Returns : r0 = address of abort ··· 48 47 /* 9 */ b .data_arm_ldmstm @ ldm*b rn, <rlist> 49 48 /* a */ b .data_unknown 50 49 /* b */ b .data_unknown 51 - /* c */ mov pc, lr @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m 52 - /* d */ mov pc, lr @ ldc rd, [rn, #m] 50 + /* c */ b do_DataAbort @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m 51 + /* d */ b do_DataAbort @ ldc rd, [rn, #m] 53 52 /* e */ b .data_unknown 54 53 /* f */ 55 54 .data_unknown: @ Part of jumptable 56 55 mov r0, r4 57 56 mov r1, r8 58 - mov r2, sp 59 - bl baddataabort 60 - b ret_from_exception 57 + b baddataabort 61 58 62 59 .data_arm_ldmstm: 63 60 tst r8, #1 << 21 @ check writeback bit 64 - moveq pc, lr @ no writeback -> no fixup 61 + beq do_DataAbort @ no writeback -> no fixup 65 62 mov r7, #0x11 66 63 orr r7, r7, #0x1100 67 64 and r6, r8, r7 ··· 78 79 subne r7, r7, r6, lsl #2 @ Undo increment 79 80 addeq r7, r7, r6, lsl #2 @ Undo decrement 80 81 str r7, [sp, r5, lsr #14] @ Put register 'Rn' 81 - mov pc, lr 82 + b do_DataAbort 82 83 83 84 .data_arm_lateldrhpre: 84 85 tst r8, #1 << 21 @ Check writeback bit 85 - moveq pc, lr @ No writeback -> no fixup 86 + beq do_DataAbort @ No writeback -> no fixup 86 87 .data_arm_lateldrhpost: 87 88 and r5, r8, #0x00f @ get Rm / low nibble of immediate value 88 89 tst r8, #1 << 22 @ if (immediate offset) ··· 96 97 subne r7, r7, r6 @ Undo incrmenet 97 98 addeq r7, r7, r6 @ Undo decrement 98 99 str r7, [sp, r5, lsr #14] @ Put register 'Rn' 99 - mov pc, lr 100 + b do_DataAbort 100 101 101 102 .data_arm_lateldrpreconst: 102 103 tst r8, #1 << 21 @ check writeback bit 103 - moveq pc, lr @ no writeback -> no fixup 104 + beq do_DataAbort @ no writeback -> no fixup 104 105 .data_arm_lateldrpostconst: 105 106 movs r9, r8, lsl #20 @ Get offset 106 - moveq pc, lr @ zero -> no fixup 107 + beq do_DataAbort @ zero -> no fixup 107 108 and r5, r8, #15 << 16 @ Extract 'n' from instruction 108 109 ldr r7, [sp, r5, lsr #14] @ Get register 'Rn' 109 110 tst r8, #1 << 23 @ Check U bit 110 111 subne r7, r7, r9, lsr #20 @ Undo increment 111 112 addeq r7, r7, r9, lsr #20 @ Undo decrement 112 113 str r7, [sp, r5, lsr #14] @ Put register 'Rn' 113 - mov pc, lr 114 + b do_DataAbort 114 115 115 116 .data_arm_lateldrprereg: 116 117 tst r8, #1 << 21 @ check writeback bit 117 - moveq pc, lr @ no writeback -> no fixup 118 + beq do_DataAbort @ no writeback -> no fixup 118 119 .data_arm_lateldrpostreg: 119 120 and r7, r8, #15 @ Extract 'm' from instruction 120 121 ldr r6, [sp, r7, lsl #2] @ Get register 'Rm' ··· 171 172 /* 3 */ b .data_unknown 172 173 /* 4 */ b .data_unknown 173 174 /* 5 */ b .data_thumb_reg 174 - /* 6 */ mov pc, lr 175 - /* 7 */ mov pc, lr 176 - /* 8 */ mov pc, lr 177 - /* 9 */ mov pc, lr 175 + /* 6 */ b do_DataAbort 176 + /* 7 */ b do_DataAbort 177 + /* 8 */ b do_DataAbort 178 + /* 9 */ b do_DataAbort 178 179 /* A */ b .data_unknown 179 180 /* B */ b .data_thumb_pushpop 180 181 /* C */ b .data_thumb_ldmstm ··· 184 185 185 186 .data_thumb_reg: 186 187 tst r8, #1 << 9 187 - moveq pc, lr 188 + beq do_DataAbort 188 189 tst r8, #1 << 10 @ If 'S' (signed) bit is set 189 190 movne r1, #0 @ it must be a load instr 190 - mov pc, lr 191 + b do_DataAbort 191 192 192 193 .data_thumb_pushpop: 193 194 tst r8, #1 << 10 ··· 206 207 addeq r7, r7, r6, lsl #2 @ increment SP if PUSH 207 208 subne r7, r7, r6, lsl #2 @ decrement SP if POP 208 209 str r7, [sp, #13 << 2] 209 - mov pc, lr 210 + b do_DataAbort 210 211 211 212 .data_thumb_ldmstm: 212 213 and r6, r8, #0x55 @ hweight8(r8) ··· 221 222 and r6, r6, #15 @ number of regs to transfer 222 223 sub r7, r7, r6, lsl #2 @ always decrement 223 224 str r7, [sp, r5, lsr #6] 224 - mov pc, lr 225 + b do_DataAbort
+2 -2
arch/arm/mm/abort-macro.S
··· 18 18 orreq \tmp, \tmp, #1 << 11 @ Set L-bit if yes 19 19 tst \tmp, #1 << 11 @ L = 0 -> write 20 20 orreq \psr, \psr, #1 << 11 @ yes. 21 - mov pc, lr 21 + b do_DataAbort 22 22 not_thumb: 23 23 .endm 24 24 ··· 34 34 bne not_ldrd 35 35 and \tmp, \insn, #0x000000f0 @ [7:4] == 1101 36 36 cmp \tmp, #0x000000d0 37 - moveq pc, lr 37 + beq do_DataAbort 38 38 not_ldrd: 39 39 .endm 40 40
+4 -4
arch/arm/mm/abort-nommu.S
··· 3 3 /* 4 4 * Function: nommu_early_abort 5 5 * 6 - * Params : r4 = aborted context pc 6 + * Params : r2 = pt_regs 7 + * : r4 = aborted context pc 7 8 * : r5 = aborted context psr 8 9 * 9 - * Returns : r0 = 0 (abort address) 10 - * : r1 = 0 (FSR) 10 + * Returns : r4 - r11, r13 preserved 11 11 * 12 12 * Note: There is no FSR/FAR on !CPU_CP15_MMU cores. 13 13 * Just fill zero into the registers. ··· 16 16 ENTRY(nommu_early_abort) 17 17 mov r0, #0 @ clear r0, r1 (no FSR/FAR) 18 18 mov r1, #0 19 - mov pc, lr 19 + b do_DataAbort 20 20 ENDPROC(nommu_early_abort)
+14 -15
arch/arm/mm/proc-arm6_7.S
··· 29 29 /* 30 30 * Function: arm6_7_data_abort () 31 31 * 32 - * Params : r4 = aborted context pc 32 + * Params : r2 = pt_regs 33 + * : r4 = aborted context pc 33 34 * : r5 = aborted context psr 34 35 * 35 36 * Purpose : obtain information about current aborted instruction ··· 50 49 nop 51 50 52 51 /* 0 */ b .data_unknown 53 - /* 1 */ mov pc, lr @ swp 52 + /* 1 */ b do_DataAbort @ swp 54 53 /* 2 */ b .data_unknown 55 54 /* 3 */ b .data_unknown 56 55 /* 4 */ b .data_arm_lateldrpostconst @ ldr rd, [rn], #m ··· 61 60 /* 9 */ b .data_arm_ldmstm @ ldm*b rn, <rlist> 62 61 /* a */ b .data_unknown 63 62 /* b */ b .data_unknown 64 - /* c */ mov pc, lr @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m 65 - /* d */ mov pc, lr @ ldc rd, [rn, #m] 63 + /* c */ b do_DataAbort @ ldc rd, [rn], #m @ Same as ldr rd, [rn], #m 64 + /* d */ b do_DataAbort @ ldc rd, [rn, #m] 66 65 /* e */ b .data_unknown 67 66 /* f */ 68 67 .data_unknown: @ Part of jumptable 69 68 mov r0, r4 70 69 mov r1, r8 71 - mov r2, sp 72 - bl baddataabort 73 - b ret_from_exception 70 + b baddataabort 74 71 75 72 ENTRY(cpu_arm6_data_abort) 76 73 mrc p15, 0, r1, c5, c0, 0 @ get FSR ··· 78 79 orreq r1, r1, #1 << 11 @ yes. 79 80 and r7, r8, #14 << 24 80 81 teq r7, #8 << 24 @ was it ldm/stm 81 - movne pc, lr 82 + bne do_DataAbort 82 83 83 84 .data_arm_ldmstm: 84 85 tst r8, #1 << 21 @ check writeback bit 85 - moveq pc, lr @ no writeback -> no fixup 86 + beq do_DataAbort @ no writeback -> no fixup 86 87 mov r7, #0x11 87 88 orr r7, r7, #0x1100 88 89 and r6, r8, r7 ··· 101 102 subne r7, r7, r6, lsl #2 @ Undo increment 102 103 addeq r7, r7, r6, lsl #2 @ Undo decrement 103 104 str r7, [sp, r5, lsr #14] @ Put register 'Rn' 104 - mov pc, lr 105 + b do_DataAbort 105 106 106 107 .data_arm_apply_r6_and_rn: 107 108 and r5, r8, #15 << 16 @ Extract 'n' from instruction ··· 110 111 subne r7, r7, r6 @ Undo incrmenet 111 112 addeq r7, r7, r6 @ Undo decrement 112 113 str r7, [sp, r5, lsr #14] @ Put register 'Rn' 113 - mov pc, lr 114 + b do_DataAbort 114 115 115 116 .data_arm_lateldrpreconst: 116 117 tst r8, #1 << 21 @ check writeback bit 117 - moveq pc, lr @ no writeback -> no fixup 118 + beq do_DataAbort @ no writeback -> no fixup 118 119 .data_arm_lateldrpostconst: 119 120 movs r9, r8, lsl #20 @ Get offset 120 - moveq pc, lr @ zero -> no fixup 121 + beq do_DataAbort @ zero -> no fixup 121 122 and r5, r8, #15 << 16 @ Extract 'n' from instruction 122 123 ldr r7, [sp, r5, lsr #14] @ Get register 'Rn' 123 124 tst r8, #1 << 23 @ Check U bit 124 125 subne r7, r7, r9, lsr #20 @ Undo increment 125 126 addeq r7, r7, r9, lsr #20 @ Undo decrement 126 127 str r7, [sp, r5, lsr #14] @ Put register 'Rn' 127 - mov pc, lr 128 + b do_DataAbort 128 129 129 130 .data_arm_lateldrprereg: 130 131 tst r8, #1 << 21 @ check writeback bit 131 - moveq pc, lr @ no writeback -> no fixup 132 + beq do_DataAbort @ no writeback -> no fixup 132 133 .data_arm_lateldrpostreg: 133 134 and r7, r8, #15 @ Extract 'm' from instruction 134 135 ldr r6, [sp, r7, lsl #2] @ Get register 'Rm'