Blackfin/ipipe: fix deferred pipeline sync for the root stage
authorPhilippe Gerum <rpm@xenomai.org>
Thu, 17 Mar 2011 06:15:24 +0000 (02:15 -0400)
committerMike Frysinger <vapier@gentoo.org>
Fri, 18 Mar 2011 08:01:11 +0000 (04:01 -0400)
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>
arch/blackfin/mach-common/entry.S
arch/blackfin/mach-common/interrupt.S

index bc08c98..4845d51 100644 (file)
@@ -952,8 +952,17 @@ ENDPROC(_evt_up_evt14)
 #ifdef CONFIG_IPIPE
 
 _resume_kernel_from_int:
+       r1 = LO(~0x8000) (Z);
+       r1 = r0 & r1;
+       r0 = 1;
+       r0 = r1 - r0;
+       r2 = r1 & r0;
+       cc = r2 == 0;
+       /* Sync the root stage only from the outer interrupt level. */
+       if !cc jump .Lnosync;
        r0.l = ___ipipe_sync_root;
        r0.h = ___ipipe_sync_root;
+       [--sp] = reti;
        [--sp] = rets;
        [--sp] = ( r7:4, p5:3 );
        SP += -12;
@@ -961,6 +970,8 @@ _resume_kernel_from_int:
        SP += 12;
        ( r7:4, p5:3 ) = [sp++];
        rets = [sp++];
+       reti = [sp++];
+.Lnosync:
        rts
 #elif defined(CONFIG_PREEMPT)
 
index 2df37db..469ce72 100644 (file)
@@ -274,16 +274,16 @@ ENDPROC(_evt_system_call)
  * level to EVT14 to prepare the caller for a normal interrupt
  * return through RTI.
  *
- * We currently use this facility in two occasions:
+ * We currently use this feature in two occasions:
  *
- * - to branch to __ipipe_irq_tail_hook as requested by a high
+ * - before branching to __ipipe_irq_tail_hook as requested by a high
  *   priority domain after the pipeline delivered an interrupt,
  *   e.g. such as Xenomai, in order to start its rescheduling
  *   procedure, since we may not switch tasks when IRQ levels are
  *   nested on the Blackfin, so we have to fake an interrupt return
  *   so that we may reschedule immediately.
  *
- * - to branch to sync_root_irqs, in order to play any interrupt
+ * - before branching to __ipipe_sync_root(), in order to play any interrupt
  *   pending for the root domain (i.e. the Linux kernel). This lowers
  *   the core priority level enough so that Linux IRQ handlers may
  *   never delay interrupts handled by high priority domains; we defer