#include <asm/pgalloc.h>
 #include <asm/mach_apic.h>
 #include <asm/nmi.h>
+#include <asm/idle.h>
 
 int apic_verbosity;
 
         * Besides, if we don't timer interrupts ignore the global
         * interrupt lock, which is the WrongThing (tm) to do.
         */
+       exit_idle();
        irq_enter();
        smp_local_timer_interrupt(regs);
        irq_exit();
 asmlinkage void smp_spurious_interrupt(void)
 {
        unsigned int v;
+       exit_idle();
        irq_enter();
        /*
         * Check if this really is a spurious interrupt and ACK it
 {
        unsigned int v, v1;
 
+       exit_idle();
        irq_enter();
        /* First tickle the hardware, only then report what went on. -- REW */
        v = apic_read(APIC_ESR);
 
 #include <linux/utsname.h>
 #include <linux/random.h>
 #include <linux/kprobes.h>
+#include <linux/notifier.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/desc.h>
 #include <asm/proto.h>
 #include <asm/ia32.h>
+#include <asm/idle.h>
 
 asmlinkage extern void ret_from_fork(void);
 
 void (*pm_idle)(void);
 static DEFINE_PER_CPU(unsigned int, cpu_idle_state);
 
+static struct notifier_block *idle_notifier;
+static DEFINE_SPINLOCK(idle_notifier_lock);
+
+void idle_notifier_register(struct notifier_block *n)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&idle_notifier_lock, flags);
+       notifier_chain_register(&idle_notifier, n);
+       spin_unlock_irqrestore(&idle_notifier_lock, flags);
+}
+EXPORT_SYMBOL_GPL(idle_notifier_register);
+
+void idle_notifier_unregister(struct notifier_block *n)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&idle_notifier_lock, flags);
+       notifier_chain_unregister(&idle_notifier, n);
+       spin_unlock_irqrestore(&idle_notifier_lock, flags);
+}
+EXPORT_SYMBOL(idle_notifier_unregister);
+
+enum idle_state { CPU_IDLE, CPU_NOT_IDLE };
+static DEFINE_PER_CPU(enum idle_state, idle_state) = CPU_NOT_IDLE;
+
+void enter_idle(void)
+{
+       __get_cpu_var(idle_state) = CPU_IDLE;
+       notifier_call_chain(&idle_notifier, IDLE_START, NULL);
+}
+
+static void __exit_idle(void)
+{
+       __get_cpu_var(idle_state) = CPU_NOT_IDLE;
+       notifier_call_chain(&idle_notifier, IDLE_END, NULL);
+}
+
+/* Called from interrupts to signify idle end */
+void exit_idle(void)
+{
+       if (current->pid | read_pda(irqcount))
+               return;
+       __exit_idle();
+}
+
 /*
  * We use this if we don't have any better
  * idle routine..
                                idle = default_idle;
                        if (cpu_is_offline(smp_processor_id()))
                                play_dead();
+                       enter_idle();
                        idle();
+                       __exit_idle();
                }
 
                preempt_enable_no_resched();