aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiuHailong <liu.hailong6@zte.com.cn>2017-02-06 21:35:52 -0500
committerScott Wood <oss@buserror.net>2017-04-30 02:05:18 -0400
commitfd615f69a18a9d4aa5ef02a1dc83f319f75da8e7 (patch)
tree75e7075a83f6be450b813da4f7281c154f0baad3
parent096ff2ddba83bf022d593a3096d683e57c4befb0 (diff)
powerpc/64e: Fix hang when debugging programs with relocated kernel
Debug interrupts can be taken during interrupt entry, since interrupt entry does not automatically turn them off. The kernel will check whether the faulting instruction is between [interrupt_base_book3e, __end_interrupts], and if so clear MSR[DE] and return. However, when the kernel is built with CONFIG_RELOCATABLE, it can't use LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) and LOAD_REG_IMMEDIATE(r15,__end_interrupts), as they ignore relocation. Thus, if the kernel is actually running at a different address than it was built at, the address comparison will fail, and the exception entry code will hang at kernel_dbg_exc. r2(toc) is also not usable here, as r2 still holds data from the interrupted context, so LOAD_REG_ADDR() doesn't work either. So we use the *name@got* to get the EV of two labels directly. Test programs test.c shows as follows: int main(int argc, char *argv[]) { if (access("/proc/sys/kernel/perf_event_paranoid", F_OK) == -1) printf("Kernel doesn't have perf_event support\n"); } Steps to reproduce the bug, for example: 1) ./gdb ./test 2) (gdb) b access 3) (gdb) r 4) (gdb) s Signed-off-by: Liu Hailong <liu.hailong6@zte.com.cn> Signed-off-by: Jiang Xuexin <jiang.xuexin@zte.com.cn> Reviewed-by: Jiang Biao <jiang.biao2@zte.com.cn> Reviewed-by: Liu Song <liu.song11@zte.com.cn> Reviewed-by: Huang Jian <huang.jian@zte.com.cn> [scottwood: cleaned up commit message, and specified bad behavior as a hang rather than an oops to correspond to mainline kernel behavior] Fixes: 1cb6e0649248 ("powerpc/book3e: support CONFIG_RELOCATABLE") Cc: <stable@vger.kernel.org> # 4.4.x- Signed-off-by: Scott Wood <oss@buserror.net>
-rw-r--r--arch/powerpc/kernel/exceptions-64e.S12
1 files changed, 12 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index 45b453e4d0c8..acd8ca76233e 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -735,8 +735,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
735 andis. r15,r14,(DBSR_IC|DBSR_BT)@h 735 andis. r15,r14,(DBSR_IC|DBSR_BT)@h
736 beq+ 1f 736 beq+ 1f
737 737
738#ifdef CONFIG_RELOCATABLE
739 ld r15,PACATOC(r13)
740 ld r14,interrupt_base_book3e@got(r15)
741 ld r15,__end_interrupts@got(r15)
742#else
738 LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) 743 LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e)
739 LOAD_REG_IMMEDIATE(r15,__end_interrupts) 744 LOAD_REG_IMMEDIATE(r15,__end_interrupts)
745#endif
740 cmpld cr0,r10,r14 746 cmpld cr0,r10,r14
741 cmpld cr1,r10,r15 747 cmpld cr1,r10,r15
742 blt+ cr0,1f 748 blt+ cr0,1f
@@ -799,8 +805,14 @@ kernel_dbg_exc:
799 andis. r15,r14,(DBSR_IC|DBSR_BT)@h 805 andis. r15,r14,(DBSR_IC|DBSR_BT)@h
800 beq+ 1f 806 beq+ 1f
801 807
808#ifdef CONFIG_RELOCATABLE
809 ld r15,PACATOC(r13)
810 ld r14,interrupt_base_book3e@got(r15)
811 ld r15,__end_interrupts@got(r15)
812#else
802 LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) 813 LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e)
803 LOAD_REG_IMMEDIATE(r15,__end_interrupts) 814 LOAD_REG_IMMEDIATE(r15,__end_interrupts)
815#endif
804 cmpld cr0,r10,r14 816 cmpld cr0,r10,r14
805 cmpld cr1,r10,r15 817 cmpld cr1,r10,r15
806 blt+ cr0,1f 818 blt+ cr0,1f