From 5388fb1025443ec223ba556b10efc4c5f83f8682 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 11 Jan 2006 22:11:39 +1100 Subject: [PATCH] powerpc: Avoid potential FP corruption with preempt and UP Heikki Lindholm pointed out that there was a potential race with the lazy CPU state (FP, VR, EVR) stuff if preempt is enabled. The race is that in the process of restoring FP state on sigreturn, the task gets preempted by a user task that wants to use the FPU. It will take an FP unavailable exception, which will write the current FPU state to the thread_struct, overwriting the values which sigreturn has stored. Note that this can only happen on UP since we don't implement lazy CPU state on SMP. The fix is to flush the lazy CPU state before updating the thread_struct. To do this we re-use the flush_lazy_cpu_state() function from process.c. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/process.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/powerpc/kernel/process.c') diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 105d560..913f906 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -201,13 +201,13 @@ int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs) } #endif /* CONFIG_SPE */ +#ifndef CONFIG_SMP /* * If we are doing lazy switching of CPU state (FP, altivec or SPE), * and the current task has some state, discard it. */ -static inline void discard_lazy_cpu_state(void) +void discard_lazy_cpu_state(void) { -#ifndef CONFIG_SMP preempt_disable(); if (last_task_used_math == current) last_task_used_math = NULL; @@ -220,8 +220,8 @@ static inline void discard_lazy_cpu_state(void) last_task_used_spe = NULL; #endif preempt_enable(); -#endif /* CONFIG_SMP */ } +#endif /* CONFIG_SMP */ int set_dabr(unsigned long dabr) { -- cgit v1.1 From 624cee31bcb14bfd85559fbec5dd7bb833542965 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 12 Jan 2006 21:22:34 +1100 Subject: powerpc: make ARCH=ppc use arch/powerpc/kernel/process.c Commit 5388fb1025443ec223ba556b10efc4c5f83f8682 made signal_32.c use discard_lazy_cpu_state, which broke ARCH=ppc because that uses the common signal_32.c but has its own process.c. Make ARCH=ppc use the common process.c to fix this and to reduce the amount of duplicated code. Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/process.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/powerpc/kernel/process.c') diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 913f906..9101358 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -223,6 +223,7 @@ void discard_lazy_cpu_state(void) } #endif /* CONFIG_SMP */ +#ifdef CONFIG_PPC_MERGE /* XXX for now */ int set_dabr(unsigned long dabr) { if (ppc_md.set_dabr) @@ -231,6 +232,7 @@ int set_dabr(unsigned long dabr) mtspr(SPRN_DABR, dabr); return 0; } +#endif #ifdef CONFIG_PPC64 DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); -- cgit v1.1