diff options
author | Philippe Gerum <rpm@xenomai.org> | 2011-03-17 02:15:24 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2011-03-18 04:01:11 -0400 |
commit | 9169b51f8ce6cd11cd19913b54466ec11e6a12f9 (patch) | |
tree | 79d6537878aefeb5c6b766971b717358a2ee1513 | |
parent | 5b5da4c4b843e0d84244472b72fe1e7500f5681f (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>
-rw-r--r-- | arch/blackfin/mach-common/entry.S | 11 | ||||
-rw-r--r-- | arch/blackfin/mach-common/interrupt.S | 6 |
2 files changed, 14 insertions, 3 deletions
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index bc08c98d008..4845d51e88a 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -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) diff --git a/arch/blackfin/mach-common/interrupt.S b/arch/blackfin/mach-common/interrupt.S index 2df37db3b49..469ce7282dc 100644 --- a/arch/blackfin/mach-common/interrupt.S +++ b/arch/blackfin/mach-common/interrupt.S @@ -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 |