The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/hyperv/utilities/hv_kvp.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2014,2016-2017 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$");
   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/sema.h>
   58 #include <sys/signal.h>
   59 #include <sys/syslog.h>
   60 #include <sys/systm.h>
   61 #include <sys/mutex.h>
   62 
   63 #include <dev/hyperv/include/hyperv.h>
   64 #include <dev/hyperv/include/vmbus.h>
   65 #include <dev/hyperv/utilities/hv_utilreg.h>
   66 #include <dev/hyperv/utilities/vmbus_icreg.h>
   67 #include <dev/hyperv/utilities/vmbus_icvar.h>
   68 
   69 #include "unicode.h"
   70 #include "hv_kvp.h"
   71 #include "vmbus_if.h"
   72 
   73 /* hv_kvp defines */
   74 #define BUFFERSIZE      sizeof(struct hv_kvp_msg)
   75 #define kvp_hdr         hdr.kvp_hdr
   76 
   77 #define KVP_FWVER_MAJOR         3
   78 #define KVP_FWVER               VMBUS_IC_VERSION(KVP_FWVER_MAJOR, 0)
   79 
   80 #define KVP_MSGVER_MAJOR        4
   81 #define KVP_MSGVER              VMBUS_IC_VERSION(KVP_MSGVER_MAJOR, 0)
   82 
   83 /* hv_kvp debug control */
   84 static int hv_kvp_log = 0;
   85 
   86 #define hv_kvp_log_error(...)   do {                            \
   87         if (hv_kvp_log > 0)                             \
   88                 log(LOG_ERR, "hv_kvp: " __VA_ARGS__);   \
   89 } while (0)
   90 
   91 #define hv_kvp_log_info(...) do {                               \
   92         if (hv_kvp_log > 1)                             \
   93                 log(LOG_INFO, "hv_kvp: " __VA_ARGS__);          \
   94 } while (0)
   95 
   96 static const struct vmbus_ic_desc vmbus_kvp_descs[] = {
   97         {
   98                 .ic_guid = { .hv_guid = {
   99                     0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d,
  100                     0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3,  0xe6 } },
  101                 .ic_desc = "Hyper-V KVP"
  102         },
  103         VMBUS_IC_DESC_END
  104 };
  105 
  106 /* character device prototypes */
  107 static d_open_t         hv_kvp_dev_open;
  108 static d_close_t        hv_kvp_dev_close;
  109 static d_read_t         hv_kvp_dev_daemon_read;
  110 static d_write_t        hv_kvp_dev_daemon_write;
  111 static d_poll_t         hv_kvp_dev_daemon_poll;
  112 
  113 /* hv_kvp character device structure */
  114 static struct cdevsw hv_kvp_cdevsw =
  115 {
  116         .d_version      = D_VERSION,
  117         .d_open         = hv_kvp_dev_open,
  118         .d_close        = hv_kvp_dev_close,
  119         .d_read         = hv_kvp_dev_daemon_read,
  120         .d_write        = hv_kvp_dev_daemon_write,
  121         .d_poll         = hv_kvp_dev_daemon_poll,
  122         .d_name         = "hv_kvp_dev",
  123 };
  124 
  125 
  126 /*
  127  * Global state to track and synchronize multiple
  128  * KVP transaction requests from the host.
  129  */
  130 typedef struct hv_kvp_sc {
  131         struct vmbus_ic_softc   util_sc;
  132         device_t                dev;
  133 
  134         /* Unless specified the pending mutex should be
  135          * used to alter the values of the following parameters:
  136          * 1. req_in_progress
  137          * 2. req_timed_out
  138          */
  139         struct mtx              pending_mutex;
  140 
  141         struct task             task;
  142 
  143         /* To track if transaction is active or not */
  144         boolean_t               req_in_progress;
  145         /* Tracks if daemon did not reply back in time */
  146         boolean_t               req_timed_out;
  147         /* Tracks if daemon is serving a request currently */
  148         boolean_t               daemon_busy;
  149 
  150         /* Length of host message */
  151         uint32_t                host_msg_len;
  152 
  153         /* Host message id */
  154         uint64_t                host_msg_id;
  155 
  156         /* Current kvp message from the host */
  157         struct hv_kvp_msg       *host_kvp_msg;
  158 
  159          /* Current kvp message for daemon */
  160         struct hv_kvp_msg       daemon_kvp_msg;
  161 
  162         /* Rcv buffer for communicating with the host*/
  163         uint8_t                 *rcv_buf;
  164 
  165         /* Device semaphore to control communication */
  166         struct sema             dev_sema;
  167 
  168         /* Indicates if daemon registered with driver */
  169         boolean_t               register_done;
  170 
  171         /* Character device status */
  172         boolean_t               dev_accessed;
  173 
  174         struct cdev *hv_kvp_dev;
  175 
  176         struct proc *daemon_task;
  177 
  178         struct selinfo hv_kvp_selinfo;
  179 } hv_kvp_sc;
  180 
  181 /* hv_kvp prototypes */
  182 static int      hv_kvp_req_in_progress(hv_kvp_sc *sc);
  183 static void     hv_kvp_transaction_init(hv_kvp_sc *sc, uint32_t, uint64_t, uint8_t *);
  184 static void     hv_kvp_send_msg_to_daemon(hv_kvp_sc *sc);
  185 static void     hv_kvp_process_request(void *context, int pending);
  186 
  187 /*
  188  * hv_kvp low level functions
  189  */
  190 
  191 /*
  192  * Check if kvp transaction is in progres
  193  */
  194 static int
  195 hv_kvp_req_in_progress(hv_kvp_sc *sc)
  196 {
  197 
  198         return (sc->req_in_progress);
  199 }
  200 
  201 
  202 /*
  203  * This routine is called whenever a message is received from the host
  204  */
  205 static void
  206 hv_kvp_transaction_init(hv_kvp_sc *sc, uint32_t rcv_len,
  207                         uint64_t request_id, uint8_t *rcv_buf)
  208 {
  209 
  210         /* Store all the relevant message details in the global structure */
  211         /* Do not need to use mutex for req_in_progress here */
  212         sc->req_in_progress = true;
  213         sc->host_msg_len = rcv_len;
  214         sc->host_msg_id = request_id;
  215         sc->rcv_buf = rcv_buf;
  216         sc->host_kvp_msg = (struct hv_kvp_msg *)&rcv_buf[
  217             sizeof(struct hv_vmbus_pipe_hdr) +
  218             sizeof(struct hv_vmbus_icmsg_hdr)];
  219 }
  220 
  221 /*
  222  * Convert ip related info in umsg from utf8 to utf16 and store in hmsg
  223  */
  224 static int
  225 hv_kvp_convert_utf8_ipinfo_to_utf16(struct hv_kvp_msg *umsg,
  226                                     struct hv_kvp_ip_msg *host_ip_msg)
  227 {
  228         int err_ip, err_subnet, err_gway, err_dns, err_adap;
  229         int UNUSED_FLAG = 1;
  230 
  231         utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.ip_addr,
  232             MAX_IP_ADDR_SIZE,
  233             (char *)umsg->body.kvp_ip_val.ip_addr,
  234             strlen((char *)umsg->body.kvp_ip_val.ip_addr),
  235             UNUSED_FLAG,
  236             &err_ip);
  237         utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.sub_net,
  238             MAX_IP_ADDR_SIZE,
  239             (char *)umsg->body.kvp_ip_val.sub_net,
  240             strlen((char *)umsg->body.kvp_ip_val.sub_net),
  241             UNUSED_FLAG,
  242             &err_subnet);
  243         utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.gate_way,
  244             MAX_GATEWAY_SIZE,
  245             (char *)umsg->body.kvp_ip_val.gate_way,
  246             strlen((char *)umsg->body.kvp_ip_val.gate_way),
  247             UNUSED_FLAG,
  248             &err_gway);
  249         utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.dns_addr,
  250             MAX_IP_ADDR_SIZE,
  251             (char *)umsg->body.kvp_ip_val.dns_addr,
  252             strlen((char *)umsg->body.kvp_ip_val.dns_addr),
  253             UNUSED_FLAG,
  254             &err_dns);
  255         utf8_to_utf16((uint16_t *)host_ip_msg->kvp_ip_val.adapter_id,
  256             MAX_ADAPTER_ID_SIZE,
  257             (char *)umsg->body.kvp_ip_val.adapter_id,
  258             strlen((char *)umsg->body.kvp_ip_val.adapter_id),
  259             UNUSED_FLAG,
  260             &err_adap);
  261 
  262         host_ip_msg->kvp_ip_val.dhcp_enabled = umsg->body.kvp_ip_val.dhcp_enabled;
  263         host_ip_msg->kvp_ip_val.addr_family = umsg->body.kvp_ip_val.addr_family;
  264 
  265         return (err_ip | err_subnet | err_gway | err_dns | err_adap);
  266 }
  267 
  268 
  269 /*
  270  * Convert ip related info in hmsg from utf16 to utf8 and store in umsg
  271  */
  272 static int
  273 hv_kvp_convert_utf16_ipinfo_to_utf8(struct hv_kvp_ip_msg *host_ip_msg,
  274                                     struct hv_kvp_msg *umsg)
  275 {
  276         int err_ip, err_subnet, err_gway, err_dns, err_adap;
  277         int UNUSED_FLAG = 1;
  278         device_t *devs;
  279         int devcnt;
  280 
  281         /* IP Address */
  282         utf16_to_utf8((char *)umsg->body.kvp_ip_val.ip_addr,
  283             MAX_IP_ADDR_SIZE,
  284             (uint16_t *)host_ip_msg->kvp_ip_val.ip_addr,
  285             MAX_IP_ADDR_SIZE,
  286             UNUSED_FLAG,
  287             &err_ip);
  288 
  289         /* Adapter ID : GUID */
  290         utf16_to_utf8((char *)umsg->body.kvp_ip_val.adapter_id,
  291             MAX_ADAPTER_ID_SIZE,
  292             (uint16_t *)host_ip_msg->kvp_ip_val.adapter_id,
  293             MAX_ADAPTER_ID_SIZE,
  294             UNUSED_FLAG,
  295             &err_adap);
  296 
  297         if (devclass_get_devices(devclass_find("hn"), &devs, &devcnt) == 0) {
  298                 for (devcnt = devcnt - 1; devcnt >= 0; devcnt--) {
  299                         device_t dev = devs[devcnt];
  300                         struct vmbus_channel *chan;
  301                         char buf[HYPERV_GUID_STRLEN];
  302                         int n;
  303 
  304                         chan = vmbus_get_channel(dev);
  305                         n = hyperv_guid2str(vmbus_chan_guid_inst(chan), buf,
  306                             sizeof(buf));
  307 
  308                         /*
  309                          * The string in the 'kvp_ip_val.adapter_id' has
  310                          * braces around the GUID; skip the leading brace
  311                          * in 'kvp_ip_val.adapter_id'.
  312                          */
  313                         if (strncmp(buf,
  314                             ((char *)&umsg->body.kvp_ip_val.adapter_id) + 1,
  315                             n) == 0) {
  316                                 strlcpy((char *)umsg->body.kvp_ip_val.adapter_id,
  317                                     device_get_nameunit(dev), MAX_ADAPTER_ID_SIZE);
  318                                 break;
  319                         }
  320                 }
  321                 free(devs, M_TEMP);
  322         }
  323 
  324         /* Address Family , DHCP , SUBNET, Gateway, DNS */
  325         umsg->kvp_hdr.operation = host_ip_msg->operation;
  326         umsg->body.kvp_ip_val.addr_family = host_ip_msg->kvp_ip_val.addr_family;
  327         umsg->body.kvp_ip_val.dhcp_enabled = host_ip_msg->kvp_ip_val.dhcp_enabled;
  328         utf16_to_utf8((char *)umsg->body.kvp_ip_val.sub_net, MAX_IP_ADDR_SIZE,
  329             (uint16_t *)host_ip_msg->kvp_ip_val.sub_net,
  330             MAX_IP_ADDR_SIZE,
  331             UNUSED_FLAG,
  332             &err_subnet);
  333 
  334         utf16_to_utf8((char *)umsg->body.kvp_ip_val.gate_way, MAX_GATEWAY_SIZE,
  335             (uint16_t *)host_ip_msg->kvp_ip_val.gate_way,
  336             MAX_GATEWAY_SIZE,
  337             UNUSED_FLAG,
  338             &err_gway);
  339 
  340         utf16_to_utf8((char *)umsg->body.kvp_ip_val.dns_addr, MAX_IP_ADDR_SIZE,
  341             (uint16_t *)host_ip_msg->kvp_ip_val.dns_addr,
  342             MAX_IP_ADDR_SIZE,
  343             UNUSED_FLAG,
  344             &err_dns);
  345 
  346         return (err_ip | err_subnet | err_gway | err_dns | err_adap);
  347 }
  348 
  349 
  350 /*
  351  * Prepare a user kvp msg based on host kvp msg (utf16 to utf8)
  352  * Ensure utf16_utf8 takes care of the additional string terminating char!!
  353  */
  354 static void
  355 hv_kvp_convert_hostmsg_to_usermsg(struct hv_kvp_msg *hmsg, struct hv_kvp_msg *umsg)
  356 {
  357         int utf_err = 0;
  358         uint32_t value_type;
  359         struct hv_kvp_ip_msg *host_ip_msg;
  360 
  361         host_ip_msg = (struct hv_kvp_ip_msg*)hmsg;
  362         memset(umsg, 0, sizeof(struct hv_kvp_msg));
  363 
  364         umsg->kvp_hdr.operation = hmsg->kvp_hdr.operation;
  365         umsg->kvp_hdr.pool = hmsg->kvp_hdr.pool;
  366 
  367         switch (umsg->kvp_hdr.operation) {
  368         case HV_KVP_OP_SET_IP_INFO:
  369                 hv_kvp_convert_utf16_ipinfo_to_utf8(host_ip_msg, umsg);
  370                 break;
  371 
  372         case HV_KVP_OP_GET_IP_INFO:
  373                 utf16_to_utf8((char *)umsg->body.kvp_ip_val.adapter_id,
  374                     MAX_ADAPTER_ID_SIZE,
  375                     (uint16_t *)host_ip_msg->kvp_ip_val.adapter_id,
  376                     MAX_ADAPTER_ID_SIZE, 1, &utf_err);
  377 
  378                 umsg->body.kvp_ip_val.addr_family =
  379                     host_ip_msg->kvp_ip_val.addr_family;
  380                 break;
  381 
  382         case HV_KVP_OP_SET:
  383                 value_type = hmsg->body.kvp_set.data.value_type;
  384 
  385                 switch (value_type) {
  386                 case HV_REG_SZ:
  387                         umsg->body.kvp_set.data.value_size =
  388                             utf16_to_utf8(
  389                                 (char *)umsg->body.kvp_set.data.msg_value.value,
  390                                 HV_KVP_EXCHANGE_MAX_VALUE_SIZE - 1,
  391                                 (uint16_t *)hmsg->body.kvp_set.data.msg_value.value,
  392                                 hmsg->body.kvp_set.data.value_size,
  393                                 1, &utf_err);
  394                         /* utf8 encoding */
  395                         umsg->body.kvp_set.data.value_size =
  396                             umsg->body.kvp_set.data.value_size / 2;
  397                         break;
  398 
  399                 case HV_REG_U32:
  400                         umsg->body.kvp_set.data.value_size =
  401                             sprintf(umsg->body.kvp_set.data.msg_value.value, "%d",
  402                                 hmsg->body.kvp_set.data.msg_value.value_u32) + 1;
  403                         break;
  404 
  405                 case HV_REG_U64:
  406                         umsg->body.kvp_set.data.value_size =
  407                             sprintf(umsg->body.kvp_set.data.msg_value.value, "%llu",
  408                                 (unsigned long long)
  409                                 hmsg->body.kvp_set.data.msg_value.value_u64) + 1;
  410                         break;
  411                 }
  412 
  413                 umsg->body.kvp_set.data.key_size =
  414                     utf16_to_utf8(
  415                         umsg->body.kvp_set.data.key,
  416                         HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1,
  417                         (uint16_t *)hmsg->body.kvp_set.data.key,
  418                         hmsg->body.kvp_set.data.key_size,
  419                         1, &utf_err);
  420 
  421                 /* utf8 encoding */
  422                 umsg->body.kvp_set.data.key_size =
  423                     umsg->body.kvp_set.data.key_size / 2;
  424                 break;
  425 
  426         case HV_KVP_OP_GET:
  427                 umsg->body.kvp_get.data.key_size =
  428                     utf16_to_utf8(umsg->body.kvp_get.data.key,
  429                         HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1,
  430                         (uint16_t *)hmsg->body.kvp_get.data.key,
  431                         hmsg->body.kvp_get.data.key_size,
  432                         1, &utf_err);
  433                 /* utf8 encoding */
  434                 umsg->body.kvp_get.data.key_size =
  435                     umsg->body.kvp_get.data.key_size / 2;
  436                 break;
  437 
  438         case HV_KVP_OP_DELETE:
  439                 umsg->body.kvp_delete.key_size =
  440                     utf16_to_utf8(umsg->body.kvp_delete.key,
  441                         HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1,
  442                         (uint16_t *)hmsg->body.kvp_delete.key,
  443                         hmsg->body.kvp_delete.key_size,
  444                         1, &utf_err);
  445                 /* utf8 encoding */
  446                 umsg->body.kvp_delete.key_size =
  447                     umsg->body.kvp_delete.key_size / 2;
  448                 break;
  449 
  450         case HV_KVP_OP_ENUMERATE:
  451                 umsg->body.kvp_enum_data.index =
  452                     hmsg->body.kvp_enum_data.index;
  453                 break;
  454 
  455         default:
  456                 hv_kvp_log_info("%s: daemon_kvp_msg: Invalid operation : %d\n",
  457                     __func__, umsg->kvp_hdr.operation);
  458         }
  459 }
  460 
  461 
  462 /*
  463  * Prepare a host kvp msg based on user kvp msg (utf8 to utf16)
  464  */
  465 static int
  466 hv_kvp_convert_usermsg_to_hostmsg(struct hv_kvp_msg *umsg, struct hv_kvp_msg *hmsg)
  467 {
  468         int hkey_len = 0, hvalue_len = 0, utf_err = 0;
  469         struct hv_kvp_exchg_msg_value *host_exchg_data;
  470         char *key_name, *value;
  471 
  472         struct hv_kvp_ip_msg *host_ip_msg = (struct hv_kvp_ip_msg *)hmsg;
  473 
  474         switch (hmsg->kvp_hdr.operation) {
  475         case HV_KVP_OP_GET_IP_INFO:
  476                 return (hv_kvp_convert_utf8_ipinfo_to_utf16(umsg, host_ip_msg));
  477 
  478         case HV_KVP_OP_SET_IP_INFO:
  479         case HV_KVP_OP_SET:
  480         case HV_KVP_OP_DELETE:
  481                 return (0);
  482 
  483         case HV_KVP_OP_ENUMERATE:
  484                 host_exchg_data = &hmsg->body.kvp_enum_data.data;
  485                 key_name = umsg->body.kvp_enum_data.data.key;
  486                 hkey_len = utf8_to_utf16((uint16_t *)host_exchg_data->key,
  487                                 ((HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2) - 2),
  488                                 key_name, strlen(key_name),
  489                                 1, &utf_err);
  490                 /* utf16 encoding */
  491                 host_exchg_data->key_size = 2 * (hkey_len + 1);
  492                 value = umsg->body.kvp_enum_data.data.msg_value.value;
  493                 hvalue_len = utf8_to_utf16(
  494                                 (uint16_t *)host_exchg_data->msg_value.value,
  495                                 ((HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2),
  496                                 value, strlen(value),
  497                                 1, &utf_err);
  498                 host_exchg_data->value_size = 2 * (hvalue_len + 1);
  499                 host_exchg_data->value_type = HV_REG_SZ;
  500 
  501                 if ((hkey_len < 0) || (hvalue_len < 0))
  502                         return (EINVAL);
  503 
  504                 return (0);
  505 
  506         case HV_KVP_OP_GET:
  507                 host_exchg_data = &hmsg->body.kvp_get.data;
  508                 value = umsg->body.kvp_get.data.msg_value.value;
  509                 hvalue_len = utf8_to_utf16(
  510                                 (uint16_t *)host_exchg_data->msg_value.value,
  511                                 ((HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2) - 2),
  512                                 value, strlen(value),
  513                                 1, &utf_err);
  514                 /* Convert value size to uft16 */
  515                 host_exchg_data->value_size = 2 * (hvalue_len + 1);
  516                 /* Use values by string */
  517                 host_exchg_data->value_type = HV_REG_SZ;
  518 
  519                 if (hvalue_len < 0)
  520                         return (EINVAL);
  521 
  522                 return (0);
  523 
  524         default:
  525                 return (EINVAL);
  526         }
  527 }
  528 
  529 
  530 /*
  531  * Send the response back to the host.
  532  */
  533 static void
  534 hv_kvp_respond_host(hv_kvp_sc *sc, uint32_t error)
  535 {
  536         struct hv_vmbus_icmsg_hdr *hv_icmsg_hdrp;
  537 
  538         hv_icmsg_hdrp = (struct hv_vmbus_icmsg_hdr *)
  539             &sc->rcv_buf[sizeof(struct hv_vmbus_pipe_hdr)];
  540 
  541         hv_icmsg_hdrp->status = error;
  542         hv_icmsg_hdrp->icflags = HV_ICMSGHDRFLAG_TRANSACTION |
  543             HV_ICMSGHDRFLAG_RESPONSE;
  544 
  545         error = vmbus_chan_send(vmbus_get_channel(sc->dev),
  546             VMBUS_CHANPKT_TYPE_INBAND, 0, sc->rcv_buf, sc->host_msg_len,
  547             sc->host_msg_id);
  548         if (error)
  549                 hv_kvp_log_info("%s: hv_kvp_respond_host: sendpacket error:%d\n",
  550                         __func__, error);
  551 }
  552 
  553 
  554 /*
  555  * This is the main kvp kernel process that interacts with both user daemon
  556  * and the host
  557  */
  558 static void
  559 hv_kvp_send_msg_to_daemon(hv_kvp_sc *sc)
  560 {
  561         struct hv_kvp_msg *hmsg = sc->host_kvp_msg;
  562         struct hv_kvp_msg *umsg = &sc->daemon_kvp_msg;
  563 
  564         /* Prepare kvp_msg to be sent to user */
  565         hv_kvp_convert_hostmsg_to_usermsg(hmsg, umsg);
  566 
  567         /* Send the msg to user via function deamon_read - setting sema */
  568         sema_post(&sc->dev_sema);
  569 
  570         /* We should wake up the daemon, in case it's doing poll() */
  571         selwakeup(&sc->hv_kvp_selinfo);
  572 }
  573 
  574 
  575 /*
  576  * Function to read the kvp request buffer from host
  577  * and interact with daemon
  578  */
  579 static void
  580 hv_kvp_process_request(void *context, int pending)
  581 {
  582         uint8_t *kvp_buf;
  583         struct vmbus_channel *channel;
  584         uint32_t recvlen = 0;
  585         uint64_t requestid;
  586         struct hv_vmbus_icmsg_hdr *icmsghdrp;
  587         int ret = 0, error;
  588         hv_kvp_sc *sc;
  589 
  590         hv_kvp_log_info("%s: entering hv_kvp_process_request\n", __func__);
  591 
  592         sc = (hv_kvp_sc*)context;
  593         kvp_buf = sc->util_sc.ic_buf;
  594         channel = vmbus_get_channel(sc->dev);
  595 
  596         recvlen = sc->util_sc.ic_buflen;
  597         ret = vmbus_chan_recv(channel, kvp_buf, &recvlen, &requestid);
  598         KASSERT(ret != ENOBUFS, ("hvkvp recvbuf is not large enough"));
  599         /* XXX check recvlen to make sure that it contains enough data */
  600 
  601         while ((ret == 0) && (recvlen > 0)) {
  602                 icmsghdrp = (struct hv_vmbus_icmsg_hdr *)
  603                     &kvp_buf[sizeof(struct hv_vmbus_pipe_hdr)];
  604 
  605                 hv_kvp_transaction_init(sc, recvlen, requestid, kvp_buf);
  606                 if (icmsghdrp->icmsgtype == HV_ICMSGTYPE_NEGOTIATE) {
  607                         error = vmbus_ic_negomsg(&sc->util_sc,
  608                             kvp_buf, &recvlen, KVP_FWVER, KVP_MSGVER);
  609                         /* XXX handle vmbus_ic_negomsg failure. */
  610                         if (!error)
  611                                 hv_kvp_respond_host(sc, HV_S_OK);
  612                         else
  613                                 hv_kvp_respond_host(sc, HV_E_FAIL);
  614                         /*
  615                          * It is ok to not acquire the mutex before setting
  616                          * req_in_progress here because negotiation is the
  617                          * first thing that happens and hence there is no
  618                          * chance of a race condition.
  619                          */
  620 
  621                         sc->req_in_progress = false;
  622                         hv_kvp_log_info("%s :version negotiated\n", __func__);
  623 
  624                 } else {
  625                         if (!sc->daemon_busy) {
  626 
  627                                 hv_kvp_log_info("%s: issuing qury to daemon\n", __func__);
  628                                 mtx_lock(&sc->pending_mutex);
  629                                 sc->req_timed_out = false;
  630                                 sc->daemon_busy = true;
  631                                 mtx_unlock(&sc->pending_mutex);
  632 
  633                                 hv_kvp_send_msg_to_daemon(sc);
  634                                 hv_kvp_log_info("%s: waiting for daemon\n", __func__);
  635                         }
  636 
  637                         /* Wait 5 seconds for daemon to respond back */
  638                         tsleep(sc, 0, "kvpworkitem", 5 * hz);
  639                         hv_kvp_log_info("%s: came out of wait\n", __func__);
  640                 }
  641 
  642                 mtx_lock(&sc->pending_mutex);
  643 
  644                 /* Notice that once req_timed_out is set to true
  645                  * it will remain true until the next request is
  646                  * sent to the daemon. The response from daemon
  647                  * is forwarded to host only when this flag is
  648                  * false.
  649                  */
  650                 sc->req_timed_out = true;
  651 
  652                 /*
  653                  * Cancel request if so need be.
  654                  */
  655                 if (hv_kvp_req_in_progress(sc)) {
  656                         hv_kvp_log_info("%s: request was still active after wait so failing\n", __func__);
  657                         hv_kvp_respond_host(sc, HV_E_FAIL);
  658                         sc->req_in_progress = false;
  659                 }
  660 
  661                 mtx_unlock(&sc->pending_mutex);
  662 
  663                 /*
  664                  * Try reading next buffer
  665                  */
  666                 recvlen = sc->util_sc.ic_buflen;
  667                 ret = vmbus_chan_recv(channel, kvp_buf, &recvlen, &requestid);
  668                 KASSERT(ret != ENOBUFS, ("hvkvp recvbuf is not large enough"));
  669                 /* XXX check recvlen to make sure that it contains enough data */
  670 
  671                 hv_kvp_log_info("%s: read: context %p, ret =%d, recvlen=%d\n",
  672                         __func__, context, ret, recvlen);
  673         }
  674 }
  675 
  676 
  677 /*
  678  * Callback routine that gets called whenever there is a message from host
  679  */
  680 static void
  681 hv_kvp_callback(struct vmbus_channel *chan __unused, void *context)
  682 {
  683         hv_kvp_sc *sc = (hv_kvp_sc*)context;
  684         /*
  685          The first request from host will not be handled until daemon is registered.
  686          when callback is triggered without a registered daemon, callback just return.
  687          When a new daemon gets regsitered, this callbcak is trigged from _write op.
  688         */
  689         if (sc->register_done) {
  690                 hv_kvp_log_info("%s: Queuing work item\n", __func__);
  691                 taskqueue_enqueue(taskqueue_thread, &sc->task);
  692         }
  693 }
  694 
  695 static int
  696 hv_kvp_dev_open(struct cdev *dev, int oflags, int devtype,
  697                                 struct thread *td)
  698 {
  699         hv_kvp_sc *sc = (hv_kvp_sc*)dev->si_drv1;
  700 
  701         hv_kvp_log_info("%s: Opened device \"hv_kvp_device\" successfully.\n", __func__);
  702         if (sc->dev_accessed)
  703                 return (-EBUSY);
  704 
  705         sc->daemon_task = curproc;
  706         sc->dev_accessed = true;
  707         sc->daemon_busy = false;
  708         return (0);
  709 }
  710 
  711 
  712 static int
  713 hv_kvp_dev_close(struct cdev *dev __unused, int fflag __unused, int devtype __unused,
  714                                  struct thread *td __unused)
  715 {
  716         hv_kvp_sc *sc = (hv_kvp_sc*)dev->si_drv1;
  717 
  718         hv_kvp_log_info("%s: Closing device \"hv_kvp_device\".\n", __func__);
  719         sc->dev_accessed = false;
  720         sc->register_done = false;
  721         return (0);
  722 }
  723 
  724 
  725 /*
  726  * hv_kvp_daemon read invokes this function
  727  * acts as a send to daemon
  728  */
  729 static int
  730 hv_kvp_dev_daemon_read(struct cdev *dev, struct uio *uio, int ioflag __unused)
  731 {
  732         size_t amt;
  733         int error = 0;
  734         struct hv_kvp_msg *hv_kvp_dev_buf;
  735         hv_kvp_sc *sc = (hv_kvp_sc*)dev->si_drv1;
  736 
  737         /* Read is not allowed util registering is done. */
  738         if (!sc->register_done)
  739                 return (EPERM);
  740 
  741         sema_wait(&sc->dev_sema);
  742 
  743         hv_kvp_dev_buf = malloc(sizeof(*hv_kvp_dev_buf), M_TEMP, M_WAITOK);
  744         memcpy(hv_kvp_dev_buf, &sc->daemon_kvp_msg, sizeof(struct hv_kvp_msg));
  745 
  746         amt = MIN(uio->uio_resid, uio->uio_offset >= BUFFERSIZE + 1 ? 0 :
  747                 BUFFERSIZE + 1 - uio->uio_offset);
  748 
  749         if ((error = uiomove(hv_kvp_dev_buf, amt, uio)) != 0)
  750                 hv_kvp_log_info("%s: hv_kvp uiomove read failed!\n", __func__);
  751 
  752         free(hv_kvp_dev_buf, M_TEMP);
  753         return (error);
  754 }
  755 
  756 
  757 /*
  758  * hv_kvp_daemon write invokes this function
  759  * acts as a receive from daemon
  760  */
  761 static int
  762 hv_kvp_dev_daemon_write(struct cdev *dev, struct uio *uio, int ioflag __unused)
  763 {
  764         size_t amt;
  765         int error = 0;
  766         struct hv_kvp_msg *hv_kvp_dev_buf;
  767         hv_kvp_sc *sc = (hv_kvp_sc*)dev->si_drv1;
  768 
  769         uio->uio_offset = 0;
  770         hv_kvp_dev_buf = malloc(sizeof(*hv_kvp_dev_buf), M_TEMP, M_WAITOK);
  771 
  772         amt = MIN(uio->uio_resid, BUFFERSIZE);
  773         error = uiomove(hv_kvp_dev_buf, amt, uio);
  774 
  775         if (error != 0) {
  776                 free(hv_kvp_dev_buf, M_TEMP);
  777                 return (error);
  778         }
  779         memcpy(&sc->daemon_kvp_msg, hv_kvp_dev_buf, sizeof(struct hv_kvp_msg));
  780 
  781         free(hv_kvp_dev_buf, M_TEMP);
  782         if (sc->register_done == false) {
  783                 if (sc->daemon_kvp_msg.kvp_hdr.operation == HV_KVP_OP_REGISTER) {
  784                         sc->register_done = true;
  785                         hv_kvp_callback(vmbus_get_channel(sc->dev), dev->si_drv1);
  786                 }
  787                 else {
  788                         hv_kvp_log_info("%s, KVP Registration Failed\n", __func__);
  789                         return (EINVAL);
  790                 }
  791         } else {
  792 
  793                 mtx_lock(&sc->pending_mutex);
  794 
  795                 if(!sc->req_timed_out) {
  796                         struct hv_kvp_msg *hmsg = sc->host_kvp_msg;
  797                         struct hv_kvp_msg *umsg = &sc->daemon_kvp_msg;
  798 
  799                         error = hv_kvp_convert_usermsg_to_hostmsg(umsg, hmsg);
  800                         hv_kvp_respond_host(sc, umsg->hdr.error);
  801                         wakeup(sc);
  802                         sc->req_in_progress = false;
  803                         if (umsg->hdr.error != HV_S_OK)
  804                                 hv_kvp_log_info("%s, Error 0x%x from daemon\n",
  805                                     __func__, umsg->hdr.error);
  806                         if (error)
  807                                 hv_kvp_log_info("%s, Error from convert\n", __func__);
  808                 }
  809 
  810                 sc->daemon_busy = false;
  811                 mtx_unlock(&sc->pending_mutex);
  812         }
  813 
  814         return (error);
  815 }
  816 
  817 
  818 /*
  819  * hv_kvp_daemon poll invokes this function to check if data is available
  820  * for daemon to read.
  821  */
  822 static int
  823 hv_kvp_dev_daemon_poll(struct cdev *dev, int events, struct thread *td)
  824 {
  825         int revents = 0;
  826         hv_kvp_sc *sc = (hv_kvp_sc*)dev->si_drv1;
  827 
  828         mtx_lock(&sc->pending_mutex);
  829         /*
  830          * We check global flag daemon_busy for the data availiability for
  831          * userland to read. Deamon_busy is set to true before driver has data
  832          * for daemon to read. It is set to false after daemon sends
  833          * then response back to driver.
  834          */
  835         if (sc->daemon_busy == true)
  836                 revents = POLLIN;
  837         else
  838                 selrecord(td, &sc->hv_kvp_selinfo);
  839 
  840         mtx_unlock(&sc->pending_mutex);
  841 
  842         return (revents);
  843 }
  844 
  845 static int
  846 hv_kvp_probe(device_t dev)
  847 {
  848 
  849         return (vmbus_ic_probe(dev, vmbus_kvp_descs));
  850 }
  851 
  852 static int
  853 hv_kvp_attach(device_t dev)
  854 {
  855         int error;
  856         struct sysctl_oid_list *child;
  857         struct sysctl_ctx_list *ctx;
  858 
  859         hv_kvp_sc *sc = (hv_kvp_sc*)device_get_softc(dev);
  860 
  861         sc->dev = dev;
  862         sema_init(&sc->dev_sema, 0, "hv_kvp device semaphore");
  863         mtx_init(&sc->pending_mutex, "hv-kvp pending mutex",
  864                 NULL, MTX_DEF);
  865 
  866         ctx = device_get_sysctl_ctx(dev);
  867         child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
  868 
  869         SYSCTL_ADD_INT(ctx, child, OID_AUTO, "hv_kvp_log",
  870             CTLFLAG_RWTUN, &hv_kvp_log, 0, "Hyperv KVP service log level");
  871 
  872         TASK_INIT(&sc->task, 0, hv_kvp_process_request, sc);
  873 
  874         /* create character device */
  875         error = make_dev_p(MAKEDEV_CHECKNAME | MAKEDEV_WAITOK,
  876                         &sc->hv_kvp_dev,
  877                         &hv_kvp_cdevsw,
  878                         0,
  879                         UID_ROOT,
  880                         GID_WHEEL,
  881                         0640,
  882                         "hv_kvp_dev");
  883 
  884         if (error != 0)
  885                 return (error);
  886         sc->hv_kvp_dev->si_drv1 = sc;
  887 
  888         return (vmbus_ic_attach(dev, hv_kvp_callback));
  889 }
  890 
  891 static int
  892 hv_kvp_detach(device_t dev)
  893 {
  894         hv_kvp_sc *sc = (hv_kvp_sc*)device_get_softc(dev);
  895 
  896         if (sc->daemon_task != NULL) {
  897                 PROC_LOCK(sc->daemon_task);
  898                 kern_psignal(sc->daemon_task, SIGKILL);
  899                 PROC_UNLOCK(sc->daemon_task);
  900         }
  901 
  902         destroy_dev(sc->hv_kvp_dev);
  903         return (vmbus_ic_detach(dev));
  904 }
  905 
  906 static device_method_t kvp_methods[] = {
  907         /* Device interface */
  908         DEVMETHOD(device_probe, hv_kvp_probe),
  909         DEVMETHOD(device_attach, hv_kvp_attach),
  910         DEVMETHOD(device_detach, hv_kvp_detach),
  911         { 0, 0 }
  912 };
  913 
  914 static driver_t kvp_driver = { "hvkvp", kvp_methods, sizeof(hv_kvp_sc)};
  915 
  916 DRIVER_MODULE(hv_kvp, vmbus, kvp_driver, NULL, NULL);
  917 MODULE_VERSION(hv_kvp, 1);
  918 MODULE_DEPEND(hv_kvp, vmbus, 1, 1, 1);

Cache object: 3c8914f87b9b4537f59d2576e19d1728


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.