diff options
author | Jim Quinlan <jim2101024@gmail.com> | 2013-11-27 15:34:50 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-03-20 08:46:15 -0400 |
commit | 71ca75888953166b72cf7a65b4c2b6a50fc0ce3b (patch) | |
tree | 3b74c1898d1c6772c7c23c9eab21d3b6a99c39c9 | |
parent | 2eddb708d83ead02b5d41c65bfb26bab5afc8210 (diff) |
MIPS: Make local_irq_disable macro safe for non-Mipsr2
For non-mipsr2 processors, the local_irq_disable contains an mfc0-mtc0
pair with instructions inbetween. With preemption enabled, this sequence
may get preempted and effect a stale value of CP0_STATUS when executing
the mtc0 instruction. This commit avoids this scenario by incrementing
the preempt count before the mfc0 and decrementing it after the mtc9.
[ralf@linux-mips.org: This patch is sorting out the part that were missed
by e97c5b6098 [MIPS: Make irqflags.h functions preempt-safe for non-mipsr2
cpus.] I also re-enabled the inclusion of <asm/asm-offsets.h> at the top
of <asm/asmmacro.h>].
Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
Cc: linux-mips@linux-mips.org
Cc: cernekee@gmail.com
Patchwork: https://patchwork.linux-mips.org/patch/6164/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/include/asm/asmmacro.h | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index 69a9a22d014a..4225e99bd7bf 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h | |||
@@ -9,6 +9,7 @@ | |||
9 | #define _ASM_ASMMACRO_H | 9 | #define _ASM_ASMMACRO_H |
10 | 10 | ||
11 | #include <asm/hazards.h> | 11 | #include <asm/hazards.h> |
12 | #include <asm/asm-offsets.h> | ||
12 | 13 | ||
13 | #ifdef CONFIG_32BIT | 14 | #ifdef CONFIG_32BIT |
14 | #include <asm/asmmacro-32.h> | 15 | #include <asm/asmmacro-32.h> |
@@ -54,11 +55,21 @@ | |||
54 | .endm | 55 | .endm |
55 | 56 | ||
56 | .macro local_irq_disable reg=t0 | 57 | .macro local_irq_disable reg=t0 |
58 | #ifdef CONFIG_PREEMPT | ||
59 | lw \reg, TI_PRE_COUNT($28) | ||
60 | addi \reg, \reg, 1 | ||
61 | sw \reg, TI_PRE_COUNT($28) | ||
62 | #endif | ||
57 | mfc0 \reg, CP0_STATUS | 63 | mfc0 \reg, CP0_STATUS |
58 | ori \reg, \reg, 1 | 64 | ori \reg, \reg, 1 |
59 | xori \reg, \reg, 1 | 65 | xori \reg, \reg, 1 |
60 | mtc0 \reg, CP0_STATUS | 66 | mtc0 \reg, CP0_STATUS |
61 | irq_disable_hazard | 67 | irq_disable_hazard |
68 | #ifdef CONFIG_PREEMPT | ||
69 | lw \reg, TI_PRE_COUNT($28) | ||
70 | addi \reg, \reg, -1 | ||
71 | sw \reg, TI_PRE_COUNT($28) | ||
72 | #endif | ||
62 | .endm | 73 | .endm |
63 | #endif /* CONFIG_MIPS_MT_SMTC */ | 74 | #endif /* CONFIG_MIPS_MT_SMTC */ |
64 | 75 | ||