diff options
Diffstat (limited to 'arch/arm/kernel')
| -rw-r--r-- | arch/arm/kernel/entry-armv.S | 16 | ||||
| -rw-r--r-- | arch/arm/kernel/kprobes-decode.c | 5 | ||||
| -rw-r--r-- | arch/arm/kernel/process.c | 23 | 
3 files changed, 23 insertions, 21 deletions
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 7ee48e7f8f3..3fd7861de4d 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -162,8 +162,6 @@ ENDPROC(__und_invalid)  	@  r4 - orig_r0 (see pt_regs definition in ptrace.h)  	@  	stmia	r5, {r0 - r4} - -	asm_trace_hardirqs_off  	.endm  	.align	5 @@ -204,7 +202,7 @@ __dabt_svc:  	@  	@ IRQs off again before pulling preserved data off the stack  	@ -	disable_irq +	disable_irq_notrace  	@  	@ restore SPSR and restart the instruction @@ -218,6 +216,9 @@ ENDPROC(__dabt_svc)  __irq_svc:  	svc_entry +#ifdef CONFIG_TRACE_IRQFLAGS +	bl	trace_hardirqs_off +#endif  #ifdef CONFIG_PREEMPT  	get_thread_info tsk  	ldr	r8, [tsk, #TI_PREEMPT]		@ get preempt count @@ -291,7 +292,7 @@ __und_svc:  	@  	@ IRQs off again before pulling preserved data off the stack  	@ -1:	disable_irq +1:	disable_irq_notrace  	@  	@ restore SPSR and restart the instruction @@ -327,7 +328,7 @@ __pabt_svc:  	@  	@ IRQs off again before pulling preserved data off the stack  	@ -	disable_irq +	disable_irq_notrace  	@  	@ restore SPSR and restart the instruction @@ -393,8 +394,6 @@ ENDPROC(__pabt_svc)  	@ Clear FP to mark the first stack frame  	@  	zero_fp - -	asm_trace_hardirqs_off  	.endm  	.macro	kuser_cmpxchg_check @@ -465,9 +464,6 @@ __irq_usr:   THUMB(	movne	r0, #0		)   THUMB(	strne	r0, [r0]	)  #endif -#ifdef CONFIG_TRACE_IRQFLAGS -	bl	trace_hardirqs_on -#endif  	mov	why, #0  	b	ret_to_user diff --git a/arch/arm/kernel/kprobes-decode.c b/arch/arm/kernel/kprobes-decode.c index da1f94906a4..8bccbfa693f 100644 --- a/arch/arm/kernel/kprobes-decode.c +++ b/arch/arm/kernel/kprobes-decode.c @@ -583,13 +583,14 @@ static void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs)  {  	insn_llret_3arg_fn_t *i_fn = (insn_llret_3arg_fn_t *)&p->ainsn.insn[0];  	kprobe_opcode_t insn = p->opcode; +	long ppc = (long)p->addr + 8;  	union reg_pair fnr;  	int rd = (insn >> 12) & 0xf;  	int rn = (insn >> 16) & 0xf;  	int rm = insn & 0xf;  	long rdv; -	long rnv  = regs->uregs[rn]; -	long rmv  = regs->uregs[rm]; /* rm/rmv may be invalid, don't care. */ +	long rnv = (rn == 15) ? ppc : regs->uregs[rn]; +	long rmv = (rm == 15) ? ppc : regs->uregs[rm];  	long cpsr = regs->ARM_cpsr;  	fnr.dr = insnslot_llret_3arg_rflags(rnv, 0, rmv, cpsr, i_fn); diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index acf5e6fdb6d..a4a9cc88bec 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -351,17 +351,21 @@ EXPORT_SYMBOL(dump_fpu);  /*   * Shuffle the argument into the correct register before calling the - * thread function.  r1 is the thread argument, r2 is the pointer to - * the thread function, and r3 points to the exit function. + * thread function.  r4 is the thread argument, r5 is the pointer to + * the thread function, and r6 points to the exit function.   */  extern void kernel_thread_helper(void);  asm(	".pushsection .text\n"  "	.align\n"  "	.type	kernel_thread_helper, #function\n"  "kernel_thread_helper:\n" -"	mov	r0, r1\n" -"	mov	lr, r3\n" -"	mov	pc, r2\n" +#ifdef CONFIG_TRACE_IRQFLAGS +"	bl	trace_hardirqs_on\n" +#endif +"	msr	cpsr_c, r7\n" +"	mov	r0, r4\n" +"	mov	lr, r6\n" +"	mov	pc, r5\n"  "	.size	kernel_thread_helper, . - kernel_thread_helper\n"  "	.popsection"); @@ -391,11 +395,12 @@ pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)  	memset(®s, 0, sizeof(regs)); -	regs.ARM_r1 = (unsigned long)arg; -	regs.ARM_r2 = (unsigned long)fn; -	regs.ARM_r3 = (unsigned long)kernel_thread_exit; +	regs.ARM_r4 = (unsigned long)arg; +	regs.ARM_r5 = (unsigned long)fn; +	regs.ARM_r6 = (unsigned long)kernel_thread_exit; +	regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE;  	regs.ARM_pc = (unsigned long)kernel_thread_helper; -	regs.ARM_cpsr = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE; +	regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT;  	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);  }  |