From 309ee04257d473ce87f2c7e99f6d69e933d307e3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 24 Mar 2017 16:15:45 +0000 Subject: ARM: use aliases for registers in entry-common Use aliases for the saved (and preserved) PSR and PC values so that we can control which registers are used. Signed-off-by: Russell King --- arch/arm/kernel/entry-common.S | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'arch/arm/kernel') diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index eb5cd77bf1d8..9abe47a206d9 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -27,6 +27,8 @@ #include "entry-header.S" +saved_psr .req r8 +saved_pc .req lr .align 5 #if !(IS_ENABLED(CONFIG_TRACE_IRQFLAGS) || IS_ENABLED(CONFIG_CONTEXT_TRACKING)) @@ -141,9 +143,9 @@ ENTRY(vector_swi) ARM( stmdb r8, {sp, lr}^ ) @ Calling sp, lr THUMB( mov r8, sp ) THUMB( store_user_sp_lr r8, r10, S_SP ) @ calling sp, lr - mrs r8, spsr @ called from non-FIQ mode, so ok. - str lr, [sp, #S_PC] @ Save calling PC - str r8, [sp, #S_PSR] @ Save CPSR + mrs saved_psr, spsr @ called from non-FIQ mode, so ok. + str saved_pc, [sp, #S_PC] @ Save calling PC + str saved_psr, [sp, #S_PSR] @ Save CPSR str r0, [sp, #S_OLD_R0] @ Save OLD_R0 #endif zero_fp @@ -163,11 +165,11 @@ ENTRY(vector_swi) * value to determine if it is an EABI or an old ABI call. */ #ifdef CONFIG_ARM_THUMB - tst r8, #PSR_T_BIT + tst saved_psr, #PSR_T_BIT movne r10, #0 @ no thumb OABI emulation - USER( ldreq r10, [lr, #-4] ) @ get SWI instruction + USER( ldreq r10, [saved_pc, #-4] ) @ get SWI instruction #else - USER( ldr r10, [lr, #-4] ) @ get SWI instruction + USER( ldr r10, [saved_pc, #-4] ) @ get SWI instruction #endif ARM_BE8(rev r10, r10) @ little endian instruction @@ -178,15 +180,17 @@ ENTRY(vector_swi) */ #elif defined(CONFIG_ARM_THUMB) /* Legacy ABI only, possibly thumb mode. */ - tst r8, #PSR_T_BIT @ this is SPSR from save_user_regs + tst saved_psr, #PSR_T_BIT @ this is SPSR from save_user_regs addne scno, r7, #__NR_SYSCALL_BASE @ put OS number in - USER( ldreq scno, [lr, #-4] ) + USER( ldreq scno, [saved_pc, #-4] ) #else /* Legacy ABI only. */ - USER( ldr scno, [lr, #-4] ) @ get SWI instruction + USER( ldr scno, [saved_pc, #-4] ) @ get SWI instruction #endif + /* saved_psr and saved_pc are now dead */ + uaccess_disable tbl adr tbl, sys_call_table @ load syscall table pointer @@ -234,7 +238,7 @@ local_restart: * current task. */ 9001: - sub lr, lr, #4 + sub lr, saved_pc, #4 str lr, [sp, #S_PC] b ret_fast_syscall #endif -- cgit v1.2.1 From da594e3fff398a164c77dd728d9fbfc6880881e6 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 24 Mar 2017 16:19:12 +0000 Subject: ARM: obtain thread info structure later Obtain the thread info structure later in the syscall processing, so that we free up a register for earlier code. Signed-off-by: Russell King --- arch/arm/kernel/entry-common.S | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/arm/kernel') diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 9abe47a206d9..374c28723547 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -152,7 +152,6 @@ ENTRY(vector_swi) alignment_trap r10, ip, __cr_alignment enable_irq ct_user_exit - get_thread_info tsk /* * Get the system call number. @@ -209,6 +208,7 @@ ENTRY(vector_swi) bic scno, scno, #0xff000000 @ mask off SWI op-code eor scno, scno, #__NR_SYSCALL_BASE @ check OS number #endif + get_thread_info tsk local_restart: ldr r10, [tsk, #TI_FLAGS] @ check for syscall tracing @@ -240,6 +240,7 @@ local_restart: 9001: sub lr, saved_pc, #4 str lr, [sp, #S_PC] + get_thread_info tsk b ret_fast_syscall #endif ENDPROC(vector_swi) -- cgit v1.2.1 From fcea45236d3ffcd317296d75612eb163bf734407 Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 24 Mar 2017 16:22:10 +0000 Subject: ARM: move PC value into r9 Move the saved PC value into r9, thereby moving it into a caller-saved register for functions that we may call during the entry to a syscall. Signed-off-by: Russell King --- arch/arm/kernel/entry-common.S | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch/arm/kernel') diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 374c28723547..1b3fc79d0e8b 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -28,7 +28,13 @@ #include "entry-header.S" saved_psr .req r8 +#if defined(CONFIG_TRACE_IRQFLAGS) || defined(CONFIG_CONTEXT_TRACKING) +saved_pc .req r9 +#define TRACE(x...) x +#else saved_pc .req lr +#define TRACE(x...) +#endif .align 5 #if !(IS_ENABLED(CONFIG_TRACE_IRQFLAGS) || IS_ENABLED(CONFIG_CONTEXT_TRACKING)) @@ -144,6 +150,7 @@ ENTRY(vector_swi) THUMB( mov r8, sp ) THUMB( store_user_sp_lr r8, r10, S_SP ) @ calling sp, lr mrs saved_psr, spsr @ called from non-FIQ mode, so ok. + TRACE( mov saved_pc, lr ) str saved_pc, [sp, #S_PC] @ Save calling PC str saved_psr, [sp, #S_PSR] @ Save CPSR str r0, [sp, #S_OLD_R0] @ Save OLD_R0 -- cgit v1.2.1 From dca778c5bbf3f1cfcf7f6ef6cadf5a7e5c5d972f Mon Sep 17 00:00:00 2001 From: Russell King Date: Fri, 24 Mar 2017 16:23:25 +0000 Subject: ARM: avoid saving and restoring registers unnecessarily Avoid repeatedly saving and restoring registers around the calls to trace_hardirqs_on() and context_tracking_user_exit(). With the previous changes, we no longer need to preserve "lr" across these calls, and if we re-load r0-r3 later, we can avoid preserving these regsiters too. Signed-off-by: Russell King --- arch/arm/kernel/entry-common.S | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'arch/arm/kernel') diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index 1b3fc79d0e8b..0b60adf4a5d9 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S @@ -157,8 +157,9 @@ ENTRY(vector_swi) #endif zero_fp alignment_trap r10, ip, __cr_alignment - enable_irq - ct_user_exit + asm_trace_hardirqs_on save=0 + enable_irq_notrace + ct_user_exit save=0 /* * Get the system call number. @@ -216,6 +217,11 @@ ENTRY(vector_swi) eor scno, scno, #__NR_SYSCALL_BASE @ check OS number #endif get_thread_info tsk + /* + * Reload the registers that may have been corrupted on entry to + * the syscall assembly (by tracing or context tracking.) + */ + TRACE( ldmia sp, {r0 - r3} ) local_restart: ldr r10, [tsk, #TI_FLAGS] @ check for syscall tracing -- cgit v1.2.1 From 1abd35023763c099bf4ee7558faa261d5c9d5025 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 26 Jul 2017 12:49:31 +0100 Subject: ARM: align .data section Robert Jarzmik reports that his PXA25x system fails to boot with 4.12, failing at __flush_whole_cache in arch/arm/mm/proc-xscale.S:215: 0xc0019e20 <+0>: ldr r1, [pc, #788] 0xc0019e24 <+4>: ldr r0, [r1] <== here with r1 containing 0xc06f82cd, which is the address of "clean_addr". Examination of the System.map shows: c06f22c8 D user_pmd_table c06f22cc d __warned.19178 c06f22cd d clean_addr indicating that a .data.unlikely section has appeared just before the .data section from proc-xscale.S. According to objdump -h, it appears that our assembly files default their .data alignment to 2**0, which is bad news if the preceding .data section size is not power-of-2 aligned at link time. Add the appropriate .align directives to all assembly files in arch/arm that are missing them where we require an appropriate alignment. Reported-by: Robert Jarzmik Tested-by: Robert Jarzmik Signed-off-by: Russell King --- arch/arm/kernel/entry-armv.S | 2 ++ arch/arm/kernel/head.S | 2 ++ arch/arm/kernel/hyp-stub.S | 1 + arch/arm/kernel/iwmmxt.S | 1 + arch/arm/kernel/sleep.S | 1 + 5 files changed, 7 insertions(+) (limited to 'arch/arm/kernel') diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 9f157e7c51e7..4c0b9e569a9e 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -721,6 +721,7 @@ do_fpe: */ .pushsection .data + .align 2 ENTRY(fp_enter) .word no_fp .popsection @@ -1221,6 +1222,7 @@ vector_addrexcptn: W(b) vector_fiq .data + .align 2 .globl cr_alignment cr_alignment: diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S index 04286fd9e09c..6b1148cafffd 100644 --- a/arch/arm/kernel/head.S +++ b/arch/arm/kernel/head.S @@ -556,6 +556,7 @@ ENDPROC(__fixup_smp) .word __smpalt_end .pushsection .data + .align 2 .globl smp_on_up smp_on_up: ALT_SMP(.long 1) @@ -716,6 +717,7 @@ ENTRY(fixup_pv_table) ENDPROC(fixup_pv_table) .data + .align 2 .globl __pv_phys_pfn_offset .type __pv_phys_pfn_offset, %object __pv_phys_pfn_offset: diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S index ec7e7377d423..60146e32619a 100644 --- a/arch/arm/kernel/hyp-stub.S +++ b/arch/arm/kernel/hyp-stub.S @@ -31,6 +31,7 @@ * zeroing of .bss would clobber it. */ .data + .align 2 ENTRY(__boot_cpu_mode) .long 0 .text diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S index 49fadbda8c63..81cd4d43b3ec 100644 --- a/arch/arm/kernel/iwmmxt.S +++ b/arch/arm/kernel/iwmmxt.S @@ -367,6 +367,7 @@ ENTRY(iwmmxt_task_release) ENDPROC(iwmmxt_task_release) .data + .align 2 concan_owner: .word 0 diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S index 0f6c1000582c..9f08d214d05a 100644 --- a/arch/arm/kernel/sleep.S +++ b/arch/arm/kernel/sleep.S @@ -171,6 +171,7 @@ mpidr_hash_ptr: .long mpidr_hash - . @ mpidr_hash struct offset .data + .align 2 .type sleep_save_sp, #object ENTRY(sleep_save_sp) .space SLEEP_SAVE_SP_SZ @ struct sleep_save_sp -- cgit v1.2.1 From 9a3dc3186fc3795e076a4122da9e0258651a9631 Mon Sep 17 00:00:00 2001 From: Dustin Brown Date: Mon, 7 Aug 2017 19:44:01 +0100 Subject: ARM: 8691/1: Export save_stack_trace_tsk() The kernel watchdog is a great debugging tool for finding tasks that consume a disproportionate amount of CPU time in contiguous chunks. One can imagine building a similar watchdog for arbitrary driver threads using save_stack_trace_tsk() and print_stack_trace(). However, this is not viable for dynamically loaded driver modules on ARM platforms because save_stack_trace_tsk() is not exported for those architectures. Export save_stack_trace_tsk() for the ARM architecture to align with x86 and support various debugging use cases such as arbitrary driver thread watchdog timers. Signed-off-by: Dustin Brown Signed-off-by: Russell King --- arch/arm/kernel/stacktrace.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/kernel') diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index 3a2fa203637a..65228bf4c6df 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c @@ -171,6 +171,7 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) { __save_stack_trace(tsk, trace, 1); } +EXPORT_SYMBOL(save_stack_trace_tsk); void save_stack_trace(struct stack_trace *trace) { -- cgit v1.2.1