RE: [PATCH V2 2/5] X86: Hyper-V: Enable IPI enlightenments

2018-05-09 Thread Michael Kelley (EOSG)
> -Original Message-
> From: k...@linuxonhyperv.com <k...@linuxonhyperv.com>
> Sent: Thursday, May 3, 2018 11:08 PM
> To: x...@kernel.org; gre...@linuxfoundation.org; linux-kernel@vger.kernel.org;
> de...@linuxdriverproject.org; o...@aepfle.de; a...@canonical.com; 
> jasow...@redhat.com;
> t...@linutronix.de; h...@zytor.com; Stephen Hemminger 
> <sthem...@microsoft.com>;
> Michael Kelley (EOSG) <michael.h.kel...@microsoft.com>; vkuzn...@redhat.com
> Cc: KY Srinivasan <k...@microsoft.com>
> Subject: [PATCH V2 2/5] X86: Hyper-V: Enable IPI enlightenments
> 
> From: "K. Y. Srinivasan" <k...@microsoft.com>
> 
> Hyper-V supports hypercalls to implement IPI; use them.
> 
> Signed-off-by: K. Y. Srinivasan <k...@microsoft.com>
> ---

Reviewed-by: Michael Kelley <mikel...@microsoft.com>


RE: [PATCH V2 2/5] X86: Hyper-V: Enable IPI enlightenments

2018-05-09 Thread Michael Kelley (EOSG)
> -Original Message-
> From: k...@linuxonhyperv.com 
> Sent: Thursday, May 3, 2018 11:08 PM
> To: x...@kernel.org; gre...@linuxfoundation.org; linux-kernel@vger.kernel.org;
> de...@linuxdriverproject.org; o...@aepfle.de; a...@canonical.com; 
> jasow...@redhat.com;
> t...@linutronix.de; h...@zytor.com; Stephen Hemminger 
> ;
> Michael Kelley (EOSG) ; vkuzn...@redhat.com
> Cc: KY Srinivasan 
> Subject: [PATCH V2 2/5] X86: Hyper-V: Enable IPI enlightenments
> 
> From: "K. Y. Srinivasan" 
> 
> Hyper-V supports hypercalls to implement IPI; use them.
> 
> Signed-off-by: K. Y. Srinivasan 
> ---

Reviewed-by: Michael Kelley 


Re: [PATCH V2 2/5] X86: Hyper-V: Enable IPI enlightenments

2018-05-04 Thread kbuild test robot
Hi Srinivasan,

I love your patch! Yet something to improve:

[auto build test ERROR on v4.17-rc3]
[also build test ERROR on next-20180504]
[cannot apply to tip/x86/core]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/kys-linuxonhyperv-com/X86-Hyper-V-APIC-enlightenments/20180505-045627
config: x86_64-randconfig-a0-05050447 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64 

All errors (new ones prefixed by >>):

   arch/x86/hyperv/hv_apic.c: In function 'hv_apic_read':
   arch/x86/hyperv/hv_apic.c:69:10: error: implicit declaration of function 
'native_apic_mem_read'; did you mean 'hv_apic_icr_read'? 
[-Werror=implicit-function-declaration]
  return native_apic_mem_read(reg);
 ^~~~
 hv_apic_icr_read
   arch/x86/hyperv/hv_apic.c: In function 'hv_apic_write':
   arch/x86/hyperv/hv_apic.c:83:3: error: implicit declaration of function 
'native_apic_mem_write'; did you mean 'hv_apic_icr_write'? 
[-Werror=implicit-function-declaration]
  native_apic_mem_write(reg, val);
  ^
  hv_apic_icr_write
   arch/x86/hyperv/hv_apic.c: In function 'hv_send_ipi':
>> arch/x86/hyperv/hv_apic.c:153:12: error: invalid use of undefined type 
>> 'struct apic'
  orig_apic.send_IPI(cpu, vector);
   ^
   arch/x86/hyperv/hv_apic.c: In function 'hv_send_ipi_mask':
   arch/x86/hyperv/hv_apic.c:159:12: error: invalid use of undefined type 
'struct apic'
  orig_apic.send_IPI_mask(mask, vector);
   ^
   arch/x86/hyperv/hv_apic.c: In function 'hv_send_ipi_mask_allbutself':
   arch/x86/hyperv/hv_apic.c:172:12: error: invalid use of undefined type 
'struct apic'
  orig_apic.send_IPI_mask_allbutself(mask, vector);
   ^
   arch/x86/hyperv/hv_apic.c: In function 'hv_send_ipi_all':
   arch/x86/hyperv/hv_apic.c:183:12: error: invalid use of undefined type 
'struct apic'
  orig_apic.send_IPI_all(vector);
   ^
   arch/x86/hyperv/hv_apic.c: In function 'hv_send_ipi_self':
   arch/x86/hyperv/hv_apic.c:189:12: error: invalid use of undefined type 
'struct apic'
  orig_apic.send_IPI_self(vector);
   ^
   arch/x86/hyperv/hv_apic.c: In function 'hv_apic_init':
>> arch/x86/hyperv/hv_apic.c:199:16: error: 'apic' undeclared (first use in 
>> this function)
  orig_apic = *apic;
   ^~~~
   arch/x86/hyperv/hv_apic.c:199:16: note: each undeclared identifier is 
reported only once for each function it appears in
>> arch/x86/hyperv/hv_apic.c:199:13: error: 'orig_apic' has an incomplete type 
>> 'struct apic'
  orig_apic = *apic;
^
   arch/x86/hyperv/hv_apic.c:211:3: error: implicit declaration of function 
'apic_set_eoi_write'; did you mean 'hv_apic_eoi_write'? 
[-Werror=implicit-function-declaration]
  apic_set_eoi_write(hv_apic_eoi_write);
  ^~
  hv_apic_eoi_write
   arch/x86/hyperv/hv_apic.c: At top level:
>> arch/x86/hyperv/hv_apic.c:35:20: error: storage size of 'orig_apic' isn't 
>> known
static struct apic orig_apic;
   ^
   cc1: some warnings being treated as errors

vim +153 arch/x86/hyperv/hv_apic.c

34  
  > 35  static struct apic orig_apic;
36  
37  static u64 hv_apic_icr_read(void)
38  {
39  u64 reg_val;
40  
41  rdmsrl(HV_X64_MSR_ICR, reg_val);
42  return reg_val;
43  }
44  
45  static void hv_apic_icr_write(u32 low, u32 id)
46  {
47  u64 reg_val;
48  
49  reg_val = SET_APIC_DEST_FIELD(id);
50  reg_val = reg_val << 32;
51  reg_val |= low;
52  
53  wrmsrl(HV_X64_MSR_ICR, reg_val);
54  }
55  
56  static u32 hv_apic_read(u32 reg)
57  {
58  u32 reg_val, hi;
59  
60  switch (reg) {
61  case APIC_EOI:
62  rdmsr(HV_X64_MSR_EOI, reg_val, hi);
63  return reg_val;
64  case APIC_TASKPRI:
65  rdmsr(HV_X64_MSR_TPR, reg_val, hi);
66  return reg_val;
67  
68  default:
69  return native_apic_mem_read(reg);
70  }
71  }
72  
73  static void hv_apic_write(u32 reg, u32 val)
74  {
75  switch (reg) {
76  case APIC_EOI:
77  wrmsr(HV_X64_MSR_EOI, val, 0);
78  break;
79  case APIC_TASKPRI:
80  wrmsr(HV_X64_MSR_TPR, val, 0);
81  break;
82  default:
  > 83  native_apic_mem_write(reg, val);
84  }
85  }
86  
87  static void hv_apic_eoi_write(u32 reg, u32 val)
88  {
89  wrmsr(HV_X64_MSR_EOI, val, 

Re: [PATCH V2 2/5] X86: Hyper-V: Enable IPI enlightenments

2018-05-04 Thread kbuild test robot
Hi Srinivasan,

I love your patch! Yet something to improve:

[auto build test ERROR on v4.17-rc3]
[also build test ERROR on next-20180504]
[cannot apply to tip/x86/core]
[if your patch is applied to the wrong git tree, please drop us a note to help 
improve the system]

url:
https://github.com/0day-ci/linux/commits/kys-linuxonhyperv-com/X86-Hyper-V-APIC-enlightenments/20180505-045627
config: x86_64-randconfig-a0-05050447 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64 

All errors (new ones prefixed by >>):

   arch/x86/hyperv/hv_apic.c: In function 'hv_apic_read':
   arch/x86/hyperv/hv_apic.c:69:10: error: implicit declaration of function 
'native_apic_mem_read'; did you mean 'hv_apic_icr_read'? 
[-Werror=implicit-function-declaration]
  return native_apic_mem_read(reg);
 ^~~~
 hv_apic_icr_read
   arch/x86/hyperv/hv_apic.c: In function 'hv_apic_write':
   arch/x86/hyperv/hv_apic.c:83:3: error: implicit declaration of function 
'native_apic_mem_write'; did you mean 'hv_apic_icr_write'? 
[-Werror=implicit-function-declaration]
  native_apic_mem_write(reg, val);
  ^
  hv_apic_icr_write
   arch/x86/hyperv/hv_apic.c: In function 'hv_send_ipi':
>> arch/x86/hyperv/hv_apic.c:153:12: error: invalid use of undefined type 
>> 'struct apic'
  orig_apic.send_IPI(cpu, vector);
   ^
   arch/x86/hyperv/hv_apic.c: In function 'hv_send_ipi_mask':
   arch/x86/hyperv/hv_apic.c:159:12: error: invalid use of undefined type 
'struct apic'
  orig_apic.send_IPI_mask(mask, vector);
   ^
   arch/x86/hyperv/hv_apic.c: In function 'hv_send_ipi_mask_allbutself':
   arch/x86/hyperv/hv_apic.c:172:12: error: invalid use of undefined type 
'struct apic'
  orig_apic.send_IPI_mask_allbutself(mask, vector);
   ^
   arch/x86/hyperv/hv_apic.c: In function 'hv_send_ipi_all':
   arch/x86/hyperv/hv_apic.c:183:12: error: invalid use of undefined type 
'struct apic'
  orig_apic.send_IPI_all(vector);
   ^
   arch/x86/hyperv/hv_apic.c: In function 'hv_send_ipi_self':
   arch/x86/hyperv/hv_apic.c:189:12: error: invalid use of undefined type 
'struct apic'
  orig_apic.send_IPI_self(vector);
   ^
   arch/x86/hyperv/hv_apic.c: In function 'hv_apic_init':
>> arch/x86/hyperv/hv_apic.c:199:16: error: 'apic' undeclared (first use in 
>> this function)
  orig_apic = *apic;
   ^~~~
   arch/x86/hyperv/hv_apic.c:199:16: note: each undeclared identifier is 
reported only once for each function it appears in
>> arch/x86/hyperv/hv_apic.c:199:13: error: 'orig_apic' has an incomplete type 
>> 'struct apic'
  orig_apic = *apic;
^
   arch/x86/hyperv/hv_apic.c:211:3: error: implicit declaration of function 
'apic_set_eoi_write'; did you mean 'hv_apic_eoi_write'? 
[-Werror=implicit-function-declaration]
  apic_set_eoi_write(hv_apic_eoi_write);
  ^~
  hv_apic_eoi_write
   arch/x86/hyperv/hv_apic.c: At top level:
>> arch/x86/hyperv/hv_apic.c:35:20: error: storage size of 'orig_apic' isn't 
>> known
static struct apic orig_apic;
   ^
   cc1: some warnings being treated as errors

vim +153 arch/x86/hyperv/hv_apic.c

34  
  > 35  static struct apic orig_apic;
36  
37  static u64 hv_apic_icr_read(void)
38  {
39  u64 reg_val;
40  
41  rdmsrl(HV_X64_MSR_ICR, reg_val);
42  return reg_val;
43  }
44  
45  static void hv_apic_icr_write(u32 low, u32 id)
46  {
47  u64 reg_val;
48  
49  reg_val = SET_APIC_DEST_FIELD(id);
50  reg_val = reg_val << 32;
51  reg_val |= low;
52  
53  wrmsrl(HV_X64_MSR_ICR, reg_val);
54  }
55  
56  static u32 hv_apic_read(u32 reg)
57  {
58  u32 reg_val, hi;
59  
60  switch (reg) {
61  case APIC_EOI:
62  rdmsr(HV_X64_MSR_EOI, reg_val, hi);
63  return reg_val;
64  case APIC_TASKPRI:
65  rdmsr(HV_X64_MSR_TPR, reg_val, hi);
66  return reg_val;
67  
68  default:
69  return native_apic_mem_read(reg);
70  }
71  }
72  
73  static void hv_apic_write(u32 reg, u32 val)
74  {
75  switch (reg) {
76  case APIC_EOI:
77  wrmsr(HV_X64_MSR_EOI, val, 0);
78  break;
79  case APIC_TASKPRI:
80  wrmsr(HV_X64_MSR_TPR, val, 0);
81  break;
82  default:
  > 83  native_apic_mem_write(reg, val);
84  }
85  }
86  
87  static void hv_apic_eoi_write(u32 reg, u32 val)
88  {
89  wrmsr(HV_X64_MSR_EOI, val, 

[PATCH V2 2/5] X86: Hyper-V: Enable IPI enlightenments

2018-05-04 Thread kys
From: "K. Y. Srinivasan" 

Hyper-V supports hypercalls to implement IPI; use them.

Signed-off-by: K. Y. Srinivasan 
---
 arch/x86/hyperv/hv_apic.c  | 118 +
 arch/x86/hyperv/hv_init.c  |  27 +
 arch/x86/include/asm/hyperv-tlfs.h |  15 +
 arch/x86/include/asm/mshyperv.h|   1 +
 4 files changed, 161 insertions(+)

diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c
index 41f8b71ca19e..f52d08a7a343 100644
--- a/arch/x86/hyperv/hv_apic.c
+++ b/arch/x86/hyperv/hv_apic.c
@@ -31,6 +31,9 @@
 #include 
 
 #if IS_ENABLED(CONFIG_HYPERV)
+
+static struct apic orig_apic;
+
 static u64 hv_apic_icr_read(void)
 {
u64 reg_val;
@@ -86,8 +89,123 @@ static void hv_apic_eoi_write(u32 reg, u32 val)
wrmsr(HV_X64_MSR_EOI, val, 0);
 }
 
+/*
+ * IPI implementation on Hyper-V.
+ */
+static bool __send_ipi_mask(const struct cpumask *mask, int vector)
+{
+   int cur_cpu, vcpu;
+   struct ipi_arg_non_ex **arg;
+   struct ipi_arg_non_ex *ipi_arg;
+   int ret = 1;
+   unsigned long flags;
+
+   if (cpumask_empty(mask))
+   return true;
+
+   if (!hv_hypercall_pg)
+   return false;
+
+   if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
+   return false;
+
+   local_irq_save(flags);
+   arg = (struct ipi_arg_non_ex **)this_cpu_ptr(hyperv_pcpu_input_arg);
+
+   ipi_arg = *arg;
+   if (unlikely(!ipi_arg))
+   goto ipi_mask_done;
+
+   ipi_arg->vector = vector;
+   ipi_arg->reserved = 0;
+   ipi_arg->cpu_mask = 0;
+
+   for_each_cpu(cur_cpu, mask) {
+   vcpu = hv_cpu_number_to_vp_number(cur_cpu);
+   /*
+* This particular version of the IPI hypercall can
+* only target upto 64 CPUs.
+*/
+   if (vcpu >= 64)
+   goto ipi_mask_done;
+
+   __set_bit(vcpu, (unsigned long *)_arg->cpu_mask);
+   }
+
+   ret = hv_do_hypercall(HVCALL_SEND_IPI, ipi_arg, NULL);
+
+ipi_mask_done:
+   local_irq_restore(flags);
+   return ((ret == 0) ? true : false);
+}
+
+static bool __send_ipi_one(int cpu, int vector)
+{
+   struct cpumask mask = CPU_MASK_NONE;
+
+   cpumask_set_cpu(cpu, );
+   return __send_ipi_mask(, vector);
+}
+
+static void hv_send_ipi(int cpu, int vector)
+{
+   if (!__send_ipi_one(cpu, vector))
+   orig_apic.send_IPI(cpu, vector);
+}
+
+static void hv_send_ipi_mask(const struct cpumask *mask, int vector)
+{
+   if (!__send_ipi_mask(mask, vector))
+   orig_apic.send_IPI_mask(mask, vector);
+}
+
+static void hv_send_ipi_mask_allbutself(const struct cpumask *mask, int vector)
+{
+   unsigned int this_cpu = smp_processor_id();
+   struct cpumask new_mask;
+   const struct cpumask *local_mask;
+
+   cpumask_copy(_mask, mask);
+   cpumask_clear_cpu(this_cpu, _mask);
+   local_mask = _mask;
+   if (!__send_ipi_mask(local_mask, vector))
+   orig_apic.send_IPI_mask_allbutself(mask, vector);
+}
+
+static void hv_send_ipi_allbutself(int vector)
+{
+   hv_send_ipi_mask_allbutself(cpu_online_mask, vector);
+}
+
+static void hv_send_ipi_all(int vector)
+{
+   if (!__send_ipi_mask(cpu_online_mask, vector))
+   orig_apic.send_IPI_all(vector);
+}
+
+static void hv_send_ipi_self(int vector)
+{
+   if (!__send_ipi_one(smp_processor_id(), vector))
+   orig_apic.send_IPI_self(vector);
+}
+
 void __init hv_apic_init(void)
 {
+   if (ms_hyperv.hints & HV_X64_CLUSTER_IPI_RECOMMENDED) {
+   pr_info("Hyper-V: Using IPI hypercalls\n");
+   /*
+* Set the IPI entry points.
+*/
+   orig_apic = *apic;
+
+   apic->send_IPI = hv_send_ipi;
+   apic->send_IPI_mask = hv_send_ipi_mask;
+   apic->send_IPI_mask_allbutself = hv_send_ipi_mask_allbutself;
+   apic->send_IPI_allbutself = hv_send_ipi_allbutself;
+   apic->send_IPI_all = hv_send_ipi_all;
+   apic->send_IPI_self = hv_send_ipi_self;
+   }
+
if (ms_hyperv.hints & HV_X64_APIC_ACCESS_RECOMMENDED) {
pr_info("Hyper-V: Using MSR based APIC access\n");
apic_set_eoi_write(hv_apic_eoi_write);
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 71e50fc2b7ef..6bc90d68ac8b 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -91,12 +91,19 @@ EXPORT_SYMBOL_GPL(hv_vp_index);
 struct hv_vp_assist_page **hv_vp_assist_page;
 EXPORT_SYMBOL_GPL(hv_vp_assist_page);
 
+void  __percpu **hyperv_pcpu_input_arg;
+EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg);
+
 u32 hv_max_vp_index;
 
 static int hv_cpu_init(unsigned int cpu)
 {
u64 msr_vp_index;
struct hv_vp_assist_page **hvp = 

[PATCH V2 2/5] X86: Hyper-V: Enable IPI enlightenments

2018-05-04 Thread kys
From: "K. Y. Srinivasan" 

Hyper-V supports hypercalls to implement IPI; use them.

Signed-off-by: K. Y. Srinivasan 
---
 arch/x86/hyperv/hv_apic.c  | 118 +
 arch/x86/hyperv/hv_init.c  |  27 +
 arch/x86/include/asm/hyperv-tlfs.h |  15 +
 arch/x86/include/asm/mshyperv.h|   1 +
 4 files changed, 161 insertions(+)

diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c
index 41f8b71ca19e..f52d08a7a343 100644
--- a/arch/x86/hyperv/hv_apic.c
+++ b/arch/x86/hyperv/hv_apic.c
@@ -31,6 +31,9 @@
 #include 
 
 #if IS_ENABLED(CONFIG_HYPERV)
+
+static struct apic orig_apic;
+
 static u64 hv_apic_icr_read(void)
 {
u64 reg_val;
@@ -86,8 +89,123 @@ static void hv_apic_eoi_write(u32 reg, u32 val)
wrmsr(HV_X64_MSR_EOI, val, 0);
 }
 
+/*
+ * IPI implementation on Hyper-V.
+ */
+static bool __send_ipi_mask(const struct cpumask *mask, int vector)
+{
+   int cur_cpu, vcpu;
+   struct ipi_arg_non_ex **arg;
+   struct ipi_arg_non_ex *ipi_arg;
+   int ret = 1;
+   unsigned long flags;
+
+   if (cpumask_empty(mask))
+   return true;
+
+   if (!hv_hypercall_pg)
+   return false;
+
+   if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
+   return false;
+
+   local_irq_save(flags);
+   arg = (struct ipi_arg_non_ex **)this_cpu_ptr(hyperv_pcpu_input_arg);
+
+   ipi_arg = *arg;
+   if (unlikely(!ipi_arg))
+   goto ipi_mask_done;
+
+   ipi_arg->vector = vector;
+   ipi_arg->reserved = 0;
+   ipi_arg->cpu_mask = 0;
+
+   for_each_cpu(cur_cpu, mask) {
+   vcpu = hv_cpu_number_to_vp_number(cur_cpu);
+   /*
+* This particular version of the IPI hypercall can
+* only target upto 64 CPUs.
+*/
+   if (vcpu >= 64)
+   goto ipi_mask_done;
+
+   __set_bit(vcpu, (unsigned long *)_arg->cpu_mask);
+   }
+
+   ret = hv_do_hypercall(HVCALL_SEND_IPI, ipi_arg, NULL);
+
+ipi_mask_done:
+   local_irq_restore(flags);
+   return ((ret == 0) ? true : false);
+}
+
+static bool __send_ipi_one(int cpu, int vector)
+{
+   struct cpumask mask = CPU_MASK_NONE;
+
+   cpumask_set_cpu(cpu, );
+   return __send_ipi_mask(, vector);
+}
+
+static void hv_send_ipi(int cpu, int vector)
+{
+   if (!__send_ipi_one(cpu, vector))
+   orig_apic.send_IPI(cpu, vector);
+}
+
+static void hv_send_ipi_mask(const struct cpumask *mask, int vector)
+{
+   if (!__send_ipi_mask(mask, vector))
+   orig_apic.send_IPI_mask(mask, vector);
+}
+
+static void hv_send_ipi_mask_allbutself(const struct cpumask *mask, int vector)
+{
+   unsigned int this_cpu = smp_processor_id();
+   struct cpumask new_mask;
+   const struct cpumask *local_mask;
+
+   cpumask_copy(_mask, mask);
+   cpumask_clear_cpu(this_cpu, _mask);
+   local_mask = _mask;
+   if (!__send_ipi_mask(local_mask, vector))
+   orig_apic.send_IPI_mask_allbutself(mask, vector);
+}
+
+static void hv_send_ipi_allbutself(int vector)
+{
+   hv_send_ipi_mask_allbutself(cpu_online_mask, vector);
+}
+
+static void hv_send_ipi_all(int vector)
+{
+   if (!__send_ipi_mask(cpu_online_mask, vector))
+   orig_apic.send_IPI_all(vector);
+}
+
+static void hv_send_ipi_self(int vector)
+{
+   if (!__send_ipi_one(smp_processor_id(), vector))
+   orig_apic.send_IPI_self(vector);
+}
+
 void __init hv_apic_init(void)
 {
+   if (ms_hyperv.hints & HV_X64_CLUSTER_IPI_RECOMMENDED) {
+   pr_info("Hyper-V: Using IPI hypercalls\n");
+   /*
+* Set the IPI entry points.
+*/
+   orig_apic = *apic;
+
+   apic->send_IPI = hv_send_ipi;
+   apic->send_IPI_mask = hv_send_ipi_mask;
+   apic->send_IPI_mask_allbutself = hv_send_ipi_mask_allbutself;
+   apic->send_IPI_allbutself = hv_send_ipi_allbutself;
+   apic->send_IPI_all = hv_send_ipi_all;
+   apic->send_IPI_self = hv_send_ipi_self;
+   }
+
if (ms_hyperv.hints & HV_X64_APIC_ACCESS_RECOMMENDED) {
pr_info("Hyper-V: Using MSR based APIC access\n");
apic_set_eoi_write(hv_apic_eoi_write);
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 71e50fc2b7ef..6bc90d68ac8b 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -91,12 +91,19 @@ EXPORT_SYMBOL_GPL(hv_vp_index);
 struct hv_vp_assist_page **hv_vp_assist_page;
 EXPORT_SYMBOL_GPL(hv_vp_assist_page);
 
+void  __percpu **hyperv_pcpu_input_arg;
+EXPORT_SYMBOL_GPL(hyperv_pcpu_input_arg);
+
 u32 hv_max_vp_index;
 
 static int hv_cpu_init(unsigned int cpu)
 {
u64 msr_vp_index;
struct hv_vp_assist_page **hvp = _vp_assist_page[smp_processor_id()];
+   void **input_arg;
+