Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * An implementation of file copy service.
0004  *
0005  * Copyright (C) 2014, Microsoft, Inc.
0006  *
0007  * Author : K. Y. Srinivasan <ksrinivasan@novell.com>
0008  */
0009 
0010 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0011 
0012 #include <linux/nls.h>
0013 #include <linux/workqueue.h>
0014 #include <linux/hyperv.h>
0015 #include <linux/sched.h>
0016 #include <asm/hyperv-tlfs.h>
0017 
0018 #include "hyperv_vmbus.h"
0019 #include "hv_utils_transport.h"
0020 
0021 #define WIN8_SRV_MAJOR      1
0022 #define WIN8_SRV_MINOR      1
0023 #define WIN8_SRV_VERSION    (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
0024 
0025 #define FCOPY_VER_COUNT 1
0026 static const int fcopy_versions[] = {
0027     WIN8_SRV_VERSION
0028 };
0029 
0030 #define FW_VER_COUNT 1
0031 static const int fw_versions[] = {
0032     UTIL_FW_VERSION
0033 };
0034 
0035 /*
0036  * Global state maintained for transaction that is being processed.
0037  * For a class of integration services, including the "file copy service",
0038  * the specified protocol is a "request/response" protocol which means that
0039  * there can only be single outstanding transaction from the host at any
0040  * given point in time. We use this to simplify memory management in this
0041  * driver - we cache and process only one message at a time.
0042  *
0043  * While the request/response protocol is guaranteed by the host, we further
0044  * ensure this by serializing packet processing in this driver - we do not
0045  * read additional packets from the VMBUs until the current packet is fully
0046  * handled.
0047  */
0048 
0049 static struct {
0050     int state;   /* hvutil_device_state */
0051     int recv_len; /* number of bytes received. */
0052     struct hv_fcopy_hdr  *fcopy_msg; /* current message */
0053     struct vmbus_channel *recv_channel; /* chn we got the request */
0054     u64 recv_req_id; /* request ID. */
0055 } fcopy_transaction;
0056 
0057 static void fcopy_respond_to_host(int error);
0058 static void fcopy_send_data(struct work_struct *dummy);
0059 static void fcopy_timeout_func(struct work_struct *dummy);
0060 static DECLARE_DELAYED_WORK(fcopy_timeout_work, fcopy_timeout_func);
0061 static DECLARE_WORK(fcopy_send_work, fcopy_send_data);
0062 static const char fcopy_devname[] = "vmbus/hv_fcopy";
0063 static u8 *recv_buffer;
0064 static struct hvutil_transport *hvt;
0065 /*
0066  * This state maintains the version number registered by the daemon.
0067  */
0068 static int dm_reg_value;
0069 
0070 static void fcopy_poll_wrapper(void *channel)
0071 {
0072     /* Transaction is finished, reset the state here to avoid races. */
0073     fcopy_transaction.state = HVUTIL_READY;
0074     tasklet_schedule(&((struct vmbus_channel *)channel)->callback_event);
0075 }
0076 
0077 static void fcopy_timeout_func(struct work_struct *dummy)
0078 {
0079     /*
0080      * If the timer fires, the user-mode component has not responded;
0081      * process the pending transaction.
0082      */
0083     fcopy_respond_to_host(HV_E_FAIL);
0084     hv_poll_channel(fcopy_transaction.recv_channel, fcopy_poll_wrapper);
0085 }
0086 
0087 static void fcopy_register_done(void)
0088 {
0089     pr_debug("FCP: userspace daemon registered\n");
0090     hv_poll_channel(fcopy_transaction.recv_channel, fcopy_poll_wrapper);
0091 }
0092 
0093 static int fcopy_handle_handshake(u32 version)
0094 {
0095     u32 our_ver = FCOPY_CURRENT_VERSION;
0096 
0097     switch (version) {
0098     case FCOPY_VERSION_0:
0099         /* Daemon doesn't expect us to reply */
0100         dm_reg_value = version;
0101         break;
0102     case FCOPY_VERSION_1:
0103         /* Daemon expects us to reply with our own version */
0104         if (hvutil_transport_send(hvt, &our_ver, sizeof(our_ver),
0105             fcopy_register_done))
0106             return -EFAULT;
0107         dm_reg_value = version;
0108         break;
0109     default:
0110         /*
0111          * For now we will fail the registration.
0112          * If and when we have multiple versions to
0113          * deal with, we will be backward compatible.
0114          * We will add this code when needed.
0115          */
0116         return -EINVAL;
0117     }
0118     pr_debug("FCP: userspace daemon ver. %d connected\n", version);
0119     return 0;
0120 }
0121 
0122 static void fcopy_send_data(struct work_struct *dummy)
0123 {
0124     struct hv_start_fcopy *smsg_out = NULL;
0125     int operation = fcopy_transaction.fcopy_msg->operation;
0126     struct hv_start_fcopy *smsg_in;
0127     void *out_src;
0128     int rc, out_len;
0129 
0130     /*
0131      * The  strings sent from the host are encoded in
0132      * utf16; convert it to utf8 strings.
0133      * The host assures us that the utf16 strings will not exceed
0134      * the max lengths specified. We will however, reserve room
0135      * for the string terminating character - in the utf16s_utf8s()
0136      * function we limit the size of the buffer where the converted
0137      * string is placed to W_MAX_PATH -1 to guarantee
0138      * that the strings can be properly terminated!
0139      */
0140 
0141     switch (operation) {
0142     case START_FILE_COPY:
0143         out_len = sizeof(struct hv_start_fcopy);
0144         smsg_out = kzalloc(sizeof(*smsg_out), GFP_KERNEL);
0145         if (!smsg_out)
0146             return;
0147 
0148         smsg_out->hdr.operation = operation;
0149         smsg_in = (struct hv_start_fcopy *)fcopy_transaction.fcopy_msg;
0150 
0151         utf16s_to_utf8s((wchar_t *)smsg_in->file_name, W_MAX_PATH,
0152                 UTF16_LITTLE_ENDIAN,
0153                 (__u8 *)&smsg_out->file_name, W_MAX_PATH - 1);
0154 
0155         utf16s_to_utf8s((wchar_t *)smsg_in->path_name, W_MAX_PATH,
0156                 UTF16_LITTLE_ENDIAN,
0157                 (__u8 *)&smsg_out->path_name, W_MAX_PATH - 1);
0158 
0159         smsg_out->copy_flags = smsg_in->copy_flags;
0160         smsg_out->file_size = smsg_in->file_size;
0161         out_src = smsg_out;
0162         break;
0163 
0164     case WRITE_TO_FILE:
0165         out_src = fcopy_transaction.fcopy_msg;
0166         out_len = sizeof(struct hv_do_fcopy);
0167         break;
0168     default:
0169         out_src = fcopy_transaction.fcopy_msg;
0170         out_len = fcopy_transaction.recv_len;
0171         break;
0172     }
0173 
0174     fcopy_transaction.state = HVUTIL_USERSPACE_REQ;
0175     rc = hvutil_transport_send(hvt, out_src, out_len, NULL);
0176     if (rc) {
0177         pr_debug("FCP: failed to communicate to the daemon: %d\n", rc);
0178         if (cancel_delayed_work_sync(&fcopy_timeout_work)) {
0179             fcopy_respond_to_host(HV_E_FAIL);
0180             fcopy_transaction.state = HVUTIL_READY;
0181         }
0182     }
0183     kfree(smsg_out);
0184 }
0185 
0186 /*
0187  * Send a response back to the host.
0188  */
0189 
0190 static void
0191 fcopy_respond_to_host(int error)
0192 {
0193     struct icmsg_hdr *icmsghdr;
0194     u32 buf_len;
0195     struct vmbus_channel *channel;
0196     u64 req_id;
0197 
0198     /*
0199      * Copy the global state for completing the transaction. Note that
0200      * only one transaction can be active at a time. This is guaranteed
0201      * by the file copy protocol implemented by the host. Furthermore,
0202      * the "transaction active" state we maintain ensures that there can
0203      * only be one active transaction at a time.
0204      */
0205 
0206     buf_len = fcopy_transaction.recv_len;
0207     channel = fcopy_transaction.recv_channel;
0208     req_id = fcopy_transaction.recv_req_id;
0209 
0210     icmsghdr = (struct icmsg_hdr *)
0211             &recv_buffer[sizeof(struct vmbuspipe_hdr)];
0212 
0213     if (channel->onchannel_callback == NULL)
0214         /*
0215          * We have raced with util driver being unloaded;
0216          * silently return.
0217          */
0218         return;
0219 
0220     icmsghdr->status = error;
0221     icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
0222     vmbus_sendpacket(channel, recv_buffer, buf_len, req_id,
0223                 VM_PKT_DATA_INBAND, 0);
0224 }
0225 
0226 void hv_fcopy_onchannelcallback(void *context)
0227 {
0228     struct vmbus_channel *channel = context;
0229     u32 recvlen;
0230     u64 requestid;
0231     struct hv_fcopy_hdr *fcopy_msg;
0232     struct icmsg_hdr *icmsghdr;
0233     int fcopy_srv_version;
0234 
0235     if (fcopy_transaction.state > HVUTIL_READY)
0236         return;
0237 
0238     if (vmbus_recvpacket(channel, recv_buffer, HV_HYP_PAGE_SIZE * 2, &recvlen, &requestid)) {
0239         pr_err_ratelimited("Fcopy request received. Could not read into recv buf\n");
0240         return;
0241     }
0242 
0243     if (!recvlen)
0244         return;
0245 
0246     /* Ensure recvlen is big enough to read header data */
0247     if (recvlen < ICMSG_HDR) {
0248         pr_err_ratelimited("Fcopy request received. Packet length too small: %d\n",
0249                    recvlen);
0250         return;
0251     }
0252 
0253     icmsghdr = (struct icmsg_hdr *)&recv_buffer[
0254             sizeof(struct vmbuspipe_hdr)];
0255 
0256     if (icmsghdr->icmsgtype == ICMSGTYPE_NEGOTIATE) {
0257         if (vmbus_prep_negotiate_resp(icmsghdr,
0258                 recv_buffer, recvlen,
0259                 fw_versions, FW_VER_COUNT,
0260                 fcopy_versions, FCOPY_VER_COUNT,
0261                 NULL, &fcopy_srv_version)) {
0262 
0263             pr_info("FCopy IC version %d.%d\n",
0264                 fcopy_srv_version >> 16,
0265                 fcopy_srv_version & 0xFFFF);
0266         }
0267     } else if (icmsghdr->icmsgtype == ICMSGTYPE_FCOPY) {
0268         /* Ensure recvlen is big enough to contain hv_fcopy_hdr */
0269         if (recvlen < ICMSG_HDR + sizeof(struct hv_fcopy_hdr)) {
0270             pr_err_ratelimited("Invalid Fcopy hdr. Packet length too small: %u\n",
0271                        recvlen);
0272             return;
0273         }
0274         fcopy_msg = (struct hv_fcopy_hdr *)&recv_buffer[ICMSG_HDR];
0275 
0276         /*
0277          * Stash away this global state for completing the
0278          * transaction; note transactions are serialized.
0279          */
0280 
0281         fcopy_transaction.recv_len = recvlen;
0282         fcopy_transaction.recv_req_id = requestid;
0283         fcopy_transaction.fcopy_msg = fcopy_msg;
0284 
0285         if (fcopy_transaction.state < HVUTIL_READY) {
0286             /* Userspace is not registered yet */
0287             fcopy_respond_to_host(HV_E_FAIL);
0288             return;
0289         }
0290         fcopy_transaction.state = HVUTIL_HOSTMSG_RECEIVED;
0291 
0292         /*
0293          * Send the information to the user-level daemon.
0294          */
0295         schedule_work(&fcopy_send_work);
0296         schedule_delayed_work(&fcopy_timeout_work,
0297                       HV_UTIL_TIMEOUT * HZ);
0298         return;
0299     } else {
0300         pr_err_ratelimited("Fcopy request received. Invalid msg type: %d\n",
0301                    icmsghdr->icmsgtype);
0302         return;
0303     }
0304     icmsghdr->icflags = ICMSGHDRFLAG_TRANSACTION | ICMSGHDRFLAG_RESPONSE;
0305     vmbus_sendpacket(channel, recv_buffer, recvlen, requestid,
0306             VM_PKT_DATA_INBAND, 0);
0307 }
0308 
0309 /* Callback when data is received from userspace */
0310 static int fcopy_on_msg(void *msg, int len)
0311 {
0312     int *val = (int *)msg;
0313 
0314     if (len != sizeof(int))
0315         return -EINVAL;
0316 
0317     if (fcopy_transaction.state == HVUTIL_DEVICE_INIT)
0318         return fcopy_handle_handshake(*val);
0319 
0320     if (fcopy_transaction.state != HVUTIL_USERSPACE_REQ)
0321         return -EINVAL;
0322 
0323     /*
0324      * Complete the transaction by forwarding the result
0325      * to the host. But first, cancel the timeout.
0326      */
0327     if (cancel_delayed_work_sync(&fcopy_timeout_work)) {
0328         fcopy_transaction.state = HVUTIL_USERSPACE_RECV;
0329         fcopy_respond_to_host(*val);
0330         hv_poll_channel(fcopy_transaction.recv_channel,
0331                 fcopy_poll_wrapper);
0332     }
0333 
0334     return 0;
0335 }
0336 
0337 static void fcopy_on_reset(void)
0338 {
0339     /*
0340      * The daemon has exited; reset the state.
0341      */
0342     fcopy_transaction.state = HVUTIL_DEVICE_INIT;
0343 
0344     if (cancel_delayed_work_sync(&fcopy_timeout_work))
0345         fcopy_respond_to_host(HV_E_FAIL);
0346 }
0347 
0348 int hv_fcopy_init(struct hv_util_service *srv)
0349 {
0350     recv_buffer = srv->recv_buffer;
0351     fcopy_transaction.recv_channel = srv->channel;
0352     fcopy_transaction.recv_channel->max_pkt_size = HV_HYP_PAGE_SIZE * 2;
0353 
0354     /*
0355      * When this driver loads, the user level daemon that
0356      * processes the host requests may not yet be running.
0357      * Defer processing channel callbacks until the daemon
0358      * has registered.
0359      */
0360     fcopy_transaction.state = HVUTIL_DEVICE_INIT;
0361 
0362     hvt = hvutil_transport_init(fcopy_devname, 0, 0,
0363                     fcopy_on_msg, fcopy_on_reset);
0364     if (!hvt)
0365         return -EFAULT;
0366 
0367     return 0;
0368 }
0369 
0370 static void hv_fcopy_cancel_work(void)
0371 {
0372     cancel_delayed_work_sync(&fcopy_timeout_work);
0373     cancel_work_sync(&fcopy_send_work);
0374 }
0375 
0376 int hv_fcopy_pre_suspend(void)
0377 {
0378     struct vmbus_channel *channel = fcopy_transaction.recv_channel;
0379     struct hv_fcopy_hdr *fcopy_msg;
0380 
0381     /*
0382      * Fake a CANCEL_FCOPY message for the user space daemon in case the
0383      * daemon is in the middle of copying some file. It doesn't matter if
0384      * there is already a message pending to be delivered to the user
0385      * space since we force fcopy_transaction.state to be HVUTIL_READY, so
0386      * the user space daemon's write() will fail with EINVAL (see
0387      * fcopy_on_msg()), and the daemon will reset the device by closing
0388      * and re-opening it.
0389      */
0390     fcopy_msg = kzalloc(sizeof(*fcopy_msg), GFP_KERNEL);
0391     if (!fcopy_msg)
0392         return -ENOMEM;
0393 
0394     tasklet_disable(&channel->callback_event);
0395 
0396     fcopy_msg->operation = CANCEL_FCOPY;
0397 
0398     hv_fcopy_cancel_work();
0399 
0400     /* We don't care about the return value. */
0401     hvutil_transport_send(hvt, fcopy_msg, sizeof(*fcopy_msg), NULL);
0402 
0403     kfree(fcopy_msg);
0404 
0405     fcopy_transaction.state = HVUTIL_READY;
0406 
0407     /* tasklet_enable() will be called in hv_fcopy_pre_resume(). */
0408     return 0;
0409 }
0410 
0411 int hv_fcopy_pre_resume(void)
0412 {
0413     struct vmbus_channel *channel = fcopy_transaction.recv_channel;
0414 
0415     tasklet_enable(&channel->callback_event);
0416 
0417     return 0;
0418 }
0419 
0420 void hv_fcopy_deinit(void)
0421 {
0422     fcopy_transaction.state = HVUTIL_DEVICE_DYING;
0423 
0424     hv_fcopy_cancel_work();
0425 
0426     hvutil_transport_destroy(hvt);
0427 }