aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin
diff options
context:
space:
mode:
authorPhilippe Gerum <rpm@xenomai.org>2011-03-17 02:15:24 -0400
committerMike Frysinger <vapier@gentoo.org>2011-03-18 04:01:11 -0400
commit9169b51f8ce6cd11cd19913b54466ec11e6a12f9 (patch)
tree79d6537878aefeb5c6b766971b717358a2ee1513 /arch/blackfin
parent5b5da4c4b843e0d84244472b72fe1e7500f5681f (diff)
Blackfin/ipipe: fix deferred pipeline sync for the root stage
This patch makes sure to sync the pipeline for the root stage only from the outer interrupt level, when resuming kernel code after an interrupt. This fixes a bug causing EVT15 to be spuriously popped off upon nested interrupts, which in turn would cause the preempted kernel code to resume without supervisor privileges. Signed-off-by: Philippe Gerum <rpm@xenomai.org> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin')
-rw-r--r--arch/blackfin/mach-common/entry.S11
-rw-r--r--arch/blackfin/mach-common/interrupt.S6
2 files changed, 14 insertions, 3 deletions
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index bc08c98d008d..4845d51e88a6 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -952,8 +952,17 @@ ENDPROC(_evt_up_evt14)
952#ifdef CONFIG_IPIPE 952#ifdef CONFIG_IPIPE
953 953
954_resume_kernel_from_int: 954_resume_kernel_from_int:
955 r1 = LO(~0x8000) (Z);
956 r1 = r0 & r1;
957 r0 = 1;
958 r0 = r1 - r0;
959 r2 = r1 & r0;
960 cc = r2 == 0;
961 /* Sync the root stage only from the outer interrupt level. */
962 if !cc jump .Lnosync;
955 r0.l = ___ipipe_sync_root; 963 r0.l = ___ipipe_sync_root;
956 r0.h = ___ipipe_sync_root; 964 r0.h = ___ipipe_sync_root;
965 [--sp] = reti;
957 [--sp] = rets; 966 [--sp] = rets;
958 [--sp] = ( r7:4, p5:3 ); 967 [--sp] = ( r7:4, p5:3 );
959 SP += -12; 968 SP += -12;
@@ -961,6 +970,8 @@ _resume_kernel_from_int:
961 SP += 12; 970 SP += 12;
962 ( r7:4, p5:3 ) = [sp++]; 971 ( r7:4, p5:3 ) = [sp++];
963 rets = [sp++]; 972 rets = [sp++];
973 reti = [sp++];
974.Lnosync:
964 rts 975 rts
965#elif defined(CONFIG_PREEMPT) 976#elif defined(CONFIG_PREEMPT)
966 977
diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S
index 2df37db3b49b..469ce7282dc8 100644
--- a/arch/blackfin/mach-common/interrupt.S
+++ b/arch/blackfin/mach-common/interrupt.S
@@ -274,16 +274,16 @@ ENDPROC(_evt_system_call)
274 * level to EVT14 to prepare the caller for a normal interrupt 274 * level to EVT14 to prepare the caller for a normal interrupt
275 * return through RTI. 275 * return through RTI.
276 * 276 *
277 * We currently use this facility in two occasions: 277 * We currently use this feature in two occasions:
278 * 278 *
279 * - to branch to __ipipe_irq_tail_hook as requested by a high 279 * - before branching to __ipipe_irq_tail_hook as requested by a high
280 * priority domain after the pipeline delivered an interrupt, 280 * priority domain after the pipeline delivered an interrupt,
281 * e.g. such as Xenomai, in order to start its rescheduling 281 * e.g. such as Xenomai, in order to start its rescheduling
282 * procedure, since we may not switch tasks when IRQ levels are 282 * procedure, since we may not switch tasks when IRQ levels are
283 * nested on the Blackfin, so we have to fake an interrupt return 283 * nested on the Blackfin, so we have to fake an interrupt return
284 * so that we may reschedule immediately. 284 * so that we may reschedule immediately.
285 * 285 *
286 * - to branch to sync_root_irqs, in order to play any interrupt 286 * - before branching to __ipipe_sync_root(), in order to play any interrupt
287 * pending for the root domain (i.e. the Linux kernel). This lowers 287 * pending for the root domain (i.e. the Linux kernel). This lowers
288 * the core priority level enough so that Linux IRQ handlers may 288 * the core priority level enough so that Linux IRQ handlers may
289 * never delay interrupts handled by high priority domains; we defer 289 * never delay interrupts handled by high priority domains; we defer