[PATCH 1/4] Drivers: hv: vmbus: Remove support for Hyper-V 2008 and Hyper-V 2008R2/Win7

From: Michael Kelley
Date: Mon May 02 2022 - 12:37:16 EST


The VMbus driver has special case code for running on the first released
versions of Hyper-V: 2008 and 2008 R2/Windows 7. These versions are now
out of support (except for extended security updates) and lack the
performance features needed for effective production usage of Linux
guests.

Simplify the code by removing the negotiation of the VMbus protocol
versions required for these releases of Hyper-V, and by removing the
special case code for handling these VMbus protocol versions.

Signed-off-by: Michael Kelley <mikelley@xxxxxxxxxxxxx>
---
drivers/hv/channel_mgmt.c | 29 +++++++++--------------
drivers/hv/connection.c | 6 ++---
drivers/hv/vmbus_drv.c | 60 ++++++++++-------------------------------------
include/linux/hyperv.h | 10 +++++---
4 files changed, 33 insertions(+), 72 deletions(-)

diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 85a2142..575459a 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -713,15 +713,13 @@ static bool hv_cpuself_used(u32 cpu, struct vmbus_channel *chn)
static int next_numa_node_id;

/*
- * Starting with Win8, we can statically distribute the incoming
- * channel interrupt load by binding a channel to VCPU.
+ * We can statically distribute the incoming channel interrupt load
+ * by binding a channel to VCPU.
*
- * For pre-win8 hosts or non-performance critical channels we assign the
- * VMBUS_CONNECT_CPU.
- *
- * Starting with win8, performance critical channels will be distributed
- * evenly among all the available NUMA nodes. Once the node is assigned,
- * we will assign the CPU based on a simple round robin scheme.
+ * For non-performance critical channels we assign the VMBUS_CONNECT_CPU.
+ * Performance critical channels will be distributed evenly among all
+ * the available NUMA nodes. Once the node is assigned, we will assign
+ * the CPU based on a simple round robin scheme.
*/
static void init_vp_index(struct vmbus_channel *channel)
{
@@ -732,13 +730,10 @@ static void init_vp_index(struct vmbus_channel *channel)
u32 target_cpu;
int numa_node;

- if ((vmbus_proto_version == VERSION_WS2008) ||
- (vmbus_proto_version == VERSION_WIN7) || (!perf_chn) ||
+ if (!perf_chn ||
!alloc_cpumask_var(&available_mask, GFP_KERNEL)) {
/*
- * Prior to win8, all channel interrupts are
- * delivered on VMBUS_CONNECT_CPU.
- * Also if the channel is not a performance critical
+ * If the channel is not a performance critical
* channel, bind it to VMBUS_CONNECT_CPU.
* In case alloc_cpumask_var() fails, bind it to
* VMBUS_CONNECT_CPU.
@@ -931,11 +926,9 @@ static void vmbus_setup_channel_state(struct vmbus_channel *channel,
*/
channel->sig_event = VMBUS_EVENT_CONNECTION_ID;

- if (vmbus_proto_version != VERSION_WS2008) {
- channel->is_dedicated_interrupt =
- (offer->is_dedicated_interrupt != 0);
- channel->sig_event = offer->connection_id;
- }
+ channel->is_dedicated_interrupt =
+ (offer->is_dedicated_interrupt != 0);
+ channel->sig_event = offer->connection_id;

memcpy(&channel->offermsg, offer,
sizeof(struct vmbus_channel_offer_channel));
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index a3d8be8..6218bbf 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -47,6 +47,8 @@ struct vmbus_connection vmbus_connection = {

/*
* Table of VMBus versions listed from newest to oldest.
+ * VERSION_WIN7 and VERSION_WS2008 are no longer supported in
+ * Linux guests and are not listed.
*/
static __u32 vmbus_versions[] = {
VERSION_WIN10_V5_3,
@@ -56,9 +58,7 @@ struct vmbus_connection vmbus_connection = {
VERSION_WIN10_V4_1,
VERSION_WIN10,
VERSION_WIN8_1,
- VERSION_WIN8,
- VERSION_WIN7,
- VERSION_WS2008
+ VERSION_WIN8
};

/*
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 14de170..9c1b3620 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1263,23 +1263,17 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu)
unsigned long *recv_int_page;
u32 maxbits, relid;

- if (vmbus_proto_version < VERSION_WIN8) {
- maxbits = MAX_NUM_CHANNELS_SUPPORTED;
- recv_int_page = vmbus_connection.recv_int_page;
- } else {
- /*
- * When the host is win8 and beyond, the event page
- * can be directly checked to get the id of the channel
- * that has the interrupt pending.
- */
- void *page_addr = hv_cpu->synic_event_page;
- union hv_synic_event_flags *event
- = (union hv_synic_event_flags *)page_addr +
- VMBUS_MESSAGE_SINT;
+ /*
+ * The event page can be directly checked to get the id of
+ * the channel that has the interrupt pending.
+ */
+ void *page_addr = hv_cpu->synic_event_page;
+ union hv_synic_event_flags *event
+ = (union hv_synic_event_flags *)page_addr +
+ VMBUS_MESSAGE_SINT;

- maxbits = HV_EVENT_FLAGS_COUNT;
- recv_int_page = event->flags;
- }
+ maxbits = HV_EVENT_FLAGS_COUNT;
+ recv_int_page = event->flags;

if (unlikely(!recv_int_page))
return;
@@ -1351,40 +1345,10 @@ static void vmbus_isr(void)
{
struct hv_per_cpu_context *hv_cpu
= this_cpu_ptr(hv_context.cpu_context);
- void *page_addr = hv_cpu->synic_event_page;
+ void *page_addr;
struct hv_message *msg;
- union hv_synic_event_flags *event;
- bool handled = false;
-
- if (unlikely(page_addr == NULL))
- return;
-
- event = (union hv_synic_event_flags *)page_addr +
- VMBUS_MESSAGE_SINT;
- /*
- * Check for events before checking for messages. This is the order
- * in which events and messages are checked in Windows guests on
- * Hyper-V, and the Windows team suggested we do the same.
- */
-
- if ((vmbus_proto_version == VERSION_WS2008) ||
- (vmbus_proto_version == VERSION_WIN7)) {
-
- /* Since we are a child, we only need to check bit 0 */
- if (sync_test_and_clear_bit(0, event->flags))
- handled = true;
- } else {
- /*
- * Our host is win8 or above. The signaling mechanism
- * has changed and we can directly look at the event page.
- * If bit n is set then we have an interrup on the channel
- * whose id is n.
- */
- handled = true;
- }

- if (handled)
- vmbus_chan_sched(hv_cpu);
+ vmbus_chan_sched(hv_cpu);

page_addr = hv_cpu->synic_message_page;
msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT;
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index fe2e017..9a4ac13 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -230,15 +230,19 @@ static inline u32 hv_get_avail_to_write_percent(
* two 16 bit quantities: major_number. minor_number.
*
* 0 . 13 (Windows Server 2008)
- * 1 . 1 (Windows 7)
- * 2 . 4 (Windows 8)
- * 3 . 0 (Windows 8 R2)
+ * 1 . 1 (Windows 7, WS2008 R2)
+ * 2 . 4 (Windows 8, WS2012)
+ * 3 . 0 (Windows 8.1, WS2012 R2)
* 4 . 0 (Windows 10)
* 4 . 1 (Windows 10 RS3)
* 5 . 0 (Newer Windows 10)
* 5 . 1 (Windows 10 RS4)
* 5 . 2 (Windows Server 2019, RS5)
* 5 . 3 (Windows Server 2022)
+ *
+ * The WS2008 and WIN7 versions are listed here for
+ * completeness but are no longer supported in the
+ * Linux kernel.
*/

#define VERSION_WS2008 ((0 << 16) | (13))
--
1.8.3.1