1 /* 2 * Copyright (c) 2009, Microsoft Corporation. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms and conditions of the GNU General Public License, 6 * version 2, as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * more details. 12 * 13 * You should have received a copy of the GNU General Public License along with 14 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 15 * Place - Suite 330, Boston, MA 02111-1307 USA. 16 * 17 * Authors: 18 * Haiyang Zhang <haiyangz@microsoft.com> 19 * Hank Janssen <hjanssen@microsoft.com> 20 */ 21 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 22 23 #include <linux/kernel.h> 24 #include <linux/sched.h> 25 #include <linux/wait.h> 26 #include <linux/mm.h> 27 #include <linux/slab.h> 28 #include <linux/list.h> 29 #include <linux/module.h> 30 #include <linux/completion.h> 31 #include <linux/hyperv.h> 32 33 #include "hyperv_vmbus.h" 34 35 struct vmbus_channel_message_table_entry { 36 enum vmbus_channel_message_type message_type; 37 void (*message_handler)(struct vmbus_channel_message_header *msg); 38 }; 39 40 41 /** 42 * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message 43 * @icmsghdrp: Pointer to msg header structure 44 * @icmsg_negotiate: Pointer to negotiate message structure 45 * @buf: Raw buffer channel data 46 * 47 * @icmsghdrp is of type &struct icmsg_hdr. 48 * @negop is of type &struct icmsg_negotiate. 49 * Set up and fill in default negotiate response message. This response can 50 * come from both the vmbus driver and the hv_utils driver. The current api 51 * will respond properly to both Windows 2008 and Windows 2008-R2 operating 52 * systems. 53 * 54 * Mainly used by Hyper-V drivers. 55 */ 56 void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, 57 struct icmsg_negotiate *negop, u8 *buf) 58 { 59 if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { 60 icmsghdrp->icmsgsize = 0x10; 61 62 negop = (struct icmsg_negotiate *)&buf[ 63 sizeof(struct vmbuspipe_hdr) + 64 sizeof(struct icmsg_hdr)]; 65 66 if (negop->icframe_vercnt == 2 && 67 negop->icversion_data[1].major == 3) { 68 negop->icversion_data[0].major = 3; 69 negop->icversion_data[0].minor = 0; 70 negop->icversion_data[1].major = 3; 71 negop->icversion_data[1].minor = 0; 72 } else { 73 negop->icversion_data[0].major = 1; 74 negop->icversion_data[0].minor = 0; 75 negop->icversion_data[1].major = 1; 76 negop->icversion_data[1].minor = 0; 77 } 78 79 negop->icframe_vercnt = 1; 80 negop->icmsg_vercnt = 1; 81 } 82 } 83 EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); 84 85 /* 86 * alloc_channel - Allocate and initialize a vmbus channel object 87 */ 88 static struct vmbus_channel *alloc_channel(void) 89 { 90 struct vmbus_channel *channel; 91 92 channel = kzalloc(sizeof(*channel), GFP_ATOMIC); 93 if (!channel) 94 return NULL; 95 96 spin_lock_init(&channel->inbound_lock); 97 98 channel->controlwq = create_workqueue("hv_vmbus_ctl"); 99 if (!channel->controlwq) { 100 kfree(channel); 101 return NULL; 102 } 103 104 return channel; 105 } 106 107 /* 108 * release_hannel - Release the vmbus channel object itself 109 */ 110 static void release_channel(struct work_struct *work) 111 { 112 struct vmbus_channel *channel = container_of(work, 113 struct vmbus_channel, 114 work); 115 116 destroy_workqueue(channel->controlwq); 117 118 kfree(channel); 119 } 120 121 /* 122 * free_channel - Release the resources used by the vmbus channel object 123 */ 124 static void free_channel(struct vmbus_channel *channel) 125 { 126 127 /* 128 * We have to release the channel's workqueue/thread in the vmbus's 129 * workqueue/thread context 130 * ie we can't destroy ourselves. 131 */ 132 INIT_WORK(&channel->work, release_channel); 133 queue_work(vmbus_connection.work_queue, &channel->work); 134 } 135 136 137 138 /* 139 * vmbus_process_rescind_offer - 140 * Rescind the offer by initiating a device removal 141 */ 142 static void vmbus_process_rescind_offer(struct work_struct *work) 143 { 144 struct vmbus_channel *channel = container_of(work, 145 struct vmbus_channel, 146 work); 147 148 vmbus_device_unregister(channel->device_obj); 149 } 150 151 void vmbus_free_channels(void) 152 { 153 struct vmbus_channel *channel; 154 155 list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { 156 vmbus_device_unregister(channel->device_obj); 157 kfree(channel->device_obj); 158 free_channel(channel); 159 } 160 } 161 162 /* 163 * vmbus_process_offer - Process the offer by creating a channel/device 164 * associated with this offer 165 */ 166 static void vmbus_process_offer(struct work_struct *work) 167 { 168 struct vmbus_channel *newchannel = container_of(work, 169 struct vmbus_channel, 170 work); 171 struct vmbus_channel *channel; 172 bool fnew = true; 173 int ret; 174 unsigned long flags; 175 176 /* The next possible work is rescind handling */ 177 INIT_WORK(&newchannel->work, vmbus_process_rescind_offer); 178 179 /* Make sure this is a new offer */ 180 spin_lock_irqsave(&vmbus_connection.channel_lock, flags); 181 182 list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { 183 if (!uuid_le_cmp(channel->offermsg.offer.if_type, 184 newchannel->offermsg.offer.if_type) && 185 !uuid_le_cmp(channel->offermsg.offer.if_instance, 186 newchannel->offermsg.offer.if_instance)) { 187 fnew = false; 188 break; 189 } 190 } 191 192 if (fnew) 193 list_add_tail(&newchannel->listentry, 194 &vmbus_connection.chn_list); 195 196 spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); 197 198 if (!fnew) { 199 free_channel(newchannel); 200 return; 201 } 202 203 /* 204 * Start the process of binding this offer to the driver 205 * We need to set the DeviceObject field before calling 206 * vmbus_child_dev_add() 207 */ 208 newchannel->device_obj = vmbus_device_create( 209 &newchannel->offermsg.offer.if_type, 210 &newchannel->offermsg.offer.if_instance, 211 newchannel); 212 213 /* 214 * Add the new device to the bus. This will kick off device-driver 215 * binding which eventually invokes the device driver's AddDevice() 216 * method. 217 */ 218 ret = vmbus_device_register(newchannel->device_obj); 219 if (ret != 0) { 220 pr_err("unable to add child device object (relid %d)\n", 221 newchannel->offermsg.child_relid); 222 223 spin_lock_irqsave(&vmbus_connection.channel_lock, flags); 224 list_del(&newchannel->listentry); 225 spin_unlock_irqrestore(&vmbus_connection.channel_lock, flags); 226 kfree(newchannel->device_obj); 227 228 free_channel(newchannel); 229 } else { 230 /* 231 * This state is used to indicate a successful open 232 * so that when we do close the channel normally, we 233 * can cleanup properly 234 */ 235 newchannel->state = CHANNEL_OPEN_STATE; 236 } 237 } 238 239 /* 240 * vmbus_onoffer - Handler for channel offers from vmbus in parent partition. 241 * 242 */ 243 static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) 244 { 245 struct vmbus_channel_offer_channel *offer; 246 struct vmbus_channel *newchannel; 247 uuid_le *guidtype; 248 uuid_le *guidinstance; 249 250 offer = (struct vmbus_channel_offer_channel *)hdr; 251 252 guidtype = &offer->offer.if_type; 253 guidinstance = &offer->offer.if_instance; 254 255 /* Allocate the channel object and save this offer. */ 256 newchannel = alloc_channel(); 257 if (!newchannel) { 258 pr_err("Unable to allocate channel object\n"); 259 return; 260 } 261 262 memcpy(&newchannel->offermsg, offer, 263 sizeof(struct vmbus_channel_offer_channel)); 264 newchannel->monitor_grp = (u8)offer->monitorid / 32; 265 newchannel->monitor_bit = (u8)offer->monitorid % 32; 266 267 INIT_WORK(&newchannel->work, vmbus_process_offer); 268 queue_work(newchannel->controlwq, &newchannel->work); 269 } 270 271 /* 272 * vmbus_onoffer_rescind - Rescind offer handler. 273 * 274 * We queue a work item to process this offer synchronously 275 */ 276 static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) 277 { 278 struct vmbus_channel_rescind_offer *rescind; 279 struct vmbus_channel *channel; 280 281 rescind = (struct vmbus_channel_rescind_offer *)hdr; 282 channel = relid2channel(rescind->child_relid); 283 284 if (channel == NULL) 285 /* Just return here, no channel found */ 286 return; 287 288 /* work is initialized for vmbus_process_rescind_offer() from 289 * vmbus_process_offer() where the channel got created */ 290 queue_work(channel->controlwq, &channel->work); 291 } 292 293 /* 294 * vmbus_onoffers_delivered - 295 * This is invoked when all offers have been delivered. 296 * 297 * Nothing to do here. 298 */ 299 static void vmbus_onoffers_delivered( 300 struct vmbus_channel_message_header *hdr) 301 { 302 } 303 304 /* 305 * vmbus_onopen_result - Open result handler. 306 * 307 * This is invoked when we received a response to our channel open request. 308 * Find the matching request, copy the response and signal the requesting 309 * thread. 310 */ 311 static void vmbus_onopen_result(struct vmbus_channel_message_header *hdr) 312 { 313 struct vmbus_channel_open_result *result; 314 struct vmbus_channel_msginfo *msginfo; 315 struct vmbus_channel_message_header *requestheader; 316 struct vmbus_channel_open_channel *openmsg; 317 unsigned long flags; 318 319 result = (struct vmbus_channel_open_result *)hdr; 320 321 /* 322 * Find the open msg, copy the result and signal/unblock the wait event 323 */ 324 spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); 325 326 list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, 327 msglistentry) { 328 requestheader = 329 (struct vmbus_channel_message_header *)msginfo->msg; 330 331 if (requestheader->msgtype == CHANNELMSG_OPENCHANNEL) { 332 openmsg = 333 (struct vmbus_channel_open_channel *)msginfo->msg; 334 if (openmsg->child_relid == result->child_relid && 335 openmsg->openid == result->openid) { 336 memcpy(&msginfo->response.open_result, 337 result, 338 sizeof( 339 struct vmbus_channel_open_result)); 340 complete(&msginfo->waitevent); 341 break; 342 } 343 } 344 } 345 spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); 346 } 347 348 /* 349 * vmbus_ongpadl_created - GPADL created handler. 350 * 351 * This is invoked when we received a response to our gpadl create request. 352 * Find the matching request, copy the response and signal the requesting 353 * thread. 354 */ 355 static void vmbus_ongpadl_created(struct vmbus_channel_message_header *hdr) 356 { 357 struct vmbus_channel_gpadl_created *gpadlcreated; 358 struct vmbus_channel_msginfo *msginfo; 359 struct vmbus_channel_message_header *requestheader; 360 struct vmbus_channel_gpadl_header *gpadlheader; 361 unsigned long flags; 362 363 gpadlcreated = (struct vmbus_channel_gpadl_created *)hdr; 364 365 /* 366 * Find the establish msg, copy the result and signal/unblock the wait 367 * event 368 */ 369 spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); 370 371 list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, 372 msglistentry) { 373 requestheader = 374 (struct vmbus_channel_message_header *)msginfo->msg; 375 376 if (requestheader->msgtype == CHANNELMSG_GPADL_HEADER) { 377 gpadlheader = 378 (struct vmbus_channel_gpadl_header *)requestheader; 379 380 if ((gpadlcreated->child_relid == 381 gpadlheader->child_relid) && 382 (gpadlcreated->gpadl == gpadlheader->gpadl)) { 383 memcpy(&msginfo->response.gpadl_created, 384 gpadlcreated, 385 sizeof( 386 struct vmbus_channel_gpadl_created)); 387 complete(&msginfo->waitevent); 388 break; 389 } 390 } 391 } 392 spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); 393 } 394 395 /* 396 * vmbus_ongpadl_torndown - GPADL torndown handler. 397 * 398 * This is invoked when we received a response to our gpadl teardown request. 399 * Find the matching request, copy the response and signal the requesting 400 * thread. 401 */ 402 static void vmbus_ongpadl_torndown( 403 struct vmbus_channel_message_header *hdr) 404 { 405 struct vmbus_channel_gpadl_torndown *gpadl_torndown; 406 struct vmbus_channel_msginfo *msginfo; 407 struct vmbus_channel_message_header *requestheader; 408 struct vmbus_channel_gpadl_teardown *gpadl_teardown; 409 unsigned long flags; 410 411 gpadl_torndown = (struct vmbus_channel_gpadl_torndown *)hdr; 412 413 /* 414 * Find the open msg, copy the result and signal/unblock the wait event 415 */ 416 spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); 417 418 list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, 419 msglistentry) { 420 requestheader = 421 (struct vmbus_channel_message_header *)msginfo->msg; 422 423 if (requestheader->msgtype == CHANNELMSG_GPADL_TEARDOWN) { 424 gpadl_teardown = 425 (struct vmbus_channel_gpadl_teardown *)requestheader; 426 427 if (gpadl_torndown->gpadl == gpadl_teardown->gpadl) { 428 memcpy(&msginfo->response.gpadl_torndown, 429 gpadl_torndown, 430 sizeof( 431 struct vmbus_channel_gpadl_torndown)); 432 complete(&msginfo->waitevent); 433 break; 434 } 435 } 436 } 437 spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); 438 } 439 440 /* 441 * vmbus_onversion_response - Version response handler 442 * 443 * This is invoked when we received a response to our initiate contact request. 444 * Find the matching request, copy the response and signal the requesting 445 * thread. 446 */ 447 static void vmbus_onversion_response( 448 struct vmbus_channel_message_header *hdr) 449 { 450 struct vmbus_channel_msginfo *msginfo; 451 struct vmbus_channel_message_header *requestheader; 452 struct vmbus_channel_initiate_contact *initiate; 453 struct vmbus_channel_version_response *version_response; 454 unsigned long flags; 455 456 version_response = (struct vmbus_channel_version_response *)hdr; 457 spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); 458 459 list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, 460 msglistentry) { 461 requestheader = 462 (struct vmbus_channel_message_header *)msginfo->msg; 463 464 if (requestheader->msgtype == 465 CHANNELMSG_INITIATE_CONTACT) { 466 initiate = 467 (struct vmbus_channel_initiate_contact *)requestheader; 468 memcpy(&msginfo->response.version_response, 469 version_response, 470 sizeof(struct vmbus_channel_version_response)); 471 complete(&msginfo->waitevent); 472 } 473 } 474 spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); 475 } 476 477 /* Channel message dispatch table */ 478 static struct vmbus_channel_message_table_entry 479 channel_message_table[CHANNELMSG_COUNT] = { 480 {CHANNELMSG_INVALID, NULL}, 481 {CHANNELMSG_OFFERCHANNEL, vmbus_onoffer}, 482 {CHANNELMSG_RESCIND_CHANNELOFFER, vmbus_onoffer_rescind}, 483 {CHANNELMSG_REQUESTOFFERS, NULL}, 484 {CHANNELMSG_ALLOFFERS_DELIVERED, vmbus_onoffers_delivered}, 485 {CHANNELMSG_OPENCHANNEL, NULL}, 486 {CHANNELMSG_OPENCHANNEL_RESULT, vmbus_onopen_result}, 487 {CHANNELMSG_CLOSECHANNEL, NULL}, 488 {CHANNELMSG_GPADL_HEADER, NULL}, 489 {CHANNELMSG_GPADL_BODY, NULL}, 490 {CHANNELMSG_GPADL_CREATED, vmbus_ongpadl_created}, 491 {CHANNELMSG_GPADL_TEARDOWN, NULL}, 492 {CHANNELMSG_GPADL_TORNDOWN, vmbus_ongpadl_torndown}, 493 {CHANNELMSG_RELID_RELEASED, NULL}, 494 {CHANNELMSG_INITIATE_CONTACT, NULL}, 495 {CHANNELMSG_VERSION_RESPONSE, vmbus_onversion_response}, 496 {CHANNELMSG_UNLOAD, NULL}, 497 }; 498 499 /* 500 * vmbus_onmessage - Handler for channel protocol messages. 501 * 502 * This is invoked in the vmbus worker thread context. 503 */ 504 void vmbus_onmessage(void *context) 505 { 506 struct hv_message *msg = context; 507 struct vmbus_channel_message_header *hdr; 508 int size; 509 510 hdr = (struct vmbus_channel_message_header *)msg->u.payload; 511 size = msg->header.payload_size; 512 513 if (hdr->msgtype >= CHANNELMSG_COUNT) { 514 pr_err("Received invalid channel message type %d size %d\n", 515 hdr->msgtype, size); 516 print_hex_dump_bytes("", DUMP_PREFIX_NONE, 517 (unsigned char *)msg->u.payload, size); 518 return; 519 } 520 521 if (channel_message_table[hdr->msgtype].message_handler) 522 channel_message_table[hdr->msgtype].message_handler(hdr); 523 else 524 pr_err("Unhandled channel message type %d\n", hdr->msgtype); 525 } 526 527 /* 528 * vmbus_request_offers - Send a request to get all our pending offers. 529 */ 530 int vmbus_request_offers(void) 531 { 532 struct vmbus_channel_message_header *msg; 533 struct vmbus_channel_msginfo *msginfo; 534 int ret, t; 535 536 msginfo = kmalloc(sizeof(*msginfo) + 537 sizeof(struct vmbus_channel_message_header), 538 GFP_KERNEL); 539 if (!msginfo) 540 return -ENOMEM; 541 542 init_completion(&msginfo->waitevent); 543 544 msg = (struct vmbus_channel_message_header *)msginfo->msg; 545 546 msg->msgtype = CHANNELMSG_REQUESTOFFERS; 547 548 549 ret = vmbus_post_msg(msg, 550 sizeof(struct vmbus_channel_message_header)); 551 if (ret != 0) { 552 pr_err("Unable to request offers - %d\n", ret); 553 554 goto cleanup; 555 } 556 557 t = wait_for_completion_timeout(&msginfo->waitevent, 5*HZ); 558 if (t == 0) { 559 ret = -ETIMEDOUT; 560 goto cleanup; 561 } 562 563 564 565 cleanup: 566 kfree(msginfo); 567 568 return ret; 569 } 570 571 /* eof */ 572