DECLARE_PER_CPU(cpumask_t, cpu_sibling_map);
 extern cpumask_t cpu_core_map[NR_CPUS];
 
+void smp_init_cpu_poke(void);
+void scheduler_poke(void);
+
 void arch_send_call_function_single_ipi(int cpu);
 void arch_send_call_function_ipi_mask(const struct cpumask *mask);
 
 #define smp_fetch_global_regs() do { } while (0)
 #define smp_fetch_global_pmu() do { } while (0)
 #define smp_fill_in_cpu_possible_map() do { } while (0)
+#define smp_init_cpu_poke() do { } while (0)
+#define scheduler_poke() do { } while (0)
 
 #endif /* !(CONFIG_SMP) */
 
 
 
 static cpumask_t smp_commenced_mask;
 
+static DEFINE_PER_CPU(bool, poke);
+static bool cpu_poke;
+
 void smp_info(struct seq_file *m)
 {
        int i;
 {
 }
 
+static void send_cpu_ipi(int cpu)
+{
+       xcall_deliver((u64) &xcall_receive_signal,
+                       0, 0, cpumask_of(cpu));
+}
+
+void scheduler_poke(void)
+{
+       if (!cpu_poke)
+               return;
+
+       if (!__this_cpu_read(poke))
+               return;
+
+       __this_cpu_write(poke, false);
+       set_softint(1 << PIL_SMP_RECEIVE_SIGNAL);
+}
+
+static unsigned long send_cpu_poke(int cpu)
+{
+       unsigned long hv_err;
+
+       per_cpu(poke, cpu) = true;
+       hv_err = sun4v_cpu_poke(cpu);
+       if (hv_err != HV_EOK) {
+               per_cpu(poke, cpu) = false;
+               pr_err_ratelimited("%s: sun4v_cpu_poke() fails err=%lu\n",
+                                   __func__, hv_err);
+       }
+
+       return hv_err;
+}
+
 void smp_send_reschedule(int cpu)
 {
        if (cpu == smp_processor_id()) {
                WARN_ON_ONCE(preemptible());
                set_softint(1 << PIL_SMP_RECEIVE_SIGNAL);
-       } else {
-               xcall_deliver((u64) &xcall_receive_signal,
-                             0, 0, cpumask_of(cpu));
+               return;
+       }
+
+       /* Use cpu poke to resume idle cpu if supported. */
+       if (cpu_poke && idle_cpu(cpu)) {
+               unsigned long ret;
+
+               ret = send_cpu_poke(cpu);
+               if (ret == HV_EOK)
+                       return;
        }
+
+       /* Use IPI in following cases:
+        * - cpu poke not supported
+        * - cpu not idle
+        * - send_cpu_poke() returns with error
+        */
+       send_cpu_ipi(cpu);
+}
+
+void smp_init_cpu_poke(void)
+{
+       unsigned long major;
+       unsigned long minor;
+       int ret;
+
+       if (tlb_type != hypervisor)
+               return;
+
+       ret = sun4v_hvapi_get(HV_GRP_CORE, &major, &minor);
+       if (ret) {
+               pr_debug("HV_GRP_CORE is not registered\n");
+               return;
+       }
+
+       if (major == 1 && minor >= 6) {
+               /* CPU POKE is registered. */
+               cpu_poke = true;
+               return;
+       }
+
+       pr_debug("CPU_POKE not supported\n");
 }
 
 void __irq_entry smp_receive_signal_client(int irq, struct pt_regs *regs)