Module: xenomai-2.6
Branch: master
Commit: 5c17a0a5c9ddd6110fb334bb3a330bf2b8420133
URL:    
http://git.xenomai.org/?p=xenomai-2.6.git;a=commit;h=5c17a0a5c9ddd6110fb334bb3a330bf2b8420133

Author: Philippe Gerum <r...@xenomai.org>
Date:   Tue Jan 22 12:04:23 2013 +0100

powerpc: upgrade I-pipe support

---

 ...c-2.patch => ipipe-core-3.2.21-powerpc-4.patch} |  127 ++++--
 ...pc-2.patch => ipipe-core-3.4.6-powerpc-4.patch} |  187 ++++++--
 ...pc-2.patch => ipipe-core-3.5.7-powerpc-3.patch} |  507 +++++++++++---------
 3 files changed, 502 insertions(+), 319 deletions(-)

diff --git a/ksrc/arch/powerpc/patches/ipipe-core-3.2.21-powerpc-2.patch 
b/ksrc/arch/powerpc/patches/ipipe-core-3.2.21-powerpc-4.patch
similarity index 99%
rename from ksrc/arch/powerpc/patches/ipipe-core-3.2.21-powerpc-2.patch
rename to ksrc/arch/powerpc/patches/ipipe-core-3.2.21-powerpc-4.patch
index 3ac7a2d..48c3f73 100644
--- a/ksrc/arch/powerpc/patches/ipipe-core-3.2.21-powerpc-2.patch
+++ b/ksrc/arch/powerpc/patches/ipipe-core-3.2.21-powerpc-4.patch
@@ -285,7 +285,7 @@ index bb712c9..8885e9b 100644
   * or should we not care like we do now ? --BenH.
 diff --git a/arch/powerpc/include/asm/ipipe.h 
b/arch/powerpc/include/asm/ipipe.h
 new file mode 100644
-index 0000000..62ac2ce
+index 0000000..c935bf8
 --- /dev/null
 +++ b/arch/powerpc/include/asm/ipipe.h
 @@ -0,0 +1,187 @@
@@ -337,7 +337,7 @@ index 0000000..62ac2ce
 +#include <asm/paca.h>
 +#endif
 +
-+#define IPIPE_CORE_RELEASE    2
++#define IPIPE_CORE_RELEASE    4
 +
 +struct ipipe_domain;
 +
@@ -889,7 +889,7 @@ index b0b06d8..cef2379 100644
  #ifdef CONFIG_IRQSOFF_TRACER
  /*
 diff --git a/arch/powerpc/include/asm/mmu_context.h 
b/arch/powerpc/include/asm/mmu_context.h
-index a73668a..e51b0e2 100644
+index a73668a..5eda09f 100644
 --- a/arch/powerpc/include/asm/mmu_context.h
 +++ b/arch/powerpc/include/asm/mmu_context.h
 @@ -36,15 +36,112 @@ extern void switch_cop(struct mm_struct *next);
@@ -1048,15 +1048,23 @@ index a73668a..e51b0e2 100644
  }
  
  #define deactivate_mm(tsk,mm) do { } while (0)
-@@ -99,7 +209,7 @@ static inline void activate_mm(struct mm_struct *prev, 
struct mm_struct *next)
+@@ -96,11 +206,15 @@ static inline void switch_mm(struct mm_struct *prev, 
struct mm_struct *next,
+  */
+ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
+ {
++#ifndef CONFIG_IPIPE
        unsigned long flags;
  
        local_irq_save(flags);
 -      switch_mm(prev, next, current);
++#endif
 +      __switch_mm(prev, next, current);
++#ifndef CONFIG_IPIPE
        local_irq_restore(flags);
++#endif
  }
  
+ /* We don't currently use enter_lazy_tlb() for anything */
 diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h
 index e6fae49..7a5f3ce 100644
 --- a/arch/powerpc/include/asm/mpic.h
@@ -5696,10 +5704,10 @@ index e6bb36a..898a91a 100644
  
 diff --git a/include/linux/ipipe.h b/include/linux/ipipe.h
 new file mode 100644
-index 0000000..f282637
+index 0000000..b8e628e
 --- /dev/null
 +++ b/include/linux/ipipe.h
-@@ -0,0 +1,399 @@
+@@ -0,0 +1,419 @@
 +/* -*- linux-c -*-
 + * include/linux/ipipe.h
 + *
@@ -5770,6 +5778,7 @@ index 0000000..f282637
 +void __ipipe_reenter_root(void);
 +
 +int __ipipe_disable_ondemand_mappings(struct task_struct *p);
++
 +int __ipipe_pin_vma(struct mm_struct *mm, struct vm_area_struct *vma);
 +
 +#ifdef CONFIG_IPIPE_WANT_PREEMPTIBLE_SWITCH
@@ -6002,31 +6011,50 @@ index 0000000..f282637
 +
 +static inline void ipipe_enable_irq(unsigned int irq)
 +{
-+      struct irq_desc *desc = irq_to_desc(irq);
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
++      struct irq_desc *desc;
++      struct irq_chip *chip;
++
++      desc = irq_to_desc(irq);
++      if (desc == NULL)
++              return;
++
++      chip = irq_desc_get_chip(desc);
 +
-+      if (WARN_ON_ONCE(chip->irq_unmask == NULL))
++      if (WARN_ON_ONCE(chip->irq_enable == NULL && chip->irq_unmask == NULL))
 +              return;
 +
-+      chip->irq_unmask(&desc->irq_data);
++      if (chip->irq_enable)
++              chip->irq_enable(&desc->irq_data);
++      else
++              chip->irq_unmask(&desc->irq_data);
 +}
 +
 +static inline void ipipe_disable_irq(unsigned int irq)
 +{
-+      struct irq_desc *desc = irq_to_desc(irq);
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
++      struct irq_desc *desc;
++      struct irq_chip *chip;
++
++      desc = irq_to_desc(irq);
++      if (desc == NULL)
++              return;
++
++      chip = irq_desc_get_chip(desc);
 +
-+      if (WARN_ON_ONCE(chip->irq_mask == NULL))
++      if (WARN_ON_ONCE(chip->irq_disable == NULL && chip->irq_mask == NULL))
 +              return;
 +
-+      chip->irq_mask(&desc->irq_data);
++      if (chip->irq_disable)
++              chip->irq_disable(&desc->irq_data);
++      else
++              chip->irq_mask(&desc->irq_data);
 +}
 +
 +static inline void ipipe_end_irq(unsigned int irq)
 +{
 +      struct irq_desc *desc = irq_to_desc(irq);
 +
-+      desc->ipipe_end(irq, desc);
++      if (desc)
++              desc->ipipe_end(irq, desc);
 +}
 +
 +static inline int ipipe_chained_irq_p(unsigned int irq)
@@ -8757,10 +8785,10 @@ index 0000000..1147bf4
 +}
 diff --git a/kernel/ipipe/core.c b/kernel/ipipe/core.c
 new file mode 100644
-index 0000000..1f32d4a
+index 0000000..19dfead
 --- /dev/null
 +++ b/kernel/ipipe/core.c
-@@ -0,0 +1,1706 @@
+@@ -0,0 +1,1729 @@
 +/* -*- linux-c -*-
 + * linux/kernel/ipipe/core.c
 + *
@@ -9825,25 +9853,50 @@ index 0000000..1f32d4a
 +{
 +}
 +
++#ifdef CONFIG_IPIPE_LEGACY
++
++static inline void complete_domain_migration(void) /* hw IRQs off */
++{
++      current->state &= ~TASK_HARDENING;
++}
++
++#else /* !CONFIG_IPIPE_LEGACY */
++
 +static void complete_domain_migration(void) /* hw IRQs off */
 +{
++      struct ipipe_percpu_domain_data *p;
 +      struct ipipe_percpu_data *pd;
-+      struct task_struct *p;
++      struct task_struct *t;
 +
++      ipipe_root_only();
 +      pd = __this_cpu_ptr(&ipipe_percpu);
-+      p = pd->task_hijacked;
-+      if (p) {
-+              p->state &= ~TASK_HARDENING;
-+              pd->task_hijacked = NULL;
-+              ipipe_migration_hook(p);
-+      }
++      t = pd->task_hijacked;
++      if (t == NULL)
++              return;
++
++      pd->task_hijacked = NULL;
++      t->state &= ~TASK_HARDENING;
++      if (t->state != TASK_INTERRUPTIBLE)
++              /* Migration aborted (by signal). */
++              return;
++
++      p = ipipe_this_cpu_head_context();
++      IPIPE_WARN_ONCE(test_bit(IPIPE_STALL_FLAG, &p->status));
++      /*
++       * hw IRQs are disabled, but the completion hook assumes the
++       * head domain is logically stalled: fix it up.
++       */
++      __set_bit(IPIPE_STALL_FLAG, &p->status);
++      ipipe_migration_hook(t);
++      __clear_bit(IPIPE_STALL_FLAG, &p->status);
 +}
 +
++#endif /* !CONFIG_IPIPE_LEGACY */
++
 +void __ipipe_complete_domain_migration(void)
 +{
 +      unsigned long flags;
 +
-+      ipipe_root_only();
 +      flags = hard_local_irq_save();
 +      complete_domain_migration();
 +      hard_local_irq_restore(flags);
@@ -9858,12 +9911,10 @@ index 0000000..1f32d4a
 +      hard_local_irq_disable();
 +#endif
 +      x = __ipipe_root_p;
-+
-+#ifdef CONFIG_IPIPE_LEGACY
-+      current->state &= ~TASK_HARDENING;
-+#else
-+      complete_domain_migration();
-+#endif        /* !CONFIG_IPIPE_LEGACY */
++#ifndef CONFIG_IPIPE_LEGACY
++      if (x)
++#endif
++              complete_domain_migration();
 +
 +#ifndef CONFIG_IPIPE_WANT_PREEMPTIBLE_SWITCH
 +      if (x)
@@ -10469,10 +10520,10 @@ index 0000000..1f32d4a
 +EXPORT_SYMBOL_GPL(__ipipe_post_work_root);
 diff --git a/kernel/ipipe/timer.c b/kernel/ipipe/timer.c
 new file mode 100644
-index 0000000..a2b8672
+index 0000000..d7d129a
 --- /dev/null
 +++ b/kernel/ipipe/timer.c
-@@ -0,0 +1,383 @@
+@@ -0,0 +1,393 @@
 +/* -*- linux-c -*-
 + * linux/kernel/ipipe/timer.c
 + *
@@ -10734,6 +10785,7 @@ index 0000000..a2b8672
 +{
 +      struct clock_event_device *evtdev;
 +      struct ipipe_timer *timer;
++      struct irq_desc *desc;
 +      unsigned long flags;
 +      int steal, rc;
 +
@@ -10774,6 +10826,10 @@ index 0000000..a2b8672
 +  done:
 +      ipipe_critical_exit(flags);
 +
++      desc = irq_to_desc(timer->irq);
++      if (desc && irqd_irq_disabled(&desc->irq_data))
++              ipipe_enable_irq(timer->irq);
++
 +      return rc;
 +}
 +
@@ -10781,11 +10837,16 @@ index 0000000..a2b8672
 +{
 +      struct clock_event_device *evtdev;
 +      struct ipipe_timer *timer;
++      struct irq_desc *desc;
 +      unsigned long flags;
 +
 +      timer = per_cpu(percpu_timer, cpu);
 +      evtdev = timer->host_timer;
 +
++      desc = irq_to_desc(timer->irq);
++      if (desc && irqd_irq_disabled(&desc->irq_data))
++              ipipe_disable_irq(timer->irq);
++
 +      flags = ipipe_critical_enter(NULL);
 +
 +#ifdef CONFIG_GENERIC_CLOCKEVENTS
diff --git a/ksrc/arch/powerpc/patches/ipipe-core-3.4.6-powerpc-2.patch 
b/ksrc/arch/powerpc/patches/ipipe-core-3.4.6-powerpc-4.patch
similarity index 99%
rename from ksrc/arch/powerpc/patches/ipipe-core-3.4.6-powerpc-2.patch
rename to ksrc/arch/powerpc/patches/ipipe-core-3.4.6-powerpc-4.patch
index cbded48..2fccba3 100644
--- a/ksrc/arch/powerpc/patches/ipipe-core-3.4.6-powerpc-2.patch
+++ b/ksrc/arch/powerpc/patches/ipipe-core-3.4.6-powerpc-4.patch
@@ -262,7 +262,7 @@ index 907e9fd..93f7996 100644
   * or should we not care like we do now ? --BenH.
 diff --git a/arch/powerpc/include/asm/ipipe.h 
b/arch/powerpc/include/asm/ipipe.h
 new file mode 100644
-index 0000000..e4bb785
+index 0000000..d9b52b9
 --- /dev/null
 +++ b/arch/powerpc/include/asm/ipipe.h
 @@ -0,0 +1,185 @@
@@ -307,7 +307,7 @@ index 0000000..e4bb785
 +#include <linux/cache.h>
 +#include <linux/threads.h>
 +
-+#define IPIPE_CORE_RELEASE    2
++#define IPIPE_CORE_RELEASE    4
 +
 +struct ipipe_domain;
 +
@@ -851,7 +851,7 @@ index 0000000..2bc8217
 +
 +#endif /* !_ASM_POWERPC_IPIPE_HWIRQ_H */
 diff --git a/arch/powerpc/include/asm/mmu_context.h 
b/arch/powerpc/include/asm/mmu_context.h
-index a73668a..a8019f2 100644
+index a73668a..c4254a3 100644
 --- a/arch/powerpc/include/asm/mmu_context.h
 +++ b/arch/powerpc/include/asm/mmu_context.h
 @@ -36,15 +36,99 @@ extern void switch_cop(struct mm_struct *next);
@@ -999,7 +999,7 @@ index a73668a..a8019f2 100644
 +      __do_switch_mm(prev, next, tsk);
 +#endif /* !CONFIG_IPIPE_WANT_PREEMPTIBLE_SWITCH */
 +}
-+
+ 
 +/*
 + * switch_mm is the entry point called from the architecture independent
 + * code in kernel/sched.c.
@@ -1016,7 +1016,7 @@ index a73668a..a8019f2 100644
 +      hard_local_irq_restore(flags);
 +#endif /* !CONFIG_IPIPE_WANT_PREEMPTIBLE_SWITCH */
 +}
- 
++
 +/*
 + * ipipe_switch_mm_head is reserved to the head domain for switching
 + * mmu context.
@@ -1030,15 +1030,23 @@ index a73668a..a8019f2 100644
  }
  
  #define deactivate_mm(tsk,mm) do { } while (0)
-@@ -99,7 +221,7 @@ static inline void activate_mm(struct mm_struct *prev, 
struct mm_struct *next)
+@@ -96,11 +218,15 @@ static inline void switch_mm(struct mm_struct *prev, 
struct mm_struct *next,
+  */
+ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
+ {
++#ifndef CONFIG_IPIPE
        unsigned long flags;
  
        local_irq_save(flags);
 -      switch_mm(prev, next, current);
++#endif
 +      __switch_mm(prev, next, current);
++#ifndef CONFIG_IPIPE
        local_irq_restore(flags);
++#endif
  }
  
+ /* We don't currently use enter_lazy_tlb() for anything */
 diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h
 index c9f698a..cd4f633 100644
 --- a/arch/powerpc/include/asm/mpic.h
@@ -4774,17 +4782,45 @@ index 78a666d..20e9852 100644
          CPU idle is a generic framework for supporting software-controlled
          idle processor power management.  It includes modular cross-platform
 diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
-index d537431..cb1e915 100644
+index d537431..bf54642 100644
 --- a/drivers/tty/serial/8250/8250.c
 +++ b/drivers/tty/serial/8250/8250.c
-@@ -3097,6 +3097,56 @@ static int serial8250_resume(struct platform_device 
*dev)
+@@ -3097,6 +3097,84 @@ static int serial8250_resume(struct platform_device 
*dev)
        return 0;
  }
  
 +#if defined(CONFIG_IPIPE_DEBUG) && defined(CONFIG_SERIAL_8250_CONSOLE)
 +
++static IPIPE_DEFINE_SPINLOCK(ipipe_8250_lock);
++
 +#include <stdarg.h>
 +
++static void wait_for_xmitr_nodelay(struct uart_8250_port *up, int bits)
++{
++      unsigned int status, tmout = 10000;
++
++      for (;;) {
++              status = serial_in(up, UART_LSR);
++
++              up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
++
++              if ((status & bits) == bits)
++                      break;
++              if (--tmout == 0)
++                      break;
++              cpu_relax();
++      }
++}
++
++static void serial8250_console_putchar_nodelay(struct uart_port *port, int ch)
++{
++      struct uart_8250_port *up =
++              container_of(port, struct uart_8250_port, port);
++
++      wait_for_xmitr_nodelay(up, UART_LSR_THRE);
++      serial_port_out(port, UART_TX, ch);
++}
++
 +void __weak __ipipe_serial_debug(const char *fmt, ...)
 +{
 +        struct uart_8250_port *up = &serial8250_ports[0];
@@ -4805,7 +4841,7 @@ index d537431..cb1e915 100644
 +
 +        touch_nmi_watchdog();
 +
-+        flags = hard_local_irq_save();
++        spin_lock_irqsave(&ipipe_8250_lock, flags);
 +
 +        /*
 +         *      First save the IER then disable the interrupts
@@ -4817,16 +4853,16 @@ index d537431..cb1e915 100644
 +        else
 +                serial_out(up, UART_IER, 0);
 +
-+        uart_console_write(&up->port, buf, count, serial8250_console_putchar);
++        uart_console_write(&up->port, buf, count, 
serial8250_console_putchar_nodelay);
 +
 +        /*
 +         *      Finally, wait for transmitter to become empty
 +         *      and restore the IER
 +         */
-+        wait_for_xmitr(up, BOTH_EMPTY);
++        wait_for_xmitr_nodelay(up, BOTH_EMPTY);
 +        serial_out(up, UART_IER, ier);
 +
-+        hard_local_irq_restore(flags);
++        spin_unlock_irqrestore(&ipipe_8250_lock, flags);
 +}
 +
 +#endif
@@ -5164,10 +5200,10 @@ index e6bb36a..898a91a 100644
  
 diff --git a/include/linux/ipipe.h b/include/linux/ipipe.h
 new file mode 100644
-index 0000000..a495bde
+index 0000000..ac0d19d
 --- /dev/null
 +++ b/include/linux/ipipe.h
-@@ -0,0 +1,406 @@
+@@ -0,0 +1,426 @@
 +/* -*- linux-c -*-
 + * include/linux/ipipe.h
 + *
@@ -5238,6 +5274,7 @@ index 0000000..a495bde
 +void __ipipe_reenter_root(void);
 +
 +int __ipipe_disable_ondemand_mappings(struct task_struct *p);
++
 +int __ipipe_pin_vma(struct mm_struct *mm, struct vm_area_struct *vma);
 +
 +#ifdef CONFIG_IPIPE_WANT_PREEMPTIBLE_SWITCH
@@ -5478,31 +5515,50 @@ index 0000000..a495bde
 +
 +static inline void ipipe_enable_irq(unsigned int irq)
 +{
-+      struct irq_desc *desc = irq_to_desc(irq);
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
++      struct irq_desc *desc;
++      struct irq_chip *chip;
 +
-+      if (WARN_ON_ONCE(chip->irq_unmask == NULL))
++      desc = irq_to_desc(irq);
++      if (desc == NULL)
 +              return;
 +
-+      chip->irq_unmask(&desc->irq_data);
++      chip = irq_desc_get_chip(desc);
++
++      if (WARN_ON_ONCE(chip->irq_enable == NULL && chip->irq_unmask == NULL))
++              return;
++
++      if (chip->irq_enable)
++              chip->irq_enable(&desc->irq_data);
++      else
++              chip->irq_unmask(&desc->irq_data);
 +}
 +
 +static inline void ipipe_disable_irq(unsigned int irq)
 +{
-+      struct irq_desc *desc = irq_to_desc(irq);
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
++      struct irq_desc *desc;
++      struct irq_chip *chip;
 +
-+      if (WARN_ON_ONCE(chip->irq_mask == NULL))
++      desc = irq_to_desc(irq);
++      if (desc == NULL)
 +              return;
 +
-+      chip->irq_mask(&desc->irq_data);
++      chip = irq_desc_get_chip(desc);
++
++      if (WARN_ON_ONCE(chip->irq_disable == NULL && chip->irq_mask == NULL))
++              return;
++
++      if (chip->irq_disable)
++              chip->irq_disable(&desc->irq_data);
++      else
++              chip->irq_mask(&desc->irq_data);
 +}
 +
 +static inline void ipipe_end_irq(unsigned int irq)
 +{
 +      struct irq_desc *desc = irq_to_desc(irq);
 +
-+      desc->ipipe_end(irq, desc);
++      if (desc)
++              desc->ipipe_end(irq, desc);
 +}
 +
 +static inline int ipipe_chained_irq_p(struct irq_desc *desc)
@@ -8325,10 +8381,10 @@ index 0000000..1147bf4
 +}
 diff --git a/kernel/ipipe/core.c b/kernel/ipipe/core.c
 new file mode 100644
-index 0000000..578468c
+index 0000000..d220c70
 --- /dev/null
 +++ b/kernel/ipipe/core.c
-@@ -0,0 +1,1706 @@
+@@ -0,0 +1,1730 @@
 +/* -*- linux-c -*-
 + * linux/kernel/ipipe/core.c
 + *
@@ -9393,25 +9449,50 @@ index 0000000..578468c
 +{
 +}
 +
++#ifdef CONFIG_IPIPE_LEGACY
++
++static inline void complete_domain_migration(void) /* hw IRQs off */
++{
++      current->state &= ~TASK_HARDENING;
++}
++
++#else /* !CONFIG_IPIPE_LEGACY */
++
 +static void complete_domain_migration(void) /* hw IRQs off */
 +{
++      struct ipipe_percpu_domain_data *p;
 +      struct ipipe_percpu_data *pd;
-+      struct task_struct *p;
++      struct task_struct *t;
 +
++      ipipe_root_only();
 +      pd = __this_cpu_ptr(&ipipe_percpu);
-+      p = pd->task_hijacked;
-+      if (p) {
-+              p->state &= ~TASK_HARDENING;
-+              pd->task_hijacked = NULL;
-+              ipipe_migration_hook(p);
-+      }
++      t = pd->task_hijacked;
++      if (t == NULL)
++              return;
++
++      pd->task_hijacked = NULL;
++      t->state &= ~TASK_HARDENING;
++      if (t->state != TASK_INTERRUPTIBLE)
++              /* Migration aborted (by signal). */
++              return;
++
++      p = ipipe_this_cpu_head_context();
++      IPIPE_WARN_ONCE(test_bit(IPIPE_STALL_FLAG, &p->status));
++      /*
++       * hw IRQs are disabled, but the completion hook assumes the
++       * head domain is logically stalled: fix it up.
++       */
++      __set_bit(IPIPE_STALL_FLAG, &p->status);
++      ipipe_migration_hook(t);
++      __clear_bit(IPIPE_STALL_FLAG, &p->status);
 +}
 +
++#endif /* !CONFIG_IPIPE_LEGACY */
++
 +void __ipipe_complete_domain_migration(void)
 +{
 +      unsigned long flags;
 +
-+      ipipe_root_only();
 +      flags = hard_local_irq_save();
 +      complete_domain_migration();
 +      hard_local_irq_restore(flags);
@@ -9426,12 +9507,10 @@ index 0000000..578468c
 +      hard_local_irq_disable();
 +#endif
 +      x = __ipipe_root_p;
-+
-+#ifdef CONFIG_IPIPE_LEGACY
-+      current->state &= ~TASK_HARDENING;
-+#else
-+      complete_domain_migration();
-+#endif        /* !CONFIG_IPIPE_LEGACY */
++#ifndef CONFIG_IPIPE_LEGACY
++      if (x)
++#endif
++              complete_domain_migration();
 +
 +#ifndef CONFIG_IPIPE_WANT_PREEMPTIBLE_SWITCH
 +      if (x)
@@ -9475,18 +9554,19 @@ index 0000000..578468c
 +      head->irqs[irq].handler(irq, head->irqs[irq].cookie);
 +      __ipipe_run_irqtail(irq);
 +      hard_local_irq_disable();
++      p = ipipe_this_cpu_head_context();
 +      __clear_bit(IPIPE_STALL_FLAG, &p->status);
 +
 +      /* Are we still running in the head domain? */
 +      if (likely(__ipipe_current_context == p)) {
 +              /* Did we enter this code over the head domain? */
-+              if (old == p) {
++              if (old->domain == head) {
 +                      /* Yes, do immediate synchronization. */
 +                      if (__ipipe_ipending_p(p))
 +                              __ipipe_sync_stage();
 +                      return;
 +              }
-+              __ipipe_set_current_context(old);
++              __ipipe_set_current_context(ipipe_this_cpu_root_context());
 +      }
 +
 +      /*
@@ -10037,10 +10117,10 @@ index 0000000..578468c
 +EXPORT_SYMBOL_GPL(__ipipe_post_work_root);
 diff --git a/kernel/ipipe/timer.c b/kernel/ipipe/timer.c
 new file mode 100644
-index 0000000..9a076ab
+index 0000000..4281cb1
 --- /dev/null
 +++ b/kernel/ipipe/timer.c
-@@ -0,0 +1,480 @@
+@@ -0,0 +1,483 @@
 +/* -*- linux-c -*-
 + * linux/kernel/ipipe/timer.c
 + *
@@ -10373,6 +10453,7 @@ index 0000000..9a076ab
 +{
 +      struct clock_event_device *evtdev;
 +      struct ipipe_timer *timer;
++      struct irq_desc *desc;
 +      unsigned long flags;
 +      int steal, ret;
 +
@@ -10412,10 +10493,10 @@ index 0000000..9a076ab
 +  done:
 +      ipipe_critical_exit(flags);
 +
-+#ifdef CONFIG_GENERIC_CLOCKEVENTS
-+      if (evtdev && evtdev->mode == CLOCK_EVT_MODE_UNUSED)
++      desc = irq_to_desc(timer->irq);
++      if (desc && irqd_irq_disabled(&desc->irq_data))
 +              ipipe_enable_irq(timer->irq);
-+#endif
++
 +      return ret;
 +}
 +
@@ -10424,15 +10505,17 @@ index 0000000..9a076ab
 +      unsigned long __maybe_unused flags;
 +      struct clock_event_device *evtdev;
 +      struct ipipe_timer *timer;
++      struct irq_desc *desc;
 +
 +      timer = per_cpu(percpu_timer, cpu);
 +      evtdev = timer->host_timer;
 +
++      desc = irq_to_desc(timer->irq);
++      if (desc && irqd_irq_disabled(&desc->irq_data))
++              ipipe_disable_irq(timer->irq);
++
 +#ifdef CONFIG_GENERIC_CLOCKEVENTS
 +      if (evtdev) {
-+              if (evtdev->mode == CLOCK_EVT_MODE_UNUSED)
-+                      ipipe_disable_irq(timer->irq);
-+
 +              flags = ipipe_critical_enter(NULL);
 +
 +              if (evtdev->ipipe_stolen) {
@@ -12629,7 +12712,7 @@ index b663c2c..a93d6fe 100644
  
  #ifdef CONFIG_A11Y_BRAILLE_CONSOLE
 diff --git a/kernel/sched/core.c b/kernel/sched/core.c
-index 817bf70..1494108 100644
+index 817bf70..a0f7815 100644
 --- a/kernel/sched/core.c
 +++ b/kernel/sched/core.c
 @@ -1501,7 +1501,9 @@ void scheduler_ipi(void)
@@ -12800,7 +12883,7 @@ index 817bf70..1494108 100644
  
        /*
         * The idle tasks have their own, simple scheduling class:
-@@ -8352,3 +8381,38 @@ struct cgroup_subsys cpuacct_subsys = {
+@@ -8352,3 +8381,40 @@ struct cgroup_subsys cpuacct_subsys = {
        .subsys_id = cpuacct_subsys_id,
  };
  #endif        /* CONFIG_CGROUP_CPUACCT */
@@ -12813,6 +12896,8 @@ index 817bf70..1494108 100644
 +
 +      preempt_disable();
 +
++      IPIPE_WARN_ONCE(__this_cpu_read(ipipe_percpu.task_hijacked) != NULL);
++
 +      __this_cpu_write(ipipe_percpu.task_hijacked, p);
 +      set_current_state(TASK_INTERRUPTIBLE | TASK_HARDENING);
 +      sched_submit_work(p);
diff --git a/ksrc/arch/powerpc/patches/ipipe-core-3.5.3-powerpc-2.patch 
b/ksrc/arch/powerpc/patches/ipipe-core-3.5.7-powerpc-3.patch
similarity index 97%
rename from ksrc/arch/powerpc/patches/ipipe-core-3.5.3-powerpc-2.patch
rename to ksrc/arch/powerpc/patches/ipipe-core-3.5.7-powerpc-3.patch
index 7a6ac8c..713ec3d 100644
--- a/ksrc/arch/powerpc/patches/ipipe-core-3.5.3-powerpc-2.patch
+++ b/ksrc/arch/powerpc/patches/ipipe-core-3.5.7-powerpc-3.patch
@@ -262,7 +262,7 @@ index 0554ab0..ec312e0 100644
   * or should we not care like we do now ? --BenH.
 diff --git a/arch/powerpc/include/asm/ipipe.h 
b/arch/powerpc/include/asm/ipipe.h
 new file mode 100644
-index 0000000..e4bb785
+index 0000000..4182870
 --- /dev/null
 +++ b/arch/powerpc/include/asm/ipipe.h
 @@ -0,0 +1,185 @@
@@ -307,7 +307,7 @@ index 0000000..e4bb785
 +#include <linux/cache.h>
 +#include <linux/threads.h>
 +
-+#define IPIPE_CORE_RELEASE    2
++#define IPIPE_CORE_RELEASE    3
 +
 +struct ipipe_domain;
 +
@@ -851,7 +851,7 @@ index 0000000..2bc8217
 +
 +#endif /* !_ASM_POWERPC_IPIPE_HWIRQ_H */
 diff --git a/arch/powerpc/include/asm/mmu_context.h 
b/arch/powerpc/include/asm/mmu_context.h
-index a73668a..a8019f2 100644
+index a73668a..c4254a3 100644
 --- a/arch/powerpc/include/asm/mmu_context.h
 +++ b/arch/powerpc/include/asm/mmu_context.h
 @@ -36,15 +36,99 @@ extern void switch_cop(struct mm_struct *next);
@@ -999,7 +999,7 @@ index a73668a..a8019f2 100644
 +      __do_switch_mm(prev, next, tsk);
 +#endif /* !CONFIG_IPIPE_WANT_PREEMPTIBLE_SWITCH */
 +}
-+
+ 
 +/*
 + * switch_mm is the entry point called from the architecture independent
 + * code in kernel/sched.c.
@@ -1016,7 +1016,7 @@ index a73668a..a8019f2 100644
 +      hard_local_irq_restore(flags);
 +#endif /* !CONFIG_IPIPE_WANT_PREEMPTIBLE_SWITCH */
 +}
- 
++
 +/*
 + * ipipe_switch_mm_head is reserved to the head domain for switching
 + * mmu context.
@@ -1030,15 +1030,23 @@ index a73668a..a8019f2 100644
  }
  
  #define deactivate_mm(tsk,mm) do { } while (0)
-@@ -99,7 +221,7 @@ static inline void activate_mm(struct mm_struct *prev, 
struct mm_struct *next)
+@@ -96,11 +218,15 @@ static inline void switch_mm(struct mm_struct *prev, 
struct mm_struct *next,
+  */
+ static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next)
+ {
++#ifndef CONFIG_IPIPE
        unsigned long flags;
  
        local_irq_save(flags);
 -      switch_mm(prev, next, current);
++#endif
 +      __switch_mm(prev, next, current);
++#ifndef CONFIG_IPIPE
        local_irq_restore(flags);
++#endif
  }
  
+ /* We don't currently use enter_lazy_tlb() for anything */
 diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h
 index c9f698a..cd4f633 100644
 --- a/arch/powerpc/include/asm/mpic.h
@@ -1448,7 +1456,7 @@ index ba3aeb4..bab7e1d 100644
   * PROM code for specific machines follows.  Put it
   * here so it's easy to add arch-specific sections later.
 diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
-index 5971c85..b42077d 100644
+index 8d2fa24..013f32e 100644
 --- a/arch/powerpc/kernel/entry_64.S
 +++ b/arch/powerpc/kernel/entry_64.S
 @@ -34,6 +34,12 @@
@@ -1562,7 +1570,7 @@ index 5971c85..b42077d 100644
        bl      .schedule_tail
        REST_NVGPRS(r1)
        li      r3,0
-@@ -538,6 +607,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
+@@ -549,6 +618,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
        addi    r1,r1,SWITCH_FRAME_SIZE
        blr
  
@@ -1577,7 +1585,7 @@ index 5971c85..b42077d 100644
        .align  7
  _GLOBAL(ret_from_except)
        ld      r11,_TRAP(r1)
-@@ -558,6 +635,16 @@ _GLOBAL(ret_from_except_lite)
+@@ -569,6 +646,16 @@ _GLOBAL(ret_from_except_lite)
        mtmsrd  r10,1             /* Update machine state */
  #endif /* CONFIG_PPC_BOOK3E */
  
@@ -1594,7 +1602,7 @@ index 5971c85..b42077d 100644
        clrrdi  r9,r1,THREAD_SHIFT      /* current_thread_info() */
        ld      r3,_MSR(r1)
        ld      r4,TI_FLAGS(r9)
-@@ -571,6 +658,9 @@ _GLOBAL(ret_from_except_lite)
+@@ -582,6 +669,9 @@ _GLOBAL(ret_from_except_lite)
        andi.   r0,r4,_TIF_NEED_RESCHED
        beq     1f
        bl      .restore_interrupts
@@ -1604,7 +1612,7 @@ index 5971c85..b42077d 100644
        bl      .schedule
        b       .ret_from_except_lite
  
-@@ -598,7 +688,12 @@ resume_kernel:
+@@ -609,7 +699,12 @@ resume_kernel:
         * sure we are soft-disabled first
         */
        SOFT_DISABLE_INTS(r3,r4)
@@ -1618,7 +1626,7 @@ index 5971c85..b42077d 100644
  
        /* Re-test flags and eventually loop */
        clrrdi  r9,r1,THREAD_SHIFT
-@@ -770,12 +865,20 @@ restore_check_irq_replay:
+@@ -781,12 +876,20 @@ restore_check_irq_replay:
        cmpwi   cr0,r3,0x500
        bne     1f
        addi    r3,r1,STACK_FRAME_OVERHEAD;
@@ -1639,7 +1647,7 @@ index 5971c85..b42077d 100644
        b       .ret_from_except
  #ifdef CONFIG_PPC_BOOK3E
  1:    cmpwi   cr0,r3,0x280
-@@ -1003,6 +1106,10 @@ _GLOBAL(_mcount)
+@@ -1014,6 +1117,10 @@ _GLOBAL(_mcount)
        blr
  
  _GLOBAL(ftrace_caller)
@@ -1650,7 +1658,7 @@ index 5971c85..b42077d 100644
        /* Taken from output of objdump from lib64/glibc */
        mflr    r3
        ld      r11, 0(r1)
-@@ -1030,6 +1137,10 @@ _GLOBAL(mcount)
+@@ -1041,6 +1148,10 @@ _GLOBAL(mcount)
        blr
  
  _GLOBAL(_mcount)
@@ -2639,7 +2647,7 @@ index 3e40315..269223f 100644
  #endif
  
 diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
-index 710f400..e8fe79b 100644
+index 1a1f2dd..18d073f 100644
 --- a/arch/powerpc/kernel/process.c
 +++ b/arch/powerpc/kernel/process.c
 @@ -102,8 +102,12 @@ EXPORT_SYMBOL_GPL(flush_fp_to_thread);
@@ -2681,7 +2689,7 @@ index 710f400..e8fe79b 100644
  
        return last;
  }
-@@ -1110,6 +1115,7 @@ static inline int valid_irq_stack(unsigned long sp, 
struct task_struct *p,
+@@ -1102,6 +1107,7 @@ static inline int valid_irq_stack(unsigned long sp, 
struct task_struct *p,
        return 0;
  }
  
@@ -2689,7 +2697,7 @@ index 710f400..e8fe79b 100644
  int validate_sp(unsigned long sp, struct task_struct *p,
                       unsigned long nbytes)
  {
-@@ -1121,6 +1127,13 @@ int validate_sp(unsigned long sp, struct task_struct *p,
+@@ -1113,6 +1119,13 @@ int validate_sp(unsigned long sp, struct task_struct *p,
  
        return valid_irq_stack(sp, p, nbytes);
  }
@@ -2753,7 +2761,7 @@ index 389bd4f..825cb22 100644
  #ifdef CONFIG_PPC_BOOK3E
  static void __init exc_lvl_early_init(void)
 diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
-index e4cb343..7f5563e 100644
+index 8d7c119..9f22096 100644
 --- a/arch/powerpc/kernel/smp.c
 +++ b/arch/powerpc/kernel/smp.c
 @@ -153,7 +153,7 @@ const char *smp_ipi_name[] = {
@@ -2780,7 +2788,7 @@ index e4cb343..7f5563e 100644
  #endif
        err = request_irq(virq, smp_ipi_action[msg],
                          IRQF_PERCPU | IRQF_NO_THREAD,
-@@ -270,8 +270,12 @@ void smp_send_debugger_break(void)
+@@ -277,8 +277,12 @@ void smp_send_debugger_break(void)
                return;
  
        for_each_online_cpu(cpu)
@@ -2907,7 +2915,7 @@ index be171ee..dbe985d 100644
  }
  
 diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
-index 1589723..abe9762 100644
+index ae0843f..14ac2f9 100644
 --- a/arch/powerpc/kernel/traps.c
 +++ b/arch/powerpc/kernel/traps.c
 @@ -661,6 +661,9 @@ void machine_check_exception(struct pt_regs *regs)
@@ -2957,7 +2965,7 @@ index 1589723..abe9762 100644
        if (notify_die(DIE_SSTEP, "single_step", regs, 5,
                                        5, SIGTRAP) == NOTIFY_STOP)
                return;
-@@ -994,6 +1008,9 @@ void __kprobes program_check_exception(struct pt_regs 
*regs)
+@@ -995,6 +1009,9 @@ void __kprobes program_check_exception(struct pt_regs 
*regs)
        /* We can now get here via a FP Unavailable exception if the core
         * has no FPU, in that case the reason flags will be 0 */
  
@@ -2967,7 +2975,7 @@ index 1589723..abe9762 100644
        if (reason & REASON_FP) {
                /* IEEE FP exception */
                parse_fpe(regs);
-@@ -1075,6 +1092,9 @@ void alignment_exception(struct pt_regs *regs)
+@@ -1076,6 +1093,9 @@ void alignment_exception(struct pt_regs *regs)
        if (!arch_irq_disabled_regs(regs))
                local_irq_enable();
  
@@ -2977,7 +2985,7 @@ index 1589723..abe9762 100644
        /* we don't implement logging of alignment exceptions */
        if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
                fixed = fix_alignment(regs);
-@@ -1112,6 +1132,8 @@ void nonrecoverable_exception(struct pt_regs *regs)
+@@ -1113,6 +1133,8 @@ void nonrecoverable_exception(struct pt_regs *regs)
  {
        printk(KERN_ERR "Non-recoverable exception at PC=%lx MSR=%lx\n",
               regs->nip, regs->msr);
@@ -2986,7 +2994,7 @@ index 1589723..abe9762 100644
        debugger(regs);
        die("nonrecoverable exception", regs, SIGKILL);
  }
-@@ -1127,11 +1149,16 @@ void kernel_fp_unavailable_exception(struct pt_regs 
*regs)
+@@ -1128,11 +1150,16 @@ void kernel_fp_unavailable_exception(struct pt_regs 
*regs)
  {
        printk(KERN_EMERG "Unrecoverable FP Unavailable Exception "
                          "%lx at %lx\n", regs->trap, regs->nip);
@@ -3003,7 +3011,7 @@ index 1589723..abe9762 100644
        if (user_mode(regs)) {
                /* A user program has executed an altivec instruction,
                   but this kernel doesn't support altivec. */
-@@ -1174,6 +1201,9 @@ void SoftwareEmulation(struct pt_regs *regs)
+@@ -1175,6 +1202,9 @@ void SoftwareEmulation(struct pt_regs *regs)
        int errcode;
  #endif
  
@@ -3013,7 +3021,7 @@ index 1589723..abe9762 100644
        CHECK_FULL_REGS(regs);
  
        if (!user_mode(regs)) {
-@@ -1287,6 +1317,9 @@ static void handle_debug(struct pt_regs *regs, unsigned 
long debug_status)
+@@ -1288,6 +1318,9 @@ static void handle_debug(struct pt_regs *regs, unsigned 
long debug_status)
  
  void __kprobes DebugException(struct pt_regs *regs, unsigned long 
debug_status)
  {
@@ -3023,7 +3031,7 @@ index 1589723..abe9762 100644
        current->thread.dbsr = debug_status;
  
        /* Hack alert: On BookE, Branch Taken stops on the branch itself, while
-@@ -1361,6 +1394,9 @@ void altivec_assist_exception(struct pt_regs *regs)
+@@ -1362,6 +1395,9 @@ void altivec_assist_exception(struct pt_regs *regs)
  {
        int err;
  
@@ -3033,7 +3041,7 @@ index 1589723..abe9762 100644
        if (!user_mode(regs)) {
                printk(KERN_EMERG "VMX/Altivec assist exception in kernel mode"
                       " at %lx\n", regs->nip);
-@@ -1413,8 +1449,11 @@ void CacheLockingException(struct pt_regs *regs, 
unsigned long address,
+@@ -1414,8 +1450,11 @@ void CacheLockingException(struct pt_regs *regs, 
unsigned long address,
         * as priv ops, in the future we could try to do
         * something smarter
         */
@@ -3046,7 +3054,7 @@ index 1589723..abe9762 100644
        return;
  }
  #endif /* CONFIG_FSL_BOOKE */
-@@ -1473,6 +1512,9 @@ void SPEFloatingPointRoundException(struct pt_regs *regs)
+@@ -1474,6 +1513,9 @@ void SPEFloatingPointRoundException(struct pt_regs *regs)
        extern int speround_handler(struct pt_regs *regs);
        int err;
  
@@ -3056,7 +3064,7 @@ index 1589723..abe9762 100644
        preempt_disable();
        if (regs->msr & MSR_SPE)
                giveup_spe(current);
-@@ -1510,6 +1552,8 @@ void unrecoverable_exception(struct pt_regs *regs)
+@@ -1511,6 +1553,8 @@ void unrecoverable_exception(struct pt_regs *regs)
  {
        printk(KERN_EMERG "Unrecoverable exception %lx at %lx\n",
               regs->trap, regs->nip);
@@ -4773,17 +4781,45 @@ index 78a666d..20e9852 100644
          CPU idle is a generic framework for supporting software-controlled
          idle processor power management.  It includes modular cross-platform
 diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
-index 6e1958a..2bb5d94 100644
+index 6e1958a..88bc148 100644
 --- a/drivers/tty/serial/8250/8250.c
 +++ b/drivers/tty/serial/8250/8250.c
-@@ -3055,6 +3055,56 @@ static int serial8250_resume(struct platform_device 
*dev)
+@@ -3055,6 +3055,84 @@ static int serial8250_resume(struct platform_device 
*dev)
        return 0;
  }
  
 +#if defined(CONFIG_IPIPE_DEBUG) && defined(CONFIG_SERIAL_8250_CONSOLE)
 +
++static IPIPE_DEFINE_SPINLOCK(ipipe_8250_lock);
++
 +#include <stdarg.h>
 +
++static void wait_for_xmitr_nodelay(struct uart_8250_port *up, int bits)
++{
++      unsigned int status, tmout = 10000;
++
++      for (;;) {
++              status = serial_in(up, UART_LSR);
++
++              up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
++
++              if ((status & bits) == bits)
++                      break;
++              if (--tmout == 0)
++                      break;
++              cpu_relax();
++      }
++}
++
++static void serial8250_console_putchar_nodelay(struct uart_port *port, int ch)
++{
++      struct uart_8250_port *up =
++              container_of(port, struct uart_8250_port, port);
++
++      wait_for_xmitr_nodelay(up, UART_LSR_THRE);
++      serial_port_out(port, UART_TX, ch);
++}
++
 +void __weak __ipipe_serial_debug(const char *fmt, ...)
 +{
 +        struct uart_8250_port *up = &serial8250_ports[0];
@@ -4804,7 +4840,7 @@ index 6e1958a..2bb5d94 100644
 +
 +        touch_nmi_watchdog();
 +
-+        flags = hard_local_irq_save();
++        spin_lock_irqsave(&ipipe_8250_lock, flags);
 +
 +        /*
 +         *      First save the IER then disable the interrupts
@@ -4816,16 +4852,16 @@ index 6e1958a..2bb5d94 100644
 +        else
 +                serial_out(up, UART_IER, 0);
 +
-+        uart_console_write(&up->port, buf, count, serial8250_console_putchar);
++        uart_console_write(&up->port, buf, count, 
serial8250_console_putchar_nodelay);
 +
 +        /*
 +         *      Finally, wait for transmitter to become empty
 +         *      and restore the IER
 +         */
-+        wait_for_xmitr(up, BOTH_EMPTY);
++        wait_for_xmitr_nodelay(up, BOTH_EMPTY);
 +        serial_out(up, UART_IER, ier);
 +
-+        hard_local_irq_restore(flags);
++        spin_unlock_irqrestore(&ipipe_8250_lock, flags);
 +}
 +
 +#endif
@@ -4980,6 +5016,20 @@ index 2533fdd..6559e2d 100644
        return prev;
  }
  
+diff --git a/include/asm-generic/mman-common.h 
b/include/asm-generic/mman-common.h
+index d030d2c..5612229 100644
+--- a/include/asm-generic/mman-common.h
++++ b/include/asm-generic/mman-common.h
+@@ -19,6 +19,9 @@
+ #define MAP_TYPE      0x0f            /* Mask for type of mapping */
+ #define MAP_FIXED     0x10            /* Interpret addr exactly */
+ #define MAP_ANONYMOUS 0x20            /* don't use a file */
++#ifndef MAP_BRK
++# define MAP_BRK      0
++#endif
+ #ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
+ # define MAP_UNINITIALIZED 0x4000000  /* For anonymous mmap, memory could be 
uninitialized */
+ #else
 diff --git a/include/asm-generic/percpu.h b/include/asm-generic/percpu.h
 index d17784e..d8e2912 100644
 --- a/include/asm-generic/percpu.h
@@ -5149,10 +5199,10 @@ index e6bb36a..898a91a 100644
  
 diff --git a/include/linux/ipipe.h b/include/linux/ipipe.h
 new file mode 100644
-index 0000000..fca32ac
+index 0000000..a04ec49
 --- /dev/null
 +++ b/include/linux/ipipe.h
-@@ -0,0 +1,411 @@
+@@ -0,0 +1,431 @@
 +/* -*- linux-c -*-
 + * include/linux/ipipe.h
 + *
@@ -5223,6 +5273,7 @@ index 0000000..fca32ac
 +void __ipipe_reenter_root(void);
 +
 +int __ipipe_disable_ondemand_mappings(struct task_struct *p);
++
 +int __ipipe_pin_vma(struct mm_struct *mm, struct vm_area_struct *vma);
 +
 +#ifdef CONFIG_IPIPE_WANT_PREEMPTIBLE_SWITCH
@@ -5468,31 +5519,50 @@ index 0000000..fca32ac
 +
 +static inline void ipipe_enable_irq(unsigned int irq)
 +{
-+      struct irq_desc *desc = irq_to_desc(irq);
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
++      struct irq_desc *desc;
++      struct irq_chip *chip;
++
++      desc = irq_to_desc(irq);
++      if (desc == NULL)
++              return;
++
++      chip = irq_desc_get_chip(desc);
 +
-+      if (WARN_ON_ONCE(chip->irq_unmask == NULL))
++      if (WARN_ON_ONCE(chip->irq_enable == NULL && chip->irq_unmask == NULL))
 +              return;
 +
-+      chip->irq_unmask(&desc->irq_data);
++      if (chip->irq_enable)
++              chip->irq_enable(&desc->irq_data);
++      else
++              chip->irq_unmask(&desc->irq_data);
 +}
 +
 +static inline void ipipe_disable_irq(unsigned int irq)
 +{
-+      struct irq_desc *desc = irq_to_desc(irq);
-+      struct irq_chip *chip = irq_desc_get_chip(desc);
++      struct irq_desc *desc;
++      struct irq_chip *chip;
++
++      desc = irq_to_desc(irq);
++      if (desc == NULL)
++              return;
++
++      chip = irq_desc_get_chip(desc);
 +
-+      if (WARN_ON_ONCE(chip->irq_mask == NULL))
++      if (WARN_ON_ONCE(chip->irq_disable == NULL && chip->irq_mask == NULL))
 +              return;
 +
-+      chip->irq_mask(&desc->irq_data);
++      if (chip->irq_disable)
++              chip->irq_disable(&desc->irq_data);
++      else
++              chip->irq_mask(&desc->irq_data);
 +}
 +
 +static inline void ipipe_end_irq(unsigned int irq)
 +{
 +      struct irq_desc *desc = irq_to_desc(irq);
 +
-+      desc->ipipe_end(irq, desc);
++      if (desc)
++              desc->ipipe_end(irq, desc);
 +}
 +
 +static inline int ipipe_chained_irq_p(struct irq_desc *desc)
@@ -7388,7 +7458,7 @@ index 9c9f049..62c894150 100644
  static inline void __raw_read_lock(rwlock_t *lock)
  {
 diff --git a/include/linux/sched.h b/include/linux/sched.h
-index 4a1f493..eb74259 100644
+index e63650f..beb101e 100644
 --- a/include/linux/sched.h
 +++ b/include/linux/sched.h
 @@ -62,6 +62,7 @@ struct sched_param {
@@ -7444,7 +7514,7 @@ index 4a1f493..eb74259 100644
  
  #define MMF_INIT_MASK         (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK)
  
-@@ -1516,6 +1537,10 @@ struct task_struct {
+@@ -1519,6 +1540,10 @@ struct task_struct {
        short pref_node_fork;
  #endif
        struct rcu_head rcu;
@@ -7455,7 +7525,7 @@ index 4a1f493..eb74259 100644
  
        /*
         * cache last used pipe for splice
-@@ -1798,6 +1823,10 @@ extern void thread_group_times(struct task_struct *p, 
cputime_t *ut, cputime_t *
+@@ -1801,6 +1826,10 @@ extern void thread_group_times(struct task_struct *p, 
cputime_t *ut, cputime_t *
  #define PF_MUTEX_TESTER       0x20000000      /* Thread belongs to the rt 
mutex tester */
  #define PF_FREEZER_SKIP       0x40000000      /* Freezer should not count it 
as freezable */
  
@@ -7730,10 +7800,10 @@ index a26e2fb..71348f2 100644
  
  #define arch_read_can_lock(lock)      (((void)(lock), 1))
 diff --git a/include/linux/time.h b/include/linux/time.h
-index c81c5e4..e82782a 100644
+index b51e664..c7d91b9 100644
 --- a/include/linux/time.h
 +++ b/include/linux/time.h
-@@ -126,6 +126,7 @@ struct timespec get_monotonic_coarse(void);
+@@ -151,6 +151,7 @@ struct timespec get_monotonic_coarse(void);
  void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim,
                                struct timespec *wtom, struct timespec *sleep);
  void timekeeping_inject_sleeptime(struct timespec *delta);
@@ -7819,7 +7889,7 @@ index 46ce8da..492e0e7 100644
        exit_shm(tsk);
        exit_files(tsk);
 diff --git a/kernel/fork.c b/kernel/fork.c
-index f00e319..fe4e0be 100644
+index f9d0499..234af7f 100644
 --- a/kernel/fork.c
 +++ b/kernel/fork.c
 @@ -315,6 +315,7 @@ static struct task_struct *dup_task_struct(struct 
task_struct *orig)
@@ -7919,7 +7989,7 @@ index 0000000..ce56a9c
 +       def_bool y if IPIPE_LEGACY
 diff --git a/kernel/ipipe/Kconfig.debug b/kernel/ipipe/Kconfig.debug
 new file mode 100644
-index 0000000..ba87335
+index 0000000..40c82a2
 --- /dev/null
 +++ b/kernel/ipipe/Kconfig.debug
 @@ -0,0 +1,95 @@
@@ -7949,8 +8019,8 @@ index 0000000..ba87335
 +config IPIPE_TRACE
 +      bool "Latency tracing"
 +      depends on IPIPE_DEBUG
-+      select ARCH_WANT_FRAME_POINTERS
-+      select FRAME_POINTER
++      select ARCH_WANT_FRAME_POINTERS if !ARM_UNWIND
++      select FRAME_POINTER if !ARM_UNWIND
 +      select KALLSYMS
 +      select PROC_FS
 +      ---help---
@@ -8303,10 +8373,10 @@ index 0000000..1147bf4
 +}
 diff --git a/kernel/ipipe/core.c b/kernel/ipipe/core.c
 new file mode 100644
-index 0000000..b0af234
+index 0000000..3bc6ef5
 --- /dev/null
 +++ b/kernel/ipipe/core.c
-@@ -0,0 +1,1705 @@
+@@ -0,0 +1,1733 @@
 +/* -*- linux-c -*-
 + * linux/kernel/ipipe/core.c
 + *
@@ -9157,7 +9227,9 @@ index 0000000..b0af234
 +      unsigned long flags;
 +      int ret = 0;
 +
++#ifndef CONFIG_IPIPE_LEGACY
 +      ipipe_root_only();
++#endif /* CONFIG_IPIPE_LEGACY */
 +
 +      if (handler == NULL ||
 +          (irq >= IPIPE_NR_XIRQS && !ipipe_virtual_irq_p(irq)))
@@ -9192,7 +9264,9 @@ index 0000000..b0af234
 +{
 +      unsigned long flags;
 +
++#ifndef CONFIG_IPIPE_LEGACY
 +      ipipe_root_only();
++#endif /* CONFIG_IPIPE_LEGACY */
 +
 +      spin_lock_irqsave(&__ipipe_lock, flags);
 +
@@ -9371,25 +9445,50 @@ index 0000000..b0af234
 +{
 +}
 +
++#ifdef CONFIG_IPIPE_LEGACY
++
++static inline void complete_domain_migration(void) /* hw IRQs off */
++{
++      current->state &= ~TASK_HARDENING;
++}
++
++#else /* !CONFIG_IPIPE_LEGACY */
++
 +static void complete_domain_migration(void) /* hw IRQs off */
 +{
++      struct ipipe_percpu_domain_data *p;
 +      struct ipipe_percpu_data *pd;
-+      struct task_struct *p;
++      struct task_struct *t;
 +
++      ipipe_root_only();
 +      pd = __this_cpu_ptr(&ipipe_percpu);
-+      p = pd->task_hijacked;
-+      if (p) {
-+              p->state &= ~TASK_HARDENING;
-+              pd->task_hijacked = NULL;
-+              ipipe_migration_hook(p);
-+      }
++      t = pd->task_hijacked;
++      if (t == NULL)
++              return;
++
++      pd->task_hijacked = NULL;
++      t->state &= ~TASK_HARDENING;
++      if (t->state != TASK_INTERRUPTIBLE)
++              /* Migration aborted (by signal). */
++              return;
++
++      p = ipipe_this_cpu_head_context();
++      IPIPE_WARN_ONCE(test_bit(IPIPE_STALL_FLAG, &p->status));
++      /*
++       * hw IRQs are disabled, but the completion hook assumes the
++       * head domain is logically stalled: fix it up.
++       */
++      __set_bit(IPIPE_STALL_FLAG, &p->status);
++      ipipe_migration_hook(t);
++      __clear_bit(IPIPE_STALL_FLAG, &p->status);
 +}
 +
++#endif /* !CONFIG_IPIPE_LEGACY */
++
 +void __ipipe_complete_domain_migration(void)
 +{
 +      unsigned long flags;
 +
-+      ipipe_root_only();
 +      flags = hard_local_irq_save();
 +      complete_domain_migration();
 +      hard_local_irq_restore(flags);
@@ -9404,12 +9503,10 @@ index 0000000..b0af234
 +      hard_local_irq_disable();
 +#endif
 +      x = __ipipe_root_p;
-+
-+#ifdef CONFIG_IPIPE_LEGACY
-+      current->state &= ~TASK_HARDENING;
-+#else
-+      complete_domain_migration();
-+#endif        /* !CONFIG_IPIPE_LEGACY */
++#ifndef CONFIG_IPIPE_LEGACY
++      if (x)
++#endif
++              complete_domain_migration();
 +
 +#ifndef CONFIG_IPIPE_WANT_PREEMPTIBLE_SWITCH
 +      if (x)
@@ -9453,18 +9550,19 @@ index 0000000..b0af234
 +      head->irqs[irq].handler(irq, head->irqs[irq].cookie);
 +      __ipipe_run_irqtail(irq);
 +      hard_local_irq_disable();
++      p = ipipe_this_cpu_head_context();
 +      __clear_bit(IPIPE_STALL_FLAG, &p->status);
 +
 +      /* Are we still running in the head domain? */
 +      if (likely(__ipipe_current_context == p)) {
 +              /* Did we enter this code over the head domain? */
-+              if (old == p) {
++              if (old->domain == head) {
 +                      /* Yes, do immediate synchronization. */
 +                      if (__ipipe_ipending_p(p))
 +                              __ipipe_sync_stage();
 +                      return;
 +              }
-+              __ipipe_set_current_context(old);
++              __ipipe_set_current_context(ipipe_this_cpu_root_context());
 +      }
 +
 +      /*
@@ -10014,10 +10112,10 @@ index 0000000..b0af234
 +EXPORT_SYMBOL_GPL(__ipipe_post_work_root);
 diff --git a/kernel/ipipe/timer.c b/kernel/ipipe/timer.c
 new file mode 100644
-index 0000000..9a076ab
+index 0000000..4281cb1
 --- /dev/null
 +++ b/kernel/ipipe/timer.c
-@@ -0,0 +1,480 @@
+@@ -0,0 +1,483 @@
 +/* -*- linux-c -*-
 + * linux/kernel/ipipe/timer.c
 + *
@@ -10350,6 +10448,7 @@ index 0000000..9a076ab
 +{
 +      struct clock_event_device *evtdev;
 +      struct ipipe_timer *timer;
++      struct irq_desc *desc;
 +      unsigned long flags;
 +      int steal, ret;
 +
@@ -10389,10 +10488,10 @@ index 0000000..9a076ab
 +  done:
 +      ipipe_critical_exit(flags);
 +
-+#ifdef CONFIG_GENERIC_CLOCKEVENTS
-+      if (evtdev && evtdev->mode == CLOCK_EVT_MODE_UNUSED)
++      desc = irq_to_desc(timer->irq);
++      if (desc && irqd_irq_disabled(&desc->irq_data))
 +              ipipe_enable_irq(timer->irq);
-+#endif
++
 +      return ret;
 +}
 +
@@ -10401,15 +10500,17 @@ index 0000000..9a076ab
 +      unsigned long __maybe_unused flags;
 +      struct clock_event_device *evtdev;
 +      struct ipipe_timer *timer;
++      struct irq_desc *desc;
 +
 +      timer = per_cpu(percpu_timer, cpu);
 +      evtdev = timer->host_timer;
 +
++      desc = irq_to_desc(timer->irq);
++      if (desc && irqd_irq_disabled(&desc->irq_data))
++              ipipe_disable_irq(timer->irq);
++
 +#ifdef CONFIG_GENERIC_CLOCKEVENTS
 +      if (evtdev) {
-+              if (evtdev->mode == CLOCK_EVT_MODE_UNUSED)
-+                      ipipe_disable_irq(timer->irq);
-+
 +              flags = ipipe_critical_enter(NULL);
 +
 +              if (evtdev->ipipe_stolen) {
@@ -11947,7 +12048,7 @@ index 0000000..1d9997a
 +#endif /* CONFIG_IPIPE_TRACE_MCOUNT */
 +}
 diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
-index eebd6d5..60f9f14 100644
+index eebd6d5..c5433eb 100644
 --- a/kernel/irq/chip.c
 +++ b/kernel/irq/chip.c
 @@ -15,6 +15,7 @@
@@ -12080,7 +12181,7 @@ index eebd6d5..60f9f14 100644
  }
  
  /**
-@@ -615,17 +646,133 @@ void handle_percpu_devid_irq(unsigned int irq, struct 
irq_desc *desc)
+@@ -615,17 +646,134 @@ void handle_percpu_devid_irq(unsigned int irq, struct 
irq_desc *desc)
  
        kstat_incr_irqs_this_cpu(irq, desc);
  
@@ -12210,11 +12311,12 @@ index eebd6d5..60f9f14 100644
 +}
 +
 +#endif /* !CONFIG_IPIPE */
++EXPORT_SYMBOL_GPL(__fixup_irq_handler);
 +
  void
  __irq_set_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
                  const char *name)
-@@ -643,6 +790,8 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t 
handle, int is_chained,
+@@ -643,6 +791,8 @@ __irq_set_handler(unsigned int irq, irq_flow_handler_t 
handle, int is_chained,
                        goto out;
        }
  
@@ -12597,7 +12699,7 @@ index 146827f..8927a03 100644
  
  #ifdef CONFIG_A11Y_BRAILLE_CONSOLE
 diff --git a/kernel/sched/core.c b/kernel/sched/core.c
-index 468bdd4..ec38567 100644
+index 9f81a3a..f8c95cf 100644
 --- a/kernel/sched/core.c
 +++ b/kernel/sched/core.c
 @@ -1499,7 +1499,9 @@ void scheduler_ipi(void)
@@ -12667,7 +12769,7 @@ index 468bdd4..ec38567 100644
  }
  
  /*
-@@ -3242,6 +3255,7 @@ notrace unsigned long get_parent_ip(unsigned long addr)
+@@ -3248,6 +3261,7 @@ notrace unsigned long get_parent_ip(unsigned long addr)
  
  void __kprobes add_preempt_count(int val)
  {
@@ -12675,7 +12777,7 @@ index 468bdd4..ec38567 100644
  #ifdef CONFIG_DEBUG_PREEMPT
        /*
         * Underflow?
-@@ -3310,6 +3324,7 @@ static noinline void __schedule_bug(struct task_struct 
*prev)
+@@ -3316,6 +3330,7 @@ static noinline void __schedule_bug(struct task_struct 
*prev)
   */
  static inline void schedule_debug(struct task_struct *prev)
  {
@@ -12683,7 +12785,7 @@ index 468bdd4..ec38567 100644
        /*
         * Test if we are atomic. Since do_exit() needs to call into
         * schedule() atomically, we ignore that path for now.
-@@ -3362,7 +3377,7 @@ pick_next_task(struct rq *rq)
+@@ -3368,7 +3383,7 @@ pick_next_task(struct rq *rq)
  /*
   * __schedule() is the main scheduler function.
   */
@@ -12692,7 +12794,7 @@ index 468bdd4..ec38567 100644
  {
        struct task_struct *prev, *next;
        unsigned long *switch_count;
-@@ -3376,6 +3391,10 @@ need_resched:
+@@ -3382,6 +3397,10 @@ need_resched:
        rcu_note_context_switch(cpu);
        prev = rq->curr;
  
@@ -12703,7 +12805,7 @@ index 468bdd4..ec38567 100644
        schedule_debug(prev);
  
        if (sched_feat(HRTICK))
-@@ -3422,7 +3441,8 @@ need_resched:
+@@ -3428,7 +3447,8 @@ need_resched:
                rq->curr = next;
                ++*switch_count;
  
@@ -12713,7 +12815,7 @@ index 468bdd4..ec38567 100644
                /*
                 * The context switch have flipped the stack from under us
                 * and restored the local variables which were saved when
-@@ -3431,14 +3451,18 @@ need_resched:
+@@ -3437,14 +3457,18 @@ need_resched:
                 */
                cpu = smp_processor_id();
                rq = cpu_rq(cpu);
@@ -12733,7 +12835,7 @@ index 468bdd4..ec38567 100644
  }
  
  static inline void sched_submit_work(struct task_struct *tsk)
-@@ -3538,7 +3562,8 @@ asmlinkage void __sched notrace preempt_schedule(void)
+@@ -3544,7 +3568,8 @@ asmlinkage void __sched notrace preempt_schedule(void)
  
        do {
                add_preempt_count_notrace(PREEMPT_ACTIVE);
@@ -12743,7 +12845,7 @@ index 468bdd4..ec38567 100644
                sub_preempt_count_notrace(PREEMPT_ACTIVE);
  
                /*
-@@ -3601,6 +3626,8 @@ static void __wake_up_common(wait_queue_head_t *q, 
unsigned int mode,
+@@ -3607,6 +3632,8 @@ static void __wake_up_common(wait_queue_head_t *q, 
unsigned int mode,
  {
        wait_queue_t *curr, *next;
  
@@ -12752,7 +12854,7 @@ index 468bdd4..ec38567 100644
        list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
                unsigned flags = curr->flags;
  
-@@ -4379,6 +4406,7 @@ recheck:
+@@ -4385,6 +4412,7 @@ recheck:
        oldprio = p->prio;
        prev_class = p->sched_class;
        __setscheduler(rq, p, policy, param->sched_priority);
@@ -12760,7 +12862,7 @@ index 468bdd4..ec38567 100644
  
        if (running)
                p->sched_class->set_curr_task(rq);
-@@ -5126,6 +5154,7 @@ void __cpuinit init_idle(struct task_struct *idle, int 
cpu)
+@@ -5132,6 +5160,7 @@ void __cpuinit init_idle(struct task_struct *idle, int 
cpu)
  
        /* Set the preempt count _outside_ the spinlocks! */
        task_thread_info(idle)->preempt_count = 0;
@@ -12768,7 +12870,7 @@ index 468bdd4..ec38567 100644
  
        /*
         * The idle tasks have their own, simple scheduling class:
-@@ -8513,3 +8542,38 @@ struct cgroup_subsys cpuacct_subsys = {
+@@ -8559,3 +8588,40 @@ struct cgroup_subsys cpuacct_subsys = {
        .base_cftypes = files,
  };
  #endif        /* CONFIG_CGROUP_CPUACCT */
@@ -12781,6 +12883,8 @@ index 468bdd4..ec38567 100644
 +
 +      preempt_disable();
 +
++      IPIPE_WARN_ONCE(__this_cpu_read(ipipe_percpu.task_hijacked) != NULL);
++
 +      __this_cpu_write(ipipe_percpu.task_hijacked, p);
 +      set_current_state(TASK_INTERRUPTIBLE | TASK_HARDENING);
 +      sched_submit_work(p);
@@ -12988,10 +13092,10 @@ index da6c9ec..0c4be00 100644
  }
  
 diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c
-index 4a08472..cc88827 100644
+index a057ed4..32138a1 100644
 --- a/kernel/time/tick-sched.c
 +++ b/kernel/time/tick-sched.c
-@@ -656,7 +656,7 @@ static void tick_nohz_handler(struct clock_event_device 
*dev)
+@@ -657,7 +657,7 @@ static void tick_nohz_handler(struct clock_event_device 
*dev)
                ts->idle_jiffies++;
        }
  
@@ -13000,7 +13104,7 @@ index 4a08472..cc88827 100644
        profile_tick(CPU_PROFILING);
  
        while (tick_nohz_reprogram(ts, now)) {
-@@ -813,7 +813,7 @@ static enum hrtimer_restart tick_sched_timer(struct 
hrtimer *timer)
+@@ -814,7 +814,7 @@ static enum hrtimer_restart tick_sched_timer(struct 
hrtimer *timer)
                        touch_softlockup_watchdog();
                        ts->idle_jiffies++;
                }
@@ -13010,10 +13114,10 @@ index 4a08472..cc88827 100644
        }
  
 diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
-index 3447cfa..08b892d 100644
+index 63c88c1..4779fb3 100644
 --- a/kernel/time/timekeeping.c
 +++ b/kernel/time/timekeeping.c
-@@ -1336,3 +1336,9 @@ void xtime_update(unsigned long ticks)
+@@ -1362,3 +1362,9 @@ void xtime_update(unsigned long ticks)
        do_timer(ticks);
        write_sequnlock(&xtime_lock);
  }
@@ -13193,8 +13297,20 @@ index 4c0d0e5..886125d 100644
                goto out;
  
        /*
+diff --git a/mm/Kconfig b/mm/Kconfig
+index 82fed4e..0ebccef 100644
+--- a/mm/Kconfig
++++ b/mm/Kconfig
+@@ -314,6 +314,7 @@ config NOMMU_INITIAL_TRIM_EXCESS
+ config TRANSPARENT_HUGEPAGE
+       bool "Transparent Hugepage Support"
+       depends on X86 && MMU
++      depends on !IPIPE
+       select COMPACTION
+       help
+         Transparent Hugepages allows the kernel to use huge pages and
 diff --git a/mm/memory.c b/mm/memory.c
-index 2466d12..ab93d65 100644
+index 2466d12..4230192 100644
 --- a/mm/memory.c
 +++ b/mm/memory.c
 @@ -822,6 +822,32 @@ out:
@@ -13271,7 +13387,7 @@ index 2466d12..ab93d65 100644
 +      struct page *uncow_page = NULL;
 +#ifdef CONFIG_IPIPE
 +      int do_cow_break = 0;
-+again:
+ again:
 +      if (do_cow_break) {
 +              uncow_page = alloc_page_vma(GFP_HIGHUSER, vma, addr);
 +              if (uncow_page == NULL)
@@ -13279,7 +13395,7 @@ index 2466d12..ab93d65 100644
 +              do_cow_break = 0;
 +      }
 +#else
- again:
++again:
 +#endif
        init_rss_vec(rss);
  
@@ -13353,92 +13469,13 @@ index 2466d12..ab93d65 100644
  /*
   * This routine handles present pages, when users try to write
   * to a shared page. It is done by copying the page to a new address
-@@ -4026,3 +4072,117 @@ void copy_user_huge_page(struct page *dst, struct page 
*src,
+@@ -4026,3 +4072,38 @@ void copy_user_huge_page(struct page *dst, struct page 
*src,
        }
  }
  #endif /* CONFIG_TRANSPARENT_HUGEPAGE || CONFIG_HUGETLBFS */
 +
 +#ifdef CONFIG_IPIPE
 +
-+static inline int ipipe_pin_pte_range(struct mm_struct *mm, pmd_t *pmd,
-+                                    struct vm_area_struct *vma,
-+                                    unsigned long addr, unsigned long end)
-+{
-+      spinlock_t *ptl;
-+      pte_t *pte;
-+
-+      do {
-+              pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
-+              if (!pte)
-+                      continue;
-+
-+              if (!pte_present(*pte) || pte_write(*pte)) {
-+                      pte_unmap_unlock(pte, ptl);
-+                      continue;
-+              }
-+
-+              if (do_wp_page(mm, vma, addr, pte, pmd, ptl, *pte) == 
VM_FAULT_OOM)
-+                      return -ENOMEM;
-+      } while (addr += PAGE_SIZE, addr != end);
-+      return 0;
-+}
-+
-+static inline int ipipe_pin_pmd_range(struct mm_struct *mm, pud_t *pud,
-+                                    struct vm_area_struct *vma,
-+                                    unsigned long addr, unsigned long end)
-+{
-+      unsigned long next;
-+      pmd_t *pmd;
-+
-+      pmd = pmd_offset(pud, addr);
-+      do {
-+              next = pmd_addr_end(addr, end);
-+              if (pmd_none_or_clear_bad(pmd))
-+                      continue;
-+              if (ipipe_pin_pte_range(mm, pmd, vma, addr, next))
-+                      return -ENOMEM;
-+      } while (pmd++, addr = next, addr != end);
-+      return 0;
-+}
-+
-+static inline int ipipe_pin_pud_range(struct mm_struct *mm, pgd_t *pgd,
-+                                    struct vm_area_struct *vma,
-+                                    unsigned long addr, unsigned long end)
-+{
-+      unsigned long next;
-+      pud_t *pud;
-+
-+      pud = pud_offset(pgd, addr);
-+      do {
-+              next = pud_addr_end(addr, end);
-+              if (pud_none_or_clear_bad(pud))
-+                      continue;
-+              if (ipipe_pin_pmd_range(mm, pud, vma, addr, next))
-+                      return -ENOMEM;
-+      } while (pud++, addr = next, addr != end);
-+      return 0;
-+}
-+
-+int __ipipe_pin_vma(struct mm_struct *mm, struct vm_area_struct *vma)
-+{
-+      unsigned long addr, next, end;
-+      pgd_t *pgd;
-+
-+      addr = vma->vm_start;
-+      end = vma->vm_end;
-+
-+      pgd = pgd_offset(mm, addr);
-+      do {
-+              next = pgd_addr_end(addr, end);
-+              if (pgd_none_or_clear_bad(pgd))
-+                      continue;
-+              if (ipipe_pin_pud_range(mm, pgd, vma, addr, next))
-+                      return -ENOMEM;
-+      } while (pgd++, addr = next, addr != end);
-+
-+      return 0;
-+}
-+
 +int __ipipe_disable_ondemand_mappings(struct task_struct *tsk)
 +{
 +      struct vm_area_struct *vma;
@@ -13471,6 +13508,45 @@ index 2466d12..ab93d65 100644
 +EXPORT_SYMBOL_GPL(__ipipe_disable_ondemand_mappings);
 +
 +#endif
+diff --git a/mm/mlock.c b/mm/mlock.c
+index ef726e8..158828b 100644
+--- a/mm/mlock.c
++++ b/mm/mlock.c
+@@ -624,3 +624,21 @@ void user_shm_unlock(size_t size, struct user_struct 
*user)
+       spin_unlock(&shmlock_user_lock);
+       free_uid(user);
+ }
++
++#ifdef CONFIG_IPIPE
++int __ipipe_pin_vma(struct mm_struct *mm, struct vm_area_struct *vma)
++{
++      int ret;
++
++      if (vma->vm_flags & (VM_IO | VM_PFNMAP))
++              return 0;
++
++      if (!((vma->vm_flags & (VM_DONTEXPAND | VM_RESERVED)) ||
++          is_vm_hugetlb_page(vma) || vma == get_gate_vma(mm))) {
++              ret = __mlock_vma_pages_range(vma, vma->vm_start, vma->vm_end,
++                                            NULL);
++              return (ret < 0) ? ret : 0;
++      } else
++              return make_pages_present(vma->vm_start, vma->vm_end);
++}
++#endif
+diff --git a/mm/mmap.c b/mm/mmap.c
+index fa1f274..a715aeb 100644
+--- a/mm/mmap.c
++++ b/mm/mmap.c
+@@ -2174,7 +2174,7 @@ static unsigned long do_brk(unsigned long addr, unsigned 
long len)
+ 
+       flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
+ 
+-      error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED);
++      error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED | MAP_BRK);
+       if (error & ~PAGE_MASK)
+               return error;
+ 
 diff --git a/mm/mmu_context.c b/mm/mmu_context.c
 index 3dcfaf4..e4ac923 100644
 --- a/mm/mmu_context.c
@@ -13496,61 +13572,22 @@ index 3dcfaf4..e4ac923 100644
  
        if (active_mm != mm)
 diff --git a/mm/mprotect.c b/mm/mprotect.c
-index a409926..195b91e 100644
+index a409926..057b1d8 100644
 --- a/mm/mprotect.c
 +++ b/mm/mprotect.c
-@@ -147,6 +147,7 @@ mprotect_fixup(struct vm_area_struct *vma, struct 
vm_area_struct **pprev,
- {
-       struct mm_struct *mm = vma->vm_mm;
-       unsigned long oldflags = vma->vm_flags;
-+      unsigned long protflags;
-       long nrpages = (end - start) >> PAGE_SHIFT;
-       unsigned long charged = 0;
-       pgoff_t pgoff;
-@@ -205,8 +206,17 @@ success:
-        * held in write mode.
-        */
-       vma->vm_flags = newflags;
-+      protflags = newflags;
-+#ifdef CONFIG_IPIPE
-+      /*
-+       * Enforce non-COW vm_page_prot by faking VM_SHARED on locked regions.
-+       */
-+      if (test_bit(MMF_VM_PINNED, &mm->flags) &&
-+          ((vma->vm_flags | mm->def_flags) & VM_LOCKED))
-+              protflags |= VM_SHARED;
-+#endif
-       vma->vm_page_prot = pgprot_modify(vma->vm_page_prot,
--                                        vm_get_page_prot(newflags));
-+                                        vm_get_page_prot(protflags));
- 
-       if (vma_wants_writenotify(vma)) {
-               vma->vm_page_prot = vm_get_page_prot(newflags & ~VM_SHARED);
-@@ -214,6 +224,24 @@ success:
-       }
- 
-       mmu_notifier_invalidate_range_start(mm, start, end);
+@@ -218,6 +218,12 @@ success:
+               hugetlb_change_protection(vma, start, end, vma->vm_page_prot);
+       else
+               change_protection(vma, start, end, vma->vm_page_prot, 
dirty_accountable);
 +#ifdef CONFIG_IPIPE
-+      /*
-+       * Privatize potential COW pages
-+       */
 +      if (test_bit(MMF_VM_PINNED, &mm->flags) &&
-+          (((vma->vm_flags | mm->def_flags) & (VM_LOCKED | VM_WRITE)) ==
-+           (VM_LOCKED | VM_WRITE))) {
-+              error = __ipipe_pin_vma(mm, vma);
-+              if (error)
-+                      /*
-+                       * OOM. Just revert the fake VM_SHARED so that the
-+                       * zero page cannot be overwritten.
-+                       */
-+                      vma->vm_page_prot =
-+                              pgprot_modify(vma->vm_page_prot,
-+                                            vm_get_page_prot(newflags));
-+      }
++          ((vma->vm_flags | mm->def_flags) & VM_LOCKED) &&
++          (vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC)))
++              __ipipe_pin_vma(mm, vma);
 +#endif
-       if (is_vm_hugetlb_page(vma))
-               hugetlb_change_protection(vma, start, end, vma->vm_page_prot);
-       else
+       mmu_notifier_invalidate_range_end(mm, start, end);
+       vm_stat_account(mm, oldflags, vma->vm_file, -nrpages);
+       vm_stat_account(mm, newflags, vma->vm_file, nrpages);
 diff --git a/mm/vmalloc.c b/mm/vmalloc.c
 index 2aad499..52aaaf7 100644
 --- a/mm/vmalloc.c


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
http://www.xenomai.org/mailman/listinfo/xenomai-git

Reply via email to