[PATCH] Fix undefined instruction exception handling
Will Deacon
will.deacon at arm.com
Mon Jul 30 07:26:07 EDT 2012
Hi Russell,
On Sun, Jul 29, 2012 at 07:22:36PM +0100, Russell King - ARM Linux wrote:
> While trying to get a v3.5 kernel booted on the cubox, I noticed that
> VFP does not work correctly with VFP handling. This is because of the
> confusion over 16-bit vs 32-bit instructions, and where PC is supposed
> to point to.
>
> The rule is that FP handlers are entered with regs->ARM_pc pointing at
> the _next_ instruction to be executed. However, if the exception is
> not handled, regs->ARM_pc points at the faulting instruction.
[...]
> diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
> index 0d1851c..ad595be 100644
> --- a/arch/arm/kernel/entry-armv.S
> +++ b/arch/arm/kernel/entry-armv.S
> @@ -244,6 +244,19 @@ ENDPROC(__irq_svc)
> b 1b
> #endif
>
> +__und_fault:
> + @ Correct the PC such that it is pointing at the instruction
> + @ which caused the fault. If the faulting instruction was ARM
> + @ the PC will be pointing at the next instruction, and have to
> + @ subtract 4. Otherwise, it is Thumb, and the PC will be
> + @ pointing at the second half of the Thumb instruction. We
> + @ have to substract 2.
s/substract/subtract/
> __und_svc:
> #ifdef CONFIG_KPROBES
> @@ -261,7 +274,7 @@ ENDPROC(__irq_svc)
> @
> @ r0 - instruction
> @
> -#ifndef CONFIG_THUMB2_KERNEL
> +#ifndef CONFIG_THUMB2_KERNEL
> ldr r0, [r4, #-4]
> #else
> ldrh r0, [r4, #-2] @ Thumb instruction at LR - 2
> @@ -269,17 +282,24 @@ ENDPROC(__irq_svc)
> ldrhhs r9, [r4] @ bottom 16 bits
> orrhs r0, r9, r0, lsl #16
Do we not need an addhs r4, r4, #2 here?
> #endif
> - adr r9, BSYM(1f)
> + adr r9, BSYM(__und_svc_finish)
> mov r2, r4
> bl call_fpe
...otherwise the fp handler invoked by call_fpe will get confused and corrupt
the saved PC value. I suppose this might not matter at the moment, given that
we don't use FP in the kernel, but in that case a comment might be useful.
> + ldr r5, [sp, #S_PSR]
> mov r0, sp @ struct pt_regs *regs
> - bl do_undefinstr
> + mov r1, #4 @ PC correction to apply
> +#ifdef CONFIG_THUMB2_KERNEL
> + tst r5, #PSR_T_BIT
> + movne r1, #2
> +#endifi
If we fixup r4 above, I think we should set r1 depending on the instruction
size, like we do for userspace.
> diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
> index 4fa9903..4f9ca8d 100644
> --- a/arch/arm/vfp/entry.S
> +++ b/arch/arm/vfp/entry.S
> @@ -19,6 +19,15 @@
> #include <asm/vfpmacros.h>
> #include "../kernel/entry-header.S"
>
> +@ VFP entry point.
> +@
> +@ r0 = instruction opcode (32-bit ARM or two 16-bit Thumb)
> +@ r2 = PC value to resume execution after successful emulation
> +@ r9 = normal "successful" return address
> +@ r10 = this threads thread_info structure
> +@ lr = unrecognised instruction return address
> +@ IRQs disabled.
> +@
There's a similar comment a few lines above from this one which is now
contradictory -- can we just replace the old one with the new, correct one?
Will
More information about the linux-arm-kernel
mailing list