aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiuHailong <liu.hailong6@zte.com.cn>2017-02-06 21:35:52 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-25 09:44:43 -0400
commit018b91870856035f9bdff45f690b933d67f6efc3 (patch)
treef23413c3624efdb7b82b016a9b75df58beeaaf96
parent3915c566ea9427947ddc1849c68f64c401a3d5c9 (diff)
powerpc/64e: Fix hang when debugging programs with relocated kernel
commit fd615f69a18a9d4aa5ef02a1dc83f319f75da8e7 upstream. 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") Signed-off-by: Scott Wood <oss@buserror.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-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 38a1f96430e1..ca03eb229a9a 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