Loading arch/arm/kernel/irq.c +1 −1 Original line number Diff line number Diff line Loading @@ -109,7 +109,7 @@ static struct irq_desc bad_irq_desc = { * come via this function. Instead, they should provide their * own 'handler' */ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); struct irq_desc *desc = irq_desc + irq; Loading arch/arm/kernel/traps.c +16 −2 Original line number Diff line number Diff line Loading @@ -45,7 +45,18 @@ static int __init user_debug_setup(char *str) __setup("user_debug=", user_debug_setup); #endif void dump_backtrace_entry(unsigned long where, unsigned long from) static void dump_mem(const char *str, unsigned long bottom, unsigned long top); static inline int in_exception_text(unsigned long ptr) { extern char __exception_text_start[]; extern char __exception_text_end[]; return ptr >= (unsigned long)&__exception_text_start && ptr < (unsigned long)&__exception_text_end; } void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame) { #ifdef CONFIG_KALLSYMS printk("[<%08lx>] ", where); Loading @@ -55,6 +66,9 @@ void dump_backtrace_entry(unsigned long where, unsigned long from) #else printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from); #endif if (in_exception_text(where)) dump_mem("Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs)); } /* Loading Loading @@ -266,7 +280,7 @@ void unregister_undef_hook(struct undef_hook *hook) spin_unlock_irqrestore(&undef_lock, flags); } asmlinkage void do_undefinstr(struct pt_regs *regs) asmlinkage void __exception do_undefinstr(struct pt_regs *regs) { unsigned int correction = thumb_mode(regs) ? 2 : 4; unsigned int instr; Loading arch/arm/kernel/vmlinux.lds.S +3 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,9 @@ SECTIONS .text : { /* Real text segment */ _text = .; /* Text and read-only data */ __exception_text_start = .; *(.exception.text) __exception_text_end = .; *(.text) SCHED_TEXT LOCK_TEXT Loading arch/arm/lib/backtrace.S +81 −84 Original line number Diff line number Diff line Loading @@ -17,8 +17,8 @@ @ fp is 0 or stack frame #define frame r4 #define next r5 #define save r6 #define sv_fp r5 #define sv_pc r6 #define mask r7 #define offset r8 Loading @@ -31,108 +31,106 @@ ENTRY(c_backtrace) #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK) mov pc, lr #else stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location... tst r1, #0x10 @ 26 or 32-bit? moveq mask, #0xfc000003 movne mask, #0 tst mask, r0 movne r0, #0 movs frame, r0 1: moveq r0, #-2 ldmeqfd sp!, {r4 - r8, pc} 2: stmfd sp!, {pc} @ calculate offset of PC in STMIA instruction ldr r0, [sp], #4 adr r1, 2b - 4 movs frame, r0 @ if frame pointer is zero beq no_frame @ we have no stack frames tst r1, #0x10 @ 26 or 32-bit mode? moveq mask, #0xfc000003 @ mask for 26-bit movne mask, #0 @ mask for 32-bit 1: stmfd sp!, {pc} @ calculate offset of PC stored ldr r0, [sp], #4 @ by stmfd for this CPU adr r1, 1b sub offset, r0, r1 3: tst frame, mask @ Check for address exceptions... bne 1b /* * Stack frame layout: * optionally saved caller registers (r4 - r10) * saved fp * saved sp * saved lr * frame => saved pc * optionally saved arguments (r0 - r3) * saved sp => <next word> * * Functions start with the following code sequence: * mov ip, sp * stmfd sp!, {r0 - r3} (optional) * corrected pc => stmfd sp!, {..., fp, ip, lr, pc} */ for_each_frame: tst frame, mask @ Check for address exceptions bne no_frame 1001: ldr next, [frame, #-12] @ get fp 1002: ldr r2, [frame, #-4] @ get lr 1003: ldr r3, [frame, #0] @ get pc sub save, r3, offset @ Correct PC for prefetching bic save, save, mask 1004: ldr r1, [save, #0] @ get instruction at function mov r1, r1, lsr #10 ldr r3, .Ldsi+4 teq r1, r3 subeq save, save, #4 mov r0, save bic r1, r2, mask 1001: ldr sv_pc, [frame, #0] @ get saved pc 1002: ldr sv_fp, [frame, #-12] @ get saved fp sub sv_pc, sv_pc, offset @ Correct PC for prefetching bic sv_pc, sv_pc, mask @ mask PC/LR for the mode 1003: ldr r2, [sv_pc, #-4] @ if stmfd sp!, {args} exists, ldr r3, .Ldsi+4 @ adjust saved 'pc' back one teq r3, r2, lsr #10 @ instruction subne r0, sv_pc, #4 @ allow for mov subeq r0, sv_pc, #8 @ allow for mov + stmia ldr r1, [frame, #-4] @ get saved lr mov r2, frame bic r1, r1, mask @ mask PC/LR for the mode bl dump_backtrace_entry ldr r0, [frame, #-8] @ get sp sub r0, r0, #4 1005: ldr r1, [save, #4] @ get instruction at function+4 mov r3, r1, lsr #10 ldr r2, .Ldsi+4 teq r3, r2 @ Check for stmia sp!, {args} addeq save, save, #4 @ next instruction bleq .Ldumpstm sub r0, frame, #16 1006: ldr r1, [save, #4] @ Get 'stmia sp!, {rlist, fp, ip, lr, pc}' instruction mov r3, r1, lsr #10 ldr r2, .Ldsi teq r3, r2 bleq .Ldumpstm ldr r1, [sv_pc, #-4] @ if stmfd sp!, {args} exists, ldr r3, .Ldsi+4 teq r3, r1, lsr #10 ldreq r0, [frame, #-8] @ get sp subeq r0, r0, #4 @ point at the last arg bleq .Ldumpstm @ dump saved registers /* * A zero next framepointer means we're done. */ teq next, #0 ldmeqfd sp!, {r4 - r8, pc} 1004: ldr r1, [sv_pc, #0] @ if stmfd sp!, {..., fp, ip, lr, pc} ldr r3, .Ldsi @ instruction exists, teq r3, r1, lsr #10 subeq r0, frame, #16 bleq .Ldumpstm @ dump saved registers /* * The next framepointer must be above the * current framepointer. */ cmp next, frame mov frame, next bhi 3b b 1007f teq sv_fp, #0 @ zero saved fp means beq no_frame @ no further frames /* * Fixup for LDMDB. Note that this must not be in the fixup section. */ 1007: ldr r0, =.Lbad cmp sv_fp, frame @ next frame must be mov frame, sv_fp @ above the current frame bhi for_each_frame 1006: adr r0, .Lbad mov r1, frame bl printk ldmfd sp!, {r4 - r8, pc} .ltorg no_frame: ldmfd sp!, {r4 - r8, pc} .section __ex_table,"a" .align 3 .long 1001b, 1007b .long 1002b, 1007b .long 1003b, 1007b .long 1004b, 1007b .long 1005b, 1007b .long 1006b, 1007b .long 1001b, 1006b .long 1002b, 1006b .long 1003b, 1006b .long 1004b, 1006b .previous #define instr r4 #define reg r5 #define stack r6 .Ldumpstm: stmfd sp!, {instr, reg, stack, r7, r8, lr} .Ldumpstm: stmfd sp!, {instr, reg, stack, r7, lr} mov stack, r0 mov instr, r1 mov reg, #9 mov reg, #10 mov r7, #0 1: mov r3, #1 tst instr, r3, lsl reg beq 2f add r7, r7, #1 teq r7, #4 moveq r7, #0 moveq r3, #'\n' movne r3, #' ' ldr r2, [stack], #-4 mov r1, reg teq r7, #6 moveq r7, #1 moveq r1, #'\n' movne r1, #' ' ldr r3, [stack], #-4 mov r2, reg adr r0, .Lfp bl printk 2: subs reg, reg, #1 Loading @@ -140,14 +138,13 @@ ENTRY(c_backtrace) teq r7, #0 adrne r0, .Lcr blne printk mov r0, stack ldmfd sp!, {instr, reg, stack, r7, r8, pc} ldmfd sp!, {instr, reg, stack, r7, pc} .Lfp: .asciz " r%d = %08X%c" .Lfp: .asciz "%cr%d:%08x" .Lcr: .asciz "\n" .Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n" .align .Ldsi: .word 0x00e92dd8 >> 2 .word 0x00e92d00 >> 2 .Ldsi: .word 0xe92dd800 >> 10 @ stmfd sp!, {... fp, ip, lr, pc} .word 0xe92d0000 >> 10 @ stmfd sp!, {} #endif arch/arm/mm/fault.c +2 −2 Original line number Diff line number Diff line Loading @@ -438,7 +438,7 @@ hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *) /* * Dispatch a data abort to the relevant handler. */ asmlinkage void asmlinkage void __exception do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { const struct fsr_info *inf = fsr_info + (fsr & 15) + ((fsr & (1 << 10)) >> 6); Loading @@ -457,7 +457,7 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) notify_die("", regs, &info, fsr, 0); } asmlinkage void asmlinkage void __exception do_PrefetchAbort(unsigned long addr, struct pt_regs *regs) { do_translation_fault(addr, 0, regs); Loading Loading
arch/arm/kernel/irq.c +1 −1 Original line number Diff line number Diff line Loading @@ -109,7 +109,7 @@ static struct irq_desc bad_irq_desc = { * come via this function. Instead, they should provide their * own 'handler' */ asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs) asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); struct irq_desc *desc = irq_desc + irq; Loading
arch/arm/kernel/traps.c +16 −2 Original line number Diff line number Diff line Loading @@ -45,7 +45,18 @@ static int __init user_debug_setup(char *str) __setup("user_debug=", user_debug_setup); #endif void dump_backtrace_entry(unsigned long where, unsigned long from) static void dump_mem(const char *str, unsigned long bottom, unsigned long top); static inline int in_exception_text(unsigned long ptr) { extern char __exception_text_start[]; extern char __exception_text_end[]; return ptr >= (unsigned long)&__exception_text_start && ptr < (unsigned long)&__exception_text_end; } void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame) { #ifdef CONFIG_KALLSYMS printk("[<%08lx>] ", where); Loading @@ -55,6 +66,9 @@ void dump_backtrace_entry(unsigned long where, unsigned long from) #else printk("Function entered at [<%08lx>] from [<%08lx>]\n", where, from); #endif if (in_exception_text(where)) dump_mem("Exception stack", frame + 4, frame + 4 + sizeof(struct pt_regs)); } /* Loading Loading @@ -266,7 +280,7 @@ void unregister_undef_hook(struct undef_hook *hook) spin_unlock_irqrestore(&undef_lock, flags); } asmlinkage void do_undefinstr(struct pt_regs *regs) asmlinkage void __exception do_undefinstr(struct pt_regs *regs) { unsigned int correction = thumb_mode(regs) ? 2 : 4; unsigned int instr; Loading
arch/arm/kernel/vmlinux.lds.S +3 −0 Original line number Diff line number Diff line Loading @@ -83,6 +83,9 @@ SECTIONS .text : { /* Real text segment */ _text = .; /* Text and read-only data */ __exception_text_start = .; *(.exception.text) __exception_text_end = .; *(.text) SCHED_TEXT LOCK_TEXT Loading
arch/arm/lib/backtrace.S +81 −84 Original line number Diff line number Diff line Loading @@ -17,8 +17,8 @@ @ fp is 0 or stack frame #define frame r4 #define next r5 #define save r6 #define sv_fp r5 #define sv_pc r6 #define mask r7 #define offset r8 Loading @@ -31,108 +31,106 @@ ENTRY(c_backtrace) #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK) mov pc, lr #else stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location... tst r1, #0x10 @ 26 or 32-bit? moveq mask, #0xfc000003 movne mask, #0 tst mask, r0 movne r0, #0 movs frame, r0 1: moveq r0, #-2 ldmeqfd sp!, {r4 - r8, pc} 2: stmfd sp!, {pc} @ calculate offset of PC in STMIA instruction ldr r0, [sp], #4 adr r1, 2b - 4 movs frame, r0 @ if frame pointer is zero beq no_frame @ we have no stack frames tst r1, #0x10 @ 26 or 32-bit mode? moveq mask, #0xfc000003 @ mask for 26-bit movne mask, #0 @ mask for 32-bit 1: stmfd sp!, {pc} @ calculate offset of PC stored ldr r0, [sp], #4 @ by stmfd for this CPU adr r1, 1b sub offset, r0, r1 3: tst frame, mask @ Check for address exceptions... bne 1b /* * Stack frame layout: * optionally saved caller registers (r4 - r10) * saved fp * saved sp * saved lr * frame => saved pc * optionally saved arguments (r0 - r3) * saved sp => <next word> * * Functions start with the following code sequence: * mov ip, sp * stmfd sp!, {r0 - r3} (optional) * corrected pc => stmfd sp!, {..., fp, ip, lr, pc} */ for_each_frame: tst frame, mask @ Check for address exceptions bne no_frame 1001: ldr next, [frame, #-12] @ get fp 1002: ldr r2, [frame, #-4] @ get lr 1003: ldr r3, [frame, #0] @ get pc sub save, r3, offset @ Correct PC for prefetching bic save, save, mask 1004: ldr r1, [save, #0] @ get instruction at function mov r1, r1, lsr #10 ldr r3, .Ldsi+4 teq r1, r3 subeq save, save, #4 mov r0, save bic r1, r2, mask 1001: ldr sv_pc, [frame, #0] @ get saved pc 1002: ldr sv_fp, [frame, #-12] @ get saved fp sub sv_pc, sv_pc, offset @ Correct PC for prefetching bic sv_pc, sv_pc, mask @ mask PC/LR for the mode 1003: ldr r2, [sv_pc, #-4] @ if stmfd sp!, {args} exists, ldr r3, .Ldsi+4 @ adjust saved 'pc' back one teq r3, r2, lsr #10 @ instruction subne r0, sv_pc, #4 @ allow for mov subeq r0, sv_pc, #8 @ allow for mov + stmia ldr r1, [frame, #-4] @ get saved lr mov r2, frame bic r1, r1, mask @ mask PC/LR for the mode bl dump_backtrace_entry ldr r0, [frame, #-8] @ get sp sub r0, r0, #4 1005: ldr r1, [save, #4] @ get instruction at function+4 mov r3, r1, lsr #10 ldr r2, .Ldsi+4 teq r3, r2 @ Check for stmia sp!, {args} addeq save, save, #4 @ next instruction bleq .Ldumpstm sub r0, frame, #16 1006: ldr r1, [save, #4] @ Get 'stmia sp!, {rlist, fp, ip, lr, pc}' instruction mov r3, r1, lsr #10 ldr r2, .Ldsi teq r3, r2 bleq .Ldumpstm ldr r1, [sv_pc, #-4] @ if stmfd sp!, {args} exists, ldr r3, .Ldsi+4 teq r3, r1, lsr #10 ldreq r0, [frame, #-8] @ get sp subeq r0, r0, #4 @ point at the last arg bleq .Ldumpstm @ dump saved registers /* * A zero next framepointer means we're done. */ teq next, #0 ldmeqfd sp!, {r4 - r8, pc} 1004: ldr r1, [sv_pc, #0] @ if stmfd sp!, {..., fp, ip, lr, pc} ldr r3, .Ldsi @ instruction exists, teq r3, r1, lsr #10 subeq r0, frame, #16 bleq .Ldumpstm @ dump saved registers /* * The next framepointer must be above the * current framepointer. */ cmp next, frame mov frame, next bhi 3b b 1007f teq sv_fp, #0 @ zero saved fp means beq no_frame @ no further frames /* * Fixup for LDMDB. Note that this must not be in the fixup section. */ 1007: ldr r0, =.Lbad cmp sv_fp, frame @ next frame must be mov frame, sv_fp @ above the current frame bhi for_each_frame 1006: adr r0, .Lbad mov r1, frame bl printk ldmfd sp!, {r4 - r8, pc} .ltorg no_frame: ldmfd sp!, {r4 - r8, pc} .section __ex_table,"a" .align 3 .long 1001b, 1007b .long 1002b, 1007b .long 1003b, 1007b .long 1004b, 1007b .long 1005b, 1007b .long 1006b, 1007b .long 1001b, 1006b .long 1002b, 1006b .long 1003b, 1006b .long 1004b, 1006b .previous #define instr r4 #define reg r5 #define stack r6 .Ldumpstm: stmfd sp!, {instr, reg, stack, r7, r8, lr} .Ldumpstm: stmfd sp!, {instr, reg, stack, r7, lr} mov stack, r0 mov instr, r1 mov reg, #9 mov reg, #10 mov r7, #0 1: mov r3, #1 tst instr, r3, lsl reg beq 2f add r7, r7, #1 teq r7, #4 moveq r7, #0 moveq r3, #'\n' movne r3, #' ' ldr r2, [stack], #-4 mov r1, reg teq r7, #6 moveq r7, #1 moveq r1, #'\n' movne r1, #' ' ldr r3, [stack], #-4 mov r2, reg adr r0, .Lfp bl printk 2: subs reg, reg, #1 Loading @@ -140,14 +138,13 @@ ENTRY(c_backtrace) teq r7, #0 adrne r0, .Lcr blne printk mov r0, stack ldmfd sp!, {instr, reg, stack, r7, r8, pc} ldmfd sp!, {instr, reg, stack, r7, pc} .Lfp: .asciz " r%d = %08X%c" .Lfp: .asciz "%cr%d:%08x" .Lcr: .asciz "\n" .Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n" .align .Ldsi: .word 0x00e92dd8 >> 2 .word 0x00e92d00 >> 2 .Ldsi: .word 0xe92dd800 >> 10 @ stmfd sp!, {... fp, ip, lr, pc} .word 0xe92d0000 >> 10 @ stmfd sp!, {} #endif
arch/arm/mm/fault.c +2 −2 Original line number Diff line number Diff line Loading @@ -438,7 +438,7 @@ hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs *) /* * Dispatch a data abort to the relevant handler. */ asmlinkage void asmlinkage void __exception do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { const struct fsr_info *inf = fsr_info + (fsr & 15) + ((fsr & (1 << 10)) >> 6); Loading @@ -457,7 +457,7 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) notify_die("", regs, &info, fsr, 0); } asmlinkage void asmlinkage void __exception do_PrefetchAbort(unsigned long addr, struct pt_regs *regs) { do_translation_fault(addr, 0, regs); Loading