diff options
author | Koen Kooi <koen@openembedded.org> | 2009-07-08 18:35:34 +0200 |
---|---|---|
committer | Koen Kooi <koen@openembedded.org> | 2009-07-08 18:35:34 +0200 |
commit | 40a2e72aed61b86bb07882cb4c26c82535d1c448 (patch) | |
tree | 08b40dd8f7bb8296faf7df958865dab1b48d4587 /recipes/linux/linux-omap-2.6.29/vfp/03-vfp-corruption.patch | |
parent | dfc54a347acd6d730c994fc42c99328749fe225b (diff) |
linux-omap 2.6.29: fix some vfp and neon bugs
Diffstat (limited to 'recipes/linux/linux-omap-2.6.29/vfp/03-vfp-corruption.patch')
-rw-r--r-- | recipes/linux/linux-omap-2.6.29/vfp/03-vfp-corruption.patch | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/recipes/linux/linux-omap-2.6.29/vfp/03-vfp-corruption.patch b/recipes/linux/linux-omap-2.6.29/vfp/03-vfp-corruption.patch new file mode 100644 index 0000000000..216d4f5eaa --- /dev/null +++ b/recipes/linux/linux-omap-2.6.29/vfp/03-vfp-corruption.patch @@ -0,0 +1,136 @@ +From: George G. Davis <gdavis@mvista.com> +Date: Wed, 1 Apr 2009 18:27:18 +0000 (+0100) +Subject: 5440/1: Fix VFP state corruption due to preemption during VFP exceptions +X-Git-Url: http://siarhei.siamashka.name/gitweb/?p=linux-omap-2.6.git;a=commitdiff_plain;h=4f7720780dc4a298a6d59c0ec39f7687022cc36f + +5440/1: Fix VFP state corruption due to preemption during VFP exceptions + +[ARM] 5440/1: Fix VFP state corruption due to preemption during VFP exceptions + +We've observed that ARM VFP state can be corrupted during VFP exception +handling when PREEMPT is enabled. The exact conditions are difficult +to reproduce but appear to occur during VFP exception handling when a +task causes a VFP exception which is handled via VFP_bounce and is then +preempted by yet another task which in turn causes yet another VFP +exception. Since the VFP_bounce code is not preempt safe, VFP state then +becomes corrupt. In order to prevent preemption from occuring while +handling a VFP exception, this patch disables preemption while handling +VFP exceptions. + +Signed-off-by: George G. Davis <gdavis@mvista.com> +Acked-by: Catalin Marinas <catalin.marinas@arm.com> +Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> +--- + +diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S +index ba592a9..a2bed62 100644 +--- a/arch/arm/vfp/entry.S ++++ b/arch/arm/vfp/entry.S +@@ -15,13 +15,16 @@ + * r10 = thread_info structure + * lr = failure return + */ +-#include <linux/linkage.h> +-#include <linux/init.h> +-#include <asm/asm-offsets.h> +-#include <asm/assembler.h> ++#include <asm/thread_info.h> + #include <asm/vfpmacros.h> ++#include "../kernel/entry-header.S" + + ENTRY(do_vfp) ++#ifdef CONFIG_PREEMPT ++ ldr r4, [r10, #TI_PREEMPT] @ get preempt count ++ add r11, r4, #1 @ increment it ++ str r11, [r10, #TI_PREEMPT] ++#endif + enable_irq + ldr r4, .LCvfp + ldr r11, [r10, #TI_CPU] @ CPU number +@@ -30,6 +33,12 @@ ENTRY(do_vfp) + ENDPROC(do_vfp) + + ENTRY(vfp_null_entry) ++#ifdef CONFIG_PREEMPT ++ get_thread_info r10 ++ ldr r4, [r10, #TI_PREEMPT] @ get preempt count ++ sub r11, r4, #1 @ decrement it ++ str r11, [r10, #TI_PREEMPT] ++#endif + mov pc, lr + ENDPROC(vfp_null_entry) + +@@ -41,6 +50,12 @@ ENDPROC(vfp_null_entry) + + __INIT + ENTRY(vfp_testing_entry) ++#ifdef CONFIG_PREEMPT ++ get_thread_info r10 ++ ldr r4, [r10, #TI_PREEMPT] @ get preempt count ++ sub r11, r4, #1 @ decrement it ++ str r11, [r10, #TI_PREEMPT] ++#endif + ldr r0, VFP_arch_address + str r5, [r0] @ known non-zero value + mov pc, r9 @ we have handled the fault +diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S +index 902d396..ea0a156 100644 +--- a/arch/arm/vfp/vfphw.S ++++ b/arch/arm/vfp/vfphw.S +@@ -131,6 +131,12 @@ check_for_exception: + VFPFMXR FPEXC, r1 @ restore FPEXC last + sub r2, r2, #4 + str r2, [sp, #S_PC] @ retry the instruction ++#ifdef CONFIG_PREEMPT ++ get_thread_info r10 ++ ldr r4, [r10, #TI_PREEMPT] @ get preempt count ++ sub r11, r4, #1 @ decrement it ++ str r11, [r10, #TI_PREEMPT] ++#endif + mov pc, r9 @ we think we have handled things + + +@@ -149,6 +155,12 @@ look_for_VFP_exceptions: + @ not recognised by VFP + + DBGSTR "not VFP" ++#ifdef CONFIG_PREEMPT ++ get_thread_info r10 ++ ldr r4, [r10, #TI_PREEMPT] @ get preempt count ++ sub r11, r4, #1 @ decrement it ++ str r11, [r10, #TI_PREEMPT] ++#endif + mov pc, lr + + process_exception: +diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c +index 75457b3..01599c4 100644 +--- a/arch/arm/vfp/vfpmodule.c ++++ b/arch/arm/vfp/vfpmodule.c +@@ -266,7 +266,7 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) + * on VFP subarch 1. + */ + vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr, regs); +- return; ++ goto exit; + } + + /* +@@ -297,7 +297,7 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) + * the FPEXC.FP2V bit is valid only if FPEXC.EX is 1. + */ + if (fpexc ^ (FPEXC_EX | FPEXC_FP2V)) +- return; ++ goto exit; + + /* + * The barrier() here prevents fpinst2 being read +@@ -310,6 +310,8 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) + exceptions = vfp_emulate_instruction(trigger, orig_fpscr, regs); + if (exceptions) + vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs); ++ exit: ++ preempt_enable(); + } + + static void vfp_enable(void *unused) |