hv_kvp.c revision 296954
1/*- 2 * Copyright (c) 2014 Microsoft Corp. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27/* 28 * Author: Sainath Varanasi. 29 * Date: 4/2012 30 * Email: bsdic@microsoft.com 31 */ 32 33#include <sys/cdefs.h> 34__FBSDID("$FreeBSD: releng/10.1/sys/dev/hyperv/utilities/hv_kvp.c 296954 2016-03-16 22:30:56Z glebius $"); 35 36#include <sys/param.h> 37#include <sys/kernel.h> 38#include <sys/conf.h> 39#include <sys/uio.h> 40#include <sys/bus.h> 41#include <sys/malloc.h> 42#include <sys/mbuf.h> 43#include <sys/module.h> 44#include <sys/reboot.h> 45#include <sys/lock.h> 46#include <sys/taskqueue.h> 47#include <sys/selinfo.h> 48#include <sys/sysctl.h> 49#include <sys/poll.h> 50#include <sys/proc.h> 51#include <sys/kthread.h> 52#include <sys/syscallsubr.h> 53#include <sys/sysproto.h> 54#include <sys/un.h> 55#include <sys/endian.h> 56#include <sys/_null.h> 57#include <sys/signal.h> 58#include <sys/syslog.h> 59#include <sys/mutex.h> 60#include <net/if_arp.h> 61 62#include <dev/hyperv/include/hyperv.h> 63#include <dev/hyperv/netvsc/hv_net_vsc.h> 64 65#include "unicode.h" 66#include "hv_kvp.h" 67 68/* hv_kvp defines */ 69#define BUFFERSIZE sizeof(struct hv_kvp_msg) 70#define KVP_SUCCESS 0 71#define KVP_ERROR 1 72#define kvp_hdr hdr.kvp_hdr 73 74/* hv_kvp debug control */ 75static int hv_kvp_log = 0; 76SYSCTL_INT(_dev, OID_AUTO, hv_kvp_log, CTLFLAG_RW, &hv_kvp_log, 0, 77 "hv_kvp log"); 78 79#define hv_kvp_log_error(...) do { \ 80 if (hv_kvp_log > 0) \ 81 log(LOG_ERR, "hv_kvp: " __VA_ARGS__); \ 82} while (0) 83 84#define hv_kvp_log_info(...) do { \ 85 if (hv_kvp_log > 1) \ 86 log(LOG_INFO, "hv_kvp: " __VA_ARGS__); \ 87} while (0) 88 89/* character device prototypes */ 90static d_open_t hv_kvp_dev_open; 91static d_close_t hv_kvp_dev_close; 92static d_read_t hv_kvp_dev_daemon_read; 93static d_write_t hv_kvp_dev_daemon_write; 94static d_poll_t hv_kvp_dev_daemon_poll; 95 96/* hv_kvp prototypes */ 97static int hv_kvp_req_in_progress(void); 98static void hv_kvp_transaction_init(uint32_t, hv_vmbus_channel *, uint64_t, uint8_t *); 99static void hv_kvp_send_msg_to_daemon(void); 100static void hv_kvp_process_request(void *context); 101 102/* hv_kvp character device structure */ 103static struct cdevsw hv_kvp_cdevsw = 104{ 105 .d_version = D_VERSION, 106 .d_open = hv_kvp_dev_open, 107 .d_close = hv_kvp_dev_close, 108 .d_read = hv_kvp_dev_daemon_read, 109 .d_write = hv_kvp_dev_daemon_write, 110 .d_poll = hv_kvp_dev_daemon_poll, 111 .d_name = "hv_kvp_dev", 112}; 113static struct cdev *hv_kvp_dev; 114static struct hv_kvp_msg *hv_kvp_dev_buf; 115struct proc *daemon_task; 116 117static struct selinfo hv_kvp_selinfo; 118 119/* 120 * Global state to track and synchronize multiple 121 * KVP transaction requests from the host. 122 */ 123static struct { 124 125 /* Pre-allocated work item for queue */ 126 hv_work_item work_item; 127 128 /* Unless specified the pending mutex should be 129 * used to alter the values of the following paramters: 130 * 1. req_in_progress 131 * 2. req_timed_out 132 * 3. pending_reqs. 133 */ 134 struct mtx pending_mutex; 135 136 /* To track if transaction is active or not */ 137 boolean_t req_in_progress; 138 /* Tracks if daemon did not reply back in time */ 139 boolean_t req_timed_out; 140 /* Tracks if daemon is serving a request currently */ 141 boolean_t daemon_busy; 142 /* Count of KVP requests from Hyper-V. */ 143 uint64_t pending_reqs; 144 145 146 /* Length of host message */ 147 uint32_t host_msg_len; 148 149 /* Pointer to channel */ 150 hv_vmbus_channel *channelp; 151 152 /* Host message id */ 153 uint64_t host_msg_id; 154 155 /* Current kvp message from the host */ 156 struct hv_kvp_msg *host_kvp_msg; 157 158 /* Current kvp message for daemon */ 159 struct hv_kvp_msg daemon_kvp_msg; 160 161 /* Rcv buffer for communicating with the host*/ 162 uint8_t *rcv_buf; 163 164 /* Device semaphore to control communication */ 165 struct sema dev_sema; 166 167 /* Indicates if daemon registered with driver */ 168 boolean_t register_done; 169 170 /* Character device status */ 171 boolean_t dev_accessed; 172} kvp_globals; 173 174/* global vars */ 175MALLOC_DECLARE(M_HV_KVP_DEV_BUF); 176MALLOC_DEFINE(M_HV_KVP_DEV_BUF, "hv_kvp_dev buffer", "buffer for hv_kvp_dev module"); 177 178/* 179 * hv_kvp low level functions 180 */ 181 182/* 183 * Check if kvp transaction is in progres 184 */ 185static int 186hv_kvp_req_in_progress(void) 187{ 188 189 return (kvp_globals.req_in_progress); 190} 191 192 193/* 194 * This routine is called whenever a message is received from the host 195 */ 196static void 197hv_kvp_transaction_init(uint32_t rcv_len, hv_vmbus_channel *rcv_channel, 198 uint64_t request_id, uint8_t *rcv_buf) 199{ 200 201 /* Store all the relevant message details in the global structure */ 202 /* Do not need to use mutex for req_in_progress here */ 203 kvp_globals.req_in_progress = true; 204 kvp_globals.host_msg_len = rcv_len; 205 kvp_globals.channelp = rcv_channel; 206 kvp_globals.host_msg_id = request_id; 207 kvp_globals.rcv_buf = rcv_buf; 208 kvp_globals.host_kvp_msg = (struct hv_kvp_msg *)&rcv_buf[ 209 sizeof(struct hv_vmbus_pipe_hdr) + 210 sizeof(struct hv_vmbus_icmsg_hdr)]; 211} 212 213 214/* 215 * hv_kvp - version neogtiation function 216 */ 217static void 218hv_kvp_negotiate_version(struct hv_vmbus_icmsg_hdr *icmsghdrp, 219 struct hv_vmbus_icmsg_negotiate *negop, 220 uint8_t *buf) 221{ 222 int icframe_vercnt; 223 int icmsg_vercnt; 224 225 icmsghdrp->icmsgsize = 0x10; 226 227 negop = (struct hv_vmbus_icmsg_negotiate *)&buf[ 228 sizeof(struct hv_vmbus_pipe_hdr) + 229 sizeof(struct hv_vmbus_icmsg_hdr)]; 230 icframe_vercnt = negop->icframe_vercnt; 231 icmsg_vercnt = negop->icmsg_vercnt; 232 233 /* 234 * Select the framework version number we will support 235 */ 236 if ((icframe_vercnt >= 2) && (negop->icversion_data[1].major == 3)) { 237 icframe_vercnt = 3; 238 if (icmsg_vercnt >= 2) 239 icmsg_vercnt = 4; 240 else 241 icmsg_vercnt = 3; 242 } else { 243 icframe_vercnt = 1; 244 icmsg_vercnt = 1; 245 } 246 247 negop->icframe_vercnt = 1; 248 negop->icmsg_vercnt = 1; 249 negop->icversion_data[0].major = icframe_vercnt; 250 negop->icversion_data[0].minor = 0; 251 negop->icversion_data[1].major = icmsg_vercnt; 252 negop->icversion_data[1].minor = 0; 253} 254 255 256/* 257 * Convert ip related info in umsg from utf8 to utf16 and store in hmsg 258 */ 259static int 260hv_kvp_convert_utf8_ipinfo_to_utf16(struct hv_kvp_msg *umsg, 261 struct hv_kvp_ip_msg *host_ip_msg) 262{ 263 int err_ip, err_subnet, err_gway, err_dns, err_adap; 264 int UNUSED_FLAG = 1; 265 266 utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.ip_addr, 267 MAX_IP_ADDR_SIZE, 268 (char *)umsg->body.kvp_ip_val.ip_addr, 269 strlen((char *)umsg->body.kvp_ip_val.ip_addr), 270 UNUSED_FLAG, 271 &err_ip); 272 utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.sub_net, 273 MAX_IP_ADDR_SIZE, 274 (char *)umsg->body.kvp_ip_val.sub_net, 275 strlen((char *)umsg->body.kvp_ip_val.sub_net), 276 UNUSED_FLAG, 277 &err_subnet); 278 utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.gate_way, 279 MAX_GATEWAY_SIZE, 280 (char *)umsg->body.kvp_ip_val.gate_way, 281 strlen((char *)umsg->body.kvp_ip_val.gate_way), 282 UNUSED_FLAG, 283 &err_gway); 284 utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.dns_addr, 285 MAX_IP_ADDR_SIZE, 286 (char *)umsg->body.kvp_ip_val.dns_addr, 287 strlen((char *)umsg->body.kvp_ip_val.dns_addr), 288 UNUSED_FLAG, 289 &err_dns); 290 utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.adapter_id, 291 MAX_IP_ADDR_SIZE, 292 (char *)umsg->body.kvp_ip_val.adapter_id, 293 strlen((char *)umsg->body.kvp_ip_val.adapter_id), 294 UNUSED_FLAG, 295 &err_adap); 296 297 host_ip_msg->kvp_ip_val.dhcp_enabled = umsg->body.kvp_ip_val.dhcp_enabled; 298 host_ip_msg->kvp_ip_val.addr_family = umsg->body.kvp_ip_val.addr_family; 299 300 return (err_ip | err_subnet | err_gway | err_dns | err_adap); 301} 302 303 304/* 305 * Convert ip related info in hmsg from utf16 to utf8 and store in umsg 306 */ 307static int 308hv_kvp_convert_utf16_ipinfo_to_utf8(struct hv_kvp_ip_msg *host_ip_msg, 309 struct hv_kvp_msg *umsg) 310{ 311 int err_ip, err_subnet, err_gway, err_dns, err_adap; 312 int UNUSED_FLAG = 1; 313 int guid_index; 314 struct hv_device *hv_dev; /* GUID Data Structure */ 315 hn_softc_t *sc; /* hn softc structure */ 316 char if_name[4]; 317 unsigned char guid_instance[40]; 318 char *guid_data = NULL; 319 char buf[39]; 320 321 struct guid_extract { 322 char a1[2]; 323 char a2[2]; 324 char a3[2]; 325 char a4[2]; 326 char b1[2]; 327 char b2[2]; 328 char c1[2]; 329 char c2[2]; 330 char d[4]; 331 char e[12]; 332 }; 333 334 struct guid_extract *id; 335 device_t *devs; 336 int devcnt; 337 338 /* IP Address */ 339 utf16_to_utf8((char *)umsg->body.kvp_ip_val.ip_addr, 340 MAX_IP_ADDR_SIZE, 341 (uint16_t *)host_ip_msg->kvp_ip_val.ip_addr, 342 MAX_IP_ADDR_SIZE, 343 UNUSED_FLAG, 344 &err_ip); 345 346 /* Adapter ID : GUID */ 347 utf16_to_utf8((char *)umsg->body.kvp_ip_val.adapter_id, 348 MAX_ADAPTER_ID_SIZE, 349 (uint16_t *)host_ip_msg->kvp_ip_val.adapter_id, 350 MAX_ADAPTER_ID_SIZE, 351 UNUSED_FLAG, 352 &err_adap); 353 354 if (devclass_get_devices(devclass_find("hn"), &devs, &devcnt) == 0) { 355 for (devcnt = devcnt - 1; devcnt >= 0; devcnt--) { 356 sc = device_get_softc(devs[devcnt]); 357 358 /* Trying to find GUID of Network Device */ 359 hv_dev = sc->hn_dev_obj; 360 361 for (guid_index = 0; guid_index < 16; guid_index++) { 362 sprintf(&guid_instance[guid_index * 2], "%02x", 363 hv_dev->device_id.data[guid_index]); 364 } 365 366 guid_data = (char *)guid_instance; 367 id = (struct guid_extract *)guid_data; 368 snprintf(buf, sizeof(buf), "{%.2s%.2s%.2s%.2s-%.2s%.2s-%.2s%.2s-%.4s-%s}", 369 id->a4, id->a3, id->a2, id->a1, 370 id->b2, id->b1, id->c2, id->c1, id->d, id->e); 371 guid_data = NULL; 372 sprintf(if_name, "%s%d", "hn", device_get_unit(devs[devcnt])); 373 374 if (strncmp(buf, (char *)umsg->body.kvp_ip_val.adapter_id, 39) == 0) { 375 strcpy((char *)umsg->body.kvp_ip_val.adapter_id, if_name); 376 break; 377 } 378 } 379 free(devs, M_TEMP); 380 } 381 382 /* Address Family , DHCP , SUBNET, Gateway, DNS */ 383 umsg->kvp_hdr.operation = host_ip_msg->operation; 384 umsg->body.kvp_ip_val.addr_family = host_ip_msg->kvp_ip_val.addr_family; 385 umsg->body.kvp_ip_val.dhcp_enabled = host_ip_msg->kvp_ip_val.dhcp_enabled; 386 utf16_to_utf8((char *)umsg->body.kvp_ip_val.sub_net, MAX_IP_ADDR_SIZE, 387 (uint16_t *)host_ip_msg->kvp_ip_val.sub_net, 388 MAX_IP_ADDR_SIZE, 389 UNUSED_FLAG, 390 &err_subnet); 391 392 utf16_to_utf8((char *)umsg->body.kvp_ip_val.gate_way, MAX_GATEWAY_SIZE, 393 (uint16_t *)host_ip_msg->kvp_ip_val.gate_way, 394 MAX_GATEWAY_SIZE, 395 UNUSED_FLAG, 396 &err_gway); 397 398 utf16_to_utf8((char *)umsg->body.kvp_ip_val.dns_addr, MAX_IP_ADDR_SIZE, 399 (uint16_t *)host_ip_msg->kvp_ip_val.dns_addr, 400 MAX_IP_ADDR_SIZE, 401 UNUSED_FLAG, 402 &err_dns); 403 404 return (err_ip | err_subnet | err_gway | err_dns | err_adap); 405} 406 407 408/* 409 * Prepare a user kvp msg based on host kvp msg (utf16 to utf8) 410 * Ensure utf16_utf8 takes care of the additional string terminating char!! 411 */ 412static void 413hv_kvp_convert_hostmsg_to_usermsg(void) 414{ 415 int utf_err = 0; 416 uint32_t value_type; 417 struct hv_kvp_ip_msg *host_ip_msg = (struct hv_kvp_ip_msg *) 418 kvp_globals.host_kvp_msg; 419 420 struct hv_kvp_msg *hmsg = kvp_globals.host_kvp_msg; 421 struct hv_kvp_msg *umsg = &kvp_globals.daemon_kvp_msg; 422 423 memset(umsg, 0, sizeof(struct hv_kvp_msg)); 424 425 umsg->kvp_hdr.operation = hmsg->kvp_hdr.operation; 426 umsg->kvp_hdr.pool = hmsg->kvp_hdr.pool; 427 428 switch (umsg->kvp_hdr.operation) { 429 case HV_KVP_OP_SET_IP_INFO: 430 hv_kvp_convert_utf16_ipinfo_to_utf8(host_ip_msg, umsg); 431 break; 432 433 case HV_KVP_OP_GET_IP_INFO: 434 utf16_to_utf8((char *)umsg->body.kvp_ip_val.adapter_id, 435 MAX_ADAPTER_ID_SIZE, 436 (uint16_t *)host_ip_msg->kvp_ip_val.adapter_id, 437 MAX_ADAPTER_ID_SIZE, 1, &utf_err); 438 439 umsg->body.kvp_ip_val.addr_family = 440 host_ip_msg->kvp_ip_val.addr_family; 441 break; 442 443 case HV_KVP_OP_SET: 444 value_type = hmsg->body.kvp_set.data.value_type; 445 446 switch (value_type) { 447 case HV_REG_SZ: 448 umsg->body.kvp_set.data.value_size = 449 utf16_to_utf8( 450 (char *)umsg->body.kvp_set.data.msg_value.value, 451 HV_KVP_EXCHANGE_MAX_VALUE_SIZE - 1, 452 (uint16_t *)hmsg->body.kvp_set.data.msg_value.value, 453 hmsg->body.kvp_set.data.value_size, 454 1, &utf_err); 455 /* utf8 encoding */ 456 umsg->body.kvp_set.data.value_size = 457 umsg->body.kvp_set.data.value_size / 2; 458 break; 459 460 case HV_REG_U32: 461 umsg->body.kvp_set.data.value_size = 462 sprintf(umsg->body.kvp_set.data.msg_value.value, "%d", 463 hmsg->body.kvp_set.data.msg_value.value_u32) + 1; 464 break; 465 466 case HV_REG_U64: 467 umsg->body.kvp_set.data.value_size = 468 sprintf(umsg->body.kvp_set.data.msg_value.value, "%llu", 469 (unsigned long long) 470 hmsg->body.kvp_set.data.msg_value.value_u64) + 1; 471 break; 472 } 473 474 umsg->body.kvp_set.data.key_size = 475 utf16_to_utf8( 476 umsg->body.kvp_set.data.key, 477 HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1, 478 (uint16_t *)hmsg->body.kvp_set.data.key, 479 hmsg->body.kvp_set.data.key_size, 480 1, &utf_err); 481 482 /* utf8 encoding */ 483 umsg->body.kvp_set.data.key_size = 484 umsg->body.kvp_set.data.key_size / 2; 485 break; 486 487 case HV_KVP_OP_GET: 488 umsg->body.kvp_get.data.key_size = 489 utf16_to_utf8(umsg->body.kvp_get.data.key, 490 HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1, 491 (uint16_t *)hmsg->body.kvp_get.data.key, 492 hmsg->body.kvp_get.data.key_size, 493 1, &utf_err); 494 /* utf8 encoding */ 495 umsg->body.kvp_get.data.key_size = 496 umsg->body.kvp_get.data.key_size / 2; 497 break; 498 499 case HV_KVP_OP_DELETE: 500 umsg->body.kvp_delete.key_size = 501 utf16_to_utf8(umsg->body.kvp_delete.key, 502 HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1, 503 (uint16_t *)hmsg->body.kvp_delete.key, 504 hmsg->body.kvp_delete.key_size, 505 1, &utf_err); 506 /* utf8 encoding */ 507 umsg->body.kvp_delete.key_size = 508 umsg->body.kvp_delete.key_size / 2; 509 break; 510 511 case HV_KVP_OP_ENUMERATE: 512 umsg->body.kvp_enum_data.index = 513 hmsg->body.kvp_enum_data.index; 514 break; 515 516 default: 517 hv_kvp_log_info("%s: daemon_kvp_msg: Invalid operation : %d\n", 518 __func__, umsg->kvp_hdr.operation); 519 } 520} 521 522 523/* 524 * Prepare a host kvp msg based on user kvp msg (utf8 to utf16) 525 */ 526static int 527hv_kvp_convert_usermsg_to_hostmsg(void) 528{ 529 int hkey_len = 0, hvalue_len = 0, utf_err = 0; 530 struct hv_kvp_exchg_msg_value *host_exchg_data; 531 char *key_name, *value; 532 533 struct hv_kvp_msg *umsg = &kvp_globals.daemon_kvp_msg; 534 struct hv_kvp_msg *hmsg = kvp_globals.host_kvp_msg; 535 struct hv_kvp_ip_msg *host_ip_msg = (struct hv_kvp_ip_msg *)hmsg; 536 537 switch (hmsg->kvp_hdr.operation) { 538 case HV_KVP_OP_GET_IP_INFO: 539 return (hv_kvp_convert_utf8_ipinfo_to_utf16(umsg, host_ip_msg)); 540 541 case HV_KVP_OP_SET_IP_INFO: 542 case HV_KVP_OP_SET: 543 case HV_KVP_OP_DELETE: 544 return (KVP_SUCCESS); 545 546 case HV_KVP_OP_ENUMERATE: 547 host_exchg_data = &hmsg->body.kvp_enum_data.data; 548 key_name = umsg->body.kvp_enum_data.data.key; 549 hkey_len = utf8_to_utf16((uint16_t *)host_exchg_data->key, 550 ((HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2) - 2), 551 key_name, strlen(key_name), 552 1, &utf_err); 553 /* utf16 encoding */ 554 host_exchg_data->key_size = 2 * (hkey_len + 1); 555 value = umsg->body.kvp_enum_data.data.msg_value.value; 556 hvalue_len = utf8_to_utf16( 557 (uint16_t *)host_exchg_data->msg_value.value, 558 ((HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2), 559 value, strlen(value), 560 1, &utf_err); 561 host_exchg_data->value_size = 2 * (hvalue_len + 1); 562 host_exchg_data->value_type = HV_REG_SZ; 563 564 if ((hkey_len < 0) || (hvalue_len < 0)) 565 return (HV_KVP_E_FAIL); 566 567 return (KVP_SUCCESS); 568 569 case HV_KVP_OP_GET: 570 host_exchg_data = &hmsg->body.kvp_get.data; 571 value = umsg->body.kvp_get.data.msg_value.value; 572 hvalue_len = utf8_to_utf16( 573 (uint16_t *)host_exchg_data->msg_value.value, 574 ((HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2), 575 value, strlen(value), 576 1, &utf_err); 577 /* Convert value size to uft16 */ 578 host_exchg_data->value_size = 2 * (hvalue_len + 1); 579 /* Use values by string */ 580 host_exchg_data->value_type = HV_REG_SZ; 581 582 if ((hkey_len < 0) || (hvalue_len < 0)) 583 return (HV_KVP_E_FAIL); 584 585 return (KVP_SUCCESS); 586 587 default: 588 return (HV_KVP_E_FAIL); 589 } 590} 591 592 593/* 594 * Send the response back to the host. 595 */ 596static void 597hv_kvp_respond_host(int error) 598{ 599 struct hv_vmbus_icmsg_hdr *hv_icmsg_hdrp; 600 601 hv_icmsg_hdrp = (struct hv_vmbus_icmsg_hdr *) 602 &kvp_globals.rcv_buf[sizeof(struct hv_vmbus_pipe_hdr)]; 603 604 if (error) 605 error = HV_KVP_E_FAIL; 606 607 hv_icmsg_hdrp->status = error; 608 hv_icmsg_hdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION | HV_ICMSGHDRFLAG_RESPONSE; 609 610 error = hv_vmbus_channel_send_packet(kvp_globals.channelp, 611 kvp_globals.rcv_buf, 612 kvp_globals.host_msg_len, kvp_globals.host_msg_id, 613 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, 0); 614 615 if (error) 616 hv_kvp_log_info("%s: hv_kvp_respond_host: sendpacket error:%d\n", 617 __func__, error); 618} 619 620 621/* 622 * This is the main kvp kernel process that interacts with both user daemon 623 * and the host 624 */ 625static void 626hv_kvp_send_msg_to_daemon(void) 627{ 628 /* Prepare kvp_msg to be sent to user */ 629 hv_kvp_convert_hostmsg_to_usermsg(); 630 631 /* Send the msg to user via function deamon_read - setting sema */ 632 sema_post(&kvp_globals.dev_sema); 633 634 /* We should wake up the daemon, in case it's doing poll() */ 635 selwakeup(&hv_kvp_selinfo); 636} 637 638 639/* 640 * Function to read the kvp request buffer from host 641 * and interact with daemon 642 */ 643static void 644hv_kvp_process_request(void *context) 645{ 646 uint8_t *kvp_buf; 647 hv_vmbus_channel *channel = context; 648 uint32_t recvlen = 0; 649 uint64_t requestid; 650 struct hv_vmbus_icmsg_hdr *icmsghdrp; 651 int ret = 0; 652 uint64_t pending_cnt = 1; 653 654 hv_kvp_log_info("%s: entering hv_kvp_process_request\n", __func__); 655 kvp_buf = receive_buffer[HV_KVP]; 656 ret = hv_vmbus_channel_recv_packet(channel, kvp_buf, 2 * PAGE_SIZE, 657 &recvlen, &requestid); 658 659 /* 660 * We start counting only after the daemon registers 661 * and therefore there could be requests pending in 662 * the VMBus that are not reflected in pending_cnt. 663 * Therefore we continue reading as long as either of 664 * the below conditions is true. 665 */ 666 667 while ((pending_cnt>0) || ((ret == 0) && (recvlen > 0))) { 668 669 if ((ret == 0) && (recvlen>0)) { 670 671 icmsghdrp = (struct hv_vmbus_icmsg_hdr *) 672 &kvp_buf[sizeof(struct hv_vmbus_pipe_hdr)]; 673 674 hv_kvp_transaction_init(recvlen, channel, requestid, kvp_buf); 675 if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) { 676 hv_kvp_negotiate_version(icmsghdrp, NULL, kvp_buf); 677 hv_kvp_respond_host(ret); 678 679 /* 680 * It is ok to not acquire the mutex before setting 681 * req_in_progress here because negotiation is the 682 * first thing that happens and hence there is no 683 * chance of a race condition. 684 */ 685 686 kvp_globals.req_in_progress = false; 687 hv_kvp_log_info("%s :version negotiated\n", __func__); 688 689 } else { 690 if (!kvp_globals.daemon_busy) { 691 692 hv_kvp_log_info("%s: issuing qury to daemon\n", __func__); 693 mtx_lock(&kvp_globals.pending_mutex); 694 kvp_globals.req_timed_out = false; 695 kvp_globals.daemon_busy = true; 696 mtx_unlock(&kvp_globals.pending_mutex); 697 698 hv_kvp_send_msg_to_daemon(); 699 hv_kvp_log_info("%s: waiting for daemon\n", __func__); 700 } 701 702 /* Wait 5 seconds for daemon to respond back */ 703 tsleep(&kvp_globals, 0, "kvpworkitem", 5 * hz); 704 hv_kvp_log_info("%s: came out of wait\n", __func__); 705 } 706 } 707 708 mtx_lock(&kvp_globals.pending_mutex); 709 710 /* Notice that once req_timed_out is set to true 711 * it will remain true until the next request is 712 * sent to the daemon. The response from daemon 713 * is forwarded to host only when this flag is 714 * false. 715 */ 716 kvp_globals.req_timed_out = true; 717 718 /* 719 * Cancel request if so need be. 720 */ 721 if (hv_kvp_req_in_progress()) { 722 hv_kvp_log_info("%s: request was still active after wait so failing\n", __func__); 723 hv_kvp_respond_host(HV_KVP_E_FAIL); 724 kvp_globals.req_in_progress = false; 725 } 726 727 /* 728 * Decrement pending request count and 729 */ 730 if (kvp_globals.pending_reqs>0) { 731 kvp_globals.pending_reqs = kvp_globals.pending_reqs - 1; 732 } 733 pending_cnt = kvp_globals.pending_reqs; 734 735 mtx_unlock(&kvp_globals.pending_mutex); 736 737 /* 738 * Try reading next buffer 739 */ 740 recvlen = 0; 741 ret = hv_vmbus_channel_recv_packet(channel, kvp_buf, 2 * PAGE_SIZE, 742 &recvlen, &requestid); 743 hv_kvp_log_info("%s: read: context %p, pending_cnt %ju ret =%d, recvlen=%d\n", 744 __func__, context, pending_cnt, ret, recvlen); 745 } 746} 747 748 749/* 750 * Callback routine that gets called whenever there is a message from host 751 */ 752void 753hv_kvp_callback(void *context) 754{ 755 uint64_t pending_cnt = 0; 756 757 if (kvp_globals.register_done == false) { 758 759 kvp_globals.channelp = context; 760 } else { 761 762 mtx_lock(&kvp_globals.pending_mutex); 763 kvp_globals.pending_reqs = kvp_globals.pending_reqs + 1; 764 pending_cnt = kvp_globals.pending_reqs; 765 mtx_unlock(&kvp_globals.pending_mutex); 766 if (pending_cnt == 1) { 767 hv_kvp_log_info("%s: Queuing work item\n", __func__); 768 hv_queue_work_item( 769 service_table[HV_KVP].work_queue, 770 hv_kvp_process_request, 771 context 772 ); 773 } 774 } 775} 776 777 778/* 779 * This function is called by the hv_kvp_init - 780 * creates character device hv_kvp_dev 781 * allocates memory to hv_kvp_dev_buf 782 * 783 */ 784static int 785hv_kvp_dev_init(void) 786{ 787 int error = 0; 788 789 /* initialize semaphore */ 790 sema_init(&kvp_globals.dev_sema, 0, "hv_kvp device semaphore"); 791 /* create character device */ 792 error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK, 793 &hv_kvp_dev, 794 &hv_kvp_cdevsw, 795 0, 796 UID_ROOT, 797 GID_WHEEL, 798 0640, 799 "hv_kvp_dev"); 800 801 if (error != 0) 802 return (error); 803 804 /* 805 * Malloc with M_WAITOK flag will never fail. 806 */ 807 hv_kvp_dev_buf = malloc(sizeof(*hv_kvp_dev_buf), M_HV_KVP_DEV_BUF, M_WAITOK | 808 M_ZERO); 809 810 return (0); 811} 812 813 814/* 815 * This function is called by the hv_kvp_deinit - 816 * destroy character device 817 */ 818static void 819hv_kvp_dev_destroy(void) 820{ 821 822 if (daemon_task != NULL) { 823 PROC_LOCK(daemon_task); 824 kern_psignal(daemon_task, SIGKILL); 825 PROC_UNLOCK(daemon_task); 826 } 827 828 destroy_dev(hv_kvp_dev); 829 free(hv_kvp_dev_buf, M_HV_KVP_DEV_BUF); 830 return; 831} 832 833 834static int 835hv_kvp_dev_open(struct cdev *dev, int oflags, int devtype, 836 struct thread *td) 837{ 838 839 hv_kvp_log_info("%s: Opened device \"hv_kvp_device\" successfully.\n", __func__); 840 if (kvp_globals.dev_accessed) 841 return (-EBUSY); 842 843 daemon_task = curproc; 844 kvp_globals.dev_accessed = true; 845 kvp_globals.daemon_busy = false; 846 return (0); 847} 848 849 850static int 851hv_kvp_dev_close(struct cdev *dev __unused, int fflag __unused, int devtype __unused, 852 struct thread *td __unused) 853{ 854 855 hv_kvp_log_info("%s: Closing device \"hv_kvp_device\".\n", __func__); 856 kvp_globals.dev_accessed = false; 857 kvp_globals.register_done = false; 858 return (0); 859} 860 861 862/* 863 * hv_kvp_daemon read invokes this function 864 * acts as a send to daemon 865 */ 866static int 867hv_kvp_dev_daemon_read(struct cdev *dev __unused, struct uio *uio, int ioflag __unused) 868{ 869 size_t amt; 870 int error = 0; 871 872 /* Check hv_kvp daemon registration status*/ 873 if (!kvp_globals.register_done) 874 return (KVP_ERROR); 875 876 sema_wait(&kvp_globals.dev_sema); 877 878 memcpy(hv_kvp_dev_buf, &kvp_globals.daemon_kvp_msg, sizeof(struct hv_kvp_msg)); 879 880 amt = MIN(uio->uio_resid, uio->uio_offset >= BUFFERSIZE + 1 ? 0 : 881 BUFFERSIZE + 1 - uio->uio_offset); 882 883 if ((error = uiomove(hv_kvp_dev_buf, amt, uio)) != 0) 884 hv_kvp_log_info("%s: hv_kvp uiomove read failed!\n", __func__); 885 886 return (error); 887} 888 889 890/* 891 * hv_kvp_daemon write invokes this function 892 * acts as a recieve from daemon 893 */ 894static int 895hv_kvp_dev_daemon_write(struct cdev *dev __unused, struct uio *uio, int ioflag __unused) 896{ 897 size_t amt; 898 int error = 0; 899 900 uio->uio_offset = 0; 901 902 amt = MIN(uio->uio_resid, BUFFERSIZE); 903 error = uiomove(hv_kvp_dev_buf, amt, uio); 904 905 if (error != 0) 906 return (error); 907 908 memcpy(&kvp_globals.daemon_kvp_msg, hv_kvp_dev_buf, sizeof(struct hv_kvp_msg)); 909 910 if (kvp_globals.register_done == false) { 911 if (kvp_globals.daemon_kvp_msg.kvp_hdr.operation == HV_KVP_OP_REGISTER) { 912 913 kvp_globals.register_done = true; 914 if (kvp_globals.channelp) { 915 916 hv_kvp_callback(kvp_globals.channelp); 917 } 918 } 919 else { 920 hv_kvp_log_info("%s, KVP Registration Failed\n", __func__); 921 return (KVP_ERROR); 922 } 923 } else { 924 925 mtx_lock(&kvp_globals.pending_mutex); 926 927 if(!kvp_globals.req_timed_out) { 928 929 hv_kvp_convert_usermsg_to_hostmsg(); 930 hv_kvp_respond_host(KVP_SUCCESS); 931 wakeup(&kvp_globals); 932 kvp_globals.req_in_progress = false; 933 } 934 935 kvp_globals.daemon_busy = false; 936 mtx_unlock(&kvp_globals.pending_mutex); 937 } 938 939 return (error); 940} 941 942 943/* 944 * hv_kvp_daemon poll invokes this function to check if data is available 945 * for daemon to read. 946 */ 947static int 948hv_kvp_dev_daemon_poll(struct cdev *dev __unused, int events, struct thread *td) 949{ 950 int revents = 0; 951 952 mtx_lock(&kvp_globals.pending_mutex); 953 /* 954 * We check global flag daemon_busy for the data availiability for 955 * userland to read. Deamon_busy is set to true before driver has data 956 * for daemon to read. It is set to false after daemon sends 957 * then response back to driver. 958 */ 959 if (kvp_globals.daemon_busy == true) 960 revents = POLLIN; 961 else 962 selrecord(td, &hv_kvp_selinfo); 963 964 mtx_unlock(&kvp_globals.pending_mutex); 965 966 return (revents); 967} 968 969 970/* 971 * hv_kvp initialization function 972 * called from hv_util service. 973 * 974 */ 975int 976hv_kvp_init(hv_vmbus_service *srv) 977{ 978 int error = 0; 979 hv_work_queue *work_queue = NULL; 980 981 memset(&kvp_globals, 0, sizeof(kvp_globals)); 982 983 work_queue = hv_work_queue_create("KVP Service"); 984 if (work_queue == NULL) { 985 hv_kvp_log_info("%s: Work queue alloc failed\n", __func__); 986 error = ENOMEM; 987 hv_kvp_log_error("%s: ENOMEM\n", __func__); 988 goto Finish; 989 } 990 srv->work_queue = work_queue; 991 992 error = hv_kvp_dev_init(); 993 mtx_init(&kvp_globals.pending_mutex, "hv-kvp pending mutex", 994 NULL, MTX_DEF); 995 kvp_globals.pending_reqs = 0; 996 997 998Finish: 999 return (error); 1000} 1001 1002 1003void 1004hv_kvp_deinit(void) 1005{ 1006 hv_kvp_dev_destroy(); 1007 mtx_destroy(&kvp_globals.pending_mutex); 1008 1009 return; 1010} 1011