From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754316AbcEOPNA (ORCPT ); Sun, 15 May 2016 11:13:00 -0400 Received: from p3plsmtps2ded03.prod.phx3.secureserver.net ([208.109.80.60]:51142 "EHLO p3plsmtps2ded03.prod.phx3.secureserver.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752068AbcEOPM4 (ORCPT ); Sun, 15 May 2016 11:12:56 -0400 x-originating-ip: 72.167.245.219 From: Dexuan Cui To: gregkh@linuxfoundation.org, davem@davemloft.net, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, devel@linuxdriverproject.org, olaf@aepfle.de, apw@canonical.com, jasowang@redhat.com, cavery@redhat.com, kys@microsoft.com, haiyangz@microsoft.com Cc: joe@perches.com, vkuznets@redhat.com Subject: =?UTF-8?q?=5BPATCH=20v11=20net-next=201/1=5D=20hv=5Fsock=3A=20introduce=20Hyper-V=20Sockets?= Date: Sun, 15 May 2016 09:53:11 -0700 Message-Id: <1463331191-6720-1-git-send-email-decui@microsoft.com> X-Mailer: git-send-email 1.7.4.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-CMAE-Envelope: MS4wfDKQGRimX13EqSD1TMvWCbYSom2XLaty4SgOaBSG0Z9Wku2kQZKvAusLeTKDivAQhx+afYve32A8GsMPYnJrP/9s6Id4MetzfvVHxq7LTp/WLhzVcCBV R7uFnEJlpS1MNj8gNousOkJ/xtx7PEHEov/Cz96/lC9Nh++MkXm+yZgZWhcAzn4ob1H3BbwzzU7i+yOCIgqt5X6JwixMBDHc3p7rUKKHAc8EjJXq94t9qWRM QNz2cV5zprbVo7QOmfEgo3h+nSXG/z/HpKaghkP7XHtkv3Hph0K/Smrn3Df4mjmDxehwretw8dcpLQzJBrlbW9rTIlPIW4L7Cbb95m0xWvVUgHWYX8XHetNM 3SsJl5LiVQBa7vrkwO+4ke/PokjPDjiasl6yqwYX7hL5YtYVdPpxOwA3INz4C56P0SAw2MsuK56+XQ769lvJIg4/OvipMCs1rGKCpKJo0p6Qw1BbO2WIlpKb 659WB5gHB/pzAGlFM+QC6UrSvT/0X5txseyL8DPIfcEpQR1oJjQBF2koAeucwGeN8GTrFxq+ela2kyQ9zZUElqEhQsJbpAPwSCLCIA== Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hyper-V Sockets (hv_sock) supplies a byte-stream based communication mechanism between the host and the guest. It's somewhat like TCP over VMBus, but the transportation layer (VMBus) is much simpler than IP. With Hyper-V Sockets, applications between the host and the guest can talk to each other directly by the traditional BSD-style socket APIs. Hyper-V Sockets is only available on new Windows hosts, like Windows Server 2016. More info is in this article "Make your own integration services": https://msdn.microsoft.com/en-us/virtualization/hyperv_on_windows/develop/make_mgmt_service The patch implements the necessary support in the guest side by introducing a new socket address family AF_HYPERV. Signed-off-by: Dexuan Cui Cc: "K. Y. Srinivasan" Cc: Haiyang Zhang Cc: Vitaly Kuznetsov Cc: Cathy Avery --- You can also get the patch on this branch: https://github.com/dcui/linux/commits/decui/hv_sock/net-next/20160515_v11 For the change log before v10, please see https://lkml.org/lkml/2016/5/4/532 In v10, the main changes consist of 1) minimize struct hvsock_sock by making the send/recv buffers pointers. the buffers are allocated by kmalloc() in __hvsock_create(). 2) minimize the sizes of the send/recv buffers and the vmbus ringbuffers. In v11, the changes are: 1) add module params: send_ring_page, recv_ring_page. They can be used to enlarge the ringbuffer size to get better performance, e.g., # modprobe hv_sock recv_ring_page=16 send_ring_page=16 By default, recv_ring_page is 3 and send_ring_page is 2. 2) add module param max_socket_number (the default is 1024). A user can enlarge the number to create more than 1024 hv_sock sockets. By default, 1024 sockets take about 1024 * (3+2+1+1) * 4KB = 28M bytes. (Here 1+1 means 1 page for send/recv buffers per connection, respectively.) 3) implement the TODO in hvsock_shutdown(). 4) fix a bug in hvsock_close_connection(): I remove "sk->sk_socket->state = SS_UNCONNECTED;" -- actually this line is not really useful. For a connection triggered by a host app’s connect(), sk->sk_socket remains NULL before the connection is accepted by the server app (in Linux VM): see hvsock_accept() -> hvsock_accept_wait() -> sock_graft(connected, newsock). If the host app exits before the server app’s accept() returns, the host can send a rescind-message to close the connection and later in the Linux VM’s message handler i.e. vmbus_onoffer_rescind()), Linux will get a NULL de-referencing crash. 5) fix a bug in hvsock_open_connection() I move the vmbus_set_chn_rescind_callback() to a later place, because when vmbus_open() fails, hvsock_close_connection() can do nothing and we count on vmbus_onoffer_rescind() -> vmbus_device_unregister() to clean up the device. 6) some stylistic modificiation. MAINTAINERS | 2 + include/linux/hyperv.h | 14 + include/linux/socket.h | 4 +- include/net/af_hvsock.h | 78 +++ include/uapi/linux/hyperv.h | 25 + net/Kconfig | 1 + net/Makefile | 1 + net/hv_sock/Kconfig | 10 + net/hv_sock/Makefile | 3 + net/hv_sock/af_hvsock.c | 1520 +++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 1657 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index b57df66..c9fe2c6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5271,7 +5271,9 @@ F: drivers/pci/host/pci-hyperv.c F: drivers/net/hyperv/ F: drivers/scsi/storvsc_drv.c F: drivers/video/fbdev/hyperv_fb.c +F: net/hv_sock/ F: include/linux/hyperv.h +F: include/net/af_hvsock.h F: tools/hv/ F: Documentation/ABI/stable/sysfs-bus-vmbus diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index aa0fadc..7be7237 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -1338,4 +1338,18 @@ extern __u32 vmbus_proto_version; int vmbus_send_tl_connect_request(const uuid_le *shv_guest_servie_id, const uuid_le *shv_host_servie_id); +struct vmpipe_proto_header { + u32 pkt_type; + u32 data_size; +}; + +#define HVSOCK_HEADER_LEN (sizeof(struct vmpacket_descriptor) + \ + sizeof(struct vmpipe_proto_header)) + +/* See 'prev_indices' in hv_ringbuffer_read(), hv_ringbuffer_write() */ +#define PREV_INDICES_LEN (sizeof(u64)) + +#define HVSOCK_PKT_LEN(payload_len) (HVSOCK_HEADER_LEN + \ + ALIGN((payload_len), 8) + \ + PREV_INDICES_LEN) #endif /* _HYPERV_H */ diff --git a/include/linux/socket.h b/include/linux/socket.h index b5cc5a6..0b68b58 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -202,8 +202,9 @@ struct ucred { #define AF_VSOCK 40 /* vSockets */ #define AF_KCM 41 /* Kernel Connection Multiplexor*/ #define AF_QIPCRTR 42 /* Qualcomm IPC Router */ +#define AF_HYPERV 43 /* Hyper-V Sockets */ -#define AF_MAX 43 /* For now.. */ +#define AF_MAX 44 /* For now.. */ /* Protocol families, same as address families. */ #define PF_UNSPEC AF_UNSPEC @@ -251,6 +252,7 @@ struct ucred { #define PF_VSOCK AF_VSOCK #define PF_KCM AF_KCM #define PF_QIPCRTR AF_QIPCRTR +#define PF_HYPERV AF_HYPERV #define PF_MAX AF_MAX /* Maximum queue length specifiable by listen. */ diff --git a/include/net/af_hvsock.h b/include/net/af_hvsock.h new file mode 100644 index 0000000..7c8c41e --- /dev/null +++ b/include/net/af_hvsock.h @@ -0,0 +1,78 @@ +#ifndef __AF_HVSOCK_H__ +#define __AF_HVSOCK_H__ + +#include +#include +#include + +/* Note: 3-page is the minimal recv ringbuffer size by default: + * + * the 1st page is used as the shared read/write index etc, rather than data: + * see hv_ringbuffer_init(); + * + * the payload length in the vmbus pipe message received from the host can + * be 4096 bytes, and considing the header of HVSOCK_HEADER_LEN bytes, we + * need at least 2 extra pages for ringbuffer data. + */ +#define HVSOCK_RCV_BUF_SZ PAGE_SIZE +#define DEF_RINGBUFFER_PAGES_HVSOCK_RCV 3 + +/* As to send, here let's make sure the hvsock_send_buf struct can be held in 1 + * page, and since we want to use 2 pages for the send ringbuffer size (this is + * the minimal size by default, because the 1st page of the two is used as the + * shared read/write index etc, rather than data), we only have 1 page for + * ringbuffer data, this means: the max payload length for hvsock data is + * PAGE_SIZE - HVSOCK_PKT_LEN(0). And, let's reduce the length by 8-bytes + * because the ringbuffer can't be 100% full: see hv_ringbuffer_write(). + */ +#define HVSOCK_SND_BUF_SZ (PAGE_SIZE - HVSOCK_PKT_LEN(0) - 8) +#define DEF_RINGBUFFER_PAGES_HVSOCK_SND 2 + +/* We only send data when the available space is "big enough". This artificial + * value must be less than HVSOCK_SND_BUF_SZ. + * + */ +#define HVSOCK_SND_THRESHOLD (PAGE_SIZE / 2) + +#define sk_to_hvsock(__sk) ((struct hvsock_sock *)(__sk)) +#define hvsock_to_sk(__hvsk) ((struct sock *)(__hvsk)) + +struct hvsock_send_buf { + struct vmpipe_proto_header hdr; + u8 buf[HVSOCK_SND_BUF_SZ]; +}; + +struct hvsock_recv_buf { + struct vmpipe_proto_header hdr; + u8 buf[HVSOCK_RCV_BUF_SZ]; + + unsigned int data_len; + unsigned int data_offset; +}; + +struct hvsock_sock { + /* sk must be the first member. */ + struct sock sk; + + struct sockaddr_hv local_addr; + struct sockaddr_hv remote_addr; + + /* protected by the global hvsock_mutex */ + struct list_head bound_list; + struct list_head connected_list; + + struct list_head accept_queue; + /* used by enqueue and dequeue */ + struct mutex accept_queue_mutex; + + struct delayed_work dwork; + + u32 peer_shutdown; + + struct vmbus_channel *channel; + + struct hvsock_send_buf *send; + struct hvsock_recv_buf *recv; +}; + +#endif /* __AF_HVSOCK_H__ */ diff --git a/include/uapi/linux/hyperv.h b/include/uapi/linux/hyperv.h index e347b24..408b832 100644 --- a/include/uapi/linux/hyperv.h +++ b/include/uapi/linux/hyperv.h @@ -26,6 +26,7 @@ #define _UAPI_HYPERV_H #include +#include /* * Framework version for util services. @@ -396,4 +397,28 @@ struct hv_kvp_ip_msg { struct hv_kvp_ipaddr_value kvp_ip_val; } __attribute__((packed)); +/* + * This is the address fromat of Hyper-V Sockets. + * Note: here we just borrow the kernel's built-in type uuid_le. When + * an application calls bind() or connect(), the 2 members of struct + * sockaddr_hv must be of GUID. + * The GUID format differs from the UUID format only in the byte order of + * the first 3 fields. Refer to: + * https://en.wikipedia.org/wiki/Globally_unique_identifier + */ +#define guid_t uuid_le +struct sockaddr_hv { + __kernel_sa_family_t shv_family; /* Address family */ + __le16 reserved; /* Must be Zero */ + guid_t shv_vm_id; /* VM ID */ + guid_t shv_service_id; /* Service ID */ +}; + +#define SHV_VMID_GUEST NULL_UUID_LE +#define SHV_VMID_HOST NULL_UUID_LE + +#define SHV_SERVICE_ID_ANY NULL_UUID_LE + +#define SHV_PROTO_RAW 1 + #endif /* _UAPI_HYPERV_H */ diff --git a/net/Kconfig b/net/Kconfig index b841c42..366e61f 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -231,6 +231,7 @@ source "net/dns_resolver/Kconfig" source "net/batman-adv/Kconfig" source "net/openvswitch/Kconfig" source "net/vmw_vsock/Kconfig" +source "net/hv_sock/Kconfig" source "net/netlink/Kconfig" source "net/mpls/Kconfig" source "net/hsr/Kconfig" diff --git a/net/Makefile b/net/Makefile index bdd1455..ec175dd 100644 --- a/net/Makefile +++ b/net/Makefile @@ -70,6 +70,7 @@ obj-$(CONFIG_BATMAN_ADV) += batman-adv/ obj-$(CONFIG_NFC) += nfc/ obj-$(CONFIG_OPENVSWITCH) += openvswitch/ obj-$(CONFIG_VSOCKETS) += vmw_vsock/ +obj-$(CONFIG_HYPERV_SOCK) += hv_sock/ obj-$(CONFIG_MPLS) += mpls/ obj-$(CONFIG_HSR) += hsr/ ifneq ($(CONFIG_NET_SWITCHDEV),) diff --git a/net/hv_sock/Kconfig b/net/hv_sock/Kconfig new file mode 100644 index 0000000..1f41848 --- /dev/null +++ b/net/hv_sock/Kconfig @@ -0,0 +1,10 @@ +config HYPERV_SOCK + tristate "Hyper-V Sockets" + depends on HYPERV + default m if HYPERV + help + Hyper-V Sockets is somewhat like TCP over VMBus, allowing + communication between Linux guest and Hyper-V host without TCP/IP. + + To compile this driver as a module, choose M here: the module + will be called hv_sock. diff --git a/net/hv_sock/Makefile b/net/hv_sock/Makefile new file mode 100644 index 0000000..716c012 --- /dev/null +++ b/net/hv_sock/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_HYPERV_SOCK) += hv_sock.o + +hv_sock-y += af_hvsock.o diff --git a/net/hv_sock/af_hvsock.c b/net/hv_sock/af_hvsock.c new file mode 100644 index 0000000..b91bd60 --- /dev/null +++ b/net/hv_sock/af_hvsock.c @@ -0,0 +1,1520 @@ +/* + * Hyper-V Sockets -- a socket-based communication channel between the + * Hyper-V host and the virtual machines running on it. + * + * Copyright(c) 2016, Microsoft Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include + +static uint send_ring_page = DEF_RINGBUFFER_PAGES_HVSOCK_SND; +static uint recv_ring_page = DEF_RINGBUFFER_PAGES_HVSOCK_RCV; +static uint max_socket_number = 1024; + +static atomic_t total_num_hvsock = ATOMIC_INIT(0); + +module_param(send_ring_page, uint, 0444); +MODULE_PARM_DESC(send_ring_page, "Send ring buffer size (# of pages)"); + +module_param(recv_ring_page, uint, 0444); +MODULE_PARM_DESC(recv_ring_page, "Receive ring buffer size (# of pages)"); + +module_param(max_socket_number, uint, 0644); +MODULE_PARM_DESC(max_socket_number, "The max number of created sockets"); + +static struct proto hvsock_proto = { + .name = "HV_SOCK", + .owner = THIS_MODULE, + .obj_size = sizeof(struct hvsock_sock), +}; + +#define SS_LISTEN 255 + +static LIST_HEAD(hvsock_bound_list); +static LIST_HEAD(hvsock_connected_list); +static DEFINE_MUTEX(hvsock_mutex); + +static bool uuid_equals(uuid_le u1, uuid_le u2) +{ + return !uuid_le_cmp(u1, u2); +} + +static struct sock *hvsock_find_bound_socket(const struct sockaddr_hv *addr) +{ + struct hvsock_sock *hvsk; + + list_for_each_entry(hvsk, &hvsock_bound_list, bound_list) { + if (uuid_equals(addr->shv_service_id, + hvsk->local_addr.shv_service_id)) + return hvsock_to_sk(hvsk); + } + return NULL; +} + +static struct sock *hvsock_find_connected_socket_by_channel( + const struct vmbus_channel *channel) +{ + struct hvsock_sock *hvsk; + + list_for_each_entry(hvsk, &hvsock_connected_list, connected_list) { + if (hvsk->channel == channel) + return hvsock_to_sk(hvsk); + } + return NULL; +} + +static +void hvsock_enqueue_accept(struct sock *listener, struct sock *connected) +{ + struct hvsock_sock *hvlistener; + struct hvsock_sock *hvconnected; + + hvlistener = sk_to_hvsock(listener); + hvconnected = sk_to_hvsock(connected); + + sock_hold(connected); + sock_hold(listener); + + mutex_lock(&hvlistener->accept_queue_mutex); + list_add_tail(&hvconnected->accept_queue, &hvlistener->accept_queue); + listener->sk_ack_backlog++; + mutex_unlock(&hvlistener->accept_queue_mutex); +} + +static struct sock *hvsock_dequeue_accept(struct sock *listener) +{ + struct hvsock_sock *hvlistener; + struct hvsock_sock *hvconnected; + + hvlistener = sk_to_hvsock(listener); + + mutex_lock(&hvlistener->accept_queue_mutex); + + if (list_empty(&hvlistener->accept_queue)) { + mutex_unlock(&hvlistener->accept_queue_mutex); + return NULL; + } + + hvconnected = list_entry(hvlistener->accept_queue.next, + struct hvsock_sock, accept_queue); + + list_del_init(&hvconnected->accept_queue); + listener->sk_ack_backlog--; + + mutex_unlock(&hvlistener->accept_queue_mutex); + + sock_put(listener); + /* The caller will need a reference on the connected socket so we let + * it call sock_put(). + */ + + return hvsock_to_sk(hvconnected); +} + +static bool hvsock_is_accept_queue_empty(struct sock *sk) +{ + struct hvsock_sock *hvsk = sk_to_hvsock(sk); + int ret; + + mutex_lock(&hvsk->accept_queue_mutex); + ret = list_empty(&hvsk->accept_queue); + mutex_unlock(&hvsk->accept_queue_mutex); + + return ret; +} + +static void hvsock_addr_init(struct sockaddr_hv *addr, uuid_le service_id) +{ + memset(addr, 0, sizeof(*addr)); + addr->shv_family = AF_HYPERV; + addr->shv_service_id = service_id; +} + +static int hvsock_addr_validate(const struct sockaddr_hv *addr) +{ + if (!addr) + return -EFAULT; + + if (addr->shv_family != AF_HYPERV) + return -EAFNOSUPPORT; + + if (addr->reserved != 0) + return -EINVAL; + + return 0; +} + +static bool hvsock_addr_bound(const struct sockaddr_hv *addr) +{ + return !uuid_equals(addr->shv_service_id, SHV_SERVICE_ID_ANY); +} + +static int hvsock_addr_cast(const struct sockaddr *addr, size_t len, + struct sockaddr_hv **out_addr) +{ + if (len < sizeof(**out_addr)) + return -EFAULT; + + *out_addr = (struct sockaddr_hv *)addr; + return hvsock_addr_validate(*out_addr); +} + +static int __hvsock_do_bind(struct hvsock_sock *hvsk, + struct sockaddr_hv *addr) +{ + struct sockaddr_hv hv_addr; + int ret = 0; + + hvsock_addr_init(&hv_addr, addr->shv_service_id); + + mutex_lock(&hvsock_mutex); + + if (uuid_equals(addr->shv_service_id, SHV_SERVICE_ID_ANY)) { + do { + uuid_le_gen(&hv_addr.shv_service_id); + } while (hvsock_find_bound_socket(&hv_addr)); + } else { + if (hvsock_find_bound_socket(&hv_addr)) { + ret = -EADDRINUSE; + goto out; + } + } + + hvsock_addr_init(&hvsk->local_addr, hv_addr.shv_service_id); + + sock_hold(&hvsk->sk); + list_add(&hvsk->bound_list, &hvsock_bound_list); +out: + mutex_unlock(&hvsock_mutex); + + return ret; +} + +static int __hvsock_bind(struct sock *sk, struct sockaddr_hv *addr) +{ + struct hvsock_sock *hvsk = sk_to_hvsock(sk); + int ret; + + if (hvsock_addr_bound(&hvsk->local_addr)) + return -EINVAL; + + switch (sk->sk_socket->type) { + case SOCK_STREAM: + ret = __hvsock_do_bind(hvsk, addr); + break; + + default: + ret = -EINVAL; + break; + } + + return ret; +} + +/* Autobind this socket to the local address if necessary. */ +static int hvsock_auto_bind(struct hvsock_sock *hvsk) +{ + struct sock *sk = hvsock_to_sk(hvsk); + struct sockaddr_hv local_addr; + + if (hvsock_addr_bound(&hvsk->local_addr)) + return 0; + hvsock_addr_init(&local_addr, SHV_SERVICE_ID_ANY); + return __hvsock_bind(sk, &local_addr); +} + +static void hvsock_sk_destruct(struct sock *sk) +{ + struct hvsock_sock *hvsk = sk_to_hvsock(sk); + struct vmbus_channel *channel = hvsk->channel; + + kfree(hvsk->send); + kfree(hvsk->recv); + atomic_dec(&total_num_hvsock); + + if (!channel) + return; + + vmbus_hvsock_device_unregister(channel); +} + +static void __hvsock_release(struct sock *sk) +{ + struct hvsock_sock *hvsk; + struct sock *pending; + + hvsk = sk_to_hvsock(sk); + + mutex_lock(&hvsock_mutex); + + if (!list_empty(&hvsk->bound_list)) { + list_del_init(&hvsk->bound_list); + sock_put(&hvsk->sk); + } + + if (!list_empty(&hvsk->connected_list)) { + list_del_init(&hvsk->connected_list); + sock_put(&hvsk->sk); + } + + mutex_unlock(&hvsock_mutex); + + lock_sock(sk); + sock_orphan(sk); + sk->sk_shutdown = SHUTDOWN_MASK; + + /* Clean up any sockets that never were accepted. */ + while ((pending = hvsock_dequeue_accept(sk)) != NULL) { + __hvsock_release(pending); + sock_put(pending); + } + + release_sock(sk); + sock_put(sk); +} + +static int hvsock_release(struct socket *sock) +{ + /* If accept() is interrupted by a signal, the temporary socket + * struct's sock->sk is NULL. + */ + if (sock->sk) { + __hvsock_release(sock->sk); + sock->sk = NULL; + } + + sock->state = SS_FREE; + return 0; +} + +static int hvsock_create(struct net *net, struct socket *sock, + gfp_t priority, unsigned short type, + struct sock **sk) +{ + struct hvsock_send_buf *send = NULL; + struct hvsock_recv_buf *recv = NULL; + struct hvsock_sock *hvsk; + int ret = -EMFILE; + int num_hvsock; + + num_hvsock = atomic_inc_return(&total_num_hvsock); + if (num_hvsock > max_socket_number) + goto err; + + ret = -ENOMEM; + send = kmalloc(sizeof(*send), GFP_KERNEL); + recv = kmalloc(sizeof(*recv), GFP_KERNEL); + if (!send || !recv) + goto err; + + *sk = sk_alloc(net, AF_HYPERV, priority, &hvsock_proto, 0); + if (!*sk) + goto err; + + sock_init_data(sock, *sk); + + /* (*sk)->sk_type is normally set in sock_init_data, but only if sock + * is non-NULL. We make sure that our sockets always have a type by + * setting it here if needed. + */ + if (!sock) + (*sk)->sk_type = type; + + (*sk)->sk_destruct = hvsock_sk_destruct; + + /* Looks stream-based socket doesn't need this. */ + (*sk)->sk_backlog_rcv = NULL; + + (*sk)->sk_state = 0; + sock_reset_flag(*sk, SOCK_DONE); + + hvsk = sk_to_hvsock(*sk); + + hvsk->send = send; + hvsk->recv = recv; + + hvsock_addr_init(&hvsk->local_addr, SHV_SERVICE_ID_ANY); + hvsock_addr_init(&hvsk->remote_addr, SHV_SERVICE_ID_ANY); + + INIT_LIST_HEAD(&hvsk->bound_list); + INIT_LIST_HEAD(&hvsk->connected_list); + + INIT_LIST_HEAD(&hvsk->accept_queue); + mutex_init(&hvsk->accept_queue_mutex); + + hvsk->peer_shutdown = 0; + + hvsk->recv->data_len = 0; + hvsk->recv->data_offset = 0; + + return 0; +err: + atomic_dec(&total_num_hvsock); + kfree(send); + kfree(recv); + *sk = NULL; + return ret; +} + +static int hvsock_bind(struct socket *sock, struct sockaddr *addr, + int addr_len) +{ + struct sockaddr_hv *hv_addr; + struct sock *sk; + int ret; + + sk = sock->sk; + + if (hvsock_addr_cast(addr, addr_len, &hv_addr) != 0) + return -EINVAL; + + if (!uuid_equals(hv_addr->shv_vm_id, NULL_UUID_LE)) + return -EINVAL; + + lock_sock(sk); + ret = __hvsock_bind(sk, hv_addr); + release_sock(sk); + + return ret; +} + +static int hvsock_getname(struct socket *sock, + struct sockaddr *addr, int *addr_len, int peer) +{ + struct sockaddr_hv *hv_addr; + struct hvsock_sock *hvsk; + struct sock *sk; + int ret; + + sk = sock->sk; + hvsk = sk_to_hvsock(sk); + ret = 0; + + lock_sock(sk); + + if (peer) { + if (sock->state != SS_CONNECTED) { + ret = -ENOTCONN; + goto out; + } + hv_addr = &hvsk->remote_addr; + } else { + hv_addr = &hvsk->local_addr; + } + + __sockaddr_check_size(sizeof(*hv_addr)); + + memcpy(addr, hv_addr, sizeof(*hv_addr)); + *addr_len = sizeof(*hv_addr); + +out: + release_sock(sk); + return ret; +} + +static void get_ringbuffer_rw_status(struct vmbus_channel *channel, + bool *can_read, bool *can_write) +{ + u32 avl_read_bytes, avl_write_bytes, dummy; + + if (can_read) { + hv_get_ringbuffer_availbytes(&channel->inbound, + &avl_read_bytes, + &dummy); + /* 0-size payload means FIN */ + *can_read = avl_read_bytes >= HVSOCK_PKT_LEN(0); + } + + if (can_write) { + hv_get_ringbuffer_availbytes(&channel->outbound, + &dummy, + &avl_write_bytes); + + *can_write = avl_write_bytes > + HVSOCK_PKT_LEN(HVSOCK_SND_THRESHOLD); + } +} + +static size_t get_ringbuffer_writable_bytes(struct vmbus_channel *channel) +{ + u32 avl_write_bytes, dummy; + size_t ret; + + hv_get_ringbuffer_availbytes(&channel->outbound, + &dummy, + &avl_write_bytes); + + if (avl_write_bytes < HVSOCK_PKT_LEN(1) + HVSOCK_PKT_LEN(0)) + return 0; + + /* The ringbuffer mustn't be 100% full, and we should reserve a + * zero-length-payload packet for the FIN: see hv_ringbuffer_write() + * and hvsock_shutdown(). + */ + ret = avl_write_bytes - HVSOCK_PKT_LEN(1) - HVSOCK_PKT_LEN(0); + + return round_down(ret, 8); +} + +static int hvsock_send_data(struct vmbus_channel *channel, + struct hvsock_sock *hvsk, + size_t to_write) +{ + hvsk->send->hdr.pkt_type = 1; + hvsk->send->hdr.data_size = to_write; + return vmbus_sendpacket(channel, &hvsk->send->hdr, + sizeof(hvsk->send->hdr) + to_write, + 0, VM_PKT_DATA_INBAND, 0); +} + +static int hvsock_recv_data(struct vmbus_channel *channel, + struct hvsock_sock *hvsk, + size_t *payload_len) +{ + u32 buffer_actual_len; + u64 dummy_req_id; + int ret; + + ret = vmbus_recvpacket(channel, &hvsk->recv->hdr, + sizeof(hvsk->recv->hdr) + + sizeof(hvsk->recv->buf), + &buffer_actual_len, &dummy_req_id); + if (ret != 0 || buffer_actual_len <= sizeof(hvsk->recv->hdr)) + *payload_len = 0; + else + *payload_len = hvsk->recv->hdr.data_size; + + return ret; +} + +static int hvsock_shutdown(struct socket *sock, int mode) +{ + struct hvsock_sock *hvsk; + struct sock *sk; + + if (mode < SHUT_RD || mode > SHUT_RDWR) + return -EINVAL; + /* This maps: + * SHUT_RD (0) -> RCV_SHUTDOWN (1) + * SHUT_WR (1) -> SEND_SHUTDOWN (2) + * SHUT_RDWR (2) -> SHUTDOWN_MASK (3) + */ + ++mode; + + if (sock->state != SS_CONNECTED) + return -ENOTCONN; + + sock->state = SS_DISCONNECTING; + + sk = sock->sk; + + lock_sock(sk); + + sk->sk_shutdown |= mode; + sk->sk_state_change(sk); + + if (mode & SEND_SHUTDOWN) { + hvsk = sk_to_hvsock(sk); + /* It can't fail: see get_ringbuffer_writable_bytes(). */ + (void)hvsock_send_data(hvsk->channel, hvsk, 0); + } + + release_sock(sk); + + return 0; +} + +static unsigned int hvsock_poll(struct file *file, struct socket *sock, + poll_table *wait) +{ + struct vmbus_channel *channel; + bool can_read, can_write; + struct hvsock_sock *hvsk; + struct sock *sk; + unsigned int mask; + + sk = sock->sk; + hvsk = sk_to_hvsock(sk); + + poll_wait(file, sk_sleep(sk), wait); + mask = 0; + + if (sk->sk_err) + /* Signify that there has been an error on this socket. */ + mask |= POLLERR; + + /* INET sockets treat local write shutdown and peer write shutdown as a + * case of POLLHUP set. + */ + if ((sk->sk_shutdown == SHUTDOWN_MASK) || + ((sk->sk_shutdown & SEND_SHUTDOWN) && + (hvsk->peer_shutdown & SEND_SHUTDOWN))) { + mask |= POLLHUP; + } + + if (sk->sk_shutdown & RCV_SHUTDOWN || + hvsk->peer_shutdown & SEND_SHUTDOWN) { + mask |= POLLRDHUP; + } + + lock_sock(sk); + + /* Listening sockets that have connections in their accept + * queue can be read. + */ + if (sk->sk_state == SS_LISTEN && !hvsock_is_accept_queue_empty(sk)) + mask |= POLLIN | POLLRDNORM; + + /* The mutex is to against hvsock_open_connection() */ + mutex_lock(&hvsock_mutex); + + channel = hvsk->channel; + if (channel) { + /* If there is something in the queue then we can read */ + get_ringbuffer_rw_status(channel, &can_read, &can_write); + + if (!can_read && hvsk->recv->data_len > 0) + can_read = true; + + if (!(sk->sk_shutdown & RCV_SHUTDOWN) && can_read) + mask |= POLLIN | POLLRDNORM; + } else { + can_read = false; + can_write = false; + } + + mutex_unlock(&hvsock_mutex); + + /* Sockets whose connections have been closed terminated should + * also be considered read, and we check the shutdown flag for that. + */ + if (sk->sk_shutdown & RCV_SHUTDOWN || + hvsk->peer_shutdown & SEND_SHUTDOWN) { + mask |= POLLIN | POLLRDNORM; + } + + /* Connected sockets that can produce data can be written. */ + if (sk->sk_state == SS_CONNECTED && can_write && + !(sk->sk_shutdown & SEND_SHUTDOWN)) { + /* Remove POLLWRBAND since INET sockets are not setting it. + */ + mask |= POLLOUT | POLLWRNORM; + } + + /* Simulate INET socket poll behaviors, which sets + * POLLOUT|POLLWRNORM when peer is closed and nothing to read, + * but local send is not shutdown. + */ + if (sk->sk_state == SS_UNCONNECTED && + !(sk->sk_shutdown & SEND_SHUTDOWN)) + mask |= POLLOUT | POLLWRNORM; + + release_sock(sk); + + return mask; +} + +/* This function runs in the tasklet context of process_chn_event() */ +static void hvsock_on_channel_cb(void *ctx) +{ + struct sock *sk = (struct sock *)ctx; + struct hvsock_sock *hvsk = sk_to_hvsock(sk); + struct vmbus_channel *channel = hvsk->channel; + bool can_read, can_write; + + if (!channel) { + WARN_ONCE(1, "NULL channel! There is a programming bug.\n"); + return; + } + + get_ringbuffer_rw_status(channel, &can_read, &can_write); + + if (can_read) + sk->sk_data_ready(sk); + + if (can_write) + sk->sk_write_space(sk); +} + +static void hvsock_close_connection(struct vmbus_channel *channel) +{ + struct hvsock_sock *hvsk; + struct sock *sk; + + mutex_lock(&hvsock_mutex); + + sk = hvsock_find_connected_socket_by_channel(channel); + + /* The guest has already closed the connection? */ + if (!sk) + goto out; + + sk->sk_state = SS_UNCONNECTED; + sock_set_flag(sk, SOCK_DONE); + + hvsk = sk_to_hvsock(sk); + hvsk->peer_shutdown |= SEND_SHUTDOWN | RCV_SHUTDOWN; + + sk->sk_state_change(sk); +out: + mutex_unlock(&hvsock_mutex); +} + +static int hvsock_open_connection(struct vmbus_channel *channel) +{ + struct hvsock_sock *hvsk, *new_hvsk; + struct sockaddr_hv hv_addr; + struct sock *sk, *new_sk; + unsigned char conn_from_host; + + uuid_le *instance, *service_id; + int ret; + + instance = &channel->offermsg.offer.if_instance; + service_id = &channel->offermsg.offer.if_type; + + /* The first byte != 0 means the host initiated the connection. */ + conn_from_host = channel->offermsg.offer.u.pipe.user_def[0]; + + mutex_lock(&hvsock_mutex); + + hvsock_addr_init(&hv_addr, conn_from_host ? *service_id : *instance); + sk = hvsock_find_bound_socket(&hv_addr); + + if (!sk || (conn_from_host && sk->sk_state != SS_LISTEN) || + (!conn_from_host && sk->sk_state != SS_CONNECTING)) { + ret = -ENXIO; + goto out; + } + + if (conn_from_host) { + if (sk->sk_ack_backlog >= sk->sk_max_ack_backlog) { + ret = -EMFILE; + goto out; + } + + ret = hvsock_create(sock_net(sk), NULL, GFP_KERNEL, + sk->sk_type, &new_sk); + if (ret != 0) + goto out; + + new_sk->sk_state = SS_CONNECTING; + new_hvsk = sk_to_hvsock(new_sk); + new_hvsk->channel = channel; + hvsock_addr_init(&new_hvsk->local_addr, *service_id); + hvsock_addr_init(&new_hvsk->remote_addr, *instance); + } else { + hvsk = sk_to_hvsock(sk); + hvsk->channel = channel; + } + + set_channel_read_state(channel, false); + ret = vmbus_open(channel, send_ring_page * PAGE_SIZE, + recv_ring_page * PAGE_SIZE, NULL, 0, + hvsock_on_channel_cb, conn_from_host ? new_sk : sk); + if (ret != 0) { + if (conn_from_host) { + new_hvsk->channel = NULL; + sock_put(new_sk); + } else { + hvsk->channel = NULL; + } + goto out; + } + + vmbus_set_chn_rescind_callback(channel, hvsock_close_connection); + set_channel_pending_send_size(channel, + HVSOCK_PKT_LEN(HVSOCK_SND_THRESHOLD)); + + if (conn_from_host) { + new_sk->sk_state = SS_CONNECTED; + + sock_hold(&new_hvsk->sk); + list_add(&new_hvsk->connected_list, &hvsock_connected_list); + + hvsock_enqueue_accept(sk, new_sk); + } else { + sk->sk_state = SS_CONNECTED; + sk->sk_socket->state = SS_CONNECTED; + + sock_hold(&hvsk->sk); + list_add(&hvsk->connected_list, &hvsock_connected_list); + } + + sk->sk_state_change(sk); +out: + mutex_unlock(&hvsock_mutex); + return ret; +} + +static void hvsock_connect_timeout(struct work_struct *work) +{ + struct hvsock_sock *hvsk; + struct sock *sk; + + hvsk = container_of(work, struct hvsock_sock, dwork.work); + sk = hvsock_to_sk(hvsk); + + lock_sock(sk); + if ((sk->sk_state == SS_CONNECTING) && + (sk->sk_shutdown != SHUTDOWN_MASK)) { + sk->sk_state = SS_UNCONNECTED; + sk->sk_err = ETIMEDOUT; + sk->sk_error_report(sk); + } + release_sock(sk); + + sock_put(sk); +} + +static int hvsock_connect_wait(struct socket *sock, + int flags, int current_ret) +{ + struct sock *sk = sock->sk; + struct hvsock_sock *hvsk = sk_to_hvsock(sk); + + int ret = current_ret; + + long timeout = 30 * HZ; + DEFINE_WAIT(wait); + + prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); + + while (sk->sk_state != SS_CONNECTED && sk->sk_err == 0) { + if (flags & O_NONBLOCK) { + /* If we're not going to block, we schedule a timeout + * function to generate a timeout on the connection + * attempt, in case the peer doesn't respond in a + * timely manner. We hold on to the socket until the + * timeout fires. + */ + sock_hold(sk); + INIT_DELAYED_WORK(&hvsk->dwork, + hvsock_connect_timeout); + schedule_delayed_work(&hvsk->dwork, timeout); + + /* Skip ahead to preserve error code set above. */ + goto out_wait; + } + + release_sock(sk); + timeout = schedule_timeout(timeout); + lock_sock(sk); + + if (signal_pending(current)) { + ret = sock_intr_errno(timeout); + goto out_wait_error; + } else if (timeout == 0) { + ret = -ETIMEDOUT; + goto out_wait_error; + } + + prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); + } + + ret = sk->sk_err ? -sk->sk_err : 0; + +out_wait_error: + if (ret < 0) { + sk->sk_state = SS_UNCONNECTED; + sock->state = SS_UNCONNECTED; + } +out_wait: + finish_wait(sk_sleep(sk), &wait); + return ret; +} + +static int hvsock_connect(struct socket *sock, struct sockaddr *addr, + int addr_len, int flags) +{ + struct sockaddr_hv *remote_addr; + struct hvsock_sock *hvsk; + struct sock *sk; + int ret = 0; + + sk = sock->sk; + hvsk = sk_to_hvsock(sk); + + lock_sock(sk); + + switch (sock->state) { + case SS_CONNECTED: + ret = -EISCONN; + goto out; + case SS_DISCONNECTING: + ret = -EINVAL; + goto out; + case SS_CONNECTING: + /* This continues on so we can move sock into the SS_CONNECTED + * state once the connection has completed (at which point err + * will be set to zero also). Otherwise, we will either wait + * for the connection or return -EALREADY should this be a + * non-blocking call. + */ + ret = -EALREADY; + break; + default: + if ((sk->sk_state == SS_LISTEN) || + hvsock_addr_cast(addr, addr_len, &remote_addr) != 0) { + ret = -EINVAL; + goto out; + } + + /* Set the remote address that we are connecting to. */ + memcpy(&hvsk->remote_addr, remote_addr, + sizeof(hvsk->remote_addr)); + + ret = hvsock_auto_bind(hvsk); + if (ret) + goto out; + + sk->sk_state = SS_CONNECTING; + + ret = vmbus_send_tl_connect_request( + &hvsk->local_addr.shv_service_id, + &hvsk->remote_addr.shv_service_id); + if (ret < 0) + goto out; + + /* Mark sock as connecting and set the error code to in + * progress in case this is a non-blocking connect. + */ + sock->state = SS_CONNECTING; + ret = -EINPROGRESS; + } + + ret = hvsock_connect_wait(sock, flags, ret); +out: + release_sock(sk); + return ret; +} + +static int hvsock_accept_wait(struct sock *listener, + struct socket *newsock, int flags) +{ + struct hvsock_sock *hvconnected; + struct sock *connected; + + DEFINE_WAIT(wait); + long timeout; + + int ret = 0; + + /* Wait for children sockets to appear; these are the new sockets + * created upon connection establishment. + */ + timeout = sock_sndtimeo(listener, flags & O_NONBLOCK); + prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE); + + while ((connected = hvsock_dequeue_accept(listener)) == NULL && + listener->sk_err == 0) { + release_sock(listener); + timeout = schedule_timeout(timeout); + lock_sock(listener); + + if (signal_pending(current)) { + ret = sock_intr_errno(timeout); + goto out_wait; + } else if (timeout == 0) { + ret = -EAGAIN; + goto out_wait; + } + + prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE); + } + + if (listener->sk_err) + ret = -listener->sk_err; + + if (connected) { + lock_sock(connected); + hvconnected = sk_to_hvsock(connected); + + if (ret) { + release_sock(connected); + sock_put(connected); + } else { + newsock->state = SS_CONNECTED; + sock_graft(connected, newsock); + release_sock(connected); + sock_put(connected); + } + } + +out_wait: + finish_wait(sk_sleep(listener), &wait); + return ret; +} + +static +int hvsock_accept(struct socket *sock, struct socket *newsock, int flags) +{ + struct sock *listener; + int ret; + + listener = sock->sk; + + lock_sock(listener); + + if (sock->type != SOCK_STREAM) { + ret = -EOPNOTSUPP; + goto out; + } + + if (listener->sk_state != SS_LISTEN) { + ret = -EINVAL; + goto out; + } + + ret = hvsock_accept_wait(listener, newsock, flags); +out: + release_sock(listener); + return ret; +} + +static int hvsock_listen(struct socket *sock, int backlog) +{ + struct hvsock_sock *hvsk; + struct sock *sk; + int ret = 0; + + sk = sock->sk; + lock_sock(sk); + + if (sock->type != SOCK_STREAM) { + ret = -EOPNOTSUPP; + goto out; + } + + if (sock->state != SS_UNCONNECTED) { + ret = -EINVAL; + goto out; + } + + if (backlog <= 0) { + ret = -EINVAL; + goto out; + } + /* This is an artificial limit */ + if (backlog > 128) + backlog = 128; + + hvsk = sk_to_hvsock(sk); + if (!hvsock_addr_bound(&hvsk->local_addr)) { + ret = -EINVAL; + goto out; + } + + sk->sk_ack_backlog = 0; + sk->sk_max_ack_backlog = backlog; + sk->sk_state = SS_LISTEN; +out: + release_sock(sk); + return ret; +} + +static +int hvsock_sendmsg_wait(struct sock *sk, struct msghdr *msg, size_t len) +{ + struct hvsock_sock *hvsk = sk_to_hvsock(sk); + struct vmbus_channel *channel = hvsk->channel; + + size_t total_to_write = len; + size_t total_written = 0; + bool can_write; + + int ret = 0; + + DEFINE_WAIT(wait); + long timeout; + + timeout = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); + prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); + + while (total_to_write > 0) { + size_t to_write, max_writable; + + while (1) { + get_ringbuffer_rw_status(channel, NULL, &can_write); + + if (can_write || sk->sk_err != 0 || + (sk->sk_shutdown & SEND_SHUTDOWN) || + (hvsk->peer_shutdown & RCV_SHUTDOWN)) + break; + + /* Don't wait for non-blocking sockets. */ + if (timeout == 0) { + ret = -EAGAIN; + goto out_wait; + } + + release_sock(sk); + + timeout = schedule_timeout(timeout); + + lock_sock(sk); + if (signal_pending(current)) { + ret = sock_intr_errno(timeout); + goto out_wait; + } else if (timeout == 0) { + ret = -EAGAIN; + goto out_wait; + } + + prepare_to_wait(sk_sleep(sk), &wait, + TASK_INTERRUPTIBLE); + } + + /* These checks occur both as part of and after the loop + * conditional since we need to check before and after + * sleeping. + */ + if (sk->sk_err) { + ret = -sk->sk_err; + goto out_wait; + } else if ((sk->sk_shutdown & SEND_SHUTDOWN) || + (hvsk->peer_shutdown & RCV_SHUTDOWN)) { + ret = -EPIPE; + goto out_wait; + } + + /* Note: that write will only write as many bytes as possible + * in the ringbuffer. It is the caller's responsibility to + * check how many bytes we actually wrote. + */ + do { + max_writable = get_ringbuffer_writable_bytes(channel); + if (max_writable == 0) + goto out_wait; + + to_write = min_t(size_t, HVSOCK_SND_BUF_SZ, + total_to_write); + if (to_write > max_writable) + to_write = max_writable; + + ret = memcpy_from_msg(hvsk->send->buf, msg, to_write); + if (ret != 0) + goto out_wait; + + ret = hvsock_send_data(channel, hvsk, to_write); + if (ret != 0) + goto out_wait; + + total_written += to_write; + total_to_write -= to_write; + } while (total_to_write > 0); + } + +out_wait: + if (total_written > 0) + ret = total_written; + + finish_wait(sk_sleep(sk), &wait); + return ret; +} + +static int hvsock_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) +{ + struct hvsock_sock *hvsk; + struct sock *sk; + int ret; + + if (len == 0) + return -EINVAL; + + if (msg->msg_flags & ~MSG_DONTWAIT) { + pr_err("%s: unsupported flags=0x%x\n", __func__, + msg->msg_flags); + return -EOPNOTSUPP; + } + + sk = sock->sk; + hvsk = sk_to_hvsock(sk); + + lock_sock(sk); + + /* Callers should not provide a destination with stream sockets. */ + if (msg->msg_namelen) { + ret = -EOPNOTSUPP; + goto out; + } + + /* Send data only if both sides are not shutdown in the direction. */ + if (sk->sk_shutdown & SEND_SHUTDOWN || + hvsk->peer_shutdown & RCV_SHUTDOWN) { + ret = -EPIPE; + goto out; + } + + if (sk->sk_state != SS_CONNECTED || + !hvsock_addr_bound(&hvsk->local_addr)) { + ret = -ENOTCONN; + goto out; + } + + if (!hvsock_addr_bound(&hvsk->remote_addr)) { + ret = -EDESTADDRREQ; + goto out; + } + + ret = hvsock_sendmsg_wait(sk, msg, len); +out: + release_sock(sk); + + /* ret is a bigger-than-0 total_written or a negative err code. */ + if (ret == 0) { + WARN(1, "unexpected return value of 0\n"); + ret = -EIO; + } + + return ret; +} + +static int hvsock_recvmsg_wait(struct sock *sk, struct msghdr *msg, + size_t len, int flags) +{ + struct hvsock_sock *hvsk = sk_to_hvsock(sk); + struct vmbus_channel *channel = hvsk->channel; + + size_t to_read, total_to_read = len; + size_t copied = 0; + bool can_read; + + int ret = 0; + + DEFINE_WAIT(wait); + long timeout; + + timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); + prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); + + while (1) { + bool need_refill = hvsk->recv->data_len == 0; + + if (need_refill) + get_ringbuffer_rw_status(channel, &can_read, NULL); + else + can_read = true; + + if (can_read) { + size_t payload_len; + + if (need_refill) { + ret = hvsock_recv_data(channel, hvsk, + &payload_len); + if (ret != 0 || + payload_len > HVSOCK_RCV_BUF_SZ) { + ret = -EIO; + goto out_wait; + } + + if (payload_len == 0) { + ret = copied; + goto out_wait; + } + + hvsk->recv->data_len = payload_len; + hvsk->recv->data_offset = 0; + } + + to_read = min_t(size_t, total_to_read, + hvsk->recv->data_len); + + ret = memcpy_to_msg(msg, hvsk->recv->buf + + hvsk->recv->data_offset, + to_read); + if (ret != 0) + break; + + copied += to_read; + total_to_read -= to_read; + + hvsk->recv->data_len -= to_read; + + if (hvsk->recv->data_len == 0) + hvsk->recv->data_offset = 0; + else + hvsk->recv->data_offset += to_read; + + if (total_to_read == 0) + break; + } else { + if (sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN) || + (hvsk->peer_shutdown & SEND_SHUTDOWN)) + break; + + /* Don't wait for non-blocking sockets. */ + if (timeout == 0) { + ret = -EAGAIN; + break; + } + + if (copied > 0) + break; + + release_sock(sk); + timeout = schedule_timeout(timeout); + lock_sock(sk); + + if (signal_pending(current)) { + ret = sock_intr_errno(timeout); + break; + } else if (timeout == 0) { + ret = -EAGAIN; + break; + } + + prepare_to_wait(sk_sleep(sk), &wait, + TASK_INTERRUPTIBLE); + } + } + + if (sk->sk_err) + ret = -sk->sk_err; + else if (sk->sk_shutdown & RCV_SHUTDOWN) + ret = 0; + + if (copied > 0) { + ret = copied; + + /* If the other side has shutdown for sending and there + * is nothing more to read, then we modify the socket + * state. + */ + if ((hvsk->peer_shutdown & SEND_SHUTDOWN) && + hvsk->recv->data_len == 0) { + get_ringbuffer_rw_status(channel, &can_read, NULL); + if (!can_read) { + sk->sk_state = SS_UNCONNECTED; + sock_set_flag(sk, SOCK_DONE); + sk->sk_state_change(sk); + } + } + } +out_wait: + finish_wait(sk_sleep(sk), &wait); + return ret; +} + +static int hvsock_recvmsg(struct socket *sock, struct msghdr *msg, + size_t len, int flags) +{ + struct sock *sk = sock->sk; + int ret; + + lock_sock(sk); + + if (sk->sk_state != SS_CONNECTED) { + /* Recvmsg is supposed to return 0 if a peer performs an + * orderly shutdown. Differentiate between that case and when a + * peer has not connected or a local shutdown occurred with the + * SOCK_DONE flag. + */ + if (sock_flag(sk, SOCK_DONE)) + ret = 0; + else + ret = -ENOTCONN; + + goto out; + } + + /* We ignore msg->addr_name/len. */ + if (flags & ~MSG_DONTWAIT) { + pr_err("%s: unsupported flags=0x%x\n", __func__, flags); + ret = -EOPNOTSUPP; + goto out; + } + + /* We don't check peer_shutdown flag here since peer may actually shut + * down, but there can be data in the queue that a local socket can + * receive. + */ + if (sk->sk_shutdown & RCV_SHUTDOWN) { + ret = 0; + goto out; + } + + /* It is valid on Linux to pass in a zero-length receive buffer. This + * is not an error. We may as well bail out now. + */ + if (!len) { + ret = 0; + goto out; + } + + ret = hvsock_recvmsg_wait(sk, msg, len, flags); +out: + release_sock(sk); + return ret; +} + +static const struct proto_ops hvsock_ops = { + .family = PF_HYPERV, + .owner = THIS_MODULE, + .release = hvsock_release, + .bind = hvsock_bind, + .connect = hvsock_connect, + .socketpair = sock_no_socketpair, + .accept = hvsock_accept, + .getname = hvsock_getname, + .poll = hvsock_poll, + .ioctl = sock_no_ioctl, + .listen = hvsock_listen, + .shutdown = hvsock_shutdown, + .setsockopt = sock_no_setsockopt, + .getsockopt = sock_no_getsockopt, + .sendmsg = hvsock_sendmsg, + .recvmsg = hvsock_recvmsg, + .mmap = sock_no_mmap, + .sendpage = sock_no_sendpage, +}; + +static int hvsock_create_sock(struct net *net, struct socket *sock, + int protocol, int kern) +{ + struct sock *sk; + + if (!capable(CAP_SYS_ADMIN) && !capable(CAP_NET_ADMIN)) + return -EPERM; + + if (protocol != 0 && protocol != SHV_PROTO_RAW) + return -EPROTONOSUPPORT; + + switch (sock->type) { + case SOCK_STREAM: + sock->ops = &hvsock_ops; + break; + default: + return -ESOCKTNOSUPPORT; + } + + sock->state = SS_UNCONNECTED; + + return hvsock_create(net, sock, GFP_KERNEL, 0, &sk); +} + +static const struct net_proto_family hvsock_family_ops = { + .family = AF_HYPERV, + .create = hvsock_create_sock, + .owner = THIS_MODULE, +}; + +static int hvsock_probe(struct hv_device *hdev, + const struct hv_vmbus_device_id *dev_id) +{ + struct vmbus_channel *channel = hdev->channel; + + /* We ignore the error return code to suppress the unnecessary + * error message in vmbus_probe(): on error the host will rescind + * the offer in 30 seconds and we can do cleanup at that time. + */ + (void)hvsock_open_connection(channel); + + return 0; +} + +static int hvsock_remove(struct hv_device *hdev) +{ + struct vmbus_channel *channel = hdev->channel; + + vmbus_close(channel); + + return 0; +} + +/* It's not really used. See vmbus_match() and vmbus_probe(). */ +static const struct hv_vmbus_device_id id_table[] = { + {}, +}; + +static struct hv_driver hvsock_drv = { + .name = "hv_sock", + .hvsock = true, + .id_table = id_table, + .probe = hvsock_probe, + .remove = hvsock_remove, +}; + +static int __init hvsock_init(void) +{ + int ret; + + if (send_ring_page < DEF_RINGBUFFER_PAGES_HVSOCK_SND) + send_ring_page = DEF_RINGBUFFER_PAGES_HVSOCK_SND; + + if (recv_ring_page < DEF_RINGBUFFER_PAGES_HVSOCK_RCV) + recv_ring_page = DEF_RINGBUFFER_PAGES_HVSOCK_RCV; + + /* Hyper-V Sockets requires at least VMBus 4.0 */ + if ((vmbus_proto_version >> 16) < 4) { + pr_err("failed to load: VMBus 4 or later is required\n"); + return -ENODEV; + } + + ret = vmbus_driver_register(&hvsock_drv); + if (ret) { + pr_err("failed to register hv_sock driver\n"); + return ret; + } + + ret = proto_register(&hvsock_proto, 0); + if (ret) { + pr_err("failed to register protocol\n"); + goto unreg_hvsock_drv; + } + + ret = sock_register(&hvsock_family_ops); + if (ret) { + pr_err("failed to register address family\n"); + goto unreg_proto; + } + + return 0; + +unreg_proto: + proto_unregister(&hvsock_proto); +unreg_hvsock_drv: + vmbus_driver_unregister(&hvsock_drv); + return ret; +} + +static void __exit hvsock_exit(void) +{ + sock_unregister(AF_HYPERV); + proto_unregister(&hvsock_proto); + vmbus_driver_unregister(&hvsock_drv); +} + +module_init(hvsock_init); +module_exit(hvsock_exit); + +MODULE_DESCRIPTION("Hyper-V Sockets"); +MODULE_LICENSE("Dual BSD/GPL"); -- 2.7.4 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Dexuan Cui Subject: =?UTF-8?q?=5BPATCH=20v11=20net-next=201/1=5D=20hv=5Fsock=3A=20introduce=20Hyper-V=20Sockets?= Date: Sun, 15 May 2016 09:53:11 -0700 Message-ID: <1463331191-6720-1-git-send-email-decui@microsoft.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Cc: joe@perches.com To: gregkh@linuxfoundation.org, davem@davemloft.net, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, devel@linuxdriverproject.org, olaf@aepfle.de, apw@canonical.com, jasowang@redhat.com, cavery@redhat.com, kys@microsoft.com, haiyangz@microsoft.com Return-path: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: driverdev-devel-bounces@linuxdriverproject.org Sender: "devel" List-Id: netdev.vger.kernel.org SHlwZXItViBTb2NrZXRzIChodl9zb2NrKSBzdXBwbGllcyBhIGJ5dGUtc3RyZWFtIGJhc2VkIGNv bW11bmljYXRpb24KbWVjaGFuaXNtIGJldHdlZW4gdGhlIGhvc3QgYW5kIHRoZSBndWVzdC4gSXQn cyBzb21ld2hhdCBsaWtlIFRDUCBvdmVyClZNQnVzLCBidXQgdGhlIHRyYW5zcG9ydGF0aW9uIGxh eWVyIChWTUJ1cykgaXMgbXVjaCBzaW1wbGVyIHRoYW4gSVAuCgpXaXRoIEh5cGVyLVYgU29ja2V0 cywgYXBwbGljYXRpb25zIGJldHdlZW4gdGhlIGhvc3QgYW5kIHRoZSBndWVzdCBjYW4gdGFsawp0 byBlYWNoIG90aGVyIGRpcmVjdGx5IGJ5IHRoZSB0cmFkaXRpb25hbCBCU0Qtc3R5bGUgc29ja2V0 IEFQSXMuCgpIeXBlci1WIFNvY2tldHMgaXMgb25seSBhdmFpbGFibGUgb24gbmV3IFdpbmRvd3Mg aG9zdHMsIGxpa2UgV2luZG93cyBTZXJ2ZXIKMjAxNi4gTW9yZSBpbmZvIGlzIGluIHRoaXMgYXJ0 aWNsZSAiTWFrZSB5b3VyIG93biBpbnRlZ3JhdGlvbiBzZXJ2aWNlcyI6Cmh0dHBzOi8vbXNkbi5t aWNyb3NvZnQuY29tL2VuLXVzL3ZpcnR1YWxpemF0aW9uL2h5cGVydl9vbl93aW5kb3dzL2RldmVs b3AvbWFrZV9tZ210X3NlcnZpY2UKClRoZSBwYXRjaCBpbXBsZW1lbnRzIHRoZSBuZWNlc3Nhcnkg c3VwcG9ydCBpbiB0aGUgZ3Vlc3Qgc2lkZSBieSBpbnRyb2R1Y2luZwphIG5ldyBzb2NrZXQgYWRk cmVzcyBmYW1pbHkgQUZfSFlQRVJWLgoKU2lnbmVkLW9mZi1ieTogRGV4dWFuIEN1aSA8ZGVjdWlA bWljcm9zb2Z0LmNvbT4KQ2M6ICJLLiBZLiBTcmluaXZhc2FuIiA8a3lzQG1pY3Jvc29mdC5jb20+ CkNjOiBIYWl5YW5nIFpoYW5nIDxoYWl5YW5nekBtaWNyb3NvZnQuY29tPgpDYzogVml0YWx5IEt1 em5ldHNvdiA8dmt1em5ldHNAcmVkaGF0LmNvbT4KQ2M6IENhdGh5IEF2ZXJ5IDxjYXZlcnlAcmVk aGF0LmNvbT4KLS0tCgpZb3UgY2FuIGFsc28gZ2V0IHRoZSBwYXRjaCBvbiB0aGlzIGJyYW5jaDoK aHR0cHM6Ly9naXRodWIuY29tL2RjdWkvbGludXgvY29tbWl0cy9kZWN1aS9odl9zb2NrL25ldC1u ZXh0LzIwMTYwNTE1X3YxMQoKRm9yIHRoZSBjaGFuZ2UgbG9nIGJlZm9yZSB2MTAsIHBsZWFzZSBz ZWUgaHR0cHM6Ly9sa21sLm9yZy9sa21sLzIwMTYvNS80LzUzMgoKSW4gdjEwLCB0aGUgbWFpbiBj aGFuZ2VzIGNvbnNpc3Qgb2YKMSkgbWluaW1pemUgc3RydWN0IGh2c29ja19zb2NrIGJ5IG1ha2lu ZyB0aGUgc2VuZC9yZWN2IGJ1ZmZlcnMgcG9pbnRlcnMuCiAgIHRoZSBidWZmZXJzIGFyZSBhbGxv Y2F0ZWQgYnkga21hbGxvYygpIGluIF9faHZzb2NrX2NyZWF0ZSgpLgoyKSBtaW5pbWl6ZSB0aGUg c2l6ZXMgb2YgdGhlIHNlbmQvcmVjdiBidWZmZXJzIGFuZCB0aGUgdm1idXMgcmluZ2J1ZmZlcnMu CgoKSW4gdjExLCB0aGUgY2hhbmdlcyBhcmU6CjEpIGFkZCBtb2R1bGUgcGFyYW1zOiBzZW5kX3Jp bmdfcGFnZSwgcmVjdl9yaW5nX3BhZ2UuIFRoZXkgY2FuIGJlIHVzZWQgdG8KZW5sYXJnZSB0aGUg cmluZ2J1ZmZlciBzaXplIHRvIGdldCBiZXR0ZXIgcGVyZm9ybWFuY2UsIGUuZy4sCiMgbW9kcHJv YmUgaHZfc29jayAgcmVjdl9yaW5nX3BhZ2U9MTYgc2VuZF9yaW5nX3BhZ2U9MTYKQnkgZGVmYXVs dCwgcmVjdl9yaW5nX3BhZ2UgaXMgMyBhbmQgc2VuZF9yaW5nX3BhZ2UgaXMgMi4KCjIpIGFkZCBt b2R1bGUgcGFyYW0gbWF4X3NvY2tldF9udW1iZXIgKHRoZSBkZWZhdWx0IGlzIDEwMjQpLgpBIHVz ZXIgY2FuIGVubGFyZ2UgdGhlIG51bWJlciB0byBjcmVhdGUgbW9yZSB0aGFuIDEwMjQgaHZfc29j ayBzb2NrZXRzLgpCeSBkZWZhdWx0LCAxMDI0IHNvY2tldHMgdGFrZSBhYm91dCAxMDI0ICogKDMr MisxKzEpICogNEtCID0gMjhNIGJ5dGVzLgooSGVyZSAxKzEgbWVhbnMgMSBwYWdlIGZvciBzZW5k L3JlY3YgYnVmZmVycyBwZXIgY29ubmVjdGlvbiwgcmVzcGVjdGl2ZWx5LikKCjMpIGltcGxlbWVu dCB0aGUgVE9ETyBpbiBodnNvY2tfc2h1dGRvd24oKS4KCjQpIGZpeCBhIGJ1ZyBpbiBodnNvY2tf Y2xvc2VfY29ubmVjdGlvbigpOgogICBJIHJlbW92ZSAic2stPnNrX3NvY2tldC0+c3RhdGUgPSBT U19VTkNPTk5FQ1RFRDsiIC0tIGFjdHVhbGx5IHRoaXMgbGluZQppcyBub3QgcmVhbGx5IHVzZWZ1 bC4gRm9yIGEgY29ubmVjdGlvbiB0cmlnZ2VyZWQgYnkgYSBob3N0IGFwcOKAmXMgY29ubmVjdCgp LApzay0+c2tfc29ja2V0IHJlbWFpbnMgTlVMTCBiZWZvcmUgdGhlIGNvbm5lY3Rpb24gaXMgYWNj ZXB0ZWQgYnkgdGhlIHNlcnZlcgphcHAgKGluIExpbnV4IFZNKTogc2VlIGh2c29ja19hY2NlcHQo KSAtPiBodnNvY2tfYWNjZXB0X3dhaXQoKSAtPgpzb2NrX2dyYWZ0KGNvbm5lY3RlZCwgbmV3c29j aykuIElmIHRoZSBob3N0IGFwcCBleGl0cyBiZWZvcmUgdGhlIHNlcnZlcgphcHDigJlzIGFjY2Vw dCgpIHJldHVybnMsIHRoZSBob3N0IGNhbiBzZW5kIGEgcmVzY2luZC1tZXNzYWdlIHRvIGNsb3Nl IHRoZQpjb25uZWN0aW9uIGFuZCBsYXRlciBpbiB0aGUgTGludXggVk3igJlzIG1lc3NhZ2UgaGFu ZGxlciAKaS5lLiB2bWJ1c19vbm9mZmVyX3Jlc2NpbmQoKSksIExpbnV4IHdpbGwgZ2V0IGEgTlVM TCBkZS1yZWZlcmVuY2luZyBjcmFzaC4gCgo1KSBmaXggYSBidWcgaW4gaHZzb2NrX29wZW5fY29u bmVjdGlvbigpCiAgSSBtb3ZlIHRoZSB2bWJ1c19zZXRfY2huX3Jlc2NpbmRfY2FsbGJhY2soKSB0 byBhIGxhdGVyIHBsYWNlLCBiZWNhdXNlCndoZW4gdm1idXNfb3BlbigpIGZhaWxzLCBodnNvY2tf Y2xvc2VfY29ubmVjdGlvbigpIGNhbiBkbyBub3RoaW5nIGFuZCB3ZQpjb3VudCBvbiB2bWJ1c19v bm9mZmVyX3Jlc2NpbmQoKSAtPiB2bWJ1c19kZXZpY2VfdW5yZWdpc3RlcigpIHRvIGNsZWFuIHVw CnRoZSBkZXZpY2UuCgo2KSBzb21lIHN0eWxpc3RpYyBtb2RpZmljaWF0aW9uLgoKCiBNQUlOVEFJ TkVSUyAgICAgICAgICAgICAgICAgfCAgICAyICsKIGluY2x1ZGUvbGludXgvaHlwZXJ2LmggICAg ICB8ICAgMTQgKwogaW5jbHVkZS9saW51eC9zb2NrZXQuaCAgICAgIHwgICAgNCArLQogaW5jbHVk ZS9uZXQvYWZfaHZzb2NrLmggICAgIHwgICA3OCArKysKIGluY2x1ZGUvdWFwaS9saW51eC9oeXBl cnYuaCB8ICAgMjUgKwogbmV0L0tjb25maWcgICAgICAgICAgICAgICAgIHwgICAgMSArCiBuZXQv TWFrZWZpbGUgICAgICAgICAgICAgICAgfCAgICAxICsKIG5ldC9odl9zb2NrL0tjb25maWcgICAg ICAgICB8ICAgMTAgKwogbmV0L2h2X3NvY2svTWFrZWZpbGUgICAgICAgIHwgICAgMyArCiBuZXQv aHZfc29jay9hZl9odnNvY2suYyAgICAgfCAxNTIwICsrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKysrKysrKysKIDEwIGZpbGVzIGNoYW5nZWQsIDE2NTcgaW5zZXJ0aW9ucygrKSwg MSBkZWxldGlvbigtKQoKZGlmZiAtLWdpdCBhL01BSU5UQUlORVJTIGIvTUFJTlRBSU5FUlMKaW5k ZXggYjU3ZGY2Ni4uYzlmZTJjNiAxMDA2NDQKLS0tIGEvTUFJTlRBSU5FUlMKKysrIGIvTUFJTlRB SU5FUlMKQEAgLTUyNzEsNyArNTI3MSw5IEBAIEY6CWRyaXZlcnMvcGNpL2hvc3QvcGNpLWh5cGVy di5jCiBGOglkcml2ZXJzL25ldC9oeXBlcnYvCiBGOglkcml2ZXJzL3Njc2kvc3RvcnZzY19kcnYu YwogRjoJZHJpdmVycy92aWRlby9mYmRldi9oeXBlcnZfZmIuYworRjoJbmV0L2h2X3NvY2svCiBG OglpbmNsdWRlL2xpbnV4L2h5cGVydi5oCitGOglpbmNsdWRlL25ldC9hZl9odnNvY2suaAogRjoJ dG9vbHMvaHYvCiBGOglEb2N1bWVudGF0aW9uL0FCSS9zdGFibGUvc3lzZnMtYnVzLXZtYnVzCiAK ZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgvaHlwZXJ2LmggYi9pbmNsdWRlL2xpbnV4L2h5cGVy di5oCmluZGV4IGFhMGZhZGMuLjdiZTcyMzcgMTAwNjQ0Ci0tLSBhL2luY2x1ZGUvbGludXgvaHlw ZXJ2LmgKKysrIGIvaW5jbHVkZS9saW51eC9oeXBlcnYuaApAQCAtMTMzOCw0ICsxMzM4LDE4IEBA IGV4dGVybiBfX3UzMiB2bWJ1c19wcm90b192ZXJzaW9uOwogCiBpbnQgdm1idXNfc2VuZF90bF9j b25uZWN0X3JlcXVlc3QoY29uc3QgdXVpZF9sZSAqc2h2X2d1ZXN0X3NlcnZpZV9pZCwKIAkJCQkg IGNvbnN0IHV1aWRfbGUgKnNodl9ob3N0X3NlcnZpZV9pZCk7CitzdHJ1Y3Qgdm1waXBlX3Byb3Rv X2hlYWRlciB7CisJdTMyIHBrdF90eXBlOworCXUzMiBkYXRhX3NpemU7Cit9OworCisjZGVmaW5l IEhWU09DS19IRUFERVJfTEVOCShzaXplb2Yoc3RydWN0IHZtcGFja2V0X2Rlc2NyaXB0b3IpICsg XAorCQkJCSBzaXplb2Yoc3RydWN0IHZtcGlwZV9wcm90b19oZWFkZXIpKQorCisvKiBTZWUgJ3By ZXZfaW5kaWNlcycgaW4gaHZfcmluZ2J1ZmZlcl9yZWFkKCksIGh2X3JpbmdidWZmZXJfd3JpdGUo KSAqLworI2RlZmluZSBQUkVWX0lORElDRVNfTEVOCShzaXplb2YodTY0KSkKKworI2RlZmluZSBI VlNPQ0tfUEtUX0xFTihwYXlsb2FkX2xlbikJKEhWU09DS19IRUFERVJfTEVOICsgXAorCQkJCQlB TElHTigocGF5bG9hZF9sZW4pLCA4KSArIFwKKwkJCQkJUFJFVl9JTkRJQ0VTX0xFTikKICNlbmRp ZiAvKiBfSFlQRVJWX0ggKi8KZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgvc29ja2V0LmggYi9p bmNsdWRlL2xpbnV4L3NvY2tldC5oCmluZGV4IGI1Y2M1YTYuLjBiNjhiNTggMTAwNjQ0Ci0tLSBh L2luY2x1ZGUvbGludXgvc29ja2V0LmgKKysrIGIvaW5jbHVkZS9saW51eC9zb2NrZXQuaApAQCAt MjAyLDggKzIwMiw5IEBAIHN0cnVjdCB1Y3JlZCB7CiAjZGVmaW5lIEFGX1ZTT0NLCTQwCS8qIHZT b2NrZXRzCQkJKi8KICNkZWZpbmUgQUZfS0NNCQk0MQkvKiBLZXJuZWwgQ29ubmVjdGlvbiBNdWx0 aXBsZXhvciovCiAjZGVmaW5lIEFGX1FJUENSVFIJNDIJLyogUXVhbGNvbW0gSVBDIFJvdXRlciAg ICAgICAgICAqLworI2RlZmluZSBBRl9IWVBFUlYJNDMJLyogSHlwZXItViBTb2NrZXRzICAgICAg ICAgICAgICAqLwogCi0jZGVmaW5lIEFGX01BWAkJNDMJLyogRm9yIG5vdy4uICovCisjZGVmaW5l IEFGX01BWAkJNDQJLyogRm9yIG5vdy4uICovCiAKIC8qIFByb3RvY29sIGZhbWlsaWVzLCBzYW1l IGFzIGFkZHJlc3MgZmFtaWxpZXMuICovCiAjZGVmaW5lIFBGX1VOU1BFQwlBRl9VTlNQRUMKQEAg LTI1MSw2ICsyNTIsNyBAQCBzdHJ1Y3QgdWNyZWQgewogI2RlZmluZSBQRl9WU09DSwlBRl9WU09D SwogI2RlZmluZSBQRl9LQ00JCUFGX0tDTQogI2RlZmluZSBQRl9RSVBDUlRSCUFGX1FJUENSVFIK KyNkZWZpbmUgUEZfSFlQRVJWCUFGX0hZUEVSVgogI2RlZmluZSBQRl9NQVgJCUFGX01BWAogCiAv KiBNYXhpbXVtIHF1ZXVlIGxlbmd0aCBzcGVjaWZpYWJsZSBieSBsaXN0ZW4uICAqLwpkaWZmIC0t Z2l0IGEvaW5jbHVkZS9uZXQvYWZfaHZzb2NrLmggYi9pbmNsdWRlL25ldC9hZl9odnNvY2suaApu ZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwLi43YzhjNDFlCi0tLSAvZGV2L251bGwK KysrIGIvaW5jbHVkZS9uZXQvYWZfaHZzb2NrLmgKQEAgLTAsMCArMSw3OCBAQAorI2lmbmRlZiBf X0FGX0hWU09DS19IX18KKyNkZWZpbmUgX19BRl9IVlNPQ0tfSF9fCisKKyNpbmNsdWRlIDxsaW51 eC9rZXJuZWwuaD4KKyNpbmNsdWRlIDxsaW51eC9oeXBlcnYuaD4KKyNpbmNsdWRlIDxuZXQvc29j ay5oPgorCisvKiBOb3RlOiAzLXBhZ2UgaXMgdGhlIG1pbmltYWwgcmVjdiByaW5nYnVmZmVyIHNp emUgYnkgZGVmYXVsdDoKKyAqCisgKiB0aGUgMXN0IHBhZ2UgaXMgdXNlZCBhcyB0aGUgc2hhcmVk IHJlYWQvd3JpdGUgaW5kZXggZXRjLCByYXRoZXIgdGhhbiBkYXRhOgorICogc2VlIGh2X3Jpbmdi dWZmZXJfaW5pdCgpOworICoKKyAqIHRoZSBwYXlsb2FkIGxlbmd0aCBpbiB0aGUgdm1idXMgcGlw ZSBtZXNzYWdlIHJlY2VpdmVkIGZyb20gdGhlIGhvc3QgY2FuCisgKiBiZSA0MDk2IGJ5dGVzLCBh bmQgY29uc2lkaW5nIHRoZSBoZWFkZXIgb2YgSFZTT0NLX0hFQURFUl9MRU4gYnl0ZXMsIHdlCisg KiBuZWVkIGF0IGxlYXN0IDIgZXh0cmEgcGFnZXMgZm9yIHJpbmdidWZmZXIgZGF0YS4KKyAqLwor I2RlZmluZSBIVlNPQ0tfUkNWX0JVRl9TWiAgICBQQUdFX1NJWkUKKyNkZWZpbmUgREVGX1JJTkdC VUZGRVJfUEFHRVNfSFZTT0NLX1JDViAzCisKKy8qIEFzIHRvIHNlbmQsIGhlcmUgbGV0J3MgbWFr ZSBzdXJlIHRoZSBodnNvY2tfc2VuZF9idWYgc3RydWN0IGNhbiBiZSBoZWxkIGluIDEKKyAqIHBh Z2UsIGFuZCBzaW5jZSB3ZSB3YW50IHRvIHVzZSAyIHBhZ2VzIGZvciB0aGUgc2VuZCByaW5nYnVm ZmVyIHNpemUgKHRoaXMgaXMKKyAqIHRoZSBtaW5pbWFsIHNpemUgYnkgZGVmYXVsdCwgYmVjYXVz ZSB0aGUgMXN0IHBhZ2Ugb2YgdGhlIHR3byBpcyB1c2VkIGFzIHRoZQorICogc2hhcmVkIHJlYWQv d3JpdGUgaW5kZXggZXRjLCByYXRoZXIgdGhhbiBkYXRhKSwgd2Ugb25seSBoYXZlIDEgcGFnZSBm b3IKKyAqIHJpbmdidWZmZXIgZGF0YSwgdGhpcyBtZWFuczogdGhlIG1heCBwYXlsb2FkIGxlbmd0 aCBmb3IgaHZzb2NrIGRhdGEgaXMKKyAqIFBBR0VfU0laRSAtIEhWU09DS19QS1RfTEVOKDApLiBB bmQsIGxldCdzIHJlZHVjZSB0aGUgbGVuZ3RoIGJ5IDgtYnl0ZXMKKyAqIGJlY2F1c2UgdGhlIHJp bmdidWZmZXIgY2FuJ3QgYmUgMTAwJSBmdWxsOiBzZWUgaHZfcmluZ2J1ZmZlcl93cml0ZSgpLgor ICovCisjZGVmaW5lIEhWU09DS19TTkRfQlVGX1NaICAgIChQQUdFX1NJWkUgLSBIVlNPQ0tfUEtU X0xFTigwKSAtIDgpCisjZGVmaW5lIERFRl9SSU5HQlVGRkVSX1BBR0VTX0hWU09DS19TTkQgMgor CisvKiBXZSBvbmx5IHNlbmQgZGF0YSB3aGVuIHRoZSBhdmFpbGFibGUgc3BhY2UgaXMgImJpZyBl bm91Z2giLiBUaGlzIGFydGlmaWNpYWwKKyAqIHZhbHVlIG11c3QgYmUgbGVzcyB0aGFuIEhWU09D S19TTkRfQlVGX1NaLgorICoKKyAqLworI2RlZmluZSBIVlNPQ0tfU05EX1RIUkVTSE9MRCAoUEFH RV9TSVpFIC8gMikKKworI2RlZmluZSBza190b19odnNvY2soX19zaykgICAoKHN0cnVjdCBodnNv Y2tfc29jayAqKShfX3NrKSkKKyNkZWZpbmUgaHZzb2NrX3RvX3NrKF9faHZzaykgKChzdHJ1Y3Qg c29jayAqKShfX2h2c2spKQorCitzdHJ1Y3QgaHZzb2NrX3NlbmRfYnVmIHsKKwlzdHJ1Y3Qgdm1w aXBlX3Byb3RvX2hlYWRlciBoZHI7CisJdTggYnVmW0hWU09DS19TTkRfQlVGX1NaXTsKK307CisK K3N0cnVjdCBodnNvY2tfcmVjdl9idWYgeworCXN0cnVjdCB2bXBpcGVfcHJvdG9faGVhZGVyIGhk cjsKKwl1OCBidWZbSFZTT0NLX1JDVl9CVUZfU1pdOworCisJdW5zaWduZWQgaW50IGRhdGFfbGVu OworCXVuc2lnbmVkIGludCBkYXRhX29mZnNldDsKK307CisKK3N0cnVjdCBodnNvY2tfc29jayB7 CisJLyogc2sgbXVzdCBiZSB0aGUgZmlyc3QgbWVtYmVyLiAqLworCXN0cnVjdCBzb2NrIHNrOwor CisJc3RydWN0IHNvY2thZGRyX2h2IGxvY2FsX2FkZHI7CisJc3RydWN0IHNvY2thZGRyX2h2IHJl bW90ZV9hZGRyOworCisJLyogcHJvdGVjdGVkIGJ5IHRoZSBnbG9iYWwgaHZzb2NrX211dGV4ICov CisJc3RydWN0IGxpc3RfaGVhZCBib3VuZF9saXN0OworCXN0cnVjdCBsaXN0X2hlYWQgY29ubmVj dGVkX2xpc3Q7CisKKwlzdHJ1Y3QgbGlzdF9oZWFkIGFjY2VwdF9xdWV1ZTsKKwkvKiB1c2VkIGJ5 IGVucXVldWUgYW5kIGRlcXVldWUgKi8KKwlzdHJ1Y3QgbXV0ZXggYWNjZXB0X3F1ZXVlX211dGV4 OworCisJc3RydWN0IGRlbGF5ZWRfd29yayBkd29yazsKKworCXUzMiBwZWVyX3NodXRkb3duOwor CisJc3RydWN0IHZtYnVzX2NoYW5uZWwgKmNoYW5uZWw7CisKKwlzdHJ1Y3QgaHZzb2NrX3NlbmRf YnVmICpzZW5kOworCXN0cnVjdCBodnNvY2tfcmVjdl9idWYgKnJlY3Y7Cit9OworCisjZW5kaWYg LyogX19BRl9IVlNPQ0tfSF9fICovCmRpZmYgLS1naXQgYS9pbmNsdWRlL3VhcGkvbGludXgvaHlw ZXJ2LmggYi9pbmNsdWRlL3VhcGkvbGludXgvaHlwZXJ2LmgKaW5kZXggZTM0N2IyNC4uNDA4Yjgz MiAxMDA2NDQKLS0tIGEvaW5jbHVkZS91YXBpL2xpbnV4L2h5cGVydi5oCisrKyBiL2luY2x1ZGUv dWFwaS9saW51eC9oeXBlcnYuaApAQCAtMjYsNiArMjYsNyBAQAogI2RlZmluZSBfVUFQSV9IWVBF UlZfSAogCiAjaW5jbHVkZSA8bGludXgvdXVpZC5oPgorI2luY2x1ZGUgPGxpbnV4L3NvY2tldC5o PgogCiAvKgogICogRnJhbWV3b3JrIHZlcnNpb24gZm9yIHV0aWwgc2VydmljZXMuCkBAIC0zOTYs NCArMzk3LDI4IEBAIHN0cnVjdCBodl9rdnBfaXBfbXNnIHsKIAlzdHJ1Y3QgaHZfa3ZwX2lwYWRk cl92YWx1ZSAgICAgIGt2cF9pcF92YWw7CiB9IF9fYXR0cmlidXRlX18oKHBhY2tlZCkpOwogCisv KgorICogVGhpcyBpcyB0aGUgYWRkcmVzcyBmcm9tYXQgb2YgSHlwZXItViBTb2NrZXRzLgorICog Tm90ZTogaGVyZSB3ZSBqdXN0IGJvcnJvdyB0aGUga2VybmVsJ3MgYnVpbHQtaW4gdHlwZSB1dWlk X2xlLiBXaGVuCisgKiBhbiBhcHBsaWNhdGlvbiBjYWxscyBiaW5kKCkgb3IgY29ubmVjdCgpLCB0 aGUgMiBtZW1iZXJzIG9mIHN0cnVjdAorICogc29ja2FkZHJfaHYgbXVzdCBiZSBvZiBHVUlELgor ICogVGhlIEdVSUQgZm9ybWF0IGRpZmZlcnMgZnJvbSB0aGUgVVVJRCBmb3JtYXQgb25seSBpbiB0 aGUgYnl0ZSBvcmRlciBvZgorICogdGhlIGZpcnN0IDMgZmllbGRzLiBSZWZlciB0bzoKKyAqIGh0 dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0dsb2JhbGx5X3VuaXF1ZV9pZGVudGlmaWVyCisg Ki8KKyNkZWZpbmUgZ3VpZF90IHV1aWRfbGUKK3N0cnVjdCBzb2NrYWRkcl9odiB7CisJX19rZXJu ZWxfc2FfZmFtaWx5X3QJc2h2X2ZhbWlseTsgIC8qIEFkZHJlc3MgZmFtaWx5CQkqLworCV9fbGUx NgkJcmVzZXJ2ZWQ7CSAgICAgLyogTXVzdCBiZSBaZXJvCQkqLworCWd1aWRfdAkJc2h2X3ZtX2lk OwkgICAgIC8qIFZNIElECQkJKi8KKwlndWlkX3QJCXNodl9zZXJ2aWNlX2lkOwkgICAgIC8qIFNl cnZpY2UgSUQJCSovCit9OworCisjZGVmaW5lIFNIVl9WTUlEX0dVRVNUCU5VTExfVVVJRF9MRQor I2RlZmluZSBTSFZfVk1JRF9IT1NUCU5VTExfVVVJRF9MRQorCisjZGVmaW5lIFNIVl9TRVJWSUNF X0lEX0FOWQlOVUxMX1VVSURfTEUKKworI2RlZmluZSBTSFZfUFJPVE9fUkFXCQkxCisKICNlbmRp ZiAvKiBfVUFQSV9IWVBFUlZfSCAqLwpkaWZmIC0tZ2l0IGEvbmV0L0tjb25maWcgYi9uZXQvS2Nv bmZpZwppbmRleCBiODQxYzQyLi4zNjZlNjFmIDEwMDY0NAotLS0gYS9uZXQvS2NvbmZpZworKysg Yi9uZXQvS2NvbmZpZwpAQCAtMjMxLDYgKzIzMSw3IEBAIHNvdXJjZSAibmV0L2Ruc19yZXNvbHZl ci9LY29uZmlnIgogc291cmNlICJuZXQvYmF0bWFuLWFkdi9LY29uZmlnIgogc291cmNlICJuZXQv b3BlbnZzd2l0Y2gvS2NvbmZpZyIKIHNvdXJjZSAibmV0L3Ztd192c29jay9LY29uZmlnIgorc291 cmNlICJuZXQvaHZfc29jay9LY29uZmlnIgogc291cmNlICJuZXQvbmV0bGluay9LY29uZmlnIgog c291cmNlICJuZXQvbXBscy9LY29uZmlnIgogc291cmNlICJuZXQvaHNyL0tjb25maWciCmRpZmYg LS1naXQgYS9uZXQvTWFrZWZpbGUgYi9uZXQvTWFrZWZpbGUKaW5kZXggYmRkMTQ1NS4uZWMxNzVk ZCAxMDA2NDQKLS0tIGEvbmV0L01ha2VmaWxlCisrKyBiL25ldC9NYWtlZmlsZQpAQCAtNzAsNiAr NzAsNyBAQCBvYmotJChDT05GSUdfQkFUTUFOX0FEVikJKz0gYmF0bWFuLWFkdi8KIG9iai0kKENP TkZJR19ORkMpCQkrPSBuZmMvCiBvYmotJChDT05GSUdfT1BFTlZTV0lUQ0gpCSs9IG9wZW52c3dp dGNoLwogb2JqLSQoQ09ORklHX1ZTT0NLRVRTKQkrPSB2bXdfdnNvY2svCitvYmotJChDT05GSUdf SFlQRVJWX1NPQ0spCSs9IGh2X3NvY2svCiBvYmotJChDT05GSUdfTVBMUykJCSs9IG1wbHMvCiBv YmotJChDT05GSUdfSFNSKQkJKz0gaHNyLwogaWZuZXEgKCQoQ09ORklHX05FVF9TV0lUQ0hERVYp LCkKZGlmZiAtLWdpdCBhL25ldC9odl9zb2NrL0tjb25maWcgYi9uZXQvaHZfc29jay9LY29uZmln Cm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAuLjFmNDE4NDgKLS0tIC9kZXYvbnVs bAorKysgYi9uZXQvaHZfc29jay9LY29uZmlnCkBAIC0wLDAgKzEsMTAgQEAKK2NvbmZpZyBIWVBF UlZfU09DSworCXRyaXN0YXRlICJIeXBlci1WIFNvY2tldHMiCisJZGVwZW5kcyBvbiBIWVBFUlYK KwlkZWZhdWx0IG0gaWYgSFlQRVJWCisJaGVscAorCSAgSHlwZXItViBTb2NrZXRzIGlzIHNvbWV3 aGF0IGxpa2UgVENQIG92ZXIgVk1CdXMsIGFsbG93aW5nCisJICBjb21tdW5pY2F0aW9uIGJldHdl ZW4gTGludXggZ3Vlc3QgYW5kIEh5cGVyLVYgaG9zdCB3aXRob3V0IFRDUC9JUC4KKworCSAgVG8g Y29tcGlsZSB0aGlzIGRyaXZlciBhcyBhIG1vZHVsZSwgY2hvb3NlIE0gaGVyZTogdGhlIG1vZHVs ZQorCSAgd2lsbCBiZSBjYWxsZWQgaHZfc29jay4KZGlmZiAtLWdpdCBhL25ldC9odl9zb2NrL01h a2VmaWxlIGIvbmV0L2h2X3NvY2svTWFrZWZpbGUKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXgg MDAwMDAwMC4uNzE2YzAxMgotLS0gL2Rldi9udWxsCisrKyBiL25ldC9odl9zb2NrL01ha2VmaWxl CkBAIC0wLDAgKzEsMyBAQAorb2JqLSQoQ09ORklHX0hZUEVSVl9TT0NLKSArPSBodl9zb2NrLm8K KworaHZfc29jay15ICs9IGFmX2h2c29jay5vCmRpZmYgLS1naXQgYS9uZXQvaHZfc29jay9hZl9o dnNvY2suYyBiL25ldC9odl9zb2NrL2FmX2h2c29jay5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0Cmlu ZGV4IDAwMDAwMDAuLmI5MWJkNjAKLS0tIC9kZXYvbnVsbAorKysgYi9uZXQvaHZfc29jay9hZl9o dnNvY2suYwpAQCAtMCwwICsxLDE1MjAgQEAKKy8qCisgKiBIeXBlci1WIFNvY2tldHMgLS0gYSBz b2NrZXQtYmFzZWQgY29tbXVuaWNhdGlvbiBjaGFubmVsIGJldHdlZW4gdGhlCisgKiBIeXBlci1W IGhvc3QgYW5kIHRoZSB2aXJ0dWFsIG1hY2hpbmVzIHJ1bm5pbmcgb24gaXQuCisgKgorICogQ29w eXJpZ2h0KGMpIDIwMTYsIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi4gQWxsIHJpZ2h0cyByZXNlcnZl ZC4KKyAqCisgKiBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZv cm1zLCB3aXRoIG9yIHdpdGhvdXQKKyAqIG1vZGlmaWNhdGlvbiwgYXJlIHBlcm1pdHRlZCBwcm92 aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucworICogYXJlIG1ldDoKKyAqCisgKiAx LiBSZWRpc3RyaWJ1dGlvbnMgb2Ygc291cmNlIGNvZGUgbXVzdCByZXRhaW4gdGhlIGFib3ZlIGNv cHlyaWdodAorICogICAgbm90aWNlLCB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZv bGxvd2luZyBkaXNjbGFpbWVyLgorICogMi4gUmVkaXN0cmlidXRpb25zIGluIGJpbmFyeSBmb3Jt IG11c3QgcmVwcm9kdWNlIHRoZSBhYm92ZSBjb3B5cmlnaHQKKyAqICAgIG5vdGljZSwgdGhpcyBs aXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUKKyAq ICAgIGRvY3VtZW50YXRpb24gYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRo ZSBkaXN0cmlidXRpb24uCisgKiAzLiBUaGUgbmFtZSBvZiB0aGUgYXV0aG9yIG1heSBub3QgYmUg dXNlZCB0byBlbmRvcnNlIG9yIHByb21vdGUKKyAqICAgIHByb2R1Y3RzIGRlcml2ZWQgZnJvbSB0 aGlzIHNvZnR3YXJlIHdpdGhvdXQgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbgorICogICAgcGVybWlz c2lvbi4KKyAqCisgKiBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBBVVRIT1IgYGBB UyBJUycnIEFORCBBTlkgRVhQUkVTUyBPUgorICogSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJ TkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRUQKKyAqIFdBUlJBTlRJRVMgT0YgTUVS Q0hBTlRBQklMSVRZIEFORCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRQorICogQVJF IERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1IgQkUgTElBQkxFIEZPUiBB TlkgRElSRUNULAorICogSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsIEVYRU1QTEFSWSwg T1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTCisgKiAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQg VE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1IKKyAqIFNFUlZJQ0VTOyBMT1NT IE9GIFVTRSwgREFUQSwgT1IgUFJPRklUUzsgT1IgQlVTSU5FU1MgSU5URVJSVVBUSU9OKQorICog SE9XRVZFUiBDQVVTRUQgQU5EIE9OIEFOWSBUSEVPUlkgT0YgTElBQklMSVRZLCBXSEVUSEVSIElO IENPTlRSQUNULAorICogU1RSSUNUIExJQUJJTElUWSwgT1IgVE9SVCAoSU5DTFVESU5HIE5FR0xJ R0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HCisgKiBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNF IE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUKKyAqIFBPU1NJQklMSVRZ IE9GIFNVQ0ggREFNQUdFLgorICovCisjZGVmaW5lIHByX2ZtdChmbXQpIEtCVUlMRF9NT0ROQU1F ICI6ICIgZm10CisKKyNpbmNsdWRlIDxsaW51eC9pbml0Lmg+CisjaW5jbHVkZSA8bGludXgvbW9k dWxlLmg+CisjaW5jbHVkZSA8bmV0L2FmX2h2c29jay5oPgorCitzdGF0aWMgdWludCBzZW5kX3Jp bmdfcGFnZSA9IERFRl9SSU5HQlVGRkVSX1BBR0VTX0hWU09DS19TTkQ7CitzdGF0aWMgdWludCBy ZWN2X3JpbmdfcGFnZSA9IERFRl9SSU5HQlVGRkVSX1BBR0VTX0hWU09DS19SQ1Y7CitzdGF0aWMg dWludCBtYXhfc29ja2V0X251bWJlciA9IDEwMjQ7CisKK3N0YXRpYyBhdG9taWNfdCB0b3RhbF9u dW1faHZzb2NrID0gQVRPTUlDX0lOSVQoMCk7CisKK21vZHVsZV9wYXJhbShzZW5kX3JpbmdfcGFn ZSwgdWludCwgMDQ0NCk7CitNT0RVTEVfUEFSTV9ERVNDKHNlbmRfcmluZ19wYWdlLCAiU2VuZCBy aW5nIGJ1ZmZlciBzaXplICgjIG9mIHBhZ2VzKSIpOworCittb2R1bGVfcGFyYW0ocmVjdl9yaW5n X3BhZ2UsIHVpbnQsIDA0NDQpOworTU9EVUxFX1BBUk1fREVTQyhyZWN2X3JpbmdfcGFnZSwgIlJl Y2VpdmUgcmluZyBidWZmZXIgc2l6ZSAoIyBvZiBwYWdlcykiKTsKKworbW9kdWxlX3BhcmFtKG1h eF9zb2NrZXRfbnVtYmVyLCB1aW50LCAwNjQ0KTsKK01PRFVMRV9QQVJNX0RFU0MobWF4X3NvY2tl dF9udW1iZXIsICJUaGUgbWF4IG51bWJlciBvZiBjcmVhdGVkIHNvY2tldHMiKTsKKworc3RhdGlj IHN0cnVjdCBwcm90byBodnNvY2tfcHJvdG8gPSB7CisJLm5hbWUgPSAiSFZfU09DSyIsCisJLm93 bmVyID0gVEhJU19NT0RVTEUsCisJLm9ial9zaXplID0gc2l6ZW9mKHN0cnVjdCBodnNvY2tfc29j ayksCit9OworCisjZGVmaW5lIFNTX0xJU1RFTiAyNTUKKworc3RhdGljIExJU1RfSEVBRChodnNv Y2tfYm91bmRfbGlzdCk7CitzdGF0aWMgTElTVF9IRUFEKGh2c29ja19jb25uZWN0ZWRfbGlzdCk7 CitzdGF0aWMgREVGSU5FX01VVEVYKGh2c29ja19tdXRleCk7CisKK3N0YXRpYyBib29sIHV1aWRf ZXF1YWxzKHV1aWRfbGUgdTEsIHV1aWRfbGUgdTIpCit7CisJcmV0dXJuICF1dWlkX2xlX2NtcCh1 MSwgdTIpOworfQorCitzdGF0aWMgc3RydWN0IHNvY2sgKmh2c29ja19maW5kX2JvdW5kX3NvY2tl dChjb25zdCBzdHJ1Y3Qgc29ja2FkZHJfaHYgKmFkZHIpCit7CisJc3RydWN0IGh2c29ja19zb2Nr ICpodnNrOworCisJbGlzdF9mb3JfZWFjaF9lbnRyeShodnNrLCAmaHZzb2NrX2JvdW5kX2xpc3Qs IGJvdW5kX2xpc3QpIHsKKwkJaWYgKHV1aWRfZXF1YWxzKGFkZHItPnNodl9zZXJ2aWNlX2lkLAor CQkJCWh2c2stPmxvY2FsX2FkZHIuc2h2X3NlcnZpY2VfaWQpKQorCQkJcmV0dXJuIGh2c29ja190 b19zayhodnNrKTsKKwl9CisJcmV0dXJuIE5VTEw7Cit9CisKK3N0YXRpYyBzdHJ1Y3Qgc29jayAq aHZzb2NrX2ZpbmRfY29ubmVjdGVkX3NvY2tldF9ieV9jaGFubmVsKAorCWNvbnN0IHN0cnVjdCB2 bWJ1c19jaGFubmVsICpjaGFubmVsKQoreworCXN0cnVjdCBodnNvY2tfc29jayAqaHZzazsKKwor CWxpc3RfZm9yX2VhY2hfZW50cnkoaHZzaywgJmh2c29ja19jb25uZWN0ZWRfbGlzdCwgY29ubmVj dGVkX2xpc3QpIHsKKwkJaWYgKGh2c2stPmNoYW5uZWwgPT0gY2hhbm5lbCkKKwkJCXJldHVybiBo dnNvY2tfdG9fc2soaHZzayk7CisJfQorCXJldHVybiBOVUxMOworfQorCitzdGF0aWMKK3ZvaWQg aHZzb2NrX2VucXVldWVfYWNjZXB0KHN0cnVjdCBzb2NrICpsaXN0ZW5lciwgc3RydWN0IHNvY2sg KmNvbm5lY3RlZCkKK3sKKwlzdHJ1Y3QgaHZzb2NrX3NvY2sgKmh2bGlzdGVuZXI7CisJc3RydWN0 IGh2c29ja19zb2NrICpodmNvbm5lY3RlZDsKKworCWh2bGlzdGVuZXIgPSBza190b19odnNvY2so bGlzdGVuZXIpOworCWh2Y29ubmVjdGVkID0gc2tfdG9faHZzb2NrKGNvbm5lY3RlZCk7CisKKwlz b2NrX2hvbGQoY29ubmVjdGVkKTsKKwlzb2NrX2hvbGQobGlzdGVuZXIpOworCisJbXV0ZXhfbG9j aygmaHZsaXN0ZW5lci0+YWNjZXB0X3F1ZXVlX211dGV4KTsKKwlsaXN0X2FkZF90YWlsKCZodmNv bm5lY3RlZC0+YWNjZXB0X3F1ZXVlLCAmaHZsaXN0ZW5lci0+YWNjZXB0X3F1ZXVlKTsKKwlsaXN0 ZW5lci0+c2tfYWNrX2JhY2tsb2crKzsKKwltdXRleF91bmxvY2soJmh2bGlzdGVuZXItPmFjY2Vw dF9xdWV1ZV9tdXRleCk7Cit9CisKK3N0YXRpYyBzdHJ1Y3Qgc29jayAqaHZzb2NrX2RlcXVldWVf YWNjZXB0KHN0cnVjdCBzb2NrICpsaXN0ZW5lcikKK3sKKwlzdHJ1Y3QgaHZzb2NrX3NvY2sgKmh2 bGlzdGVuZXI7CisJc3RydWN0IGh2c29ja19zb2NrICpodmNvbm5lY3RlZDsKKworCWh2bGlzdGVu ZXIgPSBza190b19odnNvY2sobGlzdGVuZXIpOworCisJbXV0ZXhfbG9jaygmaHZsaXN0ZW5lci0+ YWNjZXB0X3F1ZXVlX211dGV4KTsKKworCWlmIChsaXN0X2VtcHR5KCZodmxpc3RlbmVyLT5hY2Nl cHRfcXVldWUpKSB7CisJCW11dGV4X3VubG9jaygmaHZsaXN0ZW5lci0+YWNjZXB0X3F1ZXVlX211 dGV4KTsKKwkJcmV0dXJuIE5VTEw7CisJfQorCisJaHZjb25uZWN0ZWQgPSBsaXN0X2VudHJ5KGh2 bGlzdGVuZXItPmFjY2VwdF9xdWV1ZS5uZXh0LAorCQkJCSBzdHJ1Y3QgaHZzb2NrX3NvY2ssIGFj Y2VwdF9xdWV1ZSk7CisKKwlsaXN0X2RlbF9pbml0KCZodmNvbm5lY3RlZC0+YWNjZXB0X3F1ZXVl KTsKKwlsaXN0ZW5lci0+c2tfYWNrX2JhY2tsb2ctLTsKKworCW11dGV4X3VubG9jaygmaHZsaXN0 ZW5lci0+YWNjZXB0X3F1ZXVlX211dGV4KTsKKworCXNvY2tfcHV0KGxpc3RlbmVyKTsKKwkvKiBU aGUgY2FsbGVyIHdpbGwgbmVlZCBhIHJlZmVyZW5jZSBvbiB0aGUgY29ubmVjdGVkIHNvY2tldCBz byB3ZSBsZXQKKwkgKiBpdCBjYWxsIHNvY2tfcHV0KCkuCisJICovCisKKwlyZXR1cm4gaHZzb2Nr X3RvX3NrKGh2Y29ubmVjdGVkKTsKK30KKworc3RhdGljIGJvb2wgaHZzb2NrX2lzX2FjY2VwdF9x dWV1ZV9lbXB0eShzdHJ1Y3Qgc29jayAqc2spCit7CisJc3RydWN0IGh2c29ja19zb2NrICpodnNr ID0gc2tfdG9faHZzb2NrKHNrKTsKKwlpbnQgcmV0OworCisJbXV0ZXhfbG9jaygmaHZzay0+YWNj ZXB0X3F1ZXVlX211dGV4KTsKKwlyZXQgPSBsaXN0X2VtcHR5KCZodnNrLT5hY2NlcHRfcXVldWUp OworCW11dGV4X3VubG9jaygmaHZzay0+YWNjZXB0X3F1ZXVlX211dGV4KTsKKworCXJldHVybiBy ZXQ7Cit9CisKK3N0YXRpYyB2b2lkIGh2c29ja19hZGRyX2luaXQoc3RydWN0IHNvY2thZGRyX2h2 ICphZGRyLCB1dWlkX2xlIHNlcnZpY2VfaWQpCit7CisJbWVtc2V0KGFkZHIsIDAsIHNpemVvZigq YWRkcikpOworCWFkZHItPnNodl9mYW1pbHkgPSBBRl9IWVBFUlY7CisJYWRkci0+c2h2X3NlcnZp Y2VfaWQgPSBzZXJ2aWNlX2lkOworfQorCitzdGF0aWMgaW50IGh2c29ja19hZGRyX3ZhbGlkYXRl KGNvbnN0IHN0cnVjdCBzb2NrYWRkcl9odiAqYWRkcikKK3sKKwlpZiAoIWFkZHIpCisJCXJldHVy biAtRUZBVUxUOworCisJaWYgKGFkZHItPnNodl9mYW1pbHkgIT0gQUZfSFlQRVJWKQorCQlyZXR1 cm4gLUVBRk5PU1VQUE9SVDsKKworCWlmIChhZGRyLT5yZXNlcnZlZCAhPSAwKQorCQlyZXR1cm4g LUVJTlZBTDsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgYm9vbCBodnNvY2tfYWRkcl9ib3Vu ZChjb25zdCBzdHJ1Y3Qgc29ja2FkZHJfaHYgKmFkZHIpCit7CisJcmV0dXJuICF1dWlkX2VxdWFs cyhhZGRyLT5zaHZfc2VydmljZV9pZCwgU0hWX1NFUlZJQ0VfSURfQU5ZKTsKK30KKworc3RhdGlj IGludCBodnNvY2tfYWRkcl9jYXN0KGNvbnN0IHN0cnVjdCBzb2NrYWRkciAqYWRkciwgc2l6ZV90 IGxlbiwKKwkJCSAgICBzdHJ1Y3Qgc29ja2FkZHJfaHYgKipvdXRfYWRkcikKK3sKKwlpZiAobGVu IDwgc2l6ZW9mKCoqb3V0X2FkZHIpKQorCQlyZXR1cm4gLUVGQVVMVDsKKworCSpvdXRfYWRkciA9 IChzdHJ1Y3Qgc29ja2FkZHJfaHYgKilhZGRyOworCXJldHVybiBodnNvY2tfYWRkcl92YWxpZGF0 ZSgqb3V0X2FkZHIpOworfQorCitzdGF0aWMgaW50IF9faHZzb2NrX2RvX2JpbmQoc3RydWN0IGh2 c29ja19zb2NrICpodnNrLAorCQkJICAgIHN0cnVjdCBzb2NrYWRkcl9odiAqYWRkcikKK3sKKwlz dHJ1Y3Qgc29ja2FkZHJfaHYgaHZfYWRkcjsKKwlpbnQgcmV0ID0gMDsKKworCWh2c29ja19hZGRy X2luaXQoJmh2X2FkZHIsIGFkZHItPnNodl9zZXJ2aWNlX2lkKTsKKworCW11dGV4X2xvY2soJmh2 c29ja19tdXRleCk7CisKKwlpZiAodXVpZF9lcXVhbHMoYWRkci0+c2h2X3NlcnZpY2VfaWQsIFNI Vl9TRVJWSUNFX0lEX0FOWSkpIHsKKwkJZG8geworCQkJdXVpZF9sZV9nZW4oJmh2X2FkZHIuc2h2 X3NlcnZpY2VfaWQpOworCQl9IHdoaWxlIChodnNvY2tfZmluZF9ib3VuZF9zb2NrZXQoJmh2X2Fk ZHIpKTsKKwl9IGVsc2UgeworCQlpZiAoaHZzb2NrX2ZpbmRfYm91bmRfc29ja2V0KCZodl9hZGRy KSkgeworCQkJcmV0ID0gLUVBRERSSU5VU0U7CisJCQlnb3RvIG91dDsKKwkJfQorCX0KKworCWh2 c29ja19hZGRyX2luaXQoJmh2c2stPmxvY2FsX2FkZHIsIGh2X2FkZHIuc2h2X3NlcnZpY2VfaWQp OworCisJc29ja19ob2xkKCZodnNrLT5zayk7CisJbGlzdF9hZGQoJmh2c2stPmJvdW5kX2xpc3Qs ICZodnNvY2tfYm91bmRfbGlzdCk7CitvdXQ6CisJbXV0ZXhfdW5sb2NrKCZodnNvY2tfbXV0ZXgp OworCisJcmV0dXJuIHJldDsKK30KKworc3RhdGljIGludCBfX2h2c29ja19iaW5kKHN0cnVjdCBz b2NrICpzaywgc3RydWN0IHNvY2thZGRyX2h2ICphZGRyKQoreworCXN0cnVjdCBodnNvY2tfc29j ayAqaHZzayA9IHNrX3RvX2h2c29jayhzayk7CisJaW50IHJldDsKKworCWlmIChodnNvY2tfYWRk cl9ib3VuZCgmaHZzay0+bG9jYWxfYWRkcikpCisJCXJldHVybiAtRUlOVkFMOworCisJc3dpdGNo IChzay0+c2tfc29ja2V0LT50eXBlKSB7CisJY2FzZSBTT0NLX1NUUkVBTToKKwkJcmV0ID0gX19o dnNvY2tfZG9fYmluZChodnNrLCBhZGRyKTsKKwkJYnJlYWs7CisKKwlkZWZhdWx0OgorCQlyZXQg PSAtRUlOVkFMOworCQlicmVhazsKKwl9CisKKwlyZXR1cm4gcmV0OworfQorCisvKiBBdXRvYmlu ZCB0aGlzIHNvY2tldCB0byB0aGUgbG9jYWwgYWRkcmVzcyBpZiBuZWNlc3NhcnkuICovCitzdGF0 aWMgaW50IGh2c29ja19hdXRvX2JpbmQoc3RydWN0IGh2c29ja19zb2NrICpodnNrKQoreworCXN0 cnVjdCBzb2NrICpzayA9IGh2c29ja190b19zayhodnNrKTsKKwlzdHJ1Y3Qgc29ja2FkZHJfaHYg bG9jYWxfYWRkcjsKKworCWlmIChodnNvY2tfYWRkcl9ib3VuZCgmaHZzay0+bG9jYWxfYWRkcikp CisJCXJldHVybiAwOworCWh2c29ja19hZGRyX2luaXQoJmxvY2FsX2FkZHIsIFNIVl9TRVJWSUNF X0lEX0FOWSk7CisJcmV0dXJuIF9faHZzb2NrX2JpbmQoc2ssICZsb2NhbF9hZGRyKTsKK30KKwor c3RhdGljIHZvaWQgaHZzb2NrX3NrX2Rlc3RydWN0KHN0cnVjdCBzb2NrICpzaykKK3sKKwlzdHJ1 Y3QgaHZzb2NrX3NvY2sgKmh2c2sgPSBza190b19odnNvY2soc2spOworCXN0cnVjdCB2bWJ1c19j aGFubmVsICpjaGFubmVsID0gaHZzay0+Y2hhbm5lbDsKKworCWtmcmVlKGh2c2stPnNlbmQpOwor CWtmcmVlKGh2c2stPnJlY3YpOworCWF0b21pY19kZWMoJnRvdGFsX251bV9odnNvY2spOworCisJ aWYgKCFjaGFubmVsKQorCQlyZXR1cm47CisKKwl2bWJ1c19odnNvY2tfZGV2aWNlX3VucmVnaXN0 ZXIoY2hhbm5lbCk7Cit9CisKK3N0YXRpYyB2b2lkIF9faHZzb2NrX3JlbGVhc2Uoc3RydWN0IHNv Y2sgKnNrKQoreworCXN0cnVjdCBodnNvY2tfc29jayAqaHZzazsKKwlzdHJ1Y3Qgc29jayAqcGVu ZGluZzsKKworCWh2c2sgPSBza190b19odnNvY2soc2spOworCisJbXV0ZXhfbG9jaygmaHZzb2Nr X211dGV4KTsKKworCWlmICghbGlzdF9lbXB0eSgmaHZzay0+Ym91bmRfbGlzdCkpIHsKKwkJbGlz dF9kZWxfaW5pdCgmaHZzay0+Ym91bmRfbGlzdCk7CisJCXNvY2tfcHV0KCZodnNrLT5zayk7CisJ fQorCisJaWYgKCFsaXN0X2VtcHR5KCZodnNrLT5jb25uZWN0ZWRfbGlzdCkpIHsKKwkJbGlzdF9k ZWxfaW5pdCgmaHZzay0+Y29ubmVjdGVkX2xpc3QpOworCQlzb2NrX3B1dCgmaHZzay0+c2spOwor CX0KKworCW11dGV4X3VubG9jaygmaHZzb2NrX211dGV4KTsKKworCWxvY2tfc29jayhzayk7CisJ c29ja19vcnBoYW4oc2spOworCXNrLT5za19zaHV0ZG93biA9IFNIVVRET1dOX01BU0s7CisKKwkv KiBDbGVhbiB1cCBhbnkgc29ja2V0cyB0aGF0IG5ldmVyIHdlcmUgYWNjZXB0ZWQuICovCisJd2hp bGUgKChwZW5kaW5nID0gaHZzb2NrX2RlcXVldWVfYWNjZXB0KHNrKSkgIT0gTlVMTCkgeworCQlf X2h2c29ja19yZWxlYXNlKHBlbmRpbmcpOworCQlzb2NrX3B1dChwZW5kaW5nKTsKKwl9CisKKwly ZWxlYXNlX3NvY2soc2spOworCXNvY2tfcHV0KHNrKTsKK30KKworc3RhdGljIGludCBodnNvY2tf cmVsZWFzZShzdHJ1Y3Qgc29ja2V0ICpzb2NrKQoreworCS8qIElmIGFjY2VwdCgpIGlzIGludGVy cnVwdGVkIGJ5IGEgc2lnbmFsLCB0aGUgdGVtcG9yYXJ5IHNvY2tldAorCSAqIHN0cnVjdCdzIHNv Y2stPnNrIGlzIE5VTEwuCisJICovCisJaWYgKHNvY2stPnNrKSB7CisJCV9faHZzb2NrX3JlbGVh c2Uoc29jay0+c2spOworCQlzb2NrLT5zayA9IE5VTEw7CisJfQorCisJc29jay0+c3RhdGUgPSBT U19GUkVFOworCXJldHVybiAwOworfQorCitzdGF0aWMgaW50IGh2c29ja19jcmVhdGUoc3RydWN0 IG5ldCAqbmV0LCBzdHJ1Y3Qgc29ja2V0ICpzb2NrLAorCQkJIGdmcF90IHByaW9yaXR5LCB1bnNp Z25lZCBzaG9ydCB0eXBlLAorCQkJIHN0cnVjdCBzb2NrICoqc2spCit7CisJc3RydWN0IGh2c29j a19zZW5kX2J1ZiAqc2VuZCA9IE5VTEw7CisJc3RydWN0IGh2c29ja19yZWN2X2J1ZiAqcmVjdiA9 IE5VTEw7CisJc3RydWN0IGh2c29ja19zb2NrICpodnNrOworCWludCByZXQgPSAtRU1GSUxFOwor CWludCBudW1faHZzb2NrOworCisJbnVtX2h2c29jayA9IGF0b21pY19pbmNfcmV0dXJuKCZ0b3Rh bF9udW1faHZzb2NrKTsKKwlpZiAobnVtX2h2c29jayA+IG1heF9zb2NrZXRfbnVtYmVyKQorCQln b3RvIGVycjsKKworCXJldCA9IC1FTk9NRU07CisJc2VuZCA9IGttYWxsb2Moc2l6ZW9mKCpzZW5k KSwgR0ZQX0tFUk5FTCk7CisJcmVjdiA9IGttYWxsb2Moc2l6ZW9mKCpyZWN2KSwgR0ZQX0tFUk5F TCk7CisJaWYgKCFzZW5kIHx8ICFyZWN2KQorCQlnb3RvIGVycjsKKworCSpzayA9IHNrX2FsbG9j KG5ldCwgQUZfSFlQRVJWLCBwcmlvcml0eSwgJmh2c29ja19wcm90bywgMCk7CisJaWYgKCEqc2sp CisJCWdvdG8gZXJyOworCisJc29ja19pbml0X2RhdGEoc29jaywgKnNrKTsKKworCS8qICgqc2sp LT5za190eXBlIGlzIG5vcm1hbGx5IHNldCBpbiBzb2NrX2luaXRfZGF0YSwgYnV0IG9ubHkgaWYg c29jaworCSAqIGlzIG5vbi1OVUxMLiBXZSBtYWtlIHN1cmUgdGhhdCBvdXIgc29ja2V0cyBhbHdh eXMgaGF2ZSBhIHR5cGUgYnkKKwkgKiBzZXR0aW5nIGl0IGhlcmUgaWYgbmVlZGVkLgorCSAqLwor CWlmICghc29jaykKKwkJKCpzayktPnNrX3R5cGUgPSB0eXBlOworCisJKCpzayktPnNrX2Rlc3Ry dWN0ID0gaHZzb2NrX3NrX2Rlc3RydWN0OworCisJLyogTG9va3Mgc3RyZWFtLWJhc2VkIHNvY2tl dCBkb2Vzbid0IG5lZWQgdGhpcy4gKi8KKwkoKnNrKS0+c2tfYmFja2xvZ19yY3YgPSBOVUxMOwor CisJKCpzayktPnNrX3N0YXRlID0gMDsKKwlzb2NrX3Jlc2V0X2ZsYWcoKnNrLCBTT0NLX0RPTkUp OworCisJaHZzayA9IHNrX3RvX2h2c29jaygqc2spOworCisJaHZzay0+c2VuZCA9IHNlbmQ7CisJ aHZzay0+cmVjdiA9IHJlY3Y7CisKKwlodnNvY2tfYWRkcl9pbml0KCZodnNrLT5sb2NhbF9hZGRy LCBTSFZfU0VSVklDRV9JRF9BTlkpOworCWh2c29ja19hZGRyX2luaXQoJmh2c2stPnJlbW90ZV9h ZGRyLCBTSFZfU0VSVklDRV9JRF9BTlkpOworCisJSU5JVF9MSVNUX0hFQUQoJmh2c2stPmJvdW5k X2xpc3QpOworCUlOSVRfTElTVF9IRUFEKCZodnNrLT5jb25uZWN0ZWRfbGlzdCk7CisKKwlJTklU X0xJU1RfSEVBRCgmaHZzay0+YWNjZXB0X3F1ZXVlKTsKKwltdXRleF9pbml0KCZodnNrLT5hY2Nl cHRfcXVldWVfbXV0ZXgpOworCisJaHZzay0+cGVlcl9zaHV0ZG93biA9IDA7CisKKwlodnNrLT5y ZWN2LT5kYXRhX2xlbiA9IDA7CisJaHZzay0+cmVjdi0+ZGF0YV9vZmZzZXQgPSAwOworCisJcmV0 dXJuIDA7CitlcnI6CisJYXRvbWljX2RlYygmdG90YWxfbnVtX2h2c29jayk7CisJa2ZyZWUoc2Vu ZCk7CisJa2ZyZWUocmVjdik7CisJKnNrID0gTlVMTDsKKwlyZXR1cm4gcmV0OworfQorCitzdGF0 aWMgaW50IGh2c29ja19iaW5kKHN0cnVjdCBzb2NrZXQgKnNvY2ssIHN0cnVjdCBzb2NrYWRkciAq YWRkciwKKwkJICAgICAgIGludCBhZGRyX2xlbikKK3sKKwlzdHJ1Y3Qgc29ja2FkZHJfaHYgKmh2 X2FkZHI7CisJc3RydWN0IHNvY2sgKnNrOworCWludCByZXQ7CisKKwlzayA9IHNvY2stPnNrOwor CisJaWYgKGh2c29ja19hZGRyX2Nhc3QoYWRkciwgYWRkcl9sZW4sICZodl9hZGRyKSAhPSAwKQor CQlyZXR1cm4gLUVJTlZBTDsKKworCWlmICghdXVpZF9lcXVhbHMoaHZfYWRkci0+c2h2X3ZtX2lk LCBOVUxMX1VVSURfTEUpKQorCQlyZXR1cm4gLUVJTlZBTDsKKworCWxvY2tfc29jayhzayk7CisJ cmV0ID0gX19odnNvY2tfYmluZChzaywgaHZfYWRkcik7CisJcmVsZWFzZV9zb2NrKHNrKTsKKwor CXJldHVybiByZXQ7Cit9CisKK3N0YXRpYyBpbnQgaHZzb2NrX2dldG5hbWUoc3RydWN0IHNvY2tl dCAqc29jaywKKwkJCSAgc3RydWN0IHNvY2thZGRyICphZGRyLCBpbnQgKmFkZHJfbGVuLCBpbnQg cGVlcikKK3sKKwlzdHJ1Y3Qgc29ja2FkZHJfaHYgKmh2X2FkZHI7CisJc3RydWN0IGh2c29ja19z b2NrICpodnNrOworCXN0cnVjdCBzb2NrICpzazsKKwlpbnQgcmV0OworCisJc2sgPSBzb2NrLT5z azsKKwlodnNrID0gc2tfdG9faHZzb2NrKHNrKTsKKwlyZXQgPSAwOworCisJbG9ja19zb2NrKHNr KTsKKworCWlmIChwZWVyKSB7CisJCWlmIChzb2NrLT5zdGF0ZSAhPSBTU19DT05ORUNURUQpIHsK KwkJCXJldCA9IC1FTk9UQ09OTjsKKwkJCWdvdG8gb3V0OworCQl9CisJCWh2X2FkZHIgPSAmaHZz ay0+cmVtb3RlX2FkZHI7CisJfSBlbHNlIHsKKwkJaHZfYWRkciA9ICZodnNrLT5sb2NhbF9hZGRy OworCX0KKworCV9fc29ja2FkZHJfY2hlY2tfc2l6ZShzaXplb2YoKmh2X2FkZHIpKTsKKworCW1l bWNweShhZGRyLCBodl9hZGRyLCBzaXplb2YoKmh2X2FkZHIpKTsKKwkqYWRkcl9sZW4gPSBzaXpl b2YoKmh2X2FkZHIpOworCitvdXQ6CisJcmVsZWFzZV9zb2NrKHNrKTsKKwlyZXR1cm4gcmV0Owor fQorCitzdGF0aWMgdm9pZCBnZXRfcmluZ2J1ZmZlcl9yd19zdGF0dXMoc3RydWN0IHZtYnVzX2No YW5uZWwgKmNoYW5uZWwsCisJCQkJICAgICBib29sICpjYW5fcmVhZCwgYm9vbCAqY2FuX3dyaXRl KQoreworCXUzMiBhdmxfcmVhZF9ieXRlcywgYXZsX3dyaXRlX2J5dGVzLCBkdW1teTsKKworCWlm IChjYW5fcmVhZCkgeworCQlodl9nZXRfcmluZ2J1ZmZlcl9hdmFpbGJ5dGVzKCZjaGFubmVsLT5p bmJvdW5kLAorCQkJCQkgICAgICZhdmxfcmVhZF9ieXRlcywKKwkJCQkJICAgICAmZHVtbXkpOwor CQkvKiAwLXNpemUgcGF5bG9hZCBtZWFucyBGSU4gKi8KKwkJKmNhbl9yZWFkID0gYXZsX3JlYWRf Ynl0ZXMgPj0gSFZTT0NLX1BLVF9MRU4oMCk7CisJfQorCisJaWYgKGNhbl93cml0ZSkgeworCQlo dl9nZXRfcmluZ2J1ZmZlcl9hdmFpbGJ5dGVzKCZjaGFubmVsLT5vdXRib3VuZCwKKwkJCQkJICAg ICAmZHVtbXksCisJCQkJCSAgICAgJmF2bF93cml0ZV9ieXRlcyk7CisKKwkJKmNhbl93cml0ZSA9 IGF2bF93cml0ZV9ieXRlcyA+CisJCQkgICAgIEhWU09DS19QS1RfTEVOKEhWU09DS19TTkRfVEhS RVNIT0xEKTsKKwl9Cit9CisKK3N0YXRpYyBzaXplX3QgZ2V0X3JpbmdidWZmZXJfd3JpdGFibGVf Ynl0ZXMoc3RydWN0IHZtYnVzX2NoYW5uZWwgKmNoYW5uZWwpCit7CisJdTMyIGF2bF93cml0ZV9i eXRlcywgZHVtbXk7CisJc2l6ZV90IHJldDsKKworCWh2X2dldF9yaW5nYnVmZmVyX2F2YWlsYnl0 ZXMoJmNoYW5uZWwtPm91dGJvdW5kLAorCQkJCSAgICAgJmR1bW15LAorCQkJCSAgICAgJmF2bF93 cml0ZV9ieXRlcyk7CisKKwlpZiAoYXZsX3dyaXRlX2J5dGVzIDwgSFZTT0NLX1BLVF9MRU4oMSkg KyBIVlNPQ0tfUEtUX0xFTigwKSkKKwkJcmV0dXJuIDA7CisKKwkvKiBUaGUgcmluZ2J1ZmZlciBt dXN0bid0IGJlIDEwMCUgZnVsbCwgYW5kIHdlIHNob3VsZCByZXNlcnZlIGEKKwkgKiB6ZXJvLWxl bmd0aC1wYXlsb2FkIHBhY2tldCBmb3IgdGhlIEZJTjogc2VlIGh2X3JpbmdidWZmZXJfd3JpdGUo KQorCSAqIGFuZCBodnNvY2tfc2h1dGRvd24oKS4KKwkgKi8KKwlyZXQgPSBhdmxfd3JpdGVfYnl0 ZXMgLSBIVlNPQ0tfUEtUX0xFTigxKSAtIEhWU09DS19QS1RfTEVOKDApOworCisJcmV0dXJuIHJv dW5kX2Rvd24ocmV0LCA4KTsKK30KKworc3RhdGljIGludCBodnNvY2tfc2VuZF9kYXRhKHN0cnVj dCB2bWJ1c19jaGFubmVsICpjaGFubmVsLAorCQkJICAgIHN0cnVjdCBodnNvY2tfc29jayAqaHZz aywKKwkJCSAgICBzaXplX3QgdG9fd3JpdGUpCit7CisJaHZzay0+c2VuZC0+aGRyLnBrdF90eXBl ID0gMTsKKwlodnNrLT5zZW5kLT5oZHIuZGF0YV9zaXplID0gdG9fd3JpdGU7CisJcmV0dXJuIHZt YnVzX3NlbmRwYWNrZXQoY2hhbm5lbCwgJmh2c2stPnNlbmQtPmhkciwKKwkJCQlzaXplb2YoaHZz ay0+c2VuZC0+aGRyKSArIHRvX3dyaXRlLAorCQkJCTAsIFZNX1BLVF9EQVRBX0lOQkFORCwgMCk7 Cit9CisKK3N0YXRpYyBpbnQgaHZzb2NrX3JlY3ZfZGF0YShzdHJ1Y3Qgdm1idXNfY2hhbm5lbCAq Y2hhbm5lbCwKKwkJCSAgICBzdHJ1Y3QgaHZzb2NrX3NvY2sgKmh2c2ssCisJCQkgICAgc2l6ZV90 ICpwYXlsb2FkX2xlbikKK3sKKwl1MzIgYnVmZmVyX2FjdHVhbF9sZW47CisJdTY0IGR1bW15X3Jl cV9pZDsKKwlpbnQgcmV0OworCisJcmV0ID0gdm1idXNfcmVjdnBhY2tldChjaGFubmVsLCAmaHZz ay0+cmVjdi0+aGRyLAorCQkJICAgICAgIHNpemVvZihodnNrLT5yZWN2LT5oZHIpICsKKwkJCSAg ICAgICBzaXplb2YoaHZzay0+cmVjdi0+YnVmKSwKKwkJCSAgICAgICAmYnVmZmVyX2FjdHVhbF9s ZW4sICZkdW1teV9yZXFfaWQpOworCWlmIChyZXQgIT0gMCB8fCBidWZmZXJfYWN0dWFsX2xlbiA8 PSBzaXplb2YoaHZzay0+cmVjdi0+aGRyKSkKKwkJKnBheWxvYWRfbGVuID0gMDsKKwllbHNlCisJ CSpwYXlsb2FkX2xlbiA9IGh2c2stPnJlY3YtPmhkci5kYXRhX3NpemU7CisKKwlyZXR1cm4gcmV0 OworfQorCitzdGF0aWMgaW50IGh2c29ja19zaHV0ZG93bihzdHJ1Y3Qgc29ja2V0ICpzb2NrLCBp bnQgbW9kZSkKK3sKKwlzdHJ1Y3QgaHZzb2NrX3NvY2sgKmh2c2s7CisJc3RydWN0IHNvY2sgKnNr OworCisJaWYgKG1vZGUgPCBTSFVUX1JEIHx8IG1vZGUgPiBTSFVUX1JEV1IpCisJCXJldHVybiAt RUlOVkFMOworCS8qIFRoaXMgbWFwczoKKwkgKiBTSFVUX1JEICAgKDApIC0+IFJDVl9TSFVURE9X TiAgKDEpCisJICogU0hVVF9XUiAgICgxKSAtPiBTRU5EX1NIVVRET1dOICgyKQorCSAqIFNIVVRf UkRXUiAoMikgLT4gU0hVVERPV05fTUFTSyAoMykKKwkgKi8KKwkrK21vZGU7CisKKwlpZiAoc29j ay0+c3RhdGUgIT0gU1NfQ09OTkVDVEVEKQorCQlyZXR1cm4gLUVOT1RDT05OOworCisJc29jay0+ c3RhdGUgPSBTU19ESVNDT05ORUNUSU5HOworCisJc2sgPSBzb2NrLT5zazsKKworCWxvY2tfc29j ayhzayk7CisKKwlzay0+c2tfc2h1dGRvd24gfD0gbW9kZTsKKwlzay0+c2tfc3RhdGVfY2hhbmdl KHNrKTsKKworCWlmIChtb2RlICYgU0VORF9TSFVURE9XTikgeworCQlodnNrID0gc2tfdG9faHZz b2NrKHNrKTsKKwkJLyogSXQgY2FuJ3QgZmFpbDogc2VlIGdldF9yaW5nYnVmZmVyX3dyaXRhYmxl X2J5dGVzKCkuICovCisJCSh2b2lkKWh2c29ja19zZW5kX2RhdGEoaHZzay0+Y2hhbm5lbCwgaHZz aywgMCk7CisJfQorCisJcmVsZWFzZV9zb2NrKHNrKTsKKworCXJldHVybiAwOworfQorCitzdGF0 aWMgdW5zaWduZWQgaW50IGh2c29ja19wb2xsKHN0cnVjdCBmaWxlICpmaWxlLCBzdHJ1Y3Qgc29j a2V0ICpzb2NrLAorCQkJCXBvbGxfdGFibGUgKndhaXQpCit7CisJc3RydWN0IHZtYnVzX2NoYW5u ZWwgKmNoYW5uZWw7CisJYm9vbCBjYW5fcmVhZCwgY2FuX3dyaXRlOworCXN0cnVjdCBodnNvY2tf c29jayAqaHZzazsKKwlzdHJ1Y3Qgc29jayAqc2s7CisJdW5zaWduZWQgaW50IG1hc2s7CisKKwlz ayA9IHNvY2stPnNrOworCWh2c2sgPSBza190b19odnNvY2soc2spOworCisJcG9sbF93YWl0KGZp bGUsIHNrX3NsZWVwKHNrKSwgd2FpdCk7CisJbWFzayA9IDA7CisKKwlpZiAoc2stPnNrX2VycikK KwkJLyogU2lnbmlmeSB0aGF0IHRoZXJlIGhhcyBiZWVuIGFuIGVycm9yIG9uIHRoaXMgc29ja2V0 LiAqLworCQltYXNrIHw9IFBPTExFUlI7CisKKwkvKiBJTkVUIHNvY2tldHMgdHJlYXQgbG9jYWwg d3JpdGUgc2h1dGRvd24gYW5kIHBlZXIgd3JpdGUgc2h1dGRvd24gYXMgYQorCSAqIGNhc2Ugb2Yg UE9MTEhVUCBzZXQuCisJICovCisJaWYgKChzay0+c2tfc2h1dGRvd24gPT0gU0hVVERPV05fTUFT SykgfHwKKwkgICAgKChzay0+c2tfc2h1dGRvd24gJiBTRU5EX1NIVVRET1dOKSAmJgorCSAgICAg KGh2c2stPnBlZXJfc2h1dGRvd24gJiBTRU5EX1NIVVRET1dOKSkpIHsKKwkJbWFzayB8PSBQT0xM SFVQOworCX0KKworCWlmIChzay0+c2tfc2h1dGRvd24gJiBSQ1ZfU0hVVERPV04gfHwKKwkgICAg aHZzay0+cGVlcl9zaHV0ZG93biAmIFNFTkRfU0hVVERPV04pIHsKKwkJbWFzayB8PSBQT0xMUkRI VVA7CisJfQorCisJbG9ja19zb2NrKHNrKTsKKworCS8qIExpc3RlbmluZyBzb2NrZXRzIHRoYXQg aGF2ZSBjb25uZWN0aW9ucyBpbiB0aGVpciBhY2NlcHQKKwkgKiBxdWV1ZSBjYW4gYmUgcmVhZC4K KwkgKi8KKwlpZiAoc2stPnNrX3N0YXRlID09IFNTX0xJU1RFTiAmJiAhaHZzb2NrX2lzX2FjY2Vw dF9xdWV1ZV9lbXB0eShzaykpCisJCW1hc2sgfD0gUE9MTElOIHwgUE9MTFJETk9STTsKKworCS8q IFRoZSBtdXRleCBpcyB0byBhZ2FpbnN0IGh2c29ja19vcGVuX2Nvbm5lY3Rpb24oKSAqLworCW11 dGV4X2xvY2soJmh2c29ja19tdXRleCk7CisKKwljaGFubmVsID0gaHZzay0+Y2hhbm5lbDsKKwlp ZiAoY2hhbm5lbCkgeworCQkvKiBJZiB0aGVyZSBpcyBzb21ldGhpbmcgaW4gdGhlIHF1ZXVlIHRo ZW4gd2UgY2FuIHJlYWQgKi8KKwkJZ2V0X3JpbmdidWZmZXJfcndfc3RhdHVzKGNoYW5uZWwsICZj YW5fcmVhZCwgJmNhbl93cml0ZSk7CisKKwkJaWYgKCFjYW5fcmVhZCAmJiBodnNrLT5yZWN2LT5k YXRhX2xlbiA+IDApCisJCQljYW5fcmVhZCA9IHRydWU7CisKKwkJaWYgKCEoc2stPnNrX3NodXRk b3duICYgUkNWX1NIVVRET1dOKSAmJiBjYW5fcmVhZCkKKwkJCW1hc2sgfD0gUE9MTElOIHwgUE9M TFJETk9STTsKKwl9IGVsc2UgeworCQljYW5fcmVhZCA9IGZhbHNlOworCQljYW5fd3JpdGUgPSBm YWxzZTsKKwl9CisKKwltdXRleF91bmxvY2soJmh2c29ja19tdXRleCk7CisKKwkvKiBTb2NrZXRz IHdob3NlIGNvbm5lY3Rpb25zIGhhdmUgYmVlbiBjbG9zZWQgdGVybWluYXRlZCBzaG91bGQKKwkg KiBhbHNvIGJlIGNvbnNpZGVyZWQgcmVhZCwgYW5kIHdlIGNoZWNrIHRoZSBzaHV0ZG93biBmbGFn IGZvciB0aGF0LgorCSAqLworCWlmIChzay0+c2tfc2h1dGRvd24gJiBSQ1ZfU0hVVERPV04gfHwK KwkgICAgaHZzay0+cGVlcl9zaHV0ZG93biAmIFNFTkRfU0hVVERPV04pIHsKKwkJbWFzayB8PSBQ T0xMSU4gfCBQT0xMUkROT1JNOworCX0KKworCS8qIENvbm5lY3RlZCBzb2NrZXRzIHRoYXQgY2Fu IHByb2R1Y2UgZGF0YSBjYW4gYmUgd3JpdHRlbi4gKi8KKwlpZiAoc2stPnNrX3N0YXRlID09IFNT X0NPTk5FQ1RFRCAmJiBjYW5fd3JpdGUgJiYKKwkgICAgIShzay0+c2tfc2h1dGRvd24gJiBTRU5E X1NIVVRET1dOKSkgeworCQkvKiBSZW1vdmUgUE9MTFdSQkFORCBzaW5jZSBJTkVUIHNvY2tldHMg YXJlIG5vdCBzZXR0aW5nIGl0LgorCQkgKi8KKwkJbWFzayB8PSBQT0xMT1VUIHwgUE9MTFdSTk9S TTsKKwl9CisKKwkvKiBTaW11bGF0ZSBJTkVUIHNvY2tldCBwb2xsIGJlaGF2aW9ycywgd2hpY2gg c2V0cworCSAqIFBPTExPVVR8UE9MTFdSTk9STSB3aGVuIHBlZXIgaXMgY2xvc2VkIGFuZCBub3Ro aW5nIHRvIHJlYWQsCisJICogYnV0IGxvY2FsIHNlbmQgaXMgbm90IHNodXRkb3duLgorCSAqLwor CWlmIChzay0+c2tfc3RhdGUgPT0gU1NfVU5DT05ORUNURUQgJiYKKwkgICAgIShzay0+c2tfc2h1 dGRvd24gJiBTRU5EX1NIVVRET1dOKSkKKwkJbWFzayB8PSBQT0xMT1VUIHwgUE9MTFdSTk9STTsK KworCXJlbGVhc2Vfc29jayhzayk7CisKKwlyZXR1cm4gbWFzazsKK30KKworLyogVGhpcyBmdW5j dGlvbiBydW5zIGluIHRoZSB0YXNrbGV0IGNvbnRleHQgb2YgcHJvY2Vzc19jaG5fZXZlbnQoKSAq Lworc3RhdGljIHZvaWQgaHZzb2NrX29uX2NoYW5uZWxfY2Iodm9pZCAqY3R4KQoreworCXN0cnVj dCBzb2NrICpzayA9IChzdHJ1Y3Qgc29jayAqKWN0eDsKKwlzdHJ1Y3QgaHZzb2NrX3NvY2sgKmh2 c2sgPSBza190b19odnNvY2soc2spOworCXN0cnVjdCB2bWJ1c19jaGFubmVsICpjaGFubmVsID0g aHZzay0+Y2hhbm5lbDsKKwlib29sIGNhbl9yZWFkLCBjYW5fd3JpdGU7CisKKwlpZiAoIWNoYW5u ZWwpIHsKKwkJV0FSTl9PTkNFKDEsICJOVUxMIGNoYW5uZWwhIFRoZXJlIGlzIGEgcHJvZ3JhbW1p bmcgYnVnLlxuIik7CisJCXJldHVybjsKKwl9CisKKwlnZXRfcmluZ2J1ZmZlcl9yd19zdGF0dXMo Y2hhbm5lbCwgJmNhbl9yZWFkLCAmY2FuX3dyaXRlKTsKKworCWlmIChjYW5fcmVhZCkKKwkJc2st PnNrX2RhdGFfcmVhZHkoc2spOworCisJaWYgKGNhbl93cml0ZSkKKwkJc2stPnNrX3dyaXRlX3Nw YWNlKHNrKTsKK30KKworc3RhdGljIHZvaWQgaHZzb2NrX2Nsb3NlX2Nvbm5lY3Rpb24oc3RydWN0 IHZtYnVzX2NoYW5uZWwgKmNoYW5uZWwpCit7CisJc3RydWN0IGh2c29ja19zb2NrICpodnNrOwor CXN0cnVjdCBzb2NrICpzazsKKworCW11dGV4X2xvY2soJmh2c29ja19tdXRleCk7CisKKwlzayA9 IGh2c29ja19maW5kX2Nvbm5lY3RlZF9zb2NrZXRfYnlfY2hhbm5lbChjaGFubmVsKTsKKworCS8q IFRoZSBndWVzdCBoYXMgYWxyZWFkeSBjbG9zZWQgdGhlIGNvbm5lY3Rpb24/ICovCisJaWYgKCFz aykKKwkJZ290byBvdXQ7CisKKwlzay0+c2tfc3RhdGUgPSBTU19VTkNPTk5FQ1RFRDsKKwlzb2Nr X3NldF9mbGFnKHNrLCBTT0NLX0RPTkUpOworCisJaHZzayA9IHNrX3RvX2h2c29jayhzayk7CisJ aHZzay0+cGVlcl9zaHV0ZG93biB8PSBTRU5EX1NIVVRET1dOIHwgUkNWX1NIVVRET1dOOworCisJ c2stPnNrX3N0YXRlX2NoYW5nZShzayk7CitvdXQ6CisJbXV0ZXhfdW5sb2NrKCZodnNvY2tfbXV0 ZXgpOworfQorCitzdGF0aWMgaW50IGh2c29ja19vcGVuX2Nvbm5lY3Rpb24oc3RydWN0IHZtYnVz X2NoYW5uZWwgKmNoYW5uZWwpCit7CisJc3RydWN0IGh2c29ja19zb2NrICpodnNrLCAqbmV3X2h2 c2s7CisJc3RydWN0IHNvY2thZGRyX2h2IGh2X2FkZHI7CisJc3RydWN0IHNvY2sgKnNrLCAqbmV3 X3NrOworCXVuc2lnbmVkIGNoYXIgY29ubl9mcm9tX2hvc3Q7CisKKwl1dWlkX2xlICppbnN0YW5j ZSwgKnNlcnZpY2VfaWQ7CisJaW50IHJldDsKKworCWluc3RhbmNlID0gJmNoYW5uZWwtPm9mZmVy bXNnLm9mZmVyLmlmX2luc3RhbmNlOworCXNlcnZpY2VfaWQgPSAmY2hhbm5lbC0+b2ZmZXJtc2cu b2ZmZXIuaWZfdHlwZTsKKworCS8qIFRoZSBmaXJzdCBieXRlICE9IDAgbWVhbnMgdGhlIGhvc3Qg aW5pdGlhdGVkIHRoZSBjb25uZWN0aW9uLiAqLworCWNvbm5fZnJvbV9ob3N0ID0gY2hhbm5lbC0+ b2ZmZXJtc2cub2ZmZXIudS5waXBlLnVzZXJfZGVmWzBdOworCisJbXV0ZXhfbG9jaygmaHZzb2Nr X211dGV4KTsKKworCWh2c29ja19hZGRyX2luaXQoJmh2X2FkZHIsIGNvbm5fZnJvbV9ob3N0ID8g KnNlcnZpY2VfaWQgOiAqaW5zdGFuY2UpOworCXNrID0gaHZzb2NrX2ZpbmRfYm91bmRfc29ja2V0 KCZodl9hZGRyKTsKKworCWlmICghc2sgfHwgKGNvbm5fZnJvbV9ob3N0ICYmIHNrLT5za19zdGF0 ZSAhPSBTU19MSVNURU4pIHx8CisJICAgICghY29ubl9mcm9tX2hvc3QgJiYgc2stPnNrX3N0YXRl ICE9IFNTX0NPTk5FQ1RJTkcpKSB7CisJCXJldCA9IC1FTlhJTzsKKwkJZ290byBvdXQ7CisJfQor CisJaWYgKGNvbm5fZnJvbV9ob3N0KSB7CisJCWlmIChzay0+c2tfYWNrX2JhY2tsb2cgPj0gc2st PnNrX21heF9hY2tfYmFja2xvZykgeworCQkJcmV0ID0gLUVNRklMRTsKKwkJCWdvdG8gb3V0Owor CQl9CisKKwkJcmV0ID0gaHZzb2NrX2NyZWF0ZShzb2NrX25ldChzayksIE5VTEwsIEdGUF9LRVJO RUwsCisJCQkJICAgIHNrLT5za190eXBlLCAmbmV3X3NrKTsKKwkJaWYgKHJldCAhPSAwKQorCQkJ Z290byBvdXQ7CisKKwkJbmV3X3NrLT5za19zdGF0ZSA9IFNTX0NPTk5FQ1RJTkc7CisJCW5ld19o dnNrID0gc2tfdG9faHZzb2NrKG5ld19zayk7CisJCW5ld19odnNrLT5jaGFubmVsID0gY2hhbm5l bDsKKwkJaHZzb2NrX2FkZHJfaW5pdCgmbmV3X2h2c2stPmxvY2FsX2FkZHIsICpzZXJ2aWNlX2lk KTsKKwkJaHZzb2NrX2FkZHJfaW5pdCgmbmV3X2h2c2stPnJlbW90ZV9hZGRyLCAqaW5zdGFuY2Up OworCX0gZWxzZSB7CisJCWh2c2sgPSBza190b19odnNvY2soc2spOworCQlodnNrLT5jaGFubmVs ID0gY2hhbm5lbDsKKwl9CisKKwlzZXRfY2hhbm5lbF9yZWFkX3N0YXRlKGNoYW5uZWwsIGZhbHNl KTsKKwlyZXQgPSB2bWJ1c19vcGVuKGNoYW5uZWwsIHNlbmRfcmluZ19wYWdlICogUEFHRV9TSVpF LAorCQkJIHJlY3ZfcmluZ19wYWdlICogUEFHRV9TSVpFLCBOVUxMLCAwLAorCQkJIGh2c29ja19v bl9jaGFubmVsX2NiLCBjb25uX2Zyb21faG9zdCA/IG5ld19zayA6IHNrKTsKKwlpZiAocmV0ICE9 IDApIHsKKwkJaWYgKGNvbm5fZnJvbV9ob3N0KSB7CisJCQluZXdfaHZzay0+Y2hhbm5lbCA9IE5V TEw7CisJCQlzb2NrX3B1dChuZXdfc2spOworCQl9IGVsc2UgeworCQkJaHZzay0+Y2hhbm5lbCA9 IE5VTEw7CisJCX0KKwkJZ290byBvdXQ7CisJfQorCisJdm1idXNfc2V0X2Nobl9yZXNjaW5kX2Nh bGxiYWNrKGNoYW5uZWwsIGh2c29ja19jbG9zZV9jb25uZWN0aW9uKTsKKwlzZXRfY2hhbm5lbF9w ZW5kaW5nX3NlbmRfc2l6ZShjaGFubmVsLAorCQkJCSAgICAgIEhWU09DS19QS1RfTEVOKEhWU09D S19TTkRfVEhSRVNIT0xEKSk7CisKKwlpZiAoY29ubl9mcm9tX2hvc3QpIHsKKwkJbmV3X3NrLT5z a19zdGF0ZSA9IFNTX0NPTk5FQ1RFRDsKKworCQlzb2NrX2hvbGQoJm5ld19odnNrLT5zayk7CisJ CWxpc3RfYWRkKCZuZXdfaHZzay0+Y29ubmVjdGVkX2xpc3QsICZodnNvY2tfY29ubmVjdGVkX2xp c3QpOworCisJCWh2c29ja19lbnF1ZXVlX2FjY2VwdChzaywgbmV3X3NrKTsKKwl9IGVsc2Ugewor CQlzay0+c2tfc3RhdGUgPSBTU19DT05ORUNURUQ7CisJCXNrLT5za19zb2NrZXQtPnN0YXRlID0g U1NfQ09OTkVDVEVEOworCisJCXNvY2tfaG9sZCgmaHZzay0+c2spOworCQlsaXN0X2FkZCgmaHZz ay0+Y29ubmVjdGVkX2xpc3QsICZodnNvY2tfY29ubmVjdGVkX2xpc3QpOworCX0KKworCXNrLT5z a19zdGF0ZV9jaGFuZ2Uoc2spOworb3V0OgorCW11dGV4X3VubG9jaygmaHZzb2NrX211dGV4KTsK KwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgdm9pZCBodnNvY2tfY29ubmVjdF90aW1lb3V0KHN0 cnVjdCB3b3JrX3N0cnVjdCAqd29yaykKK3sKKwlzdHJ1Y3QgaHZzb2NrX3NvY2sgKmh2c2s7CisJ c3RydWN0IHNvY2sgKnNrOworCisJaHZzayA9IGNvbnRhaW5lcl9vZih3b3JrLCBzdHJ1Y3QgaHZz b2NrX3NvY2ssIGR3b3JrLndvcmspOworCXNrID0gaHZzb2NrX3RvX3NrKGh2c2spOworCisJbG9j a19zb2NrKHNrKTsKKwlpZiAoKHNrLT5za19zdGF0ZSA9PSBTU19DT05ORUNUSU5HKSAmJgorCSAg ICAoc2stPnNrX3NodXRkb3duICE9IFNIVVRET1dOX01BU0spKSB7CisJCXNrLT5za19zdGF0ZSA9 IFNTX1VOQ09OTkVDVEVEOworCQlzay0+c2tfZXJyID0gRVRJTUVET1VUOworCQlzay0+c2tfZXJy b3JfcmVwb3J0KHNrKTsKKwl9CisJcmVsZWFzZV9zb2NrKHNrKTsKKworCXNvY2tfcHV0KHNrKTsK K30KKworc3RhdGljIGludCBodnNvY2tfY29ubmVjdF93YWl0KHN0cnVjdCBzb2NrZXQgKnNvY2ss CisJCQkgICAgICAgaW50IGZsYWdzLCBpbnQgY3VycmVudF9yZXQpCit7CisJc3RydWN0IHNvY2sg KnNrID0gc29jay0+c2s7CisJc3RydWN0IGh2c29ja19zb2NrICpodnNrID0gc2tfdG9faHZzb2Nr KHNrKTsKKworCWludCByZXQgPSBjdXJyZW50X3JldDsKKworCWxvbmcgdGltZW91dCA9IDMwICog SFo7CisJREVGSU5FX1dBSVQod2FpdCk7CisKKwlwcmVwYXJlX3RvX3dhaXQoc2tfc2xlZXAoc2sp LCAmd2FpdCwgVEFTS19JTlRFUlJVUFRJQkxFKTsKKworCXdoaWxlIChzay0+c2tfc3RhdGUgIT0g U1NfQ09OTkVDVEVEICYmIHNrLT5za19lcnIgPT0gMCkgeworCQlpZiAoZmxhZ3MgJiBPX05PTkJM T0NLKSB7CisJCQkvKiBJZiB3ZSdyZSBub3QgZ29pbmcgdG8gYmxvY2ssIHdlIHNjaGVkdWxlIGEg dGltZW91dAorCQkJICogZnVuY3Rpb24gdG8gZ2VuZXJhdGUgYSB0aW1lb3V0IG9uIHRoZSBjb25u ZWN0aW9uCisJCQkgKiBhdHRlbXB0LCBpbiBjYXNlIHRoZSBwZWVyIGRvZXNuJ3QgcmVzcG9uZCBp biBhCisJCQkgKiB0aW1lbHkgbWFubmVyLiBXZSBob2xkIG9uIHRvIHRoZSBzb2NrZXQgdW50aWwg dGhlCisJCQkgKiB0aW1lb3V0IGZpcmVzLgorCQkJICovCisJCQlzb2NrX2hvbGQoc2spOworCQkJ SU5JVF9ERUxBWUVEX1dPUksoJmh2c2stPmR3b3JrLAorCQkJCQkgIGh2c29ja19jb25uZWN0X3Rp bWVvdXQpOworCQkJc2NoZWR1bGVfZGVsYXllZF93b3JrKCZodnNrLT5kd29yaywgdGltZW91dCk7 CisKKwkJCS8qIFNraXAgYWhlYWQgdG8gcHJlc2VydmUgZXJyb3IgY29kZSBzZXQgYWJvdmUuICov CisJCQlnb3RvIG91dF93YWl0OworCQl9CisKKwkJcmVsZWFzZV9zb2NrKHNrKTsKKwkJdGltZW91 dCA9IHNjaGVkdWxlX3RpbWVvdXQodGltZW91dCk7CisJCWxvY2tfc29jayhzayk7CisKKwkJaWYg KHNpZ25hbF9wZW5kaW5nKGN1cnJlbnQpKSB7CisJCQlyZXQgPSBzb2NrX2ludHJfZXJybm8odGlt ZW91dCk7CisJCQlnb3RvIG91dF93YWl0X2Vycm9yOworCQl9IGVsc2UgaWYgKHRpbWVvdXQgPT0g MCkgeworCQkJcmV0ID0gLUVUSU1FRE9VVDsKKwkJCWdvdG8gb3V0X3dhaXRfZXJyb3I7CisJCX0K KworCQlwcmVwYXJlX3RvX3dhaXQoc2tfc2xlZXAoc2spLCAmd2FpdCwgVEFTS19JTlRFUlJVUFRJ QkxFKTsKKwl9CisKKwlyZXQgPSBzay0+c2tfZXJyID8gLXNrLT5za19lcnIgOiAwOworCitvdXRf d2FpdF9lcnJvcjoKKwlpZiAocmV0IDwgMCkgeworCQlzay0+c2tfc3RhdGUgPSBTU19VTkNPTk5F Q1RFRDsKKwkJc29jay0+c3RhdGUgPSBTU19VTkNPTk5FQ1RFRDsKKwl9CitvdXRfd2FpdDoKKwlm aW5pc2hfd2FpdChza19zbGVlcChzayksICZ3YWl0KTsKKwlyZXR1cm4gcmV0OworfQorCitzdGF0 aWMgaW50IGh2c29ja19jb25uZWN0KHN0cnVjdCBzb2NrZXQgKnNvY2ssIHN0cnVjdCBzb2NrYWRk ciAqYWRkciwKKwkJCSAgaW50IGFkZHJfbGVuLCBpbnQgZmxhZ3MpCit7CisJc3RydWN0IHNvY2th ZGRyX2h2ICpyZW1vdGVfYWRkcjsKKwlzdHJ1Y3QgaHZzb2NrX3NvY2sgKmh2c2s7CisJc3RydWN0 IHNvY2sgKnNrOworCWludCByZXQgPSAwOworCisJc2sgPSBzb2NrLT5zazsKKwlodnNrID0gc2tf dG9faHZzb2NrKHNrKTsKKworCWxvY2tfc29jayhzayk7CisKKwlzd2l0Y2ggKHNvY2stPnN0YXRl KSB7CisJY2FzZSBTU19DT05ORUNURUQ6CisJCXJldCA9IC1FSVNDT05OOworCQlnb3RvIG91dDsK KwljYXNlIFNTX0RJU0NPTk5FQ1RJTkc6CisJCXJldCA9IC1FSU5WQUw7CisJCWdvdG8gb3V0Owor CWNhc2UgU1NfQ09OTkVDVElORzoKKwkJLyogVGhpcyBjb250aW51ZXMgb24gc28gd2UgY2FuIG1v dmUgc29jayBpbnRvIHRoZSBTU19DT05ORUNURUQKKwkJICogc3RhdGUgb25jZSB0aGUgY29ubmVj dGlvbiBoYXMgY29tcGxldGVkIChhdCB3aGljaCBwb2ludCBlcnIKKwkJICogd2lsbCBiZSBzZXQg dG8gemVybyBhbHNvKS4gIE90aGVyd2lzZSwgd2Ugd2lsbCBlaXRoZXIgd2FpdAorCQkgKiBmb3Ig dGhlIGNvbm5lY3Rpb24gb3IgcmV0dXJuIC1FQUxSRUFEWSBzaG91bGQgdGhpcyBiZSBhCisJCSAq IG5vbi1ibG9ja2luZyBjYWxsLgorCQkgKi8KKwkJcmV0ID0gLUVBTFJFQURZOworCQlicmVhazsK KwlkZWZhdWx0OgorCQlpZiAoKHNrLT5za19zdGF0ZSA9PSBTU19MSVNURU4pIHx8CisJCSAgICBo dnNvY2tfYWRkcl9jYXN0KGFkZHIsIGFkZHJfbGVuLCAmcmVtb3RlX2FkZHIpICE9IDApIHsKKwkJ CXJldCA9IC1FSU5WQUw7CisJCQlnb3RvIG91dDsKKwkJfQorCisJCS8qIFNldCB0aGUgcmVtb3Rl IGFkZHJlc3MgdGhhdCB3ZSBhcmUgY29ubmVjdGluZyB0by4gKi8KKwkJbWVtY3B5KCZodnNrLT5y ZW1vdGVfYWRkciwgcmVtb3RlX2FkZHIsCisJCSAgICAgICBzaXplb2YoaHZzay0+cmVtb3RlX2Fk ZHIpKTsKKworCQlyZXQgPSBodnNvY2tfYXV0b19iaW5kKGh2c2spOworCQlpZiAocmV0KQorCQkJ Z290byBvdXQ7CisKKwkJc2stPnNrX3N0YXRlID0gU1NfQ09OTkVDVElORzsKKworCQlyZXQgPSB2 bWJ1c19zZW5kX3RsX2Nvbm5lY3RfcmVxdWVzdCgKKwkJCQkJJmh2c2stPmxvY2FsX2FkZHIuc2h2 X3NlcnZpY2VfaWQsCisJCQkJCSZodnNrLT5yZW1vdGVfYWRkci5zaHZfc2VydmljZV9pZCk7CisJ CWlmIChyZXQgPCAwKQorCQkJZ290byBvdXQ7CisKKwkJLyogTWFyayBzb2NrIGFzIGNvbm5lY3Rp bmcgYW5kIHNldCB0aGUgZXJyb3IgY29kZSB0byBpbgorCQkgKiBwcm9ncmVzcyBpbiBjYXNlIHRo aXMgaXMgYSBub24tYmxvY2tpbmcgY29ubmVjdC4KKwkJICovCisJCXNvY2stPnN0YXRlID0gU1Nf Q09OTkVDVElORzsKKwkJcmV0ID0gLUVJTlBST0dSRVNTOworCX0KKworCXJldCA9IGh2c29ja19j b25uZWN0X3dhaXQoc29jaywgZmxhZ3MsIHJldCk7CitvdXQ6CisJcmVsZWFzZV9zb2NrKHNrKTsK KwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgaW50IGh2c29ja19hY2NlcHRfd2FpdChzdHJ1Y3Qg c29jayAqbGlzdGVuZXIsCisJCQkgICAgICBzdHJ1Y3Qgc29ja2V0ICpuZXdzb2NrLCBpbnQgZmxh Z3MpCit7CisJc3RydWN0IGh2c29ja19zb2NrICpodmNvbm5lY3RlZDsKKwlzdHJ1Y3Qgc29jayAq Y29ubmVjdGVkOworCisJREVGSU5FX1dBSVQod2FpdCk7CisJbG9uZyB0aW1lb3V0OworCisJaW50 IHJldCA9IDA7CisKKwkvKiBXYWl0IGZvciBjaGlsZHJlbiBzb2NrZXRzIHRvIGFwcGVhcjsgdGhl c2UgYXJlIHRoZSBuZXcgc29ja2V0cworCSAqIGNyZWF0ZWQgdXBvbiBjb25uZWN0aW9uIGVzdGFi bGlzaG1lbnQuCisJICovCisJdGltZW91dCA9IHNvY2tfc25kdGltZW8obGlzdGVuZXIsIGZsYWdz ICYgT19OT05CTE9DSyk7CisJcHJlcGFyZV90b193YWl0KHNrX3NsZWVwKGxpc3RlbmVyKSwgJndh aXQsIFRBU0tfSU5URVJSVVBUSUJMRSk7CisKKwl3aGlsZSAoKGNvbm5lY3RlZCA9IGh2c29ja19k ZXF1ZXVlX2FjY2VwdChsaXN0ZW5lcikpID09IE5VTEwgJiYKKwkgICAgICAgbGlzdGVuZXItPnNr X2VyciA9PSAwKSB7CisJCXJlbGVhc2Vfc29jayhsaXN0ZW5lcik7CisJCXRpbWVvdXQgPSBzY2hl ZHVsZV90aW1lb3V0KHRpbWVvdXQpOworCQlsb2NrX3NvY2sobGlzdGVuZXIpOworCisJCWlmIChz aWduYWxfcGVuZGluZyhjdXJyZW50KSkgeworCQkJcmV0ID0gc29ja19pbnRyX2Vycm5vKHRpbWVv dXQpOworCQkJZ290byBvdXRfd2FpdDsKKwkJfSBlbHNlIGlmICh0aW1lb3V0ID09IDApIHsKKwkJ CXJldCA9IC1FQUdBSU47CisJCQlnb3RvIG91dF93YWl0OworCQl9CisKKwkJcHJlcGFyZV90b193 YWl0KHNrX3NsZWVwKGxpc3RlbmVyKSwgJndhaXQsIFRBU0tfSU5URVJSVVBUSUJMRSk7CisJfQor CisJaWYgKGxpc3RlbmVyLT5za19lcnIpCisJCXJldCA9IC1saXN0ZW5lci0+c2tfZXJyOworCisJ aWYgKGNvbm5lY3RlZCkgeworCQlsb2NrX3NvY2soY29ubmVjdGVkKTsKKwkJaHZjb25uZWN0ZWQg PSBza190b19odnNvY2soY29ubmVjdGVkKTsKKworCQlpZiAocmV0KSB7CisJCQlyZWxlYXNlX3Nv Y2soY29ubmVjdGVkKTsKKwkJCXNvY2tfcHV0KGNvbm5lY3RlZCk7CisJCX0gZWxzZSB7CisJCQlu ZXdzb2NrLT5zdGF0ZSA9IFNTX0NPTk5FQ1RFRDsKKwkJCXNvY2tfZ3JhZnQoY29ubmVjdGVkLCBu ZXdzb2NrKTsKKwkJCXJlbGVhc2Vfc29jayhjb25uZWN0ZWQpOworCQkJc29ja19wdXQoY29ubmVj dGVkKTsKKwkJfQorCX0KKworb3V0X3dhaXQ6CisJZmluaXNoX3dhaXQoc2tfc2xlZXAobGlzdGVu ZXIpLCAmd2FpdCk7CisJcmV0dXJuIHJldDsKK30KKworc3RhdGljCitpbnQgaHZzb2NrX2FjY2Vw dChzdHJ1Y3Qgc29ja2V0ICpzb2NrLCBzdHJ1Y3Qgc29ja2V0ICpuZXdzb2NrLCBpbnQgZmxhZ3Mp Cit7CisJc3RydWN0IHNvY2sgKmxpc3RlbmVyOworCWludCByZXQ7CisKKwlsaXN0ZW5lciA9IHNv Y2stPnNrOworCisJbG9ja19zb2NrKGxpc3RlbmVyKTsKKworCWlmIChzb2NrLT50eXBlICE9IFNP Q0tfU1RSRUFNKSB7CisJCXJldCA9IC1FT1BOT1RTVVBQOworCQlnb3RvIG91dDsKKwl9CisKKwlp ZiAobGlzdGVuZXItPnNrX3N0YXRlICE9IFNTX0xJU1RFTikgeworCQlyZXQgPSAtRUlOVkFMOwor CQlnb3RvIG91dDsKKwl9CisKKwlyZXQgPSBodnNvY2tfYWNjZXB0X3dhaXQobGlzdGVuZXIsIG5l d3NvY2ssIGZsYWdzKTsKK291dDoKKwlyZWxlYXNlX3NvY2sobGlzdGVuZXIpOworCXJldHVybiBy ZXQ7Cit9CisKK3N0YXRpYyBpbnQgaHZzb2NrX2xpc3RlbihzdHJ1Y3Qgc29ja2V0ICpzb2NrLCBp bnQgYmFja2xvZykKK3sKKwlzdHJ1Y3QgaHZzb2NrX3NvY2sgKmh2c2s7CisJc3RydWN0IHNvY2sg KnNrOworCWludCByZXQgPSAwOworCisJc2sgPSBzb2NrLT5zazsKKwlsb2NrX3NvY2soc2spOwor CisJaWYgKHNvY2stPnR5cGUgIT0gU09DS19TVFJFQU0pIHsKKwkJcmV0ID0gLUVPUE5PVFNVUFA7 CisJCWdvdG8gb3V0OworCX0KKworCWlmIChzb2NrLT5zdGF0ZSAhPSBTU19VTkNPTk5FQ1RFRCkg eworCQlyZXQgPSAtRUlOVkFMOworCQlnb3RvIG91dDsKKwl9CisKKwlpZiAoYmFja2xvZyA8PSAw KSB7CisJCXJldCA9IC1FSU5WQUw7CisJCWdvdG8gb3V0OworCX0KKwkvKiBUaGlzIGlzIGFuIGFy dGlmaWNpYWwgbGltaXQgKi8KKwlpZiAoYmFja2xvZyA+IDEyOCkKKwkJYmFja2xvZyA9IDEyODsK KworCWh2c2sgPSBza190b19odnNvY2soc2spOworCWlmICghaHZzb2NrX2FkZHJfYm91bmQoJmh2 c2stPmxvY2FsX2FkZHIpKSB7CisJCXJldCA9IC1FSU5WQUw7CisJCWdvdG8gb3V0OworCX0KKwor CXNrLT5za19hY2tfYmFja2xvZyA9IDA7CisJc2stPnNrX21heF9hY2tfYmFja2xvZyA9IGJhY2ts b2c7CisJc2stPnNrX3N0YXRlID0gU1NfTElTVEVOOworb3V0OgorCXJlbGVhc2Vfc29jayhzayk7 CisJcmV0dXJuIHJldDsKK30KKworc3RhdGljCitpbnQgaHZzb2NrX3NlbmRtc2dfd2FpdChzdHJ1 Y3Qgc29jayAqc2ssIHN0cnVjdCBtc2doZHIgKm1zZywgc2l6ZV90IGxlbikKK3sKKwlzdHJ1Y3Qg aHZzb2NrX3NvY2sgKmh2c2sgPSBza190b19odnNvY2soc2spOworCXN0cnVjdCB2bWJ1c19jaGFu bmVsICpjaGFubmVsID0gaHZzay0+Y2hhbm5lbDsKKworCXNpemVfdCB0b3RhbF90b193cml0ZSA9 IGxlbjsKKwlzaXplX3QgdG90YWxfd3JpdHRlbiA9IDA7CisJYm9vbCBjYW5fd3JpdGU7CisKKwlp bnQgcmV0ID0gMDsKKworCURFRklORV9XQUlUKHdhaXQpOworCWxvbmcgdGltZW91dDsKKworCXRp bWVvdXQgPSBzb2NrX3NuZHRpbWVvKHNrLCBtc2ctPm1zZ19mbGFncyAmIE1TR19ET05UV0FJVCk7 CisJcHJlcGFyZV90b193YWl0KHNrX3NsZWVwKHNrKSwgJndhaXQsIFRBU0tfSU5URVJSVVBUSUJM RSk7CisKKwl3aGlsZSAodG90YWxfdG9fd3JpdGUgPiAwKSB7CisJCXNpemVfdCB0b193cml0ZSwg bWF4X3dyaXRhYmxlOworCisJCXdoaWxlICgxKSB7CisJCQlnZXRfcmluZ2J1ZmZlcl9yd19zdGF0 dXMoY2hhbm5lbCwgTlVMTCwgJmNhbl93cml0ZSk7CisKKwkJCWlmIChjYW5fd3JpdGUgfHwgc2st PnNrX2VyciAhPSAwIHx8CisJCQkgICAgKHNrLT5za19zaHV0ZG93biAmIFNFTkRfU0hVVERPV04p IHx8CisJCQkgICAgKGh2c2stPnBlZXJfc2h1dGRvd24gJiBSQ1ZfU0hVVERPV04pKQorCQkJCWJy ZWFrOworCisJCQkvKiBEb24ndCB3YWl0IGZvciBub24tYmxvY2tpbmcgc29ja2V0cy4gKi8KKwkJ CWlmICh0aW1lb3V0ID09IDApIHsKKwkJCQlyZXQgPSAtRUFHQUlOOworCQkJCWdvdG8gb3V0X3dh aXQ7CisJCQl9CisKKwkJCXJlbGVhc2Vfc29jayhzayk7CisKKwkJCXRpbWVvdXQgPSBzY2hlZHVs ZV90aW1lb3V0KHRpbWVvdXQpOworCisJCQlsb2NrX3NvY2soc2spOworCQkJaWYgKHNpZ25hbF9w ZW5kaW5nKGN1cnJlbnQpKSB7CisJCQkJcmV0ID0gc29ja19pbnRyX2Vycm5vKHRpbWVvdXQpOwor CQkJCWdvdG8gb3V0X3dhaXQ7CisJCQl9IGVsc2UgaWYgKHRpbWVvdXQgPT0gMCkgeworCQkJCXJl dCA9IC1FQUdBSU47CisJCQkJZ290byBvdXRfd2FpdDsKKwkJCX0KKworCQkJcHJlcGFyZV90b193 YWl0KHNrX3NsZWVwKHNrKSwgJndhaXQsCisJCQkJCVRBU0tfSU5URVJSVVBUSUJMRSk7CisJCX0K KworCQkvKiBUaGVzZSBjaGVja3Mgb2NjdXIgYm90aCBhcyBwYXJ0IG9mIGFuZCBhZnRlciB0aGUg bG9vcAorCQkgKiBjb25kaXRpb25hbCBzaW5jZSB3ZSBuZWVkIHRvIGNoZWNrIGJlZm9yZSBhbmQg YWZ0ZXIKKwkJICogc2xlZXBpbmcuCisJCSAqLworCQlpZiAoc2stPnNrX2VycikgeworCQkJcmV0 ID0gLXNrLT5za19lcnI7CisJCQlnb3RvIG91dF93YWl0OworCQl9IGVsc2UgaWYgKChzay0+c2tf c2h1dGRvd24gJiBTRU5EX1NIVVRET1dOKSB8fAorCQkJICAgKGh2c2stPnBlZXJfc2h1dGRvd24g JiBSQ1ZfU0hVVERPV04pKSB7CisJCQlyZXQgPSAtRVBJUEU7CisJCQlnb3RvIG91dF93YWl0Owor CQl9CisKKwkJLyogTm90ZTogdGhhdCB3cml0ZSB3aWxsIG9ubHkgd3JpdGUgYXMgbWFueSBieXRl cyBhcyBwb3NzaWJsZQorCQkgKiBpbiB0aGUgcmluZ2J1ZmZlci4gSXQgaXMgdGhlIGNhbGxlcidz IHJlc3BvbnNpYmlsaXR5IHRvCisJCSAqIGNoZWNrIGhvdyBtYW55IGJ5dGVzIHdlIGFjdHVhbGx5 IHdyb3RlLgorCQkgKi8KKwkJZG8geworCQkJbWF4X3dyaXRhYmxlID0gZ2V0X3JpbmdidWZmZXJf d3JpdGFibGVfYnl0ZXMoY2hhbm5lbCk7CisJCQlpZiAobWF4X3dyaXRhYmxlID09IDApCisJCQkJ Z290byBvdXRfd2FpdDsKKworCQkJdG9fd3JpdGUgPSBtaW5fdChzaXplX3QsIEhWU09DS19TTkRf QlVGX1NaLAorCQkJCQkgdG90YWxfdG9fd3JpdGUpOworCQkJaWYgKHRvX3dyaXRlID4gbWF4X3dy aXRhYmxlKQorCQkJCXRvX3dyaXRlID0gbWF4X3dyaXRhYmxlOworCisJCQlyZXQgPSBtZW1jcHlf ZnJvbV9tc2coaHZzay0+c2VuZC0+YnVmLCBtc2csIHRvX3dyaXRlKTsKKwkJCWlmIChyZXQgIT0g MCkKKwkJCQlnb3RvIG91dF93YWl0OworCisJCQlyZXQgPSBodnNvY2tfc2VuZF9kYXRhKGNoYW5u ZWwsIGh2c2ssIHRvX3dyaXRlKTsKKwkJCWlmIChyZXQgIT0gMCkKKwkJCQlnb3RvIG91dF93YWl0 OworCisJCQl0b3RhbF93cml0dGVuICs9IHRvX3dyaXRlOworCQkJdG90YWxfdG9fd3JpdGUgLT0g dG9fd3JpdGU7CisJCX0gd2hpbGUgKHRvdGFsX3RvX3dyaXRlID4gMCk7CisJfQorCitvdXRfd2Fp dDoKKwlpZiAodG90YWxfd3JpdHRlbiA+IDApCisJCXJldCA9IHRvdGFsX3dyaXR0ZW47CisKKwlm aW5pc2hfd2FpdChza19zbGVlcChzayksICZ3YWl0KTsKKwlyZXR1cm4gcmV0OworfQorCitzdGF0 aWMgaW50IGh2c29ja19zZW5kbXNnKHN0cnVjdCBzb2NrZXQgKnNvY2ssIHN0cnVjdCBtc2doZHIg Km1zZywgc2l6ZV90IGxlbikKK3sKKwlzdHJ1Y3QgaHZzb2NrX3NvY2sgKmh2c2s7CisJc3RydWN0 IHNvY2sgKnNrOworCWludCByZXQ7CisKKwlpZiAobGVuID09IDApCisJCXJldHVybiAtRUlOVkFM OworCisJaWYgKG1zZy0+bXNnX2ZsYWdzICYgfk1TR19ET05UV0FJVCkgeworCQlwcl9lcnIoIiVz OiB1bnN1cHBvcnRlZCBmbGFncz0weCV4XG4iLCBfX2Z1bmNfXywKKwkJICAgICAgIG1zZy0+bXNn X2ZsYWdzKTsKKwkJcmV0dXJuIC1FT1BOT1RTVVBQOworCX0KKworCXNrID0gc29jay0+c2s7CisJ aHZzayA9IHNrX3RvX2h2c29jayhzayk7CisKKwlsb2NrX3NvY2soc2spOworCisJLyogQ2FsbGVy cyBzaG91bGQgbm90IHByb3ZpZGUgYSBkZXN0aW5hdGlvbiB3aXRoIHN0cmVhbSBzb2NrZXRzLiAq LworCWlmIChtc2ctPm1zZ19uYW1lbGVuKSB7CisJCXJldCA9IC1FT1BOT1RTVVBQOworCQlnb3Rv IG91dDsKKwl9CisKKwkvKiBTZW5kIGRhdGEgb25seSBpZiBib3RoIHNpZGVzIGFyZSBub3Qgc2h1 dGRvd24gaW4gdGhlIGRpcmVjdGlvbi4gKi8KKwlpZiAoc2stPnNrX3NodXRkb3duICYgU0VORF9T SFVURE9XTiB8fAorCSAgICBodnNrLT5wZWVyX3NodXRkb3duICYgUkNWX1NIVVRET1dOKSB7CisJ CXJldCA9IC1FUElQRTsKKwkJZ290byBvdXQ7CisJfQorCisJaWYgKHNrLT5za19zdGF0ZSAhPSBT U19DT05ORUNURUQgfHwKKwkgICAgIWh2c29ja19hZGRyX2JvdW5kKCZodnNrLT5sb2NhbF9hZGRy KSkgeworCQlyZXQgPSAtRU5PVENPTk47CisJCWdvdG8gb3V0OworCX0KKworCWlmICghaHZzb2Nr X2FkZHJfYm91bmQoJmh2c2stPnJlbW90ZV9hZGRyKSkgeworCQlyZXQgPSAtRURFU1RBRERSUkVR OworCQlnb3RvIG91dDsKKwl9CisKKwlyZXQgPSBodnNvY2tfc2VuZG1zZ193YWl0KHNrLCBtc2cs IGxlbik7CitvdXQ6CisJcmVsZWFzZV9zb2NrKHNrKTsKKworCS8qIHJldCBpcyBhIGJpZ2dlci10 aGFuLTAgdG90YWxfd3JpdHRlbiBvciBhIG5lZ2F0aXZlIGVyciBjb2RlLiAqLworCWlmIChyZXQg PT0gMCkgeworCQlXQVJOKDEsICJ1bmV4cGVjdGVkIHJldHVybiB2YWx1ZSBvZiAwXG4iKTsKKwkJ cmV0ID0gLUVJTzsKKwl9CisKKwlyZXR1cm4gcmV0OworfQorCitzdGF0aWMgaW50IGh2c29ja19y ZWN2bXNnX3dhaXQoc3RydWN0IHNvY2sgKnNrLCBzdHJ1Y3QgbXNnaGRyICptc2csCisJCQkgICAg ICAgc2l6ZV90IGxlbiwgaW50IGZsYWdzKQoreworCXN0cnVjdCBodnNvY2tfc29jayAqaHZzayA9 IHNrX3RvX2h2c29jayhzayk7CisJc3RydWN0IHZtYnVzX2NoYW5uZWwgKmNoYW5uZWwgPSBodnNr LT5jaGFubmVsOworCisJc2l6ZV90IHRvX3JlYWQsIHRvdGFsX3RvX3JlYWQgPSBsZW47CisJc2l6 ZV90IGNvcGllZCA9IDA7CisJYm9vbCBjYW5fcmVhZDsKKworCWludCByZXQgPSAwOworCisJREVG SU5FX1dBSVQod2FpdCk7CisJbG9uZyB0aW1lb3V0OworCisJdGltZW91dCA9IHNvY2tfcmN2dGlt ZW8oc2ssIGZsYWdzICYgTVNHX0RPTlRXQUlUKTsKKwlwcmVwYXJlX3RvX3dhaXQoc2tfc2xlZXAo c2spLCAmd2FpdCwgVEFTS19JTlRFUlJVUFRJQkxFKTsKKworCXdoaWxlICgxKSB7CisJCWJvb2wg bmVlZF9yZWZpbGwgPSBodnNrLT5yZWN2LT5kYXRhX2xlbiA9PSAwOworCisJCWlmIChuZWVkX3Jl ZmlsbCkKKwkJCWdldF9yaW5nYnVmZmVyX3J3X3N0YXR1cyhjaGFubmVsLCAmY2FuX3JlYWQsIE5V TEwpOworCQllbHNlCisJCQljYW5fcmVhZCA9IHRydWU7CisKKwkJaWYgKGNhbl9yZWFkKSB7CisJ CQlzaXplX3QgcGF5bG9hZF9sZW47CisKKwkJCWlmIChuZWVkX3JlZmlsbCkgeworCQkJCXJldCA9 IGh2c29ja19yZWN2X2RhdGEoY2hhbm5lbCwgaHZzaywKKwkJCQkJCSAgICAgICAmcGF5bG9hZF9s ZW4pOworCQkJCWlmIChyZXQgIT0gMCB8fAorCQkJCSAgICBwYXlsb2FkX2xlbiA+IEhWU09DS19S Q1ZfQlVGX1NaKSB7CisJCQkJCXJldCA9IC1FSU87CisJCQkJCWdvdG8gb3V0X3dhaXQ7CisJCQkJ fQorCisJCQkJaWYgKHBheWxvYWRfbGVuID09IDApIHsKKwkJCQkJcmV0ID0gY29waWVkOworCQkJ CQlnb3RvIG91dF93YWl0OworCQkJCX0KKworCQkJCWh2c2stPnJlY3YtPmRhdGFfbGVuID0gcGF5 bG9hZF9sZW47CisJCQkJaHZzay0+cmVjdi0+ZGF0YV9vZmZzZXQgPSAwOworCQkJfQorCisJCQl0 b19yZWFkID0gbWluX3Qoc2l6ZV90LCB0b3RhbF90b19yZWFkLAorCQkJCQlodnNrLT5yZWN2LT5k YXRhX2xlbik7CisKKwkJCXJldCA9IG1lbWNweV90b19tc2cobXNnLCBodnNrLT5yZWN2LT5idWYg KworCQkJCQkgICAgaHZzay0+cmVjdi0+ZGF0YV9vZmZzZXQsCisJCQkJCSAgICB0b19yZWFkKTsK KwkJCWlmIChyZXQgIT0gMCkKKwkJCQlicmVhazsKKworCQkJY29waWVkICs9IHRvX3JlYWQ7CisJ CQl0b3RhbF90b19yZWFkIC09IHRvX3JlYWQ7CisKKwkJCWh2c2stPnJlY3YtPmRhdGFfbGVuIC09 IHRvX3JlYWQ7CisKKwkJCWlmIChodnNrLT5yZWN2LT5kYXRhX2xlbiA9PSAwKQorCQkJCWh2c2st PnJlY3YtPmRhdGFfb2Zmc2V0ID0gMDsKKwkJCWVsc2UKKwkJCQlodnNrLT5yZWN2LT5kYXRhX29m ZnNldCArPSB0b19yZWFkOworCisJCQlpZiAodG90YWxfdG9fcmVhZCA9PSAwKQorCQkJCWJyZWFr OworCQl9IGVsc2UgeworCQkJaWYgKHNrLT5za19lcnIgfHwgKHNrLT5za19zaHV0ZG93biAmIFJD Vl9TSFVURE9XTikgfHwKKwkJCSAgICAoaHZzay0+cGVlcl9zaHV0ZG93biAmIFNFTkRfU0hVVERP V04pKQorCQkJCWJyZWFrOworCisJCQkvKiBEb24ndCB3YWl0IGZvciBub24tYmxvY2tpbmcgc29j a2V0cy4gKi8KKwkJCWlmICh0aW1lb3V0ID09IDApIHsKKwkJCQlyZXQgPSAtRUFHQUlOOworCQkJ CWJyZWFrOworCQkJfQorCisJCQlpZiAoY29waWVkID4gMCkKKwkJCQlicmVhazsKKworCQkJcmVs ZWFzZV9zb2NrKHNrKTsKKwkJCXRpbWVvdXQgPSBzY2hlZHVsZV90aW1lb3V0KHRpbWVvdXQpOwor CQkJbG9ja19zb2NrKHNrKTsKKworCQkJaWYgKHNpZ25hbF9wZW5kaW5nKGN1cnJlbnQpKSB7CisJ CQkJcmV0ID0gc29ja19pbnRyX2Vycm5vKHRpbWVvdXQpOworCQkJCWJyZWFrOworCQkJfSBlbHNl IGlmICh0aW1lb3V0ID09IDApIHsKKwkJCQlyZXQgPSAtRUFHQUlOOworCQkJCWJyZWFrOworCQkJ fQorCisJCQlwcmVwYXJlX3RvX3dhaXQoc2tfc2xlZXAoc2spLCAmd2FpdCwKKwkJCQkJVEFTS19J TlRFUlJVUFRJQkxFKTsKKwkJfQorCX0KKworCWlmIChzay0+c2tfZXJyKQorCQlyZXQgPSAtc2st PnNrX2VycjsKKwllbHNlIGlmIChzay0+c2tfc2h1dGRvd24gJiBSQ1ZfU0hVVERPV04pCisJCXJl dCA9IDA7CisKKwlpZiAoY29waWVkID4gMCkgeworCQlyZXQgPSBjb3BpZWQ7CisKKwkJLyogSWYg dGhlIG90aGVyIHNpZGUgaGFzIHNodXRkb3duIGZvciBzZW5kaW5nIGFuZCB0aGVyZQorCQkgKiBp cyBub3RoaW5nIG1vcmUgdG8gcmVhZCwgdGhlbiB3ZSBtb2RpZnkgdGhlIHNvY2tldAorCQkgKiBz dGF0ZS4KKwkJICovCisJCWlmICgoaHZzay0+cGVlcl9zaHV0ZG93biAmIFNFTkRfU0hVVERPV04p ICYmCisJCSAgICBodnNrLT5yZWN2LT5kYXRhX2xlbiA9PSAwKSB7CisJCQlnZXRfcmluZ2J1ZmZl cl9yd19zdGF0dXMoY2hhbm5lbCwgJmNhbl9yZWFkLCBOVUxMKTsKKwkJCWlmICghY2FuX3JlYWQp IHsKKwkJCQlzay0+c2tfc3RhdGUgPSBTU19VTkNPTk5FQ1RFRDsKKwkJCQlzb2NrX3NldF9mbGFn KHNrLCBTT0NLX0RPTkUpOworCQkJCXNrLT5za19zdGF0ZV9jaGFuZ2Uoc2spOworCQkJfQorCQl9 CisJfQorb3V0X3dhaXQ6CisJZmluaXNoX3dhaXQoc2tfc2xlZXAoc2spLCAmd2FpdCk7CisJcmV0 dXJuIHJldDsKK30KKworc3RhdGljIGludCBodnNvY2tfcmVjdm1zZyhzdHJ1Y3Qgc29ja2V0ICpz b2NrLCBzdHJ1Y3QgbXNnaGRyICptc2csCisJCQkgIHNpemVfdCBsZW4sIGludCBmbGFncykKK3sK KwlzdHJ1Y3Qgc29jayAqc2sgPSBzb2NrLT5zazsKKwlpbnQgcmV0OworCisJbG9ja19zb2NrKHNr KTsKKworCWlmIChzay0+c2tfc3RhdGUgIT0gU1NfQ09OTkVDVEVEKSB7CisJCS8qIFJlY3Ztc2cg aXMgc3VwcG9zZWQgdG8gcmV0dXJuIDAgaWYgYSBwZWVyIHBlcmZvcm1zIGFuCisJCSAqIG9yZGVy bHkgc2h1dGRvd24uIERpZmZlcmVudGlhdGUgYmV0d2VlbiB0aGF0IGNhc2UgYW5kIHdoZW4gYQor CQkgKiBwZWVyIGhhcyBub3QgY29ubmVjdGVkIG9yIGEgbG9jYWwgc2h1dGRvd24gb2NjdXJyZWQg d2l0aCB0aGUKKwkJICogU09DS19ET05FIGZsYWcuCisJCSAqLworCQlpZiAoc29ja19mbGFnKHNr LCBTT0NLX0RPTkUpKQorCQkJcmV0ID0gMDsKKwkJZWxzZQorCQkJcmV0ID0gLUVOT1RDT05OOwor CisJCWdvdG8gb3V0OworCX0KKworCS8qIFdlIGlnbm9yZSBtc2ctPmFkZHJfbmFtZS9sZW4uICov CisJaWYgKGZsYWdzICYgfk1TR19ET05UV0FJVCkgeworCQlwcl9lcnIoIiVzOiB1bnN1cHBvcnRl ZCBmbGFncz0weCV4XG4iLCBfX2Z1bmNfXywgZmxhZ3MpOworCQlyZXQgPSAtRU9QTk9UU1VQUDsK KwkJZ290byBvdXQ7CisJfQorCisJLyogV2UgZG9uJ3QgY2hlY2sgcGVlcl9zaHV0ZG93biBmbGFn IGhlcmUgc2luY2UgcGVlciBtYXkgYWN0dWFsbHkgc2h1dAorCSAqIGRvd24sIGJ1dCB0aGVyZSBj YW4gYmUgZGF0YSBpbiB0aGUgcXVldWUgdGhhdCBhIGxvY2FsIHNvY2tldCBjYW4KKwkgKiByZWNl aXZlLgorCSAqLworCWlmIChzay0+c2tfc2h1dGRvd24gJiBSQ1ZfU0hVVERPV04pIHsKKwkJcmV0 ID0gMDsKKwkJZ290byBvdXQ7CisJfQorCisJLyogSXQgaXMgdmFsaWQgb24gTGludXggdG8gcGFz cyBpbiBhIHplcm8tbGVuZ3RoIHJlY2VpdmUgYnVmZmVyLiAgVGhpcworCSAqIGlzIG5vdCBhbiBl cnJvci4gIFdlIG1heSBhcyB3ZWxsIGJhaWwgb3V0IG5vdy4KKwkgKi8KKwlpZiAoIWxlbikgewor CQlyZXQgPSAwOworCQlnb3RvIG91dDsKKwl9CisKKwlyZXQgPSBodnNvY2tfcmVjdm1zZ193YWl0 KHNrLCBtc2csIGxlbiwgZmxhZ3MpOworb3V0OgorCXJlbGVhc2Vfc29jayhzayk7CisJcmV0dXJu IHJldDsKK30KKworc3RhdGljIGNvbnN0IHN0cnVjdCBwcm90b19vcHMgaHZzb2NrX29wcyA9IHsK KwkuZmFtaWx5ID0gUEZfSFlQRVJWLAorCS5vd25lciA9IFRISVNfTU9EVUxFLAorCS5yZWxlYXNl ID0gaHZzb2NrX3JlbGVhc2UsCisJLmJpbmQgPSBodnNvY2tfYmluZCwKKwkuY29ubmVjdCA9IGh2 c29ja19jb25uZWN0LAorCS5zb2NrZXRwYWlyID0gc29ja19ub19zb2NrZXRwYWlyLAorCS5hY2Nl cHQgPSBodnNvY2tfYWNjZXB0LAorCS5nZXRuYW1lID0gaHZzb2NrX2dldG5hbWUsCisJLnBvbGwg PSBodnNvY2tfcG9sbCwKKwkuaW9jdGwgPSBzb2NrX25vX2lvY3RsLAorCS5saXN0ZW4gPSBodnNv Y2tfbGlzdGVuLAorCS5zaHV0ZG93biA9IGh2c29ja19zaHV0ZG93biwKKwkuc2V0c29ja29wdCA9 IHNvY2tfbm9fc2V0c29ja29wdCwKKwkuZ2V0c29ja29wdCA9IHNvY2tfbm9fZ2V0c29ja29wdCwK Kwkuc2VuZG1zZyA9IGh2c29ja19zZW5kbXNnLAorCS5yZWN2bXNnID0gaHZzb2NrX3JlY3Ztc2cs CisJLm1tYXAgPSBzb2NrX25vX21tYXAsCisJLnNlbmRwYWdlID0gc29ja19ub19zZW5kcGFnZSwK K307CisKK3N0YXRpYyBpbnQgaHZzb2NrX2NyZWF0ZV9zb2NrKHN0cnVjdCBuZXQgKm5ldCwgc3Ry dWN0IHNvY2tldCAqc29jaywKKwkJCSAgICAgIGludCBwcm90b2NvbCwgaW50IGtlcm4pCit7CisJ c3RydWN0IHNvY2sgKnNrOworCisJaWYgKCFjYXBhYmxlKENBUF9TWVNfQURNSU4pICYmICFjYXBh YmxlKENBUF9ORVRfQURNSU4pKQorCQlyZXR1cm4gLUVQRVJNOworCisJaWYgKHByb3RvY29sICE9 IDAgJiYgcHJvdG9jb2wgIT0gU0hWX1BST1RPX1JBVykKKwkJcmV0dXJuIC1FUFJPVE9OT1NVUFBP UlQ7CisKKwlzd2l0Y2ggKHNvY2stPnR5cGUpIHsKKwljYXNlIFNPQ0tfU1RSRUFNOgorCQlzb2Nr LT5vcHMgPSAmaHZzb2NrX29wczsKKwkJYnJlYWs7CisJZGVmYXVsdDoKKwkJcmV0dXJuIC1FU09D S1ROT1NVUFBPUlQ7CisJfQorCisJc29jay0+c3RhdGUgPSBTU19VTkNPTk5FQ1RFRDsKKworCXJl dHVybiBodnNvY2tfY3JlYXRlKG5ldCwgc29jaywgR0ZQX0tFUk5FTCwgMCwgJnNrKTsKK30KKwor c3RhdGljIGNvbnN0IHN0cnVjdCBuZXRfcHJvdG9fZmFtaWx5IGh2c29ja19mYW1pbHlfb3BzID0g eworCS5mYW1pbHkgPSBBRl9IWVBFUlYsCisJLmNyZWF0ZSA9IGh2c29ja19jcmVhdGVfc29jaywK Kwkub3duZXIgPSBUSElTX01PRFVMRSwKK307CisKK3N0YXRpYyBpbnQgaHZzb2NrX3Byb2JlKHN0 cnVjdCBodl9kZXZpY2UgKmhkZXYsCisJCQljb25zdCBzdHJ1Y3QgaHZfdm1idXNfZGV2aWNlX2lk ICpkZXZfaWQpCit7CisJc3RydWN0IHZtYnVzX2NoYW5uZWwgKmNoYW5uZWwgPSBoZGV2LT5jaGFu bmVsOworCisJLyogV2UgaWdub3JlIHRoZSBlcnJvciByZXR1cm4gY29kZSB0byBzdXBwcmVzcyB0 aGUgdW5uZWNlc3NhcnkKKwkgKiBlcnJvciBtZXNzYWdlIGluIHZtYnVzX3Byb2JlKCk6IG9uIGVy cm9yIHRoZSBob3N0IHdpbGwgcmVzY2luZAorCSAqIHRoZSBvZmZlciBpbiAzMCBzZWNvbmRzIGFu ZCB3ZSBjYW4gZG8gY2xlYW51cCBhdCB0aGF0IHRpbWUuCisJICovCisJKHZvaWQpaHZzb2NrX29w ZW5fY29ubmVjdGlvbihjaGFubmVsKTsKKworCXJldHVybiAwOworfQorCitzdGF0aWMgaW50IGh2 c29ja19yZW1vdmUoc3RydWN0IGh2X2RldmljZSAqaGRldikKK3sKKwlzdHJ1Y3Qgdm1idXNfY2hh bm5lbCAqY2hhbm5lbCA9IGhkZXYtPmNoYW5uZWw7CisKKwl2bWJ1c19jbG9zZShjaGFubmVsKTsK KworCXJldHVybiAwOworfQorCisvKiBJdCdzIG5vdCByZWFsbHkgdXNlZC4gU2VlIHZtYnVzX21h dGNoKCkgYW5kIHZtYnVzX3Byb2JlKCkuICovCitzdGF0aWMgY29uc3Qgc3RydWN0IGh2X3ZtYnVz X2RldmljZV9pZCBpZF90YWJsZVtdID0geworCXt9LAorfTsKKworc3RhdGljIHN0cnVjdCBodl9k cml2ZXIgaHZzb2NrX2RydiA9IHsKKwkubmFtZQkJPSAiaHZfc29jayIsCisJLmh2c29jawkJPSB0 cnVlLAorCS5pZF90YWJsZQk9IGlkX3RhYmxlLAorCS5wcm9iZQkJPSBodnNvY2tfcHJvYmUsCisJ LnJlbW92ZQkJPSBodnNvY2tfcmVtb3ZlLAorfTsKKworc3RhdGljIGludCBfX2luaXQgaHZzb2Nr X2luaXQodm9pZCkKK3sKKwlpbnQgcmV0OworCisJaWYgKHNlbmRfcmluZ19wYWdlIDwgREVGX1JJ TkdCVUZGRVJfUEFHRVNfSFZTT0NLX1NORCkKKwkJc2VuZF9yaW5nX3BhZ2UgPSBERUZfUklOR0JV RkZFUl9QQUdFU19IVlNPQ0tfU05EOworCisJaWYgKHJlY3ZfcmluZ19wYWdlIDwgREVGX1JJTkdC VUZGRVJfUEFHRVNfSFZTT0NLX1JDVikKKwkJcmVjdl9yaW5nX3BhZ2UgPSBERUZfUklOR0JVRkZF Ul9QQUdFU19IVlNPQ0tfUkNWOworCisJLyogSHlwZXItViBTb2NrZXRzIHJlcXVpcmVzIGF0IGxl YXN0IFZNQnVzIDQuMCAqLworCWlmICgodm1idXNfcHJvdG9fdmVyc2lvbiA+PiAxNikgPCA0KSB7 CisJCXByX2VycigiZmFpbGVkIHRvIGxvYWQ6IFZNQnVzIDQgb3IgbGF0ZXIgaXMgcmVxdWlyZWRc biIpOworCQlyZXR1cm4gLUVOT0RFVjsKKwl9CisKKwlyZXQgPSB2bWJ1c19kcml2ZXJfcmVnaXN0 ZXIoJmh2c29ja19kcnYpOworCWlmIChyZXQpIHsKKwkJcHJfZXJyKCJmYWlsZWQgdG8gcmVnaXN0 ZXIgaHZfc29jayBkcml2ZXJcbiIpOworCQlyZXR1cm4gcmV0OworCX0KKworCXJldCA9IHByb3Rv X3JlZ2lzdGVyKCZodnNvY2tfcHJvdG8sIDApOworCWlmIChyZXQpIHsKKwkJcHJfZXJyKCJmYWls ZWQgdG8gcmVnaXN0ZXIgcHJvdG9jb2xcbiIpOworCQlnb3RvIHVucmVnX2h2c29ja19kcnY7CisJ fQorCisJcmV0ID0gc29ja19yZWdpc3RlcigmaHZzb2NrX2ZhbWlseV9vcHMpOworCWlmIChyZXQp IHsKKwkJcHJfZXJyKCJmYWlsZWQgdG8gcmVnaXN0ZXIgYWRkcmVzcyBmYW1pbHlcbiIpOworCQln b3RvIHVucmVnX3Byb3RvOworCX0KKworCXJldHVybiAwOworCit1bnJlZ19wcm90bzoKKwlwcm90 b191bnJlZ2lzdGVyKCZodnNvY2tfcHJvdG8pOwordW5yZWdfaHZzb2NrX2RydjoKKwl2bWJ1c19k cml2ZXJfdW5yZWdpc3RlcigmaHZzb2NrX2Rydik7CisJcmV0dXJuIHJldDsKK30KKworc3RhdGlj IHZvaWQgX19leGl0IGh2c29ja19leGl0KHZvaWQpCit7CisJc29ja191bnJlZ2lzdGVyKEFGX0hZ UEVSVik7CisJcHJvdG9fdW5yZWdpc3RlcigmaHZzb2NrX3Byb3RvKTsKKwl2bWJ1c19kcml2ZXJf dW5yZWdpc3RlcigmaHZzb2NrX2Rydik7Cit9CisKK21vZHVsZV9pbml0KGh2c29ja19pbml0KTsK K21vZHVsZV9leGl0KGh2c29ja19leGl0KTsKKworTU9EVUxFX0RFU0NSSVBUSU9OKCJIeXBlci1W IFNvY2tldHMiKTsKK01PRFVMRV9MSUNFTlNFKCJEdWFsIEJTRC9HUEwiKTsKLS0gCjIuNy40CgoK X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KZGV2ZWwgbWFp bGluZyBsaXN0CmRldmVsQGxpbnV4ZHJpdmVycHJvamVjdC5vcmcKaHR0cDovL2RyaXZlcmRldi5s aW51eGRyaXZlcnByb2plY3Qub3JnL21haWxtYW4vbGlzdGluZm8vZHJpdmVyZGV2LWRldmVsCg==