[PATCH 2/2] Drivers: hv: vmbus: offload the handling of channels to two workqueues

2018-11-25 Thread kys
From: Dexuan Cui 

vmbus_process_offer() mustn't call channel->sc_creation_callback()
directly for sub-channels, because sc_creation_callback() ->
vmbus_open() may never get the host's response to the
OPEN_CHANNEL message (the host may rescind a channel at any time,
e.g. in the case of hot removing a NIC), and vmbus_onoffer_rescind()
may not wake up the vmbus_open() as it's blocked due to a non-zero
vmbus_connection.offer_in_progress, and finally we have a deadlock.

The above is also true for primary channels, if the related device
drivers use sync probing mode by default.

And, usually the handling of primary channels and sub-channels can
depend on each other, so we should offload them to different
workqueues to avoid possible deadlock, e.g. in sync-probing mode,
NIC1's netvsc_subchan_work() can race with NIC2's netvsc_probe() ->
rtnl_lock(), and causes deadlock: the former gets the rtnl_lock
and waits for all the sub-channels to appear, but the latter
can't get the rtnl_lock and this blocks the handling of sub-channels.

The patch can fix the multiple-NIC deadlock described above for
v3.x kernels (e.g. RHEL 7.x) which don't support async-probing
of devices, and v4.4, v4.9, v4.14 and v4.18 which support async-probing
but don't enable async-probing for Hyper-V drivers (yet).

The patch can also fix the hang issue in sub-channel's handling described
above for all versions of kernels, including v4.19 and v4.20-rc3.

So the patch should be applied to all the existing kernels.

Fixes: 8195b1396ec8 ("hv_netvsc: fix deadlock on hotplug")
Cc: sta...@vger.kernel.org
Cc: Stephen Hemminger 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Signed-off-by: Dexuan Cui 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/channel_mgmt.c | 188 +-
 drivers/hv/connection.c   |  24 -
 drivers/hv/hyperv_vmbus.h |   7 ++
 include/linux/hyperv.h|   7 ++
 4 files changed, 161 insertions(+), 65 deletions(-)

diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 82e673671087..d01689079e9b 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -434,60 +434,16 @@ void vmbus_free_channels(void)
}
 }
 
-/*
- * vmbus_process_offer - Process the offer by creating a channel/device
- * associated with this offer
- */
-static void vmbus_process_offer(struct vmbus_channel *newchannel)
+/* Note: the function can run concurrently for primary/sub channels. */
+static void vmbus_add_channel_work(struct work_struct *work)
 {
-   struct vmbus_channel *channel;
-   bool fnew = true;
+   struct vmbus_channel *newchannel =
+   container_of(work, struct vmbus_channel, add_channel_work);
+   struct vmbus_channel *primary_channel = newchannel->primary_channel;
unsigned long flags;
u16 dev_type;
int ret;
 
-   /* Make sure this is a new offer */
-   mutex_lock(_connection.channel_mutex);
-
-   /*
-* Now that we have acquired the channel_mutex,
-* we can release the potentially racing rescind thread.
-*/
-   atomic_dec(_connection.offer_in_progress);
-
-   list_for_each_entry(channel, _connection.chn_list, listentry) {
-   if (!uuid_le_cmp(channel->offermsg.offer.if_type,
-   newchannel->offermsg.offer.if_type) &&
-   !uuid_le_cmp(channel->offermsg.offer.if_instance,
-   newchannel->offermsg.offer.if_instance)) {
-   fnew = false;
-   break;
-   }
-   }
-
-   if (fnew)
-   list_add_tail(>listentry,
- _connection.chn_list);
-
-   mutex_unlock(_connection.channel_mutex);
-
-   if (!fnew) {
-   /*
-* Check to see if this is a sub-channel.
-*/
-   if (newchannel->offermsg.offer.sub_channel_index != 0) {
-   /*
-* Process the sub-channel.
-*/
-   newchannel->primary_channel = channel;
-   spin_lock_irqsave(>lock, flags);
-   list_add_tail(>sc_list, >sc_list);
-   spin_unlock_irqrestore(>lock, flags);
-   } else {
-   goto err_free_chan;
-   }
-   }
-
dev_type = hv_get_dev_type(newchannel);
 
init_vp_index(newchannel, dev_type);
@@ -505,27 +461,26 @@ static void vmbus_process_offer(struct vmbus_channel 
*newchannel)
/*
 * This state is used to indicate a successful open
 * so that when we do close the channel normally, we
-* can cleanup properly
+* can cleanup properly.
 */
newchannel->state = CHANNEL_OPEN_STATE;
 
-   if (!fnew) {
-   struct hv_device *dev
-   = newchannel->primary_channel->device_obj;
+   if (primary_channel != NULL) {
+

[PATCH 2/2] Drivers: hv: vmbus: offload the handling of channels to two workqueues

2018-11-25 Thread kys
From: Dexuan Cui 

vmbus_process_offer() mustn't call channel->sc_creation_callback()
directly for sub-channels, because sc_creation_callback() ->
vmbus_open() may never get the host's response to the
OPEN_CHANNEL message (the host may rescind a channel at any time,
e.g. in the case of hot removing a NIC), and vmbus_onoffer_rescind()
may not wake up the vmbus_open() as it's blocked due to a non-zero
vmbus_connection.offer_in_progress, and finally we have a deadlock.

The above is also true for primary channels, if the related device
drivers use sync probing mode by default.

And, usually the handling of primary channels and sub-channels can
depend on each other, so we should offload them to different
workqueues to avoid possible deadlock, e.g. in sync-probing mode,
NIC1's netvsc_subchan_work() can race with NIC2's netvsc_probe() ->
rtnl_lock(), and causes deadlock: the former gets the rtnl_lock
and waits for all the sub-channels to appear, but the latter
can't get the rtnl_lock and this blocks the handling of sub-channels.

The patch can fix the multiple-NIC deadlock described above for
v3.x kernels (e.g. RHEL 7.x) which don't support async-probing
of devices, and v4.4, v4.9, v4.14 and v4.18 which support async-probing
but don't enable async-probing for Hyper-V drivers (yet).

The patch can also fix the hang issue in sub-channel's handling described
above for all versions of kernels, including v4.19 and v4.20-rc3.

So the patch should be applied to all the existing kernels.

Fixes: 8195b1396ec8 ("hv_netvsc: fix deadlock on hotplug")
Cc: sta...@vger.kernel.org
Cc: Stephen Hemminger 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Signed-off-by: Dexuan Cui 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/channel_mgmt.c | 188 +-
 drivers/hv/connection.c   |  24 -
 drivers/hv/hyperv_vmbus.h |   7 ++
 include/linux/hyperv.h|   7 ++
 4 files changed, 161 insertions(+), 65 deletions(-)

diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 82e673671087..d01689079e9b 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -434,60 +434,16 @@ void vmbus_free_channels(void)
}
 }
 
-/*
- * vmbus_process_offer - Process the offer by creating a channel/device
- * associated with this offer
- */
-static void vmbus_process_offer(struct vmbus_channel *newchannel)
+/* Note: the function can run concurrently for primary/sub channels. */
+static void vmbus_add_channel_work(struct work_struct *work)
 {
-   struct vmbus_channel *channel;
-   bool fnew = true;
+   struct vmbus_channel *newchannel =
+   container_of(work, struct vmbus_channel, add_channel_work);
+   struct vmbus_channel *primary_channel = newchannel->primary_channel;
unsigned long flags;
u16 dev_type;
int ret;
 
-   /* Make sure this is a new offer */
-   mutex_lock(_connection.channel_mutex);
-
-   /*
-* Now that we have acquired the channel_mutex,
-* we can release the potentially racing rescind thread.
-*/
-   atomic_dec(_connection.offer_in_progress);
-
-   list_for_each_entry(channel, _connection.chn_list, listentry) {
-   if (!uuid_le_cmp(channel->offermsg.offer.if_type,
-   newchannel->offermsg.offer.if_type) &&
-   !uuid_le_cmp(channel->offermsg.offer.if_instance,
-   newchannel->offermsg.offer.if_instance)) {
-   fnew = false;
-   break;
-   }
-   }
-
-   if (fnew)
-   list_add_tail(>listentry,
- _connection.chn_list);
-
-   mutex_unlock(_connection.channel_mutex);
-
-   if (!fnew) {
-   /*
-* Check to see if this is a sub-channel.
-*/
-   if (newchannel->offermsg.offer.sub_channel_index != 0) {
-   /*
-* Process the sub-channel.
-*/
-   newchannel->primary_channel = channel;
-   spin_lock_irqsave(>lock, flags);
-   list_add_tail(>sc_list, >sc_list);
-   spin_unlock_irqrestore(>lock, flags);
-   } else {
-   goto err_free_chan;
-   }
-   }
-
dev_type = hv_get_dev_type(newchannel);
 
init_vp_index(newchannel, dev_type);
@@ -505,27 +461,26 @@ static void vmbus_process_offer(struct vmbus_channel 
*newchannel)
/*
 * This state is used to indicate a successful open
 * so that when we do close the channel normally, we
-* can cleanup properly
+* can cleanup properly.
 */
newchannel->state = CHANNEL_OPEN_STATE;
 
-   if (!fnew) {
-   struct hv_device *dev
-   = newchannel->primary_channel->device_obj;
+   if (primary_channel != NULL) {
+

[PATCH 1/2] Drivers: hv: vmbus: check the creation_status in vmbus_establish_gpadl()

2018-11-25 Thread kys
From: Dexuan Cui 

This is a longstanding issue: if the vmbus upper-layer drivers try to
consume too many GPADLs, the host may return with an error
0xC044 (STATUS_QUOTA_EXCEEDED), but currently we forget to check
the creation_status, and hence we can pass an invalid GPADL handle
into the OPEN_CHANNEL message, and get an error code 0xc225 in
open_info->response.open_result.status, and finally we hang in
vmbus_open() -> "goto error_free_info" -> vmbus_teardown_gpadl().

With this patch, we can exit gracefully on STATUS_QUOTA_EXCEEDED.

Cc: Stephen Hemminger 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: sta...@vger.kernel.org
Signed-off-by: Dexuan Cui 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/channel.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index f96a77b18bb9..ce0ba2062723 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -516,6 +516,14 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, 
void *kbuffer,
}
wait_for_completion(>waitevent);
 
+   if (msginfo->response.gpadl_created.creation_status != 0) {
+   pr_err("Failed to establish GPADL: err = 0x%x\n",
+  msginfo->response.gpadl_created.creation_status);
+
+   ret = -EDQUOT;
+   goto cleanup;
+   }
+
if (channel->rescind) {
ret = -ENODEV;
goto cleanup;
-- 
2.19.1



[PATCH 1/2] Drivers: hv: vmbus: check the creation_status in vmbus_establish_gpadl()

2018-11-25 Thread kys
From: Dexuan Cui 

This is a longstanding issue: if the vmbus upper-layer drivers try to
consume too many GPADLs, the host may return with an error
0xC044 (STATUS_QUOTA_EXCEEDED), but currently we forget to check
the creation_status, and hence we can pass an invalid GPADL handle
into the OPEN_CHANNEL message, and get an error code 0xc225 in
open_info->response.open_result.status, and finally we hang in
vmbus_open() -> "goto error_free_info" -> vmbus_teardown_gpadl().

With this patch, we can exit gracefully on STATUS_QUOTA_EXCEEDED.

Cc: Stephen Hemminger 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: sta...@vger.kernel.org
Signed-off-by: Dexuan Cui 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/channel.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index f96a77b18bb9..ce0ba2062723 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -516,6 +516,14 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, 
void *kbuffer,
}
wait_for_completion(>waitevent);
 
+   if (msginfo->response.gpadl_created.creation_status != 0) {
+   pr_err("Failed to establish GPADL: err = 0x%x\n",
+  msginfo->response.gpadl_created.creation_status);
+
+   ret = -EDQUOT;
+   goto cleanup;
+   }
+
if (channel->rescind) {
ret = -ENODEV;
goto cleanup;
-- 
2.19.1



[PATCH 0/2] Drivers: hv: vmbus: Miscellaneous fixes

2018-11-25 Thread kys
From: "K. Y. Srinivasan" 

Miscellaneous fixes.

Dexuan Cui (2):
  Drivers: hv: vmbus: check the creation_status in
vmbus_establish_gpadl()
  Drivers: hv: vmbus: offload the handling of channels to two workqueues

 drivers/hv/channel.c  |   8 ++
 drivers/hv/channel_mgmt.c | 188 +-
 drivers/hv/connection.c   |  24 -
 drivers/hv/hyperv_vmbus.h |   7 ++
 include/linux/hyperv.h|   7 ++
 5 files changed, 169 insertions(+), 65 deletions(-)

-- 
2.19.1



[PATCH 0/2] Drivers: hv: vmbus: Miscellaneous fixes

2018-11-25 Thread kys
From: "K. Y. Srinivasan" 

Miscellaneous fixes.

Dexuan Cui (2):
  Drivers: hv: vmbus: check the creation_status in
vmbus_establish_gpadl()
  Drivers: hv: vmbus: offload the handling of channels to two workqueues

 drivers/hv/channel.c  |   8 ++
 drivers/hv/channel_mgmt.c | 188 +-
 drivers/hv/connection.c   |  24 -
 drivers/hv/hyperv_vmbus.h |   7 ++
 include/linux/hyperv.h|   7 ++
 5 files changed, 169 insertions(+), 65 deletions(-)

-- 
2.19.1



[PATCH] Drivers: hv: vmbus: Remove the useless API vmbus_get_outgoing_channel()

2018-11-25 Thread kys
From: Dexuan Cui 

Commit d86adf482b84 ("scsi: storvsc: Enable multi-queue support") removed
the usage of the API in Jan 2017, and the API is not used since then.

netvsc and storvsc have their own algorithms to determine the outgoing
channel, so this API is useless.

And the API is potentially unsafe, because it reads primary->num_sc without
any lock held. This can be risky considering the RESCIND-OFFER message.

Let's remove the API.

Cc: Long Li 
Cc: Stephen Hemminger 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Signed-off-by: Dexuan Cui 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/channel.c  |  1 -
 drivers/hv/channel_mgmt.c | 45 ---
 include/linux/hyperv.h| 17 ---
 3 files changed, 63 deletions(-)

diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index de8193f3b838..f96a77b18bb9 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -703,7 +703,6 @@ int vmbus_disconnect_ring(struct vmbus_channel *channel)
/* Snapshot the list of subchannels */
spin_lock_irqsave(>lock, flags);
list_splice_init(>sc_list, );
-   channel->num_sc = 0;
spin_unlock_irqrestore(>lock, flags);
 
list_for_each_entry_safe(cur_channel, tmp, , sc_list) {
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 6277597d3d58..82e673671087 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -405,7 +405,6 @@ void hv_process_channel_removal(struct vmbus_channel 
*channel)
primary_channel = channel->primary_channel;
spin_lock_irqsave(_channel->lock, flags);
list_del(>sc_list);
-   primary_channel->num_sc--;
spin_unlock_irqrestore(_channel->lock, flags);
}
 
@@ -483,7 +482,6 @@ static void vmbus_process_offer(struct vmbus_channel 
*newchannel)
newchannel->primary_channel = channel;
spin_lock_irqsave(>lock, flags);
list_add_tail(>sc_list, >sc_list);
-   channel->num_sc++;
spin_unlock_irqrestore(>lock, flags);
} else {
goto err_free_chan;
@@ -1239,49 +1237,6 @@ int vmbus_request_offers(void)
return ret;
 }
 
-/*
- * Retrieve the (sub) channel on which to send an outgoing request.
- * When a primary channel has multiple sub-channels, we try to
- * distribute the load equally amongst all available channels.
- */
-struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary)
-{
-   struct list_head *cur, *tmp;
-   int cur_cpu;
-   struct vmbus_channel *cur_channel;
-   struct vmbus_channel *outgoing_channel = primary;
-   int next_channel;
-   int i = 1;
-
-   if (list_empty(>sc_list))
-   return outgoing_channel;
-
-   next_channel = primary->next_oc++;
-
-   if (next_channel > (primary->num_sc)) {
-   primary->next_oc = 0;
-   return outgoing_channel;
-   }
-
-   cur_cpu = hv_cpu_number_to_vp_number(smp_processor_id());
-   list_for_each_safe(cur, tmp, >sc_list) {
-   cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
-   if (cur_channel->state != CHANNEL_OPENED_STATE)
-   continue;
-
-   if (cur_channel->target_vp == cur_cpu)
-   return cur_channel;
-
-   if (i == next_channel)
-   return cur_channel;
-
-   i++;
-   }
-
-   return outgoing_channel;
-}
-EXPORT_SYMBOL_GPL(vmbus_get_outgoing_channel);
-
 static void invoke_sc_cb(struct vmbus_channel *primary_channel)
 {
struct list_head *cur, *tmp;
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index b3e24368930a..07a367f5e22f 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -830,15 +830,6 @@ struct vmbus_channel {
 * All Sub-channels of a primary channel are linked here.
 */
struct list_head sc_list;
-   /*
-* Current number of sub-channels.
-*/
-   int num_sc;
-   /*
-* Number of a sub-channel (position within sc_list) which is supposed
-* to be used as the next outgoing channel.
-*/
-   int next_oc;
/*
 * The primary channel this sub-channel belongs to.
 * This will be NULL for the primary channel.
@@ -965,14 +956,6 @@ void vmbus_set_sc_create_callback(struct vmbus_channel 
*primary_channel,
 void vmbus_set_chn_rescind_callback(struct vmbus_channel *channel,
void (*chn_rescind_cb)(struct vmbus_channel *));
 
-/*
- * Retrieve the (sub) channel on which to send an outgoing request.
- * When a primary channel has multiple sub-channels, we choose a
- * channel whose VCPU binding is closest to the VCPU on which
- * this call is being made.
- */
-struct vmbus_channel *vmbus_get_outgoing_channel(struct 

[PATCH] Drivers: hv: vmbus: Remove the useless API vmbus_get_outgoing_channel()

2018-11-25 Thread kys
From: Dexuan Cui 

Commit d86adf482b84 ("scsi: storvsc: Enable multi-queue support") removed
the usage of the API in Jan 2017, and the API is not used since then.

netvsc and storvsc have their own algorithms to determine the outgoing
channel, so this API is useless.

And the API is potentially unsafe, because it reads primary->num_sc without
any lock held. This can be risky considering the RESCIND-OFFER message.

Let's remove the API.

Cc: Long Li 
Cc: Stephen Hemminger 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Signed-off-by: Dexuan Cui 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/channel.c  |  1 -
 drivers/hv/channel_mgmt.c | 45 ---
 include/linux/hyperv.h| 17 ---
 3 files changed, 63 deletions(-)

diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index de8193f3b838..f96a77b18bb9 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -703,7 +703,6 @@ int vmbus_disconnect_ring(struct vmbus_channel *channel)
/* Snapshot the list of subchannels */
spin_lock_irqsave(>lock, flags);
list_splice_init(>sc_list, );
-   channel->num_sc = 0;
spin_unlock_irqrestore(>lock, flags);
 
list_for_each_entry_safe(cur_channel, tmp, , sc_list) {
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 6277597d3d58..82e673671087 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -405,7 +405,6 @@ void hv_process_channel_removal(struct vmbus_channel 
*channel)
primary_channel = channel->primary_channel;
spin_lock_irqsave(_channel->lock, flags);
list_del(>sc_list);
-   primary_channel->num_sc--;
spin_unlock_irqrestore(_channel->lock, flags);
}
 
@@ -483,7 +482,6 @@ static void vmbus_process_offer(struct vmbus_channel 
*newchannel)
newchannel->primary_channel = channel;
spin_lock_irqsave(>lock, flags);
list_add_tail(>sc_list, >sc_list);
-   channel->num_sc++;
spin_unlock_irqrestore(>lock, flags);
} else {
goto err_free_chan;
@@ -1239,49 +1237,6 @@ int vmbus_request_offers(void)
return ret;
 }
 
-/*
- * Retrieve the (sub) channel on which to send an outgoing request.
- * When a primary channel has multiple sub-channels, we try to
- * distribute the load equally amongst all available channels.
- */
-struct vmbus_channel *vmbus_get_outgoing_channel(struct vmbus_channel *primary)
-{
-   struct list_head *cur, *tmp;
-   int cur_cpu;
-   struct vmbus_channel *cur_channel;
-   struct vmbus_channel *outgoing_channel = primary;
-   int next_channel;
-   int i = 1;
-
-   if (list_empty(>sc_list))
-   return outgoing_channel;
-
-   next_channel = primary->next_oc++;
-
-   if (next_channel > (primary->num_sc)) {
-   primary->next_oc = 0;
-   return outgoing_channel;
-   }
-
-   cur_cpu = hv_cpu_number_to_vp_number(smp_processor_id());
-   list_for_each_safe(cur, tmp, >sc_list) {
-   cur_channel = list_entry(cur, struct vmbus_channel, sc_list);
-   if (cur_channel->state != CHANNEL_OPENED_STATE)
-   continue;
-
-   if (cur_channel->target_vp == cur_cpu)
-   return cur_channel;
-
-   if (i == next_channel)
-   return cur_channel;
-
-   i++;
-   }
-
-   return outgoing_channel;
-}
-EXPORT_SYMBOL_GPL(vmbus_get_outgoing_channel);
-
 static void invoke_sc_cb(struct vmbus_channel *primary_channel)
 {
struct list_head *cur, *tmp;
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index b3e24368930a..07a367f5e22f 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -830,15 +830,6 @@ struct vmbus_channel {
 * All Sub-channels of a primary channel are linked here.
 */
struct list_head sc_list;
-   /*
-* Current number of sub-channels.
-*/
-   int num_sc;
-   /*
-* Number of a sub-channel (position within sc_list) which is supposed
-* to be used as the next outgoing channel.
-*/
-   int next_oc;
/*
 * The primary channel this sub-channel belongs to.
 * This will be NULL for the primary channel.
@@ -965,14 +956,6 @@ void vmbus_set_sc_create_callback(struct vmbus_channel 
*primary_channel,
 void vmbus_set_chn_rescind_callback(struct vmbus_channel *channel,
void (*chn_rescind_cb)(struct vmbus_channel *));
 
-/*
- * Retrieve the (sub) channel on which to send an outgoing request.
- * When a primary channel has multiple sub-channels, we choose a
- * channel whose VCPU binding is closest to the VCPU on which
- * this call is being made.
- */
-struct vmbus_channel *vmbus_get_outgoing_channel(struct 

[PATCH 2/4] arm64: hyperv: Add support for Hyper-V as a hypervisor

2018-11-21 Thread kys
From: Michael Kelley 

Add ARM64-specific code to enable Hyper-V. This code includes:
* Detecting Hyper-V and initializing the guest/Hyper-V interface
* Setting up Hyper-V's synthetic clocks
* Making hypercalls using the HVC instruction
* Setting up VMbus and stimer0 interrupts
* Setting up kexec and crash handlers
This code is architecture dependent code and is mostly driven by
architecture independent code in the VMbus driver in drivers/hv/hv.c
and drivers/hv/vmbus_drv.c.

This code is built only when CONFIG_HYPERV is enabled.

Signed-off-by: Michael Kelley 
Signed-off-by: K. Y. Srinivasan 
---
 MAINTAINERS  |   1 +
 arch/arm64/Makefile  |   1 +
 arch/arm64/hyperv/Makefile   |   2 +
 arch/arm64/hyperv/hv_hvc.S   |  54 +
 arch/arm64/hyperv/hv_init.c  | 441 +++
 arch/arm64/hyperv/mshyperv.c | 178 ++
 6 files changed, 677 insertions(+)
 create mode 100644 arch/arm64/hyperv/Makefile
 create mode 100644 arch/arm64/hyperv/hv_hvc.S
 create mode 100644 arch/arm64/hyperv/hv_init.c
 create mode 100644 arch/arm64/hyperv/mshyperv.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 72f19cef4c48..326eeb32a0cd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6837,6 +6837,7 @@ F:arch/x86/kernel/cpu/mshyperv.c
 F: arch/x86/hyperv
 F: arch/arm64/include/asm/hyperv-tlfs.h
 F: arch/arm64/include/asm/mshyperv.h
+F: arch/arm64/hyperv
 F: drivers/hid/hid-hyperv.c
 F: drivers/hv/
 F: drivers/input/serio/hyperv-keyboard.c
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 6cb9fc7e9382..ad9ec0579553 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -106,6 +106,7 @@ core-y  += arch/arm64/kernel/ arch/arm64/mm/
 core-$(CONFIG_NET) += arch/arm64/net/
 core-$(CONFIG_KVM) += arch/arm64/kvm/
 core-$(CONFIG_XEN) += arch/arm64/xen/
+core-$(CONFIG_HYPERV) += arch/arm64/hyperv/
 core-$(CONFIG_CRYPTO) += arch/arm64/crypto/
 libs-y := arch/arm64/lib/ $(libs-y)
 core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
diff --git a/arch/arm64/hyperv/Makefile b/arch/arm64/hyperv/Makefile
new file mode 100644
index ..988eda55330c
--- /dev/null
+++ b/arch/arm64/hyperv/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-y  := hv_init.o hv_hvc.o mshyperv.o
diff --git a/arch/arm64/hyperv/hv_hvc.S b/arch/arm64/hyperv/hv_hvc.S
new file mode 100644
index ..82636969b4f2
--- /dev/null
+++ b/arch/arm64/hyperv/hv_hvc.S
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Microsoft Hyper-V hypervisor invocation routines
+ *
+ * Copyright (C) 2018, Microsoft, Inc.
+ *
+ * Author : Michael Kelley 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include 
+
+   .text
+/*
+ * Do the HVC instruction.  For Hyper-V the argument is always 1.
+ * x0 contains the hypercall control value, while additional registers
+ * vary depending on the hypercall, and whether the hypercall arguments
+ * are in memory or in registers (a "fast" hypercall per the Hyper-V
+ * TLFS).  When the arguments are in memory x1 is the guest physical
+ * address of the input arguments, and x2 is the guest physical
+ * address of the output arguments.  When the arguments are in
+ * registers, the register values depends on the hypercall.  Note
+ * that this version cannot return any values in registers.
+ */
+ENTRY(hv_do_hvc)
+   hvc #1
+   ret
+ENDPROC(hv_do_hvc)
+
+/*
+ * This variant of HVC invocation is for hv_get_vpreg and
+ * hv_get_vpreg_128. The input parameters are passed in registers
+ * along with a pointer in x4 to where the output result should
+ * be stored. The output is returned in x15 and x16.  x18 is used as
+ * scratch space to avoid buildng a stack frame, as Hyper-V does
+ * not preserve registers x0-x17.
+ */
+ENTRY(hv_do_hvc_fast_get)
+   mov x18, x4
+   hvc #1
+   str x15,[x18]
+   str x16,[x18,#8]
+   ret
+ENDPROC(hv_do_hvc_fast_get)
diff --git a/arch/arm64/hyperv/hv_init.c b/arch/arm64/hyperv/hv_init.c
new file mode 100644
index ..aa1a8c09d989
--- /dev/null
+++ b/arch/arm64/hyperv/hv_init.c
@@ -0,0 +1,441 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Initialization of the interface with Microsoft's Hyper-V hypervisor,
+ * and various low level utility routines for interacting with Hyper-V.
+ *
+ * Copyright (C) 2018, Microsoft, Inc.
+ *
+ * Author : Michael Kelley 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 

[PATCH 3/4] Drivers: hv: vmbus: Add hooks for per-CPU IRQ

2018-11-21 Thread kys
From: Michael Kelley 

Add hooks to enable/disable a per-CPU IRQ for VMbus. These hooks
are in the architecture independent setup and shutdown paths for
Hyper-V, and are needed by Linux guests on Hyper-V on ARM64.  The
x86/x64 implementation is null because VMbus interrupts on x86/x64
don't use an IRQ.

Signed-off-by: Michael Kelley 
Signed-off-by: K. Y. Srinivasan 
---
 arch/x86/include/asm/mshyperv.h | 4 
 drivers/hv/hv.c | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 0d6271cce198..8d97bd3a13a6 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -109,6 +109,10 @@ void hyperv_vector_handler(struct pt_regs *regs);
 void hv_setup_vmbus_irq(void (*handler)(void));
 void hv_remove_vmbus_irq(void);
 
+/* On x86/x64, there isn't a real IRQ to be enabled/disable */
+static inline void hv_enable_vmbus_irq(void) {}
+static inline void hv_disable_vmbus_irq(void) {}
+
 void hv_setup_kexec_handler(void (*handler)(void));
 void hv_remove_kexec_handler(void);
 void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 166c2501de17..d0bb09a4bd73 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -307,6 +307,7 @@ int hv_synic_init(unsigned int cpu)
hv_set_siefp(siefp.as_uint64);
 
/* Setup the shared SINT. */
+   hv_enable_vmbus_irq();
hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
 
shared_sint.vector = HYPERVISOR_CALLBACK_VECTOR;
@@ -434,6 +435,7 @@ int hv_synic_cleanup(unsigned int cpu)
/* Disable the global synic bit */
sctrl.enable = 0;
hv_set_synic_state(sctrl.as_uint64);
+   hv_disable_vmbus_irq();
 
return 0;
 }
-- 
2.19.1



[PATCH 2/4] arm64: hyperv: Add support for Hyper-V as a hypervisor

2018-11-21 Thread kys
From: Michael Kelley 

Add ARM64-specific code to enable Hyper-V. This code includes:
* Detecting Hyper-V and initializing the guest/Hyper-V interface
* Setting up Hyper-V's synthetic clocks
* Making hypercalls using the HVC instruction
* Setting up VMbus and stimer0 interrupts
* Setting up kexec and crash handlers
This code is architecture dependent code and is mostly driven by
architecture independent code in the VMbus driver in drivers/hv/hv.c
and drivers/hv/vmbus_drv.c.

This code is built only when CONFIG_HYPERV is enabled.

Signed-off-by: Michael Kelley 
Signed-off-by: K. Y. Srinivasan 
---
 MAINTAINERS  |   1 +
 arch/arm64/Makefile  |   1 +
 arch/arm64/hyperv/Makefile   |   2 +
 arch/arm64/hyperv/hv_hvc.S   |  54 +
 arch/arm64/hyperv/hv_init.c  | 441 +++
 arch/arm64/hyperv/mshyperv.c | 178 ++
 6 files changed, 677 insertions(+)
 create mode 100644 arch/arm64/hyperv/Makefile
 create mode 100644 arch/arm64/hyperv/hv_hvc.S
 create mode 100644 arch/arm64/hyperv/hv_init.c
 create mode 100644 arch/arm64/hyperv/mshyperv.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 72f19cef4c48..326eeb32a0cd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6837,6 +6837,7 @@ F:arch/x86/kernel/cpu/mshyperv.c
 F: arch/x86/hyperv
 F: arch/arm64/include/asm/hyperv-tlfs.h
 F: arch/arm64/include/asm/mshyperv.h
+F: arch/arm64/hyperv
 F: drivers/hid/hid-hyperv.c
 F: drivers/hv/
 F: drivers/input/serio/hyperv-keyboard.c
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 6cb9fc7e9382..ad9ec0579553 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -106,6 +106,7 @@ core-y  += arch/arm64/kernel/ arch/arm64/mm/
 core-$(CONFIG_NET) += arch/arm64/net/
 core-$(CONFIG_KVM) += arch/arm64/kvm/
 core-$(CONFIG_XEN) += arch/arm64/xen/
+core-$(CONFIG_HYPERV) += arch/arm64/hyperv/
 core-$(CONFIG_CRYPTO) += arch/arm64/crypto/
 libs-y := arch/arm64/lib/ $(libs-y)
 core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
diff --git a/arch/arm64/hyperv/Makefile b/arch/arm64/hyperv/Makefile
new file mode 100644
index ..988eda55330c
--- /dev/null
+++ b/arch/arm64/hyperv/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-y  := hv_init.o hv_hvc.o mshyperv.o
diff --git a/arch/arm64/hyperv/hv_hvc.S b/arch/arm64/hyperv/hv_hvc.S
new file mode 100644
index ..82636969b4f2
--- /dev/null
+++ b/arch/arm64/hyperv/hv_hvc.S
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * Microsoft Hyper-V hypervisor invocation routines
+ *
+ * Copyright (C) 2018, Microsoft, Inc.
+ *
+ * Author : Michael Kelley 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#include 
+
+   .text
+/*
+ * Do the HVC instruction.  For Hyper-V the argument is always 1.
+ * x0 contains the hypercall control value, while additional registers
+ * vary depending on the hypercall, and whether the hypercall arguments
+ * are in memory or in registers (a "fast" hypercall per the Hyper-V
+ * TLFS).  When the arguments are in memory x1 is the guest physical
+ * address of the input arguments, and x2 is the guest physical
+ * address of the output arguments.  When the arguments are in
+ * registers, the register values depends on the hypercall.  Note
+ * that this version cannot return any values in registers.
+ */
+ENTRY(hv_do_hvc)
+   hvc #1
+   ret
+ENDPROC(hv_do_hvc)
+
+/*
+ * This variant of HVC invocation is for hv_get_vpreg and
+ * hv_get_vpreg_128. The input parameters are passed in registers
+ * along with a pointer in x4 to where the output result should
+ * be stored. The output is returned in x15 and x16.  x18 is used as
+ * scratch space to avoid buildng a stack frame, as Hyper-V does
+ * not preserve registers x0-x17.
+ */
+ENTRY(hv_do_hvc_fast_get)
+   mov x18, x4
+   hvc #1
+   str x15,[x18]
+   str x16,[x18,#8]
+   ret
+ENDPROC(hv_do_hvc_fast_get)
diff --git a/arch/arm64/hyperv/hv_init.c b/arch/arm64/hyperv/hv_init.c
new file mode 100644
index ..aa1a8c09d989
--- /dev/null
+++ b/arch/arm64/hyperv/hv_init.c
@@ -0,0 +1,441 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Initialization of the interface with Microsoft's Hyper-V hypervisor,
+ * and various low level utility routines for interacting with Hyper-V.
+ *
+ * Copyright (C) 2018, Microsoft, Inc.
+ *
+ * Author : Michael Kelley 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 

[PATCH 3/4] Drivers: hv: vmbus: Add hooks for per-CPU IRQ

2018-11-21 Thread kys
From: Michael Kelley 

Add hooks to enable/disable a per-CPU IRQ for VMbus. These hooks
are in the architecture independent setup and shutdown paths for
Hyper-V, and are needed by Linux guests on Hyper-V on ARM64.  The
x86/x64 implementation is null because VMbus interrupts on x86/x64
don't use an IRQ.

Signed-off-by: Michael Kelley 
Signed-off-by: K. Y. Srinivasan 
---
 arch/x86/include/asm/mshyperv.h | 4 
 drivers/hv/hv.c | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 0d6271cce198..8d97bd3a13a6 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -109,6 +109,10 @@ void hyperv_vector_handler(struct pt_regs *regs);
 void hv_setup_vmbus_irq(void (*handler)(void));
 void hv_remove_vmbus_irq(void);
 
+/* On x86/x64, there isn't a real IRQ to be enabled/disable */
+static inline void hv_enable_vmbus_irq(void) {}
+static inline void hv_disable_vmbus_irq(void) {}
+
 void hv_setup_kexec_handler(void (*handler)(void));
 void hv_remove_kexec_handler(void);
 void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 166c2501de17..d0bb09a4bd73 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -307,6 +307,7 @@ int hv_synic_init(unsigned int cpu)
hv_set_siefp(siefp.as_uint64);
 
/* Setup the shared SINT. */
+   hv_enable_vmbus_irq();
hv_get_synint_state(VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
 
shared_sint.vector = HYPERVISOR_CALLBACK_VECTOR;
@@ -434,6 +435,7 @@ int hv_synic_cleanup(unsigned int cpu)
/* Disable the global synic bit */
sctrl.enable = 0;
hv_set_synic_state(sctrl.as_uint64);
+   hv_disable_vmbus_irq();
 
return 0;
 }
-- 
2.19.1



[PATCH 4/4] Drivers: hv: Enable CONFIG_HYPERV on ARM64

2018-11-21 Thread kys
From: Michael Kelley 

Update drivers/hv/Kconfig so CONFIG_HYPERV can be selected on ARM64,
causing the Hyper-V specific code to be built.

Signed-off-by: Michael Kelley 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/Kconfig | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
index 97954f575c3f..c3e11a2f9c70 100644
--- a/drivers/hv/Kconfig
+++ b/drivers/hv/Kconfig
@@ -4,7 +4,8 @@ menu "Microsoft Hyper-V guest support"
 
 config HYPERV
tristate "Microsoft Hyper-V client drivers"
-   depends on X86 && ACPI && PCI && X86_LOCAL_APIC && HYPERVISOR_GUEST
+   depends on ACPI && PCI && \
+   ((X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) || ARM64)
select PARAVIRT
help
  Select this option to run Linux as a Hyper-V client operating
-- 
2.19.1



[PATCH 4/4] Drivers: hv: Enable CONFIG_HYPERV on ARM64

2018-11-21 Thread kys
From: Michael Kelley 

Update drivers/hv/Kconfig so CONFIG_HYPERV can be selected on ARM64,
causing the Hyper-V specific code to be built.

Signed-off-by: Michael Kelley 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/Kconfig | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig
index 97954f575c3f..c3e11a2f9c70 100644
--- a/drivers/hv/Kconfig
+++ b/drivers/hv/Kconfig
@@ -4,7 +4,8 @@ menu "Microsoft Hyper-V guest support"
 
 config HYPERV
tristate "Microsoft Hyper-V client drivers"
-   depends on X86 && ACPI && PCI && X86_LOCAL_APIC && HYPERVISOR_GUEST
+   depends on ACPI && PCI && \
+   ((X86 && X86_LOCAL_APIC && HYPERVISOR_GUEST) || ARM64)
select PARAVIRT
help
  Select this option to run Linux as a Hyper-V client operating
-- 
2.19.1



[PATCH 1/4] arm64: hyperv: Add core Hyper-V include files

2018-11-21 Thread kys
From: Michael Kelley 

hyperv-tlfs.h defines Hyper-V interfaces from the Hyper-V Top Level
Functional Spec (TLFS). The TLFS is distinctly oriented to x86/x64,
and Hyper-V has not separated out the architecture-dependent parts into
x86/x64 vs. ARM64. So hyperv-tlfs.h includes information for ARM64
that is not yet formally published. The TLFS is available here:

  docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs

mshyperv.h defines Linux-specific structures and routines for
interacting with Hyper-V. It is split into an ARM64 specific file
and an architecture independent file in include/asm-generic.

Signed-off-by: Michael Kelley 
Signed-off-by: K. Y. Srinivasan 
---
 MAINTAINERS  |   3 +
 arch/arm64/include/asm/hyperv-tlfs.h | 338 +++
 arch/arm64/include/asm/mshyperv.h| 116 +
 include/asm-generic/mshyperv.h   | 240 +++
 4 files changed, 697 insertions(+)
 create mode 100644 arch/arm64/include/asm/hyperv-tlfs.h
 create mode 100644 arch/arm64/include/asm/mshyperv.h
 create mode 100644 include/asm-generic/mshyperv.h

diff --git a/MAINTAINERS b/MAINTAINERS
index f4855974f325..72f19cef4c48 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6835,6 +6835,8 @@ F:arch/x86/include/asm/trace/hyperv.h
 F: arch/x86/include/asm/hyperv-tlfs.h
 F: arch/x86/kernel/cpu/mshyperv.c
 F: arch/x86/hyperv
+F: arch/arm64/include/asm/hyperv-tlfs.h
+F: arch/arm64/include/asm/mshyperv.h
 F: drivers/hid/hid-hyperv.c
 F: drivers/hv/
 F: drivers/input/serio/hyperv-keyboard.c
@@ -6846,6 +6848,7 @@ F:drivers/video/fbdev/hyperv_fb.c
 F: net/vmw_vsock/hyperv_transport.c
 F: include/linux/hyperv.h
 F: include/uapi/linux/hyperv.h
+F: include/asm-generic/mshyperv.h
 F: tools/hv/
 F: Documentation/ABI/stable/sysfs-bus-vmbus
 
diff --git a/arch/arm64/include/asm/hyperv-tlfs.h 
b/arch/arm64/include/asm/hyperv-tlfs.h
new file mode 100644
index ..924e37600e92
--- /dev/null
+++ b/arch/arm64/include/asm/hyperv-tlfs.h
@@ -0,0 +1,338 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * This file contains definitions from the Hyper-V Hypervisor Top-Level
+ * Functional Specification (TLFS):
+ * 
https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fvirtualization%2Fhyper-v-on-windows%2Freference%2Ftlfsdata=02%7C01%7Ckys%40microsoft.com%7Cc831a45fd63e4a4b083908d641216aa8%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636768009113747528sdata=jRSrs9ZWXdmeS7LQUEpoSyUfBS7a5KLYy%2FolFdE2tI0%3Dreserved=0
+ *
+ * Copyright (C) 2018, Microsoft, Inc.
+ *
+ * Author : Michael Kelley 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef _ASM_ARM64_HYPERV_H
+#define _ASM_ARM64_HYPERV_H
+
+#include 
+
+/*
+ * These Hyper-V registers provide information equivalent to the CPUID
+ * instruction on x86/x64.
+ */
+#define HV_REGISTER_HYPERVISOR_VERSION 0x0100 /*CPUID 0x4002 */
+#defineHV_REGISTER_PRIVILEGES_AND_FEATURES 0x0200 /*CPUID 
0x4003 */
+#defineHV_REGISTER_FEATURES0x0201 /*CPUID 
0x4004 */
+#defineHV_REGISTER_IMPLEMENTATION_LIMITS   0x0202 /*CPUID 
0x4005 */
+#define HV_ARM64_REGISTER_INTERFACE_VERSION0x00090006 /*CPUID 0x4001 */
+
+/*
+ * Feature identification. HvRegisterPrivilegesAndFeaturesInfo returns a
+ * 128-bit value with flags indicating which features are available to the
+ * partition based upon the current partition privileges. The 128-bit
+ * value is broken up with different portions stored in different 32-bit
+ * fields in the ms_hyperv structure.
+ */
+
+/* Partition Reference Counter available*/
+#define HV_MSR_TIME_REF_COUNT_AVAILABLE(1 << 1)
+
+/*
+ * Synthetic Timers available
+ */
+#define HV_MSR_SYNTIMER_AVAILABLE  (1 << 3)
+
+/* Frequency MSRs available */
+#define HV_FEATURE_FREQUENCY_MSRS_AVAILABLE(1 << 8)
+
+/* Reference TSC available */
+#define HV_MSR_REFERENCE_TSC_AVAILABLE (1 << 9)
+
+/* Crash MSR available */
+#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE   (1 << 10)
+
+
+/*
+ * This group of flags is in the high order 64-bits of the returned
+ * 128-bit value.
+ */
+
+/* STIMER direct mode is available */
+#define HV_STIMER_DIRECT_MODE_AVAILABLE(1 << 19)
+
+/*
+ * Implementation recommendations in register
+ * HvRegisterFeaturesInfo. Indicates which behaviors the hypervisor
+ * recommends the OS implement for optimal 

[PATCH 1/4] arm64: hyperv: Add core Hyper-V include files

2018-11-21 Thread kys
From: Michael Kelley 

hyperv-tlfs.h defines Hyper-V interfaces from the Hyper-V Top Level
Functional Spec (TLFS). The TLFS is distinctly oriented to x86/x64,
and Hyper-V has not separated out the architecture-dependent parts into
x86/x64 vs. ARM64. So hyperv-tlfs.h includes information for ARM64
that is not yet formally published. The TLFS is available here:

  docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs

mshyperv.h defines Linux-specific structures and routines for
interacting with Hyper-V. It is split into an ARM64 specific file
and an architecture independent file in include/asm-generic.

Signed-off-by: Michael Kelley 
Signed-off-by: K. Y. Srinivasan 
---
 MAINTAINERS  |   3 +
 arch/arm64/include/asm/hyperv-tlfs.h | 338 +++
 arch/arm64/include/asm/mshyperv.h| 116 +
 include/asm-generic/mshyperv.h   | 240 +++
 4 files changed, 697 insertions(+)
 create mode 100644 arch/arm64/include/asm/hyperv-tlfs.h
 create mode 100644 arch/arm64/include/asm/mshyperv.h
 create mode 100644 include/asm-generic/mshyperv.h

diff --git a/MAINTAINERS b/MAINTAINERS
index f4855974f325..72f19cef4c48 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6835,6 +6835,8 @@ F:arch/x86/include/asm/trace/hyperv.h
 F: arch/x86/include/asm/hyperv-tlfs.h
 F: arch/x86/kernel/cpu/mshyperv.c
 F: arch/x86/hyperv
+F: arch/arm64/include/asm/hyperv-tlfs.h
+F: arch/arm64/include/asm/mshyperv.h
 F: drivers/hid/hid-hyperv.c
 F: drivers/hv/
 F: drivers/input/serio/hyperv-keyboard.c
@@ -6846,6 +6848,7 @@ F:drivers/video/fbdev/hyperv_fb.c
 F: net/vmw_vsock/hyperv_transport.c
 F: include/linux/hyperv.h
 F: include/uapi/linux/hyperv.h
+F: include/asm-generic/mshyperv.h
 F: tools/hv/
 F: Documentation/ABI/stable/sysfs-bus-vmbus
 
diff --git a/arch/arm64/include/asm/hyperv-tlfs.h 
b/arch/arm64/include/asm/hyperv-tlfs.h
new file mode 100644
index ..924e37600e92
--- /dev/null
+++ b/arch/arm64/include/asm/hyperv-tlfs.h
@@ -0,0 +1,338 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/*
+ * This file contains definitions from the Hyper-V Hypervisor Top-Level
+ * Functional Specification (TLFS):
+ * 
https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fvirtualization%2Fhyper-v-on-windows%2Freference%2Ftlfsdata=02%7C01%7Ckys%40microsoft.com%7Cc831a45fd63e4a4b083908d641216aa8%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636768009113747528sdata=jRSrs9ZWXdmeS7LQUEpoSyUfBS7a5KLYy%2FolFdE2tI0%3Dreserved=0
+ *
+ * Copyright (C) 2018, Microsoft, Inc.
+ *
+ * Author : Michael Kelley 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ */
+
+#ifndef _ASM_ARM64_HYPERV_H
+#define _ASM_ARM64_HYPERV_H
+
+#include 
+
+/*
+ * These Hyper-V registers provide information equivalent to the CPUID
+ * instruction on x86/x64.
+ */
+#define HV_REGISTER_HYPERVISOR_VERSION 0x0100 /*CPUID 0x4002 */
+#defineHV_REGISTER_PRIVILEGES_AND_FEATURES 0x0200 /*CPUID 
0x4003 */
+#defineHV_REGISTER_FEATURES0x0201 /*CPUID 
0x4004 */
+#defineHV_REGISTER_IMPLEMENTATION_LIMITS   0x0202 /*CPUID 
0x4005 */
+#define HV_ARM64_REGISTER_INTERFACE_VERSION0x00090006 /*CPUID 0x4001 */
+
+/*
+ * Feature identification. HvRegisterPrivilegesAndFeaturesInfo returns a
+ * 128-bit value with flags indicating which features are available to the
+ * partition based upon the current partition privileges. The 128-bit
+ * value is broken up with different portions stored in different 32-bit
+ * fields in the ms_hyperv structure.
+ */
+
+/* Partition Reference Counter available*/
+#define HV_MSR_TIME_REF_COUNT_AVAILABLE(1 << 1)
+
+/*
+ * Synthetic Timers available
+ */
+#define HV_MSR_SYNTIMER_AVAILABLE  (1 << 3)
+
+/* Frequency MSRs available */
+#define HV_FEATURE_FREQUENCY_MSRS_AVAILABLE(1 << 8)
+
+/* Reference TSC available */
+#define HV_MSR_REFERENCE_TSC_AVAILABLE (1 << 9)
+
+/* Crash MSR available */
+#define HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE   (1 << 10)
+
+
+/*
+ * This group of flags is in the high order 64-bits of the returned
+ * 128-bit value.
+ */
+
+/* STIMER direct mode is available */
+#define HV_STIMER_DIRECT_MODE_AVAILABLE(1 << 19)
+
+/*
+ * Implementation recommendations in register
+ * HvRegisterFeaturesInfo. Indicates which behaviors the hypervisor
+ * recommends the OS implement for optimal 

[PATCH 0/4] Hyper-V: Enable Linux guests on Hyper-V on ARM64

2018-11-21 Thread kys
From: "K. Y. Srinivasan" 

This series enables Linux guests running on Hyper-V on ARM64
hardware. New ARM64-specific code in arch/arm64/hyperv initializes
Hyper-V, including its synthetic clocks and hypercall mechanism.
Existing architecture independent drivers for Hyper-V's VMbus and
synthetic devices just work when built for ARM64. Hyper-V code is
built and included in the image and modules only if CONFIG_HYPERV
is enabled.

The four patches are organized as follows:
1) Add include files that define the Hyper-V interface as
   described in the Hyper-V Top Level Functional Spec (TLFS), plus
   additional definitions specific to Linux running on Hyper-V.

2) Add core Hyper-V support on ARM64, including hypercalls,
   synthetic clock initialization, and interrupt handlers.

3) Update the existing VMbus driver to generalize interrupt
   management across x86/x64 and ARM64.

4) Make CONFIG_HYPERV selectable on ARM64 in addition to x86/x64.

Some areas of Linux guests on Hyper-V on ARM64 are a work-
in-progress, primarily due to work still being done in Hyper-V:

* Hyper-V on ARM64 currently runs with a 4 Kbyte page size, and only
  supports guests with a 4 Kbyte page size. Because Hyper-V uses
  shared pages to communicate between the guest and the hypervisor,
  there are open design decisions on the page size to use when
  the guest is using 16K/64K pages.  Once those issues are
  resolved and Hyper-V fully supports 16K/64K guest pages, changes
  may be needed in the Linux drivers for Hyper-V synthetic devices.

* Hyper-V on ARM64 does not currently support mapping PCI devices
  into the guest address space. The Hyper-V PCI driver at
  drivers/pci/host/pci-hyperv.c has x86/x64-specific code and is
  not being built for ARM64.

In a few cases, terminology from the x86/x64 world has been carried
over into the ARM64 code ("MSR", "TSC").  Hyper-V still uses the
x86/x64 terminology and has not replaced it with something more
generic, so the code uses the Hyper-V terminology.  This will be
fixed when Hyper-V updates the usage in the TLFS.


Michael Kelley (4):
  arm64: hyperv: Add core Hyper-V include files
  arm64: hyperv: Add support for Hyper-V as a hypervisor
  Drivers: hv: vmbus: Add hooks for per-CPU IRQ
  Drivers: hv: Enable CONFIG_HYPERV on ARM64

 MAINTAINERS  |   4 +
 arch/arm64/Makefile  |   1 +
 arch/arm64/hyperv/Makefile   |   2 +
 arch/arm64/hyperv/hv_hvc.S   |  54 
 arch/arm64/hyperv/hv_init.c  | 441 +++
 arch/arm64/hyperv/mshyperv.c | 178 +++
 arch/arm64/include/asm/hyperv-tlfs.h | 338 
 arch/arm64/include/asm/mshyperv.h| 116 +++
 arch/x86/include/asm/mshyperv.h  |   4 +
 drivers/hv/Kconfig   |   3 +-
 drivers/hv/hv.c  |   2 +
 include/asm-generic/mshyperv.h   | 240 +++
 12 files changed, 1382 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/hyperv/Makefile
 create mode 100644 arch/arm64/hyperv/hv_hvc.S
 create mode 100644 arch/arm64/hyperv/hv_init.c
 create mode 100644 arch/arm64/hyperv/mshyperv.c
 create mode 100644 arch/arm64/include/asm/hyperv-tlfs.h
 create mode 100644 arch/arm64/include/asm/mshyperv.h
 create mode 100644 include/asm-generic/mshyperv.h

-- 
2.19.1



[PATCH 0/4] Hyper-V: Enable Linux guests on Hyper-V on ARM64

2018-11-21 Thread kys
From: "K. Y. Srinivasan" 

This series enables Linux guests running on Hyper-V on ARM64
hardware. New ARM64-specific code in arch/arm64/hyperv initializes
Hyper-V, including its synthetic clocks and hypercall mechanism.
Existing architecture independent drivers for Hyper-V's VMbus and
synthetic devices just work when built for ARM64. Hyper-V code is
built and included in the image and modules only if CONFIG_HYPERV
is enabled.

The four patches are organized as follows:
1) Add include files that define the Hyper-V interface as
   described in the Hyper-V Top Level Functional Spec (TLFS), plus
   additional definitions specific to Linux running on Hyper-V.

2) Add core Hyper-V support on ARM64, including hypercalls,
   synthetic clock initialization, and interrupt handlers.

3) Update the existing VMbus driver to generalize interrupt
   management across x86/x64 and ARM64.

4) Make CONFIG_HYPERV selectable on ARM64 in addition to x86/x64.

Some areas of Linux guests on Hyper-V on ARM64 are a work-
in-progress, primarily due to work still being done in Hyper-V:

* Hyper-V on ARM64 currently runs with a 4 Kbyte page size, and only
  supports guests with a 4 Kbyte page size. Because Hyper-V uses
  shared pages to communicate between the guest and the hypervisor,
  there are open design decisions on the page size to use when
  the guest is using 16K/64K pages.  Once those issues are
  resolved and Hyper-V fully supports 16K/64K guest pages, changes
  may be needed in the Linux drivers for Hyper-V synthetic devices.

* Hyper-V on ARM64 does not currently support mapping PCI devices
  into the guest address space. The Hyper-V PCI driver at
  drivers/pci/host/pci-hyperv.c has x86/x64-specific code and is
  not being built for ARM64.

In a few cases, terminology from the x86/x64 world has been carried
over into the ARM64 code ("MSR", "TSC").  Hyper-V still uses the
x86/x64 terminology and has not replaced it with something more
generic, so the code uses the Hyper-V terminology.  This will be
fixed when Hyper-V updates the usage in the TLFS.


Michael Kelley (4):
  arm64: hyperv: Add core Hyper-V include files
  arm64: hyperv: Add support for Hyper-V as a hypervisor
  Drivers: hv: vmbus: Add hooks for per-CPU IRQ
  Drivers: hv: Enable CONFIG_HYPERV on ARM64

 MAINTAINERS  |   4 +
 arch/arm64/Makefile  |   1 +
 arch/arm64/hyperv/Makefile   |   2 +
 arch/arm64/hyperv/hv_hvc.S   |  54 
 arch/arm64/hyperv/hv_init.c  | 441 +++
 arch/arm64/hyperv/mshyperv.c | 178 +++
 arch/arm64/include/asm/hyperv-tlfs.h | 338 
 arch/arm64/include/asm/mshyperv.h| 116 +++
 arch/x86/include/asm/mshyperv.h  |   4 +
 drivers/hv/Kconfig   |   3 +-
 drivers/hv/hv.c  |   2 +
 include/asm-generic/mshyperv.h   | 240 +++
 12 files changed, 1382 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/hyperv/Makefile
 create mode 100644 arch/arm64/hyperv/hv_hvc.S
 create mode 100644 arch/arm64/hyperv/hv_init.c
 create mode 100644 arch/arm64/hyperv/mshyperv.c
 create mode 100644 arch/arm64/include/asm/hyperv-tlfs.h
 create mode 100644 arch/arm64/include/asm/mshyperv.h
 create mode 100644 include/asm-generic/mshyperv.h

-- 
2.19.1



[PATCH 0/4] Hyper-V: Enable Linux guests on Hyper-V on ARM64

2018-11-21 Thread kys
From: "K. Y. Srinivasan" 

This series enables Linux guests running on Hyper-V on ARM64
hardware. New ARM64-specific code in arch/arm64/hyperv initializes
Hyper-V, including its synthetic clocks and hypercall mechanism.
Existing architecture independent drivers for Hyper-V's VMbus and
synthetic devices just work when built for ARM64. Hyper-V code is
built and included in the image and modules only if CONFIG_HYPERV
is enabled.

The four patches are organized as follows:
1) Add include files that define the Hyper-V interface as
   described in the Hyper-V Top Level Functional Spec (TLFS), plus
   additional definitions specific to Linux running on Hyper-V.

2) Add core Hyper-V support on ARM64, including hypercalls,
   synthetic clock initialization, and interrupt handlers.

3) Update the existing VMbus driver to generalize interrupt
   management across x86/x64 and ARM64.

4) Make CONFIG_HYPERV selectable on ARM64 in addition to x86/x64.

Some areas of Linux guests on Hyper-V on ARM64 are a work-
in-progress, primarily due to work still being done in Hyper-V:

* Hyper-V on ARM64 currently runs with a 4 Kbyte page size, and only
  supports guests with a 4 Kbyte page size. Because Hyper-V uses
  shared pages to communicate between the guest and the hypervisor,
  there are open design decisions on the page size to use when
  the guest is using 16K/64K pages.  Once those issues are
  resolved and Hyper-V fully supports 16K/64K guest pages, changes
  may be needed in the Linux drivers for Hyper-V synthetic devices.

* Hyper-V on ARM64 does not currently support mapping PCI devices
  into the guest address space. The Hyper-V PCI driver at
  drivers/pci/host/pci-hyperv.c has x86/x64-specific code and is
  not being built for ARM64.

In a few cases, terminology from the x86/x64 world has been carried
over into the ARM64 code ("MSR", "TSC").  Hyper-V still uses the
x86/x64 terminology and has not replaced it with something more
generic, so the code uses the Hyper-V terminology.  This will be
fixed when Hyper-V updates the usage in the TLFS.


Michael Kelley (4):
  arm64: hyperv: Add core Hyper-V include files
  arm64: hyperv: Add support for Hyper-V as a hypervisor
  Drivers: hv: vmbus: Add hooks for per-CPU IRQ
  Drivers: hv: Enable CONFIG_HYPERV on ARM64

 MAINTAINERS  |   4 +
 arch/arm64/Makefile  |   1 +
 arch/arm64/hyperv/Makefile   |   2 +
 arch/arm64/hyperv/hv_hvc.S   |  54 
 arch/arm64/hyperv/hv_init.c  | 441 +++
 arch/arm64/hyperv/mshyperv.c | 178 +++
 arch/arm64/include/asm/hyperv-tlfs.h | 338 
 arch/arm64/include/asm/mshyperv.h| 116 +++
 arch/x86/include/asm/mshyperv.h  |   4 +
 drivers/hv/Kconfig   |   3 +-
 drivers/hv/hv.c  |   2 +
 include/asm-generic/mshyperv.h   | 240 +++
 12 files changed, 1382 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/hyperv/Makefile
 create mode 100644 arch/arm64/hyperv/hv_hvc.S
 create mode 100644 arch/arm64/hyperv/hv_init.c
 create mode 100644 arch/arm64/hyperv/mshyperv.c
 create mode 100644 arch/arm64/include/asm/hyperv-tlfs.h
 create mode 100644 arch/arm64/include/asm/mshyperv.h
 create mode 100644 include/asm-generic/mshyperv.h

-- 
2.19.1



[PATCH 0/4] Hyper-V: Enable Linux guests on Hyper-V on ARM64

2018-11-21 Thread kys
From: "K. Y. Srinivasan" 

This series enables Linux guests running on Hyper-V on ARM64
hardware. New ARM64-specific code in arch/arm64/hyperv initializes
Hyper-V, including its synthetic clocks and hypercall mechanism.
Existing architecture independent drivers for Hyper-V's VMbus and
synthetic devices just work when built for ARM64. Hyper-V code is
built and included in the image and modules only if CONFIG_HYPERV
is enabled.

The four patches are organized as follows:
1) Add include files that define the Hyper-V interface as
   described in the Hyper-V Top Level Functional Spec (TLFS), plus
   additional definitions specific to Linux running on Hyper-V.

2) Add core Hyper-V support on ARM64, including hypercalls,
   synthetic clock initialization, and interrupt handlers.

3) Update the existing VMbus driver to generalize interrupt
   management across x86/x64 and ARM64.

4) Make CONFIG_HYPERV selectable on ARM64 in addition to x86/x64.

Some areas of Linux guests on Hyper-V on ARM64 are a work-
in-progress, primarily due to work still being done in Hyper-V:

* Hyper-V on ARM64 currently runs with a 4 Kbyte page size, and only
  supports guests with a 4 Kbyte page size. Because Hyper-V uses
  shared pages to communicate between the guest and the hypervisor,
  there are open design decisions on the page size to use when
  the guest is using 16K/64K pages.  Once those issues are
  resolved and Hyper-V fully supports 16K/64K guest pages, changes
  may be needed in the Linux drivers for Hyper-V synthetic devices.

* Hyper-V on ARM64 does not currently support mapping PCI devices
  into the guest address space. The Hyper-V PCI driver at
  drivers/pci/host/pci-hyperv.c has x86/x64-specific code and is
  not being built for ARM64.

In a few cases, terminology from the x86/x64 world has been carried
over into the ARM64 code ("MSR", "TSC").  Hyper-V still uses the
x86/x64 terminology and has not replaced it with something more
generic, so the code uses the Hyper-V terminology.  This will be
fixed when Hyper-V updates the usage in the TLFS.


Michael Kelley (4):
  arm64: hyperv: Add core Hyper-V include files
  arm64: hyperv: Add support for Hyper-V as a hypervisor
  Drivers: hv: vmbus: Add hooks for per-CPU IRQ
  Drivers: hv: Enable CONFIG_HYPERV on ARM64

 MAINTAINERS  |   4 +
 arch/arm64/Makefile  |   1 +
 arch/arm64/hyperv/Makefile   |   2 +
 arch/arm64/hyperv/hv_hvc.S   |  54 
 arch/arm64/hyperv/hv_init.c  | 441 +++
 arch/arm64/hyperv/mshyperv.c | 178 +++
 arch/arm64/include/asm/hyperv-tlfs.h | 338 
 arch/arm64/include/asm/mshyperv.h| 116 +++
 arch/x86/include/asm/mshyperv.h  |   4 +
 drivers/hv/Kconfig   |   3 +-
 drivers/hv/hv.c  |   2 +
 include/asm-generic/mshyperv.h   | 240 +++
 12 files changed, 1382 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm64/hyperv/Makefile
 create mode 100644 arch/arm64/hyperv/hv_hvc.S
 create mode 100644 arch/arm64/hyperv/hv_init.c
 create mode 100644 arch/arm64/hyperv/mshyperv.c
 create mode 100644 arch/arm64/include/asm/hyperv-tlfs.h
 create mode 100644 arch/arm64/include/asm/mshyperv.h
 create mode 100644 include/asm-generic/mshyperv.h

-- 
2.19.1



[PATCH V2 4/5] Drivers: hv: kvp: Use %u to print U32

2018-10-17 Thread kys
From: Dexuan Cui 

I didn't find a real issue. Let's just make it consistent with the
next "case REG_U64:" where %llu is used.

Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_kvp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index d6106e1a0d4a..5054d1105236 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -437,7 +437,7 @@ kvp_send_key(struct work_struct *dummy)
val32 = in_msg->body.kvp_set.data.value_u32;
message->body.kvp_set.data.value_size =
sprintf(message->body.kvp_set.data.value,
-   "%d", val32) + 1;
+   "%u", val32) + 1;
break;
 
case REG_U64:
-- 
2.18.0



[PATCH V2 4/5] Drivers: hv: kvp: Use %u to print U32

2018-10-17 Thread kys
From: Dexuan Cui 

I didn't find a real issue. Let's just make it consistent with the
next "case REG_U64:" where %llu is used.

Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_kvp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index d6106e1a0d4a..5054d1105236 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -437,7 +437,7 @@ kvp_send_key(struct work_struct *dummy)
val32 = in_msg->body.kvp_set.data.value_u32;
message->body.kvp_set.data.value_size =
sprintf(message->body.kvp_set.data.value,
-   "%d", val32) + 1;
+   "%u", val32) + 1;
break;
 
case REG_U64:
-- 
2.18.0



[PATCH V2 0/5] Drivers: hv: Miscellaneous fixes

2018-10-17 Thread kys
From: "K. Y. Srinivasan" 

Miscellaneous fixes.

V2: Addressed comments from Greg.

Dexuan Cui (3):
  Drivers: hv: kvp: Fix the recent regression caused by incorrect
clean-up
  Drivers: hv: kvp: Use %u to print U32
  Tools: hv: kvp: Fix a warning of buffer overflow with gcc 8.0.1

Haiyang Zhang (1):
  hv_utils: update name in struct hv_driver util_drv

K. Y. Srinivasan (1):
  Drivers: hv: vmbus: Get rid of unnecessary state in hv_context

 drivers/hv/hv.c   | 10 +++---
 drivers/hv/hv_kvp.c   | 28 +++-
 drivers/hv/hv_util.c  |  2 +-
 drivers/hv/hyperv_vmbus.h |  2 --
 tools/hv/hv_kvp_daemon.c  | 15 +--
 5 files changed, 40 insertions(+), 17 deletions(-)

-- 
2.18.0



[PATCH V2 0/5] Drivers: hv: Miscellaneous fixes

2018-10-17 Thread kys
From: "K. Y. Srinivasan" 

Miscellaneous fixes.

V2: Addressed comments from Greg.

Dexuan Cui (3):
  Drivers: hv: kvp: Fix the recent regression caused by incorrect
clean-up
  Drivers: hv: kvp: Use %u to print U32
  Tools: hv: kvp: Fix a warning of buffer overflow with gcc 8.0.1

Haiyang Zhang (1):
  hv_utils: update name in struct hv_driver util_drv

K. Y. Srinivasan (1):
  Drivers: hv: vmbus: Get rid of unnecessary state in hv_context

 drivers/hv/hv.c   | 10 +++---
 drivers/hv/hv_kvp.c   | 28 +++-
 drivers/hv/hv_util.c  |  2 +-
 drivers/hv/hyperv_vmbus.h |  2 --
 tools/hv/hv_kvp_daemon.c  | 15 +--
 5 files changed, 40 insertions(+), 17 deletions(-)

-- 
2.18.0



[PATCH V2 2/5] hv_utils: update name in struct hv_driver util_drv

2018-10-17 Thread kys
From: Haiyang Zhang 

The correct module name is hv_utils. This patch corrects
the name in struct hv_driver util_drv.

Signed-off-by: Haiyang Zhang 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_util.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index 423205077bf6..f10eeb120c8b 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -483,7 +483,7 @@ MODULE_DEVICE_TABLE(vmbus, id_table);
 
 /* The one and only one */
 static  struct hv_driver util_drv = {
-   .name = "hv_util",
+   .name = "hv_utils",
.id_table = id_table,
.probe =  util_probe,
.remove =  util_remove,
-- 
2.18.0



[PATCH V2 1/5] Drivers: hv: vmbus: Get rid of unnecessary state in hv_context

2018-10-17 Thread kys
From: "K. Y. Srinivasan" 

Currently we are replicating state in struct hv_context that is unnecessary -
this state can be retrieved from the hypervisor. Furthermore, this is a per-cpu
state that is being maintained as a global state in struct hv_context.
Get rid of this state in struct hv_context.

Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv.c   | 10 +++---
 drivers/hv/hyperv_vmbus.h |  2 --
 2 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 332d7c34be5c..166c2501de17 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -33,9 +33,7 @@
 #include "hyperv_vmbus.h"
 
 /* The one and only */
-struct hv_context hv_context = {
-   .synic_initialized  = false,
-};
+struct hv_context hv_context;
 
 /*
  * If false, we're using the old mechanism for stimer0 interrupts
@@ -326,8 +324,6 @@ int hv_synic_init(unsigned int cpu)
 
hv_set_synic_state(sctrl.as_uint64);
 
-   hv_context.synic_initialized = true;
-
/*
 * Register the per-cpu clockevent source.
 */
@@ -373,7 +369,8 @@ int hv_synic_cleanup(unsigned int cpu)
bool channel_found = false;
unsigned long flags;
 
-   if (!hv_context.synic_initialized)
+   hv_get_synic_state(sctrl.as_uint64);
+   if (sctrl.enable != 1)
return -EFAULT;
 
/*
@@ -435,7 +432,6 @@ int hv_synic_cleanup(unsigned int cpu)
hv_set_siefp(siefp.as_uint64);
 
/* Disable the global synic bit */
-   hv_get_synic_state(sctrl.as_uint64);
sctrl.enable = 0;
hv_set_synic_state(sctrl.as_uint64);
 
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 72eaba3d50fc..f17c06a5e74b 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -230,8 +230,6 @@ struct hv_context {
 
void *tsc_page;
 
-   bool synic_initialized;
-
struct hv_per_cpu_context __percpu *cpu_context;
 
/*
-- 
2.18.0



[PATCH V2 2/5] hv_utils: update name in struct hv_driver util_drv

2018-10-17 Thread kys
From: Haiyang Zhang 

The correct module name is hv_utils. This patch corrects
the name in struct hv_driver util_drv.

Signed-off-by: Haiyang Zhang 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_util.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index 423205077bf6..f10eeb120c8b 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -483,7 +483,7 @@ MODULE_DEVICE_TABLE(vmbus, id_table);
 
 /* The one and only one */
 static  struct hv_driver util_drv = {
-   .name = "hv_util",
+   .name = "hv_utils",
.id_table = id_table,
.probe =  util_probe,
.remove =  util_remove,
-- 
2.18.0



[PATCH V2 1/5] Drivers: hv: vmbus: Get rid of unnecessary state in hv_context

2018-10-17 Thread kys
From: "K. Y. Srinivasan" 

Currently we are replicating state in struct hv_context that is unnecessary -
this state can be retrieved from the hypervisor. Furthermore, this is a per-cpu
state that is being maintained as a global state in struct hv_context.
Get rid of this state in struct hv_context.

Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv.c   | 10 +++---
 drivers/hv/hyperv_vmbus.h |  2 --
 2 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 332d7c34be5c..166c2501de17 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -33,9 +33,7 @@
 #include "hyperv_vmbus.h"
 
 /* The one and only */
-struct hv_context hv_context = {
-   .synic_initialized  = false,
-};
+struct hv_context hv_context;
 
 /*
  * If false, we're using the old mechanism for stimer0 interrupts
@@ -326,8 +324,6 @@ int hv_synic_init(unsigned int cpu)
 
hv_set_synic_state(sctrl.as_uint64);
 
-   hv_context.synic_initialized = true;
-
/*
 * Register the per-cpu clockevent source.
 */
@@ -373,7 +369,8 @@ int hv_synic_cleanup(unsigned int cpu)
bool channel_found = false;
unsigned long flags;
 
-   if (!hv_context.synic_initialized)
+   hv_get_synic_state(sctrl.as_uint64);
+   if (sctrl.enable != 1)
return -EFAULT;
 
/*
@@ -435,7 +432,6 @@ int hv_synic_cleanup(unsigned int cpu)
hv_set_siefp(siefp.as_uint64);
 
/* Disable the global synic bit */
-   hv_get_synic_state(sctrl.as_uint64);
sctrl.enable = 0;
hv_set_synic_state(sctrl.as_uint64);
 
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 72eaba3d50fc..f17c06a5e74b 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -230,8 +230,6 @@ struct hv_context {
 
void *tsc_page;
 
-   bool synic_initialized;
-
struct hv_per_cpu_context __percpu *cpu_context;
 
/*
-- 
2.18.0



[PATCH V2 3/5] Drivers: hv: kvp: Fix the recent regression caused by incorrect clean-up

2018-10-17 Thread kys
From: Dexuan Cui 

In kvp_send_key(), we do need call process_ib_ipinfo() if
message->kvp_hdr.operation is KVP_OP_GET_IP_INFO, because it turns out
the userland hv_kvp_daemon needs the info of operation, adapter_id and
addr_family. With the incorrect fc62c3b1977d, the host can't get the
VM's IP via KVP.

And, fc62c3b1977d added a "break;", but actually forgot to initialize
the key_size/value in the case of KVP_OP_SET, so the default key_size of
0 is passed to the kvp daemon, and the pool files
/var/lib/hyperv/.kvp_pool_* can't be updated.

This patch effectively rolls back the previous fc62c3b1977d, and
correctly fixes the "this statement may fall through" warnings.

This patch is tested on WS 2012 R2 and 2016.

Fixes: fc62c3b1977d ("Drivers: hv: kvp: Fix two "this statement may fall 
through" warnings")
Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Cc: 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_kvp.c | 26 ++
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index a7513a8a8e37..d6106e1a0d4a 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -353,6 +353,9 @@ static void process_ib_ipinfo(void *in_msg, void *out_msg, 
int op)
 
out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled;
 
+   /* fallthrough */
+
+   case KVP_OP_GET_IP_INFO:
utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id,
MAX_ADAPTER_ID_SIZE,
UTF16_LITTLE_ENDIAN,
@@ -405,7 +408,11 @@ kvp_send_key(struct work_struct *dummy)
process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);
break;
case KVP_OP_GET_IP_INFO:
-   /* We only need to pass on message->kvp_hdr.operation.  */
+   /*
+* We only need to pass on the info of operation, adapter_id
+* and addr_family to the userland kvp daemon.
+*/
+   process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);
break;
case KVP_OP_SET:
switch (in_msg->body.kvp_set.data.value_type) {
@@ -446,9 +453,9 @@ kvp_send_key(struct work_struct *dummy)
 
}
 
-   break;
-
-   case KVP_OP_GET:
+   /*
+* The key is always a string - utf16 encoding.
+*/
message->body.kvp_set.data.key_size =
utf16s_to_utf8s(
(wchar_t *)in_msg->body.kvp_set.data.key,
@@ -456,6 +463,17 @@ kvp_send_key(struct work_struct *dummy)
UTF16_LITTLE_ENDIAN,
message->body.kvp_set.data.key,
HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
+
+   break;
+
+   case KVP_OP_GET:
+   message->body.kvp_get.data.key_size =
+   utf16s_to_utf8s(
+   (wchar_t *)in_msg->body.kvp_get.data.key,
+   in_msg->body.kvp_get.data.key_size,
+   UTF16_LITTLE_ENDIAN,
+   message->body.kvp_get.data.key,
+   HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
break;
 
case KVP_OP_DELETE:
-- 
2.18.0



[PATCH V2 5/5] Tools: hv: kvp: Fix a warning of buffer overflow with gcc 8.0.1

2018-10-17 Thread kys
From: Dexuan Cui 

The patch fixes:

hv_kvp_daemon.c: In function 'kvp_set_ip_info':
hv_kvp_daemon.c:1305:2: note: 'snprintf' output between 41 and 4136 bytes
into a destination of size 4096

The "(unsigned int)str_len" is to avoid:

hv_kvp_daemon.c:1309:30: warning: comparison of integer expressions of
different signedness: 'int' and 'long unsigned int' [-Wsign-compare]

Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 tools/hv/hv_kvp_daemon.c | 15 +--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index bbb2a8ef367c..d7e06fe0270e 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -1178,6 +1178,7 @@ static int kvp_set_ip_info(char *if_name, struct 
hv_kvp_ipaddr_value *new_val)
FILE *file;
char cmd[PATH_MAX];
char *mac_addr;
+   int str_len;
 
/*
 * Set the configuration for the specified interface with
@@ -1301,8 +1302,18 @@ static int kvp_set_ip_info(char *if_name, struct 
hv_kvp_ipaddr_value *new_val)
 * invoke the external script to do its magic.
 */
 
-   snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s",
-"hv_set_ifconfig", if_file);
+   str_len = snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s",
+  "hv_set_ifconfig", if_file);
+   /*
+* This is a little overcautious, but it's necessary to suppress some
+* false warnings from gcc 8.0.1.
+*/
+   if (str_len <= 0 || (unsigned int)str_len >= sizeof(cmd)) {
+   syslog(LOG_ERR, "Cmd '%s' (len=%d) may be too long",
+  cmd, str_len);
+   return HV_E_FAIL;
+   }
+
if (system(cmd)) {
syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s",
cmd, errno, strerror(errno));
-- 
2.18.0



[PATCH V2 3/5] Drivers: hv: kvp: Fix the recent regression caused by incorrect clean-up

2018-10-17 Thread kys
From: Dexuan Cui 

In kvp_send_key(), we do need call process_ib_ipinfo() if
message->kvp_hdr.operation is KVP_OP_GET_IP_INFO, because it turns out
the userland hv_kvp_daemon needs the info of operation, adapter_id and
addr_family. With the incorrect fc62c3b1977d, the host can't get the
VM's IP via KVP.

And, fc62c3b1977d added a "break;", but actually forgot to initialize
the key_size/value in the case of KVP_OP_SET, so the default key_size of
0 is passed to the kvp daemon, and the pool files
/var/lib/hyperv/.kvp_pool_* can't be updated.

This patch effectively rolls back the previous fc62c3b1977d, and
correctly fixes the "this statement may fall through" warnings.

This patch is tested on WS 2012 R2 and 2016.

Fixes: fc62c3b1977d ("Drivers: hv: kvp: Fix two "this statement may fall 
through" warnings")
Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Cc: 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_kvp.c | 26 ++
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index a7513a8a8e37..d6106e1a0d4a 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -353,6 +353,9 @@ static void process_ib_ipinfo(void *in_msg, void *out_msg, 
int op)
 
out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled;
 
+   /* fallthrough */
+
+   case KVP_OP_GET_IP_INFO:
utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id,
MAX_ADAPTER_ID_SIZE,
UTF16_LITTLE_ENDIAN,
@@ -405,7 +408,11 @@ kvp_send_key(struct work_struct *dummy)
process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);
break;
case KVP_OP_GET_IP_INFO:
-   /* We only need to pass on message->kvp_hdr.operation.  */
+   /*
+* We only need to pass on the info of operation, adapter_id
+* and addr_family to the userland kvp daemon.
+*/
+   process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);
break;
case KVP_OP_SET:
switch (in_msg->body.kvp_set.data.value_type) {
@@ -446,9 +453,9 @@ kvp_send_key(struct work_struct *dummy)
 
}
 
-   break;
-
-   case KVP_OP_GET:
+   /*
+* The key is always a string - utf16 encoding.
+*/
message->body.kvp_set.data.key_size =
utf16s_to_utf8s(
(wchar_t *)in_msg->body.kvp_set.data.key,
@@ -456,6 +463,17 @@ kvp_send_key(struct work_struct *dummy)
UTF16_LITTLE_ENDIAN,
message->body.kvp_set.data.key,
HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
+
+   break;
+
+   case KVP_OP_GET:
+   message->body.kvp_get.data.key_size =
+   utf16s_to_utf8s(
+   (wchar_t *)in_msg->body.kvp_get.data.key,
+   in_msg->body.kvp_get.data.key_size,
+   UTF16_LITTLE_ENDIAN,
+   message->body.kvp_get.data.key,
+   HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
break;
 
case KVP_OP_DELETE:
-- 
2.18.0



[PATCH V2 5/5] Tools: hv: kvp: Fix a warning of buffer overflow with gcc 8.0.1

2018-10-17 Thread kys
From: Dexuan Cui 

The patch fixes:

hv_kvp_daemon.c: In function 'kvp_set_ip_info':
hv_kvp_daemon.c:1305:2: note: 'snprintf' output between 41 and 4136 bytes
into a destination of size 4096

The "(unsigned int)str_len" is to avoid:

hv_kvp_daemon.c:1309:30: warning: comparison of integer expressions of
different signedness: 'int' and 'long unsigned int' [-Wsign-compare]

Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 tools/hv/hv_kvp_daemon.c | 15 +--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index bbb2a8ef367c..d7e06fe0270e 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -1178,6 +1178,7 @@ static int kvp_set_ip_info(char *if_name, struct 
hv_kvp_ipaddr_value *new_val)
FILE *file;
char cmd[PATH_MAX];
char *mac_addr;
+   int str_len;
 
/*
 * Set the configuration for the specified interface with
@@ -1301,8 +1302,18 @@ static int kvp_set_ip_info(char *if_name, struct 
hv_kvp_ipaddr_value *new_val)
 * invoke the external script to do its magic.
 */
 
-   snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s",
-"hv_set_ifconfig", if_file);
+   str_len = snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s",
+  "hv_set_ifconfig", if_file);
+   /*
+* This is a little overcautious, but it's necessary to suppress some
+* false warnings from gcc 8.0.1.
+*/
+   if (str_len <= 0 || (unsigned int)str_len >= sizeof(cmd)) {
+   syslog(LOG_ERR, "Cmd '%s' (len=%d) may be too long",
+  cmd, str_len);
+   return HV_E_FAIL;
+   }
+
if (system(cmd)) {
syslog(LOG_ERR, "Failed to execute cmd '%s'; error: %d %s",
cmd, errno, strerror(errno));
-- 
2.18.0



[PATCH 3/5] Drivers: hv: kvp: Fix the recent regression caused by incorrect clean-up

2018-10-16 Thread kys
From: Dexuan Cui 

In kvp_send_key(), we do need call process_ib_ipinfo() if
message->kvp_hdr.operation is KVP_OP_GET_IP_INFO, because it turns out
the userland hv_kvp_daemon needs the info of operation, adapter_id and
addr_family. With the incorrect fc62c3b1977d, the host can't get the
VM's IP via KVP.

And, fc62c3b1977d added a "break;", but actually forgot to initialize
the key_size/value in the case of KVP_OP_SET, so the default key_size of
0 is passed to the kvp daemon, and the pool files
/var/lib/hyperv/.kvp_pool_* can't be updated.

This patch effectively rolls back the previous fc62c3b1977d, and
correctly fixes the "this statement may fall through" warnings.

This patch is tested on WS 2012 R2 and 2016.

Fixes: fc62c3b1977d ("Drivers: hv: kvp: Fix two "this statement may fall 
through" warnings")
Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Cc: 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_kvp.c | 26 ++
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index a7513a8a8e37..9fbb15c62c6c 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -353,6 +353,9 @@ static void process_ib_ipinfo(void *in_msg, void *out_msg, 
int op)
 
out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled;
 
+   __attribute__ ((fallthrough));
+
+   case KVP_OP_GET_IP_INFO:
utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id,
MAX_ADAPTER_ID_SIZE,
UTF16_LITTLE_ENDIAN,
@@ -405,7 +408,11 @@ kvp_send_key(struct work_struct *dummy)
process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);
break;
case KVP_OP_GET_IP_INFO:
-   /* We only need to pass on message->kvp_hdr.operation.  */
+   /*
+* We only need to pass on the info of operation, adapter_id
+* and addr_family to the userland kvp daemon.
+*/
+   process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);
break;
case KVP_OP_SET:
switch (in_msg->body.kvp_set.data.value_type) {
@@ -446,9 +453,9 @@ kvp_send_key(struct work_struct *dummy)
 
}
 
-   break;
-
-   case KVP_OP_GET:
+   /*
+* The key is always a string - utf16 encoding.
+*/
message->body.kvp_set.data.key_size =
utf16s_to_utf8s(
(wchar_t *)in_msg->body.kvp_set.data.key,
@@ -456,6 +463,17 @@ kvp_send_key(struct work_struct *dummy)
UTF16_LITTLE_ENDIAN,
message->body.kvp_set.data.key,
HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
+
+   break;
+
+   case KVP_OP_GET:
+   message->body.kvp_get.data.key_size =
+   utf16s_to_utf8s(
+   (wchar_t *)in_msg->body.kvp_get.data.key,
+   in_msg->body.kvp_get.data.key_size,
+   UTF16_LITTLE_ENDIAN,
+   message->body.kvp_get.data.key,
+   HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
break;
 
case KVP_OP_DELETE:
-- 
2.18.0



[PATCH 1/5] Drivers: hv: vmbus: Get rid of unnecessary state in hv_context

2018-10-16 Thread kys
From: "K. Y. Srinivasan" 

Currently we are replicating state in struct hv_context that is unnecessary -
this state can be retrieved from the hypervisor. Furthermore, this is a per-cpu
state that is being maintained as a global state in struct hv_context.
Get rid of this state in struct hv_context.

Reply-To: k...@microsoft.com

Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv.c   | 10 +++---
 drivers/hv/hyperv_vmbus.h |  2 --
 2 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 332d7c34be5c..166c2501de17 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -33,9 +33,7 @@
 #include "hyperv_vmbus.h"
 
 /* The one and only */
-struct hv_context hv_context = {
-   .synic_initialized  = false,
-};
+struct hv_context hv_context;
 
 /*
  * If false, we're using the old mechanism for stimer0 interrupts
@@ -326,8 +324,6 @@ int hv_synic_init(unsigned int cpu)
 
hv_set_synic_state(sctrl.as_uint64);
 
-   hv_context.synic_initialized = true;
-
/*
 * Register the per-cpu clockevent source.
 */
@@ -373,7 +369,8 @@ int hv_synic_cleanup(unsigned int cpu)
bool channel_found = false;
unsigned long flags;
 
-   if (!hv_context.synic_initialized)
+   hv_get_synic_state(sctrl.as_uint64);
+   if (sctrl.enable != 1)
return -EFAULT;
 
/*
@@ -435,7 +432,6 @@ int hv_synic_cleanup(unsigned int cpu)
hv_set_siefp(siefp.as_uint64);
 
/* Disable the global synic bit */
-   hv_get_synic_state(sctrl.as_uint64);
sctrl.enable = 0;
hv_set_synic_state(sctrl.as_uint64);
 
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 72eaba3d50fc..f17c06a5e74b 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -230,8 +230,6 @@ struct hv_context {
 
void *tsc_page;
 
-   bool synic_initialized;
-
struct hv_per_cpu_context __percpu *cpu_context;
 
/*
-- 
2.18.0



[PATCH 2/5] hv_utils: update name in struct hv_driver util_drv

2018-10-16 Thread kys
From: Haiyang Zhang 

The correct module name is hv_utils. This patch corrects
the name in struct hv_driver util_drv.

Signed-off-by: Haiyang Zhang 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_util.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index 423205077bf6..f10eeb120c8b 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -483,7 +483,7 @@ MODULE_DEVICE_TABLE(vmbus, id_table);
 
 /* The one and only one */
 static  struct hv_driver util_drv = {
-   .name = "hv_util",
+   .name = "hv_utils",
.id_table = id_table,
.probe =  util_probe,
.remove =  util_remove,
-- 
2.18.0



[PATCH 3/5] Drivers: hv: kvp: Fix the recent regression caused by incorrect clean-up

2018-10-16 Thread kys
From: Dexuan Cui 

In kvp_send_key(), we do need call process_ib_ipinfo() if
message->kvp_hdr.operation is KVP_OP_GET_IP_INFO, because it turns out
the userland hv_kvp_daemon needs the info of operation, adapter_id and
addr_family. With the incorrect fc62c3b1977d, the host can't get the
VM's IP via KVP.

And, fc62c3b1977d added a "break;", but actually forgot to initialize
the key_size/value in the case of KVP_OP_SET, so the default key_size of
0 is passed to the kvp daemon, and the pool files
/var/lib/hyperv/.kvp_pool_* can't be updated.

This patch effectively rolls back the previous fc62c3b1977d, and
correctly fixes the "this statement may fall through" warnings.

This patch is tested on WS 2012 R2 and 2016.

Fixes: fc62c3b1977d ("Drivers: hv: kvp: Fix two "this statement may fall 
through" warnings")
Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Cc: 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_kvp.c | 26 ++
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index a7513a8a8e37..9fbb15c62c6c 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -353,6 +353,9 @@ static void process_ib_ipinfo(void *in_msg, void *out_msg, 
int op)
 
out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled;
 
+   __attribute__ ((fallthrough));
+
+   case KVP_OP_GET_IP_INFO:
utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id,
MAX_ADAPTER_ID_SIZE,
UTF16_LITTLE_ENDIAN,
@@ -405,7 +408,11 @@ kvp_send_key(struct work_struct *dummy)
process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);
break;
case KVP_OP_GET_IP_INFO:
-   /* We only need to pass on message->kvp_hdr.operation.  */
+   /*
+* We only need to pass on the info of operation, adapter_id
+* and addr_family to the userland kvp daemon.
+*/
+   process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);
break;
case KVP_OP_SET:
switch (in_msg->body.kvp_set.data.value_type) {
@@ -446,9 +453,9 @@ kvp_send_key(struct work_struct *dummy)
 
}
 
-   break;
-
-   case KVP_OP_GET:
+   /*
+* The key is always a string - utf16 encoding.
+*/
message->body.kvp_set.data.key_size =
utf16s_to_utf8s(
(wchar_t *)in_msg->body.kvp_set.data.key,
@@ -456,6 +463,17 @@ kvp_send_key(struct work_struct *dummy)
UTF16_LITTLE_ENDIAN,
message->body.kvp_set.data.key,
HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
+
+   break;
+
+   case KVP_OP_GET:
+   message->body.kvp_get.data.key_size =
+   utf16s_to_utf8s(
+   (wchar_t *)in_msg->body.kvp_get.data.key,
+   in_msg->body.kvp_get.data.key_size,
+   UTF16_LITTLE_ENDIAN,
+   message->body.kvp_get.data.key,
+   HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
break;
 
case KVP_OP_DELETE:
-- 
2.18.0



[PATCH 1/5] Drivers: hv: vmbus: Get rid of unnecessary state in hv_context

2018-10-16 Thread kys
From: "K. Y. Srinivasan" 

Currently we are replicating state in struct hv_context that is unnecessary -
this state can be retrieved from the hypervisor. Furthermore, this is a per-cpu
state that is being maintained as a global state in struct hv_context.
Get rid of this state in struct hv_context.

Reply-To: k...@microsoft.com

Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv.c   | 10 +++---
 drivers/hv/hyperv_vmbus.h |  2 --
 2 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 332d7c34be5c..166c2501de17 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -33,9 +33,7 @@
 #include "hyperv_vmbus.h"
 
 /* The one and only */
-struct hv_context hv_context = {
-   .synic_initialized  = false,
-};
+struct hv_context hv_context;
 
 /*
  * If false, we're using the old mechanism for stimer0 interrupts
@@ -326,8 +324,6 @@ int hv_synic_init(unsigned int cpu)
 
hv_set_synic_state(sctrl.as_uint64);
 
-   hv_context.synic_initialized = true;
-
/*
 * Register the per-cpu clockevent source.
 */
@@ -373,7 +369,8 @@ int hv_synic_cleanup(unsigned int cpu)
bool channel_found = false;
unsigned long flags;
 
-   if (!hv_context.synic_initialized)
+   hv_get_synic_state(sctrl.as_uint64);
+   if (sctrl.enable != 1)
return -EFAULT;
 
/*
@@ -435,7 +432,6 @@ int hv_synic_cleanup(unsigned int cpu)
hv_set_siefp(siefp.as_uint64);
 
/* Disable the global synic bit */
-   hv_get_synic_state(sctrl.as_uint64);
sctrl.enable = 0;
hv_set_synic_state(sctrl.as_uint64);
 
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 72eaba3d50fc..f17c06a5e74b 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -230,8 +230,6 @@ struct hv_context {
 
void *tsc_page;
 
-   bool synic_initialized;
-
struct hv_per_cpu_context __percpu *cpu_context;
 
/*
-- 
2.18.0



[PATCH 2/5] hv_utils: update name in struct hv_driver util_drv

2018-10-16 Thread kys
From: Haiyang Zhang 

The correct module name is hv_utils. This patch corrects
the name in struct hv_driver util_drv.

Signed-off-by: Haiyang Zhang 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_util.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index 423205077bf6..f10eeb120c8b 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -483,7 +483,7 @@ MODULE_DEVICE_TABLE(vmbus, id_table);
 
 /* The one and only one */
 static  struct hv_driver util_drv = {
-   .name = "hv_util",
+   .name = "hv_utils",
.id_table = id_table,
.probe =  util_probe,
.remove =  util_remove,
-- 
2.18.0



[PATCH 5/5] Tools: hv: kvp: Fix a warning of buffer overflow with gcc 8.0.1

2018-10-16 Thread kys
From: Dexuan Cui 

The patch fixes:

hv_kvp_daemon.c: In function 'kvp_set_ip_info':
hv_kvp_daemon.c:1305:2: note: 'snprintf' output between 41 and 4136 bytes
into a destination of size 4096

Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Cc: 
Signed-off-by: K. Y. Srinivasan 
---
 tools/hv/hv_kvp_daemon.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index bbb2a8ef367c..b7c2cf7eaba5 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -1176,7 +1176,7 @@ static int kvp_set_ip_info(char *if_name, struct 
hv_kvp_ipaddr_value *new_val)
int error = 0;
char if_file[PATH_MAX];
FILE *file;
-   char cmd[PATH_MAX];
+   char cmd[PATH_MAX * 2];
char *mac_addr;
 
/*
-- 
2.18.0



[PATCH 5/5] Tools: hv: kvp: Fix a warning of buffer overflow with gcc 8.0.1

2018-10-16 Thread kys
From: Dexuan Cui 

The patch fixes:

hv_kvp_daemon.c: In function 'kvp_set_ip_info':
hv_kvp_daemon.c:1305:2: note: 'snprintf' output between 41 and 4136 bytes
into a destination of size 4096

Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Cc: 
Signed-off-by: K. Y. Srinivasan 
---
 tools/hv/hv_kvp_daemon.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index bbb2a8ef367c..b7c2cf7eaba5 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -1176,7 +1176,7 @@ static int kvp_set_ip_info(char *if_name, struct 
hv_kvp_ipaddr_value *new_val)
int error = 0;
char if_file[PATH_MAX];
FILE *file;
-   char cmd[PATH_MAX];
+   char cmd[PATH_MAX * 2];
char *mac_addr;
 
/*
-- 
2.18.0



[PATCH 4/5] Drivers: hv: kvp: Use %u to print U32

2018-10-16 Thread kys
From: Dexuan Cui 

I didn't find a real issue. Let's just make it consistent with the
next "case REG_U64:" where %llu is used.

Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Cc: 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_kvp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 9fbb15c62c6c..3b8590ff94ba 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -437,7 +437,7 @@ kvp_send_key(struct work_struct *dummy)
val32 = in_msg->body.kvp_set.data.value_u32;
message->body.kvp_set.data.value_size =
sprintf(message->body.kvp_set.data.value,
-   "%d", val32) + 1;
+   "%u", val32) + 1;
break;
 
case REG_U64:
-- 
2.18.0



[PATCH 4/5] Drivers: hv: kvp: Use %u to print U32

2018-10-16 Thread kys
From: Dexuan Cui 

I didn't find a real issue. Let's just make it consistent with the
next "case REG_U64:" where %llu is used.

Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Cc: 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_kvp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 9fbb15c62c6c..3b8590ff94ba 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -437,7 +437,7 @@ kvp_send_key(struct work_struct *dummy)
val32 = in_msg->body.kvp_set.data.value_u32;
message->body.kvp_set.data.value_size =
sprintf(message->body.kvp_set.data.value,
-   "%d", val32) + 1;
+   "%u", val32) + 1;
break;
 
case REG_U64:
-- 
2.18.0



[PATCH 0/5] Drivers: hv: Miscellaneous fixes

2018-10-16 Thread kys
From: "K. Y. Srinivasan" 

Miscellaneous fixes.

Dexuan Cui (3):
  Drivers: hv: kvp: Fix the recent regression caused by incorrect
clean-up
  Drivers: hv: kvp: Use %u to print U32
  Tools: hv: kvp: Fix a warning of buffer overflow with gcc 8.0.1

Haiyang Zhang (1):
  hv_utils: update name in struct hv_driver util_drv

K. Y. Srinivasan (1):
  Drivers: hv: vmbus: Get rid of unnecessary state in hv_context

 drivers/hv/hv.c   | 10 +++---
 drivers/hv/hv_kvp.c   | 28 +++-
 drivers/hv/hv_util.c  |  2 +-
 drivers/hv/hyperv_vmbus.h |  2 --
 tools/hv/hv_kvp_daemon.c  |  2 +-
 5 files changed, 28 insertions(+), 16 deletions(-)

-- 
2.18.0



[PATCH 0/5] Drivers: hv: Miscellaneous fixes

2018-10-16 Thread kys
From: "K. Y. Srinivasan" 

Miscellaneous fixes.

Dexuan Cui (3):
  Drivers: hv: kvp: Fix the recent regression caused by incorrect
clean-up
  Drivers: hv: kvp: Use %u to print U32
  Tools: hv: kvp: Fix a warning of buffer overflow with gcc 8.0.1

Haiyang Zhang (1):
  hv_utils: update name in struct hv_driver util_drv

K. Y. Srinivasan (1):
  Drivers: hv: vmbus: Get rid of unnecessary state in hv_context

 drivers/hv/hv.c   | 10 +++---
 drivers/hv/hv_kvp.c   | 28 +++-
 drivers/hv/hv_util.c  |  2 +-
 drivers/hv/hyperv_vmbus.h |  2 --
 tools/hv/hv_kvp_daemon.c  |  2 +-
 5 files changed, 28 insertions(+), 16 deletions(-)

-- 
2.18.0



[PATCH 3/4] Drivers: hv: kvp: Fix two "this statement may fall through" warnings

2018-09-23 Thread kys
From: Dexuan Cui 

We don't need to call process_ib_ipinfo() if message->kvp_hdr.operation is
KVP_OP_GET_IP_INFO in kvp_send_key(), because here we just need to pass on
the op code from the host to the userspace; when the userspace returns
the info requested by the host, we pass the info on to the host in
kvp_respond_to_host() -> process_ob_ipinfo(). BTW, the current buggy code
actually doesn't cause any harm, because only message->kvp_hdr.operation
is used by the userspace, in the case of KVP_OP_GET_IP_INFO.

The patch also adds a missing "break;" in kvp_send_key(). BTW, the current
buggy code actually doesn't cause any harm, because in the case of
KVP_OP_SET, the unexpected fall-through corrupts
message->body.kvp_set.data.key_size, but that is not really used: see
the definition of struct hv_kvp_exchg_msg_value.

Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Cc: 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_kvp.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 023bd185d21a..a7513a8a8e37 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -353,7 +353,6 @@ static void process_ib_ipinfo(void *in_msg, void *out_msg, 
int op)
 
out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled;
 
-   default:
utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id,
MAX_ADAPTER_ID_SIZE,
UTF16_LITTLE_ENDIAN,
@@ -406,7 +405,7 @@ kvp_send_key(struct work_struct *dummy)
process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);
break;
case KVP_OP_GET_IP_INFO:
-   process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);
+   /* We only need to pass on message->kvp_hdr.operation.  */
break;
case KVP_OP_SET:
switch (in_msg->body.kvp_set.data.value_type) {
@@ -446,6 +445,9 @@ kvp_send_key(struct work_struct *dummy)
break;
 
}
+
+   break;
+
case KVP_OP_GET:
message->body.kvp_set.data.key_size =
utf16s_to_utf8s(
-- 
2.18.0



[PATCH 3/4] Drivers: hv: kvp: Fix two "this statement may fall through" warnings

2018-09-23 Thread kys
From: Dexuan Cui 

We don't need to call process_ib_ipinfo() if message->kvp_hdr.operation is
KVP_OP_GET_IP_INFO in kvp_send_key(), because here we just need to pass on
the op code from the host to the userspace; when the userspace returns
the info requested by the host, we pass the info on to the host in
kvp_respond_to_host() -> process_ob_ipinfo(). BTW, the current buggy code
actually doesn't cause any harm, because only message->kvp_hdr.operation
is used by the userspace, in the case of KVP_OP_GET_IP_INFO.

The patch also adds a missing "break;" in kvp_send_key(). BTW, the current
buggy code actually doesn't cause any harm, because in the case of
KVP_OP_SET, the unexpected fall-through corrupts
message->body.kvp_set.data.key_size, but that is not really used: see
the definition of struct hv_kvp_exchg_msg_value.

Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Cc: 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_kvp.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 023bd185d21a..a7513a8a8e37 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -353,7 +353,6 @@ static void process_ib_ipinfo(void *in_msg, void *out_msg, 
int op)
 
out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled;
 
-   default:
utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id,
MAX_ADAPTER_ID_SIZE,
UTF16_LITTLE_ENDIAN,
@@ -406,7 +405,7 @@ kvp_send_key(struct work_struct *dummy)
process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);
break;
case KVP_OP_GET_IP_INFO:
-   process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);
+   /* We only need to pass on message->kvp_hdr.operation.  */
break;
case KVP_OP_SET:
switch (in_msg->body.kvp_set.data.value_type) {
@@ -446,6 +445,9 @@ kvp_send_key(struct work_struct *dummy)
break;
 
}
+
+   break;
+
case KVP_OP_GET:
message->body.kvp_set.data.key_size =
utf16s_to_utf8s(
-- 
2.18.0



[PATCH 1/4] Drivers: hv: vmbus: Fix the descriptions of some function parameters

2018-09-23 Thread kys
From: Dexuan Cui 

No functional change.

Added descriptions for some parameters.
Fixed some typos.
Removed some out-of-date comments.

Signed-off-by: Dexuan Cui 
Cc: Jonathan Corbet 
Cc: linux-...@vger.kernel.org
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/channel.c  | 24 +---
 drivers/hv/channel_mgmt.c | 23 +--
 2 files changed, 22 insertions(+), 25 deletions(-)

diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index 741857d80da1..ab92779271d0 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -709,15 +709,16 @@ EXPORT_SYMBOL_GPL(vmbus_close);
 
 /**
  * vmbus_sendpacket() - Send the specified buffer on the given channel
- * @channel: Pointer to vmbus_channel structure.
- * @buffer: Pointer to the buffer you want to receive the data into.
- * @bufferlen: Maximum size of what the the buffer will hold
+ * @channel: Pointer to vmbus_channel structure
+ * @buffer: Pointer to the buffer you want to send the data from.
+ * @bufferlen: Maximum size of what the buffer holds.
  * @requestid: Identifier of the request
- * @type: Type of packet that is being send e.g. negotiate, time
- * packet etc.
+ * @type: Type of packet that is being sent e.g. negotiate, time
+ *   packet etc.
+ * @flags: 0 or VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
  *
- * Sends data in @buffer directly to hyper-v via the vmbus
- * This will send the data unparsed to hyper-v.
+ * Sends data in @buffer directly to Hyper-V via the vmbus.
+ * This will send the data unparsed to Hyper-V.
  *
  * Mainly used by Hyper-V drivers.
  */
@@ -850,12 +851,13 @@ int vmbus_sendpacket_mpb_desc(struct vmbus_channel 
*channel,
 EXPORT_SYMBOL_GPL(vmbus_sendpacket_mpb_desc);
 
 /**
- * vmbus_recvpacket() - Retrieve the user packet on the specified channel
- * @channel: Pointer to vmbus_channel structure.
+ * __vmbus_recvpacket() - Retrieve the user packet on the specified channel
+ * @channel: Pointer to vmbus_channel structure
  * @buffer: Pointer to the buffer you want to receive the data into.
- * @bufferlen: Maximum size of what the the buffer will hold
- * @buffer_actual_len: The actual size of the data after it was received
+ * @bufferlen: Maximum size of what the buffer can hold.
+ * @buffer_actual_len: The actual size of the data after it was received.
  * @requestid: Identifier of the request
+ * @raw: true means keep the vmpacket_descriptor header in the received data.
  *
  * Receives directly from the hyper-v vmbus and puts the data it received
  * into Buffer. This will receive the data unparsed from hyper-v.
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 0f0e091c117c..e7598b569bea 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -198,24 +198,19 @@ static u16 hv_get_dev_type(const struct vmbus_channel 
*channel)
 }
 
 /**
- * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate 
message
+ * vmbus_prep_negotiate_resp() - Create default response for Negotiate message
  * @icmsghdrp: Pointer to msg header structure
- * @icmsg_negotiate: Pointer to negotiate message structure
  * @buf: Raw buffer channel data
+ * @fw_version: The framework versions we can support.
+ * @fw_vercnt: The size of @fw_version.
+ * @srv_version: The service versions we can support.
+ * @srv_vercnt: The size of @srv_version.
+ * @nego_fw_version: The selected framework version.
+ * @nego_srv_version: The selected service version.
  *
- * @icmsghdrp is of type  icmsg_hdr.
- * Set up and fill in default negotiate response message.
- *
- * The fw_version and fw_vercnt specifies the framework version that
- * we can support.
- *
- * The srv_version and srv_vercnt specifies the service
- * versions we can support.
- *
- * Versions are given in decreasing order.
- *
- * nego_fw_version and nego_srv_version store the selected protocol versions.
+ * Note: Versions are given in decreasing order.
  *
+ * Set up and fill in default negotiate response message.
  * Mainly used by Hyper-V drivers.
  */
 bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
-- 
2.18.0



[PATCH 1/4] Drivers: hv: vmbus: Fix the descriptions of some function parameters

2018-09-23 Thread kys
From: Dexuan Cui 

No functional change.

Added descriptions for some parameters.
Fixed some typos.
Removed some out-of-date comments.

Signed-off-by: Dexuan Cui 
Cc: Jonathan Corbet 
Cc: linux-...@vger.kernel.org
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/channel.c  | 24 +---
 drivers/hv/channel_mgmt.c | 23 +--
 2 files changed, 22 insertions(+), 25 deletions(-)

diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index 741857d80da1..ab92779271d0 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -709,15 +709,16 @@ EXPORT_SYMBOL_GPL(vmbus_close);
 
 /**
  * vmbus_sendpacket() - Send the specified buffer on the given channel
- * @channel: Pointer to vmbus_channel structure.
- * @buffer: Pointer to the buffer you want to receive the data into.
- * @bufferlen: Maximum size of what the the buffer will hold
+ * @channel: Pointer to vmbus_channel structure
+ * @buffer: Pointer to the buffer you want to send the data from.
+ * @bufferlen: Maximum size of what the buffer holds.
  * @requestid: Identifier of the request
- * @type: Type of packet that is being send e.g. negotiate, time
- * packet etc.
+ * @type: Type of packet that is being sent e.g. negotiate, time
+ *   packet etc.
+ * @flags: 0 or VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
  *
- * Sends data in @buffer directly to hyper-v via the vmbus
- * This will send the data unparsed to hyper-v.
+ * Sends data in @buffer directly to Hyper-V via the vmbus.
+ * This will send the data unparsed to Hyper-V.
  *
  * Mainly used by Hyper-V drivers.
  */
@@ -850,12 +851,13 @@ int vmbus_sendpacket_mpb_desc(struct vmbus_channel 
*channel,
 EXPORT_SYMBOL_GPL(vmbus_sendpacket_mpb_desc);
 
 /**
- * vmbus_recvpacket() - Retrieve the user packet on the specified channel
- * @channel: Pointer to vmbus_channel structure.
+ * __vmbus_recvpacket() - Retrieve the user packet on the specified channel
+ * @channel: Pointer to vmbus_channel structure
  * @buffer: Pointer to the buffer you want to receive the data into.
- * @bufferlen: Maximum size of what the the buffer will hold
- * @buffer_actual_len: The actual size of the data after it was received
+ * @bufferlen: Maximum size of what the buffer can hold.
+ * @buffer_actual_len: The actual size of the data after it was received.
  * @requestid: Identifier of the request
+ * @raw: true means keep the vmpacket_descriptor header in the received data.
  *
  * Receives directly from the hyper-v vmbus and puts the data it received
  * into Buffer. This will receive the data unparsed from hyper-v.
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 0f0e091c117c..e7598b569bea 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -198,24 +198,19 @@ static u16 hv_get_dev_type(const struct vmbus_channel 
*channel)
 }
 
 /**
- * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate 
message
+ * vmbus_prep_negotiate_resp() - Create default response for Negotiate message
  * @icmsghdrp: Pointer to msg header structure
- * @icmsg_negotiate: Pointer to negotiate message structure
  * @buf: Raw buffer channel data
+ * @fw_version: The framework versions we can support.
+ * @fw_vercnt: The size of @fw_version.
+ * @srv_version: The service versions we can support.
+ * @srv_vercnt: The size of @srv_version.
+ * @nego_fw_version: The selected framework version.
+ * @nego_srv_version: The selected service version.
  *
- * @icmsghdrp is of type  icmsg_hdr.
- * Set up and fill in default negotiate response message.
- *
- * The fw_version and fw_vercnt specifies the framework version that
- * we can support.
- *
- * The srv_version and srv_vercnt specifies the service
- * versions we can support.
- *
- * Versions are given in decreasing order.
- *
- * nego_fw_version and nego_srv_version store the selected protocol versions.
+ * Note: Versions are given in decreasing order.
  *
+ * Set up and fill in default negotiate response message.
  * Mainly used by Hyper-V drivers.
  */
 bool vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp,
-- 
2.18.0



[PATCH 4/4] Drivers: hv: vmbus: Use cpumask_var_t for on-stack cpu mask

2018-09-23 Thread kys
From: Dexuan Cui 

A cpumask structure on the stack can cause a warning with
CONFIG_NR_CPUS=8192 (e.g. Ubuntu 16.04 and 18.04 use this):

drivers/hv//channel_mgmt.c: In function ‘init_vp_index’:
drivers/hv//channel_mgmt.c:702:1: warning: the frame size of 1032 bytes
  is larger than 1024 bytes [-Wframe-larger-than=]

Nowadays it looks most distros enable CONFIG_CPUMASK_OFFSTACK=y, and
hence we can work around the warning by using cpumask_var_t.

Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Cc: 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/channel_mgmt.c | 14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index e7598b569bea..d943fa022e34 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -601,16 +601,18 @@ static void init_vp_index(struct vmbus_channel *channel, 
u16 dev_type)
bool perf_chn = vmbus_devs[dev_type].perf_device;
struct vmbus_channel *primary = channel->primary_channel;
int next_node;
-   struct cpumask available_mask;
+   cpumask_var_t available_mask;
struct cpumask *alloced_mask;
 
if ((vmbus_proto_version == VERSION_WS2008) ||
-   (vmbus_proto_version == VERSION_WIN7) || (!perf_chn)) {
+   (vmbus_proto_version == VERSION_WIN7) || (!perf_chn) ||
+   !alloc_cpumask_var(_mask, GFP_KERNEL)) {
/*
 * Prior to win8, all channel interrupts are
 * delivered on cpu 0.
 * Also if the channel is not a performance critical
 * channel, bind it to cpu 0.
+* In case alloc_cpumask_var() fails, bind it to cpu 0.
 */
channel->numa_node = 0;
channel->target_cpu = 0;
@@ -648,7 +650,7 @@ static void init_vp_index(struct vmbus_channel *channel, 
u16 dev_type)
cpumask_clear(alloced_mask);
}
 
-   cpumask_xor(_mask, alloced_mask,
+   cpumask_xor(available_mask, alloced_mask,
cpumask_of_node(primary->numa_node));
 
cur_cpu = -1;
@@ -666,10 +668,10 @@ static void init_vp_index(struct vmbus_channel *channel, 
u16 dev_type)
}
 
while (true) {
-   cur_cpu = cpumask_next(cur_cpu, _mask);
+   cur_cpu = cpumask_next(cur_cpu, available_mask);
if (cur_cpu >= nr_cpu_ids) {
cur_cpu = -1;
-   cpumask_copy(_mask,
+   cpumask_copy(available_mask,
 cpumask_of_node(primary->numa_node));
continue;
}
@@ -699,6 +701,8 @@ static void init_vp_index(struct vmbus_channel *channel, 
u16 dev_type)
 
channel->target_cpu = cur_cpu;
channel->target_vp = hv_cpu_number_to_vp_number(cur_cpu);
+
+   free_cpumask_var(available_mask);
 }
 
 static void vmbus_wait_for_unload(void)
-- 
2.18.0



[PATCH 4/4] Drivers: hv: vmbus: Use cpumask_var_t for on-stack cpu mask

2018-09-23 Thread kys
From: Dexuan Cui 

A cpumask structure on the stack can cause a warning with
CONFIG_NR_CPUS=8192 (e.g. Ubuntu 16.04 and 18.04 use this):

drivers/hv//channel_mgmt.c: In function ‘init_vp_index’:
drivers/hv//channel_mgmt.c:702:1: warning: the frame size of 1032 bytes
  is larger than 1024 bytes [-Wframe-larger-than=]

Nowadays it looks most distros enable CONFIG_CPUMASK_OFFSTACK=y, and
hence we can work around the warning by using cpumask_var_t.

Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Cc: 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/channel_mgmt.c | 14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index e7598b569bea..d943fa022e34 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -601,16 +601,18 @@ static void init_vp_index(struct vmbus_channel *channel, 
u16 dev_type)
bool perf_chn = vmbus_devs[dev_type].perf_device;
struct vmbus_channel *primary = channel->primary_channel;
int next_node;
-   struct cpumask available_mask;
+   cpumask_var_t available_mask;
struct cpumask *alloced_mask;
 
if ((vmbus_proto_version == VERSION_WS2008) ||
-   (vmbus_proto_version == VERSION_WIN7) || (!perf_chn)) {
+   (vmbus_proto_version == VERSION_WIN7) || (!perf_chn) ||
+   !alloc_cpumask_var(_mask, GFP_KERNEL)) {
/*
 * Prior to win8, all channel interrupts are
 * delivered on cpu 0.
 * Also if the channel is not a performance critical
 * channel, bind it to cpu 0.
+* In case alloc_cpumask_var() fails, bind it to cpu 0.
 */
channel->numa_node = 0;
channel->target_cpu = 0;
@@ -648,7 +650,7 @@ static void init_vp_index(struct vmbus_channel *channel, 
u16 dev_type)
cpumask_clear(alloced_mask);
}
 
-   cpumask_xor(_mask, alloced_mask,
+   cpumask_xor(available_mask, alloced_mask,
cpumask_of_node(primary->numa_node));
 
cur_cpu = -1;
@@ -666,10 +668,10 @@ static void init_vp_index(struct vmbus_channel *channel, 
u16 dev_type)
}
 
while (true) {
-   cur_cpu = cpumask_next(cur_cpu, _mask);
+   cur_cpu = cpumask_next(cur_cpu, available_mask);
if (cur_cpu >= nr_cpu_ids) {
cur_cpu = -1;
-   cpumask_copy(_mask,
+   cpumask_copy(available_mask,
 cpumask_of_node(primary->numa_node));
continue;
}
@@ -699,6 +701,8 @@ static void init_vp_index(struct vmbus_channel *channel, 
u16 dev_type)
 
channel->target_cpu = cur_cpu;
channel->target_vp = hv_cpu_number_to_vp_number(cur_cpu);
+
+   free_cpumask_var(available_mask);
 }
 
 static void vmbus_wait_for_unload(void)
-- 
2.18.0



[PATCH 2/4] Drivers: hv: kvp: Fix the indentation of some "break" statements

2018-09-23 Thread kys
From: Dexuan Cui 

No functional change.

Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_kvp.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 5eed1e7da15c..023bd185d21a 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -421,7 +421,7 @@ kvp_send_key(struct work_struct *dummy)
UTF16_LITTLE_ENDIAN,
message->body.kvp_set.data.value,
HV_KVP_EXCHANGE_MAX_VALUE_SIZE - 1) + 1;
-   break;
+   break;
 
case REG_U32:
/*
@@ -454,7 +454,7 @@ kvp_send_key(struct work_struct *dummy)
UTF16_LITTLE_ENDIAN,
message->body.kvp_set.data.key,
HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
-   break;
+   break;
 
case KVP_OP_DELETE:
message->body.kvp_delete.key_size =
@@ -464,12 +464,12 @@ kvp_send_key(struct work_struct *dummy)
UTF16_LITTLE_ENDIAN,
message->body.kvp_delete.key,
HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
-   break;
+   break;
 
case KVP_OP_ENUMERATE:
message->body.kvp_enum_data.index =
in_msg->body.kvp_enum_data.index;
-   break;
+   break;
}
 
kvp_transaction.state = HVUTIL_USERSPACE_REQ;
-- 
2.18.0



[PATCH 2/4] Drivers: hv: kvp: Fix the indentation of some "break" statements

2018-09-23 Thread kys
From: Dexuan Cui 

No functional change.

Signed-off-by: Dexuan Cui 
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv_kvp.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index 5eed1e7da15c..023bd185d21a 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -421,7 +421,7 @@ kvp_send_key(struct work_struct *dummy)
UTF16_LITTLE_ENDIAN,
message->body.kvp_set.data.value,
HV_KVP_EXCHANGE_MAX_VALUE_SIZE - 1) + 1;
-   break;
+   break;
 
case REG_U32:
/*
@@ -454,7 +454,7 @@ kvp_send_key(struct work_struct *dummy)
UTF16_LITTLE_ENDIAN,
message->body.kvp_set.data.key,
HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
-   break;
+   break;
 
case KVP_OP_DELETE:
message->body.kvp_delete.key_size =
@@ -464,12 +464,12 @@ kvp_send_key(struct work_struct *dummy)
UTF16_LITTLE_ENDIAN,
message->body.kvp_delete.key,
HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
-   break;
+   break;
 
case KVP_OP_ENUMERATE:
message->body.kvp_enum_data.index =
in_msg->body.kvp_enum_data.index;
-   break;
+   break;
}
 
kvp_transaction.state = HVUTIL_USERSPACE_REQ;
-- 
2.18.0



[PATCH 0/4] Drivers: hv: Miscellaneous fixes

2018-09-23 Thread kys
From: "K. Y. Srinivasan" 

Miscellaneous fixes.

Dexuan Cui (4):
  Drivers: hv: vmbus: Fix the descriptions of some function parameters
  Drivers: hv: kvp: Fix the indentation of some "break" statements
  Drivers: hv: kvp: Fix two "this statement may fall through" warnings
  Drivers: hv: vmbus: Use cpumask_var_t for on-stack cpu mask

 drivers/hv/channel.c  | 24 +---
 drivers/hv/channel_mgmt.c | 37 ++---
 drivers/hv/hv_kvp.c   | 14 --
 3 files changed, 39 insertions(+), 36 deletions(-)

-- 
2.18.0



[PATCH 0/4] Drivers: hv: Miscellaneous fixes

2018-09-23 Thread kys
From: "K. Y. Srinivasan" 

Miscellaneous fixes.

Dexuan Cui (4):
  Drivers: hv: vmbus: Fix the descriptions of some function parameters
  Drivers: hv: kvp: Fix the indentation of some "break" statements
  Drivers: hv: kvp: Fix two "this statement may fall through" warnings
  Drivers: hv: vmbus: Use cpumask_var_t for on-stack cpu mask

 drivers/hv/channel.c  | 24 +---
 drivers/hv/channel_mgmt.c | 37 ++---
 drivers/hv/hv_kvp.c   | 14 --
 3 files changed, 39 insertions(+), 36 deletions(-)

-- 
2.18.0



[PATCH 2/2] tools: hv: fcopy: set 'error' in case an unknown operation was requested

2018-09-16 Thread kys
From: Vitaly Kuznetsov 

'error' variable is left uninitialized in case we see an unknown operation.
As we don't immediately return and proceed to pwrite() we need to set it
to something, HV_E_FAIL sounds good enough.

Signed-off-by: Vitaly Kuznetsov 
Signed-off-by: K. Y. Srinivasan 
---
 tools/hv/hv_fcopy_daemon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c
index d78aed86af09..8ff8cb1a11f4 100644
--- a/tools/hv/hv_fcopy_daemon.c
+++ b/tools/hv/hv_fcopy_daemon.c
@@ -234,6 +234,7 @@ int main(int argc, char *argv[])
break;
 
default:
+   error = HV_E_FAIL;
syslog(LOG_ERR, "Unknown operation: %d",
buffer.hdr.operation);
 
-- 
2.18.0



[PATCH 1/2] Drivers: hv: vmbus: Use get/put_cpu() in vmbus_connect()

2018-09-16 Thread kys
From: Dexuan Cui 

With CONFIG_DEBUG_PREEMPT=y, I always see this warning:
BUG: using smp_processor_id() in preemptible []

Fix the false warning by using get/put_cpu().

Here vmbus_connect() sends a message to the host and waits for the
host's response. The host will deliver the response message and an
interrupt on CPU msg->target_vcpu, and later the interrupt handler
will wake up vmbus_connect(). vmbus_connect() doesn't really have
to run on the same cpu as CPU msg->target_vcpu, so it's safe to
call put_cpu() just here.

Signed-off-by: Dexuan Cui 
Cc: sta...@vger.kernel.org
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/connection.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index ced041899456..f4d08c8ac7f8 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -76,6 +76,7 @@ static int vmbus_negotiate_version(struct 
vmbus_channel_msginfo *msginfo,
__u32 version)
 {
int ret = 0;
+   unsigned int cur_cpu;
struct vmbus_channel_initiate_contact *msg;
unsigned long flags;
 
@@ -118,9 +119,10 @@ static int vmbus_negotiate_version(struct 
vmbus_channel_msginfo *msginfo,
 * the CPU attempting to connect may not be CPU 0.
 */
if (version >= VERSION_WIN8_1) {
-   msg->target_vcpu =
-   hv_cpu_number_to_vp_number(smp_processor_id());
-   vmbus_connection.connect_cpu = smp_processor_id();
+   cur_cpu = get_cpu();
+   msg->target_vcpu = hv_cpu_number_to_vp_number(cur_cpu);
+   vmbus_connection.connect_cpu = cur_cpu;
+   put_cpu();
} else {
msg->target_vcpu = 0;
vmbus_connection.connect_cpu = 0;
-- 
2.18.0



[PATCH 2/2] tools: hv: fcopy: set 'error' in case an unknown operation was requested

2018-09-16 Thread kys
From: Vitaly Kuznetsov 

'error' variable is left uninitialized in case we see an unknown operation.
As we don't immediately return and proceed to pwrite() we need to set it
to something, HV_E_FAIL sounds good enough.

Signed-off-by: Vitaly Kuznetsov 
Signed-off-by: K. Y. Srinivasan 
---
 tools/hv/hv_fcopy_daemon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c
index d78aed86af09..8ff8cb1a11f4 100644
--- a/tools/hv/hv_fcopy_daemon.c
+++ b/tools/hv/hv_fcopy_daemon.c
@@ -234,6 +234,7 @@ int main(int argc, char *argv[])
break;
 
default:
+   error = HV_E_FAIL;
syslog(LOG_ERR, "Unknown operation: %d",
buffer.hdr.operation);
 
-- 
2.18.0



[PATCH 1/2] Drivers: hv: vmbus: Use get/put_cpu() in vmbus_connect()

2018-09-16 Thread kys
From: Dexuan Cui 

With CONFIG_DEBUG_PREEMPT=y, I always see this warning:
BUG: using smp_processor_id() in preemptible []

Fix the false warning by using get/put_cpu().

Here vmbus_connect() sends a message to the host and waits for the
host's response. The host will deliver the response message and an
interrupt on CPU msg->target_vcpu, and later the interrupt handler
will wake up vmbus_connect(). vmbus_connect() doesn't really have
to run on the same cpu as CPU msg->target_vcpu, so it's safe to
call put_cpu() just here.

Signed-off-by: Dexuan Cui 
Cc: sta...@vger.kernel.org
Cc: K. Y. Srinivasan 
Cc: Haiyang Zhang 
Cc: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/connection.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index ced041899456..f4d08c8ac7f8 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -76,6 +76,7 @@ static int vmbus_negotiate_version(struct 
vmbus_channel_msginfo *msginfo,
__u32 version)
 {
int ret = 0;
+   unsigned int cur_cpu;
struct vmbus_channel_initiate_contact *msg;
unsigned long flags;
 
@@ -118,9 +119,10 @@ static int vmbus_negotiate_version(struct 
vmbus_channel_msginfo *msginfo,
 * the CPU attempting to connect may not be CPU 0.
 */
if (version >= VERSION_WIN8_1) {
-   msg->target_vcpu =
-   hv_cpu_number_to_vp_number(smp_processor_id());
-   vmbus_connection.connect_cpu = smp_processor_id();
+   cur_cpu = get_cpu();
+   msg->target_vcpu = hv_cpu_number_to_vp_number(cur_cpu);
+   vmbus_connection.connect_cpu = cur_cpu;
+   put_cpu();
} else {
msg->target_vcpu = 0;
vmbus_connection.connect_cpu = 0;
-- 
2.18.0



[PATCH 0/2] Drivers: hv: Miscellaneous fixes

2018-09-16 Thread kys
From: "K. Y. Srinivasan" 

Some miscellaneous fixes.

Dexuan Cui (1):
  Drivers: hv: vmbus: Use get/put_cpu() in vmbus_connect()

Vitaly Kuznetsov (1):
  tools: hv: fcopy: set 'error' in case an unknown operation was
requested

 drivers/hv/connection.c| 8 +---
 tools/hv/hv_fcopy_daemon.c | 1 +
 2 files changed, 6 insertions(+), 3 deletions(-)

-- 
2.18.0



[PATCH 0/2] Drivers: hv: Miscellaneous fixes

2018-09-16 Thread kys
From: "K. Y. Srinivasan" 

Some miscellaneous fixes.

Dexuan Cui (1):
  Drivers: hv: vmbus: Use get/put_cpu() in vmbus_connect()

Vitaly Kuznetsov (1):
  tools: hv: fcopy: set 'error' in case an unknown operation was
requested

 drivers/hv/connection.c| 8 +---
 tools/hv/hv_fcopy_daemon.c | 1 +
 2 files changed, 6 insertions(+), 3 deletions(-)

-- 
2.18.0



[PATCH] vmbus: don't return values for uninitalized channels

2018-08-20 Thread kys
From: Stephen Hemminger 

For unsupported device types, the vmbus channel ringbuffer is never
initialized, and therefore reading the sysfs files will return garbage
or cause a kernel OOPS.

Fixes: c2e5df616e1a ("vmbus: add per-channel sysfs info")

Signed-off-by: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
Cc:  # 4.15
---
 drivers/hv/vmbus_drv.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index e6d8fdac6d8b..4bbc420d1213 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1368,6 +1368,9 @@ static ssize_t vmbus_chan_attr_show(struct kobject *kobj,
if (!attribute->show)
return -EIO;
 
+   if (chan->state != CHANNEL_OPENED_STATE)
+   return -EINVAL;
+
return attribute->show(chan, buf);
 }
 
-- 
2.18.0



[PATCH] vmbus: don't return values for uninitalized channels

2018-08-20 Thread kys
From: Stephen Hemminger 

For unsupported device types, the vmbus channel ringbuffer is never
initialized, and therefore reading the sysfs files will return garbage
or cause a kernel OOPS.

Fixes: c2e5df616e1a ("vmbus: add per-channel sysfs info")

Signed-off-by: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
Cc:  # 4.15
---
 drivers/hv/vmbus_drv.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index e6d8fdac6d8b..4bbc420d1213 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1368,6 +1368,9 @@ static ssize_t vmbus_chan_attr_show(struct kobject *kobj,
if (!attribute->show)
return -EIO;
 
+   if (chan->state != CHANNEL_OPENED_STATE)
+   return -EINVAL;
+
return attribute->show(chan, buf);
 }
 
-- 
2.18.0



[PATCH 2/5] vmbus: add driver_override support

2018-08-10 Thread kys
From: Stephen Hemminger 

Add support for overriding the default driver for a VMBus device
in the same way that it can be done for PCI devices. This patch
adds the /sys/bus/vmbus/devices/.../driver_override file
and the logic for matching.

This is used by driverctl tool to do driver override.
https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitlab.com%2Fdriverctl%2Fdriverctldata=02%7C01%7Ckys%40microsoft.com%7C42e803feb2c544ef6ea908d5fd538878%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636693457619960040sdata=kEyYHRIjNZCk%2B37moCSqbrZL426YccNQrsWpENcrZdw%3Dreserved=0

Signed-off-by: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 Documentation/ABI/testing/sysfs-bus-vmbus |  21 
 drivers/hv/vmbus_drv.c| 115 ++
 include/linux/hyperv.h|   1 +
 3 files changed, 118 insertions(+), 19 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-vmbus

diff --git a/Documentation/ABI/testing/sysfs-bus-vmbus 
b/Documentation/ABI/testing/sysfs-bus-vmbus
new file mode 100644
index ..91e6c065973c
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-vmbus
@@ -0,0 +1,21 @@
+What:  /sys/bus/vmbus/devices/.../driver_override
+Date:  August 2019
+Contact:   Stephen Hemminger 
+Description:
+   This file allows the driver for a device to be specified which
+   will override standard static and dynamic ID matching.  When
+   specified, only a driver with a name matching the value written
+   to driver_override will have an opportunity to bind to the
+   device.  The override is specified by writing a string to the
+   driver_override file (echo uio_hv_generic > driver_override) and
+   may be cleared with an empty string (echo > driver_override).
+   This returns the device to standard matching rules binding.
+   Writing to driver_override does not automatically unbind the
+   device from its current driver or make any attempt to
+   automatically load the specified driver.  If no driver with a
+   matching name is currently loaded in the kernel, the device
+   will not bind to any driver.  This also allows devices to
+   opt-out of driver binding using a driver_override name such as
+   "none".  Only a single driver may be specified in the override,
+   there is no support for parsing delimiters.
+
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index b1b548a21f91..e6d8fdac6d8b 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -498,6 +498,54 @@ static ssize_t device_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(device);
 
+static ssize_t driver_override_store(struct device *dev,
+struct device_attribute *attr,
+const char *buf, size_t count)
+{
+   struct hv_device *hv_dev = device_to_hv_device(dev);
+   char *driver_override, *old, *cp;
+
+   /* We need to keep extra room for a newline */
+   if (count >= (PAGE_SIZE - 1))
+   return -EINVAL;
+
+   driver_override = kstrndup(buf, count, GFP_KERNEL);
+   if (!driver_override)
+   return -ENOMEM;
+
+   cp = strchr(driver_override, '\n');
+   if (cp)
+   *cp = '\0';
+
+   device_lock(dev);
+   old = hv_dev->driver_override;
+   if (strlen(driver_override)) {
+   hv_dev->driver_override = driver_override;
+   } else {
+   kfree(driver_override);
+   hv_dev->driver_override = NULL;
+   }
+   device_unlock(dev);
+
+   kfree(old);
+
+   return count;
+}
+
+static ssize_t driver_override_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct hv_device *hv_dev = device_to_hv_device(dev);
+   ssize_t len;
+
+   device_lock(dev);
+   len = snprintf(buf, PAGE_SIZE, "%s\n", hv_dev->driver_override);
+   device_unlock(dev);
+
+   return len;
+}
+static DEVICE_ATTR_RW(driver_override);
+
 /* Set up per device attributes in /sys/bus/vmbus/devices/ */
 static struct attribute *vmbus_dev_attrs[] = {
_attr_id.attr,
@@ -528,6 +576,7 @@ static struct attribute *vmbus_dev_attrs[] = {
_attr_channel_vp_mapping.attr,
_attr_vendor.attr,
_attr_device.attr,
+   _attr_driver_override.attr,
NULL,
 };
 ATTRIBUTE_GROUPS(vmbus_dev);
@@ -563,17 +612,26 @@ static inline bool is_null_guid(const uuid_le *guid)
return true;
 }
 
-/*
- * Return a matching hv_vmbus_device_id pointer.
- * If there is no match, return NULL.
- */
-static const struct hv_vmbus_device_id *hv_vmbus_get_id(struct hv_driver *drv,
-   const uuid_le *guid)
+static const struct hv_vmbus_device_id *

[PATCH 2/5] vmbus: add driver_override support

2018-08-10 Thread kys
From: Stephen Hemminger 

Add support for overriding the default driver for a VMBus device
in the same way that it can be done for PCI devices. This patch
adds the /sys/bus/vmbus/devices/.../driver_override file
and the logic for matching.

This is used by driverctl tool to do driver override.
https://na01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitlab.com%2Fdriverctl%2Fdriverctldata=02%7C01%7Ckys%40microsoft.com%7C42e803feb2c544ef6ea908d5fd538878%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C636693457619960040sdata=kEyYHRIjNZCk%2B37moCSqbrZL426YccNQrsWpENcrZdw%3Dreserved=0

Signed-off-by: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 Documentation/ABI/testing/sysfs-bus-vmbus |  21 
 drivers/hv/vmbus_drv.c| 115 ++
 include/linux/hyperv.h|   1 +
 3 files changed, 118 insertions(+), 19 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-vmbus

diff --git a/Documentation/ABI/testing/sysfs-bus-vmbus 
b/Documentation/ABI/testing/sysfs-bus-vmbus
new file mode 100644
index ..91e6c065973c
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-vmbus
@@ -0,0 +1,21 @@
+What:  /sys/bus/vmbus/devices/.../driver_override
+Date:  August 2019
+Contact:   Stephen Hemminger 
+Description:
+   This file allows the driver for a device to be specified which
+   will override standard static and dynamic ID matching.  When
+   specified, only a driver with a name matching the value written
+   to driver_override will have an opportunity to bind to the
+   device.  The override is specified by writing a string to the
+   driver_override file (echo uio_hv_generic > driver_override) and
+   may be cleared with an empty string (echo > driver_override).
+   This returns the device to standard matching rules binding.
+   Writing to driver_override does not automatically unbind the
+   device from its current driver or make any attempt to
+   automatically load the specified driver.  If no driver with a
+   matching name is currently loaded in the kernel, the device
+   will not bind to any driver.  This also allows devices to
+   opt-out of driver binding using a driver_override name such as
+   "none".  Only a single driver may be specified in the override,
+   there is no support for parsing delimiters.
+
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index b1b548a21f91..e6d8fdac6d8b 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -498,6 +498,54 @@ static ssize_t device_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(device);
 
+static ssize_t driver_override_store(struct device *dev,
+struct device_attribute *attr,
+const char *buf, size_t count)
+{
+   struct hv_device *hv_dev = device_to_hv_device(dev);
+   char *driver_override, *old, *cp;
+
+   /* We need to keep extra room for a newline */
+   if (count >= (PAGE_SIZE - 1))
+   return -EINVAL;
+
+   driver_override = kstrndup(buf, count, GFP_KERNEL);
+   if (!driver_override)
+   return -ENOMEM;
+
+   cp = strchr(driver_override, '\n');
+   if (cp)
+   *cp = '\0';
+
+   device_lock(dev);
+   old = hv_dev->driver_override;
+   if (strlen(driver_override)) {
+   hv_dev->driver_override = driver_override;
+   } else {
+   kfree(driver_override);
+   hv_dev->driver_override = NULL;
+   }
+   device_unlock(dev);
+
+   kfree(old);
+
+   return count;
+}
+
+static ssize_t driver_override_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct hv_device *hv_dev = device_to_hv_device(dev);
+   ssize_t len;
+
+   device_lock(dev);
+   len = snprintf(buf, PAGE_SIZE, "%s\n", hv_dev->driver_override);
+   device_unlock(dev);
+
+   return len;
+}
+static DEVICE_ATTR_RW(driver_override);
+
 /* Set up per device attributes in /sys/bus/vmbus/devices/ */
 static struct attribute *vmbus_dev_attrs[] = {
_attr_id.attr,
@@ -528,6 +576,7 @@ static struct attribute *vmbus_dev_attrs[] = {
_attr_channel_vp_mapping.attr,
_attr_vendor.attr,
_attr_device.attr,
+   _attr_driver_override.attr,
NULL,
 };
 ATTRIBUTE_GROUPS(vmbus_dev);
@@ -563,17 +612,26 @@ static inline bool is_null_guid(const uuid_le *guid)
return true;
 }
 
-/*
- * Return a matching hv_vmbus_device_id pointer.
- * If there is no match, return NULL.
- */
-static const struct hv_vmbus_device_id *hv_vmbus_get_id(struct hv_driver *drv,
-   const uuid_le *guid)
+static const struct hv_vmbus_device_id *

[PATCH 1/5] Tools: hv: Fix a bug in the key delete code

2018-08-10 Thread kys
From: "K. Y. Srinivasan" 

Fix a bug in the key delete code - the num_records range
from 0 to num_records-1.

Signed-off-by: K. Y. Srinivasan 
Reported-by: David Binderman 
Cc: 
---
 tools/hv/hv_kvp_daemon.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index dbf6e8bd98ba..bbb2a8ef367c 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -286,7 +286,7 @@ static int kvp_key_delete(int pool, const __u8 *key, int 
key_size)
 * Found a match; just move the remaining
 * entries up.
 */
-   if (i == num_records) {
+   if (i == (num_records - 1)) {
kvp_file_info[pool].num_records--;
kvp_update_file(pool);
return 0;
-- 
2.18.0



[PATCH 4/5] uio_hv_generic: drop #ifdef DEBUG

2018-08-10 Thread kys
From: Stephen Hemminger 

DEBUG is leftover from the development phase, remove it.

Signed-off-by: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/uio/uio_hv_generic.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c
index 35678d08d9d8..ab0c0e7e8a44 100644
--- a/drivers/uio/uio_hv_generic.c
+++ b/drivers/uio/uio_hv_generic.c
@@ -19,7 +19,6 @@
  * # echo -n "ed963694-e847-4b2a-85af-bc9cfc11d6f3" \
  *> /sys/bus/vmbus/drivers/uio_hv_generic/bind
  */
-#define DEBUG 1
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include 
-- 
2.18.0



[PATCH 3/5] uio_hv_generic: increase size of receive and send buffers

2018-08-10 Thread kys
From: Stephen Hemminger 

When using DPDK there is significant performance boost by using
the largest possible send and receive buffer area.

Unfortunately, with UIO model there is not a good way to configure
this at run time. But it is okay to have a bigger buffer available
even if application only decides to use a smaller piece of it.

Signed-off-by: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/uio/uio_hv_generic.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c
index c690d100adcd..35678d08d9d8 100644
--- a/drivers/uio/uio_hv_generic.c
+++ b/drivers/uio/uio_hv_generic.c
@@ -35,13 +35,13 @@
 
 #include "../hv/hyperv_vmbus.h"
 
-#define DRIVER_VERSION "0.02.0"
+#define DRIVER_VERSION "0.02.1"
 #define DRIVER_AUTHOR  "Stephen Hemminger "
 #define DRIVER_DESC"Generic UIO driver for VMBus devices"
 
 #define HV_RING_SIZE512/* pages */
-#define SEND_BUFFER_SIZE (15 * 1024 * 1024)
-#define RECV_BUFFER_SIZE (15 * 1024 * 1024)
+#define SEND_BUFFER_SIZE (16 * 1024 * 1024)
+#define RECV_BUFFER_SIZE (31 * 1024 * 1024)
 
 /*
  * List of resources to be mapped to user space
-- 
2.18.0



[PATCH 1/5] Tools: hv: Fix a bug in the key delete code

2018-08-10 Thread kys
From: "K. Y. Srinivasan" 

Fix a bug in the key delete code - the num_records range
from 0 to num_records-1.

Signed-off-by: K. Y. Srinivasan 
Reported-by: David Binderman 
Cc: 
---
 tools/hv/hv_kvp_daemon.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index dbf6e8bd98ba..bbb2a8ef367c 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -286,7 +286,7 @@ static int kvp_key_delete(int pool, const __u8 *key, int 
key_size)
 * Found a match; just move the remaining
 * entries up.
 */
-   if (i == num_records) {
+   if (i == (num_records - 1)) {
kvp_file_info[pool].num_records--;
kvp_update_file(pool);
return 0;
-- 
2.18.0



[PATCH 4/5] uio_hv_generic: drop #ifdef DEBUG

2018-08-10 Thread kys
From: Stephen Hemminger 

DEBUG is leftover from the development phase, remove it.

Signed-off-by: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/uio/uio_hv_generic.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c
index 35678d08d9d8..ab0c0e7e8a44 100644
--- a/drivers/uio/uio_hv_generic.c
+++ b/drivers/uio/uio_hv_generic.c
@@ -19,7 +19,6 @@
  * # echo -n "ed963694-e847-4b2a-85af-bc9cfc11d6f3" \
  *> /sys/bus/vmbus/drivers/uio_hv_generic/bind
  */
-#define DEBUG 1
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include 
-- 
2.18.0



[PATCH 3/5] uio_hv_generic: increase size of receive and send buffers

2018-08-10 Thread kys
From: Stephen Hemminger 

When using DPDK there is significant performance boost by using
the largest possible send and receive buffer area.

Unfortunately, with UIO model there is not a good way to configure
this at run time. But it is okay to have a bigger buffer available
even if application only decides to use a smaller piece of it.

Signed-off-by: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/uio/uio_hv_generic.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c
index c690d100adcd..35678d08d9d8 100644
--- a/drivers/uio/uio_hv_generic.c
+++ b/drivers/uio/uio_hv_generic.c
@@ -35,13 +35,13 @@
 
 #include "../hv/hyperv_vmbus.h"
 
-#define DRIVER_VERSION "0.02.0"
+#define DRIVER_VERSION "0.02.1"
 #define DRIVER_AUTHOR  "Stephen Hemminger "
 #define DRIVER_DESC"Generic UIO driver for VMBus devices"
 
 #define HV_RING_SIZE512/* pages */
-#define SEND_BUFFER_SIZE (15 * 1024 * 1024)
-#define RECV_BUFFER_SIZE (15 * 1024 * 1024)
+#define SEND_BUFFER_SIZE (16 * 1024 * 1024)
+#define RECV_BUFFER_SIZE (31 * 1024 * 1024)
 
 /*
  * List of resources to be mapped to user space
-- 
2.18.0



[PATCH 5/5] Drivers: hv: vmbus: Fix synic per-cpu context initialization

2018-08-10 Thread kys
From: Michael Kelley 

If hv_synic_alloc() errors out, the state of the per-cpu context
for some CPUs is unknown since the zero'ing is done as each
CPU is iterated over.  In such case, hv_synic_cleanup() may try to
free memory based on uninitialized values.  Fix this by zero'ing
the per-cpu context for all CPUs before doing any memory
allocations that might fail.

Signed-off-by: Michael Kelley 
Reported-by: Dan Carpenter 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 748a1c4172a6..332d7c34be5c 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -189,6 +189,17 @@ static void hv_init_clockevent_device(struct 
clock_event_device *dev, int cpu)
 int hv_synic_alloc(void)
 {
int cpu;
+   struct hv_per_cpu_context *hv_cpu;
+
+   /*
+* First, zero all per-cpu memory areas so hv_synic_free() can
+* detect what memory has been allocated and cleanup properly
+* after any failures.
+*/
+   for_each_present_cpu(cpu) {
+   hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu);
+   memset(hv_cpu, 0, sizeof(*hv_cpu));
+   }
 
hv_context.hv_numa_map = kcalloc(nr_node_ids, sizeof(struct cpumask),
 GFP_KERNEL);
@@ -198,10 +209,8 @@ int hv_synic_alloc(void)
}
 
for_each_present_cpu(cpu) {
-   struct hv_per_cpu_context *hv_cpu
-   = per_cpu_ptr(hv_context.cpu_context, cpu);
+   hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu);
 
-   memset(hv_cpu, 0, sizeof(*hv_cpu));
tasklet_init(_cpu->msg_dpc,
 vmbus_on_msg_dpc, (unsigned long) hv_cpu);
 
-- 
2.18.0



[PATCH 5/5] Drivers: hv: vmbus: Fix synic per-cpu context initialization

2018-08-10 Thread kys
From: Michael Kelley 

If hv_synic_alloc() errors out, the state of the per-cpu context
for some CPUs is unknown since the zero'ing is done as each
CPU is iterated over.  In such case, hv_synic_cleanup() may try to
free memory based on uninitialized values.  Fix this by zero'ing
the per-cpu context for all CPUs before doing any memory
allocations that might fail.

Signed-off-by: Michael Kelley 
Reported-by: Dan Carpenter 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 748a1c4172a6..332d7c34be5c 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -189,6 +189,17 @@ static void hv_init_clockevent_device(struct 
clock_event_device *dev, int cpu)
 int hv_synic_alloc(void)
 {
int cpu;
+   struct hv_per_cpu_context *hv_cpu;
+
+   /*
+* First, zero all per-cpu memory areas so hv_synic_free() can
+* detect what memory has been allocated and cleanup properly
+* after any failures.
+*/
+   for_each_present_cpu(cpu) {
+   hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu);
+   memset(hv_cpu, 0, sizeof(*hv_cpu));
+   }
 
hv_context.hv_numa_map = kcalloc(nr_node_ids, sizeof(struct cpumask),
 GFP_KERNEL);
@@ -198,10 +209,8 @@ int hv_synic_alloc(void)
}
 
for_each_present_cpu(cpu) {
-   struct hv_per_cpu_context *hv_cpu
-   = per_cpu_ptr(hv_context.cpu_context, cpu);
+   hv_cpu = per_cpu_ptr(hv_context.cpu_context, cpu);
 
-   memset(hv_cpu, 0, sizeof(*hv_cpu));
tasklet_init(_cpu->msg_dpc,
 vmbus_on_msg_dpc, (unsigned long) hv_cpu);
 
-- 
2.18.0



[PATCH 0/5] Miscellaneous fixes/enhancements

2018-08-10 Thread kys
From: "K. Y. Srinivasan" 

Miscellaneous fixes/enhancements.

K. Y. Srinivasan (1):
  Tools: hv: Fix a bug in the key delete code

Michael Kelley (1):
  Drivers: hv: vmbus: Fix synic per-cpu context initialization

Stephen Hemminger (3):
  vmbus: add driver_override support
  uio_hv_generic: increase size of receive and send buffers
  uio_hv_generic: drop #ifdef DEBUG

 Documentation/ABI/testing/sysfs-bus-vmbus |  21 
 drivers/hv/hv.c   |  15 ++-
 drivers/hv/vmbus_drv.c| 115 ++
 drivers/uio/uio_hv_generic.c  |   7 +-
 include/linux/hyperv.h|   1 +
 tools/hv/hv_kvp_daemon.c  |   2 +-
 6 files changed, 134 insertions(+), 27 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-vmbus

-- 
2.18.0



[PATCH 0/5] Miscellaneous fixes/enhancements

2018-08-10 Thread kys
From: "K. Y. Srinivasan" 

Miscellaneous fixes/enhancements.

K. Y. Srinivasan (1):
  Tools: hv: Fix a bug in the key delete code

Michael Kelley (1):
  Drivers: hv: vmbus: Fix synic per-cpu context initialization

Stephen Hemminger (3):
  vmbus: add driver_override support
  uio_hv_generic: increase size of receive and send buffers
  uio_hv_generic: drop #ifdef DEBUG

 Documentation/ABI/testing/sysfs-bus-vmbus |  21 
 drivers/hv/hv.c   |  15 ++-
 drivers/hv/vmbus_drv.c| 115 ++
 drivers/uio/uio_hv_generic.c  |   7 +-
 include/linux/hyperv.h|   1 +
 tools/hv/hv_kvp_daemon.c  |   2 +-
 6 files changed, 134 insertions(+), 27 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-vmbus

-- 
2.18.0



[PATCH 1/3] Drivers: hv: vmbus: Reset the channel callback in vmbus_onoffer_rescind()

2018-08-01 Thread kys
From: Dexuan Cui 

Before setting channel->rescind in vmbus_rescind_cleanup(), we should make
sure the channel callback won't run any more, otherwise a high-level
driver like pci_hyperv, which may be infinitely waiting for the host VSP's
response and notices the channel has been rescinded, can't safely give
up: e.g., in hv_pci_protocol_negotiation() -> wait_for_response(), it's
unsafe to exit from wait_for_response() and proceed with the on-stack
variable "comp_pkt" popped. The issue was originally spotted by
Michael Kelley .

In vmbus_close_internal(), the patch also minimizes the range protected by
disabling/enabling channel->callback_event: we don't really need that for
the whole function.

Signed-off-by: Dexuan Cui 
Reviewed-by: Michael Kelley 
Cc: sta...@vger.kernel.org
Cc: K. Y. Srinivasan 
Cc: Stephen Hemminger 
Cc: Michael Kelley 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/channel.c  | 40 +++
 drivers/hv/channel_mgmt.c |  6 ++
 include/linux/hyperv.h|  2 ++
 3 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index ba0a092ae085..c3949220b770 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -558,11 +558,8 @@ static void reset_channel_cb(void *arg)
channel->onchannel_callback = NULL;
 }
 
-static int vmbus_close_internal(struct vmbus_channel *channel)
+void vmbus_reset_channel_cb(struct vmbus_channel *channel)
 {
-   struct vmbus_channel_close_channel *msg;
-   int ret;
-
/*
 * vmbus_on_event(), running in the per-channel tasklet, can race
 * with vmbus_close_internal() in the case of SMP guest, e.g., when
@@ -572,6 +569,29 @@ static int vmbus_close_internal(struct vmbus_channel 
*channel)
 */
tasklet_disable(>callback_event);
 
+   channel->sc_creation_callback = NULL;
+
+   /* Stop the callback asap */
+   if (channel->target_cpu != get_cpu()) {
+   put_cpu();
+   smp_call_function_single(channel->target_cpu, reset_channel_cb,
+channel, true);
+   } else {
+   reset_channel_cb(channel);
+   put_cpu();
+   }
+
+   /* Re-enable tasklet for use on re-open */
+   tasklet_enable(>callback_event);
+}
+
+static int vmbus_close_internal(struct vmbus_channel *channel)
+{
+   struct vmbus_channel_close_channel *msg;
+   int ret;
+
+   vmbus_reset_channel_cb(channel);
+
/*
 * In case a device driver's probe() fails (e.g.,
 * util_probe() -> vmbus_open() returns -ENOMEM) and the device is
@@ -585,16 +605,6 @@ static int vmbus_close_internal(struct vmbus_channel 
*channel)
}
 
channel->state = CHANNEL_OPEN_STATE;
-   channel->sc_creation_callback = NULL;
-   /* Stop callback and cancel the timer asap */
-   if (channel->target_cpu != get_cpu()) {
-   put_cpu();
-   smp_call_function_single(channel->target_cpu, reset_channel_cb,
-channel, true);
-   } else {
-   reset_channel_cb(channel);
-   put_cpu();
-   }
 
/* Send a closing message */
 
@@ -639,8 +649,6 @@ static int vmbus_close_internal(struct vmbus_channel 
*channel)
get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
 
 out:
-   /* re-enable tasklet for use on re-open */
-   tasklet_enable(>callback_event);
return ret;
 }
 
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index f3b551a50653..0f0e091c117c 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -892,6 +892,12 @@ static void vmbus_onoffer_rescind(struct 
vmbus_channel_message_header *hdr)
return;
}
 
+   /*
+* Before setting channel->rescind in vmbus_rescind_cleanup(), we
+* should make sure the channel callback is not running any more.
+*/
+   vmbus_reset_channel_cb(channel);
+
/*
 * Now wait for offer handling to complete.
 */
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 2330f08062c7..efda23cf32c7 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1061,6 +1061,8 @@ extern int vmbus_establish_gpadl(struct vmbus_channel 
*channel,
 extern int vmbus_teardown_gpadl(struct vmbus_channel *channel,
 u32 gpadl_handle);
 
+void vmbus_reset_channel_cb(struct vmbus_channel *channel);
+
 extern int vmbus_recvpacket(struct vmbus_channel *channel,
  void *buffer,
  u32 bufferlen,
-- 
2.17.1



[PATCH 3/3] Drivers: hv: vmbus: Cleanup synic memory free path

2018-08-01 Thread kys
From: Michael Kelley 

clk_evt memory is not being freed when the synic is shutdown
or when there is an allocation error.  Add the appropriate
kfree() call, along with a comment to clarify how the memory
gets freed after an allocation error.  Make the free path
consistent by removing checks for NULL since kfree() and
free_page() already do the check.

Signed-off-by: Michael Kelley 
Reported-by: Dan Carpenter 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 312fe5ed7c40..748a1c4172a6 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -242,6 +242,10 @@ int hv_synic_alloc(void)
 
return 0;
 err:
+   /*
+* Any memory allocations that succeeded will be freed when
+* the caller cleans up by calling hv_synic_free()
+*/
return -ENOMEM;
 }
 
@@ -254,12 +258,10 @@ void hv_synic_free(void)
struct hv_per_cpu_context *hv_cpu
= per_cpu_ptr(hv_context.cpu_context, cpu);
 
-   if (hv_cpu->synic_event_page)
-   free_page((unsigned long)hv_cpu->synic_event_page);
-   if (hv_cpu->synic_message_page)
-   free_page((unsigned long)hv_cpu->synic_message_page);
-   if (hv_cpu->post_msg_page)
-   free_page((unsigned long)hv_cpu->post_msg_page);
+   kfree(hv_cpu->clk_evt);
+   free_page((unsigned long)hv_cpu->synic_event_page);
+   free_page((unsigned long)hv_cpu->synic_message_page);
+   free_page((unsigned long)hv_cpu->post_msg_page);
}
 
kfree(hv_context.hv_numa_map);
-- 
2.17.1



[PATCH 2/3] Drivers: hv: vmbus: Remove use of slow_virt_to_phys()

2018-08-01 Thread kys
From: Michael Kelley 

slow_virt_to_phys() is only implemented for arch/x86.
Remove its use in arch independent Hyper-V drivers, and
replace with test for vmalloc() address followed by
appropriate v-to-p function. This follows the typical
pattern of other drivers and avoids the need to implement
slow_virt_to_phys() for Hyper-V on ARM64.

Signed-off-by: Michael Kelley 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/channel.c | 27 ---
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index c3949220b770..741857d80da1 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -29,12 +29,26 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "hyperv_vmbus.h"
 
 #define NUM_PAGES_SPANNED(addr, len) \
 ((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))
 
+static unsigned long virt_to_hvpfn(void *addr)
+{
+   unsigned long paddr;
+
+   if (is_vmalloc_addr(addr))
+   paddr = page_to_phys(vmalloc_to_page(addr)) +
+offset_in_page(addr);
+   else
+   paddr = __pa(addr);
+
+   return  paddr >> PAGE_SHIFT;
+}
+
 /*
  * vmbus_setevent- Trigger an event notification on the specified
  * channel.
@@ -298,8 +312,8 @@ static int create_gpadl_header(void *kbuffer, u32 size,
gpadl_header->range[0].byte_offset = 0;
gpadl_header->range[0].byte_count = size;
for (i = 0; i < pfncount; i++)
-   gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys(
-   kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;
+   gpadl_header->range[0].pfn_array[i] = virt_to_hvpfn(
+   kbuffer + PAGE_SIZE * i);
*msginfo = msgheader;
 
pfnsum = pfncount;
@@ -350,9 +364,8 @@ static int create_gpadl_header(void *kbuffer, u32 size,
 * so the hypervisor guarantees that this is ok.
 */
for (i = 0; i < pfncurr; i++)
-   gpadl_body->pfn[i] = slow_virt_to_phys(
-   kbuffer + PAGE_SIZE * (pfnsum + i)) >>
-   PAGE_SHIFT;
+   gpadl_body->pfn[i] = virt_to_hvpfn(
+   kbuffer + PAGE_SIZE * (pfnsum + i));
 
/* add to msg header */
list_add_tail(>msglistentry,
@@ -380,8 +393,8 @@ static int create_gpadl_header(void *kbuffer, u32 size,
gpadl_header->range[0].byte_offset = 0;
gpadl_header->range[0].byte_count = size;
for (i = 0; i < pagecount; i++)
-   gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys(
-   kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;
+   gpadl_header->range[0].pfn_array[i] = virt_to_hvpfn(
+   kbuffer + PAGE_SIZE * i);
 
*msginfo = msgheader;
}
-- 
2.17.1



[PATCH 3/3] Drivers: hv: vmbus: Cleanup synic memory free path

2018-08-01 Thread kys
From: Michael Kelley 

clk_evt memory is not being freed when the synic is shutdown
or when there is an allocation error.  Add the appropriate
kfree() call, along with a comment to clarify how the memory
gets freed after an allocation error.  Make the free path
consistent by removing checks for NULL since kfree() and
free_page() already do the check.

Signed-off-by: Michael Kelley 
Reported-by: Dan Carpenter 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/hv.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 312fe5ed7c40..748a1c4172a6 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -242,6 +242,10 @@ int hv_synic_alloc(void)
 
return 0;
 err:
+   /*
+* Any memory allocations that succeeded will be freed when
+* the caller cleans up by calling hv_synic_free()
+*/
return -ENOMEM;
 }
 
@@ -254,12 +258,10 @@ void hv_synic_free(void)
struct hv_per_cpu_context *hv_cpu
= per_cpu_ptr(hv_context.cpu_context, cpu);
 
-   if (hv_cpu->synic_event_page)
-   free_page((unsigned long)hv_cpu->synic_event_page);
-   if (hv_cpu->synic_message_page)
-   free_page((unsigned long)hv_cpu->synic_message_page);
-   if (hv_cpu->post_msg_page)
-   free_page((unsigned long)hv_cpu->post_msg_page);
+   kfree(hv_cpu->clk_evt);
+   free_page((unsigned long)hv_cpu->synic_event_page);
+   free_page((unsigned long)hv_cpu->synic_message_page);
+   free_page((unsigned long)hv_cpu->post_msg_page);
}
 
kfree(hv_context.hv_numa_map);
-- 
2.17.1



[PATCH 2/3] Drivers: hv: vmbus: Remove use of slow_virt_to_phys()

2018-08-01 Thread kys
From: Michael Kelley 

slow_virt_to_phys() is only implemented for arch/x86.
Remove its use in arch independent Hyper-V drivers, and
replace with test for vmalloc() address followed by
appropriate v-to-p function. This follows the typical
pattern of other drivers and avoids the need to implement
slow_virt_to_phys() for Hyper-V on ARM64.

Signed-off-by: Michael Kelley 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/channel.c | 27 ---
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index c3949220b770..741857d80da1 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -29,12 +29,26 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "hyperv_vmbus.h"
 
 #define NUM_PAGES_SPANNED(addr, len) \
 ((PAGE_ALIGN(addr + len) >> PAGE_SHIFT) - (addr >> PAGE_SHIFT))
 
+static unsigned long virt_to_hvpfn(void *addr)
+{
+   unsigned long paddr;
+
+   if (is_vmalloc_addr(addr))
+   paddr = page_to_phys(vmalloc_to_page(addr)) +
+offset_in_page(addr);
+   else
+   paddr = __pa(addr);
+
+   return  paddr >> PAGE_SHIFT;
+}
+
 /*
  * vmbus_setevent- Trigger an event notification on the specified
  * channel.
@@ -298,8 +312,8 @@ static int create_gpadl_header(void *kbuffer, u32 size,
gpadl_header->range[0].byte_offset = 0;
gpadl_header->range[0].byte_count = size;
for (i = 0; i < pfncount; i++)
-   gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys(
-   kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;
+   gpadl_header->range[0].pfn_array[i] = virt_to_hvpfn(
+   kbuffer + PAGE_SIZE * i);
*msginfo = msgheader;
 
pfnsum = pfncount;
@@ -350,9 +364,8 @@ static int create_gpadl_header(void *kbuffer, u32 size,
 * so the hypervisor guarantees that this is ok.
 */
for (i = 0; i < pfncurr; i++)
-   gpadl_body->pfn[i] = slow_virt_to_phys(
-   kbuffer + PAGE_SIZE * (pfnsum + i)) >>
-   PAGE_SHIFT;
+   gpadl_body->pfn[i] = virt_to_hvpfn(
+   kbuffer + PAGE_SIZE * (pfnsum + i));
 
/* add to msg header */
list_add_tail(>msglistentry,
@@ -380,8 +393,8 @@ static int create_gpadl_header(void *kbuffer, u32 size,
gpadl_header->range[0].byte_offset = 0;
gpadl_header->range[0].byte_count = size;
for (i = 0; i < pagecount; i++)
-   gpadl_header->range[0].pfn_array[i] = slow_virt_to_phys(
-   kbuffer + PAGE_SIZE * i) >> PAGE_SHIFT;
+   gpadl_header->range[0].pfn_array[i] = virt_to_hvpfn(
+   kbuffer + PAGE_SIZE * i);
 
*msginfo = msgheader;
}
-- 
2.17.1



[PATCH 1/3] Drivers: hv: vmbus: Reset the channel callback in vmbus_onoffer_rescind()

2018-08-01 Thread kys
From: Dexuan Cui 

Before setting channel->rescind in vmbus_rescind_cleanup(), we should make
sure the channel callback won't run any more, otherwise a high-level
driver like pci_hyperv, which may be infinitely waiting for the host VSP's
response and notices the channel has been rescinded, can't safely give
up: e.g., in hv_pci_protocol_negotiation() -> wait_for_response(), it's
unsafe to exit from wait_for_response() and proceed with the on-stack
variable "comp_pkt" popped. The issue was originally spotted by
Michael Kelley .

In vmbus_close_internal(), the patch also minimizes the range protected by
disabling/enabling channel->callback_event: we don't really need that for
the whole function.

Signed-off-by: Dexuan Cui 
Reviewed-by: Michael Kelley 
Cc: sta...@vger.kernel.org
Cc: K. Y. Srinivasan 
Cc: Stephen Hemminger 
Cc: Michael Kelley 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/channel.c  | 40 +++
 drivers/hv/channel_mgmt.c |  6 ++
 include/linux/hyperv.h|  2 ++
 3 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index ba0a092ae085..c3949220b770 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -558,11 +558,8 @@ static void reset_channel_cb(void *arg)
channel->onchannel_callback = NULL;
 }
 
-static int vmbus_close_internal(struct vmbus_channel *channel)
+void vmbus_reset_channel_cb(struct vmbus_channel *channel)
 {
-   struct vmbus_channel_close_channel *msg;
-   int ret;
-
/*
 * vmbus_on_event(), running in the per-channel tasklet, can race
 * with vmbus_close_internal() in the case of SMP guest, e.g., when
@@ -572,6 +569,29 @@ static int vmbus_close_internal(struct vmbus_channel 
*channel)
 */
tasklet_disable(>callback_event);
 
+   channel->sc_creation_callback = NULL;
+
+   /* Stop the callback asap */
+   if (channel->target_cpu != get_cpu()) {
+   put_cpu();
+   smp_call_function_single(channel->target_cpu, reset_channel_cb,
+channel, true);
+   } else {
+   reset_channel_cb(channel);
+   put_cpu();
+   }
+
+   /* Re-enable tasklet for use on re-open */
+   tasklet_enable(>callback_event);
+}
+
+static int vmbus_close_internal(struct vmbus_channel *channel)
+{
+   struct vmbus_channel_close_channel *msg;
+   int ret;
+
+   vmbus_reset_channel_cb(channel);
+
/*
 * In case a device driver's probe() fails (e.g.,
 * util_probe() -> vmbus_open() returns -ENOMEM) and the device is
@@ -585,16 +605,6 @@ static int vmbus_close_internal(struct vmbus_channel 
*channel)
}
 
channel->state = CHANNEL_OPEN_STATE;
-   channel->sc_creation_callback = NULL;
-   /* Stop callback and cancel the timer asap */
-   if (channel->target_cpu != get_cpu()) {
-   put_cpu();
-   smp_call_function_single(channel->target_cpu, reset_channel_cb,
-channel, true);
-   } else {
-   reset_channel_cb(channel);
-   put_cpu();
-   }
 
/* Send a closing message */
 
@@ -639,8 +649,6 @@ static int vmbus_close_internal(struct vmbus_channel 
*channel)
get_order(channel->ringbuffer_pagecount * PAGE_SIZE));
 
 out:
-   /* re-enable tasklet for use on re-open */
-   tasklet_enable(>callback_event);
return ret;
 }
 
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index f3b551a50653..0f0e091c117c 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -892,6 +892,12 @@ static void vmbus_onoffer_rescind(struct 
vmbus_channel_message_header *hdr)
return;
}
 
+   /*
+* Before setting channel->rescind in vmbus_rescind_cleanup(), we
+* should make sure the channel callback is not running any more.
+*/
+   vmbus_reset_channel_cb(channel);
+
/*
 * Now wait for offer handling to complete.
 */
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 2330f08062c7..efda23cf32c7 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1061,6 +1061,8 @@ extern int vmbus_establish_gpadl(struct vmbus_channel 
*channel,
 extern int vmbus_teardown_gpadl(struct vmbus_channel *channel,
 u32 gpadl_handle);
 
+void vmbus_reset_channel_cb(struct vmbus_channel *channel);
+
 extern int vmbus_recvpacket(struct vmbus_channel *channel,
  void *buffer,
  u32 bufferlen,
-- 
2.17.1



[PATCH 0/3] Drivers: hv: vmbus: Miscellaneous fixes

2018-08-01 Thread kys
From: "K. Y. Srinivasan" 

Miscellaneous fixes.

Dexuan Cui (1):
  Drivers: hv: vmbus: Reset the channel callback in
vmbus_onoffer_rescind()

Michael Kelley (2):
  Drivers: hv: vmbus: Remove use of slow_virt_to_phys()
  Drivers: hv: vmbus: Cleanup synic memory free path

 drivers/hv/channel.c  | 67 +--
 drivers/hv/channel_mgmt.c |  6 
 drivers/hv/hv.c   | 14 
 include/linux/hyperv.h|  2 ++
 4 files changed, 60 insertions(+), 29 deletions(-)

-- 
2.17.1



[PATCH 0/3] Drivers: hv: vmbus: Miscellaneous fixes

2018-08-01 Thread kys
From: "K. Y. Srinivasan" 

Miscellaneous fixes.

Dexuan Cui (1):
  Drivers: hv: vmbus: Reset the channel callback in
vmbus_onoffer_rescind()

Michael Kelley (2):
  Drivers: hv: vmbus: Remove use of slow_virt_to_phys()
  Drivers: hv: vmbus: Cleanup synic memory free path

 drivers/hv/channel.c  | 67 +--
 drivers/hv/channel_mgmt.c |  6 
 drivers/hv/hv.c   | 14 
 include/linux/hyperv.h|  2 ++
 4 files changed, 60 insertions(+), 29 deletions(-)

-- 
2.17.1



[PATCH 2/4] Drivers: hv: vmbus: Fix the issue with freeing up hv_ctl_table_hdr

2018-07-28 Thread kys
From: Sunil Muthuswamy 

The check to free the Hyper-V control table header was reversed. This
fixes it.

Fixes: 81b18bce48af ("Drivers: HV: Send one page worth of kmsg dump over 
Hyper-V during panic")

Signed-off-by: Sunil Muthuswamy 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/vmbus_drv.c | 14 --
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index a7f33c1f42c5..5e946b1be54c 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1176,11 +1176,8 @@ static int vmbus_bus_init(void)
 
bus_unregister(_bus);
free_page((unsigned long)hv_panic_page);
-   if (!hv_ctl_table_hdr) {
-   unregister_sysctl_table(hv_ctl_table_hdr);
-   hv_ctl_table_hdr = NULL;
-   }
-
+   unregister_sysctl_table(hv_ctl_table_hdr);
+   hv_ctl_table_hdr = NULL;
return ret;
 }
 
@@ -1891,11 +1888,8 @@ static void __exit vmbus_exit(void)
}
 
free_page((unsigned long)hv_panic_page);
-   if (!hv_ctl_table_hdr) {
-   unregister_sysctl_table(hv_ctl_table_hdr);
-   hv_ctl_table_hdr = NULL;
-   }
-
+   unregister_sysctl_table(hv_ctl_table_hdr);
+   hv_ctl_table_hdr = NULL;
bus_unregister(_bus);
 
cpuhp_remove_state(hyperv_cpuhp_online);
-- 
2.17.1



[PATCH 2/4] Drivers: hv: vmbus: Fix the issue with freeing up hv_ctl_table_hdr

2018-07-28 Thread kys
From: Sunil Muthuswamy 

The check to free the Hyper-V control table header was reversed. This
fixes it.

Fixes: 81b18bce48af ("Drivers: HV: Send one page worth of kmsg dump over 
Hyper-V during panic")

Signed-off-by: Sunil Muthuswamy 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/vmbus_drv.c | 14 --
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index a7f33c1f42c5..5e946b1be54c 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1176,11 +1176,8 @@ static int vmbus_bus_init(void)
 
bus_unregister(_bus);
free_page((unsigned long)hv_panic_page);
-   if (!hv_ctl_table_hdr) {
-   unregister_sysctl_table(hv_ctl_table_hdr);
-   hv_ctl_table_hdr = NULL;
-   }
-
+   unregister_sysctl_table(hv_ctl_table_hdr);
+   hv_ctl_table_hdr = NULL;
return ret;
 }
 
@@ -1891,11 +1888,8 @@ static void __exit vmbus_exit(void)
}
 
free_page((unsigned long)hv_panic_page);
-   if (!hv_ctl_table_hdr) {
-   unregister_sysctl_table(hv_ctl_table_hdr);
-   hv_ctl_table_hdr = NULL;
-   }
-
+   unregister_sysctl_table(hv_ctl_table_hdr);
+   hv_ctl_table_hdr = NULL;
bus_unregister(_bus);
 
cpuhp_remove_state(hyperv_cpuhp_online);
-- 
2.17.1



[PATCH 4/4] Drivers: hv: vmbus: add numa_node to sysfs

2018-07-28 Thread kys
From: Stephen Hemminger 

Being able to find the numa_node for a device is useful for userspace
drivers (DPDK) and also for diagnosing performance issues.  This makes
vmbus similar to pci.

Signed-off-by: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 Documentation/ABI/stable/sysfs-bus-vmbus |  7 +++
 drivers/hv/vmbus_drv.c   | 17 +
 2 files changed, 24 insertions(+)

diff --git a/Documentation/ABI/stable/sysfs-bus-vmbus 
b/Documentation/ABI/stable/sysfs-bus-vmbus
index 3eaffbb2d468..3fed8fdb873d 100644
--- a/Documentation/ABI/stable/sysfs-bus-vmbus
+++ b/Documentation/ABI/stable/sysfs-bus-vmbus
@@ -42,6 +42,13 @@ Contact: K. Y. Srinivasan 
 Description:   The 16 bit vendor ID of the device
 Users: tools/hv/lsvmbus and user level RDMA libraries
 
+What:  /sys/bus/vmbus/devices//numa_node
+Date:  Jul 2018
+KernelVersion: 4.19
+Contact:   Stephen Hemminger 
+Description:   This NUMA node to which the VMBUS device is
+   attached, or -1 if the node is unknown.
+
 What:  /sys/bus/vmbus/devices//channels/
 Date:  September. 2017
 KernelVersion: 4.14
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index db145e1a7049..b1b548a21f91 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -210,6 +210,20 @@ static ssize_t modalias_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(modalias);
 
+#ifdef CONFIG_NUMA
+static ssize_t numa_node_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+   struct hv_device *hv_dev = device_to_hv_device(dev);
+
+   if (!hv_dev->channel)
+   return -ENODEV;
+
+   return sprintf(buf, "%d\n", hv_dev->channel->numa_node);
+}
+static DEVICE_ATTR_RO(numa_node);
+#endif
+
 static ssize_t server_monitor_pending_show(struct device *dev,
   struct device_attribute *dev_attr,
   char *buf)
@@ -492,6 +506,9 @@ static struct attribute *vmbus_dev_attrs[] = {
_attr_class_id.attr,
_attr_device_id.attr,
_attr_modalias.attr,
+#ifdef CONFIG_NUMA
+   _attr_numa_node.attr,
+#endif
_attr_server_monitor_pending.attr,
_attr_client_monitor_pending.attr,
_attr_server_monitor_latency.attr,
-- 
2.17.1



[PATCH 4/4] Drivers: hv: vmbus: add numa_node to sysfs

2018-07-28 Thread kys
From: Stephen Hemminger 

Being able to find the numa_node for a device is useful for userspace
drivers (DPDK) and also for diagnosing performance issues.  This makes
vmbus similar to pci.

Signed-off-by: Stephen Hemminger 
Signed-off-by: K. Y. Srinivasan 
---
 Documentation/ABI/stable/sysfs-bus-vmbus |  7 +++
 drivers/hv/vmbus_drv.c   | 17 +
 2 files changed, 24 insertions(+)

diff --git a/Documentation/ABI/stable/sysfs-bus-vmbus 
b/Documentation/ABI/stable/sysfs-bus-vmbus
index 3eaffbb2d468..3fed8fdb873d 100644
--- a/Documentation/ABI/stable/sysfs-bus-vmbus
+++ b/Documentation/ABI/stable/sysfs-bus-vmbus
@@ -42,6 +42,13 @@ Contact: K. Y. Srinivasan 
 Description:   The 16 bit vendor ID of the device
 Users: tools/hv/lsvmbus and user level RDMA libraries
 
+What:  /sys/bus/vmbus/devices//numa_node
+Date:  Jul 2018
+KernelVersion: 4.19
+Contact:   Stephen Hemminger 
+Description:   This NUMA node to which the VMBUS device is
+   attached, or -1 if the node is unknown.
+
 What:  /sys/bus/vmbus/devices//channels/
 Date:  September. 2017
 KernelVersion: 4.14
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index db145e1a7049..b1b548a21f91 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -210,6 +210,20 @@ static ssize_t modalias_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(modalias);
 
+#ifdef CONFIG_NUMA
+static ssize_t numa_node_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+   struct hv_device *hv_dev = device_to_hv_device(dev);
+
+   if (!hv_dev->channel)
+   return -ENODEV;
+
+   return sprintf(buf, "%d\n", hv_dev->channel->numa_node);
+}
+static DEVICE_ATTR_RO(numa_node);
+#endif
+
 static ssize_t server_monitor_pending_show(struct device *dev,
   struct device_attribute *dev_attr,
   char *buf)
@@ -492,6 +506,9 @@ static struct attribute *vmbus_dev_attrs[] = {
_attr_class_id.attr,
_attr_device_id.attr,
_attr_modalias.attr,
+#ifdef CONFIG_NUMA
+   _attr_numa_node.attr,
+#endif
_attr_server_monitor_pending.attr,
_attr_client_monitor_pending.attr,
_attr_server_monitor_latency.attr,
-- 
2.17.1



[PATCH 1/4] Drivers: hv: vmus: Fix the check for return value from kmsg get dump buffer

2018-07-28 Thread kys
From: Sunil Muthuswamy 

The code to support panic control message was checking the return was
checking the return value from kmsg_dump_get_buffer as error value, which
is not what the routine returns. This fixes it.

Fixes: 81b18bce48af ("Drivers: HV: Send one page worth of kmsg dump over 
Hyper-V during panic")

Signed-off-by: Sunil Muthuswamy 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/vmbus_drv.c | 11 ---
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 05e37283d7c3..a7f33c1f42c5 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1047,13 +1047,10 @@ static void hv_kmsg_dump(struct kmsg_dumper *dumper,
 * Write dump contents to the page. No need to synchronize; panic should
 * be single-threaded.
 */
-   if (!kmsg_dump_get_buffer(dumper, true, hv_panic_page,
- PAGE_SIZE, _written)) {
-   pr_err("Hyper-V: Unable to get kmsg data for panic\n");
-   return;
-   }
-
-   hyperv_report_panic_msg(panic_pa, bytes_written);
+   kmsg_dump_get_buffer(dumper, true, hv_panic_page, PAGE_SIZE,
+_written);
+   if (bytes_written)
+   hyperv_report_panic_msg(panic_pa, bytes_written);
 }
 
 static struct kmsg_dumper hv_kmsg_dumper = {
-- 
2.17.1



[PATCH 3/4] Drivers: hv: vmbus: Get rid of MSR access from vmbus_drv.c

2018-07-28 Thread kys
From: Sunil Muthuswamy 

Get rid of ISA specific code from vmus_drv.c which is common code.

Fixes: 81b18bce48af ("Drivers: HV: Send one page worth of kmsg dump over 
Hyper-V during panic")

Signed-off-by: Sunil Muthuswamy 
Signed-off-by: K. Y. Srinivasan 
---
 arch/x86/include/asm/mshyperv.h | 3 +++
 drivers/hv/vmbus_drv.c  | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 156a2e5a97a9..b731c4bf70ed 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -96,6 +96,9 @@ static inline void vmbus_signal_eom(struct hv_message *msg, 
u32 old_msg_type)
 #define hv_set_synint_state(int_num, val) \
wrmsrl(HV_X64_MSR_SINT0 + int_num, val)
 
+#define hv_get_crash_ctl(val) \
+   rdmsrl(HV_X64_MSR_CRASH_CTL, val)
+
 void hyperv_callback_vector(void);
 void hyperv_reenlightenment_vector(void);
 #ifdef CONFIG_TRACING
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 5e946b1be54c..db145e1a7049 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1146,7 +1146,7 @@ static int vmbus_bus_init(void)
 * Register for panic kmsg callback only if the right
 * capability is supported by the hypervisor.
 */
-   rdmsrl(HV_X64_MSR_CRASH_CTL, hyperv_crash_ctl);
+   hv_get_crash_ctl(hyperv_crash_ctl);
if (hyperv_crash_ctl & HV_CRASH_CTL_CRASH_NOTIFY_MSG) {
hv_panic_page = (void *)get_zeroed_page(GFP_KERNEL);
if (hv_panic_page) {
-- 
2.17.1



[PATCH 1/4] Drivers: hv: vmus: Fix the check for return value from kmsg get dump buffer

2018-07-28 Thread kys
From: Sunil Muthuswamy 

The code to support panic control message was checking the return was
checking the return value from kmsg_dump_get_buffer as error value, which
is not what the routine returns. This fixes it.

Fixes: 81b18bce48af ("Drivers: HV: Send one page worth of kmsg dump over 
Hyper-V during panic")

Signed-off-by: Sunil Muthuswamy 
Signed-off-by: K. Y. Srinivasan 
---
 drivers/hv/vmbus_drv.c | 11 ---
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 05e37283d7c3..a7f33c1f42c5 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1047,13 +1047,10 @@ static void hv_kmsg_dump(struct kmsg_dumper *dumper,
 * Write dump contents to the page. No need to synchronize; panic should
 * be single-threaded.
 */
-   if (!kmsg_dump_get_buffer(dumper, true, hv_panic_page,
- PAGE_SIZE, _written)) {
-   pr_err("Hyper-V: Unable to get kmsg data for panic\n");
-   return;
-   }
-
-   hyperv_report_panic_msg(panic_pa, bytes_written);
+   kmsg_dump_get_buffer(dumper, true, hv_panic_page, PAGE_SIZE,
+_written);
+   if (bytes_written)
+   hyperv_report_panic_msg(panic_pa, bytes_written);
 }
 
 static struct kmsg_dumper hv_kmsg_dumper = {
-- 
2.17.1



[PATCH 3/4] Drivers: hv: vmbus: Get rid of MSR access from vmbus_drv.c

2018-07-28 Thread kys
From: Sunil Muthuswamy 

Get rid of ISA specific code from vmus_drv.c which is common code.

Fixes: 81b18bce48af ("Drivers: HV: Send one page worth of kmsg dump over 
Hyper-V during panic")

Signed-off-by: Sunil Muthuswamy 
Signed-off-by: K. Y. Srinivasan 
---
 arch/x86/include/asm/mshyperv.h | 3 +++
 drivers/hv/vmbus_drv.c  | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 156a2e5a97a9..b731c4bf70ed 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -96,6 +96,9 @@ static inline void vmbus_signal_eom(struct hv_message *msg, 
u32 old_msg_type)
 #define hv_set_synint_state(int_num, val) \
wrmsrl(HV_X64_MSR_SINT0 + int_num, val)
 
+#define hv_get_crash_ctl(val) \
+   rdmsrl(HV_X64_MSR_CRASH_CTL, val)
+
 void hyperv_callback_vector(void);
 void hyperv_reenlightenment_vector(void);
 #ifdef CONFIG_TRACING
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 5e946b1be54c..db145e1a7049 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1146,7 +1146,7 @@ static int vmbus_bus_init(void)
 * Register for panic kmsg callback only if the right
 * capability is supported by the hypervisor.
 */
-   rdmsrl(HV_X64_MSR_CRASH_CTL, hyperv_crash_ctl);
+   hv_get_crash_ctl(hyperv_crash_ctl);
if (hyperv_crash_ctl & HV_CRASH_CTL_CRASH_NOTIFY_MSG) {
hv_panic_page = (void *)get_zeroed_page(GFP_KERNEL);
if (hv_panic_page) {
-- 
2.17.1



[PATCH 0/4] Drivers: hv: vmbus: Miscellaneous fixes/enhancements

2018-07-28 Thread kys
From: "K. Y. Srinivasan" 

Miscellaneous fixes/enhancements

Stephen Hemminger (1):
  Drivers: hv: vmbus: add numa_node to sysfs

Sunil Muthuswamy (3):
  Drivers: hv: vmus: Fix the check for return value from kmsg get dump
buffer
  Drivers: hv: vmbus: Fix the issue with freeing up hv_ctl_table_hdr
  Drivers: hv: vmbus: Get rid of MSR access from vmbus_drv.c

 Documentation/ABI/stable/sysfs-bus-vmbus |  7 
 arch/x86/include/asm/mshyperv.h  |  3 ++
 drivers/hv/vmbus_drv.c   | 44 ++--
 3 files changed, 36 insertions(+), 18 deletions(-)

-- 
2.17.1



[PATCH 0/4] Drivers: hv: vmbus: Miscellaneous fixes/enhancements

2018-07-28 Thread kys
From: "K. Y. Srinivasan" 

Miscellaneous fixes/enhancements

Stephen Hemminger (1):
  Drivers: hv: vmbus: add numa_node to sysfs

Sunil Muthuswamy (3):
  Drivers: hv: vmus: Fix the check for return value from kmsg get dump
buffer
  Drivers: hv: vmbus: Fix the issue with freeing up hv_ctl_table_hdr
  Drivers: hv: vmbus: Get rid of MSR access from vmbus_drv.c

 Documentation/ABI/stable/sysfs-bus-vmbus |  7 
 arch/x86/include/asm/mshyperv.h  |  3 ++
 drivers/hv/vmbus_drv.c   | 44 ++--
 3 files changed, 36 insertions(+), 18 deletions(-)

-- 
2.17.1



[PATCH 1/1] x86/hyper-v: Fix a merge error

2018-07-19 Thread kys
From: "K. Y. Srinivasan" 

When the mapping betwween the Linux notion of CPU ID
to the hypervisor's notion of CPU ID is not initialized,
we should fall back on the non-enligghtened path for IPI.
A merge error introduced this bug; fix it.

Fixes: 1268ed0c474a ("Merge branch 'x86/urgent' into x86/hyperv")

Reported-by: Michael Kelley 
Signed-off-by: K. Y. Srinivasan 
---
 arch/x86/hyperv/hv_apic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c
index 0c3c9f8fee77..5b0f613428c2 100644
--- a/arch/x86/hyperv/hv_apic.c
+++ b/arch/x86/hyperv/hv_apic.c
@@ -168,7 +168,7 @@ static bool __send_ipi_mask(const struct cpumask *mask, int 
vector)
for_each_cpu(cur_cpu, mask) {
vcpu = hv_cpu_number_to_vp_number(cur_cpu);
if (vcpu == VP_INVAL)
-   return true;
+   return false;
 
/*
 * This particular version of the IPI hypercall can
-- 
2.17.1



[PATCH 1/1] x86/hyper-v: Fix a merge error

2018-07-19 Thread kys
From: "K. Y. Srinivasan" 

When the mapping betwween the Linux notion of CPU ID
to the hypervisor's notion of CPU ID is not initialized,
we should fall back on the non-enligghtened path for IPI.
A merge error introduced this bug; fix it.

Fixes: 1268ed0c474a ("Merge branch 'x86/urgent' into x86/hyperv")

Reported-by: Michael Kelley 
Signed-off-by: K. Y. Srinivasan 
---
 arch/x86/hyperv/hv_apic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c
index 0c3c9f8fee77..5b0f613428c2 100644
--- a/arch/x86/hyperv/hv_apic.c
+++ b/arch/x86/hyperv/hv_apic.c
@@ -168,7 +168,7 @@ static bool __send_ipi_mask(const struct cpumask *mask, int 
vector)
for_each_cpu(cur_cpu, mask) {
vcpu = hv_cpu_number_to_vp_number(cur_cpu);
if (vcpu == VP_INVAL)
-   return true;
+   return false;
 
/*
 * This particular version of the IPI hypercall can
-- 
2.17.1



[PATCH 1/1] Drivers: HV: Send one page worth of kmsg dump over Hyper-V during panic

2018-07-07 Thread kys
From: Sunil Muthuswamy 

In the VM mode on Hyper-V, currently, when the kernel panics, an error
code and few register values are populated in an MSR and the Hypervisor
notified. This information is collected on the host. The amount of
information currently collected is found to be limited and not very
actionable. To gather more actionable data, such as stack trace, the
proposal is to write one page worth of kmsg data on an allocated page
and the Hypervisor notified of the page address through the MSR.

- Sysctl option to control the behavior, with ON by default.

Cc: K. Y. Srinivasan 
Cc: Stephen Hemminger 
Signed-off-by: Sunil Muthuswamy 
Signed-off-by: K. Y. Srinivasan 
---
 Documentation/sysctl/kernel.txt|  11 +++
 arch/x86/hyperv/hv_init.c  |  27 +++
 arch/x86/include/asm/hyperv-tlfs.h |   5 +-
 arch/x86/include/asm/mshyperv.h|   1 +
 drivers/hv/vmbus_drv.c | 110 +
 5 files changed, 152 insertions(+), 2 deletions(-)

diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index eded671d55eb..59585030cbaf 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -39,6 +39,7 @@ show up in /proc/sys/kernel:
 - hung_task_check_count
 - hung_task_timeout_secs
 - hung_task_warnings
+- hyperv_record_panic_msg
 - kexec_load_disabled
 - kptr_restrict
 - l2cr[ PPC only ]
@@ -374,6 +375,16 @@ This file shows up if CONFIG_DETECT_HUNG_TASK is enabled.
 
 ==
 
+hyperv_record_panic_msg:
+
+Controls whether the panic kmsg data should be reported to Hyper-V.
+
+0: do not report panic kmsg data.
+
+1: report the panic kmsg data. This is the default behavior.
+
+==
+
 kexec_load_disabled:
 
 A toggle indicating if the kexec_load syscall has been disabled. This
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 595e44e8abaa..9c70018a9906 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -423,6 +423,33 @@ void hyperv_report_panic(struct pt_regs *regs, long err)
 }
 EXPORT_SYMBOL_GPL(hyperv_report_panic);
 
+/**
+ * hyperv_report_panic_msg - report panic message to Hyper-V
+ * @pa: physical address of the panic page containing the message
+ * @size: size of the message in the page
+ */
+void hyperv_report_panic_msg(phys_addr_t pa, size_t size)
+{
+   /*
+* P3 to contain the physical address of the panic page & P4 to
+* contain the size of the panic data in that page. Rest of the
+* registers are no-op when the NOTIFY_MSG flag is set.
+*/
+   wrmsrl(HV_X64_MSR_CRASH_P0, 0);
+   wrmsrl(HV_X64_MSR_CRASH_P1, 0);
+   wrmsrl(HV_X64_MSR_CRASH_P2, 0);
+   wrmsrl(HV_X64_MSR_CRASH_P3, pa);
+   wrmsrl(HV_X64_MSR_CRASH_P4, size);
+
+   /*
+* Let Hyper-V know there is crash data available along with
+* the panic message.
+*/
+   wrmsrl(HV_X64_MSR_CRASH_CTL,
+  (HV_CRASH_CTL_CRASH_NOTIFY | HV_CRASH_CTL_CRASH_NOTIFY_MSG));
+}
+EXPORT_SYMBOL_GPL(hyperv_report_panic_msg);
+
 bool hv_is_hyperv_initialized(void)
 {
union hv_x64_msr_hypercall_contents hypercall_msr;
diff --git a/arch/x86/include/asm/hyperv-tlfs.h 
b/arch/x86/include/asm/hyperv-tlfs.h
index 96272e99b64e..6ced78af48da 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -176,9 +176,10 @@
 #define HV_X64_ENLIGHTENED_VMCS_RECOMMENDED(1 << 14)
 
 /*
- * Crash notification flag.
+ * Crash notification flags.
  */
-#define HV_CRASH_CTL_CRASH_NOTIFY (1ULL << 63)
+#define HV_CRASH_CTL_CRASH_NOTIFY_MSG  BIT_ULL(62)
+#define HV_CRASH_CTL_CRASH_NOTIFY  BIT_ULL(63)
 
 /* MSR used to identify the guest OS. */
 #define HV_X64_MSR_GUEST_OS_ID 0x4000
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 81e768b8d9eb..156a2e5a97a9 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -299,6 +299,7 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset,
 void __init hyperv_init(void);
 void hyperv_setup_mmu_ops(void);
 void hyperv_report_panic(struct pt_regs *regs, long err);
+void hyperv_report_panic_msg(phys_addr_t pa, size_t size);
 bool hv_is_hyperv_initialized(void);
 void hyperv_cleanup(void);
 
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index b10fe26c4891..05e37283d7c3 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -56,6 +56,8 @@ static struct completion probe_event;
 
 static int hyperv_cpuhp_online;
 
+static void *hv_panic_page;
+
 static int hyperv_panic_event(struct notifier_block *nb, unsigned long val,
  void *args)
 {
@@ -1018,6 +1020,75 @@ static void vmbus_isr(void)
add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0);
 }
 
+/*
+ * Boolean to control whether to 

[PATCH 1/1] Drivers: HV: Send one page worth of kmsg dump over Hyper-V during panic

2018-07-07 Thread kys
From: Sunil Muthuswamy 

In the VM mode on Hyper-V, currently, when the kernel panics, an error
code and few register values are populated in an MSR and the Hypervisor
notified. This information is collected on the host. The amount of
information currently collected is found to be limited and not very
actionable. To gather more actionable data, such as stack trace, the
proposal is to write one page worth of kmsg data on an allocated page
and the Hypervisor notified of the page address through the MSR.

- Sysctl option to control the behavior, with ON by default.

Cc: K. Y. Srinivasan 
Cc: Stephen Hemminger 
Signed-off-by: Sunil Muthuswamy 
Signed-off-by: K. Y. Srinivasan 
---
 Documentation/sysctl/kernel.txt|  11 +++
 arch/x86/hyperv/hv_init.c  |  27 +++
 arch/x86/include/asm/hyperv-tlfs.h |   5 +-
 arch/x86/include/asm/mshyperv.h|   1 +
 drivers/hv/vmbus_drv.c | 110 +
 5 files changed, 152 insertions(+), 2 deletions(-)

diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index eded671d55eb..59585030cbaf 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -39,6 +39,7 @@ show up in /proc/sys/kernel:
 - hung_task_check_count
 - hung_task_timeout_secs
 - hung_task_warnings
+- hyperv_record_panic_msg
 - kexec_load_disabled
 - kptr_restrict
 - l2cr[ PPC only ]
@@ -374,6 +375,16 @@ This file shows up if CONFIG_DETECT_HUNG_TASK is enabled.
 
 ==
 
+hyperv_record_panic_msg:
+
+Controls whether the panic kmsg data should be reported to Hyper-V.
+
+0: do not report panic kmsg data.
+
+1: report the panic kmsg data. This is the default behavior.
+
+==
+
 kexec_load_disabled:
 
 A toggle indicating if the kexec_load syscall has been disabled. This
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 595e44e8abaa..9c70018a9906 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -423,6 +423,33 @@ void hyperv_report_panic(struct pt_regs *regs, long err)
 }
 EXPORT_SYMBOL_GPL(hyperv_report_panic);
 
+/**
+ * hyperv_report_panic_msg - report panic message to Hyper-V
+ * @pa: physical address of the panic page containing the message
+ * @size: size of the message in the page
+ */
+void hyperv_report_panic_msg(phys_addr_t pa, size_t size)
+{
+   /*
+* P3 to contain the physical address of the panic page & P4 to
+* contain the size of the panic data in that page. Rest of the
+* registers are no-op when the NOTIFY_MSG flag is set.
+*/
+   wrmsrl(HV_X64_MSR_CRASH_P0, 0);
+   wrmsrl(HV_X64_MSR_CRASH_P1, 0);
+   wrmsrl(HV_X64_MSR_CRASH_P2, 0);
+   wrmsrl(HV_X64_MSR_CRASH_P3, pa);
+   wrmsrl(HV_X64_MSR_CRASH_P4, size);
+
+   /*
+* Let Hyper-V know there is crash data available along with
+* the panic message.
+*/
+   wrmsrl(HV_X64_MSR_CRASH_CTL,
+  (HV_CRASH_CTL_CRASH_NOTIFY | HV_CRASH_CTL_CRASH_NOTIFY_MSG));
+}
+EXPORT_SYMBOL_GPL(hyperv_report_panic_msg);
+
 bool hv_is_hyperv_initialized(void)
 {
union hv_x64_msr_hypercall_contents hypercall_msr;
diff --git a/arch/x86/include/asm/hyperv-tlfs.h 
b/arch/x86/include/asm/hyperv-tlfs.h
index 96272e99b64e..6ced78af48da 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -176,9 +176,10 @@
 #define HV_X64_ENLIGHTENED_VMCS_RECOMMENDED(1 << 14)
 
 /*
- * Crash notification flag.
+ * Crash notification flags.
  */
-#define HV_CRASH_CTL_CRASH_NOTIFY (1ULL << 63)
+#define HV_CRASH_CTL_CRASH_NOTIFY_MSG  BIT_ULL(62)
+#define HV_CRASH_CTL_CRASH_NOTIFY  BIT_ULL(63)
 
 /* MSR used to identify the guest OS. */
 #define HV_X64_MSR_GUEST_OS_ID 0x4000
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 81e768b8d9eb..156a2e5a97a9 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -299,6 +299,7 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset,
 void __init hyperv_init(void);
 void hyperv_setup_mmu_ops(void);
 void hyperv_report_panic(struct pt_regs *regs, long err);
+void hyperv_report_panic_msg(phys_addr_t pa, size_t size);
 bool hv_is_hyperv_initialized(void);
 void hyperv_cleanup(void);
 
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index b10fe26c4891..05e37283d7c3 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -56,6 +56,8 @@ static struct completion probe_event;
 
 static int hyperv_cpuhp_online;
 
+static void *hv_panic_page;
+
 static int hyperv_panic_event(struct notifier_block *nb, unsigned long val,
  void *args)
 {
@@ -1018,6 +1020,75 @@ static void vmbus_isr(void)
add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0);
 }
 
+/*
+ * Boolean to control whether to 

[PATCH 1/1] X86/Hyper-V:: Fix the circular dependency in IPI enlightenment.

2018-07-03 Thread kys
From: "K. Y. Srinivasan" 

The IPI hypercalls depend on being able to map the Linux notion of CPU ID
to the hypervisor's notion of the CPU ID. The array hv_vp_index[] provides
this mapping. Code for populating this array depends on the IPI functionality.
Break this circular dependency.

Fixes: 68bb7bfb7985 ("X86/Hyper-V: Enable IPI enlightenments")

Signed-off-by: K. Y. Srinivasan 
Tested-by: Michael Kelley 
---
 arch/x86/hyperv/hv_apic.c   | 5 +
 arch/x86/hyperv/hv_init.c   | 5 -
 arch/x86/include/asm/mshyperv.h | 2 ++
 3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c
index f68855499391..63d7c196739f 100644
--- a/arch/x86/hyperv/hv_apic.c
+++ b/arch/x86/hyperv/hv_apic.c
@@ -114,6 +114,8 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, 
int vector)
ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K;
nr_bank = cpumask_to_vpset(&(ipi_arg->vp_set), mask);
}
+   if (nr_bank == -1)
+   goto ipi_mask_ex_done;
if (!nr_bank)
ipi_arg->vp_set.format = HV_GENERIC_SET_ALL;
 
@@ -158,6 +160,9 @@ static bool __send_ipi_mask(const struct cpumask *mask, int 
vector)
 
for_each_cpu(cur_cpu, mask) {
vcpu = hv_cpu_number_to_vp_number(cur_cpu);
+   if (vcpu == -1)
+   goto ipi_mask_done;
+
/*
 * This particular version of the IPI hypercall can
 * only target upto 64 CPUs.
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 4c431e1c1eff..04159893702e 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -265,7 +265,7 @@ void __init hyperv_init(void)
 {
u64 guest_id, required_msrs;
union hv_x64_msr_hypercall_contents hypercall_msr;
-   int cpuhp;
+   int cpuhp, i;
 
if (x86_hyper_type != X86_HYPER_MS_HYPERV)
return;
@@ -293,6 +293,9 @@ void __init hyperv_init(void)
if (!hv_vp_index)
return;
 
+   for (i = 0; i < num_possible_cpus(); i++)
+   hv_vp_index[i] = -1;
+
hv_vp_assist_page = kcalloc(num_possible_cpus(),
sizeof(*hv_vp_assist_page), GFP_KERNEL);
if (!hv_vp_assist_page) {
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 3cd14311edfa..dee3f7347253 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -281,6 +281,8 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset,
 */
for_each_cpu(cpu, cpus) {
vcpu = hv_cpu_number_to_vp_number(cpu);
+   if (vcpu == -1)
+   return -1;
vcpu_bank = vcpu / 64;
vcpu_offset = vcpu % 64;
__set_bit(vcpu_offset, (unsigned long *)
-- 
2.17.1



[PATCH 1/1] X86/Hyper-V:: Fix the circular dependency in IPI enlightenment.

2018-07-03 Thread kys
From: "K. Y. Srinivasan" 

The IPI hypercalls depend on being able to map the Linux notion of CPU ID
to the hypervisor's notion of the CPU ID. The array hv_vp_index[] provides
this mapping. Code for populating this array depends on the IPI functionality.
Break this circular dependency.

Fixes: 68bb7bfb7985 ("X86/Hyper-V: Enable IPI enlightenments")

Signed-off-by: K. Y. Srinivasan 
Tested-by: Michael Kelley 
---
 arch/x86/hyperv/hv_apic.c   | 5 +
 arch/x86/hyperv/hv_init.c   | 5 -
 arch/x86/include/asm/mshyperv.h | 2 ++
 3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c
index f68855499391..63d7c196739f 100644
--- a/arch/x86/hyperv/hv_apic.c
+++ b/arch/x86/hyperv/hv_apic.c
@@ -114,6 +114,8 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, 
int vector)
ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K;
nr_bank = cpumask_to_vpset(&(ipi_arg->vp_set), mask);
}
+   if (nr_bank == -1)
+   goto ipi_mask_ex_done;
if (!nr_bank)
ipi_arg->vp_set.format = HV_GENERIC_SET_ALL;
 
@@ -158,6 +160,9 @@ static bool __send_ipi_mask(const struct cpumask *mask, int 
vector)
 
for_each_cpu(cur_cpu, mask) {
vcpu = hv_cpu_number_to_vp_number(cur_cpu);
+   if (vcpu == -1)
+   goto ipi_mask_done;
+
/*
 * This particular version of the IPI hypercall can
 * only target upto 64 CPUs.
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 4c431e1c1eff..04159893702e 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -265,7 +265,7 @@ void __init hyperv_init(void)
 {
u64 guest_id, required_msrs;
union hv_x64_msr_hypercall_contents hypercall_msr;
-   int cpuhp;
+   int cpuhp, i;
 
if (x86_hyper_type != X86_HYPER_MS_HYPERV)
return;
@@ -293,6 +293,9 @@ void __init hyperv_init(void)
if (!hv_vp_index)
return;
 
+   for (i = 0; i < num_possible_cpus(); i++)
+   hv_vp_index[i] = -1;
+
hv_vp_assist_page = kcalloc(num_possible_cpus(),
sizeof(*hv_vp_assist_page), GFP_KERNEL);
if (!hv_vp_assist_page) {
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 3cd14311edfa..dee3f7347253 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -281,6 +281,8 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset,
 */
for_each_cpu(cpu, cpus) {
vcpu = hv_cpu_number_to_vp_number(cpu);
+   if (vcpu == -1)
+   return -1;
vcpu_bank = vcpu / 64;
vcpu_offset = vcpu % 64;
__set_bit(vcpu_offset, (unsigned long *)
-- 
2.17.1



[PATCH 1/1] X86: Fix the circular dependency in IPI enlightenment.

2018-07-03 Thread kys
From: "K. Y. Srinivasan" 

The IPI hypercalls depend on being able to map the Linux notion of CPU ID
to the hypervisor's notion of the CPU ID. The array hv_vp_index[] provides
this mapping. Code for populating this array depends on the IPI functionality.
Break this circular dependency.

Fixes: 68bb7bfb7985 ("X86/Hyper-V: Enable IPI enlightenments")

Signed-off-by: K. Y. Srinivasan 
Tested-by: Michael Kelley 
---
 arch/x86/hyperv/hv_apic.c   | 5 +
 arch/x86/hyperv/hv_init.c   | 3 +++
 arch/x86/include/asm/mshyperv.h | 2 ++
 3 files changed, 10 insertions(+)

diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c
index f68855499391..63d7c196739f 100644
--- a/arch/x86/hyperv/hv_apic.c
+++ b/arch/x86/hyperv/hv_apic.c
@@ -114,6 +114,8 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, 
int vector)
ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K;
nr_bank = cpumask_to_vpset(&(ipi_arg->vp_set), mask);
}
+   if (nr_bank == -1)
+   goto ipi_mask_ex_done;
if (!nr_bank)
ipi_arg->vp_set.format = HV_GENERIC_SET_ALL;
 
@@ -158,6 +160,9 @@ static bool __send_ipi_mask(const struct cpumask *mask, int 
vector)
 
for_each_cpu(cur_cpu, mask) {
vcpu = hv_cpu_number_to_vp_number(cur_cpu);
+   if (vcpu == -1)
+   goto ipi_mask_done;
+
/*
 * This particular version of the IPI hypercall can
 * only target upto 64 CPUs.
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 595e44e8abaa..762ce164d733 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -293,6 +293,9 @@ void __init hyperv_init(void)
if (!hv_vp_index)
return;
 
+   for (i = 0; i < num_possible_cpus(); i++)
+   hv_vp_index[i] = -1;
+
hv_vp_assist_page = kcalloc(num_possible_cpus(),
sizeof(*hv_vp_assist_page), GFP_KERNEL);
if (!hv_vp_assist_page) {
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 81e768b8d9eb..299de3dcc319 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -285,6 +285,8 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset,
 */
for_each_cpu(cpu, cpus) {
vcpu = hv_cpu_number_to_vp_number(cpu);
+   if (vcpu == -1)
+   return -1;
vcpu_bank = vcpu / 64;
vcpu_offset = vcpu % 64;
__set_bit(vcpu_offset, (unsigned long *)
-- 
2.17.1



[PATCH 1/1] X86: Fix the circular dependency in IPI enlightenment.

2018-07-03 Thread kys
From: "K. Y. Srinivasan" 

The IPI hypercalls depend on being able to map the Linux notion of CPU ID
to the hypervisor's notion of the CPU ID. The array hv_vp_index[] provides
this mapping. Code for populating this array depends on the IPI functionality.
Break this circular dependency.

Fixes: 68bb7bfb7985 ("X86/Hyper-V: Enable IPI enlightenments")

Signed-off-by: K. Y. Srinivasan 
Tested-by: Michael Kelley 
---
 arch/x86/hyperv/hv_apic.c   | 5 +
 arch/x86/hyperv/hv_init.c   | 3 +++
 arch/x86/include/asm/mshyperv.h | 2 ++
 3 files changed, 10 insertions(+)

diff --git a/arch/x86/hyperv/hv_apic.c b/arch/x86/hyperv/hv_apic.c
index f68855499391..63d7c196739f 100644
--- a/arch/x86/hyperv/hv_apic.c
+++ b/arch/x86/hyperv/hv_apic.c
@@ -114,6 +114,8 @@ static bool __send_ipi_mask_ex(const struct cpumask *mask, 
int vector)
ipi_arg->vp_set.format = HV_GENERIC_SET_SPARSE_4K;
nr_bank = cpumask_to_vpset(&(ipi_arg->vp_set), mask);
}
+   if (nr_bank == -1)
+   goto ipi_mask_ex_done;
if (!nr_bank)
ipi_arg->vp_set.format = HV_GENERIC_SET_ALL;
 
@@ -158,6 +160,9 @@ static bool __send_ipi_mask(const struct cpumask *mask, int 
vector)
 
for_each_cpu(cur_cpu, mask) {
vcpu = hv_cpu_number_to_vp_number(cur_cpu);
+   if (vcpu == -1)
+   goto ipi_mask_done;
+
/*
 * This particular version of the IPI hypercall can
 * only target upto 64 CPUs.
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 595e44e8abaa..762ce164d733 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -293,6 +293,9 @@ void __init hyperv_init(void)
if (!hv_vp_index)
return;
 
+   for (i = 0; i < num_possible_cpus(); i++)
+   hv_vp_index[i] = -1;
+
hv_vp_assist_page = kcalloc(num_possible_cpus(),
sizeof(*hv_vp_assist_page), GFP_KERNEL);
if (!hv_vp_assist_page) {
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 81e768b8d9eb..299de3dcc319 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -285,6 +285,8 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset,
 */
for_each_cpu(cpu, cpus) {
vcpu = hv_cpu_number_to_vp_number(cpu);
+   if (vcpu == -1)
+   return -1;
vcpu_bank = vcpu / 64;
vcpu_offset = vcpu % 64;
__set_bit(vcpu_offset, (unsigned long *)
-- 
2.17.1



  1   2   3   4   5   6   7   8   9   >