Skip to content

Commit f56dbdd

Browse files
committed
Merge tag 'hyperv-next-signed-20220528' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux
Pull hyperv updates from Wei Liu: - Harden hv_sock driver (Andrea Parri) - Harden Hyper-V PCI driver (Andrea Parri) - Fix multi-MSI for Hyper-V PCI driver (Jeffrey Hugo) - Fix Hyper-V PCI to reduce boot time (Dexuan Cui) - Remove code for long EOL'ed Hyper-V versions (Michael Kelley, Saurabh Sengar) - Fix balloon driver error handling (Shradha Gupta) - Fix a typo in vmbus driver (Julia Lawall) - Ignore vmbus IMC device (Michael Kelley) - Add a new error message to Hyper-V DRM driver (Saurabh Sengar) * tag 'hyperv-next-signed-20220528' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: (28 commits) hv_balloon: Fix balloon_probe() and balloon_remove() error handling scsi: storvsc: Removing Pre Win8 related logic Drivers: hv: vmbus: fix typo in comment PCI: hv: Fix synchronization between channel callback and hv_pci_bus_exit() PCI: hv: Add validation for untrusted Hyper-V values PCI: hv: Fix interrupt mapping for multi-MSI PCI: hv: Reuse existing IRTE allocation in compose_msi_msg() drm/hyperv: Remove support for Hyper-V 2008 and 2008R2/Win7 video: hyperv_fb: Remove support for Hyper-V 2008 and 2008R2/Win7 scsi: storvsc: Remove support for Hyper-V 2008 and 2008R2/Win7 Drivers: hv: vmbus: Remove support for Hyper-V 2008 and Hyper-V 2008R2/Win7 x86/hyperv: Disable hardlockup detector by default in Hyper-V guests drm/hyperv: Add error message for fb size greater than allocated PCI: hv: Do not set PCI_COMMAND_MEMORY to reduce VM boot time PCI: hv: Fix hv_arch_irq_unmask() for multi-MSI Drivers: hv: vmbus: Refactor the ring-buffer iterator functions Drivers: hv: vmbus: Accept hv_sock offers in isolated guests hv_sock: Add validation for untrusted Hyper-V values hv_sock: Copy packets sent by Hyper-V out of the ring buffer hv_sock: Check hv_pkt_iter_first_raw()'s return value ...
2 parents 6112bd0 + d27423b commit f56dbdd

15 files changed

Lines changed: 477 additions & 419 deletions

File tree

arch/x86/kernel/cpu/mshyperv.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,8 @@ static void __init ms_hyperv_init_platform(void)
457457
*/
458458
if (!(ms_hyperv.features & HV_ACCESS_TSC_INVARIANT))
459459
mark_tsc_unstable("running on Hyper-V");
460+
461+
hardlockup_detector_disable();
460462
}
461463

462464
static bool __init ms_hyperv_x2apic_available(void)

drivers/gpu/drm/hyperv/hyperv_drm_modeset.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,11 @@ static int hyperv_pipe_check(struct drm_simple_display_pipe *pipe,
123123
if (fb->format->format != DRM_FORMAT_XRGB8888)
124124
return -EINVAL;
125125

126-
if (fb->pitches[0] * fb->height > hv->fb_size)
126+
if (fb->pitches[0] * fb->height > hv->fb_size) {
127+
drm_err(&hv->dev, "fb size requested by %s for %dX%d (pitch %d) greater than %ld\n",
128+
current->comm, fb->width, fb->height, fb->pitches[0], hv->fb_size);
127129
return -EINVAL;
130+
}
128131

129132
return 0;
130133
}

drivers/gpu/drm/hyperv/hyperv_drm_proto.c

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@
1818
#define SYNTHVID_VERSION(major, minor) ((minor) << 16 | (major))
1919
#define SYNTHVID_VER_GET_MAJOR(ver) (ver & 0x0000ffff)
2020
#define SYNTHVID_VER_GET_MINOR(ver) ((ver & 0xffff0000) >> 16)
21+
22+
/* Support for VERSION_WIN7 is removed. #define is retained for reference. */
2123
#define SYNTHVID_VERSION_WIN7 SYNTHVID_VERSION(3, 0)
2224
#define SYNTHVID_VERSION_WIN8 SYNTHVID_VERSION(3, 2)
2325
#define SYNTHVID_VERSION_WIN10 SYNTHVID_VERSION(3, 5)
2426

25-
#define SYNTHVID_DEPTH_WIN7 16
2627
#define SYNTHVID_DEPTH_WIN8 32
27-
#define SYNTHVID_FB_SIZE_WIN7 (4 * 1024 * 1024)
28+
#define SYNTHVID_WIDTH_WIN8 1600
29+
#define SYNTHVID_HEIGHT_WIN8 1200
2830
#define SYNTHVID_FB_SIZE_WIN8 (8 * 1024 * 1024)
29-
#define SYNTHVID_WIDTH_MAX_WIN7 1600
30-
#define SYNTHVID_HEIGHT_MAX_WIN7 1200
3131

3232
enum pipe_msg_type {
3333
PIPE_MSG_INVALID,
@@ -496,12 +496,6 @@ int hyperv_connect_vsp(struct hv_device *hdev)
496496
case VERSION_WIN8:
497497
case VERSION_WIN8_1:
498498
ret = hyperv_negotiate_version(hdev, SYNTHVID_VERSION_WIN8);
499-
if (!ret)
500-
break;
501-
fallthrough;
502-
case VERSION_WS2008:
503-
case VERSION_WIN7:
504-
ret = hyperv_negotiate_version(hdev, SYNTHVID_VERSION_WIN7);
505499
break;
506500
default:
507501
ret = hyperv_negotiate_version(hdev, SYNTHVID_VERSION_WIN10);
@@ -513,18 +507,15 @@ int hyperv_connect_vsp(struct hv_device *hdev)
513507
goto error;
514508
}
515509

516-
if (hv->synthvid_version == SYNTHVID_VERSION_WIN7)
517-
hv->screen_depth = SYNTHVID_DEPTH_WIN7;
518-
else
519-
hv->screen_depth = SYNTHVID_DEPTH_WIN8;
510+
hv->screen_depth = SYNTHVID_DEPTH_WIN8;
520511

521512
if (hyperv_version_ge(hv->synthvid_version, SYNTHVID_VERSION_WIN10)) {
522513
ret = hyperv_get_supported_resolution(hdev);
523514
if (ret)
524515
drm_err(dev, "Failed to get supported resolution from host, use default\n");
525516
} else {
526-
hv->screen_width_max = SYNTHVID_WIDTH_MAX_WIN7;
527-
hv->screen_height_max = SYNTHVID_HEIGHT_MAX_WIN7;
517+
hv->screen_width_max = SYNTHVID_WIDTH_WIN8;
518+
hv->screen_height_max = SYNTHVID_HEIGHT_WIN8;
528519
}
529520

530521
hv->mmio_megabytes = hdev->channel->offermsg.offer.mmio_megabytes;

drivers/hv/channel.c

Lines changed: 86 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,11 +1022,13 @@ void vmbus_close(struct vmbus_channel *channel)
10221022
EXPORT_SYMBOL_GPL(vmbus_close);
10231023

10241024
/**
1025-
* vmbus_sendpacket() - Send the specified buffer on the given channel
1025+
* vmbus_sendpacket_getid() - Send the specified buffer on the given channel
10261026
* @channel: Pointer to vmbus_channel structure
10271027
* @buffer: Pointer to the buffer you want to send the data from.
10281028
* @bufferlen: Maximum size of what the buffer holds.
10291029
* @requestid: Identifier of the request
1030+
* @trans_id: Identifier of the transaction associated to this request, if
1031+
* the send is successful; undefined, otherwise.
10301032
* @type: Type of packet that is being sent e.g. negotiate, time
10311033
* packet etc.
10321034
* @flags: 0 or VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
@@ -1036,8 +1038,8 @@ EXPORT_SYMBOL_GPL(vmbus_close);
10361038
*
10371039
* Mainly used by Hyper-V drivers.
10381040
*/
1039-
int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
1040-
u32 bufferlen, u64 requestid,
1041+
int vmbus_sendpacket_getid(struct vmbus_channel *channel, void *buffer,
1042+
u32 bufferlen, u64 requestid, u64 *trans_id,
10411043
enum vmbus_packet_type type, u32 flags)
10421044
{
10431045
struct vmpacket_descriptor desc;
@@ -1063,7 +1065,31 @@ int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
10631065
bufferlist[2].iov_base = &aligned_data;
10641066
bufferlist[2].iov_len = (packetlen_aligned - packetlen);
10651067

1066-
return hv_ringbuffer_write(channel, bufferlist, num_vecs, requestid);
1068+
return hv_ringbuffer_write(channel, bufferlist, num_vecs, requestid, trans_id);
1069+
}
1070+
EXPORT_SYMBOL(vmbus_sendpacket_getid);
1071+
1072+
/**
1073+
* vmbus_sendpacket() - Send the specified buffer on the given channel
1074+
* @channel: Pointer to vmbus_channel structure
1075+
* @buffer: Pointer to the buffer you want to send the data from.
1076+
* @bufferlen: Maximum size of what the buffer holds.
1077+
* @requestid: Identifier of the request
1078+
* @type: Type of packet that is being sent e.g. negotiate, time
1079+
* packet etc.
1080+
* @flags: 0 or VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED
1081+
*
1082+
* Sends data in @buffer directly to Hyper-V via the vmbus.
1083+
* This will send the data unparsed to Hyper-V.
1084+
*
1085+
* Mainly used by Hyper-V drivers.
1086+
*/
1087+
int vmbus_sendpacket(struct vmbus_channel *channel, void *buffer,
1088+
u32 bufferlen, u64 requestid,
1089+
enum vmbus_packet_type type, u32 flags)
1090+
{
1091+
return vmbus_sendpacket_getid(channel, buffer, bufferlen,
1092+
requestid, NULL, type, flags);
10671093
}
10681094
EXPORT_SYMBOL(vmbus_sendpacket);
10691095

@@ -1122,7 +1148,7 @@ int vmbus_sendpacket_pagebuffer(struct vmbus_channel *channel,
11221148
bufferlist[2].iov_base = &aligned_data;
11231149
bufferlist[2].iov_len = (packetlen_aligned - packetlen);
11241150

1125-
return hv_ringbuffer_write(channel, bufferlist, 3, requestid);
1151+
return hv_ringbuffer_write(channel, bufferlist, 3, requestid, NULL);
11261152
}
11271153
EXPORT_SYMBOL_GPL(vmbus_sendpacket_pagebuffer);
11281154

@@ -1160,7 +1186,7 @@ int vmbus_sendpacket_mpb_desc(struct vmbus_channel *channel,
11601186
bufferlist[2].iov_base = &aligned_data;
11611187
bufferlist[2].iov_len = (packetlen_aligned - packetlen);
11621188

1163-
return hv_ringbuffer_write(channel, bufferlist, 3, requestid);
1189+
return hv_ringbuffer_write(channel, bufferlist, 3, requestid, NULL);
11641190
}
11651191
EXPORT_SYMBOL_GPL(vmbus_sendpacket_mpb_desc);
11661192

@@ -1226,12 +1252,12 @@ u64 vmbus_next_request_id(struct vmbus_channel *channel, u64 rqst_addr)
12261252
if (!channel->rqstor_size)
12271253
return VMBUS_NO_RQSTOR;
12281254

1229-
spin_lock_irqsave(&rqstor->req_lock, flags);
1255+
lock_requestor(channel, flags);
12301256
current_id = rqstor->next_request_id;
12311257

12321258
/* Requestor array is full */
12331259
if (current_id >= rqstor->size) {
1234-
spin_unlock_irqrestore(&rqstor->req_lock, flags);
1260+
unlock_requestor(channel, flags);
12351261
return VMBUS_RQST_ERROR;
12361262
}
12371263

@@ -1241,27 +1267,23 @@ u64 vmbus_next_request_id(struct vmbus_channel *channel, u64 rqst_addr)
12411267
/* The already held spin lock provides atomicity */
12421268
bitmap_set(rqstor->req_bitmap, current_id, 1);
12431269

1244-
spin_unlock_irqrestore(&rqstor->req_lock, flags);
1270+
unlock_requestor(channel, flags);
12451271

12461272
/*
12471273
* Cannot return an ID of 0, which is reserved for an unsolicited
1248-
* message from Hyper-V.
1274+
* message from Hyper-V; Hyper-V does not acknowledge (respond to)
1275+
* VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED requests with ID of
1276+
* 0 sent by the guest.
12491277
*/
12501278
return current_id + 1;
12511279
}
12521280
EXPORT_SYMBOL_GPL(vmbus_next_request_id);
12531281

1254-
/*
1255-
* vmbus_request_addr - Returns the memory address stored at @trans_id
1256-
* in @rqstor. Uses a spin lock to avoid race conditions.
1257-
* @channel: Pointer to the VMbus channel struct
1258-
* @trans_id: Request id sent back from Hyper-V. Becomes the requestor's
1259-
* next request id.
1260-
*/
1261-
u64 vmbus_request_addr(struct vmbus_channel *channel, u64 trans_id)
1282+
/* As in vmbus_request_addr_match() but without the requestor lock */
1283+
u64 __vmbus_request_addr_match(struct vmbus_channel *channel, u64 trans_id,
1284+
u64 rqst_addr)
12621285
{
12631286
struct vmbus_requestor *rqstor = &channel->requestor;
1264-
unsigned long flags;
12651287
u64 req_addr;
12661288

12671289
/* Check rqstor has been initialized */
@@ -1270,27 +1292,61 @@ u64 vmbus_request_addr(struct vmbus_channel *channel, u64 trans_id)
12701292

12711293
/* Hyper-V can send an unsolicited message with ID of 0 */
12721294
if (!trans_id)
1273-
return trans_id;
1274-
1275-
spin_lock_irqsave(&rqstor->req_lock, flags);
1295+
return VMBUS_RQST_ERROR;
12761296

12771297
/* Data corresponding to trans_id is stored at trans_id - 1 */
12781298
trans_id--;
12791299

12801300
/* Invalid trans_id */
1281-
if (trans_id >= rqstor->size || !test_bit(trans_id, rqstor->req_bitmap)) {
1282-
spin_unlock_irqrestore(&rqstor->req_lock, flags);
1301+
if (trans_id >= rqstor->size || !test_bit(trans_id, rqstor->req_bitmap))
12831302
return VMBUS_RQST_ERROR;
1284-
}
12851303

12861304
req_addr = rqstor->req_arr[trans_id];
1287-
rqstor->req_arr[trans_id] = rqstor->next_request_id;
1288-
rqstor->next_request_id = trans_id;
1305+
if (rqst_addr == VMBUS_RQST_ADDR_ANY || req_addr == rqst_addr) {
1306+
rqstor->req_arr[trans_id] = rqstor->next_request_id;
1307+
rqstor->next_request_id = trans_id;
12891308

1290-
/* The already held spin lock provides atomicity */
1291-
bitmap_clear(rqstor->req_bitmap, trans_id, 1);
1309+
/* The already held spin lock provides atomicity */
1310+
bitmap_clear(rqstor->req_bitmap, trans_id, 1);
1311+
}
12921312

1293-
spin_unlock_irqrestore(&rqstor->req_lock, flags);
12941313
return req_addr;
12951314
}
1315+
EXPORT_SYMBOL_GPL(__vmbus_request_addr_match);
1316+
1317+
/*
1318+
* vmbus_request_addr_match - Clears/removes @trans_id from the @channel's
1319+
* requestor, provided the memory address stored at @trans_id equals @rqst_addr
1320+
* (or provided @rqst_addr matches the sentinel value VMBUS_RQST_ADDR_ANY).
1321+
*
1322+
* Returns the memory address stored at @trans_id, or VMBUS_RQST_ERROR if
1323+
* @trans_id is not contained in the requestor.
1324+
*
1325+
* Acquires and releases the requestor spin lock.
1326+
*/
1327+
u64 vmbus_request_addr_match(struct vmbus_channel *channel, u64 trans_id,
1328+
u64 rqst_addr)
1329+
{
1330+
unsigned long flags;
1331+
u64 req_addr;
1332+
1333+
lock_requestor(channel, flags);
1334+
req_addr = __vmbus_request_addr_match(channel, trans_id, rqst_addr);
1335+
unlock_requestor(channel, flags);
1336+
1337+
return req_addr;
1338+
}
1339+
EXPORT_SYMBOL_GPL(vmbus_request_addr_match);
1340+
1341+
/*
1342+
* vmbus_request_addr - Returns the memory address stored at @trans_id
1343+
* in @rqstor. Uses a spin lock to avoid race conditions.
1344+
* @channel: Pointer to the VMbus channel struct
1345+
* @trans_id: Request id sent back from Hyper-V. Becomes the requestor's
1346+
* next request id.
1347+
*/
1348+
u64 vmbus_request_addr(struct vmbus_channel *channel, u64 trans_id)
1349+
{
1350+
return vmbus_request_addr_match(channel, trans_id, VMBUS_RQST_ADDR_ANY);
1351+
}
12961352
EXPORT_SYMBOL_GPL(vmbus_request_addr);

drivers/hv/channel_mgmt.c

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ static const struct {
152152
{ HV_AVMA1_GUID },
153153
{ HV_AVMA2_GUID },
154154
{ HV_RDV_GUID },
155+
{ HV_IMC_GUID },
155156
};
156157

157158
/*
@@ -442,7 +443,7 @@ void hv_process_channel_removal(struct vmbus_channel *channel)
442443
/*
443444
* Upon suspend, an in-use hv_sock channel is removed from the array of
444445
* channels and the relid is invalidated. After hibernation, when the
445-
* user-space appplication destroys the channel, it's unnecessary and
446+
* user-space application destroys the channel, it's unnecessary and
446447
* unsafe to remove the channel from the array of channels. See also
447448
* the inline comments before the call of vmbus_release_relid() below.
448449
*/
@@ -713,15 +714,13 @@ static bool hv_cpuself_used(u32 cpu, struct vmbus_channel *chn)
713714
static int next_numa_node_id;
714715

715716
/*
716-
* Starting with Win8, we can statically distribute the incoming
717-
* channel interrupt load by binding a channel to VCPU.
717+
* We can statically distribute the incoming channel interrupt load
718+
* by binding a channel to VCPU.
718719
*
719-
* For pre-win8 hosts or non-performance critical channels we assign the
720-
* VMBUS_CONNECT_CPU.
721-
*
722-
* Starting with win8, performance critical channels will be distributed
723-
* evenly among all the available NUMA nodes. Once the node is assigned,
724-
* we will assign the CPU based on a simple round robin scheme.
720+
* For non-performance critical channels we assign the VMBUS_CONNECT_CPU.
721+
* Performance critical channels will be distributed evenly among all
722+
* the available NUMA nodes. Once the node is assigned, we will assign
723+
* the CPU based on a simple round robin scheme.
725724
*/
726725
static void init_vp_index(struct vmbus_channel *channel)
727726
{
@@ -732,13 +731,10 @@ static void init_vp_index(struct vmbus_channel *channel)
732731
u32 target_cpu;
733732
int numa_node;
734733

735-
if ((vmbus_proto_version == VERSION_WS2008) ||
736-
(vmbus_proto_version == VERSION_WIN7) || (!perf_chn) ||
734+
if (!perf_chn ||
737735
!alloc_cpumask_var(&available_mask, GFP_KERNEL)) {
738736
/*
739-
* Prior to win8, all channel interrupts are
740-
* delivered on VMBUS_CONNECT_CPU.
741-
* Also if the channel is not a performance critical
737+
* If the channel is not a performance critical
742738
* channel, bind it to VMBUS_CONNECT_CPU.
743739
* In case alloc_cpumask_var() fails, bind it to
744740
* VMBUS_CONNECT_CPU.
@@ -931,11 +927,9 @@ static void vmbus_setup_channel_state(struct vmbus_channel *channel,
931927
*/
932928
channel->sig_event = VMBUS_EVENT_CONNECTION_ID;
933929

934-
if (vmbus_proto_version != VERSION_WS2008) {
935-
channel->is_dedicated_interrupt =
936-
(offer->is_dedicated_interrupt != 0);
937-
channel->sig_event = offer->connection_id;
938-
}
930+
channel->is_dedicated_interrupt =
931+
(offer->is_dedicated_interrupt != 0);
932+
channel->sig_event = offer->connection_id;
939933

940934
memcpy(&channel->offermsg, offer,
941935
sizeof(struct vmbus_channel_offer_channel));
@@ -975,13 +969,17 @@ find_primary_channel_by_offer(const struct vmbus_channel_offer_channel *offer)
975969
return channel;
976970
}
977971

978-
static bool vmbus_is_valid_device(const guid_t *guid)
972+
static bool vmbus_is_valid_offer(const struct vmbus_channel_offer_channel *offer)
979973
{
974+
const guid_t *guid = &offer->offer.if_type;
980975
u16 i;
981976

982977
if (!hv_is_isolation_supported())
983978
return true;
984979

980+
if (is_hvsock_offer(offer))
981+
return true;
982+
985983
for (i = 0; i < ARRAY_SIZE(vmbus_devs); i++) {
986984
if (guid_equal(guid, &vmbus_devs[i].guid))
987985
return vmbus_devs[i].allowed_in_isolated;
@@ -1003,7 +1001,7 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
10031001

10041002
trace_vmbus_onoffer(offer);
10051003

1006-
if (!vmbus_is_valid_device(&offer->offer.if_type)) {
1004+
if (!vmbus_is_valid_offer(offer)) {
10071005
pr_err_ratelimited("Invalid offer %d from the host supporting isolation\n",
10081006
offer->child_relid);
10091007
atomic_dec(&vmbus_connection.offer_in_progress);

drivers/hv/connection.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ EXPORT_SYMBOL_GPL(vmbus_proto_version);
4747

4848
/*
4949
* Table of VMBus versions listed from newest to oldest.
50+
* VERSION_WIN7 and VERSION_WS2008 are no longer supported in
51+
* Linux guests and are not listed.
5052
*/
5153
static __u32 vmbus_versions[] = {
5254
VERSION_WIN10_V5_3,
@@ -56,9 +58,7 @@ static __u32 vmbus_versions[] = {
5658
VERSION_WIN10_V4_1,
5759
VERSION_WIN10,
5860
VERSION_WIN8_1,
59-
VERSION_WIN8,
60-
VERSION_WIN7,
61-
VERSION_WS2008
61+
VERSION_WIN8
6262
};
6363

6464
/*

0 commit comments

Comments
 (0)