Module: xenomai-3
Branch: wip/drivers
Commit: b88368afe7545b6900660785b1cb131d68e72839
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=b88368afe7545b6900660785b1cb131d68e72839

Author: Philippe Gerum <r...@xenomai.org>
Date:   Fri Sep  9 18:59:32 2016 +0200

cobalt/powerpc: upgrade I-pipe support

---

 ...-6.patch => ipipe-core-3.18.20-powerpc-8.patch} |   94 +-
 ...c-3.patch => ipipe-core-4.1.18-powerpc-7.patch} | 1133 +++++++++++++++-----
 2 files changed, 924 insertions(+), 303 deletions(-)

diff --git 
a/kernel/cobalt/arch/powerpc/patches/ipipe-core-3.18.20-powerpc-6.patch 
b/kernel/cobalt/arch/powerpc/patches/ipipe-core-3.18.20-powerpc-8.patch
similarity index 99%
rename from 
kernel/cobalt/arch/powerpc/patches/ipipe-core-3.18.20-powerpc-6.patch
rename to kernel/cobalt/arch/powerpc/patches/ipipe-core-3.18.20-powerpc-8.patch
index a3792aa..f92259f 100644
--- a/kernel/cobalt/arch/powerpc/patches/ipipe-core-3.18.20-powerpc-6.patch
+++ b/kernel/cobalt/arch/powerpc/patches/ipipe-core-3.18.20-powerpc-8.patch
@@ -304,7 +304,7 @@ index b59ac27..9cc1d25 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..f79050e
+index 0000000..40aca5b
 --- /dev/null
 +++ b/arch/powerpc/include/asm/ipipe.h
 @@ -0,0 +1,157 @@
@@ -349,7 +349,7 @@ index 0000000..f79050e
 +#include <linux/cache.h>
 +#include <linux/threads.h>
 +
-+#define IPIPE_CORE_RELEASE    6
++#define IPIPE_CORE_RELEASE    8
 +
 +struct ipipe_domain;
 +
@@ -1640,7 +1640,7 @@ index 22b45a4..e973007 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 0905c8d..df2cc87 100644
+index 0905c8d..f9293c9 100644
 --- a/arch/powerpc/kernel/entry_64.S
 +++ b/arch/powerpc/kernel/entry_64.S
 @@ -33,6 +33,7 @@
@@ -1879,25 +1879,21 @@ index 0905c8d..df2cc87 100644
  #endif /* CONFIG_PREEMPT */
  
        .globl  fast_exc_return_irq
-@@ -751,6 +806,17 @@ restore:
+@@ -751,6 +806,13 @@ restore:
         * are about to re-enable interrupts
         */
        ld      r5,SOFTE(r1)
 +#ifdef CONFIG_IPIPE
-+      cmpwi   cr0,r5,0
-+      nor     r5,r5,r5        /* IPIPE_STALL_FLAG = !SOFTE */
 +      ld      r4,PACAROOTPCPU(r13)
-+      ld      r3,0(r4)
-+      insrdi  r3,r5,1,63
-+      std     r3,0(r4)
-+      beq     1f
++      cmpwi   cr0,r4,0
++      bne     1f
 +      TRACE_ENABLE_INTS
 +1:
 +#else /* !CONFIG_IPIPE */
        lbz     r6,PACASOFTIRQEN(r13)
        cmpwi   cr0,r5,0
        beq     restore_irq_off
-@@ -777,6 +843,7 @@ restore_no_replay:
+@@ -777,6 +839,7 @@ restore_no_replay:
        TRACE_ENABLE_INTS
        li      r0,1
        stb     r0,PACASOFTIRQEN(r13);
@@ -1905,7 +1901,7 @@ index 0905c8d..df2cc87 100644
  
        /*
         * Final return path. BookE is handled in a different file
-@@ -867,6 +934,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
+@@ -867,6 +930,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
  
  #endif /* CONFIG_PPC_BOOK3E */
  
@@ -1913,7 +1909,7 @@ index 0905c8d..df2cc87 100644
        /*
         * We are returning to a context with interrupts soft disabled.
         *
-@@ -948,6 +1016,8 @@ restore_check_irq_replay:
+@@ -948,6 +1012,8 @@ restore_check_irq_replay:
        b       ret_from_except
  #endif /* CONFIG_PPC_DOORBELL */
  1:    b       ret_from_except /* What else to do here ? */
@@ -1922,7 +1918,7 @@ index 0905c8d..df2cc87 100644
   
  unrecov_restore:
        addi    r3,r1,STACK_FRAME_OVERHEAD
-@@ -994,7 +1064,7 @@ _GLOBAL(enter_rtas)
+@@ -994,7 +1060,7 @@ _GLOBAL(enter_rtas)
        li      r0,0
        mtcr    r0
  
@@ -2835,7 +2831,7 @@ index 0000000..292fed5
 +#endif        /* !CONFIG_PPC64 */
 +#endif /* !CONFIG_IPIPE_LEGACY */
 diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
-index c143835..6b92a8b 100644
+index c143835..82279ee 100644
 --- a/arch/powerpc/kernel/irq.c
 +++ b/arch/powerpc/kernel/irq.c
 @@ -95,6 +95,36 @@ extern int tau_interrupts(int);
@@ -2867,7 +2863,7 @@ index c143835..6b92a8b 100644
 +static inline notrace int decrementer_check_overflow(void)
 +{
 +      u64 now = get_tb_or_rtc();
-+      u64 *next_tb = &__get_cpu_var(decrementers_next_tb);
++      u64 *next_tb = this_cpu_ptr(&decrementers_next_tb);
 + 
 +      return now >= *next_tb;
 +}
@@ -6004,6 +6000,18 @@ index abcafaa..a8440e4 100644
  } ____cacheline_aligned;
  
  /*
+diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
+index 662697b..6a9b6ad 100644
+--- a/include/linux/ftrace.h
++++ b/include/linux/ftrace.h
+@@ -108,6 +108,7 @@ enum {
+       FTRACE_OPS_FL_ADDING                    = 1 << 9,
+       FTRACE_OPS_FL_REMOVING                  = 1 << 10,
+       FTRACE_OPS_FL_MODIFYING                 = 1 << 11,
++      FTRACE_OPS_FL_IPIPE_EXCLUSIVE           = 1 << 12,
+ };
+ 
+ #ifdef CONFIG_DYNAMIC_FTRACE
 diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
 index cba442e..b513a46 100644
 --- a/include/linux/hardirq.h
@@ -11949,7 +11957,7 @@ index 0000000..143f9e6
 +#endif /* CONFIG_IPIPE_HAVE_HOSTRT */
 diff --git a/kernel/ipipe/tracer.c b/kernel/ipipe/tracer.c
 new file mode 100644
-index 0000000..da272c50
+index 0000000..8388671
 --- /dev/null
 +++ b/kernel/ipipe/tracer.c
 @@ -0,0 +1,1468 @@
@@ -13287,7 +13295,7 @@ index 0000000..da272c50
 +
 +static struct ftrace_ops ipipe_trace_ops = {
 +      .func = ipipe_trace_function,
-+      .flags = FTRACE_OPS_FL_RECURSION_SAFE,
++      .flags = FTRACE_OPS_FL_IPIPE_EXCLUSIVE,
 +};
 +
 +static ssize_t __ipipe_wr_enable(struct file *file, const char __user *buffer,
@@ -14848,7 +14856,7 @@ index a5da09c..6650799 100644
        help
          This option will modify all the calls to function tracing
 diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
-index d1eff3d..2a324bc 100644
+index d1eff3d..f8b9472 100644
 --- a/kernel/trace/ftrace.c
 +++ b/kernel/trace/ftrace.c
 @@ -32,6 +32,7 @@
@@ -14859,7 +14867,33 @@ index d1eff3d..2a324bc 100644
  
  #include <trace/events/sched.h>
  
-@@ -2298,6 +2299,9 @@ void __weak arch_ftrace_update_code(int command)
+@@ -251,8 +252,17 @@ static inline void update_function_graph_func(void) { }
+ 
+ static void update_ftrace_function(void)
+ {
++      struct ftrace_ops *ops;
+       ftrace_func_t func;
+ 
++      for (ops = ftrace_ops_list;
++           ops != &ftrace_list_end; ops = ops->next)
++              if (ops->flags & FTRACE_OPS_FL_IPIPE_EXCLUSIVE) {
++                      set_function_trace_op = ops;
++                      func = ops->func;
++                      goto set_pointers;
++              }
++
+       /*
+        * Prepare the ftrace_ops that the arch callback will use.
+        * If there's only one ftrace_ops registered, the ftrace_ops_list
+@@ -280,6 +290,7 @@ static void update_ftrace_function(void)
+ 
+       update_function_graph_func();
+ 
++  set_pointers:
+       /* If there's no change, then do nothing more here */
+       if (ftrace_trace_function == func)
+               return;
+@@ -2298,6 +2309,9 @@ void __weak arch_ftrace_update_code(int command)
  
  static void ftrace_run_update_code(int command)
  {
@@ -14869,7 +14903,7 @@ index d1eff3d..2a324bc 100644
        int ret;
  
        ret = ftrace_arch_code_modify_prepare();
-@@ -2311,7 +2315,13 @@ static void ftrace_run_update_code(int command)
+@@ -2311,7 +2325,13 @@ static void ftrace_run_update_code(int command)
         * is safe. The stop_machine() is the safest, but also
         * produces the most overhead.
         */
@@ -14883,7 +14917,7 @@ index d1eff3d..2a324bc 100644
  
        ret = ftrace_arch_code_modify_post_process();
        FTRACE_WARN_ON(ret);
-@@ -4621,10 +4631,10 @@ static int ftrace_process_locs(struct module *mod,
+@@ -4621,10 +4641,10 @@ static int ftrace_process_locs(struct module *mod,
         * reason to cause large interrupt latencies while we do it.
         */
        if (!mod)
@@ -14896,7 +14930,7 @@ index d1eff3d..2a324bc 100644
        ret = 0;
   out:
        mutex_unlock(&ftrace_lock);
-@@ -4723,9 +4733,11 @@ void __init ftrace_init(void)
+@@ -4723,9 +4743,11 @@ void __init ftrace_init(void)
        unsigned long count, flags;
        int ret;
  
@@ -14910,7 +14944,7 @@ index d1eff3d..2a324bc 100644
        if (ret)
                goto failed;
  
-@@ -4891,7 +4903,16 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long 
parent_ip,
+@@ -4891,7 +4913,16 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long 
parent_ip,
                }
        } while_for_each_ftrace_op(op);
  out:
@@ -15276,24 +15310,22 @@ index 0c9216c..00a9a30 100644
        return err;
  }
 diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c
-index 1afec32..5803111 100644
+index 1afec32..f7c1a2a 100644
 --- a/lib/smp_processor_id.c
 +++ b/lib/smp_processor_id.c
-@@ -12,10 +12,13 @@ notrace static unsigned int 
check_preemption_disabled(const char *what1,
+@@ -12,6 +12,12 @@ notrace static unsigned int check_preemption_disabled(const 
char *what1,
  {
        int this_cpu = raw_smp_processor_id();
  
++      if (hard_irqs_disabled())
++              goto out;
++
 +      if (!ipipe_root_p)
 +              goto out;
 +
        if (likely(preempt_count()))
                goto out;
  
--      if (irqs_disabled())
-+      if (irqs_disabled() || hard_irqs_disabled())
-               goto out;
- 
-       /*
 diff --git a/mm/memory.c b/mm/memory.c
 index 90fb265..8a1fd79 100644
 --- a/mm/memory.c
diff --git 
a/kernel/cobalt/arch/powerpc/patches/ipipe-core-4.1.18-powerpc-3.patch 
b/kernel/cobalt/arch/powerpc/patches/ipipe-core-4.1.18-powerpc-7.patch
similarity index 94%
rename from kernel/cobalt/arch/powerpc/patches/ipipe-core-4.1.18-powerpc-3.patch
rename to kernel/cobalt/arch/powerpc/patches/ipipe-core-4.1.18-powerpc-7.patch
index c524961..49f4856 100644
--- a/kernel/cobalt/arch/powerpc/patches/ipipe-core-4.1.18-powerpc-3.patch
+++ b/kernel/cobalt/arch/powerpc/patches/ipipe-core-4.1.18-powerpc-7.patch
@@ -51,43 +51,44 @@ index 4eec430..c6a528b 100644
  ifeq ($(call cc-option-yn, -fstack-protector),y)
  BOOTCFLAGS    += -fno-stack-protector
  endif
+diff --git a/arch/powerpc/include/asm/exception-64e.h 
b/arch/powerpc/include/asm/exception-64e.h
+index a8b52b6..6df92057 100644
+--- a/arch/powerpc/include/asm/exception-64e.h
++++ b/arch/powerpc/include/asm/exception-64e.h
+@@ -11,6 +11,8 @@
+ #ifndef _ASM_POWERPC_EXCEPTION_64E_H
+ #define _ASM_POWERPC_EXCEPTION_64E_H
+ 
++#include <asm/irq_softstate.h>
++
+ /*
+  * SPRGs usage an other considerations...
+  *
 diff --git a/arch/powerpc/include/asm/exception-64s.h 
b/arch/powerpc/include/asm/exception-64s.h
-index 77f52b2..8eb3473 100644
+index 77f52b2..4650dc38 100644
 --- a/arch/powerpc/include/asm/exception-64s.h
 +++ b/arch/powerpc/include/asm/exception-64s.h
-@@ -332,6 +332,20 @@ do_kvm_##n:                                               
                \
-       GET_CTR(r10, area);                                                \
-       std     r10,_CTR(r1);
+@@ -35,6 +35,8 @@
+  * implementations as possible.
+  */
  
-+#ifdef CONFIG_IPIPE
-+/* Do NOT alter Rc(eq) in this code;  our caller uses it. */
-+#define COPY_SOFTISTATE(mreg)                 \
-+      ld      mreg,PACAROOTPCPU(r13);         \
-+      ld      mreg,0(mreg);                   \
-+      nor     mreg,mreg,mreg;                 \
-+      clrldi  mreg,mreg,63;                   \
-+      std     mreg,SOFTE(r1)
-+#else /* !CONFIG_IPIPE */
-+#define COPY_SOFTISTATE(mreg)                 \
-+      lbz     mreg,PACASOFTIRQEN(r13);        \
-+      std     mreg,SOFTE(r1)
-+#endif /* !CONFIG_IPIPE */
++#include <asm/irq_softstate.h>
 +
- #define EXCEPTION_PROLOG_COMMON_3(n)                                     \
-       std     r2,GPR2(r1);            /* save r2 in stackframe        */ \
-       SAVE_4GPRS(3, r1);              /* save r3 - r6 in stackframe   */ \
-@@ -339,9 +353,8 @@ do_kvm_##n:                                                
                \
+ #define EX_R9         0
+ #define EX_R10                8
+ #define EX_R11                16
+@@ -339,9 +341,8 @@ do_kvm_##n:                                                
                \
        mflr    r9;                     /* Get LR, later save to stack  */ \
        ld      r2,PACATOC(r13);        /* get kernel TOC into r2       */ \
        std     r9,_LINK(r1);                                              \
 -      lbz     r10,PACASOFTIRQEN(r13);                            \
-+      COPY_SOFTISTATE(r10);                                              \
++      EXC_SAVE_SOFTISTATE(r10);                                          \
        mfspr   r11,SPRN_XER;           /* save XER in stackframe       */ \
 -      std     r10,SOFTE(r1);                                             \
        std     r11,_XER(r1);                                              \
        li      r9,(n)+1;                                                  \
        std     r9,_TRAP(r1);           /* set trap number              */ \
-@@ -428,11 +441,15 @@ label##_relon_hv:                                        
        \
+@@ -428,11 +429,15 @@ label##_relon_hv:                                        
        \
  #define SOFTEN_VALUE_0xe60    PACA_IRQ_HMI
  #define SOFTEN_VALUE_0xe62    PACA_IRQ_HMI
  
@@ -103,51 +104,7 @@ index 77f52b2..8eb3473 100644
  #define _SOFTEN_TEST(h, vec)  __SOFTEN_TEST(h, vec)
  
  #define SOFTEN_TEST_PR(vec)                                           \
-@@ -515,11 +532,63 @@ label##_relon_hv:                                        
                \
-  * runlatch, etc...
-  */
- 
-+.macro HARD_ENABLE_INTS tmp=r10
-+#ifdef CONFIG_PPC_BOOK3E
-+      wrteei  1
-+#else
-+      ld      \tmp,PACAKMSR(r13)
-+      ori     \tmp,\tmp,MSR_EE
-+      mtmsrd  \tmp,1
-+#endif /* CONFIG_PPC_BOOK3E */
-+.endm
-+
-+.macro HARD_DISABLE_INTS tmp=r10
-+#ifdef CONFIG_PPC_BOOK3E
-+      wrteei  0
-+#else
-+      ld      \tmp,PACAKMSR(r13) /* Get kernel MSR without EE */
-+      mtmsrd  \tmp,1            /* Update machine state */
-+#endif /* CONFIG_PPC_BOOK3E */
-+.endm
-+
-+.macro HARD_DISABLE_INTS_RI
-+#ifdef CONFIG_PPC_BOOK3E
-+      wrteei  0
-+#else
-+      /*
-+       * For performance reasons we clear RI the same time that we
-+       * clear EE. We only need to clear RI just before we restore r13
-+       * below, but batching it with EE saves us one expensive mtmsrd call.
-+       * We have to be careful to restore RI if we branch anywhere from
-+       * here (eg syscall_exit_work).
-+       *
-+       * CAUTION: using r9-r11 the way they are is assumed by the
-+       * caller.
-+       */
-+      ld      r10,PACAKMSR(r13) /* Get kernel MSR without EE */
-+      li      r9,MSR_RI
-+      andc    r11,r10,r9
-+      mtmsrd  r11,1             /* Update machine state */
-+#endif /* CONFIG_PPC_BOOK3E */
-+.endm
-+
- /*
+@@ -519,7 +524,18 @@ label##_relon_hv:                                         
        \
   * This addition reconciles our actual IRQ state with the various software
   * flags that track it. This may call C code.
   */
@@ -160,14 +117,13 @@ index 77f52b2..8eb3473 100644
 +      mfmsr   r11;                            \
 +      ori     r11,r11,MSR_EE;                 \
 +      mtmsrd  r11,1;
-+#define RECONCILE_IRQ_STATE(__rA, __rB)       HARD_DISABLE_INTS __rA
 +#else /* !CONFIG_IPIPE */
  #define ADD_RECONCILE RECONCILE_IRQ_STATE(r10,r11)
 +#endif /* !CONFIG_IPIPE */
  
  #define ADD_NVGPRS                            \
        bl      save_nvgprs
-@@ -552,9 +621,24 @@ label##_common:                                           
        \
+@@ -552,9 +568,24 @@ label##_common:                                           
        \
   * in the idle task and therefore need the special idle handling
   * (finish nap and runlatch)
   */
@@ -304,10 +260,10 @@ index b59ac27..9cc1d25 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..271fc48
+index 0000000..d7e4acd
 --- /dev/null
 +++ b/arch/powerpc/include/asm/ipipe.h
-@@ -0,0 +1,151 @@
+@@ -0,0 +1,153 @@
 +/*
 + *   include/asm-powerpc/ipipe.h
 + *
@@ -349,14 +305,14 @@ index 0000000..271fc48
 +#include <linux/cache.h>
 +#include <linux/threads.h>
 +
-+#define IPIPE_CORE_RELEASE    3
++#define IPIPE_CORE_RELEASE    7
 +
 +struct ipipe_domain;
 +
 +struct ipipe_arch_sysinfo {
 +};
 +
-+#ifdef CONFIG_DEBUGGER
++#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
 +extern cpumask_t __ipipe_dbrk_pending;
 +#endif
 +
@@ -418,7 +374,9 @@ index 0000000..271fc48
 +
 +void __ipipe_hook_critical_ipi(struct ipipe_domain *ipd);
 +
-+void __ipipe_register_ipi(unsigned int irq);
++void __ipipe_register_mux_ipi(unsigned int irq);
++
++void __ipipe_finish_ipi_demux(unsigned int irq);
 +#else
 +#define __ipipe_hook_critical_ipi(ipd)        do { } while(0)
 +#endif /* CONFIG_SMP */
@@ -461,10 +419,10 @@ index 0000000..271fc48
 +#endif /* !__ASM_POWERPC_IPIPE_H */
 diff --git a/arch/powerpc/include/asm/ipipe_base.h 
b/arch/powerpc/include/asm/ipipe_base.h
 new file mode 100644
-index 0000000..167a70d
+index 0000000..14f7692
 --- /dev/null
 +++ b/arch/powerpc/include/asm/ipipe_base.h
-@@ -0,0 +1,135 @@
+@@ -0,0 +1,134 @@
 +/* -*- linux-c -*-
 + * include/asm-powerpc/ipipe_base.h
 + *
@@ -502,7 +460,8 @@ index 0000000..167a70d
 + * The first virtual interrupt is reserved for the timer (see
 + * __ipipe_early_core_setup).
 + */
-+#define IPIPE_TIMER_VIRQ      IPIPE_VIRQ_BASE
++#define IPIPE_TIMER_VIRQ      (IPIPE_VIRQ_BASE + 0)
++#define IPIPE_DOORBELL_VIRQ   (IPIPE_VIRQ_BASE + 1)
 +
 +#ifdef CONFIG_SMP
 +/* 
@@ -511,21 +470,19 @@ index 0000000..167a70d
 + * implemented by piggybacking the debugger break IPI 0x3,
 + * which is demultiplexed in __ipipe_ipi_demux().
 + */
++#define IPIPE_CRITICAL_IPI    (IPIPE_VIRQ_BASE + 2)
++#define IPIPE_HRTIMER_IPI     (IPIPE_VIRQ_BASE + 3)
++#define IPIPE_RESCHEDULE_IPI  (IPIPE_VIRQ_BASE + 4)
++#define IPIPE_BASE_IPI_OFFSET IPIPE_CRITICAL_IPI
++
 +/* these are bit numbers in practice */
 +#define IPIPE_MSG_CRITICAL_IPI                0
 +#define IPIPE_MSG_HRTIMER_IPI         (IPIPE_MSG_CRITICAL_IPI + 1)
 +#define IPIPE_MSG_RESCHEDULE_IPI      (IPIPE_MSG_CRITICAL_IPI + 2)
-+
 +#define IPIPE_MSG_IPI_MASK    ((1UL << IPIPE_MSG_CRITICAL_IPI) |      \
 +                               (1UL << IPIPE_MSG_HRTIMER_IPI) |       \
 +                               (1UL << IPIPE_MSG_RESCHEDULE_IPI))
 +
-+#define IPIPE_CRITICAL_IPI    (IPIPE_VIRQ_BASE + 1)
-+#define IPIPE_HRTIMER_IPI     (IPIPE_CRITICAL_IPI + 1)
-+#define IPIPE_RESCHEDULE_IPI  (IPIPE_CRITICAL_IPI + 2)
-+
-+#define IPIPE_BASE_IPI_OFFSET IPIPE_CRITICAL_IPI
-+
 +#define ipipe_processor_id()  raw_smp_processor_id()
 +
 +#else  /* !CONFIG_SMP */
@@ -602,10 +559,10 @@ index 0000000..167a70d
 +#endif        /* !__ASM_POWERPC_IPIPE_BASE_H */
 diff --git a/arch/powerpc/include/asm/ipipe_hwirq.h 
b/arch/powerpc/include/asm/ipipe_hwirq.h
 new file mode 100644
-index 0000000..2bc8217
+index 0000000..1f94e29
 --- /dev/null
 +++ b/arch/powerpc/include/asm/ipipe_hwirq.h
-@@ -0,0 +1,252 @@
+@@ -0,0 +1,256 @@
 +/* -*- linux-c -*-
 + * include/asm-powerpc/ipipe_hwirq.h
 + *
@@ -682,6 +639,9 @@ index 0000000..2bc8217
 +{
 +      __asm__ __volatile__("wrteei 1": : :"memory");
 +}
++
++#define hard_local_irq_restore_notrace(x)     mtmsr(x)
++
 +#else /* !CONFIG_PPC_BOOK3E */
 +static inline void hard_local_irq_disable_notrace(void)
 +{
@@ -692,6 +652,9 @@ index 0000000..2bc8217
 +{
 +      __mtmsrd(mfmsr() | MSR_EE, 1);
 +}
++
++#define hard_local_irq_restore_notrace(x)     __mtmsrd(x, 1)
++
 +#endif /* !CONFIG_PPC_BOOK3E */
 +
 +static inline unsigned long hard_local_irq_save_notrace(void)
@@ -701,8 +664,6 @@ index 0000000..2bc8217
 +      return msr;
 +}
 +
-+#define hard_local_irq_restore_notrace(x)     __mtmsrd(x, 1)
-+
 +#endif /* CONFIG_PPC64 */
 +
 +#ifdef CONFIG_IPIPE
@@ -880,37 +841,167 @@ index e8e3a0a..90fe40a 100644
 +
  #endif /* _ASM_IRQ_H */
  #endif /* __KERNEL__ */
+diff --git a/arch/powerpc/include/asm/irq_softstate.h 
b/arch/powerpc/include/asm/irq_softstate.h
+new file mode 100644
+index 0000000..663ce0f
+--- /dev/null
++++ b/arch/powerpc/include/asm/irq_softstate.h
+@@ -0,0 +1,118 @@
++#ifndef _ASM_POWERPC_IRQ_SOFTSTATE_H
++#define _ASM_POWERPC_IRQ_SOFTSTATE_H
++
++#ifdef __ASSEMBLY__
++
++.macro HARD_ENABLE_INTS tmp=r10
++#ifdef CONFIG_PPC_BOOK3E
++      wrteei  1
++#else
++      ld      \tmp,PACAKMSR(r13)
++      ori     \tmp,\tmp,MSR_EE
++      mtmsrd  \tmp,1
++#endif /* CONFIG_PPC_BOOK3E */
++.endm
++
++.macro HARD_DISABLE_INTS tmp=r10
++#ifdef CONFIG_PPC_BOOK3E
++      wrteei  0
++#else
++      ld      \tmp,PACAKMSR(r13) /* Get kernel MSR without EE */
++      mtmsrd  \tmp,1            /* Update machine state */
++#endif /* CONFIG_PPC_BOOK3E */
++.endm
++
++.macro HARD_DISABLE_INTS_RI
++#ifdef CONFIG_PPC_BOOK3E
++      wrteei  0
++#else
++      /*
++       * For performance reasons we clear RI the same time that we
++       * clear EE. We only need to clear RI just before we restore r13
++       * below, but batching it with EE saves us one expensive mtmsrd call.
++       * We have to be careful to restore RI if we branch anywhere from
++       * here (eg syscall_exit_work).
++       *
++       * CAUTION: using r9-r11 the way they are is assumed by the
++       * caller.
++       */
++      ld      r10,PACAKMSR(r13) /* Get kernel MSR without EE */
++      li      r9,MSR_RI
++      andc    r11,r10,r9
++      mtmsrd  r11,1             /* Update machine state */
++#endif /* CONFIG_PPC_BOOK3E */
++.endm
++
++#ifdef CONFIG_IPIPE
++
++  /* Do NOT alter Rc(eq) in this code;  our caller uses it. */
++#define __COPY_SOFTISTATE(mreg)                       \
++      ld      mreg,PACAROOTPCPU(r13);         \
++      ld      mreg,0(mreg);                   \
++      nor     mreg,mreg,mreg;                 \
++      clrldi  mreg,mreg,63;                   \
++
++/* Do NOT alter Rc(eq) in this code;  our caller uses it. */
++#define COPY_SOFTISTATE(mreg)                 \
++      __COPY_SOFTISTATE(mreg);                \
++      std     mreg,SOFTE(r1)
++
++#ifdef CONFIG_PPC_BOOK3E
++#define SPECIAL_SAVE_SOFTISTATE(mreg)         \
++      __COPY_SOFTISTATE(mreg);                \
++      SPECIAL_EXC_STORE(mreg, SOFTE)
++#endif
++
++#define EXC_SAVE_SOFTISTATE(mreg)             \
++      COPY_SOFTISTATE(mreg)
++
++#define RECONCILE_IRQ_STATE(__rA, __rB)       HARD_DISABLE_INTS __rA
++
++#else /* !CONFIG_IPIPE */
++
++#define COPY_SOFTISTATE(mreg)                 \
++      lbz     mreg,PACASOFTIRQEN(r13);        \
++      std     mreg,SOFTE(r1)
++
++#ifdef CONFIG_PPC_BOOK3E
++#define SPECIAL_SAVE_SOFTISTATE(mreg)         \
++      lbz     mreg,PACASOFTIRQEN(r13);        \
++      SPECIAL_EXC_STORE(mreg, SOFTE)
++#endif
++
++#define EXC_SAVE_SOFTISTATE(mreg)             \
++      COPY_SOFTISTATE(mreg)
++
++ /*
++ * This is used by assembly code to soft-disable interrupts first and
++ * reconcile irq state.
++ *
++ * NB: This may call C code, so the caller must be prepared for volatiles to
++ * be clobbered.
++ */
++#ifdef CONFIG_TRACE_IRQFLAGS
++#define RECONCILE_IRQ_STATE(__rA, __rB)               \
++      lbz     __rA,PACASOFTIRQEN(r13);        \
++      lbz     __rB,PACAIRQHAPPENED(r13);      \
++      cmpwi   cr0,__rA,0;                     \
++      li      __rA,0;                         \
++      ori     __rB,__rB,PACA_IRQ_HARD_DIS;    \
++      stb     __rB,PACAIRQHAPPENED(r13);      \
++      beq     44f;                            \
++      stb     __rA,PACASOFTIRQEN(r13);        \
++      TRACE_DISABLE_INTS;                     \
++44:
++#else
++#define RECONCILE_IRQ_STATE(__rA, __rB)               \
++      lbz     __rA,PACAIRQHAPPENED(r13);      \
++      li      __rB,0;                         \
++      ori     __rA,__rA,PACA_IRQ_HARD_DIS;    \
++      stb     __rB,PACASOFTIRQEN(r13);        \
++      stb     __rA,PACAIRQHAPPENED(r13)
++#endif /* !CONFIG_TRACE_IRQFLAGS */
++
++#endif /* !CONFIG_IPIPE */
++
++#endif /* __ASSEMBLY__ */
++   
++#endif /* _ASM_POWERPC_IRQ_SOFTSTATE_H */
 diff --git a/arch/powerpc/include/asm/irqflags.h 
b/arch/powerpc/include/asm/irqflags.h
-index f214906..093829c 100644
+index f214906..fa36751 100644
 --- a/arch/powerpc/include/asm/irqflags.h
 +++ b/arch/powerpc/include/asm/irqflags.h
-@@ -45,6 +45,7 @@
-  * NB: This may call C code, so the caller must be prepared for volatiles to
-  * be clobbered.
-  */
-+#ifndef CONFIG_IPIPE
- #define RECONCILE_IRQ_STATE(__rA, __rB)               \
-       lbz     __rA,PACASOFTIRQEN(r13);        \
-       lbz     __rB,PACAIRQHAPPENED(r13);      \
-@@ -56,17 +57,21 @@
-       stb     __rA,PACASOFTIRQEN(r13);        \
-       TRACE_DISABLE_INTS;                     \
- 44:
-+#endif /* !CONFIG_IPIPE */
+@@ -38,35 +38,10 @@
+ #define TRACE_ENABLE_INTS     TRACE_WITH_FRAME_BUFFER(trace_hardirqs_on)
+ #define TRACE_DISABLE_INTS    TRACE_WITH_FRAME_BUFFER(trace_hardirqs_off)
  
+-/*
+- * This is used by assembly code to soft-disable interrupts first and
+- * reconcile irq state.
+- *
+- * NB: This may call C code, so the caller must be prepared for volatiles to
+- * be clobbered.
+- */
+-#define RECONCILE_IRQ_STATE(__rA, __rB)               \
+-      lbz     __rA,PACASOFTIRQEN(r13);        \
+-      lbz     __rB,PACAIRQHAPPENED(r13);      \
+-      cmpwi   cr0,__rA,0;                     \
+-      li      __rA,0;                         \
+-      ori     __rB,__rB,PACA_IRQ_HARD_DIS;    \
+-      stb     __rB,PACAIRQHAPPENED(r13);      \
+-      beq     44f;                            \
+-      stb     __rA,PACASOFTIRQEN(r13);        \
+-      TRACE_DISABLE_INTS;                     \
+-44:
+-
  #else
  #define TRACE_ENABLE_INTS
  #define TRACE_DISABLE_INTS
  
-+#ifndef CONFIG_IPIPE
- #define RECONCILE_IRQ_STATE(__rA, __rB)               \
-       lbz     __rA,PACAIRQHAPPENED(r13);      \
-       li      __rB,0;                         \
-       ori     __rA,__rA,PACA_IRQ_HARD_DIS;    \
-       stb     __rB,PACASOFTIRQEN(r13);        \
-       stb     __rA,PACAIRQHAPPENED(r13)
-+#endif /* !CONFIG_IPIPE */
-+
+-#define RECONCILE_IRQ_STATE(__rA, __rB)               \
+-      lbz     __rA,PACAIRQHAPPENED(r13);      \
+-      li      __rB,0;                         \
+-      ori     __rA,__rA,PACA_IRQ_HARD_DIS;    \
+-      stb     __rB,PACASOFTIRQEN(r13);        \
+-      stb     __rA,PACAIRQHAPPENED(r13)
  #endif
  #endif
  
@@ -1122,10 +1213,18 @@ index 70bd438..c43f0e4 100644
        u64 user_time;                  /* accumulated usermode TB ticks */
        u64 system_time;                /* accumulated system TB ticks */
 diff --git a/arch/powerpc/include/asm/qe_ic.h 
b/arch/powerpc/include/asm/qe_ic.h
-index 25784cc..f29c8cf 100644
+index 25784cc..8eb2d78 100644
 --- a/arch/powerpc/include/asm/qe_ic.h
 +++ b/arch/powerpc/include/asm/qe_ic.h
-@@ -85,7 +85,7 @@ static inline void qe_ic_cascade_low_ipic(unsigned int irq,
+@@ -16,6 +16,7 @@
+ #define _ASM_POWERPC_QE_IC_H
+ 
+ #include <linux/irq.h>
++#include <linux/ipipe.h>
+ 
+ struct device_node;
+ struct qe_ic;
+@@ -85,7 +86,7 @@ static inline void qe_ic_cascade_low_ipic(unsigned int irq,
        unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
  
        if (cascade_irq != NO_IRQ)
@@ -1134,7 +1233,7 @@ index 25784cc..f29c8cf 100644
  }
  
  static inline void qe_ic_cascade_high_ipic(unsigned int irq,
-@@ -95,7 +95,7 @@ static inline void qe_ic_cascade_high_ipic(unsigned int irq,
+@@ -95,7 +96,7 @@ static inline void qe_ic_cascade_high_ipic(unsigned int irq,
        unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
  
        if (cascade_irq != NO_IRQ)
@@ -1143,7 +1242,7 @@ index 25784cc..f29c8cf 100644
  }
  
  static inline void qe_ic_cascade_low_mpic(unsigned int irq,
-@@ -106,7 +106,7 @@ static inline void qe_ic_cascade_low_mpic(unsigned int irq,
+@@ -106,7 +107,7 @@ static inline void qe_ic_cascade_low_mpic(unsigned int irq,
        struct irq_chip *chip = irq_desc_get_chip(desc);
  
        if (cascade_irq != NO_IRQ)
@@ -1152,7 +1251,7 @@ index 25784cc..f29c8cf 100644
  
        chip->irq_eoi(&desc->irq_data);
  }
-@@ -119,7 +119,7 @@ static inline void qe_ic_cascade_high_mpic(unsigned int 
irq,
+@@ -119,7 +120,7 @@ static inline void qe_ic_cascade_high_mpic(unsigned int 
irq,
        struct irq_chip *chip = irq_desc_get_chip(desc);
  
        if (cascade_irq != NO_IRQ)
@@ -1161,7 +1260,7 @@ index 25784cc..f29c8cf 100644
  
        chip->irq_eoi(&desc->irq_data);
  }
-@@ -136,7 +136,7 @@ static inline void qe_ic_cascade_muxed_mpic(unsigned int 
irq,
+@@ -136,7 +137,7 @@ static inline void qe_ic_cascade_muxed_mpic(unsigned int 
irq,
                cascade_irq = qe_ic_get_low_irq(qe_ic);
  
        if (cascade_irq != NO_IRQ)
@@ -1434,7 +1533,7 @@ index 60262fd..e4db6db 100644
        struct cpu_spec *s = cpu_specs;
        int i;
 diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
-index 46fc0f4..f4568bb 100644
+index 46fc0f4..fa32ed8 100644
 --- a/arch/powerpc/kernel/entry_32.S
 +++ b/arch/powerpc/kernel/entry_32.S
 @@ -179,9 +179,11 @@ transfer_to_handler:
@@ -1604,11 +1703,13 @@ index 46fc0f4..f4568bb 100644
        CURRENT_THREAD_INFO(r9, r1)
        lwz     r3,TI_FLAGS(r9)
        andi.   r0,r3,_TIF_NEED_RESCHED
-@@ -1233,6 +1346,13 @@ ee_restarts:
+@@ -1233,6 +1346,15 @@ ee_restarts:
        .space  4
        .previous
  
 +#ifdef CONFIG_IPIPE
++_GLOBAL(__ipipe_ret_from_except_full)
++      REST_NVGPRS(r1)
 +_GLOBAL(__ipipe_ret_from_except)
 +        cmpwi   r3, 0
 +        bne+ ret_from_except
@@ -1619,7 +1720,7 @@ index 46fc0f4..f4568bb 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 afbc200..65fe2c1 100644
+index afbc200..107d0dd 100644
 --- a/arch/powerpc/kernel/entry_64.S
 +++ b/arch/powerpc/kernel/entry_64.S
 @@ -33,6 +33,7 @@
@@ -1858,25 +1959,21 @@ index afbc200..65fe2c1 100644
  #endif /* CONFIG_PREEMPT */
  
        .globl  fast_exc_return_irq
-@@ -743,6 +798,17 @@ restore:
+@@ -743,6 +798,13 @@ restore:
         * are about to re-enable interrupts
         */
        ld      r5,SOFTE(r1)
 +#ifdef CONFIG_IPIPE
-+      cmpwi   cr0,r5,0
-+      nor     r5,r5,r5        /* IPIPE_STALL_FLAG = !SOFTE */
 +      ld      r4,PACAROOTPCPU(r13)
-+      ld      r3,0(r4)
-+      insrdi  r3,r5,1,63
-+      std     r3,0(r4)
-+      beq     1f
++      cmpwi   cr0,r4,0
++      bne     1f
 +      TRACE_ENABLE_INTS
 +1:
 +#else /* !CONFIG_IPIPE */
        lbz     r6,PACASOFTIRQEN(r13)
        cmpwi   cr0,r5,0
        beq     restore_irq_off
-@@ -769,6 +835,7 @@ restore_no_replay:
+@@ -769,6 +831,7 @@ restore_no_replay:
        TRACE_ENABLE_INTS
        li      r0,1
        stb     r0,PACASOFTIRQEN(r13);
@@ -1884,7 +1981,7 @@ index afbc200..65fe2c1 100644
  
        /*
         * Final return path. BookE is handled in a different file
-@@ -859,6 +926,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
+@@ -859,6 +922,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
  
  #endif /* CONFIG_PPC_BOOK3E */
  
@@ -1892,7 +1989,7 @@ index afbc200..65fe2c1 100644
        /*
         * We are returning to a context with interrupts soft disabled.
         *
-@@ -940,6 +1008,8 @@ restore_check_irq_replay:
+@@ -940,6 +1004,8 @@ restore_check_irq_replay:
        b       ret_from_except
  #endif /* CONFIG_PPC_DOORBELL */
  1:    b       ret_from_except /* What else to do here ? */
@@ -1901,7 +1998,7 @@ index afbc200..65fe2c1 100644
   
  unrecov_restore:
        addi    r3,r1,STACK_FRAME_OVERHEAD
-@@ -986,7 +1056,7 @@ _GLOBAL(enter_rtas)
+@@ -986,7 +1052,7 @@ _GLOBAL(enter_rtas)
        li      r0,0
        mtcr    r0
  
@@ -1910,6 +2007,170 @@ index afbc200..65fe2c1 100644
        /* There is no way it is acceptable to get here with interrupts enabled,
         * check it with the asm equivalent of WARN_ON
         */
+diff --git a/arch/powerpc/kernel/exceptions-64e.S 
b/arch/powerpc/kernel/exceptions-64e.S
+index 3e68d1c..18a6004 100644
+--- a/arch/powerpc/kernel/exceptions-64e.S
++++ b/arch/powerpc/kernel/exceptions-64e.S
+@@ -65,7 +65,9 @@
+       ld      reg, (SPECIAL_EXC_##name * 8 + SPECIAL_EXC_FRAME_OFFS)(r1)
+ 
+ special_reg_save:
++#ifndef CONFIG_IPIPE  
+       lbz     r9,PACAIRQHAPPENED(r13)
++#endif        
+       RECONCILE_IRQ_STATE(r3,r4)
+ 
+       /*
+@@ -132,15 +134,15 @@ BEGIN_FTR_SECTION
+       mtspr   SPRN_MAS5,r10
+       mtspr   SPRN_MAS8,r10
+ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
++#ifndef CONFIG_IPIPE  
+       SPECIAL_EXC_STORE(r9,IRQHAPPENED)
+-
++#endif
+       mfspr   r10,SPRN_DEAR
+       SPECIAL_EXC_STORE(r10,DEAR)
+       mfspr   r10,SPRN_ESR
+       SPECIAL_EXC_STORE(r10,ESR)
+ 
+-      lbz     r10,PACASOFTIRQEN(r13)
+-      SPECIAL_EXC_STORE(r10,SOFTE)
++      SPECIAL_SAVE_SOFTISTATE(r10)
+       ld      r10,_NIP(r1)
+       SPECIAL_EXC_STORE(r10,CSRR0)
+       ld      r10,_MSR(r1)
+@@ -206,8 +208,15 @@ BEGIN_FTR_SECTION
+       mtspr   SPRN_MAS8,r10
+ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
+ 
+-      lbz     r6,PACASOFTIRQEN(r13)
++#ifdef CONFIG_IPIPE
++      ld      r6,PACAROOTPCPU(r13)
++      cmpwi   cr0,r6,0
++      bne     1f
++      TRACE_ENABLE_INTS
++1:
++#else
+       ld      r5,SOFTE(r1)
++      lbz     r6,PACASOFTIRQEN(r13)
+ 
+       /* Interrupts had better not already be enabled... */
+       twnei   r6,0
+@@ -226,6 +235,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
+        */
+       SPECIAL_EXC_LOAD(r10,IRQHAPPENED)
+       stb     r10,PACAIRQHAPPENED(r13)
++#endif
+ 
+       SPECIAL_EXC_LOAD(r10,DEAR)
+       mtspr   SPRN_DEAR,r10
+@@ -350,10 +360,16 @@ ret_from_mc_except:
+ #define PROLOG_ADDITION_NONE_DBG(n)
+ #define PROLOG_ADDITION_NONE_MC(n)
+ 
++#ifdef CONFIG_IPIPE
++#define PROLOG_ADDITION_MASKABLE_GEN(n)
++#define MASKABLE_EXCEPTION_EXIT        b      __ipipe_ret_from_except_lite
++#else
+ #define PROLOG_ADDITION_MASKABLE_GEN(n)                                       
    \
+       lbz     r10,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */      \
+       cmpwi   cr0,r10,0;              /* yes -> go out of line */         \
+       beq     masked_interrupt_book3e_##n
++#define MASKABLE_EXCEPTION_EXIT        b      ret_from_except_lite
++#endif
+ 
+ #define PROLOG_ADDITION_2REGS_GEN(n)                                      \
+       std     r14,PACA_EXGEN+EX_R14(r13);                                 \
+@@ -397,8 +413,8 @@ exc_##n##_common:                                          
            \
+       mfspr   r8,SPRN_XER;            /* save XER in stackframe */        \
+       ld      r9,excf+EX_R1(r13);     /* load orig r1 back from PACA */   \
+       lwz     r10,excf+EX_CR(r13);    /* load orig CR back from PACA  */  \
+-      lbz     r11,PACASOFTIRQEN(r13); /* get current IRQ softe */         \
+       ld      r12,exception_marker@toc(r2);                               \
++      EXC_SAVE_SOFTISTATE(r11);                                           \
+       li      r0,0;                                                       \
+       std     r3,GPR10(r1);           /* save r10 to stackframe */        \
+       std     r4,GPR11(r1);           /* save r11 to stackframe */        \
+@@ -410,7 +426,6 @@ exc_##n##_common:                                          
            \
+       std     r9,0(r1);               /* store stack frame back link */   \
+       std     r10,_CCR(r1);           /* store orig CR in stackframe */   \
+       std     r9,GPR1(r1);            /* store stack frame back link */   \
+-      std     r11,SOFTE(r1);          /* and save it to stackframe */     \
+       std     r12,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */       \
+       std     r3,_TRAP(r1);           /* set trap number              */  \
+       std     r0,RESULT(r1);          /* clear regs->result */
+@@ -499,7 +514,7 @@ exc_##n##_bad_stack:                                       
                    \
+       CHECK_NAPPING();                                                \
+       addi    r3,r1,STACK_FRAME_OVERHEAD;                             \
+       bl      hdlr;                                                   \
+-      b       ret_from_except_lite;
++      MASKABLE_EXCEPTION_EXIT;
+ 
+ /* This value is used to mark exception frames on the stack. */
+       .section        ".toc","aw"
+@@ -545,6 +560,16 @@ interrupt_base_book3e:                                    
/* fake trap */
+       .globl interrupt_end_book3e
+ interrupt_end_book3e:
+ 
++#ifdef CONFIG_IPIPE
++#define BOOKE_EXTIRQ_HANDLER  __ipipe_grab_irq
++#define BOOKE_TIMER_HANDLER   __ipipe_grab_timer
++#define BOOKE_DBELL_HANDLER   __ipipe_grab_doorbell
++#else 
++#define BOOKE_EXTIRQ_HANDLER  do_IRQ
++#define BOOKE_TIMER_HANDLER   timer_interrupt
++#define BOOKE_DBELL_HANDLER   doorbell_exception
++#endif        
++      
+ /* Critical Input Interrupt */
+       START_EXCEPTION(critical_input);
+       CRIT_EXCEPTION_PROLOG(0x100, BOOKE_INTERRUPT_CRITICAL,
+@@ -591,8 +616,8 @@ interrupt_end_book3e:
+ 
+ /* External Input Interrupt */
+       MASKABLE_EXCEPTION(0x500, BOOKE_INTERRUPT_EXTERNAL,
+-                         external_input, do_IRQ, ACK_NONE)
+-
++                         external_input, BOOKE_EXTIRQ_HANDLER, ACK_NONE)
++      
+ /* Alignment */
+       START_EXCEPTION(alignment);
+       NORMAL_EXCEPTION_PROLOG(0x600, BOOKE_INTERRUPT_ALIGNMENT,
+@@ -676,7 +701,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+ 
+ /* Decrementer Interrupt */
+       MASKABLE_EXCEPTION(0x900, BOOKE_INTERRUPT_DECREMENTER,
+-                         decrementer, timer_interrupt, ACK_DEC)
++                         decrementer, BOOKE_TIMER_HANDLER, ACK_DEC)
+ 
+ /* Fixed Interval Timer Interrupt */
+       MASKABLE_EXCEPTION(0x980, BOOKE_INTERRUPT_FIT,
+@@ -855,7 +880,7 @@ kernel_dbg_exc:
+ 
+ /* Doorbell interrupt */
+       MASKABLE_EXCEPTION(0x280, BOOKE_INTERRUPT_DOORBELL,
+-                         doorbell, doorbell_exception, ACK_NONE)
++                         doorbell, BOOKE_DBELL_HANDLER, ACK_NONE)
+ 
+ /* Doorbell critical Interrupt */
+       START_EXCEPTION(doorbell_crit);
+@@ -928,6 +953,7 @@ kernel_dbg_exc:
+       bl      .unknown_exception
+       b       .ret_from_except
+ 
++#ifndef CONFIG_IPIPE
+ /*
+  * An interrupt came in while soft-disabled; We mark paca->irq_happened
+  * accordingly and if the interrupt is level sensitive, we hard disable
+@@ -1000,6 +1026,7 @@ _GLOBAL(__replay_interrupt)
+       beq     exc_0x280_common
+       blr
+ 
++#endif /* !CONFIG_IPIPE */
+ 
+ /*
+  * This is called from 0x300 and 0x400 handlers after the prologs with
 diff --git a/arch/powerpc/kernel/exceptions-64s.S 
b/arch/powerpc/kernel/exceptions-64s.S
 index 9519e6b..fbcbc46 100644
 --- a/arch/powerpc/kernel/exceptions-64s.S
@@ -2227,10 +2488,10 @@ index 9b53fe1..35b4944 100644
        blr
  #endif
 diff --git a/arch/powerpc/kernel/head_booke.h 
b/arch/powerpc/kernel/head_booke.h
-index a620203..a67bb7c 100644
+index a620203..1fd92fb 100644
 --- a/arch/powerpc/kernel/head_booke.h
 +++ b/arch/powerpc/kernel/head_booke.h
-@@ -240,6 +240,12 @@ label:
+@@ -240,6 +240,16 @@ label:
        EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, 
transfer_to_handler_full, \
                          ret_from_except_full)
  
@@ -2238,12 +2499,16 @@ index a620203..a67bb7c 100644
 +#define EXC_XFER_IPIPE(n, hdlr)               \
 +      EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
 +                        __ipipe_ret_from_except)
++
++#define EXC_XFER_IPIPE_FULL(n, hdlr)                                          
\
++      EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, 
transfer_to_handler_full, \
++                        __ipipe_ret_from_except_full)
 +#endif /* CONFIG_IPIPE */
 +
  #define EXC_XFER_LITE(n, hdlr)                \
        EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \
                          ret_from_except)
-@@ -404,6 +410,15 @@ label:
+@@ -404,6 +414,15 @@ label:
        addi    r3,r1,STACK_FRAME_OVERHEAD;                                   \
        EXC_XFER_STD(0x0700, program_check_exception)
  
@@ -2259,7 +2524,7 @@ index a620203..a67bb7c 100644
  #define DECREMENTER_EXCEPTION                                               \
        START_EXCEPTION(Decrementer)                                          \
        NORMAL_EXCEPTION_PROLOG(DECREMENTER);                 \
-@@ -411,6 +426,7 @@ label:
+@@ -411,6 +430,7 @@ label:
        mtspr   SPRN_TSR,r0;            /* Clear the DEC interrupt */         \
        addi    r3,r1,STACK_FRAME_OVERHEAD;                                   \
        EXC_XFER_LITE(0x0900, timer_interrupt)
@@ -2268,7 +2533,7 @@ index a620203..a67bb7c 100644
  #define FP_UNAVAILABLE_EXCEPTION                                            \
        START_EXCEPTION(FloatingPointUnavailable)                             \
 diff --git a/arch/powerpc/kernel/head_fsl_booke.S 
b/arch/powerpc/kernel/head_fsl_booke.S
-index fffd1f9..66425e9 100644
+index fffd1f9..25db5bf 100644
 --- a/arch/powerpc/kernel/head_fsl_booke.S
 +++ b/arch/powerpc/kernel/head_fsl_booke.S
 @@ -390,7 +390,11 @@ interrupt_base:
@@ -2283,7 +2548,19 @@ index fffd1f9..66425e9 100644
  
        /* Alignment Interrupt */
        ALIGNMENT_EXCEPTION
-@@ -1017,10 +1021,14 @@ _GLOBAL(__setup_ehv_ivors)
+@@ -648,7 +652,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
+       EXCEPTION(0x2060, PERFORMANCE_MONITOR, PerformanceMonitor, \
+                 performance_monitor_exception, EXC_XFER_STD)
+ 
++#ifdef CONFIG_IPIPE
++      EXCEPTION(0x2070, DOORBELL, Doorbell, __ipipe_grab_doorbell, 
EXC_XFER_IPIPE_FULL)
++#else
+       EXCEPTION(0x2070, DOORBELL, Doorbell, doorbell_exception, EXC_XFER_STD)
++#endif
+ 
+       CRITICAL_EXCEPTION(0x2080, DOORBELL_CRITICAL, \
+                          CriticalDoorbell, unknown_exception)
+@@ -1017,10 +1025,14 @@ _GLOBAL(__setup_ehv_ivors)
  _GLOBAL(giveup_spe)
        mfmsr   r5
        oris    r5,r5,MSR_SPE@h
@@ -2299,7 +2576,7 @@ index fffd1f9..66425e9 100644
        addi    r3,r3,THREAD            /* want THREAD of task */
        lwz     r5,PT_REGS(r3)
        cmpi    0,r5,0
-@@ -1040,6 +1048,15 @@ _GLOBAL(giveup_spe)
+@@ -1040,6 +1052,15 @@ _GLOBAL(giveup_spe)
        lis     r4,last_task_used_spe@ha
        stw     r5,last_task_used_spe@l(r4)
  #endif /* !CONFIG_SMP */
@@ -2376,6 +2653,43 @@ index d7216c9..888dfd1 100644
                local_irq_enable();
                /*
                 * Go into low thread priority and possibly
+diff --git a/arch/powerpc/kernel/idle_book3e.S 
b/arch/powerpc/kernel/idle_book3e.S
+index 48c21ac..329e162 100644
+--- a/arch/powerpc/kernel/idle_book3e.S
++++ b/arch/powerpc/kernel/idle_book3e.S
+@@ -27,15 +27,20 @@ _GLOBAL(\name)
+       mflr    r0
+       std     r0,16(r1)
+ 
++#ifndef CONFIG_IPIPE  
+       /* Hard disable interrupts */
+       wrteei  0
+ 
+       /* Now check if an interrupt came in while we were soft disabled
+-       * since we may otherwise lose it (doorbells etc...).
++       * since we may otherwise lose it (doorbells etc...). There is no
++       * need to do that if pipelining IRQs, since our caller already
++       * cleared the stall bit, then synchronized the interrupt log,
++       * disabling hw IRQs before getting here.
+        */
+       lbz     r3,PACAIRQHAPPENED(r13)
+       cmpwi   cr0,r3,0
+       bnelr
++#endif        
+ 
+       /* Now we are going to mark ourselves as soft and hard enabled in
+        * order to be able to take interrupts while asleep. We inform lockdep
+@@ -46,8 +51,10 @@ _GLOBAL(\name)
+       bl      trace_hardirqs_on
+       addi    r1,r1,128
+ #endif
++#ifndef CONFIG_IPIPE  
+       li      r0,1
+       stb     r0,PACASOFTIRQEN(r13)
++#endif
+       
+       /* Interrupts will make use return to LR, so get something we want
+        * in there
 diff --git a/arch/powerpc/kernel/idle_power4.S 
b/arch/powerpc/kernel/idle_power4.S
 index f57a193..ac19c01 100644
 --- a/arch/powerpc/kernel/idle_power4.S
@@ -2437,10 +2751,10 @@ index 112ccf4..5dd70f7 100644
        li      r0,0
 diff --git a/arch/powerpc/kernel/ipipe.c b/arch/powerpc/kernel/ipipe.c
 new file mode 100644
-index 0000000..9a5702a
+index 0000000..1ea81c6
 --- /dev/null
 +++ b/arch/powerpc/kernel/ipipe.c
-@@ -0,0 +1,372 @@
+@@ -0,0 +1,406 @@
 +/* -*- linux-c -*-
 + * linux/arch/powerpc/kernel/ipipe.c
 + *
@@ -2487,23 +2801,33 @@ index 0000000..9a5702a
 +#include <asm/time.h>
 +#include <asm/runlatch.h>
 +#include <asm/debug.h>
++#include <asm/dbell.h>
 +
 +static void __ipipe_do_IRQ(unsigned int irq, void *cookie);
 +
 +static void __ipipe_do_timer(unsigned int irq, void *cookie);
 +
++#ifdef CONFIG_PPC_DOORBELL
++static void __ipipe_do_doorbell(unsigned int irq, void *cookie);
++#endif
++
 +#define DECREMENTER_MAX       0x7fffffff
 +
 +#ifdef CONFIG_SMP
 +
 +static DEFINE_PER_CPU(struct ipipe_ipi_struct, ipipe_ipi_message);
 +
-+unsigned int __ipipe_ipi_irq = NR_IRQS + 1; /* dummy value */
-+
-+#ifdef CONFIG_DEBUGGER
++#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
 +cpumask_t __ipipe_dbrk_pending;       /* pending debugger break IPIs */
 +#endif
 +
++static unsigned int mux_ipi;
++
++void __ipipe_register_mux_ipi(unsigned int irq)
++{
++      mux_ipi = irq;
++}
++
 +void __ipipe_hook_critical_ipi(struct ipipe_domain *ipd)
 +{
 +      unsigned int ipi = IPIPE_CRITICAL_IPI;
@@ -2514,30 +2838,22 @@ index 0000000..9a5702a
 +      ipd->irqs[ipi].control = IPIPE_HANDLE_MASK|IPIPE_STICKY_MASK;
 +}
 +
-+void __ipipe_register_ipi(unsigned int irq)
++static void do_ipi_demux(int irq, struct pt_regs *regs)
 +{
-+      __ipipe_ipi_irq = irq;
-+}
-+
-+static void __ipipe_ipi_demux(int irq, struct pt_regs *regs)
-+{
-+      struct irq_desc *desc = irq_to_desc(irq);
-+      int ipi, cpu = ipipe_processor_id();
-+
-+      desc->ipipe_ack(irq, desc);
-+
-+      kstat_incr_irq_this_cpu(irq);
-+
-+      while (per_cpu(ipipe_ipi_message, cpu).value & IPIPE_MSG_IPI_MASK) {
-+              for (ipi = IPIPE_MSG_CRITICAL_IPI; ipi <= 
IPIPE_MSG_RESCHEDULE_IPI; ++ipi) {
-+                      if (test_and_clear_bit(ipi, &per_cpu(ipipe_ipi_message, 
cpu).value)) {
++      int cpu __maybe_unused = ipipe_processor_id(), ipi;
++      
++      while (this_cpu_ptr(&ipipe_ipi_message)->value & IPIPE_MSG_IPI_MASK) {
++              for (ipi = IPIPE_MSG_CRITICAL_IPI;
++                   ipi <= IPIPE_MSG_RESCHEDULE_IPI; ++ipi) {
++                      if (test_and_clear_bit(ipi,
++                             &this_cpu_ptr(&ipipe_ipi_message)->value)) {
 +                              mb();
 +                              __ipipe_handle_irq(ipi + IPIPE_BASE_IPI_OFFSET, 
NULL);
 +                      }
 +              }
 +      }
 +
-+#ifdef CONFIG_DEBUGGER
++#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
 +      /*
 +       * The debugger IPI handler should be NMI-safe, so let's call
 +       * it immediately in case the IPI is pending.
@@ -2546,9 +2862,9 @@ index 0000000..9a5702a
 +              cpumask_clear_cpu(cpu, &__ipipe_dbrk_pending);
 +              debugger_ipi(regs);
 +      }
-+#endif /* CONFIG_DEBUGGER */
++#endif /* CONFIG_DEBUGGER || CONFIG_KEXEC */
 +
-+      ipipe_end_irq(irq);
++      __ipipe_finish_ipi_demux(irq);
 +}
 +
 +void ipipe_set_irq_affinity(unsigned int irq, cpumask_t cpumask)
@@ -2570,22 +2886,20 @@ index 0000000..9a5702a
 +
 +      flags = hard_local_irq_save();
 +
-+      ipi -= IPIPE_BASE_IPI_OFFSET;
-+      for_each_online_cpu(cpu) {
-+              if (cpumask_test_cpu(cpu, &cpumask))
-+                      set_bit(ipi, &per_cpu(ipipe_ipi_message, cpu).value);
-+      }
-+      mb();
-+
-+      if (unlikely(cpumask_empty(&cpumask)))
-+              goto out;
-+
 +      me = ipipe_processor_id();
++      ipi -= IPIPE_BASE_IPI_OFFSET;
 +      for_each_cpu(cpu, &cpumask) {
-+              if (cpu != me)
++              if (cpu == me)
++                      continue;
++              set_bit(ipi, &per_cpu(ipipe_ipi_message, cpu).value);
++              if (smp_ops->message_pass)
 +                      smp_ops->message_pass(cpu, PPC_MSG_IPIPE_DEMUX);
++#ifdef CONFIG_PPC_SMP_MUXED_IPI
++              else
++                      smp_muxed_ipi_message_pass(cpu, PPC_MSG_IPIPE_DEMUX);
++#endif
 +      }
-+out:
++
 +      hard_local_irq_restore(flags);
 +}
 +EXPORT_SYMBOL_GPL(ipipe_send_ipi);
@@ -2628,7 +2942,7 @@ index 0000000..9a5702a
 +}
 +EXPORT_SYMBOL_GPL(ipipe_test_root);
 +
-+#endif        /* CONFIG_SMP */
++#endif        /* !CONFIG_SMP */
 +
 +void __ipipe_early_core_setup(void)
 +{
@@ -2640,6 +2954,13 @@ index 0000000..9a5702a
 +       */
 +      virq = ipipe_alloc_virq();
 +      BUG_ON(virq != IPIPE_TIMER_VIRQ);
++      /*
++       * Although not all CPUs define the doorbell event, we always
++       * allocate the corresponding VIRQ, so that we can keep fixed
++       * values for all VIRQ numbers.
++       */
++      virq = ipipe_alloc_virq();
++      BUG_ON(virq != IPIPE_DOORBELL_VIRQ);
 +#ifdef CONFIG_SMP
 +      virq = ipipe_alloc_virq();
 +      BUG_ON(virq != IPIPE_CRITICAL_IPI);
@@ -2681,6 +3002,13 @@ index 0000000..9a5702a
 +                        __ipipe_do_timer, NULL,
 +                        NULL);
 +
++#ifdef CONFIG_PPC_DOORBELL
++      ipipe_request_irq(ipipe_root_domain,
++                        IPIPE_DOORBELL_VIRQ,
++                        __ipipe_do_doorbell, NULL,
++                        NULL);
++#endif
++      
 +      ipipe_critical_exit(flags);
 +}
 +
@@ -2741,10 +3069,13 @@ index 0000000..9a5702a
 +      if (likely(irq != NO_IRQ)) {
 +              ipipe_trace_irq_entry(irq);
 +#ifdef CONFIG_SMP
-+              /* Check for cascaded I-pipe IPIs */
-+              if (irq == __ipipe_ipi_irq)
-+                      __ipipe_ipi_demux(irq, regs);
-+              else
++              if (irq == mux_ipi) {
++                      struct irq_desc *desc = irq_to_desc(irq);
++                      desc->ipipe_ack(irq, desc);
++                      kstat_incr_irq_this_cpu(irq);
++                      do_ipi_demux(irq, regs);
++                      ipipe_end_irq(irq);
++              } else
 +#endif /* CONFIG_SMP */
 +                      __ipipe_handle_irq(irq, regs);
 +      }
@@ -2771,6 +3102,23 @@ index 0000000..9a5702a
 +      timer_interrupt(raw_cpu_ptr(&ipipe_percpu.tick_regs));
 +}
 +
++#ifdef CONFIG_PPC_DOORBELL
++
++int __ipipe_grab_doorbell(struct pt_regs *regs)
++{
++#ifdef CONFIG_SMP
++      do_ipi_demux(IPIPE_DOORBELL_VIRQ, regs);
++#endif
++      return __ipipe_exit_irq(regs);
++}
++
++static void __ipipe_do_doorbell(unsigned int irq, void *cookie)
++{
++      doorbell_exception(raw_cpu_ptr(&ipipe_percpu.tick_regs));
++}
++
++#endif
++
 +int __ipipe_grab_timer(struct pt_regs *regs)
 +{
 +      struct pt_regs *tick_regs;
@@ -2814,7 +3162,7 @@ index 0000000..9a5702a
 +#endif        /* !CONFIG_PPC64 */
 +#endif /* !CONFIG_IPIPE_LEGACY */
 diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
-index 4509603..8d64765 100644
+index 4509603..c63ea4c 100644
 --- a/arch/powerpc/kernel/irq.c
 +++ b/arch/powerpc/kernel/irq.c
 @@ -94,6 +94,36 @@ extern int tau_interrupts(int);
@@ -2846,7 +3194,7 @@ index 4509603..8d64765 100644
 +static inline notrace int decrementer_check_overflow(void)
 +{
 +      u64 now = get_tb_or_rtc();
-+      u64 *next_tb = &__get_cpu_var(decrementers_next_tb);
++      u64 *next_tb = this_cpu_ptr(&decrementers_next_tb);
 + 
 +      return now >= *next_tb;
 +}
@@ -2987,7 +3335,7 @@ index 4509603..8d64765 100644
  
        set_irq_regs(old_regs);
  }
-@@ -595,6 +613,19 @@ void exc_lvl_ctx_init(void)
+@@ -595,6 +613,21 @@ void exc_lvl_ctx_init(void)
  }
  #endif
  
@@ -2997,17 +3345,19 @@ index 4509603..8d64765 100644
 +
 +void irq_ctx_init(void) { }
 +
++#ifndef CONFIG_PREEMPT_RT_FULL
 +void do_softirq_own_stack(void)
 +{
 +      __do_softirq();
 +}
++#endif
 +
 +#else  /* !CONFIG_IPIPE */
 +
  struct thread_info *softirq_ctx[NR_CPUS] __read_mostly;
  struct thread_info *hardirq_ctx[NR_CPUS] __read_mostly;
  
-@@ -632,6 +663,8 @@ void do_softirq_own_stack(void)
+@@ -632,6 +665,8 @@ void do_softirq_own_stack(void)
                set_bits(irqtp->flags, &curtp->flags);
  }
  
@@ -3300,7 +3650,7 @@ index c69671c..66ac366 100644
  #endif
  
 diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
-index ec9ec20..a17ba31 100644
+index ec9ec20..73ba6f2 100644
 --- a/arch/powerpc/kernel/smp.c
 +++ b/arch/powerpc/kernel/smp.c
 @@ -179,7 +179,7 @@ const char *smp_ipi_name[] = {
@@ -3312,7 +3662,7 @@ index ec9ec20..a17ba31 100644
  };
  
  /* optional function to request ipi, for controllers with >= 4 ipis */
-@@ -190,10 +190,10 @@ int smp_request_message_ipi(int virq, int msg)
+@@ -190,10 +190,9 @@ int smp_request_message_ipi(int virq, int msg)
        if (msg < 0 || msg > PPC_MSG_DEBUGGER_BREAK) {
                return -EINVAL;
        }
@@ -3322,12 +3672,36 @@ index ec9ec20..a17ba31 100644
 -      }
 +#ifdef CONFIG_IPIPE
 +      if (msg == PPC_MSG_DEBUGGER_BREAK)
-+              /* Piggyback the debugger IPI for the I-pipe. */
-+              __ipipe_register_ipi(virq);
++              __ipipe_register_mux_ipi(virq);
  #endif
        err = request_irq(virq, smp_ipi_action[msg],
                          IRQF_PERCPU | IRQF_NO_THREAD | IRQF_NO_SUSPEND,
-@@ -314,8 +314,12 @@ void smp_send_debugger_break(void)
+@@ -262,6 +261,24 @@ irqreturn_t smp_ipi_demux(void)
+ 
+       return IRQ_HANDLED;
+ }
++
++#ifdef CONFIG_IPIPE
++
++void __ipipe_finish_ipi_demux(unsigned int irq)
++{
++      struct cpu_messages *info = this_cpu_ptr(&ipi_message);
++
++      /* Propagate remaining events to the root domain. */
++      if (info->messages)
++              __ipipe_handle_irq(irq, NULL);
++}
++
++#endif
++
++#elif defined(CONFIG_IPIPE)
++
++void __ipipe_finish_ipi_demux(unsigned int irq) { }
++
+ #endif /* CONFIG_PPC_SMP_MUXED_IPI */
+ 
+ static inline void do_message_pass(int cpu, int msg)
+@@ -314,8 +331,12 @@ void smp_send_debugger_break(void)
                return;
  
        for_each_online_cpu(cpu)
@@ -3341,7 +3715,7 @@ index ec9ec20..a17ba31 100644
  }
  #endif
  
-@@ -680,6 +684,9 @@ void start_secondary(void *unused)
+@@ -680,6 +701,9 @@ void start_secondary(void *unused)
        unsigned int cpu = smp_processor_id();
        int i, base;
  
@@ -4903,10 +5277,18 @@ index b83f325..782d29f 100644
 +      }
  }
 diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c
-index fd16cb5..884694d 100644
+index fd16cb5..088f7a2 100644
 --- a/arch/powerpc/sysdev/fsl_msi.c
 +++ b/arch/powerpc/sysdev/fsl_msi.c
-@@ -316,7 +316,7 @@ static irqreturn_t fsl_msi_cascade(int irq, void *data)
+@@ -19,6 +19,7 @@
+ #include <linux/of_platform.h>
+ #include <linux/interrupt.h>
+ #include <linux/seq_file.h>
++#include <linux/ipipe.h>
+ #include <sysdev/fsl_soc.h>
+ #include <asm/prom.h>
+ #include <asm/hw_irq.h>
+@@ -316,7 +317,7 @@ static irqreturn_t fsl_msi_cascade(int irq, void *data)
                                msi_hwirq(msi_data, msir_index,
                                          intr_index + have_shift));
                if (cascade_irq != NO_IRQ) {
@@ -4915,7 +5297,7 @@ index fd16cb5..884694d 100644
                        ret = IRQ_HANDLED;
                }
                have_shift += intr_index + 1;
-@@ -326,6 +326,13 @@ static irqreturn_t fsl_msi_cascade(int irq, void *data)
+@@ -326,6 +327,13 @@ static irqreturn_t fsl_msi_cascade(int irq, void *data)
        return ret;
  }
  
@@ -4929,7 +5311,7 @@ index fd16cb5..884694d 100644
  static int fsl_of_msi_remove(struct platform_device *ofdev)
  {
        struct fsl_msi *msi = platform_get_drvdata(ofdev);
-@@ -379,12 +386,17 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, 
struct platform_device *dev,
+@@ -379,12 +387,17 @@ static int fsl_msi_setup_hwirq(struct fsl_msi *msi, 
struct platform_device *dev,
        cascade_data->virq = virt_msir;
        msi->cascade_array[irq_index] = cascade_data;
  
@@ -5118,7 +5500,7 @@ index c4828c0..fb9654a 100644
  
  unsigned int mpc8xx_get_irq(void)
 diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
-index b2b8447..687357f 100644
+index b2b8447..1f85b59 100644
 --- a/arch/powerpc/sysdev/mpic.c
 +++ b/arch/powerpc/sysdev/mpic.c
 @@ -29,6 +29,7 @@
@@ -5156,10 +5538,10 @@ index b2b8447..687357f 100644
 +{
 +      unsigned long flags;
 +
-+      spin_lock_irqsave(&mpic_lock, flags);
++      raw_spin_lock_irqsave(&mpic_lock, flags);
 +      ipipe_unlock_irq(d->irq);
 +      __mpic_unmask_irq(d);
-+      spin_unlock_irqrestore(&mpic_lock, flags);
++      raw_spin_unlock_irqrestore(&mpic_lock, flags);
 +}
 +
 +void __mpic_mask_irq(struct irq_data *d)
@@ -5174,10 +5556,10 @@ index b2b8447..687357f 100644
 +{
 +      unsigned long flags;
 +
-+      spin_lock_irqsave(&mpic_lock, flags);
++      raw_spin_lock_irqsave(&mpic_lock, flags);
 +      __mpic_mask_irq(d);
 +      ipipe_lock_irq(d->irq);
-+      spin_unlock_irqrestore(&mpic_lock, flags);
++      raw_spin_unlock_irqrestore(&mpic_lock, flags);
 +}
 +
  void mpic_end_irq(struct irq_data *d)
@@ -5194,19 +5576,19 @@ index b2b8447..687357f 100644
 +      struct mpic *mpic = mpic_from_irq_data(d);
 +      unsigned long flags;
 +
-+      spin_lock_irqsave(&mpic_lock, flags);
++      raw_spin_lock_irqsave(&mpic_lock, flags);
 +      mpic_eoi(mpic);
 +      __mpic_mask_irq(d);
-+      spin_unlock_irqrestore(&mpic_lock, flags);
++      raw_spin_unlock_irqrestore(&mpic_lock, flags);
 +}
 +
 +void mpic_release_irq(struct irq_data *d)
 +{
 +      unsigned long flags;
 +
-+      spin_lock_irqsave(&mpic_lock, flags);
++      raw_spin_lock_irqsave(&mpic_lock, flags);
 +      __mpic_unmask_irq(d);
-+      spin_unlock_irqrestore(&mpic_lock, flags);
++      raw_spin_unlock_irqrestore(&mpic_lock, flags);
 +}
 +
 +#endif
@@ -5249,9 +5631,9 @@ index b2b8447..687357f 100644
  
 -      DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, d->irq, src);
 +      DBG("%s: unmask_ipi: %d (ipi %d)\n", mpic->name, d->irq, src);
-+      spin_lock_irqsave(&mpic_lock, flags);
++      raw_spin_lock_irqsave(&mpic_lock, flags);
        mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
-+      spin_unlock_irqrestore(&mpic_lock, flags);
++      raw_spin_unlock_irqrestore(&mpic_lock, flags);
  }
  
  static void mpic_mask_ipi(struct irq_data *d)
@@ -5447,6 +5829,53 @@ index 7c37157..ca1d5c9 100644
  }
  
  static struct uic * __init uic_init_one(struct device_node *node)
+diff --git a/arch/powerpc/sysdev/xics/xics-common.c 
b/arch/powerpc/sysdev/xics/xics-common.c
+index 878a540..be519cd 100644
+--- a/arch/powerpc/sysdev/xics/xics-common.c
++++ b/arch/powerpc/sysdev/xics/xics-common.c
+@@ -20,6 +20,7 @@
+ #include <linux/of.h>
+ #include <linux/slab.h>
+ #include <linux/spinlock.h>
++#include <linux/ipipe.h>
+ 
+ #include <asm/prom.h>
+ #include <asm/io.h>
+@@ -132,6 +133,7 @@ static void xics_request_ipi(void)
+ 
+       ipi = irq_create_mapping(xics_host, XICS_IPI);
+       BUG_ON(ipi == NO_IRQ);
++      __ipipe_register_mux_ipi(ipi);
+ 
+       /*
+        * IPIs are marked IRQF_PERCPU. The handler was set in map.
+@@ -313,9 +315,26 @@ static int xics_host_match(struct irq_domain *h, struct 
device_node *node)
+ static void xics_ipi_unmask(struct irq_data *d) { }
+ static void xics_ipi_mask(struct irq_data *d) { }
+ 
++#ifdef CONFIG_IPIPE
++
++static struct irq_chip xics_ipi_chip;
++
++static void xics_ipi_hold(struct irq_data *d)
++{
++      xics_ipi_chip.irq_eoi(d);
++}
++
++static void xics_ipi_release(struct irq_data *d) { }
++
++#endif
++
+ static struct irq_chip xics_ipi_chip = {
+       .name = "XICS",
+       .irq_eoi = NULL, /* Patched at init time */
++#ifdef CONFIG_IPIPE
++      .irq_hold = xics_ipi_hold,
++      .irq_release = xics_ipi_release,
++#endif
+       .irq_mask = xics_ipi_mask,
+       .irq_unmask = xics_ipi_unmask,
+ };
 diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
 index e599259..fd55e35 100644
 --- a/arch/powerpc/xmon/xmon.c
@@ -5994,6 +6423,19 @@ index 0000000..1f6e9c3
 +static inline void __ipipe_init_threadinfo(struct ipipe_threadinfo *p) { }
 +
 +#endif /* !_IPIPE_THREAD_INFO_H */
+diff --git a/include/linux/basic_mmio_gpio.h b/include/linux/basic_mmio_gpio.h
+index 0e97856..b5d7e60 100644
+--- a/include/linux/basic_mmio_gpio.h
++++ b/include/linux/basic_mmio_gpio.h
+@@ -50,7 +50,7 @@ struct bgpio_chip {
+        * Used to lock bgpio_chip->data. Also, this is needed to keep
+        * shadowed and real data registers writes together.
+        */
+-      spinlock_t lock;
++      ipipe_spinlock_t lock;
+ 
+       /* Shadowed data register to clear/set bits safely. */
+       unsigned long data;
 diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
 index 96c280b..0baa8f1 100644
 --- a/include/linux/clockchips.h
@@ -6046,6 +6488,18 @@ index 901555a..1ba117c 100644
        int     (*read)(struct console *, char *, unsigned);
        struct tty_driver *(*device)(struct console *, int *);
        void    (*unblank)(void);
+diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
+index 6cd8c0e..0951ab4 100644
+--- a/include/linux/ftrace.h
++++ b/include/linux/ftrace.h
+@@ -134,6 +134,7 @@ enum {
+       FTRACE_OPS_FL_ALLOC_TRAMP               = 1 << 12,
+       FTRACE_OPS_FL_IPMODIFY                  = 1 << 13,
+       FTRACE_OPS_FL_PID                       = 1 << 14,
++      FTRACE_OPS_FL_IPIPE_EXCLUSIVE           = 1 << 15,
+ };
+ 
+ #ifdef CONFIG_DYNAMIC_FTRACE
 diff --git a/include/linux/hardirq.h b/include/linux/hardirq.h
 index f4af034..fa16b8c 100644
 --- a/include/linux/hardirq.h
@@ -6556,10 +7010,10 @@ index 0000000..0a9b5b6
 +#endif        /* !__LINUX_IPIPE_H */
 diff --git a/include/linux/ipipe_base.h b/include/linux/ipipe_base.h
 new file mode 100644
-index 0000000..8c06eed
+index 0000000..42b368a
 --- /dev/null
 +++ b/include/linux/ipipe_base.h
-@@ -0,0 +1,360 @@
+@@ -0,0 +1,365 @@
 +/* -*- linux-c -*-
 + * include/linux/ipipe_base.h
 + *
@@ -6670,6 +7124,7 @@ index 0000000..8c06eed
 +#define IPIPE_KEVT_EXIT               4
 +#define IPIPE_KEVT_CLEANUP    5
 +#define IPIPE_KEVT_HOSTRT     6
++#define IPIPE_KEVT_CLOCKFREQ  7
 +
 +struct ipipe_vm_notifier {
 +      void (*handler)(struct ipipe_vm_notifier *nfy);
@@ -6798,6 +7253,9 @@ index 0000000..8c06eed
 +#define __ipipe_report_cleanup(mm)                                    \
 +      __ipipe_notify_kevent(IPIPE_KEVT_CLEANUP, mm)
 +
++#define __ipipe_report_clockfreq_update(freq)                         \
++      __ipipe_notify_kevent(IPIPE_KEVT_CLOCKFREQ, &(freq))
++
 +void __ipipe_notify_vm_preemption(void);
 +
 +void __ipipe_call_mayday(struct pt_regs *regs);
@@ -6817,7 +7275,8 @@ index 0000000..8c06eed
 +#define IPIPE_EVENT_EXIT      (IPIPE_FIRST_EVENT + 4)
 +#define IPIPE_EVENT_CLEANUP   (IPIPE_FIRST_EVENT + 5)
 +#define IPIPE_EVENT_HOSTRT    (IPIPE_FIRST_EVENT + 6)
-+#define IPIPE_EVENT_SYSCALL   (IPIPE_FIRST_EVENT + 7)
++#define IPIPE_EVENT_CLOCKFREQ (IPIPE_FIRST_EVENT + 7)
++#define IPIPE_EVENT_SYSCALL   (IPIPE_FIRST_EVENT + 8)
 +#define IPIPE_LAST_EVENT      IPIPE_EVENT_SYSCALL
 +#define IPIPE_NR_EVENTS               (IPIPE_LAST_EVENT + 1)
 +
@@ -7668,10 +8127,10 @@ index 0000000..d00c56b
 +#endif        /* !__LINUX_IPIPE_DOMAIN_H */
 diff --git a/include/linux/ipipe_lock.h b/include/linux/ipipe_lock.h
 new file mode 100644
-index 0000000..f71d2f1
+index 0000000..a108278
 --- /dev/null
 +++ b/include/linux/ipipe_lock.h
-@@ -0,0 +1,260 @@
+@@ -0,0 +1,327 @@
 +/*   -*- linux-c -*-
 + *   include/linux/ipipe_lock.h
 + *
@@ -7700,22 +8159,87 @@ index 0000000..f71d2f1
 +      arch_spinlock_t arch_lock;
 +} __ipipe_spinlock_t;
 +
++#define ipipe_spinlock(lock)  ((__ipipe_spinlock_t *)(lock))
 +#define ipipe_spinlock_p(lock)                                                
        \
 +      __builtin_types_compatible_p(typeof(lock), __ipipe_spinlock_t *) ||     
\
 +      __builtin_types_compatible_p(typeof(lock), __ipipe_spinlock_t [])
 +
++#define std_spinlock_raw(lock)        ((raw_spinlock_t *)(lock))
 +#define std_spinlock_raw_p(lock)                                      \
 +      __builtin_types_compatible_p(typeof(lock), raw_spinlock_t *) || \
 +      __builtin_types_compatible_p(typeof(lock), raw_spinlock_t [])
 +
++#ifdef CONFIG_PREEMPT_RT_FULL
++
++#define PICK_SPINLOCK_IRQSAVE(lock, flags)                            \
++      do {                                                            \
++              if (ipipe_spinlock_p(lock))                             \
++                      (flags) = 
__ipipe_spin_lock_irqsave(ipipe_spinlock(lock)); \
++              else if (std_spinlock_raw_p(lock))                              
\
++                      __real_raw_spin_lock_irqsave(std_spinlock_raw(lock), 
flags); \
++              else __bad_lock_type();                                 \
++      } while (0)
++
++#define PICK_SPINTRYLOCK_IRQSAVE(lock, flags)                         \
++      ({                                                              \
++              int __ret__;                                            \
++              if (ipipe_spinlock_p(lock))                             \
++                      __ret__ = 
__ipipe_spin_trylock_irqsave(ipipe_spinlock(lock), &(flags)); \
++              else if (std_spinlock_raw_p(lock))                              
\
++                      __ret__ = 
__real_raw_spin_trylock_irqsave(std_spinlock_raw(lock), flags); \
++              else __bad_lock_type();                                 \
++              __ret__;                                                \
++       })
++
++#define PICK_SPINTRYLOCK_IRQ(lock)                                    \
++      ({                                                              \
++              int __ret__;                                            \
++              if (ipipe_spinlock_p(lock))                             \
++                      __ret__ = 
__ipipe_spin_trylock_irq(ipipe_spinlock(lock)); \
++              else if (std_spinlock_raw_p(lock))                              
\
++                      __ret__ = 
__real_raw_spin_trylock_irq(std_spinlock_raw(lock)); \
++              else __bad_lock_type();                                 \
++              __ret__;                                                \
++       })
++
++#define PICK_SPINUNLOCK_IRQRESTORE(lock, flags)                               
\
++      do {                                                            \
++              if (ipipe_spinlock_p(lock))                             \
++                      __ipipe_spin_unlock_irqrestore(ipipe_spinlock(lock), 
flags); \
++              else if (std_spinlock_raw_p(lock)) {                    \
++                      __ipipe_spin_unlock_debug(flags);               \
++                      
__real_raw_spin_unlock_irqrestore(std_spinlock_raw(lock), flags); \
++              } else __bad_lock_type();                               \
++      } while (0)
++
++#define PICK_SPINOP(op, lock)                                         \
++      ({                                                              \
++              if (ipipe_spinlock_p(lock))                             \
++                      arch_spin##op(&ipipe_spinlock(lock)->arch_lock); \
++              else if (std_spinlock_raw_p(lock))                      \
++                      __real_raw_spin##op(std_spinlock_raw(lock));    \
++              else __bad_lock_type();                                 \
++              (void)0;                                                \
++      })
++
++#define PICK_SPINOP_RET(op, lock, type)                                       
\
++      ({                                                              \
++              type __ret__;                                           \
++              if (ipipe_spinlock_p(lock))                             \
++                      __ret__ = 
arch_spin##op(&ipipe_spinlock(lock)->arch_lock); \
++              else if (std_spinlock_raw_p(lock))                      \
++                      __ret__ = __real_raw_spin##op(std_spinlock_raw(lock)); \
++              else { __ret__ = -1; __bad_lock_type(); }               \
++              __ret__;                                                \
++      })
++
++#else /* !CONFIG_PREEMPT_RT_FULL */
++
++#define std_spinlock(lock)    ((spinlock_t *)(lock))
 +#define std_spinlock_p(lock)                                          \
 +      __builtin_types_compatible_p(typeof(lock), spinlock_t *) ||     \
 +      __builtin_types_compatible_p(typeof(lock), spinlock_t [])
 +
-+#define ipipe_spinlock(lock)  ((__ipipe_spinlock_t *)(lock))
-+#define std_spinlock_raw(lock)        ((raw_spinlock_t *)(lock))
-+#define std_spinlock(lock)    ((spinlock_t *)(lock))
-+
 +#define PICK_SPINLOCK_IRQSAVE(lock, flags)                            \
 +      do {                                                            \
 +              if (ipipe_spinlock_p(lock))                             \
@@ -7791,6 +8315,8 @@ index 0000000..f71d2f1
 +              __ret__;                                                \
 +      })
 +
++#endif /* !CONFIG_PREEMPT_RT_FULL */
++
 +#define arch_spin_lock_init(lock)                                     \
 +      do {                                                            \
 +              IPIPE_DEFINE_SPINLOCK(__lock__);                        \
@@ -7920,7 +8446,7 @@ index 0000000..f71d2f1
 +#define __ipipe_spin_trylock_irq(lock)                1
 +#define __ipipe_spin_trylock_irqsave(lock, x) ({ (void)(x); 1; })
 +#define __ipipe_spin_unlock_irqrestore(lock, x)       do { (void)(x); } while 
(0)
-+#define __ipipe_spin_unlock_irqbegin(lock)    do { } while (0)
++#define __ipipe_spin_unlock_irqbegin(lock)    spin_unlock(lock)
 +#define __ipipe_spin_unlock_irqcomplete(x)    do { (void)(x); } while (0)
 +#define __ipipe_spin_unlock_debug(flags)      do { } while (0)
 +
@@ -7934,10 +8460,10 @@ index 0000000..f71d2f1
 +#endif /* !__LINUX_IPIPE_LOCK_H */
 diff --git a/include/linux/ipipe_tickdev.h b/include/linux/ipipe_tickdev.h
 new file mode 100644
-index 0000000..58a4142
+index 0000000..2f065ad
 --- /dev/null
 +++ b/include/linux/ipipe_tickdev.h
-@@ -0,0 +1,145 @@
+@@ -0,0 +1,148 @@
 +/* -*- linux-c -*-
 + * include/linux/ipipe_tickdev.h
 + *
@@ -8017,6 +8543,7 @@ index 0000000..58a4142
 +                            struct clock_event_device *cdev);
 +      int (*real_set_next_event)(unsigned long evt,
 +                                 struct clock_event_device *cdev);
++      unsigned int (*refresh_freq)(void);
 +};
 +
 +#define __ipipe_hrtimer_irq __ipipe_raw_cpu_read(ipipe_percpu.hrtimer_irq)
@@ -8069,6 +8596,8 @@ index 0000000..58a4142
 +
 +unsigned ipipe_timer_ns2ticks(struct ipipe_timer *timer, unsigned ns);
 +
++void __ipipe_timer_refresh_freq(unsigned int hrclock_freq);
++
 +#else /* !CONFIG_IPIPE */
 +
 +#define ipipe_host_timer_register(clkevt) do { } while (0)
@@ -9623,7 +10152,7 @@ index 0000000..797a849
 +}
 diff --git a/kernel/ipipe/core.c b/kernel/ipipe/core.c
 new file mode 100644
-index 0000000..3b07d65
+index 0000000..339fb95
 --- /dev/null
 +++ b/kernel/ipipe/core.c
 @@ -0,0 +1,1916 @@
@@ -10451,7 +10980,7 @@ index 0000000..3b07d65
 +      unsigned long flags, irq = 0;
 +      int ipos;
 +
-+      spin_lock_irqsave(&__ipipe_lock, flags);
++      raw_spin_lock_irqsave(&__ipipe_lock, flags);
 +
 +      if (__ipipe_virtual_irq_map != ~0) {
 +              ipos = ffz(__ipipe_virtual_irq_map);
@@ -10459,7 +10988,7 @@ index 0000000..3b07d65
 +              irq = ipos + IPIPE_VIRQ_BASE;
 +      }
 +
-+      spin_unlock_irqrestore(&__ipipe_lock, flags);
++      raw_spin_unlock_irqrestore(&__ipipe_lock, flags);
 +
 +      return irq;
 +}
@@ -10489,7 +11018,7 @@ index 0000000..3b07d65
 +          (irq >= IPIPE_NR_XIRQS && !ipipe_virtual_irq_p(irq)))
 +              return -EINVAL;
 +
-+      spin_lock_irqsave(&__ipipe_lock, flags);
++      raw_spin_lock_irqsave(&__ipipe_lock, flags);
 +
 +      if (ipd->irqs[irq].handler) {
 +              ret = -EBUSY;
@@ -10507,7 +11036,7 @@ index 0000000..3b07d65
 +      if (irq < IPIPE_NR_ROOT_IRQS)
 +              __ipipe_enable_irqdesc(ipd, irq);
 +out:
-+      spin_unlock_irqrestore(&__ipipe_lock, flags);
++      raw_spin_unlock_irqrestore(&__ipipe_lock, flags);
 +
 +      return ret;
 +}
@@ -10522,7 +11051,7 @@ index 0000000..3b07d65
 +      ipipe_root_only();
 +#endif /* CONFIG_IPIPE_LEGACY */
 +
-+      spin_lock_irqsave(&__ipipe_lock, flags);
++      raw_spin_lock_irqsave(&__ipipe_lock, flags);
 +
 +      if (ipd->irqs[irq].handler == NULL)
 +              goto out;
@@ -10535,7 +11064,7 @@ index 0000000..3b07d65
 +      if (irq < IPIPE_NR_ROOT_IRQS)
 +              __ipipe_disable_irqdesc(ipd, irq);
 +out:
-+      spin_unlock_irqrestore(&__ipipe_lock, flags);
++      raw_spin_unlock_irqrestore(&__ipipe_lock, flags);
 +}
 +EXPORT_SYMBOL_GPL(ipipe_free_irq);
 +
@@ -11178,7 +11707,7 @@ index 0000000..3b07d65
 +       * another CPU. Enter a spinning wait until he releases the
 +       * global lock.
 +       */
-+      spin_lock(&__ipipe_cpu_barrier);
++      raw_spin_lock(&__ipipe_cpu_barrier);
 +
 +      /* Got it. Now get out. */
 +
@@ -11188,7 +11717,7 @@ index 0000000..3b07d65
 +
 +      cpumask_set_cpu(cpu, &__ipipe_cpu_pass_map);
 +
-+      spin_unlock(&__ipipe_cpu_barrier);
++      raw_spin_unlock(&__ipipe_cpu_barrier);
 +
 +      cpumask_clear_cpu(cpu, &__ipipe_cpu_sync_map);
 +}
@@ -11221,7 +11750,7 @@ index 0000000..3b07d65
 +              }
 +restart:
 +              online = *cpu_online_mask;
-+              spin_lock(&__ipipe_cpu_barrier);
++              raw_spin_lock(&__ipipe_cpu_barrier);
 +
 +              __ipipe_cpu_sync = syncfn;
 +
@@ -11247,7 +11776,7 @@ index 0000000..3b07d65
 +                       */
 +                      __ipipe_cpu_sync = NULL;
 +
-+                      spin_unlock(&__ipipe_cpu_barrier);
++                      raw_spin_unlock(&__ipipe_cpu_barrier);
 +                      /*
 +                       * Ensure all CPUs consumed the IPI to avoid
 +                       * running __ipipe_cpu_sync prematurely. This
@@ -11277,7 +11806,7 @@ index 0000000..3b07d65
 +
 +#ifdef CONFIG_SMP
 +      if (atomic_dec_and_test(&__ipipe_critical_count)) {
-+              spin_unlock(&__ipipe_cpu_barrier);
++              raw_spin_unlock(&__ipipe_cpu_barrier);
 +              while (!cpumask_empty(&__ipipe_cpu_sync_map))
 +                      cpu_relax();
 +              cpumask_clear_cpu(ipipe_processor_id(), &__ipipe_cpu_lock_map);
@@ -11545,10 +12074,10 @@ index 0000000..3b07d65
 +#endif
 diff --git a/kernel/ipipe/timer.c b/kernel/ipipe/timer.c
 new file mode 100644
-index 0000000..73f748e
+index 0000000..a9917f4
 --- /dev/null
 +++ b/kernel/ipipe/timer.c
-@@ -0,0 +1,497 @@
+@@ -0,0 +1,520 @@
 +/* -*- linux-c -*-
 + * linux/kernel/ipipe/timer.c
 + *
@@ -11675,7 +12204,7 @@ index 0000000..73f748e
 +      if (timer->cpumask == NULL)
 +              timer->cpumask = cpumask_of(smp_processor_id());
 +
-+      spin_lock_irqsave(&lock, flags);
++      raw_spin_lock_irqsave(&lock, flags);
 +
 +      list_for_each_entry(t, &timers, link) {
 +              if (t->rating <= timer->rating) {
@@ -11685,7 +12214,7 @@ index 0000000..73f748e
 +      }
 +      list_add_tail(&timer->link, &timers);
 +  done:
-+      spin_unlock_irqrestore(&lock, flags);
++      raw_spin_unlock_irqrestore(&lock, flags);
 +}
 +
 +static void ipipe_timer_request_sync(void)
@@ -11708,18 +12237,14 @@ index 0000000..73f748e
 +      timer->request(timer, steal);
 +}
 +
-+/* Set up a timer as per-cpu timer for ipipe */
-+static void install_pcpu_timer(unsigned cpu, unsigned hrclock_freq,
-+                            struct ipipe_timer *t) {
-+      unsigned hrtimer_freq;
++static void config_pcpu_timer(struct ipipe_timer *t, unsigned hrclock_freq)
++{
 +      unsigned long long tmp;
++      unsigned hrtimer_freq;
 +
-+      if (__ipipe_hrtimer_freq == 0)
++      if (__ipipe_hrtimer_freq != t->freq)
 +              __ipipe_hrtimer_freq = t->freq;
 +
-+      per_cpu(ipipe_percpu.hrtimer_irq, cpu) = t->irq;
-+      per_cpu(percpu_timer, cpu) = t;
-+
 +      hrtimer_freq = t->freq;
 +      if (__ipipe_hrclock_freq > UINT_MAX)
 +              hrtimer_freq /= 1000;
@@ -11732,6 +12257,15 @@ index 0000000..73f748e
 +      t->c2t_frac = tmp;
 +}
 +
++/* Set up a timer as per-cpu timer for ipipe */
++static void install_pcpu_timer(unsigned cpu, unsigned hrclock_freq,
++                            struct ipipe_timer *t)
++{
++      per_cpu(ipipe_percpu.hrtimer_irq, cpu) = t->irq;
++      per_cpu(percpu_timer, cpu) = t;
++      config_pcpu_timer(t, hrclock_freq);
++}
++
 +static void select_root_only_timer(unsigned cpu, unsigned hrclock_khz,
 +                                 const struct cpumask *mask,
 +                                 struct ipipe_timer *t) {
@@ -11785,7 +12319,7 @@ index 0000000..73f748e
 +      } else
 +              hrclock_freq = __ipipe_hrclock_freq;
 +
-+      spin_lock_irqsave(&lock, flags);
++      raw_spin_lock_irqsave(&lock, flags);
 +
 +      /* First, choose timers for the CPUs handled by ipipe */
 +      for_each_cpu(cpu, mask) {
@@ -11825,7 +12359,7 @@ index 0000000..73f748e
 +              }
 +      }
 +
-+      spin_unlock_irqrestore(&lock, flags);
++      raw_spin_unlock_irqrestore(&lock, flags);
 +
 +      flags = ipipe_critical_enter(ipipe_timer_request_sync);
 +      ipipe_timer_request_sync();
@@ -11834,7 +12368,7 @@ index 0000000..73f748e
 +      return 0;
 +
 +err_remove_all:
-+      spin_unlock_irqrestore(&lock, flags);
++      raw_spin_unlock_irqrestore(&lock, flags);
 +
 +      for_each_cpu(cpu, mask) {
 +              per_cpu(ipipe_percpu.hrtimer_irq, cpu) = -1;
@@ -12046,9 +12580,27 @@ index 0000000..73f748e
 +}
 +
 +#endif /* CONFIG_IPIPE_HAVE_HOSTRT */
++
++int clockevents_program_event(struct clock_event_device *dev, ktime_t expires,
++                            bool force);
++
++void __ipipe_timer_refresh_freq(unsigned int hrclock_freq)
++{
++      struct ipipe_timer *t = __ipipe_raw_cpu_read(percpu_timer);
++      unsigned long flags;
++
++      if (t && t->refresh_freq) {
++              t->freq = t->refresh_freq();
++              flags = hard_local_irq_save();
++              config_pcpu_timer(t, hrclock_freq);
++              hard_local_irq_restore(flags);
++              clockevents_program_event(t->host_timer,
++                                        t->host_timer->next_event, false);
++      }
++}
 diff --git a/kernel/ipipe/tracer.c b/kernel/ipipe/tracer.c
 new file mode 100644
-index 0000000..da272c50
+index 0000000..1ae7bc2
 --- /dev/null
 +++ b/kernel/ipipe/tracer.c
 @@ -0,0 +1,1468 @@
@@ -12113,7 +12665,7 @@ index 0000000..da272c50
 +#define IPIPE_TFLG_CURRDOM_SHIFT    10         /* bits 10..11: current domain 
*/
 +#define IPIPE_TFLG_CURRDOM_MASK           0x0C00
 +#define IPIPE_TFLG_DOMSTATE_SHIFT   12         /* bits 12..15: domain 
stalled? */
-+#define IPIPE_TFLG_DOMSTATE_BITS    3
++#define IPIPE_TFLG_DOMSTATE_BITS    1
 +
 +#define IPIPE_TFLG_DOMAIN_STALLED(point, n) \
 +      (point->flags & (1 << (n + IPIPE_TFLG_DOMSTATE_SHIFT)))
@@ -12256,7 +12808,7 @@ index 0000000..da272c50
 +      if (length > per_cpu(trace_path, cpu)[per_cpu(max_path, cpu)].length) {
 +              /* we need protection here against other cpus trying
 +                 to start a proc dump */
-+              spin_lock(&global_path_lock);
++              raw_spin_lock(&global_path_lock);
 +
 +              /* active path holds new worst case */
 +              tp->length = length;
@@ -12265,7 +12817,7 @@ index 0000000..da272c50
 +              /* find next unused trace path */
 +              active = __ipipe_get_free_trace_path(active, cpu);
 +
-+              spin_unlock(&global_path_lock);
++              raw_spin_unlock(&global_path_lock);
 +
 +              tp = &per_cpu(trace_path, cpu)[active];
 +
@@ -12288,7 +12840,7 @@ index 0000000..da272c50
 +
 +      /* we need protection here against other cpus trying
 +       * to set their frozen path or to start a proc dump */
-+      spin_lock(&global_path_lock);
++      raw_spin_lock(&global_path_lock);
 +
 +      per_cpu(frozen_path, cpu) = active;
 +
@@ -12302,7 +12854,7 @@ index 0000000..da272c50
 +                      tp->end = -1;
 +      }
 +
-+      spin_unlock(&global_path_lock);
++      raw_spin_unlock(&global_path_lock);
 +
 +      tp = &per_cpu(trace_path, cpu)[active];
 +
@@ -12457,7 +13009,7 @@ index 0000000..da272c50
 +      int cpu;
 +      struct ipipe_trace_path *tp;
 +
-+      spin_lock_irqsave(&global_path_lock, flags);
++      raw_spin_lock_irqsave(&global_path_lock, flags);
 +
 +      cpu = ipipe_processor_id();
 + restart:
@@ -13386,7 +13938,7 @@ index 0000000..da272c50
 +
 +static struct ftrace_ops ipipe_trace_ops = {
 +      .func = ipipe_trace_function,
-+      .flags = FTRACE_OPS_FL_RECURSION_SAFE,
++      .flags = FTRACE_OPS_FL_IPIPE_EXCLUSIVE,
 +};
 +
 +static ssize_t __ipipe_wr_enable(struct file *file, const char __user *buffer,
@@ -14273,7 +14825,7 @@ index 2329daa..79cfe9b 100644
        if (pm_wakeup_pending()) {
                error = -EAGAIN;
 diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
-index 3c1aca0..90b1189 100644
+index 3c1aca0..ae6b3d5 100644
 --- a/kernel/printk/printk.c
 +++ b/kernel/printk/printk.c
 @@ -62,6 +62,9 @@ int console_printk[4] = {
@@ -14389,7 +14941,7 @@ index 3c1aca0..90b1189 100644
 +      goto start;
 +
 +      do {
-+              spin_unlock_irqrestore(&__ipipe_printk_lock, flags);
++              raw_spin_unlock_irqrestore(&__ipipe_printk_lock, flags);
 + start:
 +              lmax = __ipipe_printk_fill;
 +              while (out < lmax) {
@@ -14398,13 +14950,13 @@ index 3c1aca0..90b1189 100644
 +                      p += len;
 +                      out += len;
 +              }
-+              spin_lock_irqsave(&__ipipe_printk_lock, flags);
++              raw_spin_lock_irqsave(&__ipipe_printk_lock, flags);
 +      }
 +      while (__ipipe_printk_fill != lmax);
 +
 +      __ipipe_printk_fill = 0;
 +
-+      spin_unlock_irqrestore(&__ipipe_printk_lock, flags);
++      raw_spin_unlock_irqrestore(&__ipipe_printk_lock, flags);
 +}
 +
  /**
@@ -14442,7 +14994,7 @@ index 3c1aca0..90b1189 100644
 +              goto out;
 +      }
 +
-+      spin_lock_irqsave(&__ipipe_printk_lock, flags);
++      raw_spin_lock_irqsave(&__ipipe_printk_lock, flags);
 +
 +      oldcount = __ipipe_printk_fill;
 +      fbytes = __LOG_BUF_LEN - oldcount;
@@ -14453,7 +15005,7 @@ index 3c1aca0..90b1189 100644
 +      } else
 +              r = 0;
 +
-+      spin_unlock_irqrestore(&__ipipe_printk_lock, flags);
++      raw_spin_unlock_irqrestore(&__ipipe_printk_lock, flags);
 +
 +      if (oldcount == 0)
 +              ipipe_raise_irq(__ipipe_printk_virq);
@@ -15102,7 +15654,7 @@ index 3b9a48a..edd9470 100644
        help
          This option will modify all the calls to function tracing
 diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
-index eb11011..5fa6c0a 100644
+index eb11011..d0957bd 100644
 --- a/kernel/trace/ftrace.c
 +++ b/kernel/trace/ftrace.c
 @@ -32,6 +32,7 @@
@@ -15113,7 +15665,33 @@ index eb11011..5fa6c0a 100644
  
  #include <trace/events/sched.h>
  
-@@ -2518,6 +2519,9 @@ void __weak arch_ftrace_update_code(int command)
+@@ -262,8 +263,17 @@ static ftrace_func_t ftrace_ops_get_list_func(struct 
ftrace_ops *ops)
+ 
+ static void update_ftrace_function(void)
+ {
++      struct ftrace_ops *ops;
+       ftrace_func_t func;
+ 
++      for (ops = ftrace_ops_list;
++           ops != &ftrace_list_end; ops = ops->next)
++              if (ops->flags & FTRACE_OPS_FL_IPIPE_EXCLUSIVE) {
++                      set_function_trace_op = ops;
++                      func = ops->func;
++                      goto set_pointers;
++              }
++
+       /*
+        * Prepare the ftrace_ops that the arch callback will use.
+        * If there's only one ftrace_ops registered, the ftrace_ops_list
+@@ -291,6 +301,7 @@ static void update_ftrace_function(void)
+ 
+       update_function_graph_func();
+ 
++  set_pointers:
+       /* If there's no change, then do nothing more here */
+       if (ftrace_trace_function == func)
+               return;
+@@ -2518,6 +2529,9 @@ void __weak arch_ftrace_update_code(int command)
  
  static void ftrace_run_update_code(int command)
  {
@@ -15123,7 +15701,7 @@ index eb11011..5fa6c0a 100644
        int ret;
  
        ret = ftrace_arch_code_modify_prepare();
-@@ -2531,7 +2535,13 @@ static void ftrace_run_update_code(int command)
+@@ -2531,7 +2545,13 @@ static void ftrace_run_update_code(int command)
         * is safe. The stop_machine() is the safest, but also
         * produces the most overhead.
         */
@@ -15137,7 +15715,7 @@ index eb11011..5fa6c0a 100644
  
        ret = ftrace_arch_code_modify_post_process();
        FTRACE_WARN_ON(ret);
-@@ -4877,10 +4887,10 @@ static int ftrace_process_locs(struct module *mod,
+@@ -4877,10 +4897,10 @@ static int ftrace_process_locs(struct module *mod,
         * reason to cause large interrupt latencies while we do it.
         */
        if (!mod)
@@ -15150,7 +15728,7 @@ index eb11011..5fa6c0a 100644
        ret = 0;
   out:
        mutex_unlock(&ftrace_lock);
-@@ -4979,9 +4989,11 @@ void __init ftrace_init(void)
+@@ -4979,9 +4999,11 @@ void __init ftrace_init(void)
        unsigned long count, flags;
        int ret;
  
@@ -15164,7 +15742,7 @@ index eb11011..5fa6c0a 100644
        if (ret)
                goto failed;
  
-@@ -5174,7 +5186,16 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long 
parent_ip,
+@@ -5174,7 +5196,16 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long 
parent_ip,
                }
        } while_for_each_ftrace_op(op);
  out:
@@ -15524,24 +16102,22 @@ index 86c8911..373a30b 100644
        return err;
  }
 diff --git a/lib/smp_processor_id.c b/lib/smp_processor_id.c
-index 1afec32..5803111 100644
+index 1afec32..f7c1a2a 100644
 --- a/lib/smp_processor_id.c
 +++ b/lib/smp_processor_id.c
-@@ -12,10 +12,13 @@ notrace static unsigned int 
check_preemption_disabled(const char *what1,
+@@ -12,6 +12,12 @@ notrace static unsigned int check_preemption_disabled(const 
char *what1,
  {
        int this_cpu = raw_smp_processor_id();
  
++      if (hard_irqs_disabled())
++              goto out;
++
 +      if (!ipipe_root_p)
 +              goto out;
 +
        if (likely(preempt_count()))
                goto out;
  
--      if (irqs_disabled())
-+      if (irqs_disabled() || hard_irqs_disabled())
-               goto out;
- 
-       /*
 diff --git a/mm/memory.c b/mm/memory.c
 index 2a9e098..46ec4cd 100644
 --- a/mm/memory.c
@@ -15749,7 +16325,7 @@ index 2a9e098..46ec4cd 100644
  
  static struct kmem_cache *page_ptl_cachep;
 diff --git a/mm/mlock.c b/mm/mlock.c
-index 3d3ee6c..ed47c08 100644
+index 3d3ee6ca..ed47c08 100644
 --- a/mm/mlock.c
 +++ b/mm/mlock.c
 @@ -756,3 +756,28 @@ void user_shm_unlock(size_t size, struct user_struct 
*user)
@@ -15884,3 +16460,16 @@ index 2faaa29..ef00f26 100644
        return nr;
  }
  
+diff --git a/sound/soc/intel/atom/sst/sst.c b/sound/soc/intel/atom/sst/sst.c
+index 96c2e42..2e6e3cf 100644
+--- a/sound/soc/intel/atom/sst/sst.c
++++ b/sound/soc/intel/atom/sst/sst.c
+@@ -369,7 +369,7 @@ static inline void sst_restore_shim64(struct intel_sst_drv 
*ctx,
+        */
+       spin_lock_irqsave(&ctx->ipc_spin_lock, irq_flags);
+       sst_shim_write64(shim, SST_IMRX, shim_regs->imrx),
+-      sst_shim_write64(shim, SST_CSR, shim_regs->csr),
++      sst_shim_write64(shim, SST_CSR, shim_regs->csr);
+       spin_unlock_irqrestore(&ctx->ipc_spin_lock, irq_flags);
+ }
+ 


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

Reply via email to