From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-17.5 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER,INCLUDES_PATCH,MAILING_LIST_MULTI,NICE_REPLY_A, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 289F3C433E0 for ; Thu, 28 Jan 2021 04:29:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 90B3764DD9 for ; Thu, 28 Jan 2021 04:29:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231124AbhA1E3L (ORCPT ); Wed, 27 Jan 2021 23:29:11 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:20437 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229528AbhA1E3G (ORCPT ); Wed, 27 Jan 2021 23:29:06 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1611808054; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vUxRrabFkJIbvDaiO8CDnSK+Dd50UKrEOmGMcEjNtrU=; b=J3rYtVuQoiD7NzHNonECJPmRLcT5KSCR4A9GzwA7nlI4Zb2RUvAThwH0TdaBOXGYboaAZM arApxwKVogDDOhOIeGk9so35dEcZJE+0PDHyU663nt3LQQIyzlwqa0/HXRynVVu6CRflCR lAYKAXgm3ixhWgHzck/xPkC8VMYEpw0= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-391-2BOwtVvrO5iC0mHi8O9-DQ-1; Wed, 27 Jan 2021 23:27:30 -0500 X-MC-Unique: 2BOwtVvrO5iC0mHi8O9-DQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 8E37D107ACE4; Thu, 28 Jan 2021 04:27:27 +0000 (UTC) Received: from [10.72.12.167] (ovpn-12-167.pek2.redhat.com [10.72.12.167]) by smtp.corp.redhat.com (Postfix) with ESMTP id A34A71002382; Thu, 28 Jan 2021 04:27:15 +0000 (UTC) Subject: Re: [RFC v3 08/11] vduse: Introduce VDUSE - vDPA Device in Userspace To: Yongji Xie Cc: "Michael S. Tsirkin" , Stefan Hajnoczi , sgarzare@redhat.com, Parav Pandit , Bob Liu , Christoph Hellwig , Randy Dunlap , Matthew Wilcox , viro@zeniv.linux.org.uk, axboe@kernel.dk, bcrl@kvack.org, Jonathan Corbet , virtualization@lists.linux-foundation.org, netdev@vger.kernel.org, kvm@vger.kernel.org, linux-aio@kvack.org, linux-fsdevel@vger.kernel.org References: <20210119045920.447-1-xieyongji@bytedance.com> <20210119050756.600-1-xieyongji@bytedance.com> <20210119050756.600-2-xieyongji@bytedance.com> <1bb3af07-0ec2-109c-d6d1-83d4d1f410c3@redhat.com> From: Jason Wang Message-ID: Date: Thu, 28 Jan 2021 12:27:14 +0800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org On 2021/1/27 下午4:50, Yongji Xie wrote: > On Tue, Jan 26, 2021 at 4:09 PM Jason Wang wrote: >> >> On 2021/1/19 下午1:07, Xie Yongji wrote: >>> This VDUSE driver enables implementing vDPA devices in userspace. >>> Both control path and data path of vDPA devices will be able to >>> be handled in userspace. >>> >>> In the control path, the VDUSE driver will make use of message >>> mechnism to forward the config operation from vdpa bus driver >>> to userspace. Userspace can use read()/write() to receive/reply >>> those control messages. >>> >>> In the data path, VDUSE_IOTLB_GET_FD ioctl will be used to get >>> the file descriptors referring to vDPA device's iova regions. Then >>> userspace can use mmap() to access those iova regions. Besides, >>> the eventfd mechanism is used to trigger interrupt callbacks and >>> receive virtqueue kicks in userspace. >>> >>> Signed-off-by: Xie Yongji >>> --- >>> Documentation/driver-api/vduse.rst | 85 ++ >>> Documentation/userspace-api/ioctl/ioctl-number.rst | 1 + >>> drivers/vdpa/Kconfig | 7 + >>> drivers/vdpa/Makefile | 1 + >>> drivers/vdpa/vdpa_user/Makefile | 5 + >>> drivers/vdpa/vdpa_user/eventfd.c | 221 ++++ >>> drivers/vdpa/vdpa_user/eventfd.h | 48 + >>> drivers/vdpa/vdpa_user/iova_domain.c | 426 +++++++ >>> drivers/vdpa/vdpa_user/iova_domain.h | 68 ++ >>> drivers/vdpa/vdpa_user/vduse.h | 62 + >>> drivers/vdpa/vdpa_user/vduse_dev.c | 1217 ++++++++++++++++++++ >>> include/uapi/linux/vdpa.h | 1 + >>> include/uapi/linux/vduse.h | 125 ++ >>> 13 files changed, 2267 insertions(+) >>> create mode 100644 Documentation/driver-api/vduse.rst >>> create mode 100644 drivers/vdpa/vdpa_user/Makefile >>> create mode 100644 drivers/vdpa/vdpa_user/eventfd.c >>> create mode 100644 drivers/vdpa/vdpa_user/eventfd.h >>> create mode 100644 drivers/vdpa/vdpa_user/iova_domain.c >>> create mode 100644 drivers/vdpa/vdpa_user/iova_domain.h >>> create mode 100644 drivers/vdpa/vdpa_user/vduse.h >>> create mode 100644 drivers/vdpa/vdpa_user/vduse_dev.c >>> create mode 100644 include/uapi/linux/vduse.h >>> >>> diff --git a/Documentation/driver-api/vduse.rst b/Documentation/driver-api/vduse.rst >>> new file mode 100644 >>> index 000000000000..9418a7f6646b >>> --- /dev/null >>> +++ b/Documentation/driver-api/vduse.rst >>> @@ -0,0 +1,85 @@ >>> +================================== >>> +VDUSE - "vDPA Device in Userspace" >>> +================================== >>> + >>> +vDPA (virtio data path acceleration) device is a device that uses a >>> +datapath which complies with the virtio specifications with vendor >>> +specific control path. vDPA devices can be both physically located on >>> +the hardware or emulated by software. VDUSE is a framework that makes it >>> +possible to implement software-emulated vDPA devices in userspace. >>> + >>> +How VDUSE works >>> +------------ >>> +Each userspace vDPA device is created by the VDUSE_CREATE_DEV ioctl on >>> +the VDUSE character device (/dev/vduse). Then a file descriptor pointing >>> +to the new resources will be returned, which can be used to implement the >>> +userspace vDPA device's control path and data path. >>> + >>> +To implement control path, the read/write operations to the file descriptor >>> +will be used to receive/reply the control messages from/to VDUSE driver. >> >> It's better to document the protocol here. E.g the identifier stuffs. >> > I have documented those stuffs in include/uapi/linux/vduse.h, is it > OK? Or add something like "Please see include/uapi/linux/vduse.h for > details." It might be better if we add some userspace sample code to demonstrate how the protocol work. > >>> +Those control messages are mostly based on the vdpa_config_ops which defines >>> +a unified interface to control different types of vDPA device. >>> + >>> +The following types of messages are provided by the VDUSE framework now: >>> + >>> +- VDUSE_SET_VQ_ADDR: Set the addresses of the different aspects of virtqueue. >> >> "Set the vring address of a virtqueue" might be better here. >> > OK. > >>> + >>> +- VDUSE_SET_VQ_NUM: Set the size of virtqueue >>> + >>> +- VDUSE_SET_VQ_READY: Set ready status of virtqueue >>> + >>> +- VDUSE_GET_VQ_READY: Get ready status of virtqueue >>> + >>> +- VDUSE_SET_VQ_STATE: Set the state (last_avail_idx) for virtqueue >>> + >>> +- VDUSE_GET_VQ_STATE: Get the state (last_avail_idx) for virtqueue >> >> It's better not to mention layout specific stuffs here (last_avail_idx). >> Consider we should support packed virtqueue in the future. >> > I see. > >>> + >>> +- VDUSE_SET_FEATURES: Set virtio features supported by the driver >>> + >>> +- VDUSE_GET_FEATURES: Get virtio features supported by the device >>> + >>> +- VDUSE_SET_STATUS: Set the device status >>> + >>> +- VDUSE_GET_STATUS: Get the device status >>> + >>> +- VDUSE_SET_CONFIG: Write to device specific configuration space >>> + >>> +- VDUSE_GET_CONFIG: Read from device specific configuration space >>> + >>> +- VDUSE_UPDATE_IOTLB: Notify userspace to update the memory mapping in device IOTLB >>> + >>> +Please see include/linux/vdpa.h for details. >>> + >>> +In the data path, vDPA device's iova regions will be mapped into userspace with >>> +the help of VDUSE_IOTLB_GET_FD ioctl on the userspace vDPA device fd: >>> + >>> +- VDUSE_IOTLB_GET_FD: get the file descriptor to iova region. Userspace can >>> + access this iova region by passing the fd to mmap(2). >>> + >>> +Besides, the eventfd mechanism is used to trigger interrupt callbacks and >>> +receive virtqueue kicks in userspace. The following ioctls on the userspace >>> +vDPA device fd are provided to support that: >>> + >>> +- VDUSE_VQ_SETUP_KICKFD: set the kickfd for virtqueue, this eventfd is used >>> + by VDUSE driver to notify userspace to consume the vring. >>> + >>> +- VDUSE_VQ_SETUP_IRQFD: set the irqfd for virtqueue, this eventfd is used >>> + by userspace to notify VDUSE driver to trigger interrupt callbacks. >>> + >>> +MMU-based IOMMU Driver >>> +---------------------- >>> +In virtio-vdpa case, VDUSE framework implements a MMU-based on-chip IOMMU >>> +driver to support mapping the kernel dma buffer into the userspace iova >>> +region dynamically. >>> + >>> +The basic idea behind this driver is treating MMU (VA->PA) as IOMMU (IOVA->PA). >>> +The driver will set up MMU mapping instead of IOMMU mapping for the DMA transfer >>> +so that the userspace process is able to use its virtual address to access >>> +the dma buffer in kernel. >>> + >>> +And to avoid security issue, a bounce-buffering mechanism is introduced to >>> +prevent userspace accessing the original buffer directly which may contain other >>> +kernel data. During the mapping, unmapping, the driver will copy the data from >>> +the original buffer to the bounce buffer and back, depending on the direction of >>> +the transfer. And the bounce-buffer addresses will be mapped into the user address >>> +space instead of the original one. >>> diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst >>> index a4c75a28c839..71722e6f8f23 100644 >>> --- a/Documentation/userspace-api/ioctl/ioctl-number.rst >>> +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst >>> @@ -300,6 +300,7 @@ Code Seq# Include File Comments >>> 'z' 10-4F drivers/s390/crypto/zcrypt_api.h conflict! >>> '|' 00-7F linux/media.h >>> 0x80 00-1F linux/fb.h >>> +0x81 00-1F linux/vduse.h >>> 0x89 00-06 arch/x86/include/asm/sockios.h >>> 0x89 0B-DF linux/sockios.h >>> 0x89 E0-EF linux/sockios.h SIOCPROTOPRIVATE range >>> diff --git a/drivers/vdpa/Kconfig b/drivers/vdpa/Kconfig >>> index 4be7be39be26..667354309bf4 100644 >>> --- a/drivers/vdpa/Kconfig >>> +++ b/drivers/vdpa/Kconfig >>> @@ -21,6 +21,13 @@ config VDPA_SIM >>> to RX. This device is used for testing, prototyping and >>> development of vDPA. >>> >>> +config VDPA_USER >>> + tristate "VDUSE (vDPA Device in Userspace) support" >>> + depends on EVENTFD && MMU && HAS_DMA >> >> Need select VHOST_IOTLB. >> > OK. > >>> + help >>> + With VDUSE it is possible to emulate a vDPA Device >>> + in a userspace program. >>> + >>> config IFCVF >>> tristate "Intel IFC VF vDPA driver" >>> depends on PCI_MSI >>> diff --git a/drivers/vdpa/Makefile b/drivers/vdpa/Makefile >>> index d160e9b63a66..66e97778ad03 100644 >>> --- a/drivers/vdpa/Makefile >>> +++ b/drivers/vdpa/Makefile >>> @@ -1,5 +1,6 @@ >>> # SPDX-License-Identifier: GPL-2.0 >>> obj-$(CONFIG_VDPA) += vdpa.o >>> obj-$(CONFIG_VDPA_SIM) += vdpa_sim/ >>> +obj-$(CONFIG_VDPA_USER) += vdpa_user/ >>> obj-$(CONFIG_IFCVF) += ifcvf/ >>> obj-$(CONFIG_MLX5_VDPA) += mlx5/ >>> diff --git a/drivers/vdpa/vdpa_user/Makefile b/drivers/vdpa/vdpa_user/Makefile >>> new file mode 100644 >>> index 000000000000..b7645e36992b >>> --- /dev/null >>> +++ b/drivers/vdpa/vdpa_user/Makefile >>> @@ -0,0 +1,5 @@ >>> +# SPDX-License-Identifier: GPL-2.0 >>> + >>> +vduse-y := vduse_dev.o iova_domain.o eventfd.o >>> + >>> +obj-$(CONFIG_VDPA_USER) += vduse.o >>> diff --git a/drivers/vdpa/vdpa_user/eventfd.c b/drivers/vdpa/vdpa_user/eventfd.c >>> new file mode 100644 >>> index 000000000000..dbffddb08908 >>> --- /dev/null >>> +++ b/drivers/vdpa/vdpa_user/eventfd.c >>> @@ -0,0 +1,221 @@ >>> +// SPDX-License-Identifier: GPL-2.0-only >>> +/* >>> + * Eventfd support for VDUSE >>> + * >>> + * Copyright (C) 2020 Bytedance Inc. and/or its affiliates. All rights reserved. >>> + * >>> + * Author: Xie Yongji >>> + * >>> + */ >>> + >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#include "eventfd.h" >>> + >>> +static struct workqueue_struct *vduse_irqfd_cleanup_wq; >>> + >>> +static void vduse_virqfd_shutdown(struct work_struct *work) >>> +{ >>> + u64 cnt; >>> + struct vduse_virqfd *virqfd = container_of(work, >>> + struct vduse_virqfd, shutdown); >>> + >>> + eventfd_ctx_remove_wait_queue(virqfd->ctx, &virqfd->wait, &cnt); >>> + flush_work(&virqfd->inject); >>> + eventfd_ctx_put(virqfd->ctx); >>> + kfree(virqfd); >>> +} >>> + >>> +static void vduse_virqfd_inject(struct work_struct *work) >>> +{ >>> + struct vduse_virqfd *virqfd = container_of(work, >>> + struct vduse_virqfd, inject); >>> + struct vduse_virtqueue *vq = virqfd->vq; >>> + >>> + spin_lock_irq(&vq->irq_lock); >>> + if (vq->ready && vq->cb) >>> + vq->cb(vq->private); >>> + spin_unlock_irq(&vq->irq_lock); >>> +} >>> + >>> +static void virqfd_deactivate(struct vduse_virqfd *virqfd) >>> +{ >>> + queue_work(vduse_irqfd_cleanup_wq, &virqfd->shutdown); >>> +} >>> + >>> +static int vduse_virqfd_wakeup(wait_queue_entry_t *wait, unsigned int mode, >>> + int sync, void *key) >>> +{ >>> + struct vduse_virqfd *virqfd = container_of(wait, struct vduse_virqfd, wait); >>> + struct vduse_virtqueue *vq = virqfd->vq; >>> + >>> + __poll_t flags = key_to_poll(key); >>> + >>> + if (flags & EPOLLIN) >>> + schedule_work(&virqfd->inject); >>> + >>> + if (flags & EPOLLHUP) { >>> + spin_lock(&vq->irq_lock); >>> + if (vq->virqfd == virqfd) { >>> + vq->virqfd = NULL; >>> + virqfd_deactivate(virqfd); >>> + } >>> + spin_unlock(&vq->irq_lock); >>> + } >>> + >>> + return 0; >>> +} >>> + >>> +static void vduse_virqfd_ptable_queue_proc(struct file *file, >>> + wait_queue_head_t *wqh, poll_table *pt) >>> +{ >>> + struct vduse_virqfd *virqfd = container_of(pt, struct vduse_virqfd, pt); >>> + >>> + add_wait_queue(wqh, &virqfd->wait); >>> +} >>> + >>> +int vduse_virqfd_setup(struct vduse_dev *dev, >>> + struct vduse_vq_eventfd *eventfd) >>> +{ >>> + struct vduse_virqfd *virqfd; >>> + struct fd irqfd; >>> + struct eventfd_ctx *ctx; >>> + struct vduse_virtqueue *vq; >>> + __poll_t events; >>> + int ret; >>> + >>> + if (eventfd->index >= dev->vq_num) >>> + return -EINVAL; >>> + >>> + vq = &dev->vqs[eventfd->index]; >>> + virqfd = kzalloc(sizeof(*virqfd), GFP_KERNEL); >>> + if (!virqfd) >>> + return -ENOMEM; >>> + >>> + INIT_WORK(&virqfd->shutdown, vduse_virqfd_shutdown); >>> + INIT_WORK(&virqfd->inject, vduse_virqfd_inject); >>> + >>> + ret = -EBADF; >>> + irqfd = fdget(eventfd->fd); >>> + if (!irqfd.file) >>> + goto err_fd; >>> + >>> + ctx = eventfd_ctx_fileget(irqfd.file); >>> + if (IS_ERR(ctx)) { >>> + ret = PTR_ERR(ctx); >>> + goto err_ctx; >>> + } >>> + >>> + virqfd->vq = vq; >>> + virqfd->ctx = ctx; >>> + spin_lock(&vq->irq_lock); >>> + if (vq->virqfd) >>> + virqfd_deactivate(virqfd); >>> + vq->virqfd = virqfd; >>> + spin_unlock(&vq->irq_lock); >>> + >>> + init_waitqueue_func_entry(&virqfd->wait, vduse_virqfd_wakeup); >>> + init_poll_funcptr(&virqfd->pt, vduse_virqfd_ptable_queue_proc); >>> + >>> + events = vfs_poll(irqfd.file, &virqfd->pt); >>> + >>> + /* >>> + * Check if there was an event already pending on the eventfd >>> + * before we registered and trigger it as if we didn't miss it. >>> + */ >>> + if (events & EPOLLIN) >>> + schedule_work(&virqfd->inject); >>> + >>> + fdput(irqfd); >>> + >>> + return 0; >>> +err_ctx: >>> + fdput(irqfd); >>> +err_fd: >>> + kfree(virqfd); >>> + return ret; >>> +} >>> + >>> +void vduse_virqfd_release(struct vduse_dev *dev) >>> +{ >>> + int i; >>> + >>> + for (i = 0; i < dev->vq_num; i++) { >>> + struct vduse_virtqueue *vq = &dev->vqs[i]; >>> + >>> + spin_lock(&vq->irq_lock); >>> + if (vq->virqfd) { >>> + virqfd_deactivate(vq->virqfd); >>> + vq->virqfd = NULL; >>> + } >>> + spin_unlock(&vq->irq_lock); >>> + } >>> + flush_workqueue(vduse_irqfd_cleanup_wq); >>> +} >>> + >>> +int vduse_virqfd_init(void) >>> +{ >>> + vduse_irqfd_cleanup_wq = alloc_workqueue("vduse-irqfd-cleanup", >>> + WQ_UNBOUND, 0); >>> + if (!vduse_irqfd_cleanup_wq) >>> + return -ENOMEM; >>> + >>> + return 0; >>> +} >>> + >>> +void vduse_virqfd_exit(void) >>> +{ >>> + destroy_workqueue(vduse_irqfd_cleanup_wq); >>> +} >>> + >>> +void vduse_vq_kick(struct vduse_virtqueue *vq) >>> +{ >>> + spin_lock(&vq->kick_lock); >>> + if (vq->ready && vq->kickfd) >>> + eventfd_signal(vq->kickfd, 1); >>> + spin_unlock(&vq->kick_lock); >>> +} >>> + >>> +int vduse_kickfd_setup(struct vduse_dev *dev, >>> + struct vduse_vq_eventfd *eventfd) >>> +{ >>> + struct eventfd_ctx *ctx; >>> + struct vduse_virtqueue *vq; >>> + >>> + if (eventfd->index >= dev->vq_num) >>> + return -EINVAL; >>> + >>> + vq = &dev->vqs[eventfd->index]; >>> + ctx = eventfd_ctx_fdget(eventfd->fd); >>> + if (IS_ERR(ctx)) >>> + return PTR_ERR(ctx); >>> + >>> + spin_lock(&vq->kick_lock); >>> + if (vq->kickfd) >>> + eventfd_ctx_put(vq->kickfd); >>> + vq->kickfd = ctx; >>> + spin_unlock(&vq->kick_lock); >>> + >>> + return 0; >>> +} >>> + >>> +void vduse_kickfd_release(struct vduse_dev *dev) >>> +{ >>> + int i; >>> + >>> + for (i = 0; i < dev->vq_num; i++) { >>> + struct vduse_virtqueue *vq = &dev->vqs[i]; >>> + >>> + spin_lock(&vq->kick_lock); >>> + if (vq->kickfd) { >>> + eventfd_ctx_put(vq->kickfd); >>> + vq->kickfd = NULL; >>> + } >>> + spin_unlock(&vq->kick_lock); >>> + } >>> +} >>> diff --git a/drivers/vdpa/vdpa_user/eventfd.h b/drivers/vdpa/vdpa_user/eventfd.h >>> new file mode 100644 >>> index 000000000000..14269ff27f47 >>> --- /dev/null >>> +++ b/drivers/vdpa/vdpa_user/eventfd.h >>> @@ -0,0 +1,48 @@ >>> +/* SPDX-License-Identifier: GPL-2.0-only */ >>> +/* >>> + * Eventfd support for VDUSE >>> + * >>> + * Copyright (C) 2020 Bytedance Inc. and/or its affiliates. All rights reserved. >>> + * >>> + * Author: Xie Yongji >>> + * >>> + */ >>> + >>> +#ifndef _VDUSE_EVENTFD_H >>> +#define _VDUSE_EVENTFD_H >>> + >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#include "vduse.h" >>> + >>> +struct vduse_dev; >>> + >>> +struct vduse_virqfd { >>> + struct eventfd_ctx *ctx; >>> + struct vduse_virtqueue *vq; >>> + struct work_struct inject; >>> + struct work_struct shutdown; >>> + wait_queue_entry_t wait; >>> + poll_table pt; >>> +}; >>> + >>> +int vduse_virqfd_setup(struct vduse_dev *dev, >>> + struct vduse_vq_eventfd *eventfd); >>> + >>> +void vduse_virqfd_release(struct vduse_dev *dev); >>> + >>> +int vduse_virqfd_init(void); >>> + >>> +void vduse_virqfd_exit(void); >>> + >>> +void vduse_vq_kick(struct vduse_virtqueue *vq); >>> + >>> +int vduse_kickfd_setup(struct vduse_dev *dev, >>> + struct vduse_vq_eventfd *eventfd); >>> + >>> +void vduse_kickfd_release(struct vduse_dev *dev); >>> + >>> +#endif /* _VDUSE_EVENTFD_H */ >>> diff --git a/drivers/vdpa/vdpa_user/iova_domain.c b/drivers/vdpa/vdpa_user/iova_domain.c >>> new file mode 100644 >>> index 000000000000..cdfef8e9f9d6 >>> --- /dev/null >>> +++ b/drivers/vdpa/vdpa_user/iova_domain.c >>> @@ -0,0 +1,426 @@ >>> +// SPDX-License-Identifier: GPL-2.0-only >>> +/* >>> + * MMU-based IOMMU implementation >>> + * >>> + * Copyright (C) 2020 Bytedance Inc. and/or its affiliates. All rights reserved. >>> + * >>> + * Author: Xie Yongji >>> + * >>> + */ >>> + >>> +#include >>> +#include >>> +#include >>> + >>> +#include "iova_domain.h" >>> + >>> +#define IOVA_START_PFN 1 >>> +#define IOVA_ALLOC_ORDER 12 >>> +#define IOVA_ALLOC_SIZE (1 << IOVA_ALLOC_ORDER) >> >> Can this work for all archs (e.g why not use PAGE_SIZE)? >> > It can work for all archs. Use IOVA_ALLOC_SIZE might save some space > in some cases/archs (e.g. PAGE_SIZE = 64K) when we have lots of > small-size I/Os. OK, if I understand correctly, so you want to share pages among those small I/Os. > >>> + >>> +#define CONSISTENT_DMA_SIZE (1024 * 1024 * 1024) >>> + >>> +static inline struct page * >>> +vduse_domain_get_bounce_page(struct vduse_iova_domain *domain, >>> + unsigned long iova) >>> +{ >>> + unsigned long index = iova >> PAGE_SHIFT; >>> + >>> + return domain->bounce_pages[index]; >>> +} >>> + >>> +static inline void >>> +vduse_domain_set_bounce_page(struct vduse_iova_domain *domain, >>> + unsigned long iova, struct page *page) >>> +{ >>> + unsigned long index = iova >> PAGE_SHIFT; >>> + >>> + domain->bounce_pages[index] = page; >>> +} >>> + >>> +static struct vduse_iova_map * >>> +vduse_domain_alloc_iova_map(struct vduse_iova_domain *domain, >>> + unsigned long iova, unsigned long orig, >>> + size_t size, enum dma_data_direction dir) >>> +{ >>> + struct vduse_iova_map *map; >>> + >>> + map = kzalloc(sizeof(struct vduse_iova_map), GFP_ATOMIC); >>> + if (!map) >>> + return NULL; >>> + >>> + map->iova.start = iova; >>> + map->iova.last = iova + size - 1; >>> + map->orig = orig; >>> + map->size = size; >>> + map->dir = dir; >>> + >>> + return map; >>> +} >>> + >>> +static struct page * >>> +vduse_domain_get_mapping_page(struct vduse_iova_domain *domain, >>> + unsigned long iova) >>> +{ >>> + unsigned long start = iova & PAGE_MASK; >>> + unsigned long last = start + PAGE_SIZE - 1; >>> + struct vduse_iova_map *map; >>> + struct interval_tree_node *node; >>> + struct page *page = NULL; >>> + >>> + spin_lock(&domain->map_lock); >>> + node = interval_tree_iter_first(&domain->mappings, start, last); >>> + if (!node) >>> + goto out; >>> + >>> + map = container_of(node, struct vduse_iova_map, iova); >>> + page = virt_to_page(map->orig + iova - map->iova.start); >>> + get_page(page); >>> +out: >>> + spin_unlock(&domain->map_lock); >>> + >>> + return page; >>> +} >>> + >>> +static struct page * >>> +vduse_domain_alloc_bounce_page(struct vduse_iova_domain *domain, >>> + unsigned long iova) >>> +{ >>> + unsigned long start = iova & PAGE_MASK; >>> + unsigned long last = start + PAGE_SIZE - 1; >>> + struct vduse_iova_map *map; >>> + struct interval_tree_node *node; >>> + struct page *page = NULL, *new_page = alloc_page(GFP_KERNEL); >>> + >>> + if (!new_page) >>> + return NULL; >>> + >>> + spin_lock(&domain->map_lock); >>> + node = interval_tree_iter_first(&domain->mappings, start, last); >>> + if (!node) { >>> + __free_page(new_page); >>> + goto out; >>> + } >>> + page = vduse_domain_get_bounce_page(domain, iova); >>> + if (page) { >>> + get_page(page); >>> + __free_page(new_page); >> >> Let's delay the allocation of new_page until it is really required. > If so, we need to allocate the page in atomic context. Right, I see. >>> + goto out; >>> + } >>> + vduse_domain_set_bounce_page(domain, iova, new_page); >>> + get_page(new_page); >>> + page = new_page; >>> + >>> + while (node) { >> >> I may miss something but which case should we do the loop here? >> > When IOVA_ALLOC_SIZE != PAGE_SIZE > >>> + unsigned int src_offset = 0, dst_offset = 0; >>> + void *src, *dst; >>> + size_t copy_len; >>> + >>> + map = container_of(node, struct vduse_iova_map, iova); >>> + node = interval_tree_iter_next(node, start, last); >>> + if (map->dir == DMA_FROM_DEVICE) >>> + continue; >>> + >>> + if (start > map->iova.start) >>> + src_offset = start - map->iova.start; >>> + else >>> + dst_offset = map->iova.start - start; >>> + >>> + src = (void *)(map->orig + src_offset); >>> + dst = page_address(page) + dst_offset; >>> + copy_len = min_t(size_t, map->size - src_offset, >>> + PAGE_SIZE - dst_offset); >>> + memcpy(dst, src, copy_len); >>> + } >>> +out: >>> + spin_unlock(&domain->map_lock); >>> + >>> + return page; >>> +} >>> + >>> +static void >>> +vduse_domain_free_bounce_pages(struct vduse_iova_domain *domain, >>> + unsigned long iova, size_t size) >>> +{ >>> + struct page *page; >>> + struct interval_tree_node *node; >>> + unsigned long last = iova + size - 1; >>> + >>> + spin_lock(&domain->map_lock); >>> + node = interval_tree_iter_first(&domain->mappings, iova, last); >>> + if (WARN_ON(node)) >>> + goto out; >>> + >>> + while (size > 0) { >>> + page = vduse_domain_get_bounce_page(domain, iova); >>> + if (page) { >>> + vduse_domain_set_bounce_page(domain, iova, NULL); >>> + __free_page(page); >>> + } >>> + size -= PAGE_SIZE; >>> + iova += PAGE_SIZE; >>> + } >>> +out: >>> + spin_unlock(&domain->map_lock); >>> +} >>> + >>> +static void vduse_domain_bounce(struct vduse_iova_domain *domain, >>> + unsigned long iova, unsigned long orig, >>> + size_t size, enum dma_data_direction dir) >>> +{ >>> + unsigned int offset = offset_in_page(iova); >>> + >>> + while (size) { >>> + struct page *p = vduse_domain_get_bounce_page(domain, iova); >>> + size_t copy_len = min_t(size_t, PAGE_SIZE - offset, size); >>> + void *addr; >>> + >>> + WARN_ON(!p && dir == DMA_FROM_DEVICE); >>> + >>> + if (p) { >>> + addr = page_address(p) + offset; >>> + if (dir == DMA_TO_DEVICE) >>> + memcpy(addr, (void *)orig, copy_len); >>> + else if (dir == DMA_FROM_DEVICE) >>> + memcpy((void *)orig, addr, copy_len); >>> + } >>> + >>> + size -= copy_len; >>> + orig += copy_len; >>> + iova += copy_len; >>> + offset = 0; >>> + } >>> +} >>> + >>> +static unsigned long vduse_domain_alloc_iova(struct iova_domain *iovad, >>> + unsigned long size, unsigned long limit) >>> +{ >>> + unsigned long shift = iova_shift(iovad); >>> + unsigned long iova_len = iova_align(iovad, size) >> shift; >>> + unsigned long iova_pfn; >>> + >>> + if (iova_len < (1 << (IOVA_RANGE_CACHE_MAX_SIZE - 1))) >>> + iova_len = roundup_pow_of_two(iova_len); >>> + iova_pfn = alloc_iova_fast(iovad, iova_len, limit >> shift, true); >>> + >>> + return iova_pfn << shift; >>> +} >>> + >>> +static void vduse_domain_free_iova(struct iova_domain *iovad, >>> + unsigned long iova, size_t size) >>> +{ >>> + unsigned long shift = iova_shift(iovad); >>> + unsigned long iova_len = iova_align(iovad, size) >> shift; >>> + >>> + free_iova_fast(iovad, iova >> shift, iova_len); >>> +} >>> + >>> +dma_addr_t vduse_domain_map_page(struct vduse_iova_domain *domain, >>> + struct page *page, unsigned long offset, >>> + size_t size, enum dma_data_direction dir, >>> + unsigned long attrs) >>> +{ >>> + struct iova_domain *iovad = &domain->stream_iovad; >>> + unsigned long limit = domain->bounce_size - 1; >>> + unsigned long iova = vduse_domain_alloc_iova(iovad, size, limit); >>> + unsigned long orig = (unsigned long)page_address(page) + offset; >>> + struct vduse_iova_map *map; >>> + >>> + if (!iova) >>> + return DMA_MAPPING_ERROR; >>> + >>> + map = vduse_domain_alloc_iova_map(domain, iova, orig, size, dir); >>> + if (!map) { >>> + vduse_domain_free_iova(iovad, iova, size); >>> + return DMA_MAPPING_ERROR; >>> + } >>> + >>> + spin_lock(&domain->map_lock); >>> + interval_tree_insert(&map->iova, &domain->mappings); >>> + spin_unlock(&domain->map_lock); >>> + >>> + if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) >>> + vduse_domain_bounce(domain, iova, orig, size, DMA_TO_DEVICE); >>> + >>> + return (dma_addr_t)iova; >>> +} >>> + >>> +void vduse_domain_unmap_page(struct vduse_iova_domain *domain, >>> + dma_addr_t dma_addr, size_t size, >>> + enum dma_data_direction dir, unsigned long attrs) >>> +{ >>> + struct iova_domain *iovad = &domain->stream_iovad; >>> + unsigned long iova = (unsigned long)dma_addr; >>> + struct interval_tree_node *node; >>> + struct vduse_iova_map *map; >>> + >>> + spin_lock(&domain->map_lock); >>> + node = interval_tree_iter_first(&domain->mappings, iova, iova + 1); >>> + if (WARN_ON(!node)) { >>> + spin_unlock(&domain->map_lock); >>> + return; >>> + } >>> + interval_tree_remove(node, &domain->mappings); >>> + spin_unlock(&domain->map_lock); >>> + >>> + map = container_of(node, struct vduse_iova_map, iova); >>> + if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) >>> + vduse_domain_bounce(domain, iova, map->orig, >>> + size, DMA_FROM_DEVICE); >>> + vduse_domain_free_iova(iovad, iova, size); >>> + kfree(map); >>> +} >>> + >>> +void *vduse_domain_alloc_coherent(struct vduse_iova_domain *domain, >>> + size_t size, dma_addr_t *dma_addr, >>> + gfp_t flag, unsigned long attrs) >>> +{ >>> + struct iova_domain *iovad = &domain->consistent_iovad; >>> + unsigned long limit = domain->bounce_size + CONSISTENT_DMA_SIZE - 1; >>> + unsigned long iova = vduse_domain_alloc_iova(iovad, size, limit); >>> + void *orig = alloc_pages_exact(size, flag); >>> + struct vduse_iova_map *map; >>> + >>> + if (!iova || !orig) >>> + goto err; >>> + >>> + map = vduse_domain_alloc_iova_map(domain, iova, (unsigned long)orig, >>> + size, DMA_BIDIRECTIONAL); >>> + if (!map) >>> + goto err; >>> + >>> + spin_lock(&domain->map_lock); >>> + interval_tree_insert(&map->iova, &domain->mappings); >>> + spin_unlock(&domain->map_lock); >>> + *dma_addr = (dma_addr_t)iova; >>> + >>> + return orig; >>> +err: >>> + *dma_addr = DMA_MAPPING_ERROR; >>> + if (orig) >>> + free_pages_exact(orig, size); >>> + if (iova) >>> + vduse_domain_free_iova(iovad, iova, size); >>> + >>> + return NULL; >>> +} >>> + >>> +void vduse_domain_free_coherent(struct vduse_iova_domain *domain, size_t size, >>> + void *vaddr, dma_addr_t dma_addr, >>> + unsigned long attrs) >>> +{ >>> + struct iova_domain *iovad = &domain->consistent_iovad; >>> + unsigned long iova = (unsigned long)dma_addr; >>> + struct interval_tree_node *node; >>> + struct vduse_iova_map *map; >>> + >>> + spin_lock(&domain->map_lock); >>> + node = interval_tree_iter_first(&domain->mappings, iova, iova + 1); >>> + if (WARN_ON(!node)) { >>> + spin_unlock(&domain->map_lock); >>> + return; >>> + } >>> + interval_tree_remove(node, &domain->mappings); >>> + spin_unlock(&domain->map_lock); >>> + >>> + map = container_of(node, struct vduse_iova_map, iova); >>> + vduse_domain_free_iova(iovad, iova, size); >>> + free_pages_exact(vaddr, size); >>> + kfree(map); >>> +} >>> + >>> +static vm_fault_t vduse_domain_mmap_fault(struct vm_fault *vmf) >>> +{ >>> + struct vduse_iova_domain *domain = vmf->vma->vm_private_data; >>> + unsigned long iova = vmf->pgoff << PAGE_SHIFT; >>> + struct page *page; >>> + >>> + if (!domain) >>> + return VM_FAULT_SIGBUS; >>> + >>> + if (iova < domain->bounce_size) >>> + page = vduse_domain_alloc_bounce_page(domain, iova); >>> + else >>> + page = vduse_domain_get_mapping_page(domain, iova); >>> + >>> + if (!page) >>> + return VM_FAULT_SIGBUS; >>> + >>> + vmf->page = page; >>> + >>> + return 0; >>> +} >>> + >>> +static const struct vm_operations_struct vduse_domain_mmap_ops = { >>> + .fault = vduse_domain_mmap_fault, >>> +}; >>> + >>> +static int vduse_domain_mmap(struct file *file, struct vm_area_struct *vma) >>> +{ >>> + struct vduse_iova_domain *domain = file->private_data; >>> + >>> + vma->vm_flags |= VM_DONTCOPY | VM_DONTDUMP | VM_DONTEXPAND; >>> + vma->vm_private_data = domain; >>> + vma->vm_ops = &vduse_domain_mmap_ops; >>> + >>> + return 0; >>> +} >>> + >>> +static int vduse_domain_release(struct inode *inode, struct file *file) >>> +{ >>> + struct vduse_iova_domain *domain = file->private_data; >>> + >>> + vduse_domain_free_bounce_pages(domain, 0, domain->bounce_size); >>> + put_iova_domain(&domain->stream_iovad); >>> + put_iova_domain(&domain->consistent_iovad); >>> + vfree(domain->bounce_pages); >>> + kfree(domain); >>> + >>> + return 0; >>> +} >>> + >>> +static const struct file_operations vduse_domain_fops = { >>> + .mmap = vduse_domain_mmap, >>> + .release = vduse_domain_release, >>> +}; >> >> It's better to explain the reason for introducing a dedicated file for >> mmap() here. >> > To make the implementation of iova_domain independent with vduse_dev. My understanding is that, the only usage for this is to: 1) support different type of iova mappings 2) or switch between iova domain mappings But I can't think of a need for this. > >>> + >>> +void vduse_domain_destroy(struct vduse_iova_domain *domain) >>> +{ >>> + fput(domain->file); >>> +} >>> + >>> +struct vduse_iova_domain *vduse_domain_create(size_t bounce_size) >>> +{ >>> + struct vduse_iova_domain *domain; >>> + struct file *file; >>> + unsigned long bounce_pfns = PAGE_ALIGN(bounce_size) >> PAGE_SHIFT; >>> + >>> + domain = kzalloc(sizeof(*domain), GFP_KERNEL); >>> + if (!domain) >>> + return NULL; >>> + >>> + domain->bounce_size = PAGE_ALIGN(bounce_size); >>> + domain->bounce_pages = vzalloc(bounce_pfns * sizeof(struct page *)); >>> + if (!domain->bounce_pages) >>> + goto err_page; >>> + >>> + file = anon_inode_getfile("[vduse-domain]", &vduse_domain_fops, >>> + domain, O_RDWR); >>> + if (IS_ERR(file)) >>> + goto err_file; >>> + >>> + domain->file = file; >>> + spin_lock_init(&domain->map_lock); >>> + domain->mappings = RB_ROOT_CACHED; >>> + init_iova_domain(&domain->stream_iovad, >>> + IOVA_ALLOC_SIZE, IOVA_START_PFN); >>> + init_iova_domain(&domain->consistent_iovad, >>> + PAGE_SIZE, bounce_pfns); >>> + >>> + return domain; >>> +err_file: >>> + vfree(domain->bounce_pages); >>> +err_page: >>> + kfree(domain); >>> + return NULL; >>> +} >>> diff --git a/drivers/vdpa/vdpa_user/iova_domain.h b/drivers/vdpa/vdpa_user/iova_domain.h >>> new file mode 100644 >>> index 000000000000..cc61866acb56 >>> --- /dev/null >>> +++ b/drivers/vdpa/vdpa_user/iova_domain.h >>> @@ -0,0 +1,68 @@ >>> +/* SPDX-License-Identifier: GPL-2.0-only */ >>> +/* >>> + * MMU-based IOMMU implementation >>> + * >>> + * Copyright (C) 2020 Bytedance Inc. and/or its affiliates. All rights reserved. >>> + * >>> + * Author: Xie Yongji >>> + * >>> + */ >>> + >>> +#ifndef _VDUSE_IOVA_DOMAIN_H >>> +#define _VDUSE_IOVA_DOMAIN_H >>> + >>> +#include >>> +#include >>> +#include >>> + >>> +struct vduse_iova_map { >>> + struct interval_tree_node iova; >>> + unsigned long orig; >> >> Need a better name, probably "va"? >> > Fine. > >>> + size_t size; >>> + enum dma_data_direction dir; >>> +}; >>> + >>> +struct vduse_iova_domain { >>> + struct iova_domain stream_iovad; >>> + struct iova_domain consistent_iovad; >>> + struct page **bounce_pages; >>> + size_t bounce_size; >>> + struct rb_root_cached mappings; >> >> We had IOTLB, any reason for this extra mappings here? >> > It is used to store iova <-> vduse_iova_map (vaddr, size, dir) > mapping. We must use it to know how to do DMA bouncing during dma > unmapping. Right, so I meant consider we support opaque data in the vhost IOTLB. It looks to me we can piggyback the "orig" in the opaque. Then there's no need for an extra interval tree? > >>> + spinlock_t map_lock; >>> + struct file *file; >>> +}; >>> + >>> +static inline struct file * >>> +vduse_domain_file(struct vduse_iova_domain *domain) >>> +{ >>> + return domain->file; >>> +} >>> + >>> +static inline unsigned long >>> +vduse_domain_get_offset(struct vduse_iova_domain *domain, unsigned long iova) >>> +{ >>> + return iova; >>> +} >>> + >>> +dma_addr_t vduse_domain_map_page(struct vduse_iova_domain *domain, >>> + struct page *page, unsigned long offset, >>> + size_t size, enum dma_data_direction dir, >>> + unsigned long attrs); >>> + >>> +void vduse_domain_unmap_page(struct vduse_iova_domain *domain, >>> + dma_addr_t dma_addr, size_t size, >>> + enum dma_data_direction dir, unsigned long attrs); >>> + >>> +void *vduse_domain_alloc_coherent(struct vduse_iova_domain *domain, >>> + size_t size, dma_addr_t *dma_addr, >>> + gfp_t flag, unsigned long attrs); >>> + >>> +void vduse_domain_free_coherent(struct vduse_iova_domain *domain, size_t size, >>> + void *vaddr, dma_addr_t dma_addr, >>> + unsigned long attrs); >>> + >>> +void vduse_domain_destroy(struct vduse_iova_domain *domain); >>> + >>> +struct vduse_iova_domain *vduse_domain_create(size_t bounce_size); >>> + >>> +#endif /* _VDUSE_IOVA_DOMAIN_H */ >>> diff --git a/drivers/vdpa/vdpa_user/vduse.h b/drivers/vdpa/vdpa_user/vduse.h >>> new file mode 100644 >>> index 000000000000..3566d229382e >>> --- /dev/null >>> +++ b/drivers/vdpa/vdpa_user/vduse.h >>> @@ -0,0 +1,62 @@ >>> +/* SPDX-License-Identifier: GPL-2.0-only */ >>> +/* >>> + * VDUSE: vDPA Device in Userspace >>> + * >>> + * Copyright (C) 2020 Bytedance Inc. and/or its affiliates. All rights reserved. >>> + * >>> + * Author: Xie Yongji >>> + * >>> + */ >>> + >>> +#ifndef _VDUSE_H >>> +#define _VDUSE_H >>> + >>> +#include >>> +#include >>> +#include >>> + >>> +#include "iova_domain.h" >>> +#include "eventfd.h" >>> + >>> +struct vduse_virtqueue { >>> + u16 index; >>> + bool ready; >>> + spinlock_t kick_lock; >>> + spinlock_t irq_lock; >>> + struct eventfd_ctx *kickfd; >>> + struct vduse_virqfd *virqfd; >>> + void *private; >>> + irqreturn_t (*cb)(void *data); >>> +}; >>> + >>> +struct vduse_dev; >>> + >>> +struct vduse_vdpa { >>> + struct vdpa_device vdpa; >>> + struct vduse_dev *dev; >>> +}; >>> + >>> +struct vduse_dev { >>> + struct vduse_vdpa *vdev; >>> + struct mutex lock; >>> + struct vduse_virtqueue *vqs; >>> + struct vduse_iova_domain *domain; >>> + struct vhost_iotlb *iommu; >>> + spinlock_t iommu_lock; >>> + atomic_t bounce_map; >>> + spinlock_t msg_lock; >>> + atomic64_t msg_unique; >>> + wait_queue_head_t waitq; >>> + struct list_head send_list; >>> + struct list_head recv_list; >>> + struct list_head list; >>> + bool connected; >>> + u32 id; >>> + u16 vq_size_max; >>> + u16 vq_num; >>> + u32 vq_align; >>> + u32 device_id; >>> + u32 vendor_id; >>> +}; >>> + >>> +#endif /* _VDUSE_H_ */ >>> diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c >>> new file mode 100644 >>> index 000000000000..1cf759bc5914 >>> --- /dev/null >>> +++ b/drivers/vdpa/vdpa_user/vduse_dev.c >>> @@ -0,0 +1,1217 @@ >>> +// SPDX-License-Identifier: GPL-2.0-only >>> +/* >>> + * VDUSE: vDPA Device in Userspace >>> + * >>> + * Copyright (C) 2020 Bytedance Inc. and/or its affiliates. All rights reserved. >>> + * >>> + * Author: Xie Yongji >>> + * >>> + */ >>> + >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> +#include >>> + >>> +#include "vduse.h" >>> + >>> +#define DRV_VERSION "1.0" >>> +#define DRV_AUTHOR "Yongji Xie " >>> +#define DRV_DESC "vDPA Device in Userspace" >>> +#define DRV_LICENSE "GPL v2" >>> + >>> +struct vduse_dev_msg { >>> + struct vduse_dev_request req; >>> + struct vduse_dev_response resp; >>> + struct list_head list; >>> + wait_queue_head_t waitq; >>> + bool completed; >>> + refcount_t refcnt; >> >> The reference count here will bring extra complexity. I think we can >> sync through msg_lock. >> > Do you mean using wait_event_interruptible_locked() and > wake_up_locked()? I think it works. Right. > >> >>> +}; >>> + >>> +static struct workqueue_struct *vduse_vdpa_wq; >>> +static DEFINE_MUTEX(vduse_lock); >>> +static LIST_HEAD(vduse_devs); >>> + >>> +static inline struct vduse_dev *vdpa_to_vduse(struct vdpa_device *vdpa) >>> +{ >>> + struct vduse_vdpa *vdev = container_of(vdpa, struct vduse_vdpa, vdpa); >>> + >>> + return vdev->dev; >>> +} >>> + >>> +static inline struct vduse_dev *dev_to_vduse(struct device *dev) >>> +{ >>> + struct vdpa_device *vdpa = dev_to_vdpa(dev); >>> + >>> + return vdpa_to_vduse(vdpa); >>> +} >>> + >>> +static struct vduse_dev_msg *vduse_dev_new_msg(struct vduse_dev *dev, int type) >>> +{ >>> + struct vduse_dev_msg *msg = kzalloc(sizeof(*msg), >>> + GFP_KERNEL | __GFP_NOFAIL); >>> + >>> + msg->req.type = type; >>> + msg->req.unique = atomic64_fetch_inc(&dev->msg_unique); >> >> This looks not safe, let's use idr here. >> > Could you give more details? Looks like idr should not used in this > case which can not tolerate failure. And using a list to store the msg > is better than using idr when the msg needs to be re-inserted in some > cases. My understanding is the "unique" (probably need a better name) is a token that is used to uniquely identify a message. The reply from userspace is required to write with exact the same token(unique). IDR seems better but consider we can hardly hit 64bit overflow, atomic might be OK as well. Btw, under what case do we need to do "re-inserted"? > >>> + init_waitqueue_head(&msg->waitq); >>> + refcount_set(&msg->refcnt, 1); >>> + >>> + return msg; >>> +} >>> + >>> +static void vduse_dev_msg_get(struct vduse_dev_msg *msg) >>> +{ >>> + refcount_inc(&msg->refcnt); >>> +} >>> + >>> +static void vduse_dev_msg_put(struct vduse_dev_msg *msg) >>> +{ >>> + if (refcount_dec_and_test(&msg->refcnt)) >>> + kfree(msg); >>> +} >>> + >>> +static struct vduse_dev_msg *vduse_dev_find_msg(struct vduse_dev *dev, >>> + struct list_head *head, >>> + uint32_t unique) >>> +{ >>> + struct vduse_dev_msg *tmp, *msg = NULL; >>> + >>> + spin_lock(&dev->msg_lock); >>> + list_for_each_entry(tmp, head, list) { >>> + if (tmp->req.unique == unique) { >>> + msg = tmp; >>> + list_del(&tmp->list); >>> + break; >>> + } >>> + } >>> + spin_unlock(&dev->msg_lock); >>> + >>> + return msg; >>> +} >>> + >>> +static struct vduse_dev_msg *vduse_dev_dequeue_msg(struct vduse_dev *dev, >>> + struct list_head *head) >>> +{ >>> + struct vduse_dev_msg *msg = NULL; >>> + >>> + spin_lock(&dev->msg_lock); >>> + if (!list_empty(head)) { >>> + msg = list_first_entry(head, struct vduse_dev_msg, list); >>> + list_del(&msg->list); >>> + } >>> + spin_unlock(&dev->msg_lock); >>> + >>> + return msg; >>> +} >>> + >>> +static void vduse_dev_enqueue_msg(struct vduse_dev *dev, >>> + struct vduse_dev_msg *msg, struct list_head *head) >>> +{ >>> + spin_lock(&dev->msg_lock); >>> + list_add_tail(&msg->list, head); >>> + spin_unlock(&dev->msg_lock); >>> +} >>> + >>> +static int vduse_dev_msg_sync(struct vduse_dev *dev, struct vduse_dev_msg *msg) >>> +{ >>> + int ret; >>> + >>> + vduse_dev_enqueue_msg(dev, msg, &dev->send_list); >>> + wake_up(&dev->waitq); >>> + wait_event(msg->waitq, msg->completed); >> >> This is uninterruptible wait, it means if the userspace forget to >> process the command, we will stuck here forever. >> > Yes, wait_event_interruptible() should be better here. > >>> + /* coupled with smp_wmb() in vduse_dev_msg_complete() */ >>> + smp_rmb(); >> >> Instead of using barriers, I wonder why not simply use msg lock here? >> > As mentioned above, using > wait_event_interruptible_locked()/wake_up_locked() is OK to me. > >>> + ret = msg->resp.result; >>> + >>> + return ret; >>> +} >>> + >>> +static void vduse_dev_msg_complete(struct vduse_dev_msg *msg, >>> + struct vduse_dev_response *resp) >>> +{ >>> + vduse_dev_msg_get(msg); >>> + memcpy(&msg->resp, resp, sizeof(*resp)); >>> + /* coupled with smp_rmb() in vduse_dev_msg_sync() */ >>> + smp_wmb(); >>> + msg->completed = 1; >>> + wake_up(&msg->waitq); >>> + vduse_dev_msg_put(msg); >>> +} >>> + >>> +static u64 vduse_dev_get_features(struct vduse_dev *dev) >>> +{ >>> + struct vduse_dev_msg *msg = vduse_dev_new_msg(dev, VDUSE_GET_FEATURES); >>> + u64 features; >>> + >>> + vduse_dev_msg_sync(dev, msg); >>> + features = msg->resp.features; >>> + vduse_dev_msg_put(msg); >>> + >>> + return features; >>> +} >>> + >>> +static int vduse_dev_set_features(struct vduse_dev *dev, u64 features) >>> +{ >>> + struct vduse_dev_msg *msg = vduse_dev_new_msg(dev, VDUSE_SET_FEATURES); >>> + int ret; >>> + >>> + msg->req.size = sizeof(features); >>> + msg->req.features = features; >>> + >>> + ret = vduse_dev_msg_sync(dev, msg); >>> + vduse_dev_msg_put(msg); >>> + >>> + return ret; >>> +} >>> + >>> +static u8 vduse_dev_get_status(struct vduse_dev *dev) >>> +{ >>> + struct vduse_dev_msg *msg = vduse_dev_new_msg(dev, VDUSE_GET_STATUS); >>> + u8 status; >>> + >>> + vduse_dev_msg_sync(dev, msg); >>> + status = msg->resp.status; >>> + vduse_dev_msg_put(msg); >>> + >>> + return status; >>> +} >>> + >>> +static void vduse_dev_set_status(struct vduse_dev *dev, u8 status) >>> +{ >>> + struct vduse_dev_msg *msg = vduse_dev_new_msg(dev, VDUSE_SET_STATUS); >>> + >>> + msg->req.size = sizeof(status); >>> + msg->req.status = status; >>> + >>> + vduse_dev_msg_sync(dev, msg); >>> + vduse_dev_msg_put(msg); >>> +} >>> + >>> +static void vduse_dev_get_config(struct vduse_dev *dev, unsigned int offset, >>> + void *buf, unsigned int len) >>> +{ >>> + struct vduse_dev_msg *msg = vduse_dev_new_msg(dev, VDUSE_GET_CONFIG); >>> + >>> + WARN_ON(len > sizeof(msg->req.config.data)); >>> + >>> + msg->req.size = sizeof(struct vduse_dev_config_data); >>> + msg->req.config.offset = offset; >>> + msg->req.config.len = len; >>> + vduse_dev_msg_sync(dev, msg); >>> + memcpy(buf, msg->resp.config.data, len); >>> + vduse_dev_msg_put(msg); >>> +} >>> + >>> +static void vduse_dev_set_config(struct vduse_dev *dev, unsigned int offset, >>> + const void *buf, unsigned int len) >>> +{ >>> + struct vduse_dev_msg *msg = vduse_dev_new_msg(dev, VDUSE_SET_CONFIG); >>> + >>> + WARN_ON(len > sizeof(msg->req.config.data)); >>> + >>> + msg->req.size = sizeof(struct vduse_dev_config_data); >>> + msg->req.config.offset = offset; >>> + msg->req.config.len = len; >>> + memcpy(msg->req.config.data, buf, len); >>> + vduse_dev_msg_sync(dev, msg); >>> + vduse_dev_msg_put(msg); >>> +} >>> + >>> +static void vduse_dev_set_vq_num(struct vduse_dev *dev, >>> + struct vduse_virtqueue *vq, u32 num) >>> +{ >>> + struct vduse_dev_msg *msg = vduse_dev_new_msg(dev, VDUSE_SET_VQ_NUM); >>> + >>> + msg->req.size = sizeof(struct vduse_vq_num); >>> + msg->req.vq_num.index = vq->index; >>> + msg->req.vq_num.num = num; >>> + >>> + vduse_dev_msg_sync(dev, msg); >>> + vduse_dev_msg_put(msg); >>> +} >>> + >>> +static int vduse_dev_set_vq_addr(struct vduse_dev *dev, >>> + struct vduse_virtqueue *vq, u64 desc_addr, >>> + u64 driver_addr, u64 device_addr) >>> +{ >>> + struct vduse_dev_msg *msg = vduse_dev_new_msg(dev, VDUSE_SET_VQ_ADDR); >>> + int ret; >>> + >>> + msg->req.size = sizeof(struct vduse_vq_addr); >>> + msg->req.vq_addr.index = vq->index; >>> + msg->req.vq_addr.desc_addr = desc_addr; >>> + msg->req.vq_addr.driver_addr = driver_addr; >>> + msg->req.vq_addr.device_addr = device_addr; >>> + >>> + ret = vduse_dev_msg_sync(dev, msg); >>> + vduse_dev_msg_put(msg); >>> + >>> + return ret; >>> +} >>> + >>> +static void vduse_dev_set_vq_ready(struct vduse_dev *dev, >>> + struct vduse_virtqueue *vq, bool ready) >>> +{ >>> + struct vduse_dev_msg *msg = vduse_dev_new_msg(dev, VDUSE_SET_VQ_READY); >>> + >>> + msg->req.size = sizeof(struct vduse_vq_ready); >>> + msg->req.vq_ready.index = vq->index; >>> + msg->req.vq_ready.ready = ready; >>> + >>> + vduse_dev_msg_sync(dev, msg); >>> + vduse_dev_msg_put(msg); >>> +} >>> + >>> +static bool vduse_dev_get_vq_ready(struct vduse_dev *dev, >>> + struct vduse_virtqueue *vq) >>> +{ >>> + struct vduse_dev_msg *msg = vduse_dev_new_msg(dev, VDUSE_GET_VQ_READY); >>> + bool ready; >>> + >>> + msg->req.size = sizeof(struct vduse_vq_ready); >>> + msg->req.vq_ready.index = vq->index; >>> + >>> + vduse_dev_msg_sync(dev, msg); >>> + ready = msg->resp.vq_ready.ready; >>> + vduse_dev_msg_put(msg); >>> + >>> + return ready; >>> +} >>> + >>> +static int vduse_dev_get_vq_state(struct vduse_dev *dev, >>> + struct vduse_virtqueue *vq, >>> + struct vdpa_vq_state *state) >>> +{ >>> + struct vduse_dev_msg *msg = vduse_dev_new_msg(dev, VDUSE_GET_VQ_STATE); >>> + int ret; >>> + >>> + msg->req.size = sizeof(struct vduse_vq_state); >>> + msg->req.vq_state.index = vq->index; >>> + >>> + ret = vduse_dev_msg_sync(dev, msg); >>> + state->avail_index = msg->resp.vq_state.avail_idx; >>> + vduse_dev_msg_put(msg); >>> + >>> + return ret; >>> +} >>> + >>> +static int vduse_dev_set_vq_state(struct vduse_dev *dev, >>> + struct vduse_virtqueue *vq, >>> + const struct vdpa_vq_state *state) >>> +{ >>> + struct vduse_dev_msg *msg = vduse_dev_new_msg(dev, VDUSE_SET_VQ_STATE); >>> + int ret; >>> + >>> + msg->req.size = sizeof(struct vduse_vq_state); >>> + msg->req.vq_state.index = vq->index; >>> + msg->req.vq_state.avail_idx = state->avail_index; >>> + >>> + ret = vduse_dev_msg_sync(dev, msg); >>> + vduse_dev_msg_put(msg); >>> + >>> + return ret; >>> +} >>> + >>> +static int vduse_dev_update_iotlb(struct vduse_dev *dev, >>> + u64 start, u64 last) >>> +{ >>> + struct vduse_dev_msg *msg; >>> + int ret; >>> + >>> + if (last < start) >>> + return -EINVAL; >>> + >>> + msg = vduse_dev_new_msg(dev, VDUSE_UPDATE_IOTLB); >> >> This is actually a IOTLB invalidation. So let's rename the function and >> message type. >> > Actually VDUSE_UPDATE_IOTLB now is used to notify userspace that IOTLB > is changed rather than IOTLB needs to be invalidated. Then userspace > can use GET_IOTLB ioctl to get the change. It seems to be more > friendly to userspace. Ok. > >>> + msg->req.size = sizeof(struct vduse_iova_range); >>> + msg->req.iova.start = start; >>> + msg->req.iova.last = last; >>> + >>> + ret = vduse_dev_msg_sync(dev, msg); >>> + vduse_dev_msg_put(msg); >>> + >>> + return ret; >>> +} >>> + >>> +static ssize_t vduse_dev_read_iter(struct kiocb *iocb, struct iov_iter *to) >>> +{ >>> + struct file *file = iocb->ki_filp; >>> + struct vduse_dev *dev = file->private_data; >>> + struct vduse_dev_msg *msg; >>> + int size = sizeof(struct vduse_dev_request); >>> + ssize_t ret = 0; >>> + >>> + if (iov_iter_count(to) < size) >>> + return 0; >>> + >>> + while (1) { >>> + msg = vduse_dev_dequeue_msg(dev, &dev->send_list); >>> + if (msg) >>> + break; >>> + >>> + if (file->f_flags & O_NONBLOCK) >>> + return -EAGAIN; >>> + >>> + ret = wait_event_interruptible_exclusive(dev->waitq, >>> + !list_empty(&dev->send_list)); >>> + if (ret) >>> + return ret; >>> + } >>> + ret = copy_to_iter(&msg->req, size, to); >>> + if (ret != size) { >>> + vduse_dev_enqueue_msg(dev, msg, &dev->send_list); >>> + return -EFAULT; >>> + } >>> + vduse_dev_enqueue_msg(dev, msg, &dev->recv_list); >>> + >>> + return ret; >>> +} >>> + >>> +static ssize_t vduse_dev_write_iter(struct kiocb *iocb, struct iov_iter *from) >>> +{ >>> + struct file *file = iocb->ki_filp; >>> + struct vduse_dev *dev = file->private_data; >>> + struct vduse_dev_response resp; >>> + struct vduse_dev_msg *msg; >>> + size_t ret; >>> + >>> + ret = copy_from_iter(&resp, sizeof(resp), from); >>> + if (ret != sizeof(resp)) >>> + return -EINVAL; >>> + >>> + msg = vduse_dev_find_msg(dev, &dev->recv_list, resp.unique); >>> + if (!msg) >>> + return -EINVAL; >>> + >>> + vduse_dev_msg_complete(msg, &resp); >> >> So we had multiple types of requests/responses, is this better to >> introduce a queue based admin interface other than ioctl? >> > Sorry, I didn't get your point. What do you mean by queue-based admin > interface? Virtqueue-based? Yes, a queue(virtqueue). The commands could be passed through the queue. (Just an idea, not sure it's worth) > >>> + >>> + return ret; >>> +} >>> + >>> +static __poll_t vduse_dev_poll(struct file *file, poll_table *wait) >>> +{ >>> + struct vduse_dev *dev = file->private_data; >>> + __poll_t mask = 0; >>> + >>> + poll_wait(file, &dev->waitq, wait); >>> + >>> + if (!list_empty(&dev->send_list)) >>> + mask |= EPOLLIN | EPOLLRDNORM; >>> + >>> + return mask; >>> +} >>> + >>> +static int vduse_iotlb_add_range(struct vduse_dev *dev, >>> + u64 start, u64 last, >>> + u64 addr, unsigned int perm, >>> + struct file *file, u64 offset) >>> +{ >>> + struct vhost_iotlb_file *iotlb_file; >>> + int ret; >>> + >>> + iotlb_file = kmalloc(sizeof(*iotlb_file), GFP_ATOMIC); >>> + if (!iotlb_file) >>> + return -ENOMEM; >>> + >>> + iotlb_file->file = get_file(file); >>> + iotlb_file->offset = offset; >>> + >>> + spin_lock(&dev->iommu_lock); >>> + ret = vhost_iotlb_add_range(dev->iommu, start, last, >>> + addr, perm, iotlb_file); >>> + spin_unlock(&dev->iommu_lock); >>> + if (ret) { >>> + fput(iotlb_file->file); >>> + kfree(iotlb_file); >>> + return ret; >>> + } >>> + return 0; >>> +} >>> + >>> +static void vduse_iotlb_del_range(struct vduse_dev *dev, u64 start, u64 last) >>> +{ >>> + struct vhost_iotlb_file *iotlb_file; >>> + struct vhost_iotlb_map *map; >>> + >>> + spin_lock(&dev->iommu_lock); >>> + while ((map = vhost_iotlb_itree_first(dev->iommu, start, last))) { >>> + iotlb_file = (struct vhost_iotlb_file *)map->opaque; >>> + fput(iotlb_file->file); >>> + kfree(iotlb_file); >>> + vhost_iotlb_map_free(dev->iommu, map); >>> + } >>> + spin_unlock(&dev->iommu_lock); >>> +} >>> + >>> +static void vduse_dev_reset(struct vduse_dev *dev) >>> +{ >>> + int i; >>> + >>> + atomic_set(&dev->bounce_map, 0); >>> + vduse_iotlb_del_range(dev, 0ULL, 0ULL - 1); >>> + vduse_dev_update_iotlb(dev, 0ULL, 0ULL - 1); >> >> ULLONG_MAX please. >> > OK. > >>> + >>> + for (i = 0; i < dev->vq_num; i++) { >>> + struct vduse_virtqueue *vq = &dev->vqs[i]; >>> + >>> + spin_lock(&vq->irq_lock); >>> + vq->ready = false; >>> + vq->cb = NULL; >>> + vq->private = NULL; >>> + spin_unlock(&vq->irq_lock); >>> + } >>> +} >>> + >>> +static int vduse_vdpa_set_vq_address(struct vdpa_device *vdpa, u16 idx, >>> + u64 desc_area, u64 driver_area, >>> + u64 device_area) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + struct vduse_virtqueue *vq = &dev->vqs[idx]; >>> + >>> + return vduse_dev_set_vq_addr(dev, vq, desc_area, >>> + driver_area, device_area); >>> +} >>> + >>> +static void vduse_vdpa_kick_vq(struct vdpa_device *vdpa, u16 idx) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + struct vduse_virtqueue *vq = &dev->vqs[idx]; >>> + >>> + vduse_vq_kick(vq); >>> +} >>> + >>> +static void vduse_vdpa_set_vq_cb(struct vdpa_device *vdpa, u16 idx, >>> + struct vdpa_callback *cb) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + struct vduse_virtqueue *vq = &dev->vqs[idx]; >>> + >>> + vq->cb = cb->callback; >>> + vq->private = cb->private; >>> +} >>> + >>> +static void vduse_vdpa_set_vq_num(struct vdpa_device *vdpa, u16 idx, u32 num) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + struct vduse_virtqueue *vq = &dev->vqs[idx]; >>> + >>> + vduse_dev_set_vq_num(dev, vq, num); >>> +} >>> + >>> +static void vduse_vdpa_set_vq_ready(struct vdpa_device *vdpa, >>> + u16 idx, bool ready) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + struct vduse_virtqueue *vq = &dev->vqs[idx]; >>> + >>> + vduse_dev_set_vq_ready(dev, vq, ready); >>> + vq->ready = ready; >>> +} >>> + >>> +static bool vduse_vdpa_get_vq_ready(struct vdpa_device *vdpa, u16 idx) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + struct vduse_virtqueue *vq = &dev->vqs[idx]; >>> + >>> + vq->ready = vduse_dev_get_vq_ready(dev, vq); >>> + >>> + return vq->ready; >>> +} >>> + >>> +static int vduse_vdpa_set_vq_state(struct vdpa_device *vdpa, u16 idx, >>> + const struct vdpa_vq_state *state) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + struct vduse_virtqueue *vq = &dev->vqs[idx]; >>> + >>> + return vduse_dev_set_vq_state(dev, vq, state); >>> +} >>> + >>> +static int vduse_vdpa_get_vq_state(struct vdpa_device *vdpa, u16 idx, >>> + struct vdpa_vq_state *state) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + struct vduse_virtqueue *vq = &dev->vqs[idx]; >>> + >>> + return vduse_dev_get_vq_state(dev, vq, state); >>> +} >>> + >>> +static u32 vduse_vdpa_get_vq_align(struct vdpa_device *vdpa) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + >>> + return dev->vq_align; >>> +} >>> + >>> +static u64 vduse_vdpa_get_features(struct vdpa_device *vdpa) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + u64 fixed = (1ULL << VIRTIO_F_ACCESS_PLATFORM); >>> + >>> + return (vduse_dev_get_features(dev) | fixed); >>> +} >>> + >>> +static int vduse_vdpa_set_features(struct vdpa_device *vdpa, u64 features) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + >>> + return vduse_dev_set_features(dev, features); >>> +} >>> + >>> +static void vduse_vdpa_set_config_cb(struct vdpa_device *vdpa, >>> + struct vdpa_callback *cb) >>> +{ >>> + /* We don't support config interrupt */ >> >> If it's not hard, let's add this. Otherwise we need a per device feature >> blacklist to filter out all features that depends on config interrupt. >> > Will do it. > >>> +} >>> + >>> +static u16 vduse_vdpa_get_vq_num_max(struct vdpa_device *vdpa) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + >>> + return dev->vq_size_max; >>> +} >>> + >>> +static u32 vduse_vdpa_get_device_id(struct vdpa_device *vdpa) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + >>> + return dev->device_id; >>> +} >>> + >>> +static u32 vduse_vdpa_get_vendor_id(struct vdpa_device *vdpa) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + >>> + return dev->vendor_id; >>> +} >>> + >>> +static u8 vduse_vdpa_get_status(struct vdpa_device *vdpa) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + >>> + return vduse_dev_get_status(dev); >>> +} >>> + >>> +static void vduse_vdpa_set_status(struct vdpa_device *vdpa, u8 status) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + >>> + if (status == 0) >>> + vduse_dev_reset(dev); >>> + else >>> + vduse_dev_update_iotlb(dev, 0ULL, 0ULL - 1); >> >> Any reason for such IOTLB invalidation here? >> > As I mentioned before, this is used to notify userspace to update the > IOTLB. Mainly for virtio-vdpa case. So the question is, usually, there could be several times of status setting during driver initialization. Do we really need to update IOTLB every time? > >>> + >>> + vduse_dev_set_status(dev, status); >>> +} >>> + >>> +static void vduse_vdpa_get_config(struct vdpa_device *vdpa, unsigned int offset, >>> + void *buf, unsigned int len) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + >>> + vduse_dev_get_config(dev, offset, buf, len); >>> +} >>> + >>> +static void vduse_vdpa_set_config(struct vdpa_device *vdpa, unsigned int offset, >>> + const void *buf, unsigned int len) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + >>> + vduse_dev_set_config(dev, offset, buf, len); >>> +} >>> + >>> +static int vduse_vdpa_set_map(struct vdpa_device *vdpa, >>> + struct vhost_iotlb *iotlb) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + struct vhost_iotlb_map *map; >>> + struct vhost_iotlb_file *iotlb_file; >>> + u64 start = 0ULL, last = 0ULL - 1; >>> + int ret = 0; >>> + >>> + vduse_iotlb_del_range(dev, start, last); >>> + >>> + for (map = vhost_iotlb_itree_first(iotlb, start, last); map; >>> + map = vhost_iotlb_itree_next(map, start, last)) { >>> + if (!map->opaque) >>> + continue; >> >> What will happen if we simply accept NULL opaque here? >> > No file to mmap in userspace. So it's useless. > >>> + >>> + iotlb_file = (struct vhost_iotlb_file *)map->opaque; >>> + ret = vduse_iotlb_add_range(dev, map->start, map->last, >>> + map->addr, map->perm, >>> + iotlb_file->file, >>> + iotlb_file->offset); >>> + if (ret) >>> + break; >>> + } >>> + vduse_dev_update_iotlb(dev, start, last); >>> + >>> + return ret; >>> +} >>> + >>> +static void vduse_vdpa_free(struct vdpa_device *vdpa) >>> +{ >>> + struct vduse_dev *dev = vdpa_to_vduse(vdpa); >>> + >>> + WARN_ON(!list_empty(&dev->send_list)); >>> + WARN_ON(!list_empty(&dev->recv_list)); >>> + dev->vdev = NULL; >>> +} >>> + >>> +static const struct vdpa_config_ops vduse_vdpa_config_ops = { >>> + .set_vq_address = vduse_vdpa_set_vq_address, >>> + .kick_vq = vduse_vdpa_kick_vq, >>> + .set_vq_cb = vduse_vdpa_set_vq_cb, >>> + .set_vq_num = vduse_vdpa_set_vq_num, >>> + .set_vq_ready = vduse_vdpa_set_vq_ready, >>> + .get_vq_ready = vduse_vdpa_get_vq_ready, >>> + .set_vq_state = vduse_vdpa_set_vq_state, >>> + .get_vq_state = vduse_vdpa_get_vq_state, >>> + .get_vq_align = vduse_vdpa_get_vq_align, >>> + .get_features = vduse_vdpa_get_features, >>> + .set_features = vduse_vdpa_set_features, >>> + .set_config_cb = vduse_vdpa_set_config_cb, >>> + .get_vq_num_max = vduse_vdpa_get_vq_num_max, >>> + .get_device_id = vduse_vdpa_get_device_id, >>> + .get_vendor_id = vduse_vdpa_get_vendor_id, >>> + .get_status = vduse_vdpa_get_status, >>> + .set_status = vduse_vdpa_set_status, >>> + .get_config = vduse_vdpa_get_config, >>> + .set_config = vduse_vdpa_set_config, >>> + .set_map = vduse_vdpa_set_map, >>> + .free = vduse_vdpa_free, >>> +}; >>> + >>> +static dma_addr_t vduse_dev_map_page(struct device *dev, struct page *page, >>> + unsigned long offset, size_t size, >>> + enum dma_data_direction dir, >>> + unsigned long attrs) >>> +{ >>> + struct vduse_dev *vdev = dev_to_vduse(dev); >>> + struct vduse_iova_domain *domain = vdev->domain; >>> + >>> + if (atomic_xchg(&vdev->bounce_map, 1) == 0 && >>> + vduse_iotlb_add_range(vdev, 0, domain->bounce_size - 1, >>> + 0, VDUSE_ACCESS_RW, >> >> Is this safe to use VDUSE_ACCESS_RW here, consider we might have device >> readonly mappings. >> > This mapping is for the whole bounce buffer. Maybe userspace needs to > tell us if it only support readonly mappings. Right, so I think we don't need to care about this. > >>> + vduse_domain_file(domain), >>> + vduse_domain_get_offset(domain, 0))) { >>> + atomic_set(&vdev->bounce_map, 0); >>> + return DMA_MAPPING_ERROR; >>> + } >>> + >>> + return vduse_domain_map_page(domain, page, offset, size, dir, attrs); >>> +} >>> + >>> +static void vduse_dev_unmap_page(struct device *dev, dma_addr_t dma_addr, >>> + size_t size, enum dma_data_direction dir, >>> + unsigned long attrs) >>> +{ >>> + struct vduse_dev *vdev = dev_to_vduse(dev); >>> + struct vduse_iova_domain *domain = vdev->domain; >>> + >>> + return vduse_domain_unmap_page(domain, dma_addr, size, dir, attrs); >>> +} >>> + >>> +static void *vduse_dev_alloc_coherent(struct device *dev, size_t size, >>> + dma_addr_t *dma_addr, gfp_t flag, >>> + unsigned long attrs) >>> +{ >>> + struct vduse_dev *vdev = dev_to_vduse(dev); >>> + struct vduse_iova_domain *domain = vdev->domain; >>> + unsigned long iova; >>> + void *addr; >>> + >>> + *dma_addr = DMA_MAPPING_ERROR; >>> + addr = vduse_domain_alloc_coherent(domain, size, >>> + (dma_addr_t *)&iova, flag, attrs); >>> + if (!addr) >>> + return NULL; >>> + >>> + if (vduse_iotlb_add_range(vdev, iova, iova + size - 1, >>> + iova, VDUSE_ACCESS_RW, >>> + vduse_domain_file(domain), >>> + vduse_domain_get_offset(domain, iova))) { >>> + vduse_domain_free_coherent(domain, size, addr, iova, attrs); >>> + return NULL; >>> + } >>> + *dma_addr = (dma_addr_t)iova; >>> + >>> + return addr; >>> +} >>> + >>> +static void vduse_dev_free_coherent(struct device *dev, size_t size, >>> + void *vaddr, dma_addr_t dma_addr, >>> + unsigned long attrs) >>> +{ >>> + struct vduse_dev *vdev = dev_to_vduse(dev); >>> + struct vduse_iova_domain *domain = vdev->domain; >>> + unsigned long start = (unsigned long)dma_addr; >>> + unsigned long last = start + size - 1; >>> + >>> + vduse_iotlb_del_range(vdev, start, last); >>> + vduse_dev_update_iotlb(vdev, start, last); >>> + vduse_domain_free_coherent(domain, size, vaddr, dma_addr, attrs); >>> +} >>> + >>> +static const struct dma_map_ops vduse_dev_dma_ops = { >>> + .map_page = vduse_dev_map_page, >>> + .unmap_page = vduse_dev_unmap_page, >>> + .alloc = vduse_dev_alloc_coherent, >>> + .free = vduse_dev_free_coherent, >>> +}; >>> + >>> +static unsigned int perm_to_file_flags(u8 perm) >>> +{ >>> + unsigned int flags = 0; >>> + >>> + switch (perm) { >>> + case VDUSE_ACCESS_WO: >>> + flags |= O_WRONLY; >>> + break; >>> + case VDUSE_ACCESS_RO: >>> + flags |= O_RDONLY; >>> + break; >>> + case VDUSE_ACCESS_RW: >>> + flags |= O_RDWR; >>> + break; >>> + default: >>> + WARN(1, "invalidate vhost IOTLB permission\n"); >>> + break; >>> + } >>> + >>> + return flags; >>> +} >>> + >>> +static long vduse_dev_ioctl(struct file *file, unsigned int cmd, >>> + unsigned long arg) >>> +{ >>> + struct vduse_dev *dev = file->private_data; >>> + void __user *argp = (void __user *)arg; >>> + int ret; >>> + >>> + mutex_lock(&dev->lock); >>> + switch (cmd) { >>> + case VDUSE_IOTLB_GET_FD: { >>> + struct vduse_iotlb_entry entry; >>> + struct vhost_iotlb_map *map; >>> + struct vhost_iotlb_file *iotlb_file; >>> + struct file *f = NULL; >>> + >>> + ret = -EFAULT; >>> + if (copy_from_user(&entry, argp, sizeof(entry))) >>> + break; >>> + >>> + spin_lock(&dev->iommu_lock); >>> + map = vhost_iotlb_itree_first(dev->iommu, entry.start, >>> + entry.last); >>> + if (map) { >>> + iotlb_file = (struct vhost_iotlb_file *)map->opaque; >>> + f = get_file(iotlb_file->file); >>> + entry.offset = iotlb_file->offset; >>> + entry.start = map->start; >>> + entry.last = map->last; >>> + entry.perm = map->perm; >>> + } >>> + spin_unlock(&dev->iommu_lock); >>> + if (!f) { >>> + ret = -EINVAL; >>> + break; >>> + } >>> + if (copy_to_user(argp, &entry, sizeof(entry))) { >>> + fput(f); >>> + ret = -EFAULT; >>> + break; >>> + } >>> + ret = get_unused_fd_flags(perm_to_file_flags(entry.perm)); >>> + if (ret < 0) { >>> + fput(f); >>> + break; >>> + } >>> + fd_install(ret, f); >>> + break; >>> + } >>> + case VDUSE_VQ_SETUP_KICKFD: { >>> + struct vduse_vq_eventfd eventfd; >>> + >>> + ret = -EFAULT; >>> + if (copy_from_user(&eventfd, argp, sizeof(eventfd))) >>> + break; >>> + >>> + ret = vduse_kickfd_setup(dev, &eventfd); >>> + break; >>> + } >>> + case VDUSE_VQ_SETUP_IRQFD: { >>> + struct vduse_vq_eventfd eventfd; >>> + >>> + ret = -EFAULT; >>> + if (copy_from_user(&eventfd, argp, sizeof(eventfd))) >>> + break; >>> + >>> + ret = vduse_virqfd_setup(dev, &eventfd); >>> + break; >>> + } >>> + } >>> + mutex_unlock(&dev->lock); >>> + >>> + return ret; >>> +} >>> + >>> +static int vduse_dev_release(struct inode *inode, struct file *file) >>> +{ >>> + struct vduse_dev *dev = file->private_data; >>> + >>> + vduse_kickfd_release(dev); >>> + vduse_virqfd_release(dev); >>> + dev->connected = false; >>> + >>> + return 0; >>> +} >>> + >>> +static const struct file_operations vduse_dev_fops = { >>> + .owner = THIS_MODULE, >>> + .release = vduse_dev_release, >>> + .read_iter = vduse_dev_read_iter, >>> + .write_iter = vduse_dev_write_iter, >>> + .poll = vduse_dev_poll, >>> + .unlocked_ioctl = vduse_dev_ioctl, >>> + .compat_ioctl = compat_ptr_ioctl, >>> + .llseek = noop_llseek, >>> +}; >>> + >>> +static struct vduse_dev *vduse_dev_create(void) >>> +{ >>> + struct vduse_dev *dev = kzalloc(sizeof(*dev), GFP_KERNEL); >>> + >>> + if (!dev) >>> + return NULL; >>> + >>> + dev->iommu = vhost_iotlb_alloc(2048, 0); >> >> Is 2048 sufficient here? >> > How about letting userspace to define it? Fine with me. > > >>> + if (!dev->iommu) { >>> + kfree(dev); >>> + return NULL; >>> + } >>> + >>> + mutex_init(&dev->lock); >>> + spin_lock_init(&dev->msg_lock); >>> + INIT_LIST_HEAD(&dev->send_list); >>> + INIT_LIST_HEAD(&dev->recv_list); >>> + atomic64_set(&dev->msg_unique, 0); >>> + spin_lock_init(&dev->iommu_lock); >>> + atomic_set(&dev->bounce_map, 0); >>> + >>> + init_waitqueue_head(&dev->waitq); >>> + >>> + return dev; >>> +} >>> + >>> +static void vduse_dev_destroy(struct vduse_dev *dev) >>> +{ >>> + vhost_iotlb_free(dev->iommu); >>> + mutex_destroy(&dev->lock); >>> + kfree(dev); >>> +} >>> + >>> +static struct vduse_dev *vduse_find_dev(u32 id) >>> +{ >>> + struct vduse_dev *tmp, *dev = NULL; >>> + >>> + list_for_each_entry(tmp, &vduse_devs, list) { >>> + if (tmp->id == id) { >>> + dev = tmp; >>> + break; >>> + } >>> + } >>> + return dev; >>> +} >>> + >>> +static int vduse_destroy_dev(u32 id) >>> +{ >>> + struct vduse_dev *dev = vduse_find_dev(id); >>> + >>> + if (!dev) >>> + return -EINVAL; >>> + >>> + if (dev->vdev || dev->connected) >>> + return -EBUSY; >>> + >>> + list_del(&dev->list); >>> + kfree(dev->vqs); >>> + vduse_domain_destroy(dev->domain); >>> + vduse_dev_destroy(dev); >>> + >>> + return 0; >>> +} >>> + >>> +static int vduse_create_dev(struct vduse_dev_config *config) >>> +{ >>> + int i, fd; >>> + struct vduse_dev *dev; >>> + char name[64]; >>> + >>> + if (vduse_find_dev(config->id)) >>> + return -EEXIST; >>> + >>> + dev = vduse_dev_create(); >>> + if (!dev) >>> + return -ENOMEM; >>> + >>> + dev->id = config->id; >>> + dev->device_id = config->device_id; >>> + dev->vendor_id = config->vendor_id; >>> + dev->domain = vduse_domain_create(config->bounce_size); >> >> Do we need a upper limit of bounce_size? >> > I agree. Any comment for the value? Something like swiotlb default value (64M)? > >>> + if (!dev->domain) >>> + goto err_domain; >>> + >>> + dev->vq_align = config->vq_align; >>> + dev->vq_size_max = config->vq_size_max; >>> + dev->vq_num = config->vq_num; >>> + dev->vqs = kcalloc(dev->vq_num, sizeof(*dev->vqs), GFP_KERNEL); >>> + if (!dev->vqs) >>> + goto err_vqs; >>> + >>> + for (i = 0; i < dev->vq_num; i++) { >>> + dev->vqs[i].index = i; >>> + spin_lock_init(&dev->vqs[i].kick_lock); >>> + spin_lock_init(&dev->vqs[i].irq_lock); >>> + } >>> + >>> + snprintf(name, sizeof(name), "[vduse-dev:%u]", config->id); >>> + fd = anon_inode_getfd(name, &vduse_dev_fops, dev, O_RDWR | O_CLOEXEC); >> >> Any reason for closing on exec here? >> > Looks like we can remove this flag. > >>> + if (fd < 0) >>> + goto err_fd; >>> + >>> + dev->connected = true; >>> + list_add(&dev->list, &vduse_devs); >>> + >>> + return fd; >>> +err_fd: >>> + kfree(dev->vqs); >>> +err_vqs: >>> + vduse_domain_destroy(dev->domain); >>> +err_domain: >>> + vduse_dev_destroy(dev); >>> + return fd; >>> +} >>> + >>> +static long vduse_ioctl(struct file *file, unsigned int cmd, >>> + unsigned long arg) >>> +{ >>> + int ret; >>> + void __user *argp = (void __user *)arg; >>> + >>> + mutex_lock(&vduse_lock); >>> + switch (cmd) { >>> + case VDUSE_CREATE_DEV: { >>> + struct vduse_dev_config config; >>> + >>> + ret = -EFAULT; >>> + if (copy_from_user(&config, argp, sizeof(config))) >>> + break; >>> + >>> + ret = vduse_create_dev(&config); >>> + break; >>> + } >>> + case VDUSE_DESTROY_DEV: >>> + ret = vduse_destroy_dev(arg); >>> + break; >>> + default: >>> + ret = -EINVAL; >>> + break; >>> + } >>> + mutex_unlock(&vduse_lock); >>> + >>> + return ret; >>> +} >>> + >>> +static const struct file_operations vduse_fops = { >>> + .owner = THIS_MODULE, >>> + .unlocked_ioctl = vduse_ioctl, >>> + .compat_ioctl = compat_ptr_ioctl, >>> + .llseek = noop_llseek, >>> +}; >>> + >>> +static struct miscdevice vduse_misc = { >>> + .fops = &vduse_fops, >>> + .minor = MISC_DYNAMIC_MINOR, >>> + .name = "vduse", >>> +}; >>> + >>> +static void vduse_parent_release(struct device *dev) >>> +{ >>> +} >>> + >>> +static struct device vduse_parent = { >>> + .init_name = "vduse", >>> + .release = vduse_parent_release, >>> +}; >>> + >>> +static struct vdpa_parent_dev parent_dev; >>> + >>> +static int vduse_dev_add_vdpa(struct vduse_dev *dev, const char *name) >>> +{ >>> + struct vduse_vdpa *vdev = dev->vdev; >>> + int ret; >>> + >>> + if (vdev) >>> + return -EEXIST; >>> + >>> + vdev = vdpa_alloc_device(struct vduse_vdpa, vdpa, NULL, >>> + &vduse_vdpa_config_ops, >>> + dev->vq_num, name, true); >>> + if (!vdev) >>> + return -ENOMEM; >>> + >>> + vdev->dev = dev; >>> + vdev->vdpa.dev.dma_mask = &vdev->vdpa.dev.coherent_dma_mask; >>> + ret = dma_set_mask_and_coherent(&vdev->vdpa.dev, DMA_BIT_MASK(64)); >>> + if (ret) >>> + goto err; >>> + >>> + set_dma_ops(&vdev->vdpa.dev, &vduse_dev_dma_ops); >>> + vdev->vdpa.dma_dev = &vdev->vdpa.dev; >>> + vdev->vdpa.pdev = &parent_dev; >>> + >>> + ret = _vdpa_register_device(&vdev->vdpa); >>> + if (ret) >>> + goto err; >>> + >>> + dev->vdev = vdev; >>> + >>> + return 0; >>> +err: >>> + put_device(&vdev->vdpa.dev); >>> + return ret; >>> +} >>> + >>> +static struct vdpa_device *vdpa_dev_add(struct vdpa_parent_dev *pdev, >>> + const char *name, u32 device_id, >>> + struct nlattr **attrs) >>> +{ >>> + u32 vduse_id; >>> + struct vduse_dev *dev; >>> + int ret = -EINVAL; >>> + >>> + if (!attrs[VDPA_ATTR_BACKEND_ID]) >>> + return ERR_PTR(-EINVAL); >>> + >>> + mutex_lock(&vduse_lock); >>> + vduse_id = nla_get_u32(attrs[VDPA_ATTR_BACKEND_ID]); >> >> I wonder why not using name here? >> > Do you mean use the same name for both backend and frontend? If so, we > need to add a name for vduse device or replace id with name to > identify a vduse device. Which way do you prefer? I think if we can do it in name, it's better not introduce any other thing like "id". It will complicate the management software. > >> And it looks to me it would be easier if we create a char device per >> vduse. This makes the device addressing more robust than passing id >> silently among processes. >> > It's OK to me. > >>> + dev = vduse_find_dev(vduse_id); >>> + if (!dev) >>> + goto unlock; >>> + >>> + if (dev->device_id != device_id) >>> + goto unlock; >>> + >>> + ret = vduse_dev_add_vdpa(dev, name); >>> +unlock: >>> + mutex_unlock(&vduse_lock); >>> + if (ret) >>> + return ERR_PTR(ret); >>> + >>> + return &dev->vdev->vdpa; >>> +} >>> + >>> +static void vdpa_dev_del(struct vdpa_parent_dev *pdev, struct vdpa_device *dev) >>> +{ >>> + _vdpa_unregister_device(dev); >>> +} >>> + >>> +static const struct vdpa_dev_ops vdpa_dev_parent_ops = { >>> + .dev_add = vdpa_dev_add, >>> + .dev_del = vdpa_dev_del >>> +}; >>> + >>> +static struct virtio_device_id id_table[] = { >>> + { VIRTIO_DEV_ANY_ID, VIRTIO_DEV_ANY_ID }, >>> + { 0 }, >>> +}; >>> + >>> +static struct vdpa_parent_dev parent_dev = { >>> + .device = &vduse_parent, >>> + .id_table = id_table, >>> + .ops = &vdpa_dev_parent_ops, >>> +}; >>> + >>> +static int vduse_parentdev_init(void) >>> +{ >>> + int ret; >>> + >>> + ret = device_register(&vduse_parent); >>> + if (ret) >>> + return ret; >>> + >>> + ret = vdpa_parentdev_register(&parent_dev); >>> + if (ret) >>> + goto err; >>> + >>> + return 0; >>> +err: >>> + device_unregister(&vduse_parent); >>> + return ret; >>> +} >>> + >>> +static void vduse_parentdev_exit(void) >>> +{ >>> + vdpa_parentdev_unregister(&parent_dev); >>> + device_unregister(&vduse_parent); >>> +} >>> + >>> +static int vduse_init(void) >>> +{ >>> + int ret; >>> + >>> + ret = misc_register(&vduse_misc); >>> + if (ret) >>> + return ret; >>> + >>> + ret = -ENOMEM; >>> + vduse_vdpa_wq = alloc_workqueue("vduse-vdpa", WQ_UNBOUND, 1); >>> + if (!vduse_vdpa_wq) >>> + goto err_vdpa_wq; >>> + >>> + ret = vduse_virqfd_init(); >>> + if (ret) >>> + goto err_irqfd; >>> + >>> + ret = vduse_parentdev_init(); >>> + if (ret) >>> + goto err_parentdev; >>> + >>> + return 0; >>> +err_parentdev: >>> + vduse_virqfd_exit(); >>> +err_irqfd: >>> + destroy_workqueue(vduse_vdpa_wq); >>> +err_vdpa_wq: >>> + misc_deregister(&vduse_misc); >>> + return ret; >>> +} >>> +module_init(vduse_init); >>> + >>> +static void vduse_exit(void) >>> +{ >>> + misc_deregister(&vduse_misc); >>> + destroy_workqueue(vduse_vdpa_wq); >>> + vduse_virqfd_exit(); >>> + vduse_parentdev_exit(); >>> +} >>> +module_exit(vduse_exit); >>> + >>> +MODULE_VERSION(DRV_VERSION); >>> +MODULE_LICENSE(DRV_LICENSE); >>> +MODULE_AUTHOR(DRV_AUTHOR); >>> +MODULE_DESCRIPTION(DRV_DESC); >>> diff --git a/include/uapi/linux/vdpa.h b/include/uapi/linux/vdpa.h >>> index bba8b83a94b5..a7a841e5ffc7 100644 >>> --- a/include/uapi/linux/vdpa.h >>> +++ b/include/uapi/linux/vdpa.h >>> @@ -33,6 +33,7 @@ enum vdpa_attr { >>> VDPA_ATTR_DEV_VENDOR_ID, /* u32 */ >>> VDPA_ATTR_DEV_MAX_VQS, /* u32 */ >>> VDPA_ATTR_DEV_MAX_VQ_SIZE, /* u16 */ >>> + VDPA_ATTR_BACKEND_ID, /* u32 */ >> >> As discussed, this needs more thought. But if necessary, we need a >> separate patch for this. >> > OK. > >>> /* new attributes must be added above here */ >>> VDPA_ATTR_MAX, >>> diff --git a/include/uapi/linux/vduse.h b/include/uapi/linux/vduse.h >>> new file mode 100644 >>> index 000000000000..9fb555ddcfbd >>> --- /dev/null >>> +++ b/include/uapi/linux/vduse.h >>> @@ -0,0 +1,125 @@ >>> +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ >>> +#ifndef _UAPI_VDUSE_H_ >>> +#define _UAPI_VDUSE_H_ >>> + >>> +#include >>> + >>> +/* the control messages definition for read/write */ >>> + >>> +#define VDUSE_CONFIG_DATA_LEN 256 >>> + >>> +enum vduse_req_type { >>> + VDUSE_SET_VQ_NUM, >>> + VDUSE_SET_VQ_ADDR, >>> + VDUSE_SET_VQ_READY, >>> + VDUSE_GET_VQ_READY, >>> + VDUSE_SET_VQ_STATE, >>> + VDUSE_GET_VQ_STATE, >>> + VDUSE_SET_FEATURES, >>> + VDUSE_GET_FEATURES, >>> + VDUSE_SET_STATUS, >>> + VDUSE_GET_STATUS, >>> + VDUSE_SET_CONFIG, >>> + VDUSE_GET_CONFIG, >>> + VDUSE_UPDATE_IOTLB, >>> +}; >>> + >>> +struct vduse_vq_num { >>> + __u32 index; >>> + __u32 num; >>> +}; >>> + >>> +struct vduse_vq_addr { >>> + __u32 index; >>> + __u64 desc_addr; >>> + __u64 driver_addr; >>> + __u64 device_addr; >>> +}; >>> + >>> +struct vduse_vq_ready { >>> + __u32 index; >>> + __u8 ready; >>> +}; >>> + >>> +struct vduse_vq_state { >>> + __u32 index; >>> + __u16 avail_idx; >>> +}; >>> + >>> +struct vduse_dev_config_data { >>> + __u32 offset; >>> + __u32 len; >>> + __u8 data[VDUSE_CONFIG_DATA_LEN]; >> >> This no guarantee that 256 is sufficient here. >> > If the size is larger than 256, we can try to split the original request. Fine, then we need document here or in the doc. > >>> +}; >>> + >>> +struct vduse_iova_range { >>> + __u64 start; >>> + __u64 last; >>> +}; >>> + >>> +struct vduse_dev_request { >>> + __u32 type; /* request type */ >>> + __u32 unique; /* request id */ >>> + __u32 flags; /* request flags */ >> >> Seems unused in this series. >> > This is for future use. So let's use pad or other name. > >>> + __u32 size; /* the payload size */ >> >> Unused. >> > Will remove it. > >>> + union { >>> + struct vduse_vq_num vq_num; /* virtqueue num */ >>> + struct vduse_vq_addr vq_addr; /* virtqueue address */ >>> + struct vduse_vq_ready vq_ready; /* virtqueue ready status */ >>> + struct vduse_vq_state vq_state; /* virtqueue state */ >>> + struct vduse_dev_config_data config; /* virtio device config space */ >>> + struct vduse_iova_range iova; /* iova range for updating */ >>> + __u64 features; /* virtio features */ >>> + __u8 status; /* device status */ >> >> Let's add some padding for future extensions. >> > Is sizeof(vduse_dev_config_data) ok? Or char[1024]? 1024 seems too large, 128 or 256 looks better. > >>> + }; >>> +}; >>> + >>> +struct vduse_dev_response { >>> + __u32 unique; /* corresponding request id */ >> >> Let's use request id. >> > Fine. > >>> + __s32 result; /* the result of request */ >> >> Let's use macro or enum to define the success and failure value. >> > Will do it. > >>> + union { >>> + struct vduse_vq_ready vq_ready; /* virtqueue ready status */ >>> + struct vduse_vq_state vq_state; /* virtqueue state */ >>> + struct vduse_dev_config_data config; /* virtio device config space */ >>> + __u64 features; /* virtio features */ >>> + __u8 status; /* device status */ >>> + }; >>> +}; >>> + >>> +/* ioctls */ >>> + >>> +struct vduse_dev_config { >>> + __u32 id; /* vduse device id */ >>> + __u32 vendor_id; /* virtio vendor id */ >>> + __u32 device_id; /* virtio device id */ >>> + __u64 bounce_size; /* bounce buffer size for iommu */ >>> + __u16 vq_num; /* the number of virtqueues */ >>> + __u16 vq_size_max; /* the max size of virtqueue */ >>> + __u32 vq_align; /* the allocation alignment of virtqueue's metadata */ >>> +}; >>> + >>> +struct vduse_iotlb_entry { >>> + __u64 offset; /* the mmap offset on fd */ >>> + __u64 start; /* start of the IOVA range */ >>> + __u64 last; /* last of the IOVA range */ >>> +#define VDUSE_ACCESS_RO 0x1 >>> +#define VDUSE_ACCESS_WO 0x2 >>> +#define VDUSE_ACCESS_RW 0x3 >>> + __u8 perm; /* access permission of this range */ >>> +}; >>> + >>> +struct vduse_vq_eventfd { >>> + __u32 index; /* virtqueue index */ >>> + __u32 fd; /* eventfd */ >> >> Any reason for not using int here? >> > Will use __s32 instead. Let's use "int" here, so -1 can be used for de-assigning the eventfd. > >>> +}; >>> + >>> +#define VDUSE_BASE 0x81 >>> + >>> +#define VDUSE_CREATE_DEV _IOW(VDUSE_BASE, 0x01, struct vduse_dev_config) >>> +#define VDUSE_DESTROY_DEV _IO(VDUSE_BASE, 0x02) >>> + >>> +#define VDUSE_IOTLB_GET_FD _IOWR(VDUSE_BASE, 0x04, struct vduse_iotlb_entry) >>> +#define VDUSE_VQ_SETUP_KICKFD _IOW(VDUSE_BASE, 0x05, struct vduse_vq_eventfd) >>> +#define VDUSE_VQ_SETUP_IRQFD _IOW(VDUSE_BASE, 0x06, struct vduse_vq_eventfd) >> >> Better with documentation to explain those ioctls. >> > Will do it. > > Thanks, > Yongji Thanks > From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-15.1 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,NICE_REPLY_A,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED, USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 43F78C433E0 for ; Thu, 28 Jan 2021 04:27:47 +0000 (UTC) Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7BEF064DD8 for ; Thu, 28 Jan 2021 04:27:46 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7BEF064DD8 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=virtualization-bounces@lists.linux-foundation.org Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id DF9E987363; Thu, 28 Jan 2021 04:27:45 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id UBzuhflP4YO7; Thu, 28 Jan 2021 04:27:41 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by hemlock.osuosl.org (Postfix) with ESMTP id 16550872B8; Thu, 28 Jan 2021 04:27:41 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id D7563C08A1; Thu, 28 Jan 2021 04:27:40 +0000 (UTC) Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 482BCC013A for ; Thu, 28 Jan 2021 04:27:39 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 2BEE38735B for ; Thu, 28 Jan 2021 04:27:39 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id PzesOdj+SWZR for ; Thu, 28 Jan 2021 04:27:34 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by hemlock.osuosl.org (Postfix) with ESMTPS id E665D872B8 for ; Thu, 28 Jan 2021 04:27:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1611808052; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vUxRrabFkJIbvDaiO8CDnSK+Dd50UKrEOmGMcEjNtrU=; b=UFtaT7it8uIAbnXb1TnMzhj6JqxaULc4TTT0/UiKFPKhYeIVEBDR8JgO3T/ukLF0dg00dF KP1Ok4KEcJ225tLSk7JTZ5goODiKtJ5ww82O8tfKCNtcOiP9203g5ISmaJJhd2RIIEH+sF XsMn93ZoV0Q9Y/yw9NvZ8koQkoTVCIk= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-391-2BOwtVvrO5iC0mHi8O9-DQ-1; Wed, 27 Jan 2021 23:27:30 -0500 X-MC-Unique: 2BOwtVvrO5iC0mHi8O9-DQ-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 8E37D107ACE4; Thu, 28 Jan 2021 04:27:27 +0000 (UTC) Received: from [10.72.12.167] (ovpn-12-167.pek2.redhat.com [10.72.12.167]) by smtp.corp.redhat.com (Postfix) with ESMTP id A34A71002382; Thu, 28 Jan 2021 04:27:15 +0000 (UTC) Subject: Re: [RFC v3 08/11] vduse: Introduce VDUSE - vDPA Device in Userspace To: Yongji Xie References: <20210119045920.447-1-xieyongji@bytedance.com> <20210119050756.600-1-xieyongji@bytedance.com> <20210119050756.600-2-xieyongji@bytedance.com> <1bb3af07-0ec2-109c-d6d1-83d4d1f410c3@redhat.com> From: Jason Wang Message-ID: Date: Thu, 28 Jan 2021 12:27:14 +0800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.10.0 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Cc: axboe@kernel.dk, Jonathan Corbet , kvm@vger.kernel.org, "Michael S. Tsirkin" , linux-aio@kvack.org, netdev@vger.kernel.org, Randy Dunlap , Matthew Wilcox , virtualization@lists.linux-foundation.org, Christoph Hellwig , Bob Liu , bcrl@kvack.org, viro@zeniv.linux.org.uk, Stefan Hajnoczi , linux-fsdevel@vger.kernel.org X-BeenThere: virtualization@lists.linux-foundation.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Linux virtualization List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: base64 Content-Type: text/plain; charset="utf-8"; Format="flowed" Errors-To: virtualization-bounces@lists.linux-foundation.org Sender: "Virtualization" Ck9uIDIwMjEvMS8yNyDkuIvljYg0OjUwLCBZb25namkgWGllIHdyb3RlOgo+ICAgT24gVHVlLCBK YW4gMjYsIDIwMjEgYXQgNDowOSBQTSBKYXNvbiBXYW5nIDxqYXNvd2FuZ0ByZWRoYXQuY29tPiB3 cm90ZToKPj4KPj4gT24gMjAyMS8xLzE5IOS4i+WNiDE6MDcsIFhpZSBZb25namkgd3JvdGU6Cj4+ PiBUaGlzIFZEVVNFIGRyaXZlciBlbmFibGVzIGltcGxlbWVudGluZyB2RFBBIGRldmljZXMgaW4g dXNlcnNwYWNlLgo+Pj4gQm90aCBjb250cm9sIHBhdGggYW5kIGRhdGEgcGF0aCBvZiB2RFBBIGRl dmljZXMgd2lsbCBiZSBhYmxlIHRvCj4+PiBiZSBoYW5kbGVkIGluIHVzZXJzcGFjZS4KPj4+Cj4+ PiBJbiB0aGUgY29udHJvbCBwYXRoLCB0aGUgVkRVU0UgZHJpdmVyIHdpbGwgbWFrZSB1c2Ugb2Yg bWVzc2FnZQo+Pj4gbWVjaG5pc20gdG8gZm9yd2FyZCB0aGUgY29uZmlnIG9wZXJhdGlvbiBmcm9t IHZkcGEgYnVzIGRyaXZlcgo+Pj4gdG8gdXNlcnNwYWNlLiBVc2Vyc3BhY2UgY2FuIHVzZSByZWFk KCkvd3JpdGUoKSB0byByZWNlaXZlL3JlcGx5Cj4+PiB0aG9zZSBjb250cm9sIG1lc3NhZ2VzLgo+ Pj4KPj4+IEluIHRoZSBkYXRhIHBhdGgsIFZEVVNFX0lPVExCX0dFVF9GRCBpb2N0bCB3aWxsIGJl IHVzZWQgdG8gZ2V0Cj4+PiB0aGUgZmlsZSBkZXNjcmlwdG9ycyByZWZlcnJpbmcgdG8gdkRQQSBk ZXZpY2UncyBpb3ZhIHJlZ2lvbnMuIFRoZW4KPj4+IHVzZXJzcGFjZSBjYW4gdXNlIG1tYXAoKSB0 byBhY2Nlc3MgdGhvc2UgaW92YSByZWdpb25zLiBCZXNpZGVzLAo+Pj4gdGhlIGV2ZW50ZmQgbWVj aGFuaXNtIGlzIHVzZWQgdG8gdHJpZ2dlciBpbnRlcnJ1cHQgY2FsbGJhY2tzIGFuZAo+Pj4gcmVj ZWl2ZSB2aXJ0cXVldWUga2lja3MgaW4gdXNlcnNwYWNlLgo+Pj4KPj4+IFNpZ25lZC1vZmYtYnk6 IFhpZSBZb25namkgPHhpZXlvbmdqaUBieXRlZGFuY2UuY29tPgo+Pj4gLS0tCj4+PiAgICBEb2N1 bWVudGF0aW9uL2RyaXZlci1hcGkvdmR1c2UucnN0ICAgICAgICAgICAgICAgICB8ICAgODUgKysK Pj4+ICAgIERvY3VtZW50YXRpb24vdXNlcnNwYWNlLWFwaS9pb2N0bC9pb2N0bC1udW1iZXIucnN0 IHwgICAgMSArCj4+PiAgICBkcml2ZXJzL3ZkcGEvS2NvbmZpZyAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICB8ICAgIDcgKwo+Pj4gICAgZHJpdmVycy92ZHBhL01ha2VmaWxlICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgfCAgICAxICsKPj4+ICAgIGRyaXZlcnMvdmRwYS92ZHBhX3Vz ZXIvTWFrZWZpbGUgICAgICAgICAgICAgICAgICAgIHwgICAgNSArCj4+PiAgICBkcml2ZXJzL3Zk cGEvdmRwYV91c2VyL2V2ZW50ZmQuYyAgICAgICAgICAgICAgICAgICB8ICAyMjEgKysrKwo+Pj4g ICAgZHJpdmVycy92ZHBhL3ZkcGFfdXNlci9ldmVudGZkLmggICAgICAgICAgICAgICAgICAgfCAg IDQ4ICsKPj4+ICAgIGRyaXZlcnMvdmRwYS92ZHBhX3VzZXIvaW92YV9kb21haW4uYyAgICAgICAg ICAgICAgIHwgIDQyNiArKysrKysrCj4+PiAgICBkcml2ZXJzL3ZkcGEvdmRwYV91c2VyL2lvdmFf ZG9tYWluLmggICAgICAgICAgICAgICB8ICAgNjggKysKPj4+ICAgIGRyaXZlcnMvdmRwYS92ZHBh X3VzZXIvdmR1c2UuaCAgICAgICAgICAgICAgICAgICAgIHwgICA2MiArCj4+PiAgICBkcml2ZXJz L3ZkcGEvdmRwYV91c2VyL3ZkdXNlX2Rldi5jICAgICAgICAgICAgICAgICB8IDEyMTcgKysrKysr KysrKysrKysrKysrKysKPj4+ICAgIGluY2x1ZGUvdWFwaS9saW51eC92ZHBhLmggICAgICAgICAg ICAgICAgICAgICAgICAgIHwgICAgMSArCj4+PiAgICBpbmNsdWRlL3VhcGkvbGludXgvdmR1c2Uu aCAgICAgICAgICAgICAgICAgICAgICAgICB8ICAxMjUgKysKPj4+ICAgIDEzIGZpbGVzIGNoYW5n ZWQsIDIyNjcgaW5zZXJ0aW9ucygrKQo+Pj4gICAgY3JlYXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50 YXRpb24vZHJpdmVyLWFwaS92ZHVzZS5yc3QKPj4+ICAgIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2 ZXJzL3ZkcGEvdmRwYV91c2VyL01ha2VmaWxlCj4+PiAgICBjcmVhdGUgbW9kZSAxMDA2NDQgZHJp dmVycy92ZHBhL3ZkcGFfdXNlci9ldmVudGZkLmMKPj4+ICAgIGNyZWF0ZSBtb2RlIDEwMDY0NCBk cml2ZXJzL3ZkcGEvdmRwYV91c2VyL2V2ZW50ZmQuaAo+Pj4gICAgY3JlYXRlIG1vZGUgMTAwNjQ0 IGRyaXZlcnMvdmRwYS92ZHBhX3VzZXIvaW92YV9kb21haW4uYwo+Pj4gICAgY3JlYXRlIG1vZGUg MTAwNjQ0IGRyaXZlcnMvdmRwYS92ZHBhX3VzZXIvaW92YV9kb21haW4uaAo+Pj4gICAgY3JlYXRl IG1vZGUgMTAwNjQ0IGRyaXZlcnMvdmRwYS92ZHBhX3VzZXIvdmR1c2UuaAo+Pj4gICAgY3JlYXRl IG1vZGUgMTAwNjQ0IGRyaXZlcnMvdmRwYS92ZHBhX3VzZXIvdmR1c2VfZGV2LmMKPj4+ICAgIGNy ZWF0ZSBtb2RlIDEwMDY0NCBpbmNsdWRlL3VhcGkvbGludXgvdmR1c2UuaAo+Pj4KPj4+IGRpZmYg LS1naXQgYS9Eb2N1bWVudGF0aW9uL2RyaXZlci1hcGkvdmR1c2UucnN0IGIvRG9jdW1lbnRhdGlv bi9kcml2ZXItYXBpL3ZkdXNlLnJzdAo+Pj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPj4+IGluZGV4 IDAwMDAwMDAwMDAwMC4uOTQxOGE3ZjY2NDZiCj4+PiAtLS0gL2Rldi9udWxsCj4+PiArKysgYi9E b2N1bWVudGF0aW9uL2RyaXZlci1hcGkvdmR1c2UucnN0Cj4+PiBAQCAtMCwwICsxLDg1IEBACj4+ PiArPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQo+Pj4gK1ZEVVNFIC0gInZEUEEg RGV2aWNlIGluIFVzZXJzcGFjZSIKPj4+ICs9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09 PT09Cj4+PiArCj4+PiArdkRQQSAodmlydGlvIGRhdGEgcGF0aCBhY2NlbGVyYXRpb24pIGRldmlj ZSBpcyBhIGRldmljZSB0aGF0IHVzZXMgYQo+Pj4gK2RhdGFwYXRoIHdoaWNoIGNvbXBsaWVzIHdp dGggdGhlIHZpcnRpbyBzcGVjaWZpY2F0aW9ucyB3aXRoIHZlbmRvcgo+Pj4gK3NwZWNpZmljIGNv bnRyb2wgcGF0aC4gdkRQQSBkZXZpY2VzIGNhbiBiZSBib3RoIHBoeXNpY2FsbHkgbG9jYXRlZCBv bgo+Pj4gK3RoZSBoYXJkd2FyZSBvciBlbXVsYXRlZCBieSBzb2Z0d2FyZS4gVkRVU0UgaXMgYSBm cmFtZXdvcmsgdGhhdCBtYWtlcyBpdAo+Pj4gK3Bvc3NpYmxlIHRvIGltcGxlbWVudCBzb2Z0d2Fy ZS1lbXVsYXRlZCB2RFBBIGRldmljZXMgaW4gdXNlcnNwYWNlLgo+Pj4gKwo+Pj4gK0hvdyBWRFVT RSB3b3Jrcwo+Pj4gKy0tLS0tLS0tLS0tLQo+Pj4gK0VhY2ggdXNlcnNwYWNlIHZEUEEgZGV2aWNl IGlzIGNyZWF0ZWQgYnkgdGhlIFZEVVNFX0NSRUFURV9ERVYgaW9jdGwgb24KPj4+ICt0aGUgVkRV U0UgY2hhcmFjdGVyIGRldmljZSAoL2Rldi92ZHVzZSkuIFRoZW4gYSBmaWxlIGRlc2NyaXB0b3Ig cG9pbnRpbmcKPj4+ICt0byB0aGUgbmV3IHJlc291cmNlcyB3aWxsIGJlIHJldHVybmVkLCB3aGlj aCBjYW4gYmUgdXNlZCB0byBpbXBsZW1lbnQgdGhlCj4+PiArdXNlcnNwYWNlIHZEUEEgZGV2aWNl J3MgY29udHJvbCBwYXRoIGFuZCBkYXRhIHBhdGguCj4+PiArCj4+PiArVG8gaW1wbGVtZW50IGNv bnRyb2wgcGF0aCwgdGhlIHJlYWQvd3JpdGUgb3BlcmF0aW9ucyB0byB0aGUgZmlsZSBkZXNjcmlw dG9yCj4+PiArd2lsbCBiZSB1c2VkIHRvIHJlY2VpdmUvcmVwbHkgdGhlIGNvbnRyb2wgbWVzc2Fn ZXMgZnJvbS90byBWRFVTRSBkcml2ZXIuCj4+Cj4+IEl0J3MgYmV0dGVyIHRvIGRvY3VtZW50IHRo ZSBwcm90b2NvbCBoZXJlLiBFLmcgdGhlIGlkZW50aWZpZXIgc3R1ZmZzLgo+Pgo+IEkgaGF2ZSBk b2N1bWVudGVkIHRob3NlIHN0dWZmcyBpbiBpbmNsdWRlL3VhcGkvbGludXgvdmR1c2UuaCwgaXMg aXQKPiBPSz8gT3IgYWRkIHNvbWV0aGluZyBsaWtlICJQbGVhc2Ugc2VlIGluY2x1ZGUvdWFwaS9s aW51eC92ZHVzZS5oIGZvcgo+IGRldGFpbHMuIgoKCkl0IG1pZ2h0IGJlIGJldHRlciBpZiB3ZSBh ZGQgc29tZSB1c2Vyc3BhY2Ugc2FtcGxlIGNvZGUgdG8gZGVtb25zdHJhdGUgCmhvdyB0aGUgcHJv dG9jb2wgd29yay4KCgo+Cj4+PiArVGhvc2UgY29udHJvbCBtZXNzYWdlcyBhcmUgbW9zdGx5IGJh c2VkIG9uIHRoZSB2ZHBhX2NvbmZpZ19vcHMgd2hpY2ggZGVmaW5lcwo+Pj4gK2EgdW5pZmllZCBp bnRlcmZhY2UgdG8gY29udHJvbCBkaWZmZXJlbnQgdHlwZXMgb2YgdkRQQSBkZXZpY2UuCj4+PiAr Cj4+PiArVGhlIGZvbGxvd2luZyB0eXBlcyBvZiBtZXNzYWdlcyBhcmUgcHJvdmlkZWQgYnkgdGhl IFZEVVNFIGZyYW1ld29yayBub3c6Cj4+PiArCj4+PiArLSBWRFVTRV9TRVRfVlFfQUREUjogU2V0 IHRoZSBhZGRyZXNzZXMgb2YgdGhlIGRpZmZlcmVudCBhc3BlY3RzIG9mIHZpcnRxdWV1ZS4KPj4K Pj4gIlNldCB0aGUgdnJpbmcgYWRkcmVzcyBvZiBhIHZpcnRxdWV1ZSIgbWlnaHQgYmUgYmV0dGVy IGhlcmUuCj4+Cj4gT0suCj4KPj4+ICsKPj4+ICstIFZEVVNFX1NFVF9WUV9OVU06IFNldCB0aGUg c2l6ZSBvZiB2aXJ0cXVldWUKPj4+ICsKPj4+ICstIFZEVVNFX1NFVF9WUV9SRUFEWTogU2V0IHJl YWR5IHN0YXR1cyBvZiB2aXJ0cXVldWUKPj4+ICsKPj4+ICstIFZEVVNFX0dFVF9WUV9SRUFEWTog R2V0IHJlYWR5IHN0YXR1cyBvZiB2aXJ0cXVldWUKPj4+ICsKPj4+ICstIFZEVVNFX1NFVF9WUV9T VEFURTogU2V0IHRoZSBzdGF0ZSAobGFzdF9hdmFpbF9pZHgpIGZvciB2aXJ0cXVldWUKPj4+ICsK Pj4+ICstIFZEVVNFX0dFVF9WUV9TVEFURTogR2V0IHRoZSBzdGF0ZSAobGFzdF9hdmFpbF9pZHgp IGZvciB2aXJ0cXVldWUKPj4KPj4gSXQncyBiZXR0ZXIgbm90IHRvIG1lbnRpb24gbGF5b3V0IHNw ZWNpZmljIHN0dWZmcyBoZXJlIChsYXN0X2F2YWlsX2lkeCkuCj4+IENvbnNpZGVyIHdlIHNob3Vs ZCBzdXBwb3J0IHBhY2tlZCB2aXJ0cXVldWUgaW4gdGhlIGZ1dHVyZS4KPj4KPiBJIHNlZS4KPgo+ Pj4gKwo+Pj4gKy0gVkRVU0VfU0VUX0ZFQVRVUkVTOiBTZXQgdmlydGlvIGZlYXR1cmVzIHN1cHBv cnRlZCBieSB0aGUgZHJpdmVyCj4+PiArCj4+PiArLSBWRFVTRV9HRVRfRkVBVFVSRVM6IEdldCB2 aXJ0aW8gZmVhdHVyZXMgc3VwcG9ydGVkIGJ5IHRoZSBkZXZpY2UKPj4+ICsKPj4+ICstIFZEVVNF X1NFVF9TVEFUVVM6IFNldCB0aGUgZGV2aWNlIHN0YXR1cwo+Pj4gKwo+Pj4gKy0gVkRVU0VfR0VU X1NUQVRVUzogR2V0IHRoZSBkZXZpY2Ugc3RhdHVzCj4+PiArCj4+PiArLSBWRFVTRV9TRVRfQ09O RklHOiBXcml0ZSB0byBkZXZpY2Ugc3BlY2lmaWMgY29uZmlndXJhdGlvbiBzcGFjZQo+Pj4gKwo+ Pj4gKy0gVkRVU0VfR0VUX0NPTkZJRzogUmVhZCBmcm9tIGRldmljZSBzcGVjaWZpYyBjb25maWd1 cmF0aW9uIHNwYWNlCj4+PiArCj4+PiArLSBWRFVTRV9VUERBVEVfSU9UTEI6IE5vdGlmeSB1c2Vy c3BhY2UgdG8gdXBkYXRlIHRoZSBtZW1vcnkgbWFwcGluZyBpbiBkZXZpY2UgSU9UTEIKPj4+ICsK Pj4+ICtQbGVhc2Ugc2VlIGluY2x1ZGUvbGludXgvdmRwYS5oIGZvciBkZXRhaWxzLgo+Pj4gKwo+ Pj4gK0luIHRoZSBkYXRhIHBhdGgsIHZEUEEgZGV2aWNlJ3MgaW92YSByZWdpb25zIHdpbGwgYmUg bWFwcGVkIGludG8gdXNlcnNwYWNlIHdpdGgKPj4+ICt0aGUgaGVscCBvZiBWRFVTRV9JT1RMQl9H RVRfRkQgaW9jdGwgb24gdGhlIHVzZXJzcGFjZSB2RFBBIGRldmljZSBmZDoKPj4+ICsKPj4+ICst IFZEVVNFX0lPVExCX0dFVF9GRDogZ2V0IHRoZSBmaWxlIGRlc2NyaXB0b3IgdG8gaW92YSByZWdp b24uIFVzZXJzcGFjZSBjYW4KPj4+ICsgIGFjY2VzcyB0aGlzIGlvdmEgcmVnaW9uIGJ5IHBhc3Np bmcgdGhlIGZkIHRvIG1tYXAoMikuCj4+PiArCj4+PiArQmVzaWRlcywgdGhlIGV2ZW50ZmQgbWVj aGFuaXNtIGlzIHVzZWQgdG8gdHJpZ2dlciBpbnRlcnJ1cHQgY2FsbGJhY2tzIGFuZAo+Pj4gK3Jl Y2VpdmUgdmlydHF1ZXVlIGtpY2tzIGluIHVzZXJzcGFjZS4gVGhlIGZvbGxvd2luZyBpb2N0bHMg b24gdGhlIHVzZXJzcGFjZQo+Pj4gK3ZEUEEgZGV2aWNlIGZkIGFyZSBwcm92aWRlZCB0byBzdXBw b3J0IHRoYXQ6Cj4+PiArCj4+PiArLSBWRFVTRV9WUV9TRVRVUF9LSUNLRkQ6IHNldCB0aGUga2lj a2ZkIGZvciB2aXJ0cXVldWUsIHRoaXMgZXZlbnRmZCBpcyB1c2VkCj4+PiArICBieSBWRFVTRSBk cml2ZXIgdG8gbm90aWZ5IHVzZXJzcGFjZSB0byBjb25zdW1lIHRoZSB2cmluZy4KPj4+ICsKPj4+ ICstIFZEVVNFX1ZRX1NFVFVQX0lSUUZEOiBzZXQgdGhlIGlycWZkIGZvciB2aXJ0cXVldWUsIHRo aXMgZXZlbnRmZCBpcyB1c2VkCj4+PiArICBieSB1c2Vyc3BhY2UgdG8gbm90aWZ5IFZEVVNFIGRy aXZlciB0byB0cmlnZ2VyIGludGVycnVwdCBjYWxsYmFja3MuCj4+PiArCj4+PiArTU1VLWJhc2Vk IElPTU1VIERyaXZlcgo+Pj4gKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KPj4+ICtJbiB2aXJ0aW8t dmRwYSBjYXNlLCBWRFVTRSBmcmFtZXdvcmsgaW1wbGVtZW50cyBhIE1NVS1iYXNlZCBvbi1jaGlw IElPTU1VCj4+PiArZHJpdmVyIHRvIHN1cHBvcnQgbWFwcGluZyB0aGUga2VybmVsIGRtYSBidWZm ZXIgaW50byB0aGUgdXNlcnNwYWNlIGlvdmEKPj4+ICtyZWdpb24gZHluYW1pY2FsbHkuCj4+PiAr Cj4+PiArVGhlIGJhc2ljIGlkZWEgYmVoaW5kIHRoaXMgZHJpdmVyIGlzIHRyZWF0aW5nIE1NVSAo VkEtPlBBKSBhcyBJT01NVSAoSU9WQS0+UEEpLgo+Pj4gK1RoZSBkcml2ZXIgd2lsbCBzZXQgdXAg TU1VIG1hcHBpbmcgaW5zdGVhZCBvZiBJT01NVSBtYXBwaW5nIGZvciB0aGUgRE1BIHRyYW5zZmVy Cj4+PiArc28gdGhhdCB0aGUgdXNlcnNwYWNlIHByb2Nlc3MgaXMgYWJsZSB0byB1c2UgaXRzIHZp cnR1YWwgYWRkcmVzcyB0byBhY2Nlc3MKPj4+ICt0aGUgZG1hIGJ1ZmZlciBpbiBrZXJuZWwuCj4+ PiArCj4+PiArQW5kIHRvIGF2b2lkIHNlY3VyaXR5IGlzc3VlLCBhIGJvdW5jZS1idWZmZXJpbmcg bWVjaGFuaXNtIGlzIGludHJvZHVjZWQgdG8KPj4+ICtwcmV2ZW50IHVzZXJzcGFjZSBhY2Nlc3Np bmcgdGhlIG9yaWdpbmFsIGJ1ZmZlciBkaXJlY3RseSB3aGljaCBtYXkgY29udGFpbiBvdGhlcgo+ Pj4gK2tlcm5lbCBkYXRhLiBEdXJpbmcgdGhlIG1hcHBpbmcsIHVubWFwcGluZywgdGhlIGRyaXZl ciB3aWxsIGNvcHkgdGhlIGRhdGEgZnJvbQo+Pj4gK3RoZSBvcmlnaW5hbCBidWZmZXIgdG8gdGhl IGJvdW5jZSBidWZmZXIgYW5kIGJhY2ssIGRlcGVuZGluZyBvbiB0aGUgZGlyZWN0aW9uIG9mCj4+ PiArdGhlIHRyYW5zZmVyLiBBbmQgdGhlIGJvdW5jZS1idWZmZXIgYWRkcmVzc2VzIHdpbGwgYmUg bWFwcGVkIGludG8gdGhlIHVzZXIgYWRkcmVzcwo+Pj4gK3NwYWNlIGluc3RlYWQgb2YgdGhlIG9y aWdpbmFsIG9uZS4KPj4+IGRpZmYgLS1naXQgYS9Eb2N1bWVudGF0aW9uL3VzZXJzcGFjZS1hcGkv aW9jdGwvaW9jdGwtbnVtYmVyLnJzdCBiL0RvY3VtZW50YXRpb24vdXNlcnNwYWNlLWFwaS9pb2N0 bC9pb2N0bC1udW1iZXIucnN0Cj4+PiBpbmRleCBhNGM3NWEyOGM4MzkuLjcxNzIyZTZmOGYyMyAx MDA2NDQKPj4+IC0tLSBhL0RvY3VtZW50YXRpb24vdXNlcnNwYWNlLWFwaS9pb2N0bC9pb2N0bC1u dW1iZXIucnN0Cj4+PiArKysgYi9Eb2N1bWVudGF0aW9uL3VzZXJzcGFjZS1hcGkvaW9jdGwvaW9j dGwtbnVtYmVyLnJzdAo+Pj4gQEAgLTMwMCw2ICszMDAsNyBAQCBDb2RlICBTZXEjICAgIEluY2x1 ZGUgRmlsZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBDb21tZW50 cwo+Pj4gICAgJ3onICAgMTAtNEYgIGRyaXZlcnMvczM5MC9jcnlwdG8vemNyeXB0X2FwaS5oICAg ICAgICAgICAgICAgICAgICAgICAgY29uZmxpY3QhCj4+PiAgICAnfCcgICAwMC03RiAgbGludXgv bWVkaWEuaAo+Pj4gICAgMHg4MCAgMDAtMUYgIGxpbnV4L2ZiLmgKPj4+ICsweDgxICAwMC0xRiAg bGludXgvdmR1c2UuaAo+Pj4gICAgMHg4OSAgMDAtMDYgIGFyY2gveDg2L2luY2x1ZGUvYXNtL3Nv Y2tpb3MuaAo+Pj4gICAgMHg4OSAgMEItREYgIGxpbnV4L3NvY2tpb3MuaAo+Pj4gICAgMHg4OSAg RTAtRUYgIGxpbnV4L3NvY2tpb3MuaCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgU0lPQ1BST1RPUFJJVkFURSByYW5nZQo+Pj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvdmRw YS9LY29uZmlnIGIvZHJpdmVycy92ZHBhL0tjb25maWcKPj4+IGluZGV4IDRiZTdiZTM5YmUyNi4u NjY3MzU0MzA5YmY0IDEwMDY0NAo+Pj4gLS0tIGEvZHJpdmVycy92ZHBhL0tjb25maWcKPj4+ICsr KyBiL2RyaXZlcnMvdmRwYS9LY29uZmlnCj4+PiBAQCAtMjEsNiArMjEsMTMgQEAgY29uZmlnIFZE UEFfU0lNCj4+PiAgICAgICAgICB0byBSWC4gVGhpcyBkZXZpY2UgaXMgdXNlZCBmb3IgdGVzdGlu ZywgcHJvdG90eXBpbmcgYW5kCj4+PiAgICAgICAgICBkZXZlbG9wbWVudCBvZiB2RFBBLgo+Pj4K Pj4+ICtjb25maWcgVkRQQV9VU0VSCj4+PiArICAgICB0cmlzdGF0ZSAiVkRVU0UgKHZEUEEgRGV2 aWNlIGluIFVzZXJzcGFjZSkgc3VwcG9ydCIKPj4+ICsgICAgIGRlcGVuZHMgb24gRVZFTlRGRCAm JiBNTVUgJiYgSEFTX0RNQQo+Pgo+PiBOZWVkIHNlbGVjdCBWSE9TVF9JT1RMQi4KPj4KPiBPSy4K Pgo+Pj4gKyAgICAgaGVscAo+Pj4gKyAgICAgICBXaXRoIFZEVVNFIGl0IGlzIHBvc3NpYmxlIHRv IGVtdWxhdGUgYSB2RFBBIERldmljZQo+Pj4gKyAgICAgICBpbiBhIHVzZXJzcGFjZSBwcm9ncmFt Lgo+Pj4gKwo+Pj4gICAgY29uZmlnIElGQ1ZGCj4+PiAgICAgICAgdHJpc3RhdGUgIkludGVsIElG QyBWRiB2RFBBIGRyaXZlciIKPj4+ICAgICAgICBkZXBlbmRzIG9uIFBDSV9NU0kKPj4+IGRpZmYg LS1naXQgYS9kcml2ZXJzL3ZkcGEvTWFrZWZpbGUgYi9kcml2ZXJzL3ZkcGEvTWFrZWZpbGUKPj4+ IGluZGV4IGQxNjBlOWI2M2E2Ni4uNjZlOTc3NzhhZDAzIDEwMDY0NAo+Pj4gLS0tIGEvZHJpdmVy cy92ZHBhL01ha2VmaWxlCj4+PiArKysgYi9kcml2ZXJzL3ZkcGEvTWFrZWZpbGUKPj4+IEBAIC0x LDUgKzEsNiBAQAo+Pj4gICAgIyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMAo+Pj4g ICAgb2JqLSQoQ09ORklHX1ZEUEEpICs9IHZkcGEubwo+Pj4gICAgb2JqLSQoQ09ORklHX1ZEUEFf U0lNKSArPSB2ZHBhX3NpbS8KPj4+ICtvYmotJChDT05GSUdfVkRQQV9VU0VSKSArPSB2ZHBhX3Vz ZXIvCj4+PiAgICBvYmotJChDT05GSUdfSUZDVkYpICAgICs9IGlmY3ZmLwo+Pj4gICAgb2JqLSQo Q09ORklHX01MWDVfVkRQQSkgKz0gbWx4NS8KPj4+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3ZkcGEv dmRwYV91c2VyL01ha2VmaWxlIGIvZHJpdmVycy92ZHBhL3ZkcGFfdXNlci9NYWtlZmlsZQo+Pj4g bmV3IGZpbGUgbW9kZSAxMDA2NDQKPj4+IGluZGV4IDAwMDAwMDAwMDAwMC4uYjc2NDVlMzY5OTJi Cj4+PiAtLS0gL2Rldi9udWxsCj4+PiArKysgYi9kcml2ZXJzL3ZkcGEvdmRwYV91c2VyL01ha2Vm aWxlCj4+PiBAQCAtMCwwICsxLDUgQEAKPj4+ICsjIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBH UEwtMi4wCj4+PiArCj4+PiArdmR1c2UteSA6PSB2ZHVzZV9kZXYubyBpb3ZhX2RvbWFpbi5vIGV2 ZW50ZmQubwo+Pj4gKwo+Pj4gK29iai0kKENPTkZJR19WRFBBX1VTRVIpICs9IHZkdXNlLm8KPj4+ IGRpZmYgLS1naXQgYS9kcml2ZXJzL3ZkcGEvdmRwYV91c2VyL2V2ZW50ZmQuYyBiL2RyaXZlcnMv dmRwYS92ZHBhX3VzZXIvZXZlbnRmZC5jCj4+PiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+Pj4gaW5k ZXggMDAwMDAwMDAwMDAwLi5kYmZmZGRiMDg5MDgKPj4+IC0tLSAvZGV2L251bGwKPj4+ICsrKyBi L2RyaXZlcnMvdmRwYS92ZHBhX3VzZXIvZXZlbnRmZC5jCj4+PiBAQCAtMCwwICsxLDIyMSBAQAo+ Pj4gKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wLW9ubHkKPj4+ICsvKgo+Pj4g KyAqIEV2ZW50ZmQgc3VwcG9ydCBmb3IgVkRVU0UKPj4+ICsgKgo+Pj4gKyAqIENvcHlyaWdodCAo QykgMjAyMCBCeXRlZGFuY2UgSW5jLiBhbmQvb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCByaWdodHMg cmVzZXJ2ZWQuCj4+PiArICoKPj4+ICsgKiBBdXRob3I6IFhpZSBZb25namkgPHhpZXlvbmdqaUBi eXRlZGFuY2UuY29tPgo+Pj4gKyAqCj4+PiArICovCj4+PiArCj4+PiArI2luY2x1ZGUgPGxpbnV4 L2V2ZW50ZmQuaD4KPj4+ICsjaW5jbHVkZSA8bGludXgvcG9sbC5oPgo+Pj4gKyNpbmNsdWRlIDxs aW51eC93YWl0Lmg+Cj4+PiArI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4KPj4+ICsjaW5jbHVkZSA8 bGludXgvZmlsZS5oPgo+Pj4gKyNpbmNsdWRlIDx1YXBpL2xpbnV4L3ZkdXNlLmg+Cj4+PiArCj4+ PiArI2luY2x1ZGUgImV2ZW50ZmQuaCIKPj4+ICsKPj4+ICtzdGF0aWMgc3RydWN0IHdvcmtxdWV1 ZV9zdHJ1Y3QgKnZkdXNlX2lycWZkX2NsZWFudXBfd3E7Cj4+PiArCj4+PiArc3RhdGljIHZvaWQg dmR1c2VfdmlycWZkX3NodXRkb3duKHN0cnVjdCB3b3JrX3N0cnVjdCAqd29yaykKPj4+ICt7Cj4+ PiArICAgICB1NjQgY250Owo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX3ZpcnFmZCAqdmlycWZkID0g Y29udGFpbmVyX29mKHdvcmssCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIHN0cnVjdCB2ZHVzZV92aXJxZmQsIHNodXRkb3duKTsKPj4+ICsKPj4+ICsgICAgIGV2ZW50 ZmRfY3R4X3JlbW92ZV93YWl0X3F1ZXVlKHZpcnFmZC0+Y3R4LCAmdmlycWZkLT53YWl0LCAmY250 KTsKPj4+ICsgICAgIGZsdXNoX3dvcmsoJnZpcnFmZC0+aW5qZWN0KTsKPj4+ICsgICAgIGV2ZW50 ZmRfY3R4X3B1dCh2aXJxZmQtPmN0eCk7Cj4+PiArICAgICBrZnJlZSh2aXJxZmQpOwo+Pj4gK30K Pj4+ICsKPj4+ICtzdGF0aWMgdm9pZCB2ZHVzZV92aXJxZmRfaW5qZWN0KHN0cnVjdCB3b3JrX3N0 cnVjdCAqd29yaykKPj4+ICt7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfdmlycWZkICp2aXJxZmQg PSBjb250YWluZXJfb2Yod29yaywKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgc3RydWN0IHZkdXNlX3ZpcnFmZCwgaW5qZWN0KTsKPj4+ICsgICAgIHN0cnVjdCB2ZHVz ZV92aXJ0cXVldWUgKnZxID0gdmlycWZkLT52cTsKPj4+ICsKPj4+ICsgICAgIHNwaW5fbG9ja19p cnEoJnZxLT5pcnFfbG9jayk7Cj4+PiArICAgICBpZiAodnEtPnJlYWR5ICYmIHZxLT5jYikKPj4+ ICsgICAgICAgICAgICAgdnEtPmNiKHZxLT5wcml2YXRlKTsKPj4+ICsgICAgIHNwaW5fdW5sb2Nr X2lycSgmdnEtPmlycV9sb2NrKTsKPj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIHZvaWQgdmlycWZk X2RlYWN0aXZhdGUoc3RydWN0IHZkdXNlX3ZpcnFmZCAqdmlycWZkKQo+Pj4gK3sKPj4+ICsgICAg IHF1ZXVlX3dvcmsodmR1c2VfaXJxZmRfY2xlYW51cF93cSwgJnZpcnFmZC0+c2h1dGRvd24pOwo+ Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgaW50IHZkdXNlX3ZpcnFmZF93YWtldXAod2FpdF9xdWV1 ZV9lbnRyeV90ICp3YWl0LCB1bnNpZ25lZCBpbnQgbW9kZSwKPj4+ICsgICAgICAgICAgICAgICAg ICAgICAgICAgICAgIGludCBzeW5jLCB2b2lkICprZXkpCj4+PiArewo+Pj4gKyAgICAgc3RydWN0 IHZkdXNlX3ZpcnFmZCAqdmlycWZkID0gY29udGFpbmVyX29mKHdhaXQsIHN0cnVjdCB2ZHVzZV92 aXJxZmQsIHdhaXQpOwo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX3ZpcnRxdWV1ZSAqdnEgPSB2aXJx ZmQtPnZxOwo+Pj4gKwo+Pj4gKyAgICAgX19wb2xsX3QgZmxhZ3MgPSBrZXlfdG9fcG9sbChrZXkp Owo+Pj4gKwo+Pj4gKyAgICAgaWYgKGZsYWdzICYgRVBPTExJTikKPj4+ICsgICAgICAgICAgICAg c2NoZWR1bGVfd29yaygmdmlycWZkLT5pbmplY3QpOwo+Pj4gKwo+Pj4gKyAgICAgaWYgKGZsYWdz ICYgRVBPTExIVVApIHsKPj4+ICsgICAgICAgICAgICAgc3Bpbl9sb2NrKCZ2cS0+aXJxX2xvY2sp Owo+Pj4gKyAgICAgICAgICAgICBpZiAodnEtPnZpcnFmZCA9PSB2aXJxZmQpIHsKPj4+ICsgICAg ICAgICAgICAgICAgICAgICB2cS0+dmlycWZkID0gTlVMTDsKPj4+ICsgICAgICAgICAgICAgICAg ICAgICB2aXJxZmRfZGVhY3RpdmF0ZSh2aXJxZmQpOwo+Pj4gKyAgICAgICAgICAgICB9Cj4+PiAr ICAgICAgICAgICAgIHNwaW5fdW5sb2NrKCZ2cS0+aXJxX2xvY2spOwo+Pj4gKyAgICAgfQo+Pj4g Kwo+Pj4gKyAgICAgcmV0dXJuIDA7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyB2b2lkIHZkdXNl X3ZpcnFmZF9wdGFibGVfcXVldWVfcHJvYyhzdHJ1Y3QgZmlsZSAqZmlsZSwKPj4+ICsgICAgICAg ICAgICAgICAgICAgICB3YWl0X3F1ZXVlX2hlYWRfdCAqd3FoLCBwb2xsX3RhYmxlICpwdCkKPj4+ ICt7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfdmlycWZkICp2aXJxZmQgPSBjb250YWluZXJfb2Yo cHQsIHN0cnVjdCB2ZHVzZV92aXJxZmQsIHB0KTsKPj4+ICsKPj4+ICsgICAgIGFkZF93YWl0X3F1 ZXVlKHdxaCwgJnZpcnFmZC0+d2FpdCk7Cj4+PiArfQo+Pj4gKwo+Pj4gK2ludCB2ZHVzZV92aXJx ZmRfc2V0dXAoc3RydWN0IHZkdXNlX2RldiAqZGV2LAo+Pj4gKyAgICAgICAgICAgICAgICAgICAg IHN0cnVjdCB2ZHVzZV92cV9ldmVudGZkICpldmVudGZkKQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVj dCB2ZHVzZV92aXJxZmQgKnZpcnFmZDsKPj4+ICsgICAgIHN0cnVjdCBmZCBpcnFmZDsKPj4+ICsg ICAgIHN0cnVjdCBldmVudGZkX2N0eCAqY3R4Owo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX3ZpcnRx dWV1ZSAqdnE7Cj4+PiArICAgICBfX3BvbGxfdCBldmVudHM7Cj4+PiArICAgICBpbnQgcmV0Owo+ Pj4gKwo+Pj4gKyAgICAgaWYgKGV2ZW50ZmQtPmluZGV4ID49IGRldi0+dnFfbnVtKQo+Pj4gKyAg ICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsKPj4+ICsKPj4+ICsgICAgIHZxID0gJmRldi0+dnFz W2V2ZW50ZmQtPmluZGV4XTsKPj4+ICsgICAgIHZpcnFmZCA9IGt6YWxsb2Moc2l6ZW9mKCp2aXJx ZmQpLCBHRlBfS0VSTkVMKTsKPj4+ICsgICAgIGlmICghdmlycWZkKQo+Pj4gKyAgICAgICAgICAg ICByZXR1cm4gLUVOT01FTTsKPj4+ICsKPj4+ICsgICAgIElOSVRfV09SSygmdmlycWZkLT5zaHV0 ZG93biwgdmR1c2VfdmlycWZkX3NodXRkb3duKTsKPj4+ICsgICAgIElOSVRfV09SSygmdmlycWZk LT5pbmplY3QsIHZkdXNlX3ZpcnFmZF9pbmplY3QpOwo+Pj4gKwo+Pj4gKyAgICAgcmV0ID0gLUVC QURGOwo+Pj4gKyAgICAgaXJxZmQgPSBmZGdldChldmVudGZkLT5mZCk7Cj4+PiArICAgICBpZiAo IWlycWZkLmZpbGUpCj4+PiArICAgICAgICAgICAgIGdvdG8gZXJyX2ZkOwo+Pj4gKwo+Pj4gKyAg ICAgY3R4ID0gZXZlbnRmZF9jdHhfZmlsZWdldChpcnFmZC5maWxlKTsKPj4+ICsgICAgIGlmIChJ U19FUlIoY3R4KSkgewo+Pj4gKyAgICAgICAgICAgICByZXQgPSBQVFJfRVJSKGN0eCk7Cj4+PiAr ICAgICAgICAgICAgIGdvdG8gZXJyX2N0eDsKPj4+ICsgICAgIH0KPj4+ICsKPj4+ICsgICAgIHZp cnFmZC0+dnEgPSB2cTsKPj4+ICsgICAgIHZpcnFmZC0+Y3R4ID0gY3R4Owo+Pj4gKyAgICAgc3Bp bl9sb2NrKCZ2cS0+aXJxX2xvY2spOwo+Pj4gKyAgICAgaWYgKHZxLT52aXJxZmQpCj4+PiArICAg ICAgICAgICAgIHZpcnFmZF9kZWFjdGl2YXRlKHZpcnFmZCk7Cj4+PiArICAgICB2cS0+dmlycWZk ID0gdmlycWZkOwo+Pj4gKyAgICAgc3Bpbl91bmxvY2soJnZxLT5pcnFfbG9jayk7Cj4+PiArCj4+ PiArICAgICBpbml0X3dhaXRxdWV1ZV9mdW5jX2VudHJ5KCZ2aXJxZmQtPndhaXQsIHZkdXNlX3Zp cnFmZF93YWtldXApOwo+Pj4gKyAgICAgaW5pdF9wb2xsX2Z1bmNwdHIoJnZpcnFmZC0+cHQsIHZk dXNlX3ZpcnFmZF9wdGFibGVfcXVldWVfcHJvYyk7Cj4+PiArCj4+PiArICAgICBldmVudHMgPSB2 ZnNfcG9sbChpcnFmZC5maWxlLCAmdmlycWZkLT5wdCk7Cj4+PiArCj4+PiArICAgICAvKgo+Pj4g KyAgICAgICogQ2hlY2sgaWYgdGhlcmUgd2FzIGFuIGV2ZW50IGFscmVhZHkgcGVuZGluZyBvbiB0 aGUgZXZlbnRmZAo+Pj4gKyAgICAgICogYmVmb3JlIHdlIHJlZ2lzdGVyZWQgYW5kIHRyaWdnZXIg aXQgYXMgaWYgd2UgZGlkbid0IG1pc3MgaXQuCj4+PiArICAgICAgKi8KPj4+ICsgICAgIGlmIChl dmVudHMgJiBFUE9MTElOKQo+Pj4gKyAgICAgICAgICAgICBzY2hlZHVsZV93b3JrKCZ2aXJxZmQt PmluamVjdCk7Cj4+PiArCj4+PiArICAgICBmZHB1dChpcnFmZCk7Cj4+PiArCj4+PiArICAgICBy ZXR1cm4gMDsKPj4+ICtlcnJfY3R4Ogo+Pj4gKyAgICAgZmRwdXQoaXJxZmQpOwo+Pj4gK2Vycl9m ZDoKPj4+ICsgICAgIGtmcmVlKHZpcnFmZCk7Cj4+PiArICAgICByZXR1cm4gcmV0Owo+Pj4gK30K Pj4+ICsKPj4+ICt2b2lkIHZkdXNlX3ZpcnFmZF9yZWxlYXNlKHN0cnVjdCB2ZHVzZV9kZXYgKmRl dikKPj4+ICt7Cj4+PiArICAgICBpbnQgaTsKPj4+ICsKPj4+ICsgICAgIGZvciAoaSA9IDA7IGkg PCBkZXYtPnZxX251bTsgaSsrKSB7Cj4+PiArICAgICAgICAgICAgIHN0cnVjdCB2ZHVzZV92aXJ0 cXVldWUgKnZxID0gJmRldi0+dnFzW2ldOwo+Pj4gKwo+Pj4gKyAgICAgICAgICAgICBzcGluX2xv Y2soJnZxLT5pcnFfbG9jayk7Cj4+PiArICAgICAgICAgICAgIGlmICh2cS0+dmlycWZkKSB7Cj4+ PiArICAgICAgICAgICAgICAgICAgICAgdmlycWZkX2RlYWN0aXZhdGUodnEtPnZpcnFmZCk7Cj4+ PiArICAgICAgICAgICAgICAgICAgICAgdnEtPnZpcnFmZCA9IE5VTEw7Cj4+PiArICAgICAgICAg ICAgIH0KPj4+ICsgICAgICAgICAgICAgc3Bpbl91bmxvY2soJnZxLT5pcnFfbG9jayk7Cj4+PiAr ICAgICB9Cj4+PiArICAgICBmbHVzaF93b3JrcXVldWUodmR1c2VfaXJxZmRfY2xlYW51cF93cSk7 Cj4+PiArfQo+Pj4gKwo+Pj4gK2ludCB2ZHVzZV92aXJxZmRfaW5pdCh2b2lkKQo+Pj4gK3sKPj4+ ICsgICAgIHZkdXNlX2lycWZkX2NsZWFudXBfd3EgPSBhbGxvY193b3JrcXVldWUoInZkdXNlLWly cWZkLWNsZWFudXAiLAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIFdRX1VOQk9VTkQsIDApOwo+Pj4gKyAgICAgaWYgKCF2ZHVzZV9pcnFmZF9jbGVhbnVw X3dxKQo+Pj4gKyAgICAgICAgICAgICByZXR1cm4gLUVOT01FTTsKPj4+ICsKPj4+ICsgICAgIHJl dHVybiAwOwo+Pj4gK30KPj4+ICsKPj4+ICt2b2lkIHZkdXNlX3ZpcnFmZF9leGl0KHZvaWQpCj4+ PiArewo+Pj4gKyAgICAgZGVzdHJveV93b3JrcXVldWUodmR1c2VfaXJxZmRfY2xlYW51cF93cSk7 Cj4+PiArfQo+Pj4gKwo+Pj4gK3ZvaWQgdmR1c2VfdnFfa2ljayhzdHJ1Y3QgdmR1c2VfdmlydHF1 ZXVlICp2cSkKPj4+ICt7Cj4+PiArICAgICBzcGluX2xvY2soJnZxLT5raWNrX2xvY2spOwo+Pj4g KyAgICAgaWYgKHZxLT5yZWFkeSAmJiB2cS0+a2lja2ZkKQo+Pj4gKyAgICAgICAgICAgICBldmVu dGZkX3NpZ25hbCh2cS0+a2lja2ZkLCAxKTsKPj4+ICsgICAgIHNwaW5fdW5sb2NrKCZ2cS0+a2lj a19sb2NrKTsKPj4+ICt9Cj4+PiArCj4+PiAraW50IHZkdXNlX2tpY2tmZF9zZXR1cChzdHJ1Y3Qg dmR1c2VfZGV2ICpkZXYsCj4+PiArICAgICAgICAgICAgICAgICAgICAgc3RydWN0IHZkdXNlX3Zx X2V2ZW50ZmQgKmV2ZW50ZmQpCj4+PiArewo+Pj4gKyAgICAgc3RydWN0IGV2ZW50ZmRfY3R4ICpj dHg7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfdmlydHF1ZXVlICp2cTsKPj4+ICsKPj4+ICsgICAg IGlmIChldmVudGZkLT5pbmRleCA+PSBkZXYtPnZxX251bSkKPj4+ICsgICAgICAgICAgICAgcmV0 dXJuIC1FSU5WQUw7Cj4+PiArCj4+PiArICAgICB2cSA9ICZkZXYtPnZxc1tldmVudGZkLT5pbmRl eF07Cj4+PiArICAgICBjdHggPSBldmVudGZkX2N0eF9mZGdldChldmVudGZkLT5mZCk7Cj4+PiAr ICAgICBpZiAoSVNfRVJSKGN0eCkpCj4+PiArICAgICAgICAgICAgIHJldHVybiBQVFJfRVJSKGN0 eCk7Cj4+PiArCj4+PiArICAgICBzcGluX2xvY2soJnZxLT5raWNrX2xvY2spOwo+Pj4gKyAgICAg aWYgKHZxLT5raWNrZmQpCj4+PiArICAgICAgICAgICAgIGV2ZW50ZmRfY3R4X3B1dCh2cS0+a2lj a2ZkKTsKPj4+ICsgICAgIHZxLT5raWNrZmQgPSBjdHg7Cj4+PiArICAgICBzcGluX3VubG9jaygm dnEtPmtpY2tfbG9jayk7Cj4+PiArCj4+PiArICAgICByZXR1cm4gMDsKPj4+ICt9Cj4+PiArCj4+ PiArdm9pZCB2ZHVzZV9raWNrZmRfcmVsZWFzZShzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYpCj4+PiAr ewo+Pj4gKyAgICAgaW50IGk7Cj4+PiArCj4+PiArICAgICBmb3IgKGkgPSAwOyBpIDwgZGV2LT52 cV9udW07IGkrKykgewo+Pj4gKyAgICAgICAgICAgICBzdHJ1Y3QgdmR1c2VfdmlydHF1ZXVlICp2 cSA9ICZkZXYtPnZxc1tpXTsKPj4+ICsKPj4+ICsgICAgICAgICAgICAgc3Bpbl9sb2NrKCZ2cS0+ a2lja19sb2NrKTsKPj4+ICsgICAgICAgICAgICAgaWYgKHZxLT5raWNrZmQpIHsKPj4+ICsgICAg ICAgICAgICAgICAgICAgICBldmVudGZkX2N0eF9wdXQodnEtPmtpY2tmZCk7Cj4+PiArICAgICAg ICAgICAgICAgICAgICAgdnEtPmtpY2tmZCA9IE5VTEw7Cj4+PiArICAgICAgICAgICAgIH0KPj4+ ICsgICAgICAgICAgICAgc3Bpbl91bmxvY2soJnZxLT5raWNrX2xvY2spOwo+Pj4gKyAgICAgfQo+ Pj4gK30KPj4+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3ZkcGEvdmRwYV91c2VyL2V2ZW50ZmQuaCBi L2RyaXZlcnMvdmRwYS92ZHBhX3VzZXIvZXZlbnRmZC5oCj4+PiBuZXcgZmlsZSBtb2RlIDEwMDY0 NAo+Pj4gaW5kZXggMDAwMDAwMDAwMDAwLi4xNDI2OWZmMjdmNDcKPj4+IC0tLSAvZGV2L251bGwK Pj4+ICsrKyBiL2RyaXZlcnMvdmRwYS92ZHBhX3VzZXIvZXZlbnRmZC5oCj4+PiBAQCAtMCwwICsx LDQ4IEBACj4+PiArLyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAtb25seSAqLwo+ Pj4gKy8qCj4+PiArICogRXZlbnRmZCBzdXBwb3J0IGZvciBWRFVTRQo+Pj4gKyAqCj4+PiArICog Q29weXJpZ2h0IChDKSAyMDIwIEJ5dGVkYW5jZSBJbmMuIGFuZC9vciBpdHMgYWZmaWxpYXRlcy4g QWxsIHJpZ2h0cyByZXNlcnZlZC4KPj4+ICsgKgo+Pj4gKyAqIEF1dGhvcjogWGllIFlvbmdqaSA8 eGlleW9uZ2ppQGJ5dGVkYW5jZS5jb20+Cj4+PiArICoKPj4+ICsgKi8KPj4+ICsKPj4+ICsjaWZu ZGVmIF9WRFVTRV9FVkVOVEZEX0gKPj4+ICsjZGVmaW5lIF9WRFVTRV9FVkVOVEZEX0gKPj4+ICsK Pj4+ICsjaW5jbHVkZSA8bGludXgvZXZlbnRmZC5oPgo+Pj4gKyNpbmNsdWRlIDxsaW51eC9wb2xs Lmg+Cj4+PiArI2luY2x1ZGUgPGxpbnV4L3dhaXQuaD4KPj4+ICsjaW5jbHVkZSA8dWFwaS9saW51 eC92ZHVzZS5oPgo+Pj4gKwo+Pj4gKyNpbmNsdWRlICJ2ZHVzZS5oIgo+Pj4gKwo+Pj4gK3N0cnVj dCB2ZHVzZV9kZXY7Cj4+PiArCj4+PiArc3RydWN0IHZkdXNlX3ZpcnFmZCB7Cj4+PiArICAgICBz dHJ1Y3QgZXZlbnRmZF9jdHggKmN0eDsKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV92aXJ0cXVldWUg KnZxOwo+Pj4gKyAgICAgc3RydWN0IHdvcmtfc3RydWN0IGluamVjdDsKPj4+ICsgICAgIHN0cnVj dCB3b3JrX3N0cnVjdCBzaHV0ZG93bjsKPj4+ICsgICAgIHdhaXRfcXVldWVfZW50cnlfdCB3YWl0 Owo+Pj4gKyAgICAgcG9sbF90YWJsZSBwdDsKPj4+ICt9Owo+Pj4gKwo+Pj4gK2ludCB2ZHVzZV92 aXJxZmRfc2V0dXAoc3RydWN0IHZkdXNlX2RldiAqZGV2LAo+Pj4gKyAgICAgICAgICAgICAgICAg ICAgIHN0cnVjdCB2ZHVzZV92cV9ldmVudGZkICpldmVudGZkKTsKPj4+ICsKPj4+ICt2b2lkIHZk dXNlX3ZpcnFmZF9yZWxlYXNlKHN0cnVjdCB2ZHVzZV9kZXYgKmRldik7Cj4+PiArCj4+PiAraW50 IHZkdXNlX3ZpcnFmZF9pbml0KHZvaWQpOwo+Pj4gKwo+Pj4gK3ZvaWQgdmR1c2VfdmlycWZkX2V4 aXQodm9pZCk7Cj4+PiArCj4+PiArdm9pZCB2ZHVzZV92cV9raWNrKHN0cnVjdCB2ZHVzZV92aXJ0 cXVldWUgKnZxKTsKPj4+ICsKPj4+ICtpbnQgdmR1c2Vfa2lja2ZkX3NldHVwKHN0cnVjdCB2ZHVz ZV9kZXYgKmRldiwKPj4+ICsgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3QgdmR1c2VfdnFfZXZl bnRmZCAqZXZlbnRmZCk7Cj4+PiArCj4+PiArdm9pZCB2ZHVzZV9raWNrZmRfcmVsZWFzZShzdHJ1 Y3QgdmR1c2VfZGV2ICpkZXYpOwo+Pj4gKwo+Pj4gKyNlbmRpZiAvKiBfVkRVU0VfRVZFTlRGRF9I ICovCj4+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy92ZHBhL3ZkcGFfdXNlci9pb3ZhX2RvbWFpbi5j IGIvZHJpdmVycy92ZHBhL3ZkcGFfdXNlci9pb3ZhX2RvbWFpbi5jCj4+PiBuZXcgZmlsZSBtb2Rl IDEwMDY0NAo+Pj4gaW5kZXggMDAwMDAwMDAwMDAwLi5jZGZlZjhlOWY5ZDYKPj4+IC0tLSAvZGV2 L251bGwKPj4+ICsrKyBiL2RyaXZlcnMvdmRwYS92ZHBhX3VzZXIvaW92YV9kb21haW4uYwo+Pj4g QEAgLTAsMCArMSw0MjYgQEAKPj4+ICsvLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIu MC1vbmx5Cj4+PiArLyoKPj4+ICsgKiBNTVUtYmFzZWQgSU9NTVUgaW1wbGVtZW50YXRpb24KPj4+ ICsgKgo+Pj4gKyAqIENvcHlyaWdodCAoQykgMjAyMCBCeXRlZGFuY2UgSW5jLiBhbmQvb3IgaXRz IGFmZmlsaWF0ZXMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCj4+PiArICoKPj4+ICsgKiBBdXRob3I6 IFhpZSBZb25namkgPHhpZXlvbmdqaUBieXRlZGFuY2UuY29tPgo+Pj4gKyAqCj4+PiArICovCj4+ PiArCj4+PiArI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4KPj4+ICsjaW5jbHVkZSA8bGludXgvZmls ZS5oPgo+Pj4gKyNpbmNsdWRlIDxsaW51eC9hbm9uX2lub2Rlcy5oPgo+Pj4gKwo+Pj4gKyNpbmNs dWRlICJpb3ZhX2RvbWFpbi5oIgo+Pj4gKwo+Pj4gKyNkZWZpbmUgSU9WQV9TVEFSVF9QRk4gMQo+ Pj4gKyNkZWZpbmUgSU9WQV9BTExPQ19PUkRFUiAxMgo+Pj4gKyNkZWZpbmUgSU9WQV9BTExPQ19T SVpFICgxIDw8IElPVkFfQUxMT0NfT1JERVIpCj4+Cj4+IENhbiB0aGlzIHdvcmsgZm9yIGFsbCBh cmNocyAoZS5nIHdoeSBub3QgdXNlIFBBR0VfU0laRSk/Cj4+Cj4gSXQgY2FuIHdvcmsgZm9yIGFs bCBhcmNocy4gVXNlIElPVkFfQUxMT0NfU0laRSBtaWdodCBzYXZlIHNvbWUgc3BhY2UKPiBpbiBz b21lIGNhc2VzL2FyY2hzIChlLmcuIFBBR0VfU0laRSA9IDY0Sykgd2hlbiB3ZSBoYXZlIGxvdHMg b2YKPiBzbWFsbC1zaXplIEkvT3MuCgoKT0ssIGlmIEkgdW5kZXJzdGFuZCBjb3JyZWN0bHksIHNv IHlvdSB3YW50IHRvIHNoYXJlIHBhZ2VzIGFtb25nIHRob3NlIApzbWFsbCBJL09zLgoKCj4KPj4+ ICsKPj4+ICsjZGVmaW5lIENPTlNJU1RFTlRfRE1BX1NJWkUgKDEwMjQgKiAxMDI0ICogMTAyNCkK Pj4+ICsKPj4+ICtzdGF0aWMgaW5saW5lIHN0cnVjdCBwYWdlICoKPj4+ICt2ZHVzZV9kb21haW5f Z2V0X2JvdW5jZV9wYWdlKHN0cnVjdCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluLAo+Pj4gKyAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5zaWduZWQgbG9uZyBpb3ZhKQo+Pj4gK3sKPj4+ ICsgICAgIHVuc2lnbmVkIGxvbmcgaW5kZXggPSBpb3ZhID4+IFBBR0VfU0hJRlQ7Cj4+PiArCj4+ PiArICAgICByZXR1cm4gZG9tYWluLT5ib3VuY2VfcGFnZXNbaW5kZXhdOwo+Pj4gK30KPj4+ICsK Pj4+ICtzdGF0aWMgaW5saW5lIHZvaWQKPj4+ICt2ZHVzZV9kb21haW5fc2V0X2JvdW5jZV9wYWdl KHN0cnVjdCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluLAo+Pj4gKyAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgdW5zaWduZWQgbG9uZyBpb3ZhLCBzdHJ1Y3QgcGFnZSAqcGFnZSkKPj4+ICt7 Cj4+PiArICAgICB1bnNpZ25lZCBsb25nIGluZGV4ID0gaW92YSA+PiBQQUdFX1NISUZUOwo+Pj4g Kwo+Pj4gKyAgICAgZG9tYWluLT5ib3VuY2VfcGFnZXNbaW5kZXhdID0gcGFnZTsKPj4+ICt9Cj4+ PiArCj4+PiArc3RhdGljIHN0cnVjdCB2ZHVzZV9pb3ZhX21hcCAqCj4+PiArdmR1c2VfZG9tYWlu X2FsbG9jX2lvdmFfbWFwKHN0cnVjdCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluLAo+Pj4gKyAg ICAgICAgICAgICAgICAgICAgIHVuc2lnbmVkIGxvbmcgaW92YSwgdW5zaWduZWQgbG9uZyBvcmln LAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgIHNpemVfdCBzaXplLCBlbnVtIGRtYV9kYXRhX2Rp cmVjdGlvbiBkaXIpCj4+PiArewo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX2lvdmFfbWFwICptYXA7 Cj4+PiArCj4+PiArICAgICBtYXAgPSBremFsbG9jKHNpemVvZihzdHJ1Y3QgdmR1c2VfaW92YV9t YXApLCBHRlBfQVRPTUlDKTsKPj4+ICsgICAgIGlmICghbWFwKQo+Pj4gKyAgICAgICAgICAgICBy ZXR1cm4gTlVMTDsKPj4+ICsKPj4+ICsgICAgIG1hcC0+aW92YS5zdGFydCA9IGlvdmE7Cj4+PiAr ICAgICBtYXAtPmlvdmEubGFzdCA9IGlvdmEgKyBzaXplIC0gMTsKPj4+ICsgICAgIG1hcC0+b3Jp ZyA9IG9yaWc7Cj4+PiArICAgICBtYXAtPnNpemUgPSBzaXplOwo+Pj4gKyAgICAgbWFwLT5kaXIg PSBkaXI7Cj4+PiArCj4+PiArICAgICByZXR1cm4gbWFwOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0 aWMgc3RydWN0IHBhZ2UgKgo+Pj4gK3ZkdXNlX2RvbWFpbl9nZXRfbWFwcGluZ19wYWdlKHN0cnVj dCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluLAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgdW5zaWduZWQgbG9uZyBpb3ZhKQo+Pj4gK3sKPj4+ICsgICAgIHVuc2lnbmVkIGxvbmcg c3RhcnQgPSBpb3ZhICYgUEFHRV9NQVNLOwo+Pj4gKyAgICAgdW5zaWduZWQgbG9uZyBsYXN0ID0g c3RhcnQgKyBQQUdFX1NJWkUgLSAxOwo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX2lvdmFfbWFwICpt YXA7Cj4+PiArICAgICBzdHJ1Y3QgaW50ZXJ2YWxfdHJlZV9ub2RlICpub2RlOwo+Pj4gKyAgICAg c3RydWN0IHBhZ2UgKnBhZ2UgPSBOVUxMOwo+Pj4gKwo+Pj4gKyAgICAgc3Bpbl9sb2NrKCZkb21h aW4tPm1hcF9sb2NrKTsKPj4+ICsgICAgIG5vZGUgPSBpbnRlcnZhbF90cmVlX2l0ZXJfZmlyc3Qo JmRvbWFpbi0+bWFwcGluZ3MsIHN0YXJ0LCBsYXN0KTsKPj4+ICsgICAgIGlmICghbm9kZSkKPj4+ ICsgICAgICAgICAgICAgZ290byBvdXQ7Cj4+PiArCj4+PiArICAgICBtYXAgPSBjb250YWluZXJf b2Yobm9kZSwgc3RydWN0IHZkdXNlX2lvdmFfbWFwLCBpb3ZhKTsKPj4+ICsgICAgIHBhZ2UgPSB2 aXJ0X3RvX3BhZ2UobWFwLT5vcmlnICsgaW92YSAtIG1hcC0+aW92YS5zdGFydCk7Cj4+PiArICAg ICBnZXRfcGFnZShwYWdlKTsKPj4+ICtvdXQ6Cj4+PiArICAgICBzcGluX3VubG9jaygmZG9tYWlu LT5tYXBfbG9jayk7Cj4+PiArCj4+PiArICAgICByZXR1cm4gcGFnZTsKPj4+ICt9Cj4+PiArCj4+ PiArc3RhdGljIHN0cnVjdCBwYWdlICoKPj4+ICt2ZHVzZV9kb21haW5fYWxsb2NfYm91bmNlX3Bh Z2Uoc3RydWN0IHZkdXNlX2lvdmFfZG9tYWluICpkb21haW4sCj4+PiArICAgICAgICAgICAgICAg ICAgICAgICAgICAgICB1bnNpZ25lZCBsb25nIGlvdmEpCj4+PiArewo+Pj4gKyAgICAgdW5zaWdu ZWQgbG9uZyBzdGFydCA9IGlvdmEgJiBQQUdFX01BU0s7Cj4+PiArICAgICB1bnNpZ25lZCBsb25n IGxhc3QgPSBzdGFydCArIFBBR0VfU0laRSAtIDE7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfaW92 YV9tYXAgKm1hcDsKPj4+ICsgICAgIHN0cnVjdCBpbnRlcnZhbF90cmVlX25vZGUgKm5vZGU7Cj4+ PiArICAgICBzdHJ1Y3QgcGFnZSAqcGFnZSA9IE5VTEwsICpuZXdfcGFnZSA9IGFsbG9jX3BhZ2Uo R0ZQX0tFUk5FTCk7Cj4+PiArCj4+PiArICAgICBpZiAoIW5ld19wYWdlKQo+Pj4gKyAgICAgICAg ICAgICByZXR1cm4gTlVMTDsKPj4+ICsKPj4+ICsgICAgIHNwaW5fbG9jaygmZG9tYWluLT5tYXBf bG9jayk7Cj4+PiArICAgICBub2RlID0gaW50ZXJ2YWxfdHJlZV9pdGVyX2ZpcnN0KCZkb21haW4t Pm1hcHBpbmdzLCBzdGFydCwgbGFzdCk7Cj4+PiArICAgICBpZiAoIW5vZGUpIHsKPj4+ICsgICAg ICAgICAgICAgX19mcmVlX3BhZ2UobmV3X3BhZ2UpOwo+Pj4gKyAgICAgICAgICAgICBnb3RvIG91 dDsKPj4+ICsgICAgIH0KPj4+ICsgICAgIHBhZ2UgPSB2ZHVzZV9kb21haW5fZ2V0X2JvdW5jZV9w YWdlKGRvbWFpbiwgaW92YSk7Cj4+PiArICAgICBpZiAocGFnZSkgewo+Pj4gKyAgICAgICAgICAg ICBnZXRfcGFnZShwYWdlKTsKPj4+ICsgICAgICAgICAgICAgX19mcmVlX3BhZ2UobmV3X3BhZ2Up Owo+Pgo+PiBMZXQncyBkZWxheSB0aGUgYWxsb2NhdGlvbiBvZiBuZXdfcGFnZSB1bnRpbCBpdCBp cyByZWFsbHkgcmVxdWlyZWQuCj4gSWYgc28sIHdlIG5lZWQgdG8gYWxsb2NhdGUgdGhlIHBhZ2Ug aW4gYXRvbWljIGNvbnRleHQuCgoKUmlnaHQsIEkgc2VlLgoKCj4+PiArICAgICAgICAgICAgIGdv dG8gb3V0Owo+Pj4gKyAgICAgfQo+Pj4gKyAgICAgdmR1c2VfZG9tYWluX3NldF9ib3VuY2VfcGFn ZShkb21haW4sIGlvdmEsIG5ld19wYWdlKTsKPj4+ICsgICAgIGdldF9wYWdlKG5ld19wYWdlKTsK Pj4+ICsgICAgIHBhZ2UgPSBuZXdfcGFnZTsKPj4+ICsKPj4+ICsgICAgIHdoaWxlIChub2RlKSB7 Cj4+Cj4+IEkgbWF5IG1pc3Mgc29tZXRoaW5nIGJ1dCB3aGljaCBjYXNlIHNob3VsZCB3ZSBkbyB0 aGUgbG9vcCBoZXJlPwo+Pgo+IFdoZW4gSU9WQV9BTExPQ19TSVpFICE9IFBBR0VfU0laRQo+Cj4+ PiArICAgICAgICAgICAgIHVuc2lnbmVkIGludCBzcmNfb2Zmc2V0ID0gMCwgZHN0X29mZnNldCA9 IDA7Cj4+PiArICAgICAgICAgICAgIHZvaWQgKnNyYywgKmRzdDsKPj4+ICsgICAgICAgICAgICAg c2l6ZV90IGNvcHlfbGVuOwo+Pj4gKwo+Pj4gKyAgICAgICAgICAgICBtYXAgPSBjb250YWluZXJf b2Yobm9kZSwgc3RydWN0IHZkdXNlX2lvdmFfbWFwLCBpb3ZhKTsKPj4+ICsgICAgICAgICAgICAg bm9kZSA9IGludGVydmFsX3RyZWVfaXRlcl9uZXh0KG5vZGUsIHN0YXJ0LCBsYXN0KTsKPj4+ICsg ICAgICAgICAgICAgaWYgKG1hcC0+ZGlyID09IERNQV9GUk9NX0RFVklDRSkKPj4+ICsgICAgICAg ICAgICAgICAgICAgICBjb250aW51ZTsKPj4+ICsKPj4+ICsgICAgICAgICAgICAgaWYgKHN0YXJ0 ID4gbWFwLT5pb3ZhLnN0YXJ0KQo+Pj4gKyAgICAgICAgICAgICAgICAgICAgIHNyY19vZmZzZXQg PSBzdGFydCAtIG1hcC0+aW92YS5zdGFydDsKPj4+ICsgICAgICAgICAgICAgZWxzZQo+Pj4gKyAg ICAgICAgICAgICAgICAgICAgIGRzdF9vZmZzZXQgPSBtYXAtPmlvdmEuc3RhcnQgLSBzdGFydDsK Pj4+ICsKPj4+ICsgICAgICAgICAgICAgc3JjID0gKHZvaWQgKikobWFwLT5vcmlnICsgc3JjX29m ZnNldCk7Cj4+PiArICAgICAgICAgICAgIGRzdCA9IHBhZ2VfYWRkcmVzcyhwYWdlKSArIGRzdF9v ZmZzZXQ7Cj4+PiArICAgICAgICAgICAgIGNvcHlfbGVuID0gbWluX3Qoc2l6ZV90LCBtYXAtPnNp emUgLSBzcmNfb2Zmc2V0LAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUEFHRV9T SVpFIC0gZHN0X29mZnNldCk7Cj4+PiArICAgICAgICAgICAgIG1lbWNweShkc3QsIHNyYywgY29w eV9sZW4pOwo+Pj4gKyAgICAgfQo+Pj4gK291dDoKPj4+ICsgICAgIHNwaW5fdW5sb2NrKCZkb21h aW4tPm1hcF9sb2NrKTsKPj4+ICsKPj4+ICsgICAgIHJldHVybiBwYWdlOwo+Pj4gK30KPj4+ICsK Pj4+ICtzdGF0aWMgdm9pZAo+Pj4gK3ZkdXNlX2RvbWFpbl9mcmVlX2JvdW5jZV9wYWdlcyhzdHJ1 Y3QgdmR1c2VfaW92YV9kb21haW4gKmRvbWFpbiwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIHVuc2lnbmVkIGxvbmcgaW92YSwgc2l6ZV90IHNpemUpCj4+PiArewo+Pj4gKyAgICAg c3RydWN0IHBhZ2UgKnBhZ2U7Cj4+PiArICAgICBzdHJ1Y3QgaW50ZXJ2YWxfdHJlZV9ub2RlICpu b2RlOwo+Pj4gKyAgICAgdW5zaWduZWQgbG9uZyBsYXN0ID0gaW92YSArIHNpemUgLSAxOwo+Pj4g Kwo+Pj4gKyAgICAgc3Bpbl9sb2NrKCZkb21haW4tPm1hcF9sb2NrKTsKPj4+ICsgICAgIG5vZGUg PSBpbnRlcnZhbF90cmVlX2l0ZXJfZmlyc3QoJmRvbWFpbi0+bWFwcGluZ3MsIGlvdmEsIGxhc3Qp Owo+Pj4gKyAgICAgaWYgKFdBUk5fT04obm9kZSkpCj4+PiArICAgICAgICAgICAgIGdvdG8gb3V0 Owo+Pj4gKwo+Pj4gKyAgICAgd2hpbGUgKHNpemUgPiAwKSB7Cj4+PiArICAgICAgICAgICAgIHBh Z2UgPSB2ZHVzZV9kb21haW5fZ2V0X2JvdW5jZV9wYWdlKGRvbWFpbiwgaW92YSk7Cj4+PiArICAg ICAgICAgICAgIGlmIChwYWdlKSB7Cj4+PiArICAgICAgICAgICAgICAgICAgICAgdmR1c2VfZG9t YWluX3NldF9ib3VuY2VfcGFnZShkb21haW4sIGlvdmEsIE5VTEwpOwo+Pj4gKyAgICAgICAgICAg ICAgICAgICAgIF9fZnJlZV9wYWdlKHBhZ2UpOwo+Pj4gKyAgICAgICAgICAgICB9Cj4+PiArICAg ICAgICAgICAgIHNpemUgLT0gUEFHRV9TSVpFOwo+Pj4gKyAgICAgICAgICAgICBpb3ZhICs9IFBB R0VfU0laRTsKPj4+ICsgICAgIH0KPj4+ICtvdXQ6Cj4+PiArICAgICBzcGluX3VubG9jaygmZG9t YWluLT5tYXBfbG9jayk7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyB2b2lkIHZkdXNlX2RvbWFp bl9ib3VuY2Uoc3RydWN0IHZkdXNlX2lvdmFfZG9tYWluICpkb21haW4sCj4+PiArICAgICAgICAg ICAgICAgICAgICAgICAgICAgICB1bnNpZ25lZCBsb25nIGlvdmEsIHVuc2lnbmVkIGxvbmcgb3Jp ZywKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemVfdCBzaXplLCBlbnVtIGRt YV9kYXRhX2RpcmVjdGlvbiBkaXIpCj4+PiArewo+Pj4gKyAgICAgdW5zaWduZWQgaW50IG9mZnNl dCA9IG9mZnNldF9pbl9wYWdlKGlvdmEpOwo+Pj4gKwo+Pj4gKyAgICAgd2hpbGUgKHNpemUpIHsK Pj4+ICsgICAgICAgICAgICAgc3RydWN0IHBhZ2UgKnAgPSB2ZHVzZV9kb21haW5fZ2V0X2JvdW5j ZV9wYWdlKGRvbWFpbiwgaW92YSk7Cj4+PiArICAgICAgICAgICAgIHNpemVfdCBjb3B5X2xlbiA9 IG1pbl90KHNpemVfdCwgUEFHRV9TSVpFIC0gb2Zmc2V0LCBzaXplKTsKPj4+ICsgICAgICAgICAg ICAgdm9pZCAqYWRkcjsKPj4+ICsKPj4+ICsgICAgICAgICAgICAgV0FSTl9PTighcCAmJiBkaXIg PT0gRE1BX0ZST01fREVWSUNFKTsKPj4+ICsKPj4+ICsgICAgICAgICAgICAgaWYgKHApIHsKPj4+ ICsgICAgICAgICAgICAgICAgICAgICBhZGRyID0gcGFnZV9hZGRyZXNzKHApICsgb2Zmc2V0Owo+ Pj4gKyAgICAgICAgICAgICAgICAgICAgIGlmIChkaXIgPT0gRE1BX1RPX0RFVklDRSkKPj4+ICsg ICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lbWNweShhZGRyLCAodm9pZCAqKW9yaWcsIGNv cHlfbGVuKTsKPj4+ICsgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChkaXIgPT0gRE1BX0ZS T01fREVWSUNFKQo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVtY3B5KCh2b2lk ICopb3JpZywgYWRkciwgY29weV9sZW4pOwo+Pj4gKyAgICAgICAgICAgICB9Cj4+PiArCj4+PiAr ICAgICAgICAgICAgIHNpemUgLT0gY29weV9sZW47Cj4+PiArICAgICAgICAgICAgIG9yaWcgKz0g Y29weV9sZW47Cj4+PiArICAgICAgICAgICAgIGlvdmEgKz0gY29weV9sZW47Cj4+PiArICAgICAg ICAgICAgIG9mZnNldCA9IDA7Cj4+PiArICAgICB9Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyB1 bnNpZ25lZCBsb25nIHZkdXNlX2RvbWFpbl9hbGxvY19pb3ZhKHN0cnVjdCBpb3ZhX2RvbWFpbiAq aW92YWQsCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bnNpZ25lZCBsb25nIHNp emUsIHVuc2lnbmVkIGxvbmcgbGltaXQpCj4+PiArewo+Pj4gKyAgICAgdW5zaWduZWQgbG9uZyBz aGlmdCA9IGlvdmFfc2hpZnQoaW92YWQpOwo+Pj4gKyAgICAgdW5zaWduZWQgbG9uZyBpb3ZhX2xl biA9IGlvdmFfYWxpZ24oaW92YWQsIHNpemUpID4+IHNoaWZ0Owo+Pj4gKyAgICAgdW5zaWduZWQg bG9uZyBpb3ZhX3BmbjsKPj4+ICsKPj4+ICsgICAgIGlmIChpb3ZhX2xlbiA8ICgxIDw8IChJT1ZB X1JBTkdFX0NBQ0hFX01BWF9TSVpFIC0gMSkpKQo+Pj4gKyAgICAgICAgICAgICBpb3ZhX2xlbiA9 IHJvdW5kdXBfcG93X29mX3R3byhpb3ZhX2xlbik7Cj4+PiArICAgICBpb3ZhX3BmbiA9IGFsbG9j X2lvdmFfZmFzdChpb3ZhZCwgaW92YV9sZW4sIGxpbWl0ID4+IHNoaWZ0LCB0cnVlKTsKPj4+ICsK Pj4+ICsgICAgIHJldHVybiBpb3ZhX3BmbiA8PCBzaGlmdDsKPj4+ICt9Cj4+PiArCj4+PiArc3Rh dGljIHZvaWQgdmR1c2VfZG9tYWluX2ZyZWVfaW92YShzdHJ1Y3QgaW92YV9kb21haW4gKmlvdmFk LAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5zaWduZWQgbG9uZyBpb3ZhLCBz aXplX3Qgc2l6ZSkKPj4+ICt7Cj4+PiArICAgICB1bnNpZ25lZCBsb25nIHNoaWZ0ID0gaW92YV9z aGlmdChpb3ZhZCk7Cj4+PiArICAgICB1bnNpZ25lZCBsb25nIGlvdmFfbGVuID0gaW92YV9hbGln bihpb3ZhZCwgc2l6ZSkgPj4gc2hpZnQ7Cj4+PiArCj4+PiArICAgICBmcmVlX2lvdmFfZmFzdChp b3ZhZCwgaW92YSA+PiBzaGlmdCwgaW92YV9sZW4pOwo+Pj4gK30KPj4+ICsKPj4+ICtkbWFfYWRk cl90IHZkdXNlX2RvbWFpbl9tYXBfcGFnZShzdHJ1Y3QgdmR1c2VfaW92YV9kb21haW4gKmRvbWFp biwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBwYWdlICpwYWdlLCB1 bnNpZ25lZCBsb25nIG9mZnNldCwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNp emVfdCBzaXplLCBlbnVtIGRtYV9kYXRhX2RpcmVjdGlvbiBkaXIsCj4+PiArICAgICAgICAgICAg ICAgICAgICAgICAgICAgICB1bnNpZ25lZCBsb25nIGF0dHJzKQo+Pj4gK3sKPj4+ICsgICAgIHN0 cnVjdCBpb3ZhX2RvbWFpbiAqaW92YWQgPSAmZG9tYWluLT5zdHJlYW1faW92YWQ7Cj4+PiArICAg ICB1bnNpZ25lZCBsb25nIGxpbWl0ID0gZG9tYWluLT5ib3VuY2Vfc2l6ZSAtIDE7Cj4+PiArICAg ICB1bnNpZ25lZCBsb25nIGlvdmEgPSB2ZHVzZV9kb21haW5fYWxsb2NfaW92YShpb3ZhZCwgc2l6 ZSwgbGltaXQpOwo+Pj4gKyAgICAgdW5zaWduZWQgbG9uZyBvcmlnID0gKHVuc2lnbmVkIGxvbmcp cGFnZV9hZGRyZXNzKHBhZ2UpICsgb2Zmc2V0Owo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX2lvdmFf bWFwICptYXA7Cj4+PiArCj4+PiArICAgICBpZiAoIWlvdmEpCj4+PiArICAgICAgICAgICAgIHJl dHVybiBETUFfTUFQUElOR19FUlJPUjsKPj4+ICsKPj4+ICsgICAgIG1hcCA9IHZkdXNlX2RvbWFp bl9hbGxvY19pb3ZhX21hcChkb21haW4sIGlvdmEsIG9yaWcsIHNpemUsIGRpcik7Cj4+PiArICAg ICBpZiAoIW1hcCkgewo+Pj4gKyAgICAgICAgICAgICB2ZHVzZV9kb21haW5fZnJlZV9pb3ZhKGlv dmFkLCBpb3ZhLCBzaXplKTsKPj4+ICsgICAgICAgICAgICAgcmV0dXJuIERNQV9NQVBQSU5HX0VS Uk9SOwo+Pj4gKyAgICAgfQo+Pj4gKwo+Pj4gKyAgICAgc3Bpbl9sb2NrKCZkb21haW4tPm1hcF9s b2NrKTsKPj4+ICsgICAgIGludGVydmFsX3RyZWVfaW5zZXJ0KCZtYXAtPmlvdmEsICZkb21haW4t Pm1hcHBpbmdzKTsKPj4+ICsgICAgIHNwaW5fdW5sb2NrKCZkb21haW4tPm1hcF9sb2NrKTsKPj4+ ICsKPj4+ICsgICAgIGlmIChkaXIgPT0gRE1BX1RPX0RFVklDRSB8fCBkaXIgPT0gRE1BX0JJRElS RUNUSU9OQUwpCj4+PiArICAgICAgICAgICAgIHZkdXNlX2RvbWFpbl9ib3VuY2UoZG9tYWluLCBp b3ZhLCBvcmlnLCBzaXplLCBETUFfVE9fREVWSUNFKTsKPj4+ICsKPj4+ICsgICAgIHJldHVybiAo ZG1hX2FkZHJfdClpb3ZhOwo+Pj4gK30KPj4+ICsKPj4+ICt2b2lkIHZkdXNlX2RvbWFpbl91bm1h cF9wYWdlKHN0cnVjdCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluLAo+Pj4gKyAgICAgICAgICAg ICAgICAgICAgIGRtYV9hZGRyX3QgZG1hX2FkZHIsIHNpemVfdCBzaXplLAo+Pj4gKyAgICAgICAg ICAgICAgICAgICAgIGVudW0gZG1hX2RhdGFfZGlyZWN0aW9uIGRpciwgdW5zaWduZWQgbG9uZyBh dHRycykKPj4+ICt7Cj4+PiArICAgICBzdHJ1Y3QgaW92YV9kb21haW4gKmlvdmFkID0gJmRvbWFp bi0+c3RyZWFtX2lvdmFkOwo+Pj4gKyAgICAgdW5zaWduZWQgbG9uZyBpb3ZhID0gKHVuc2lnbmVk IGxvbmcpZG1hX2FkZHI7Cj4+PiArICAgICBzdHJ1Y3QgaW50ZXJ2YWxfdHJlZV9ub2RlICpub2Rl Owo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX2lvdmFfbWFwICptYXA7Cj4+PiArCj4+PiArICAgICBz cGluX2xvY2soJmRvbWFpbi0+bWFwX2xvY2spOwo+Pj4gKyAgICAgbm9kZSA9IGludGVydmFsX3Ry ZWVfaXRlcl9maXJzdCgmZG9tYWluLT5tYXBwaW5ncywgaW92YSwgaW92YSArIDEpOwo+Pj4gKyAg ICAgaWYgKFdBUk5fT04oIW5vZGUpKSB7Cj4+PiArICAgICAgICAgICAgIHNwaW5fdW5sb2NrKCZk b21haW4tPm1hcF9sb2NrKTsKPj4+ICsgICAgICAgICAgICAgcmV0dXJuOwo+Pj4gKyAgICAgfQo+ Pj4gKyAgICAgaW50ZXJ2YWxfdHJlZV9yZW1vdmUobm9kZSwgJmRvbWFpbi0+bWFwcGluZ3MpOwo+ Pj4gKyAgICAgc3Bpbl91bmxvY2soJmRvbWFpbi0+bWFwX2xvY2spOwo+Pj4gKwo+Pj4gKyAgICAg bWFwID0gY29udGFpbmVyX29mKG5vZGUsIHN0cnVjdCB2ZHVzZV9pb3ZhX21hcCwgaW92YSk7Cj4+ PiArICAgICBpZiAoZGlyID09IERNQV9GUk9NX0RFVklDRSB8fCBkaXIgPT0gRE1BX0JJRElSRUNU SU9OQUwpCj4+PiArICAgICAgICAgICAgIHZkdXNlX2RvbWFpbl9ib3VuY2UoZG9tYWluLCBpb3Zh LCBtYXAtPm9yaWcsCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNp emUsIERNQV9GUk9NX0RFVklDRSk7Cj4+PiArICAgICB2ZHVzZV9kb21haW5fZnJlZV9pb3ZhKGlv dmFkLCBpb3ZhLCBzaXplKTsKPj4+ICsgICAgIGtmcmVlKG1hcCk7Cj4+PiArfQo+Pj4gKwo+Pj4g K3ZvaWQgKnZkdXNlX2RvbWFpbl9hbGxvY19jb2hlcmVudChzdHJ1Y3QgdmR1c2VfaW92YV9kb21h aW4gKmRvbWFpbiwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemVfdCBzaXpl LCBkbWFfYWRkcl90ICpkbWFfYWRkciwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAg IGdmcF90IGZsYWcsIHVuc2lnbmVkIGxvbmcgYXR0cnMpCj4+PiArewo+Pj4gKyAgICAgc3RydWN0 IGlvdmFfZG9tYWluICppb3ZhZCA9ICZkb21haW4tPmNvbnNpc3RlbnRfaW92YWQ7Cj4+PiArICAg ICB1bnNpZ25lZCBsb25nIGxpbWl0ID0gZG9tYWluLT5ib3VuY2Vfc2l6ZSArIENPTlNJU1RFTlRf RE1BX1NJWkUgLSAxOwo+Pj4gKyAgICAgdW5zaWduZWQgbG9uZyBpb3ZhID0gdmR1c2VfZG9tYWlu X2FsbG9jX2lvdmEoaW92YWQsIHNpemUsIGxpbWl0KTsKPj4+ICsgICAgIHZvaWQgKm9yaWcgPSBh bGxvY19wYWdlc19leGFjdChzaXplLCBmbGFnKTsKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9pb3Zh X21hcCAqbWFwOwo+Pj4gKwo+Pj4gKyAgICAgaWYgKCFpb3ZhIHx8ICFvcmlnKQo+Pj4gKyAgICAg ICAgICAgICBnb3RvIGVycjsKPj4+ICsKPj4+ICsgICAgIG1hcCA9IHZkdXNlX2RvbWFpbl9hbGxv Y19pb3ZhX21hcChkb21haW4sIGlvdmEsICh1bnNpZ25lZCBsb25nKW9yaWcsCj4+PiArICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemUsIERNQV9CSURJUkVDVElPTkFMKTsK Pj4+ICsgICAgIGlmICghbWFwKQo+Pj4gKyAgICAgICAgICAgICBnb3RvIGVycjsKPj4+ICsKPj4+ ICsgICAgIHNwaW5fbG9jaygmZG9tYWluLT5tYXBfbG9jayk7Cj4+PiArICAgICBpbnRlcnZhbF90 cmVlX2luc2VydCgmbWFwLT5pb3ZhLCAmZG9tYWluLT5tYXBwaW5ncyk7Cj4+PiArICAgICBzcGlu X3VubG9jaygmZG9tYWluLT5tYXBfbG9jayk7Cj4+PiArICAgICAqZG1hX2FkZHIgPSAoZG1hX2Fk ZHJfdClpb3ZhOwo+Pj4gKwo+Pj4gKyAgICAgcmV0dXJuIG9yaWc7Cj4+PiArZXJyOgo+Pj4gKyAg ICAgKmRtYV9hZGRyID0gRE1BX01BUFBJTkdfRVJST1I7Cj4+PiArICAgICBpZiAob3JpZykKPj4+ ICsgICAgICAgICAgICAgZnJlZV9wYWdlc19leGFjdChvcmlnLCBzaXplKTsKPj4+ICsgICAgIGlm IChpb3ZhKQo+Pj4gKyAgICAgICAgICAgICB2ZHVzZV9kb21haW5fZnJlZV9pb3ZhKGlvdmFkLCBp b3ZhLCBzaXplKTsKPj4+ICsKPj4+ICsgICAgIHJldHVybiBOVUxMOwo+Pj4gK30KPj4+ICsKPj4+ ICt2b2lkIHZkdXNlX2RvbWFpbl9mcmVlX2NvaGVyZW50KHN0cnVjdCB2ZHVzZV9pb3ZhX2RvbWFp biAqZG9tYWluLCBzaXplX3Qgc2l6ZSwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAg IHZvaWQgKnZhZGRyLCBkbWFfYWRkcl90IGRtYV9hZGRyLAo+Pj4gKyAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgdW5zaWduZWQgbG9uZyBhdHRycykKPj4+ICt7Cj4+PiArICAgICBzdHJ1Y3Qg aW92YV9kb21haW4gKmlvdmFkID0gJmRvbWFpbi0+Y29uc2lzdGVudF9pb3ZhZDsKPj4+ICsgICAg IHVuc2lnbmVkIGxvbmcgaW92YSA9ICh1bnNpZ25lZCBsb25nKWRtYV9hZGRyOwo+Pj4gKyAgICAg c3RydWN0IGludGVydmFsX3RyZWVfbm9kZSAqbm9kZTsKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9p b3ZhX21hcCAqbWFwOwo+Pj4gKwo+Pj4gKyAgICAgc3Bpbl9sb2NrKCZkb21haW4tPm1hcF9sb2Nr KTsKPj4+ICsgICAgIG5vZGUgPSBpbnRlcnZhbF90cmVlX2l0ZXJfZmlyc3QoJmRvbWFpbi0+bWFw cGluZ3MsIGlvdmEsIGlvdmEgKyAxKTsKPj4+ICsgICAgIGlmIChXQVJOX09OKCFub2RlKSkgewo+ Pj4gKyAgICAgICAgICAgICBzcGluX3VubG9jaygmZG9tYWluLT5tYXBfbG9jayk7Cj4+PiArICAg ICAgICAgICAgIHJldHVybjsKPj4+ICsgICAgIH0KPj4+ICsgICAgIGludGVydmFsX3RyZWVfcmVt b3ZlKG5vZGUsICZkb21haW4tPm1hcHBpbmdzKTsKPj4+ICsgICAgIHNwaW5fdW5sb2NrKCZkb21h aW4tPm1hcF9sb2NrKTsKPj4+ICsKPj4+ICsgICAgIG1hcCA9IGNvbnRhaW5lcl9vZihub2RlLCBz dHJ1Y3QgdmR1c2VfaW92YV9tYXAsIGlvdmEpOwo+Pj4gKyAgICAgdmR1c2VfZG9tYWluX2ZyZWVf aW92YShpb3ZhZCwgaW92YSwgc2l6ZSk7Cj4+PiArICAgICBmcmVlX3BhZ2VzX2V4YWN0KHZhZGRy LCBzaXplKTsKPj4+ICsgICAgIGtmcmVlKG1hcCk7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyB2 bV9mYXVsdF90IHZkdXNlX2RvbWFpbl9tbWFwX2ZhdWx0KHN0cnVjdCB2bV9mYXVsdCAqdm1mKQo+ Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluID0gdm1mLT52 bWEtPnZtX3ByaXZhdGVfZGF0YTsKPj4+ICsgICAgIHVuc2lnbmVkIGxvbmcgaW92YSA9IHZtZi0+ cGdvZmYgPDwgUEFHRV9TSElGVDsKPj4+ICsgICAgIHN0cnVjdCBwYWdlICpwYWdlOwo+Pj4gKwo+ Pj4gKyAgICAgaWYgKCFkb21haW4pCj4+PiArICAgICAgICAgICAgIHJldHVybiBWTV9GQVVMVF9T SUdCVVM7Cj4+PiArCj4+PiArICAgICBpZiAoaW92YSA8IGRvbWFpbi0+Ym91bmNlX3NpemUpCj4+ PiArICAgICAgICAgICAgIHBhZ2UgPSB2ZHVzZV9kb21haW5fYWxsb2NfYm91bmNlX3BhZ2UoZG9t YWluLCBpb3ZhKTsKPj4+ICsgICAgIGVsc2UKPj4+ICsgICAgICAgICAgICAgcGFnZSA9IHZkdXNl X2RvbWFpbl9nZXRfbWFwcGluZ19wYWdlKGRvbWFpbiwgaW92YSk7Cj4+PiArCj4+PiArICAgICBp ZiAoIXBhZ2UpCj4+PiArICAgICAgICAgICAgIHJldHVybiBWTV9GQVVMVF9TSUdCVVM7Cj4+PiAr Cj4+PiArICAgICB2bWYtPnBhZ2UgPSBwYWdlOwo+Pj4gKwo+Pj4gKyAgICAgcmV0dXJuIDA7Cj4+ PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3Qgdm1fb3BlcmF0aW9uc19zdHJ1Y3Qg dmR1c2VfZG9tYWluX21tYXBfb3BzID0gewo+Pj4gKyAgICAgLmZhdWx0ID0gdmR1c2VfZG9tYWlu X21tYXBfZmF1bHQsCj4+PiArfTsKPj4+ICsKPj4+ICtzdGF0aWMgaW50IHZkdXNlX2RvbWFpbl9t bWFwKHN0cnVjdCBmaWxlICpmaWxlLCBzdHJ1Y3Qgdm1fYXJlYV9zdHJ1Y3QgKnZtYSkKPj4+ICt7 Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfaW92YV9kb21haW4gKmRvbWFpbiA9IGZpbGUtPnByaXZh dGVfZGF0YTsKPj4+ICsKPj4+ICsgICAgIHZtYS0+dm1fZmxhZ3MgfD0gVk1fRE9OVENPUFkgfCBW TV9ET05URFVNUCB8IFZNX0RPTlRFWFBBTkQ7Cj4+PiArICAgICB2bWEtPnZtX3ByaXZhdGVfZGF0 YSA9IGRvbWFpbjsKPj4+ICsgICAgIHZtYS0+dm1fb3BzID0gJnZkdXNlX2RvbWFpbl9tbWFwX29w czsKPj4+ICsKPj4+ICsgICAgIHJldHVybiAwOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgaW50 IHZkdXNlX2RvbWFpbl9yZWxlYXNlKHN0cnVjdCBpbm9kZSAqaW5vZGUsIHN0cnVjdCBmaWxlICpm aWxlKQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluID0g ZmlsZS0+cHJpdmF0ZV9kYXRhOwo+Pj4gKwo+Pj4gKyAgICAgdmR1c2VfZG9tYWluX2ZyZWVfYm91 bmNlX3BhZ2VzKGRvbWFpbiwgMCwgZG9tYWluLT5ib3VuY2Vfc2l6ZSk7Cj4+PiArICAgICBwdXRf aW92YV9kb21haW4oJmRvbWFpbi0+c3RyZWFtX2lvdmFkKTsKPj4+ICsgICAgIHB1dF9pb3ZhX2Rv bWFpbigmZG9tYWluLT5jb25zaXN0ZW50X2lvdmFkKTsKPj4+ICsgICAgIHZmcmVlKGRvbWFpbi0+ Ym91bmNlX3BhZ2VzKTsKPj4+ICsgICAgIGtmcmVlKGRvbWFpbik7Cj4+PiArCj4+PiArICAgICBy ZXR1cm4gMDsKPj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIGNvbnN0IHN0cnVjdCBmaWxlX29wZXJh dGlvbnMgdmR1c2VfZG9tYWluX2ZvcHMgPSB7Cj4+PiArICAgICAubW1hcCA9IHZkdXNlX2RvbWFp bl9tbWFwLAo+Pj4gKyAgICAgLnJlbGVhc2UgPSB2ZHVzZV9kb21haW5fcmVsZWFzZSwKPj4+ICt9 Owo+Pgo+PiBJdCdzIGJldHRlciB0byBleHBsYWluIHRoZSByZWFzb24gZm9yIGludHJvZHVjaW5n IGEgZGVkaWNhdGVkIGZpbGUgZm9yCj4+IG1tYXAoKSBoZXJlLgo+Pgo+IFRvIG1ha2UgdGhlIGlt cGxlbWVudGF0aW9uIG9mIGlvdmFfZG9tYWluIGluZGVwZW5kZW50IHdpdGggdmR1c2VfZGV2LgoK Ck15IHVuZGVyc3RhbmRpbmcgaXMgdGhhdCwgdGhlIG9ubHkgdXNhZ2UgZm9yIHRoaXMgaXMgdG86 CgoxKSBzdXBwb3J0IGRpZmZlcmVudCB0eXBlIG9mIGlvdmEgbWFwcGluZ3MKMikgb3Igc3dpdGNo IGJldHdlZW4gaW92YSBkb21haW4gbWFwcGluZ3MKCkJ1dCBJIGNhbid0IHRoaW5rIG9mIGEgbmVl ZCBmb3IgdGhpcy4KCgo+Cj4+PiArCj4+PiArdm9pZCB2ZHVzZV9kb21haW5fZGVzdHJveShzdHJ1 Y3QgdmR1c2VfaW92YV9kb21haW4gKmRvbWFpbikKPj4+ICt7Cj4+PiArICAgICBmcHV0KGRvbWFp bi0+ZmlsZSk7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0cnVjdCB2ZHVzZV9pb3ZhX2RvbWFpbiAqdmR1 c2VfZG9tYWluX2NyZWF0ZShzaXplX3QgYm91bmNlX3NpemUpCj4+PiArewo+Pj4gKyAgICAgc3Ry dWN0IHZkdXNlX2lvdmFfZG9tYWluICpkb21haW47Cj4+PiArICAgICBzdHJ1Y3QgZmlsZSAqZmls ZTsKPj4+ICsgICAgIHVuc2lnbmVkIGxvbmcgYm91bmNlX3BmbnMgPSBQQUdFX0FMSUdOKGJvdW5j ZV9zaXplKSA+PiBQQUdFX1NISUZUOwo+Pj4gKwo+Pj4gKyAgICAgZG9tYWluID0ga3phbGxvYyhz aXplb2YoKmRvbWFpbiksIEdGUF9LRVJORUwpOwo+Pj4gKyAgICAgaWYgKCFkb21haW4pCj4+PiAr ICAgICAgICAgICAgIHJldHVybiBOVUxMOwo+Pj4gKwo+Pj4gKyAgICAgZG9tYWluLT5ib3VuY2Vf c2l6ZSA9IFBBR0VfQUxJR04oYm91bmNlX3NpemUpOwo+Pj4gKyAgICAgZG9tYWluLT5ib3VuY2Vf cGFnZXMgPSB2emFsbG9jKGJvdW5jZV9wZm5zICogc2l6ZW9mKHN0cnVjdCBwYWdlICopKTsKPj4+ ICsgICAgIGlmICghZG9tYWluLT5ib3VuY2VfcGFnZXMpCj4+PiArICAgICAgICAgICAgIGdvdG8g ZXJyX3BhZ2U7Cj4+PiArCj4+PiArICAgICBmaWxlID0gYW5vbl9pbm9kZV9nZXRmaWxlKCJbdmR1 c2UtZG9tYWluXSIsICZ2ZHVzZV9kb21haW5fZm9wcywKPj4+ICsgICAgICAgICAgICAgICAgICAg ICAgICAgICAgIGRvbWFpbiwgT19SRFdSKTsKPj4+ICsgICAgIGlmIChJU19FUlIoZmlsZSkpCj4+ PiArICAgICAgICAgICAgIGdvdG8gZXJyX2ZpbGU7Cj4+PiArCj4+PiArICAgICBkb21haW4tPmZp bGUgPSBmaWxlOwo+Pj4gKyAgICAgc3Bpbl9sb2NrX2luaXQoJmRvbWFpbi0+bWFwX2xvY2spOwo+ Pj4gKyAgICAgZG9tYWluLT5tYXBwaW5ncyA9IFJCX1JPT1RfQ0FDSEVEOwo+Pj4gKyAgICAgaW5p dF9pb3ZhX2RvbWFpbigmZG9tYWluLT5zdHJlYW1faW92YWQsCj4+PiArICAgICAgICAgICAgICAg ICAgICAgSU9WQV9BTExPQ19TSVpFLCBJT1ZBX1NUQVJUX1BGTik7Cj4+PiArICAgICBpbml0X2lv dmFfZG9tYWluKCZkb21haW4tPmNvbnNpc3RlbnRfaW92YWQsCj4+PiArICAgICAgICAgICAgICAg ICAgICAgUEFHRV9TSVpFLCBib3VuY2VfcGZucyk7Cj4+PiArCj4+PiArICAgICByZXR1cm4gZG9t YWluOwo+Pj4gK2Vycl9maWxlOgo+Pj4gKyAgICAgdmZyZWUoZG9tYWluLT5ib3VuY2VfcGFnZXMp Owo+Pj4gK2Vycl9wYWdlOgo+Pj4gKyAgICAga2ZyZWUoZG9tYWluKTsKPj4+ICsgICAgIHJldHVy biBOVUxMOwo+Pj4gK30KPj4+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3ZkcGEvdmRwYV91c2VyL2lv dmFfZG9tYWluLmggYi9kcml2ZXJzL3ZkcGEvdmRwYV91c2VyL2lvdmFfZG9tYWluLmgKPj4+IG5l dyBmaWxlIG1vZGUgMTAwNjQ0Cj4+PiBpbmRleCAwMDAwMDAwMDAwMDAuLmNjNjE4NjZhY2I1Ngo+ Pj4gLS0tIC9kZXYvbnVsbAo+Pj4gKysrIGIvZHJpdmVycy92ZHBhL3ZkcGFfdXNlci9pb3ZhX2Rv bWFpbi5oCj4+PiBAQCAtMCwwICsxLDY4IEBACj4+PiArLyogU1BEWC1MaWNlbnNlLUlkZW50aWZp ZXI6IEdQTC0yLjAtb25seSAqLwo+Pj4gKy8qCj4+PiArICogTU1VLWJhc2VkIElPTU1VIGltcGxl bWVudGF0aW9uCj4+PiArICoKPj4+ICsgKiBDb3B5cmlnaHQgKEMpIDIwMjAgQnl0ZWRhbmNlIElu Yy4gYW5kL29yIGl0cyBhZmZpbGlhdGVzLiBBbGwgcmlnaHRzIHJlc2VydmVkLgo+Pj4gKyAqCj4+ PiArICogQXV0aG9yOiBYaWUgWW9uZ2ppIDx4aWV5b25namlAYnl0ZWRhbmNlLmNvbT4KPj4+ICsg Kgo+Pj4gKyAqLwo+Pj4gKwo+Pj4gKyNpZm5kZWYgX1ZEVVNFX0lPVkFfRE9NQUlOX0gKPj4+ICsj ZGVmaW5lIF9WRFVTRV9JT1ZBX0RPTUFJTl9ICj4+PiArCj4+PiArI2luY2x1ZGUgPGxpbnV4L2lv dmEuaD4KPj4+ICsjaW5jbHVkZSA8bGludXgvaW50ZXJ2YWxfdHJlZS5oPgo+Pj4gKyNpbmNsdWRl IDxsaW51eC9kbWEtbWFwcGluZy5oPgo+Pj4gKwo+Pj4gK3N0cnVjdCB2ZHVzZV9pb3ZhX21hcCB7 Cj4+PiArICAgICBzdHJ1Y3QgaW50ZXJ2YWxfdHJlZV9ub2RlIGlvdmE7Cj4+PiArICAgICB1bnNp Z25lZCBsb25nIG9yaWc7Cj4+Cj4+IE5lZWQgYSBiZXR0ZXIgbmFtZSwgcHJvYmFibHkgInZhIj8K Pj4KPiBGaW5lLgo+Cj4+PiArICAgICBzaXplX3Qgc2l6ZTsKPj4+ICsgICAgIGVudW0gZG1hX2Rh dGFfZGlyZWN0aW9uIGRpcjsKPj4+ICt9Owo+Pj4gKwo+Pj4gK3N0cnVjdCB2ZHVzZV9pb3ZhX2Rv bWFpbiB7Cj4+PiArICAgICBzdHJ1Y3QgaW92YV9kb21haW4gc3RyZWFtX2lvdmFkOwo+Pj4gKyAg ICAgc3RydWN0IGlvdmFfZG9tYWluIGNvbnNpc3RlbnRfaW92YWQ7Cj4+PiArICAgICBzdHJ1Y3Qg cGFnZSAqKmJvdW5jZV9wYWdlczsKPj4+ICsgICAgIHNpemVfdCBib3VuY2Vfc2l6ZTsKPj4+ICsg ICAgIHN0cnVjdCByYl9yb290X2NhY2hlZCBtYXBwaW5nczsKPj4KPj4gV2UgaGFkIElPVExCLCBh bnkgcmVhc29uIGZvciB0aGlzIGV4dHJhIG1hcHBpbmdzIGhlcmU/Cj4+Cj4gSXQgaXMgdXNlZCB0 byBzdG9yZSBpb3ZhIDwtPiB2ZHVzZV9pb3ZhX21hcCAodmFkZHIsIHNpemUsIGRpcikKPiBtYXBw aW5nLiBXZSBtdXN0IHVzZSBpdCB0byBrbm93IGhvdyB0byBkbyBETUEgYm91bmNpbmcgZHVyaW5n IGRtYQo+IHVubWFwcGluZy4KCgpSaWdodCwgc28gSSBtZWFudCBjb25zaWRlciB3ZSBzdXBwb3J0 IG9wYXF1ZSBkYXRhIGluIHRoZSB2aG9zdCBJT1RMQi4gSXQgCmxvb2tzIHRvIG1lIHdlIGNhbiBw aWdneWJhY2sgdGhlICJvcmlnIiBpbiB0aGUgb3BhcXVlLiBUaGVuIHRoZXJlJ3Mgbm8gCm5lZWQg Zm9yIGFuIGV4dHJhIGludGVydmFsIHRyZWU/CgoKPgo+Pj4gKyAgICAgc3BpbmxvY2tfdCBtYXBf bG9jazsKPj4+ICsgICAgIHN0cnVjdCBmaWxlICpmaWxlOwo+Pj4gK307Cj4+PiArCj4+PiArc3Rh dGljIGlubGluZSBzdHJ1Y3QgZmlsZSAqCj4+PiArdmR1c2VfZG9tYWluX2ZpbGUoc3RydWN0IHZk dXNlX2lvdmFfZG9tYWluICpkb21haW4pCj4+PiArewo+Pj4gKyAgICAgcmV0dXJuIGRvbWFpbi0+ ZmlsZTsKPj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIGlubGluZSB1bnNpZ25lZCBsb25nCj4+PiAr dmR1c2VfZG9tYWluX2dldF9vZmZzZXQoc3RydWN0IHZkdXNlX2lvdmFfZG9tYWluICpkb21haW4s IHVuc2lnbmVkIGxvbmcgaW92YSkKPj4+ICt7Cj4+PiArICAgICByZXR1cm4gaW92YTsKPj4+ICt9 Cj4+PiArCj4+PiArZG1hX2FkZHJfdCB2ZHVzZV9kb21haW5fbWFwX3BhZ2Uoc3RydWN0IHZkdXNl X2lvdmFfZG9tYWluICpkb21haW4sCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICBz dHJ1Y3QgcGFnZSAqcGFnZSwgdW5zaWduZWQgbG9uZyBvZmZzZXQsCj4+PiArICAgICAgICAgICAg ICAgICAgICAgICAgICAgICBzaXplX3Qgc2l6ZSwgZW51bSBkbWFfZGF0YV9kaXJlY3Rpb24gZGly LAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5zaWduZWQgbG9uZyBhdHRycyk7 Cj4+PiArCj4+PiArdm9pZCB2ZHVzZV9kb21haW5fdW5tYXBfcGFnZShzdHJ1Y3QgdmR1c2VfaW92 YV9kb21haW4gKmRvbWFpbiwKPj4+ICsgICAgICAgICAgICAgICAgICAgICBkbWFfYWRkcl90IGRt YV9hZGRyLCBzaXplX3Qgc2l6ZSwKPj4+ICsgICAgICAgICAgICAgICAgICAgICBlbnVtIGRtYV9k YXRhX2RpcmVjdGlvbiBkaXIsIHVuc2lnbmVkIGxvbmcgYXR0cnMpOwo+Pj4gKwo+Pj4gK3ZvaWQg KnZkdXNlX2RvbWFpbl9hbGxvY19jb2hlcmVudChzdHJ1Y3QgdmR1c2VfaW92YV9kb21haW4gKmRv bWFpbiwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemVfdCBzaXplLCBkbWFf YWRkcl90ICpkbWFfYWRkciwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdmcF90 IGZsYWcsIHVuc2lnbmVkIGxvbmcgYXR0cnMpOwo+Pj4gKwo+Pj4gK3ZvaWQgdmR1c2VfZG9tYWlu X2ZyZWVfY29oZXJlbnQoc3RydWN0IHZkdXNlX2lvdmFfZG9tYWluICpkb21haW4sIHNpemVfdCBz aXplLAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdm9pZCAqdmFkZHIsIGRtYV9h ZGRyX3QgZG1hX2FkZHIsCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bnNpZ25l ZCBsb25nIGF0dHJzKTsKPj4+ICsKPj4+ICt2b2lkIHZkdXNlX2RvbWFpbl9kZXN0cm95KHN0cnVj dCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluKTsKPj4+ICsKPj4+ICtzdHJ1Y3QgdmR1c2VfaW92 YV9kb21haW4gKnZkdXNlX2RvbWFpbl9jcmVhdGUoc2l6ZV90IGJvdW5jZV9zaXplKTsKPj4+ICsK Pj4+ICsjZW5kaWYgLyogX1ZEVVNFX0lPVkFfRE9NQUlOX0ggKi8KPj4+IGRpZmYgLS1naXQgYS9k cml2ZXJzL3ZkcGEvdmRwYV91c2VyL3ZkdXNlLmggYi9kcml2ZXJzL3ZkcGEvdmRwYV91c2VyL3Zk dXNlLmgKPj4+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4+PiBpbmRleCAwMDAwMDAwMDAwMDAuLjM1 NjZkMjI5MzgyZQo+Pj4gLS0tIC9kZXYvbnVsbAo+Pj4gKysrIGIvZHJpdmVycy92ZHBhL3ZkcGFf dXNlci92ZHVzZS5oCj4+PiBAQCAtMCwwICsxLDYyIEBACj4+PiArLyogU1BEWC1MaWNlbnNlLUlk ZW50aWZpZXI6IEdQTC0yLjAtb25seSAqLwo+Pj4gKy8qCj4+PiArICogVkRVU0U6IHZEUEEgRGV2 aWNlIGluIFVzZXJzcGFjZQo+Pj4gKyAqCj4+PiArICogQ29weXJpZ2h0IChDKSAyMDIwIEJ5dGVk YW5jZSBJbmMuIGFuZC9vciBpdHMgYWZmaWxpYXRlcy4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KPj4+ ICsgKgo+Pj4gKyAqIEF1dGhvcjogWGllIFlvbmdqaSA8eGlleW9uZ2ppQGJ5dGVkYW5jZS5jb20+ Cj4+PiArICoKPj4+ICsgKi8KPj4+ICsKPj4+ICsjaWZuZGVmIF9WRFVTRV9ICj4+PiArI2RlZmlu ZSBfVkRVU0VfSAo+Pj4gKwo+Pj4gKyNpbmNsdWRlIDxsaW51eC9ldmVudGZkLmg+Cj4+PiArI2lu Y2x1ZGUgPGxpbnV4L3dhaXQuaD4KPj4+ICsjaW5jbHVkZSA8bGludXgvdmRwYS5oPgo+Pj4gKwo+ Pj4gKyNpbmNsdWRlICJpb3ZhX2RvbWFpbi5oIgo+Pj4gKyNpbmNsdWRlICJldmVudGZkLmgiCj4+ PiArCj4+PiArc3RydWN0IHZkdXNlX3ZpcnRxdWV1ZSB7Cj4+PiArICAgICB1MTYgaW5kZXg7Cj4+ PiArICAgICBib29sIHJlYWR5Owo+Pj4gKyAgICAgc3BpbmxvY2tfdCBraWNrX2xvY2s7Cj4+PiAr ICAgICBzcGlubG9ja190IGlycV9sb2NrOwo+Pj4gKyAgICAgc3RydWN0IGV2ZW50ZmRfY3R4ICpr aWNrZmQ7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfdmlycWZkICp2aXJxZmQ7Cj4+PiArICAgICB2 b2lkICpwcml2YXRlOwo+Pj4gKyAgICAgaXJxcmV0dXJuX3QgKCpjYikodm9pZCAqZGF0YSk7Cj4+ PiArfTsKPj4+ICsKPj4+ICtzdHJ1Y3QgdmR1c2VfZGV2Owo+Pj4gKwo+Pj4gK3N0cnVjdCB2ZHVz ZV92ZHBhIHsKPj4+ICsgICAgIHN0cnVjdCB2ZHBhX2RldmljZSB2ZHBhOwo+Pj4gKyAgICAgc3Ry dWN0IHZkdXNlX2RldiAqZGV2Owo+Pj4gK307Cj4+PiArCj4+PiArc3RydWN0IHZkdXNlX2RldiB7 Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfdmRwYSAqdmRldjsKPj4+ICsgICAgIHN0cnVjdCBtdXRl eCBsb2NrOwo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX3ZpcnRxdWV1ZSAqdnFzOwo+Pj4gKyAgICAg c3RydWN0IHZkdXNlX2lvdmFfZG9tYWluICpkb21haW47Cj4+PiArICAgICBzdHJ1Y3Qgdmhvc3Rf aW90bGIgKmlvbW11Owo+Pj4gKyAgICAgc3BpbmxvY2tfdCBpb21tdV9sb2NrOwo+Pj4gKyAgICAg YXRvbWljX3QgYm91bmNlX21hcDsKPj4+ICsgICAgIHNwaW5sb2NrX3QgbXNnX2xvY2s7Cj4+PiAr ICAgICBhdG9taWM2NF90IG1zZ191bmlxdWU7Cj4+PiArICAgICB3YWl0X3F1ZXVlX2hlYWRfdCB3 YWl0cTsKPj4+ICsgICAgIHN0cnVjdCBsaXN0X2hlYWQgc2VuZF9saXN0Owo+Pj4gKyAgICAgc3Ry dWN0IGxpc3RfaGVhZCByZWN2X2xpc3Q7Cj4+PiArICAgICBzdHJ1Y3QgbGlzdF9oZWFkIGxpc3Q7 Cj4+PiArICAgICBib29sIGNvbm5lY3RlZDsKPj4+ICsgICAgIHUzMiBpZDsKPj4+ICsgICAgIHUx NiB2cV9zaXplX21heDsKPj4+ICsgICAgIHUxNiB2cV9udW07Cj4+PiArICAgICB1MzIgdnFfYWxp Z247Cj4+PiArICAgICB1MzIgZGV2aWNlX2lkOwo+Pj4gKyAgICAgdTMyIHZlbmRvcl9pZDsKPj4+ ICt9Owo+Pj4gKwo+Pj4gKyNlbmRpZiAvKiBfVkRVU0VfSF8gKi8KPj4+IGRpZmYgLS1naXQgYS9k cml2ZXJzL3ZkcGEvdmRwYV91c2VyL3ZkdXNlX2Rldi5jIGIvZHJpdmVycy92ZHBhL3ZkcGFfdXNl ci92ZHVzZV9kZXYuYwo+Pj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPj4+IGluZGV4IDAwMDAwMDAw MDAwMC4uMWNmNzU5YmM1OTE0Cj4+PiAtLS0gL2Rldi9udWxsCj4+PiArKysgYi9kcml2ZXJzL3Zk cGEvdmRwYV91c2VyL3ZkdXNlX2Rldi5jCj4+PiBAQCAtMCwwICsxLDEyMTcgQEAKPj4+ICsvLyBT UERYLUxpY2Vuc2UtSWRlbnRpZmllcjogR1BMLTIuMC1vbmx5Cj4+PiArLyoKPj4+ICsgKiBWRFVT RTogdkRQQSBEZXZpY2UgaW4gVXNlcnNwYWNlCj4+PiArICoKPj4+ICsgKiBDb3B5cmlnaHQgKEMp IDIwMjAgQnl0ZWRhbmNlIEluYy4gYW5kL29yIGl0cyBhZmZpbGlhdGVzLiBBbGwgcmlnaHRzIHJl c2VydmVkLgo+Pj4gKyAqCj4+PiArICogQXV0aG9yOiBYaWUgWW9uZ2ppIDx4aWV5b25namlAYnl0 ZWRhbmNlLmNvbT4KPj4+ICsgKgo+Pj4gKyAqLwo+Pj4gKwo+Pj4gKyNpbmNsdWRlIDxsaW51eC9p bml0Lmg+Cj4+PiArI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPgo+Pj4gKyNpbmNsdWRlIDxsaW51 eC9taXNjZGV2aWNlLmg+Cj4+PiArI2luY2x1ZGUgPGxpbnV4L2RldmljZS5oPgo+Pj4gKyNpbmNs dWRlIDxsaW51eC9ldmVudGZkLmg+Cj4+PiArI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4KPj4+ICsj aW5jbHVkZSA8bGludXgvd2FpdC5oPgo+Pj4gKyNpbmNsdWRlIDxsaW51eC9kbWEtbWFwLW9wcy5o Pgo+Pj4gKyNpbmNsdWRlIDxsaW51eC9hbm9uX2lub2Rlcy5oPgo+Pj4gKyNpbmNsdWRlIDxsaW51 eC9maWxlLmg+Cj4+PiArI2luY2x1ZGUgPGxpbnV4L3Vpby5oPgo+Pj4gKyNpbmNsdWRlIDxsaW51 eC92ZHBhLmg+Cj4+PiArI2luY2x1ZGUgPHVhcGkvbGludXgvdmR1c2UuaD4KPj4+ICsjaW5jbHVk ZSA8dWFwaS9saW51eC92ZHBhLmg+Cj4+PiArI2luY2x1ZGUgPHVhcGkvbGludXgvdmlydGlvX2Nv bmZpZy5oPgo+Pj4gKyNpbmNsdWRlIDxsaW51eC9tb2RfZGV2aWNldGFibGUuaD4KPj4+ICsKPj4+ ICsjaW5jbHVkZSAidmR1c2UuaCIKPj4+ICsKPj4+ICsjZGVmaW5lIERSVl9WRVJTSU9OICAiMS4w Igo+Pj4gKyNkZWZpbmUgRFJWX0FVVEhPUiAgICJZb25namkgWGllIDx4aWV5b25namlAYnl0ZWRh bmNlLmNvbT4iCj4+PiArI2RlZmluZSBEUlZfREVTQyAgICAgInZEUEEgRGV2aWNlIGluIFVzZXJz cGFjZSIKPj4+ICsjZGVmaW5lIERSVl9MSUNFTlNFICAiR1BMIHYyIgo+Pj4gKwo+Pj4gK3N0cnVj dCB2ZHVzZV9kZXZfbXNnIHsKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXZfcmVxdWVzdCByZXE7 Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfZGV2X3Jlc3BvbnNlIHJlc3A7Cj4+PiArICAgICBzdHJ1 Y3QgbGlzdF9oZWFkIGxpc3Q7Cj4+PiArICAgICB3YWl0X3F1ZXVlX2hlYWRfdCB3YWl0cTsKPj4+ ICsgICAgIGJvb2wgY29tcGxldGVkOwo+Pj4gKyAgICAgcmVmY291bnRfdCByZWZjbnQ7Cj4+Cj4+ IFRoZSByZWZlcmVuY2UgY291bnQgaGVyZSB3aWxsIGJyaW5nIGV4dHJhIGNvbXBsZXhpdHkuIEkg dGhpbmsgd2UgY2FuCj4+IHN5bmMgdGhyb3VnaCBtc2dfbG9jay4KPj4KPiBEbyB5b3UgbWVhbiB1 c2luZyB3YWl0X2V2ZW50X2ludGVycnVwdGlibGVfbG9ja2VkKCkgYW5kCj4gd2FrZV91cF9sb2Nr ZWQoKT8gSSB0aGluayBpdCB3b3Jrcy4KCgpSaWdodC4KCgo+Cj4+Cj4+PiArfTsKPj4+ICsKPj4+ ICtzdGF0aWMgc3RydWN0IHdvcmtxdWV1ZV9zdHJ1Y3QgKnZkdXNlX3ZkcGFfd3E7Cj4+PiArc3Rh dGljIERFRklORV9NVVRFWCh2ZHVzZV9sb2NrKTsKPj4+ICtzdGF0aWMgTElTVF9IRUFEKHZkdXNl X2RldnMpOwo+Pj4gKwo+Pj4gK3N0YXRpYyBpbmxpbmUgc3RydWN0IHZkdXNlX2RldiAqdmRwYV90 b192ZHVzZShzdHJ1Y3QgdmRwYV9kZXZpY2UgKnZkcGEpCj4+PiArewo+Pj4gKyAgICAgc3RydWN0 IHZkdXNlX3ZkcGEgKnZkZXYgPSBjb250YWluZXJfb2YodmRwYSwgc3RydWN0IHZkdXNlX3ZkcGEs IHZkcGEpOwo+Pj4gKwo+Pj4gKyAgICAgcmV0dXJuIHZkZXYtPmRldjsKPj4+ICt9Cj4+PiArCj4+ PiArc3RhdGljIGlubGluZSBzdHJ1Y3QgdmR1c2VfZGV2ICpkZXZfdG9fdmR1c2Uoc3RydWN0IGRl dmljZSAqZGV2KQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHBhX2RldmljZSAqdmRwYSA9IGRl dl90b192ZHBhKGRldik7Cj4+PiArCj4+PiArICAgICByZXR1cm4gdmRwYV90b192ZHVzZSh2ZHBh KTsKPj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIHN0cnVjdCB2ZHVzZV9kZXZfbXNnICp2ZHVzZV9k ZXZfbmV3X21zZyhzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYsIGludCB0eXBlKQo+Pj4gK3sKPj4+ICsg ICAgIHN0cnVjdCB2ZHVzZV9kZXZfbXNnICptc2cgPSBremFsbG9jKHNpemVvZigqbXNnKSwKPj4+ ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR0ZQX0tFUk5FTCB8IF9fR0ZQ X05PRkFJTCk7Cj4+PiArCj4+PiArICAgICBtc2ctPnJlcS50eXBlID0gdHlwZTsKPj4+ICsgICAg IG1zZy0+cmVxLnVuaXF1ZSA9IGF0b21pYzY0X2ZldGNoX2luYygmZGV2LT5tc2dfdW5pcXVlKTsK Pj4KPj4gVGhpcyBsb29rcyBub3Qgc2FmZSwgbGV0J3MgdXNlIGlkciBoZXJlLgo+Pgo+IENvdWxk IHlvdSBnaXZlIG1vcmUgZGV0YWlscz8gTG9va3MgbGlrZSBpZHIgc2hvdWxkIG5vdCB1c2VkIGlu IHRoaXMKPiBjYXNlIHdoaWNoIGNhbiBub3QgdG9sZXJhdGUgZmFpbHVyZS4gQW5kIHVzaW5nIGEg bGlzdCB0byBzdG9yZSB0aGUgbXNnCj4gaXMgYmV0dGVyIHRoYW4gdXNpbmcgaWRyIHdoZW4gdGhl IG1zZyBuZWVkcyB0byBiZSByZS1pbnNlcnRlZCBpbiBzb21lCj4gY2FzZXMuCgoKTXkgdW5kZXJz dGFuZGluZyBpcyB0aGUgInVuaXF1ZSIgKHByb2JhYmx5IG5lZWQgYSBiZXR0ZXIgbmFtZSkgaXMg YSAKdG9rZW4gdGhhdCBpcyB1c2VkIHRvIHVuaXF1ZWx5IGlkZW50aWZ5IGEgbWVzc2FnZS4gVGhl IHJlcGx5IGZyb20gCnVzZXJzcGFjZSBpcyByZXF1aXJlZCB0byB3cml0ZSB3aXRoIGV4YWN0IHRo ZSBzYW1lIHRva2VuKHVuaXF1ZSkuIElEUiAKc2VlbXMgYmV0dGVyIGJ1dCBjb25zaWRlciB3ZSBj YW4gaGFyZGx5IGhpdCA2NGJpdCBvdmVyZmxvdywgYXRvbWljIG1pZ2h0IApiZSBPSyBhcyB3ZWxs LgoKQnR3LCB1bmRlciB3aGF0IGNhc2UgZG8gd2UgbmVlZCB0byBkbyAicmUtaW5zZXJ0ZWQiPwoK Cj4KPj4+ICsgICAgIGluaXRfd2FpdHF1ZXVlX2hlYWQoJm1zZy0+d2FpdHEpOwo+Pj4gKyAgICAg cmVmY291bnRfc2V0KCZtc2ctPnJlZmNudCwgMSk7Cj4+PiArCj4+PiArICAgICByZXR1cm4gbXNn Owo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgdm9pZCB2ZHVzZV9kZXZfbXNnX2dldChzdHJ1Y3Qg dmR1c2VfZGV2X21zZyAqbXNnKQo+Pj4gK3sKPj4+ICsgICAgIHJlZmNvdW50X2luYygmbXNnLT5y ZWZjbnQpOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgdm9pZCB2ZHVzZV9kZXZfbXNnX3B1dChz dHJ1Y3QgdmR1c2VfZGV2X21zZyAqbXNnKQo+Pj4gK3sKPj4+ICsgICAgIGlmIChyZWZjb3VudF9k ZWNfYW5kX3Rlc3QoJm1zZy0+cmVmY250KSkKPj4+ICsgICAgICAgICAgICAga2ZyZWUobXNnKTsK Pj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIHN0cnVjdCB2ZHVzZV9kZXZfbXNnICp2ZHVzZV9kZXZf ZmluZF9tc2coc3RydWN0IHZkdXNlX2RldiAqZGV2LAo+Pj4gKyAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBsaXN0X2hlYWQgKmhlYWQsCj4+PiArICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdWludDMyX3QgdW5pcXVl KQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXZfbXNnICp0bXAsICptc2cgPSBOVUxM Owo+Pj4gKwo+Pj4gKyAgICAgc3Bpbl9sb2NrKCZkZXYtPm1zZ19sb2NrKTsKPj4+ICsgICAgIGxp c3RfZm9yX2VhY2hfZW50cnkodG1wLCBoZWFkLCBsaXN0KSB7Cj4+PiArICAgICAgICAgICAgIGlm ICh0bXAtPnJlcS51bmlxdWUgPT0gdW5pcXVlKSB7Cj4+PiArICAgICAgICAgICAgICAgICAgICAg bXNnID0gdG1wOwo+Pj4gKyAgICAgICAgICAgICAgICAgICAgIGxpc3RfZGVsKCZ0bXAtPmxpc3Qp Owo+Pj4gKyAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwo+Pj4gKyAgICAgICAgICAgICB9Cj4+ PiArICAgICB9Cj4+PiArICAgICBzcGluX3VubG9jaygmZGV2LT5tc2dfbG9jayk7Cj4+PiArCj4+ PiArICAgICByZXR1cm4gbXNnOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgc3RydWN0IHZkdXNl X2Rldl9tc2cgKnZkdXNlX2Rldl9kZXF1ZXVlX21zZyhzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYsCj4+ PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IGxp c3RfaGVhZCAqaGVhZCkKPj4+ICt7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfZGV2X21zZyAqbXNn ID0gTlVMTDsKPj4+ICsKPj4+ICsgICAgIHNwaW5fbG9jaygmZGV2LT5tc2dfbG9jayk7Cj4+PiAr ICAgICBpZiAoIWxpc3RfZW1wdHkoaGVhZCkpIHsKPj4+ICsgICAgICAgICAgICAgbXNnID0gbGlz dF9maXJzdF9lbnRyeShoZWFkLCBzdHJ1Y3QgdmR1c2VfZGV2X21zZywgbGlzdCk7Cj4+PiArICAg ICAgICAgICAgIGxpc3RfZGVsKCZtc2ctPmxpc3QpOwo+Pj4gKyAgICAgfQo+Pj4gKyAgICAgc3Bp bl91bmxvY2soJmRldi0+bXNnX2xvY2spOwo+Pj4gKwo+Pj4gKyAgICAgcmV0dXJuIG1zZzsKPj4+ ICt9Cj4+PiArCj4+PiArc3RhdGljIHZvaWQgdmR1c2VfZGV2X2VucXVldWVfbXNnKHN0cnVjdCB2 ZHVzZV9kZXYgKmRldiwKPj4+ICsgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3QgdmR1c2VfZGV2 X21zZyAqbXNnLCBzdHJ1Y3QgbGlzdF9oZWFkICpoZWFkKQo+Pj4gK3sKPj4+ICsgICAgIHNwaW5f bG9jaygmZGV2LT5tc2dfbG9jayk7Cj4+PiArICAgICBsaXN0X2FkZF90YWlsKCZtc2ctPmxpc3Qs IGhlYWQpOwo+Pj4gKyAgICAgc3Bpbl91bmxvY2soJmRldi0+bXNnX2xvY2spOwo+Pj4gK30KPj4+ ICsKPj4+ICtzdGF0aWMgaW50IHZkdXNlX2Rldl9tc2dfc3luYyhzdHJ1Y3QgdmR1c2VfZGV2ICpk ZXYsIHN0cnVjdCB2ZHVzZV9kZXZfbXNnICptc2cpCj4+PiArewo+Pj4gKyAgICAgaW50IHJldDsK Pj4+ICsKPj4+ICsgICAgIHZkdXNlX2Rldl9lbnF1ZXVlX21zZyhkZXYsIG1zZywgJmRldi0+c2Vu ZF9saXN0KTsKPj4+ICsgICAgIHdha2VfdXAoJmRldi0+d2FpdHEpOwo+Pj4gKyAgICAgd2FpdF9l dmVudChtc2ctPndhaXRxLCBtc2ctPmNvbXBsZXRlZCk7Cj4+Cj4+IFRoaXMgaXMgdW5pbnRlcnJ1 cHRpYmxlIHdhaXQsIGl0IG1lYW5zIGlmIHRoZSB1c2Vyc3BhY2UgZm9yZ2V0IHRvCj4+IHByb2Nl c3MgdGhlIGNvbW1hbmQsIHdlIHdpbGwgc3R1Y2sgaGVyZSBmb3JldmVyLgo+Pgo+IFllcywgd2Fp dF9ldmVudF9pbnRlcnJ1cHRpYmxlKCkgc2hvdWxkIGJlIGJldHRlciBoZXJlLgo+Cj4+PiArICAg ICAvKiBjb3VwbGVkIHdpdGggc21wX3dtYigpIGluIHZkdXNlX2Rldl9tc2dfY29tcGxldGUoKSAq Lwo+Pj4gKyAgICAgc21wX3JtYigpOwo+Pgo+PiBJbnN0ZWFkIG9mIHVzaW5nIGJhcnJpZXJzLCBJ IHdvbmRlciB3aHkgbm90IHNpbXBseSB1c2UgbXNnIGxvY2sgaGVyZT8KPj4KPiBBcyBtZW50aW9u ZWQgYWJvdmUsIHVzaW5nCj4gd2FpdF9ldmVudF9pbnRlcnJ1cHRpYmxlX2xvY2tlZCgpL3dha2Vf dXBfbG9ja2VkKCkgaXMgT0sgdG8gbWUuCj4KPj4+ICsgICAgIHJldCA9IG1zZy0+cmVzcC5yZXN1 bHQ7Cj4+PiArCj4+PiArICAgICByZXR1cm4gcmV0Owo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMg dm9pZCB2ZHVzZV9kZXZfbXNnX2NvbXBsZXRlKHN0cnVjdCB2ZHVzZV9kZXZfbXNnICptc2csCj4+ PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCB2ZHVzZV9kZXZf cmVzcG9uc2UgKnJlc3ApCj4+PiArewo+Pj4gKyAgICAgdmR1c2VfZGV2X21zZ19nZXQobXNnKTsK Pj4+ICsgICAgIG1lbWNweSgmbXNnLT5yZXNwLCByZXNwLCBzaXplb2YoKnJlc3ApKTsKPj4+ICsg ICAgIC8qIGNvdXBsZWQgd2l0aCBzbXBfcm1iKCkgaW4gdmR1c2VfZGV2X21zZ19zeW5jKCkgKi8K Pj4+ICsgICAgIHNtcF93bWIoKTsKPj4+ICsgICAgIG1zZy0+Y29tcGxldGVkID0gMTsKPj4+ICsg ICAgIHdha2VfdXAoJm1zZy0+d2FpdHEpOwo+Pj4gKyAgICAgdmR1c2VfZGV2X21zZ19wdXQobXNn KTsKPj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIHU2NCB2ZHVzZV9kZXZfZ2V0X2ZlYXR1cmVzKHN0 cnVjdCB2ZHVzZV9kZXYgKmRldikKPj4+ICt7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfZGV2X21z ZyAqbXNnID0gdmR1c2VfZGV2X25ld19tc2coZGV2LCBWRFVTRV9HRVRfRkVBVFVSRVMpOwo+Pj4g KyAgICAgdTY0IGZlYXR1cmVzOwo+Pj4gKwo+Pj4gKyAgICAgdmR1c2VfZGV2X21zZ19zeW5jKGRl diwgbXNnKTsKPj4+ICsgICAgIGZlYXR1cmVzID0gbXNnLT5yZXNwLmZlYXR1cmVzOwo+Pj4gKyAg ICAgdmR1c2VfZGV2X21zZ19wdXQobXNnKTsKPj4+ICsKPj4+ICsgICAgIHJldHVybiBmZWF0dXJl czsKPj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIGludCB2ZHVzZV9kZXZfc2V0X2ZlYXR1cmVzKHN0 cnVjdCB2ZHVzZV9kZXYgKmRldiwgdTY0IGZlYXR1cmVzKQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVj dCB2ZHVzZV9kZXZfbXNnICptc2cgPSB2ZHVzZV9kZXZfbmV3X21zZyhkZXYsIFZEVVNFX1NFVF9G RUFUVVJFUyk7Cj4+PiArICAgICBpbnQgcmV0Owo+Pj4gKwo+Pj4gKyAgICAgbXNnLT5yZXEuc2l6 ZSA9IHNpemVvZihmZWF0dXJlcyk7Cj4+PiArICAgICBtc2ctPnJlcS5mZWF0dXJlcyA9IGZlYXR1 cmVzOwo+Pj4gKwo+Pj4gKyAgICAgcmV0ID0gdmR1c2VfZGV2X21zZ19zeW5jKGRldiwgbXNnKTsK Pj4+ICsgICAgIHZkdXNlX2Rldl9tc2dfcHV0KG1zZyk7Cj4+PiArCj4+PiArICAgICByZXR1cm4g cmV0Owo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgdTggdmR1c2VfZGV2X2dldF9zdGF0dXMoc3Ry dWN0IHZkdXNlX2RldiAqZGV2KQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXZfbXNn ICptc2cgPSB2ZHVzZV9kZXZfbmV3X21zZyhkZXYsIFZEVVNFX0dFVF9TVEFUVVMpOwo+Pj4gKyAg ICAgdTggc3RhdHVzOwo+Pj4gKwo+Pj4gKyAgICAgdmR1c2VfZGV2X21zZ19zeW5jKGRldiwgbXNn KTsKPj4+ICsgICAgIHN0YXR1cyA9IG1zZy0+cmVzcC5zdGF0dXM7Cj4+PiArICAgICB2ZHVzZV9k ZXZfbXNnX3B1dChtc2cpOwo+Pj4gKwo+Pj4gKyAgICAgcmV0dXJuIHN0YXR1czsKPj4+ICt9Cj4+ PiArCj4+PiArc3RhdGljIHZvaWQgdmR1c2VfZGV2X3NldF9zdGF0dXMoc3RydWN0IHZkdXNlX2Rl diAqZGV2LCB1OCBzdGF0dXMpCj4+PiArewo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX2Rldl9tc2cg Km1zZyA9IHZkdXNlX2Rldl9uZXdfbXNnKGRldiwgVkRVU0VfU0VUX1NUQVRVUyk7Cj4+PiArCj4+ PiArICAgICBtc2ctPnJlcS5zaXplID0gc2l6ZW9mKHN0YXR1cyk7Cj4+PiArICAgICBtc2ctPnJl cS5zdGF0dXMgPSBzdGF0dXM7Cj4+PiArCj4+PiArICAgICB2ZHVzZV9kZXZfbXNnX3N5bmMoZGV2 LCBtc2cpOwo+Pj4gKyAgICAgdmR1c2VfZGV2X21zZ19wdXQobXNnKTsKPj4+ICt9Cj4+PiArCj4+ PiArc3RhdGljIHZvaWQgdmR1c2VfZGV2X2dldF9jb25maWcoc3RydWN0IHZkdXNlX2RldiAqZGV2 LCB1bnNpZ25lZCBpbnQgb2Zmc2V0LAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICB2b2lkICpidWYsIHVuc2lnbmVkIGludCBsZW4pCj4+PiArewo+Pj4gKyAgICAgc3Ry dWN0IHZkdXNlX2Rldl9tc2cgKm1zZyA9IHZkdXNlX2Rldl9uZXdfbXNnKGRldiwgVkRVU0VfR0VU X0NPTkZJRyk7Cj4+PiArCj4+PiArICAgICBXQVJOX09OKGxlbiA+IHNpemVvZihtc2ctPnJlcS5j b25maWcuZGF0YSkpOwo+Pj4gKwo+Pj4gKyAgICAgbXNnLT5yZXEuc2l6ZSA9IHNpemVvZihzdHJ1 Y3QgdmR1c2VfZGV2X2NvbmZpZ19kYXRhKTsKPj4+ICsgICAgIG1zZy0+cmVxLmNvbmZpZy5vZmZz ZXQgPSBvZmZzZXQ7Cj4+PiArICAgICBtc2ctPnJlcS5jb25maWcubGVuID0gbGVuOwo+Pj4gKyAg ICAgdmR1c2VfZGV2X21zZ19zeW5jKGRldiwgbXNnKTsKPj4+ICsgICAgIG1lbWNweShidWYsIG1z Zy0+cmVzcC5jb25maWcuZGF0YSwgbGVuKTsKPj4+ICsgICAgIHZkdXNlX2Rldl9tc2dfcHV0KG1z Zyk7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyB2b2lkIHZkdXNlX2Rldl9zZXRfY29uZmlnKHN0 cnVjdCB2ZHVzZV9kZXYgKmRldiwgdW5zaWduZWQgaW50IG9mZnNldCwKPj4+ICsgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgdm9pZCAqYnVmLCB1bnNpZ25lZCBpbnQg bGVuKQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXZfbXNnICptc2cgPSB2ZHVzZV9k ZXZfbmV3X21zZyhkZXYsIFZEVVNFX1NFVF9DT05GSUcpOwo+Pj4gKwo+Pj4gKyAgICAgV0FSTl9P TihsZW4gPiBzaXplb2YobXNnLT5yZXEuY29uZmlnLmRhdGEpKTsKPj4+ICsKPj4+ICsgICAgIG1z Zy0+cmVxLnNpemUgPSBzaXplb2Yoc3RydWN0IHZkdXNlX2Rldl9jb25maWdfZGF0YSk7Cj4+PiAr ICAgICBtc2ctPnJlcS5jb25maWcub2Zmc2V0ID0gb2Zmc2V0Owo+Pj4gKyAgICAgbXNnLT5yZXEu Y29uZmlnLmxlbiA9IGxlbjsKPj4+ICsgICAgIG1lbWNweShtc2ctPnJlcS5jb25maWcuZGF0YSwg YnVmLCBsZW4pOwo+Pj4gKyAgICAgdmR1c2VfZGV2X21zZ19zeW5jKGRldiwgbXNnKTsKPj4+ICsg ICAgIHZkdXNlX2Rldl9tc2dfcHV0KG1zZyk7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyB2b2lk IHZkdXNlX2Rldl9zZXRfdnFfbnVtKHN0cnVjdCB2ZHVzZV9kZXYgKmRldiwKPj4+ICsgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCB2ZHVzZV92aXJ0cXVldWUgKnZxLCB1MzIgbnVt KQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXZfbXNnICptc2cgPSB2ZHVzZV9kZXZf bmV3X21zZyhkZXYsIFZEVVNFX1NFVF9WUV9OVU0pOwo+Pj4gKwo+Pj4gKyAgICAgbXNnLT5yZXEu c2l6ZSA9IHNpemVvZihzdHJ1Y3QgdmR1c2VfdnFfbnVtKTsKPj4+ICsgICAgIG1zZy0+cmVxLnZx X251bS5pbmRleCA9IHZxLT5pbmRleDsKPj4+ICsgICAgIG1zZy0+cmVxLnZxX251bS5udW0gPSBu dW07Cj4+PiArCj4+PiArICAgICB2ZHVzZV9kZXZfbXNnX3N5bmMoZGV2LCBtc2cpOwo+Pj4gKyAg ICAgdmR1c2VfZGV2X21zZ19wdXQobXNnKTsKPj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIGludCB2 ZHVzZV9kZXZfc2V0X3ZxX2FkZHIoc3RydWN0IHZkdXNlX2RldiAqZGV2LAo+Pj4gKyAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgc3RydWN0IHZkdXNlX3ZpcnRxdWV1ZSAqdnEsIHU2NCBkZXNj X2FkZHIsCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1NjQgZHJpdmVyX2FkZHIs IHU2NCBkZXZpY2VfYWRkcikKPj4+ICt7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfZGV2X21zZyAq bXNnID0gdmR1c2VfZGV2X25ld19tc2coZGV2LCBWRFVTRV9TRVRfVlFfQUREUik7Cj4+PiArICAg ICBpbnQgcmV0Owo+Pj4gKwo+Pj4gKyAgICAgbXNnLT5yZXEuc2l6ZSA9IHNpemVvZihzdHJ1Y3Qg dmR1c2VfdnFfYWRkcik7Cj4+PiArICAgICBtc2ctPnJlcS52cV9hZGRyLmluZGV4ID0gdnEtPmlu ZGV4Owo+Pj4gKyAgICAgbXNnLT5yZXEudnFfYWRkci5kZXNjX2FkZHIgPSBkZXNjX2FkZHI7Cj4+ PiArICAgICBtc2ctPnJlcS52cV9hZGRyLmRyaXZlcl9hZGRyID0gZHJpdmVyX2FkZHI7Cj4+PiAr ICAgICBtc2ctPnJlcS52cV9hZGRyLmRldmljZV9hZGRyID0gZGV2aWNlX2FkZHI7Cj4+PiArCj4+ PiArICAgICByZXQgPSB2ZHVzZV9kZXZfbXNnX3N5bmMoZGV2LCBtc2cpOwo+Pj4gKyAgICAgdmR1 c2VfZGV2X21zZ19wdXQobXNnKTsKPj4+ICsKPj4+ICsgICAgIHJldHVybiByZXQ7Cj4+PiArfQo+ Pj4gKwo+Pj4gK3N0YXRpYyB2b2lkIHZkdXNlX2Rldl9zZXRfdnFfcmVhZHkoc3RydWN0IHZkdXNl X2RldiAqZGV2LAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IHZkdXNl X3ZpcnRxdWV1ZSAqdnEsIGJvb2wgcmVhZHkpCj4+PiArewo+Pj4gKyAgICAgc3RydWN0IHZkdXNl X2Rldl9tc2cgKm1zZyA9IHZkdXNlX2Rldl9uZXdfbXNnKGRldiwgVkRVU0VfU0VUX1ZRX1JFQURZ KTsKPj4+ICsKPj4+ICsgICAgIG1zZy0+cmVxLnNpemUgPSBzaXplb2Yoc3RydWN0IHZkdXNlX3Zx X3JlYWR5KTsKPj4+ICsgICAgIG1zZy0+cmVxLnZxX3JlYWR5LmluZGV4ID0gdnEtPmluZGV4Owo+ Pj4gKyAgICAgbXNnLT5yZXEudnFfcmVhZHkucmVhZHkgPSByZWFkeTsKPj4+ICsKPj4+ICsgICAg IHZkdXNlX2Rldl9tc2dfc3luYyhkZXYsIG1zZyk7Cj4+PiArICAgICB2ZHVzZV9kZXZfbXNnX3B1 dChtc2cpOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgYm9vbCB2ZHVzZV9kZXZfZ2V0X3ZxX3Jl YWR5KHN0cnVjdCB2ZHVzZV9kZXYgKmRldiwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIHN0cnVjdCB2ZHVzZV92aXJ0cXVldWUgKnZxKQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVj dCB2ZHVzZV9kZXZfbXNnICptc2cgPSB2ZHVzZV9kZXZfbmV3X21zZyhkZXYsIFZEVVNFX0dFVF9W UV9SRUFEWSk7Cj4+PiArICAgICBib29sIHJlYWR5Owo+Pj4gKwo+Pj4gKyAgICAgbXNnLT5yZXEu c2l6ZSA9IHNpemVvZihzdHJ1Y3QgdmR1c2VfdnFfcmVhZHkpOwo+Pj4gKyAgICAgbXNnLT5yZXEu dnFfcmVhZHkuaW5kZXggPSB2cS0+aW5kZXg7Cj4+PiArCj4+PiArICAgICB2ZHVzZV9kZXZfbXNn X3N5bmMoZGV2LCBtc2cpOwo+Pj4gKyAgICAgcmVhZHkgPSBtc2ctPnJlc3AudnFfcmVhZHkucmVh ZHk7Cj4+PiArICAgICB2ZHVzZV9kZXZfbXNnX3B1dChtc2cpOwo+Pj4gKwo+Pj4gKyAgICAgcmV0 dXJuIHJlYWR5Owo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgaW50IHZkdXNlX2Rldl9nZXRfdnFf c3RhdGUoc3RydWN0IHZkdXNlX2RldiAqZGV2LAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgc3RydWN0IHZkdXNlX3ZpcnRxdWV1ZSAqdnEsCj4+PiArICAgICAgICAgICAgICAgICAg ICAgICAgICAgICBzdHJ1Y3QgdmRwYV92cV9zdGF0ZSAqc3RhdGUpCj4+PiArewo+Pj4gKyAgICAg c3RydWN0IHZkdXNlX2Rldl9tc2cgKm1zZyA9IHZkdXNlX2Rldl9uZXdfbXNnKGRldiwgVkRVU0Vf R0VUX1ZRX1NUQVRFKTsKPj4+ICsgICAgIGludCByZXQ7Cj4+PiArCj4+PiArICAgICBtc2ctPnJl cS5zaXplID0gc2l6ZW9mKHN0cnVjdCB2ZHVzZV92cV9zdGF0ZSk7Cj4+PiArICAgICBtc2ctPnJl cS52cV9zdGF0ZS5pbmRleCA9IHZxLT5pbmRleDsKPj4+ICsKPj4+ICsgICAgIHJldCA9IHZkdXNl X2Rldl9tc2dfc3luYyhkZXYsIG1zZyk7Cj4+PiArICAgICBzdGF0ZS0+YXZhaWxfaW5kZXggPSBt c2ctPnJlc3AudnFfc3RhdGUuYXZhaWxfaWR4Owo+Pj4gKyAgICAgdmR1c2VfZGV2X21zZ19wdXQo bXNnKTsKPj4+ICsKPj4+ICsgICAgIHJldHVybiByZXQ7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRp YyBpbnQgdmR1c2VfZGV2X3NldF92cV9zdGF0ZShzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYsCj4+PiAr ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3QgdmR1c2VfdmlydHF1ZXVlICp2cSwK Pj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0cnVjdCB2ZHBhX3ZxX3N0 YXRlICpzdGF0ZSkKPj4+ICt7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfZGV2X21zZyAqbXNnID0g dmR1c2VfZGV2X25ld19tc2coZGV2LCBWRFVTRV9TRVRfVlFfU1RBVEUpOwo+Pj4gKyAgICAgaW50 IHJldDsKPj4+ICsKPj4+ICsgICAgIG1zZy0+cmVxLnNpemUgPSBzaXplb2Yoc3RydWN0IHZkdXNl X3ZxX3N0YXRlKTsKPj4+ICsgICAgIG1zZy0+cmVxLnZxX3N0YXRlLmluZGV4ID0gdnEtPmluZGV4 Owo+Pj4gKyAgICAgbXNnLT5yZXEudnFfc3RhdGUuYXZhaWxfaWR4ID0gc3RhdGUtPmF2YWlsX2lu ZGV4Owo+Pj4gKwo+Pj4gKyAgICAgcmV0ID0gdmR1c2VfZGV2X21zZ19zeW5jKGRldiwgbXNnKTsK Pj4+ICsgICAgIHZkdXNlX2Rldl9tc2dfcHV0KG1zZyk7Cj4+PiArCj4+PiArICAgICByZXR1cm4g cmV0Owo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgaW50IHZkdXNlX2Rldl91cGRhdGVfaW90bGIo c3RydWN0IHZkdXNlX2RldiAqZGV2LAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICB1NjQgc3RhcnQsIHU2NCBsYXN0KQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVz ZV9kZXZfbXNnICptc2c7Cj4+PiArICAgICBpbnQgcmV0Owo+Pj4gKwo+Pj4gKyAgICAgaWYgKGxh c3QgPCBzdGFydCkKPj4+ICsgICAgICAgICAgICAgcmV0dXJuIC1FSU5WQUw7Cj4+PiArCj4+PiAr ICAgICBtc2cgPSB2ZHVzZV9kZXZfbmV3X21zZyhkZXYsIFZEVVNFX1VQREFURV9JT1RMQik7Cj4+ Cj4+IFRoaXMgaXMgYWN0dWFsbHkgYSBJT1RMQiBpbnZhbGlkYXRpb24uIFNvIGxldCdzIHJlbmFt ZSB0aGUgZnVuY3Rpb24gYW5kCj4+IG1lc3NhZ2UgdHlwZS4KPj4KPiBBY3R1YWxseSBWRFVTRV9V UERBVEVfSU9UTEIgbm93IGlzIHVzZWQgdG8gbm90aWZ5IHVzZXJzcGFjZSB0aGF0IElPVExCCj4g aXMgY2hhbmdlZCByYXRoZXIgdGhhbiBJT1RMQiBuZWVkcyB0byBiZSBpbnZhbGlkYXRlZC4gVGhl biB1c2Vyc3BhY2UKPiBjYW4gdXNlIEdFVF9JT1RMQiBpb2N0bCB0byBnZXQgdGhlIGNoYW5nZS4g SXQgc2VlbXMgdG8gYmUgbW9yZQo+IGZyaWVuZGx5IHRvIHVzZXJzcGFjZS4KCgpPay4KCgo+Cj4+ PiArICAgICBtc2ctPnJlcS5zaXplID0gc2l6ZW9mKHN0cnVjdCB2ZHVzZV9pb3ZhX3JhbmdlKTsK Pj4+ICsgICAgIG1zZy0+cmVxLmlvdmEuc3RhcnQgPSBzdGFydDsKPj4+ICsgICAgIG1zZy0+cmVx LmlvdmEubGFzdCA9IGxhc3Q7Cj4+PiArCj4+PiArICAgICByZXQgPSB2ZHVzZV9kZXZfbXNnX3N5 bmMoZGV2LCBtc2cpOwo+Pj4gKyAgICAgdmR1c2VfZGV2X21zZ19wdXQobXNnKTsKPj4+ICsKPj4+ ICsgICAgIHJldHVybiByZXQ7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyBzc2l6ZV90IHZkdXNl X2Rldl9yZWFkX2l0ZXIoc3RydWN0IGtpb2NiICppb2NiLCBzdHJ1Y3QgaW92X2l0ZXIgKnRvKQo+ Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCBmaWxlICpmaWxlID0gaW9jYi0+a2lfZmlscDsKPj4+ICsg ICAgIHN0cnVjdCB2ZHVzZV9kZXYgKmRldiA9IGZpbGUtPnByaXZhdGVfZGF0YTsKPj4+ICsgICAg IHN0cnVjdCB2ZHVzZV9kZXZfbXNnICptc2c7Cj4+PiArICAgICBpbnQgc2l6ZSA9IHNpemVvZihz dHJ1Y3QgdmR1c2VfZGV2X3JlcXVlc3QpOwo+Pj4gKyAgICAgc3NpemVfdCByZXQgPSAwOwo+Pj4g Kwo+Pj4gKyAgICAgaWYgKGlvdl9pdGVyX2NvdW50KHRvKSA8IHNpemUpCj4+PiArICAgICAgICAg ICAgIHJldHVybiAwOwo+Pj4gKwo+Pj4gKyAgICAgd2hpbGUgKDEpIHsKPj4+ICsgICAgICAgICAg ICAgbXNnID0gdmR1c2VfZGV2X2RlcXVldWVfbXNnKGRldiwgJmRldi0+c2VuZF9saXN0KTsKPj4+ ICsgICAgICAgICAgICAgaWYgKG1zZykKPj4+ICsgICAgICAgICAgICAgICAgICAgICBicmVhazsK Pj4+ICsKPj4+ICsgICAgICAgICAgICAgaWYgKGZpbGUtPmZfZmxhZ3MgJiBPX05PTkJMT0NLKQo+ Pj4gKyAgICAgICAgICAgICAgICAgICAgIHJldHVybiAtRUFHQUlOOwo+Pj4gKwo+Pj4gKyAgICAg ICAgICAgICByZXQgPSB3YWl0X2V2ZW50X2ludGVycnVwdGlibGVfZXhjbHVzaXZlKGRldi0+d2Fp dHEsCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICFsaXN0X2VtcHR5 KCZkZXYtPnNlbmRfbGlzdCkpOwo+Pj4gKyAgICAgICAgICAgICBpZiAocmV0KQo+Pj4gKyAgICAg ICAgICAgICAgICAgICAgIHJldHVybiByZXQ7Cj4+PiArICAgICB9Cj4+PiArICAgICByZXQgPSBj b3B5X3RvX2l0ZXIoJm1zZy0+cmVxLCBzaXplLCB0byk7Cj4+PiArICAgICBpZiAocmV0ICE9IHNp emUpIHsKPj4+ICsgICAgICAgICAgICAgdmR1c2VfZGV2X2VucXVldWVfbXNnKGRldiwgbXNnLCAm ZGV2LT5zZW5kX2xpc3QpOwo+Pj4gKyAgICAgICAgICAgICByZXR1cm4gLUVGQVVMVDsKPj4+ICsg ICAgIH0KPj4+ICsgICAgIHZkdXNlX2Rldl9lbnF1ZXVlX21zZyhkZXYsIG1zZywgJmRldi0+cmVj dl9saXN0KTsKPj4+ICsKPj4+ICsgICAgIHJldHVybiByZXQ7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0 YXRpYyBzc2l6ZV90IHZkdXNlX2Rldl93cml0ZV9pdGVyKHN0cnVjdCBraW9jYiAqaW9jYiwgc3Ry dWN0IGlvdl9pdGVyICpmcm9tKQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCBmaWxlICpmaWxlID0g aW9jYi0+a2lfZmlscDsKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXYgKmRldiA9IGZpbGUtPnBy aXZhdGVfZGF0YTsKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXZfcmVzcG9uc2UgcmVzcDsKPj4+ ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXZfbXNnICptc2c7Cj4+PiArICAgICBzaXplX3QgcmV0Owo+ Pj4gKwo+Pj4gKyAgICAgcmV0ID0gY29weV9mcm9tX2l0ZXIoJnJlc3AsIHNpemVvZihyZXNwKSwg ZnJvbSk7Cj4+PiArICAgICBpZiAocmV0ICE9IHNpemVvZihyZXNwKSkKPj4+ICsgICAgICAgICAg ICAgcmV0dXJuIC1FSU5WQUw7Cj4+PiArCj4+PiArICAgICBtc2cgPSB2ZHVzZV9kZXZfZmluZF9t c2coZGV2LCAmZGV2LT5yZWN2X2xpc3QsIHJlc3AudW5pcXVlKTsKPj4+ICsgICAgIGlmICghbXNn KQo+Pj4gKyAgICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsKPj4+ICsKPj4+ICsgICAgIHZkdXNl X2Rldl9tc2dfY29tcGxldGUobXNnLCAmcmVzcCk7Cj4+Cj4+IFNvIHdlIGhhZCBtdWx0aXBsZSB0 eXBlcyBvZiByZXF1ZXN0cy9yZXNwb25zZXMsIGlzIHRoaXMgYmV0dGVyIHRvCj4+IGludHJvZHVj ZSBhIHF1ZXVlIGJhc2VkIGFkbWluIGludGVyZmFjZSBvdGhlciB0aGFuIGlvY3RsPwo+Pgo+IFNv cnJ5LCBJIGRpZG4ndCBnZXQgeW91ciBwb2ludC4gV2hhdCBkbyB5b3UgbWVhbiBieSBxdWV1ZS1i YXNlZCBhZG1pbgo+IGludGVyZmFjZT8gVmlydHF1ZXVlLWJhc2VkPwoKClllcywgYSBxdWV1ZSh2 aXJ0cXVldWUpLiBUaGUgY29tbWFuZHMgY291bGQgYmUgcGFzc2VkIHRocm91Z2ggdGhlIHF1ZXVl LiAKKEp1c3QgYW4gaWRlYSwgbm90IHN1cmUgaXQncyB3b3J0aCkKCgo+Cj4+PiArCj4+PiArICAg ICByZXR1cm4gcmV0Owo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgX19wb2xsX3QgdmR1c2VfZGV2 X3BvbGwoc3RydWN0IGZpbGUgKmZpbGUsIHBvbGxfdGFibGUgKndhaXQpCj4+PiArewo+Pj4gKyAg ICAgc3RydWN0IHZkdXNlX2RldiAqZGV2ID0gZmlsZS0+cHJpdmF0ZV9kYXRhOwo+Pj4gKyAgICAg X19wb2xsX3QgbWFzayA9IDA7Cj4+PiArCj4+PiArICAgICBwb2xsX3dhaXQoZmlsZSwgJmRldi0+ d2FpdHEsIHdhaXQpOwo+Pj4gKwo+Pj4gKyAgICAgaWYgKCFsaXN0X2VtcHR5KCZkZXYtPnNlbmRf bGlzdCkpCj4+PiArICAgICAgICAgICAgIG1hc2sgfD0gRVBPTExJTiB8IEVQT0xMUkROT1JNOwo+ Pj4gKwo+Pj4gKyAgICAgcmV0dXJuIG1hc2s7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyBpbnQg dmR1c2VfaW90bGJfYWRkX3JhbmdlKHN0cnVjdCB2ZHVzZV9kZXYgKmRldiwKPj4+ICsgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICB1NjQgc3RhcnQsIHU2NCBsYXN0LAo+Pj4gKyAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIHU2NCBhZGRyLCB1bnNpZ25lZCBpbnQgcGVybSwKPj4+ICsg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3QgZmlsZSAqZmlsZSwgdTY0IG9mZnNl dCkKPj4+ICt7Cj4+PiArICAgICBzdHJ1Y3Qgdmhvc3RfaW90bGJfZmlsZSAqaW90bGJfZmlsZTsK Pj4+ICsgICAgIGludCByZXQ7Cj4+PiArCj4+PiArICAgICBpb3RsYl9maWxlID0ga21hbGxvYyhz aXplb2YoKmlvdGxiX2ZpbGUpLCBHRlBfQVRPTUlDKTsKPj4+ICsgICAgIGlmICghaW90bGJfZmls ZSkKPj4+ICsgICAgICAgICAgICAgcmV0dXJuIC1FTk9NRU07Cj4+PiArCj4+PiArICAgICBpb3Rs Yl9maWxlLT5maWxlID0gZ2V0X2ZpbGUoZmlsZSk7Cj4+PiArICAgICBpb3RsYl9maWxlLT5vZmZz ZXQgPSBvZmZzZXQ7Cj4+PiArCj4+PiArICAgICBzcGluX2xvY2soJmRldi0+aW9tbXVfbG9jayk7 Cj4+PiArICAgICByZXQgPSB2aG9zdF9pb3RsYl9hZGRfcmFuZ2UoZGV2LT5pb21tdSwgc3RhcnQs IGxhc3QsCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFkZHIsIHBl cm0sIGlvdGxiX2ZpbGUpOwo+Pj4gKyAgICAgc3Bpbl91bmxvY2soJmRldi0+aW9tbXVfbG9jayk7 Cj4+PiArICAgICBpZiAocmV0KSB7Cj4+PiArICAgICAgICAgICAgIGZwdXQoaW90bGJfZmlsZS0+ ZmlsZSk7Cj4+PiArICAgICAgICAgICAgIGtmcmVlKGlvdGxiX2ZpbGUpOwo+Pj4gKyAgICAgICAg ICAgICByZXR1cm4gcmV0Owo+Pj4gKyAgICAgfQo+Pj4gKyAgICAgcmV0dXJuIDA7Cj4+PiArfQo+ Pj4gKwo+Pj4gK3N0YXRpYyB2b2lkIHZkdXNlX2lvdGxiX2RlbF9yYW5nZShzdHJ1Y3QgdmR1c2Vf ZGV2ICpkZXYsIHU2NCBzdGFydCwgdTY0IGxhc3QpCj4+PiArewo+Pj4gKyAgICAgc3RydWN0IHZo b3N0X2lvdGxiX2ZpbGUgKmlvdGxiX2ZpbGU7Cj4+PiArICAgICBzdHJ1Y3Qgdmhvc3RfaW90bGJf bWFwICptYXA7Cj4+PiArCj4+PiArICAgICBzcGluX2xvY2soJmRldi0+aW9tbXVfbG9jayk7Cj4+ PiArICAgICB3aGlsZSAoKG1hcCA9IHZob3N0X2lvdGxiX2l0cmVlX2ZpcnN0KGRldi0+aW9tbXUs IHN0YXJ0LCBsYXN0KSkpIHsKPj4+ICsgICAgICAgICAgICAgaW90bGJfZmlsZSA9IChzdHJ1Y3Qg dmhvc3RfaW90bGJfZmlsZSAqKW1hcC0+b3BhcXVlOwo+Pj4gKyAgICAgICAgICAgICBmcHV0KGlv dGxiX2ZpbGUtPmZpbGUpOwo+Pj4gKyAgICAgICAgICAgICBrZnJlZShpb3RsYl9maWxlKTsKPj4+ ICsgICAgICAgICAgICAgdmhvc3RfaW90bGJfbWFwX2ZyZWUoZGV2LT5pb21tdSwgbWFwKTsKPj4+ ICsgICAgIH0KPj4+ICsgICAgIHNwaW5fdW5sb2NrKCZkZXYtPmlvbW11X2xvY2spOwo+Pj4gK30K Pj4+ICsKPj4+ICtzdGF0aWMgdm9pZCB2ZHVzZV9kZXZfcmVzZXQoc3RydWN0IHZkdXNlX2RldiAq ZGV2KQo+Pj4gK3sKPj4+ICsgICAgIGludCBpOwo+Pj4gKwo+Pj4gKyAgICAgYXRvbWljX3NldCgm ZGV2LT5ib3VuY2VfbWFwLCAwKTsKPj4+ICsgICAgIHZkdXNlX2lvdGxiX2RlbF9yYW5nZShkZXYs IDBVTEwsIDBVTEwgLSAxKTsKPj4+ICsgICAgIHZkdXNlX2Rldl91cGRhdGVfaW90bGIoZGV2LCAw VUxMLCAwVUxMIC0gMSk7Cj4+Cj4+IFVMTE9OR19NQVggcGxlYXNlLgo+Pgo+IE9LLgo+Cj4+PiAr Cj4+PiArICAgICBmb3IgKGkgPSAwOyBpIDwgZGV2LT52cV9udW07IGkrKykgewo+Pj4gKyAgICAg ICAgICAgICBzdHJ1Y3QgdmR1c2VfdmlydHF1ZXVlICp2cSA9ICZkZXYtPnZxc1tpXTsKPj4+ICsK Pj4+ICsgICAgICAgICAgICAgc3Bpbl9sb2NrKCZ2cS0+aXJxX2xvY2spOwo+Pj4gKyAgICAgICAg ICAgICB2cS0+cmVhZHkgPSBmYWxzZTsKPj4+ICsgICAgICAgICAgICAgdnEtPmNiID0gTlVMTDsK Pj4+ICsgICAgICAgICAgICAgdnEtPnByaXZhdGUgPSBOVUxMOwo+Pj4gKyAgICAgICAgICAgICBz cGluX3VubG9jaygmdnEtPmlycV9sb2NrKTsKPj4+ICsgICAgIH0KPj4+ICt9Cj4+PiArCj4+PiAr c3RhdGljIGludCB2ZHVzZV92ZHBhX3NldF92cV9hZGRyZXNzKHN0cnVjdCB2ZHBhX2RldmljZSAq dmRwYSwgdTE2IGlkeCwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHU2NCBkZXNj X2FyZWEsIHU2NCBkcml2ZXJfYXJlYSwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAg IHU2NCBkZXZpY2VfYXJlYSkKPj4+ICt7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYg PSB2ZHBhX3RvX3ZkdXNlKHZkcGEpOwo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX3ZpcnRxdWV1ZSAq dnEgPSAmZGV2LT52cXNbaWR4XTsKPj4+ICsKPj4+ICsgICAgIHJldHVybiB2ZHVzZV9kZXZfc2V0 X3ZxX2FkZHIoZGV2LCB2cSwgZGVzY19hcmVhLAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICBkcml2ZXJfYXJlYSwgZGV2aWNlX2FyZWEpOwo+Pj4gK30KPj4+ICsKPj4+ ICtzdGF0aWMgdm9pZCB2ZHVzZV92ZHBhX2tpY2tfdnEoc3RydWN0IHZkcGFfZGV2aWNlICp2ZHBh LCB1MTYgaWR4KQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXYgKmRldiA9IHZkcGFf dG9fdmR1c2UodmRwYSk7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfdmlydHF1ZXVlICp2cSA9ICZk ZXYtPnZxc1tpZHhdOwo+Pj4gKwo+Pj4gKyAgICAgdmR1c2VfdnFfa2ljayh2cSk7Cj4+PiArfQo+ Pj4gKwo+Pj4gK3N0YXRpYyB2b2lkIHZkdXNlX3ZkcGFfc2V0X3ZxX2NiKHN0cnVjdCB2ZHBhX2Rl dmljZSAqdmRwYSwgdTE2IGlkeCwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJ1 Y3QgdmRwYV9jYWxsYmFjayAqY2IpCj4+PiArewo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX2RldiAq ZGV2ID0gdmRwYV90b192ZHVzZSh2ZHBhKTsKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV92aXJ0cXVl dWUgKnZxID0gJmRldi0+dnFzW2lkeF07Cj4+PiArCj4+PiArICAgICB2cS0+Y2IgPSBjYi0+Y2Fs bGJhY2s7Cj4+PiArICAgICB2cS0+cHJpdmF0ZSA9IGNiLT5wcml2YXRlOwo+Pj4gK30KPj4+ICsK Pj4+ICtzdGF0aWMgdm9pZCB2ZHVzZV92ZHBhX3NldF92cV9udW0oc3RydWN0IHZkcGFfZGV2aWNl ICp2ZHBhLCB1MTYgaWR4LCB1MzIgbnVtKQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9k ZXYgKmRldiA9IHZkcGFfdG9fdmR1c2UodmRwYSk7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2Vfdmly dHF1ZXVlICp2cSA9ICZkZXYtPnZxc1tpZHhdOwo+Pj4gKwo+Pj4gKyAgICAgdmR1c2VfZGV2X3Nl dF92cV9udW0oZGV2LCB2cSwgbnVtKTsKPj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIHZvaWQgdmR1 c2VfdmRwYV9zZXRfdnFfcmVhZHkoc3RydWN0IHZkcGFfZGV2aWNlICp2ZHBhLAo+Pj4gKyAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1MTYgaWR4LCBib29sIHJlYWR5KQo+Pj4g K3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXYgKmRldiA9IHZkcGFfdG9fdmR1c2UodmRwYSk7 Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfdmlydHF1ZXVlICp2cSA9ICZkZXYtPnZxc1tpZHhdOwo+ Pj4gKwo+Pj4gKyAgICAgdmR1c2VfZGV2X3NldF92cV9yZWFkeShkZXYsIHZxLCByZWFkeSk7Cj4+ PiArICAgICB2cS0+cmVhZHkgPSByZWFkeTsKPj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIGJvb2wg dmR1c2VfdmRwYV9nZXRfdnFfcmVhZHkoc3RydWN0IHZkcGFfZGV2aWNlICp2ZHBhLCB1MTYgaWR4 KQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXYgKmRldiA9IHZkcGFfdG9fdmR1c2Uo dmRwYSk7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfdmlydHF1ZXVlICp2cSA9ICZkZXYtPnZxc1tp ZHhdOwo+Pj4gKwo+Pj4gKyAgICAgdnEtPnJlYWR5ID0gdmR1c2VfZGV2X2dldF92cV9yZWFkeShk ZXYsIHZxKTsKPj4+ICsKPj4+ICsgICAgIHJldHVybiB2cS0+cmVhZHk7Cj4+PiArfQo+Pj4gKwo+ Pj4gK3N0YXRpYyBpbnQgdmR1c2VfdmRwYV9zZXRfdnFfc3RhdGUoc3RydWN0IHZkcGFfZGV2aWNl ICp2ZHBhLCB1MTYgaWR4LAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qg c3RydWN0IHZkcGFfdnFfc3RhdGUgKnN0YXRlKQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVz ZV9kZXYgKmRldiA9IHZkcGFfdG9fdmR1c2UodmRwYSk7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2Vf dmlydHF1ZXVlICp2cSA9ICZkZXYtPnZxc1tpZHhdOwo+Pj4gKwo+Pj4gKyAgICAgcmV0dXJuIHZk dXNlX2Rldl9zZXRfdnFfc3RhdGUoZGV2LCB2cSwgc3RhdGUpOwo+Pj4gK30KPj4+ICsKPj4+ICtz dGF0aWMgaW50IHZkdXNlX3ZkcGFfZ2V0X3ZxX3N0YXRlKHN0cnVjdCB2ZHBhX2RldmljZSAqdmRw YSwgdTE2IGlkeCwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCB2ZHBh X3ZxX3N0YXRlICpzdGF0ZSkKPj4+ICt7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYg PSB2ZHBhX3RvX3ZkdXNlKHZkcGEpOwo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX3ZpcnRxdWV1ZSAq dnEgPSAmZGV2LT52cXNbaWR4XTsKPj4+ICsKPj4+ICsgICAgIHJldHVybiB2ZHVzZV9kZXZfZ2V0 X3ZxX3N0YXRlKGRldiwgdnEsIHN0YXRlKTsKPj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIHUzMiB2 ZHVzZV92ZHBhX2dldF92cV9hbGlnbihzdHJ1Y3QgdmRwYV9kZXZpY2UgKnZkcGEpCj4+PiArewo+ Pj4gKyAgICAgc3RydWN0IHZkdXNlX2RldiAqZGV2ID0gdmRwYV90b192ZHVzZSh2ZHBhKTsKPj4+ ICsKPj4+ICsgICAgIHJldHVybiBkZXYtPnZxX2FsaWduOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0 aWMgdTY0IHZkdXNlX3ZkcGFfZ2V0X2ZlYXR1cmVzKHN0cnVjdCB2ZHBhX2RldmljZSAqdmRwYSkK Pj4+ICt7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYgPSB2ZHBhX3RvX3ZkdXNlKHZk cGEpOwo+Pj4gKyAgICAgdTY0IGZpeGVkID0gKDFVTEwgPDwgVklSVElPX0ZfQUNDRVNTX1BMQVRG T1JNKTsKPj4+ICsKPj4+ICsgICAgIHJldHVybiAodmR1c2VfZGV2X2dldF9mZWF0dXJlcyhkZXYp IHwgZml4ZWQpOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgaW50IHZkdXNlX3ZkcGFfc2V0X2Zl YXR1cmVzKHN0cnVjdCB2ZHBhX2RldmljZSAqdmRwYSwgdTY0IGZlYXR1cmVzKQo+Pj4gK3sKPj4+ ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXYgKmRldiA9IHZkcGFfdG9fdmR1c2UodmRwYSk7Cj4+PiAr Cj4+PiArICAgICByZXR1cm4gdmR1c2VfZGV2X3NldF9mZWF0dXJlcyhkZXYsIGZlYXR1cmVzKTsK Pj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIHZvaWQgdmR1c2VfdmRwYV9zZXRfY29uZmlnX2NiKHN0 cnVjdCB2ZHBhX2RldmljZSAqdmRwYSwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgc3RydWN0IHZkcGFfY2FsbGJhY2sgKmNiKQo+Pj4gK3sKPj4+ICsgICAgIC8qIFdlIGRvbid0 IHN1cHBvcnQgY29uZmlnIGludGVycnVwdCAqLwo+Pgo+PiBJZiBpdCdzIG5vdCBoYXJkLCBsZXQn cyBhZGQgdGhpcy4gT3RoZXJ3aXNlIHdlIG5lZWQgYSBwZXIgZGV2aWNlIGZlYXR1cmUKPj4gYmxh Y2tsaXN0IHRvIGZpbHRlciBvdXQgYWxsIGZlYXR1cmVzIHRoYXQgZGVwZW5kcyBvbiBjb25maWcg aW50ZXJydXB0Lgo+Pgo+IFdpbGwgZG8gaXQuCj4KPj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIHUx NiB2ZHVzZV92ZHBhX2dldF92cV9udW1fbWF4KHN0cnVjdCB2ZHBhX2RldmljZSAqdmRwYSkKPj4+ ICt7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYgPSB2ZHBhX3RvX3ZkdXNlKHZkcGEp Owo+Pj4gKwo+Pj4gKyAgICAgcmV0dXJuIGRldi0+dnFfc2l6ZV9tYXg7Cj4+PiArfQo+Pj4gKwo+ Pj4gK3N0YXRpYyB1MzIgdmR1c2VfdmRwYV9nZXRfZGV2aWNlX2lkKHN0cnVjdCB2ZHBhX2Rldmlj ZSAqdmRwYSkKPj4+ICt7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYgPSB2ZHBhX3Rv X3ZkdXNlKHZkcGEpOwo+Pj4gKwo+Pj4gKyAgICAgcmV0dXJuIGRldi0+ZGV2aWNlX2lkOwo+Pj4g K30KPj4+ICsKPj4+ICtzdGF0aWMgdTMyIHZkdXNlX3ZkcGFfZ2V0X3ZlbmRvcl9pZChzdHJ1Y3Qg dmRwYV9kZXZpY2UgKnZkcGEpCj4+PiArewo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX2RldiAqZGV2 ID0gdmRwYV90b192ZHVzZSh2ZHBhKTsKPj4+ICsKPj4+ICsgICAgIHJldHVybiBkZXYtPnZlbmRv cl9pZDsKPj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIHU4IHZkdXNlX3ZkcGFfZ2V0X3N0YXR1cyhz dHJ1Y3QgdmRwYV9kZXZpY2UgKnZkcGEpCj4+PiArewo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX2Rl diAqZGV2ID0gdmRwYV90b192ZHVzZSh2ZHBhKTsKPj4+ICsKPj4+ICsgICAgIHJldHVybiB2ZHVz ZV9kZXZfZ2V0X3N0YXR1cyhkZXYpOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgdm9pZCB2ZHVz ZV92ZHBhX3NldF9zdGF0dXMoc3RydWN0IHZkcGFfZGV2aWNlICp2ZHBhLCB1OCBzdGF0dXMpCj4+ PiArewo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX2RldiAqZGV2ID0gdmRwYV90b192ZHVzZSh2ZHBh KTsKPj4+ICsKPj4+ICsgICAgIGlmIChzdGF0dXMgPT0gMCkKPj4+ICsgICAgICAgICAgICAgdmR1 c2VfZGV2X3Jlc2V0KGRldik7Cj4+PiArICAgICBlbHNlCj4+PiArICAgICAgICAgICAgIHZkdXNl X2Rldl91cGRhdGVfaW90bGIoZGV2LCAwVUxMLCAwVUxMIC0gMSk7Cj4+Cj4+IEFueSByZWFzb24g Zm9yIHN1Y2ggSU9UTEIgaW52YWxpZGF0aW9uIGhlcmU/Cj4+Cj4gQXMgSSBtZW50aW9uZWQgYmVm b3JlLCB0aGlzIGlzIHVzZWQgdG8gbm90aWZ5IHVzZXJzcGFjZSB0byB1cGRhdGUgdGhlCj4gSU9U TEIuIE1haW5seSBmb3IgdmlydGlvLXZkcGEgY2FzZS4KCgpTbyB0aGUgcXVlc3Rpb24gaXMsIHVz dWFsbHksIHRoZXJlIGNvdWxkIGJlIHNldmVyYWwgdGltZXMgb2Ygc3RhdHVzIApzZXR0aW5nIGR1 cmluZyBkcml2ZXIgaW5pdGlhbGl6YXRpb24uIERvIHdlIHJlYWxseSBuZWVkIHRvIHVwZGF0ZSBJ T1RMQiAKZXZlcnkgdGltZT8KCgo+Cj4+PiArCj4+PiArICAgICB2ZHVzZV9kZXZfc2V0X3N0YXR1 cyhkZXYsIHN0YXR1cyk7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyB2b2lkIHZkdXNlX3ZkcGFf Z2V0X2NvbmZpZyhzdHJ1Y3QgdmRwYV9kZXZpY2UgKnZkcGEsIHVuc2lnbmVkIGludCBvZmZzZXQs Cj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICB2b2lkICpidWYsIHVuc2lnbmVkIGludCBs ZW4pCj4+PiArewo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX2RldiAqZGV2ID0gdmRwYV90b192ZHVz ZSh2ZHBhKTsKPj4+ICsKPj4+ICsgICAgIHZkdXNlX2Rldl9nZXRfY29uZmlnKGRldiwgb2Zmc2V0 LCBidWYsIGxlbik7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyB2b2lkIHZkdXNlX3ZkcGFfc2V0 X2NvbmZpZyhzdHJ1Y3QgdmRwYV9kZXZpY2UgKnZkcGEsIHVuc2lnbmVkIGludCBvZmZzZXQsCj4+ PiArICAgICAgICAgICAgICAgICAgICAgY29uc3Qgdm9pZCAqYnVmLCB1bnNpZ25lZCBpbnQgbGVu KQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXYgKmRldiA9IHZkcGFfdG9fdmR1c2Uo dmRwYSk7Cj4+PiArCj4+PiArICAgICB2ZHVzZV9kZXZfc2V0X2NvbmZpZyhkZXYsIG9mZnNldCwg YnVmLCBsZW4pOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgaW50IHZkdXNlX3ZkcGFfc2V0X21h cChzdHJ1Y3QgdmRwYV9kZXZpY2UgKnZkcGEsCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAg ICAgICBzdHJ1Y3Qgdmhvc3RfaW90bGIgKmlvdGxiKQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2 ZHVzZV9kZXYgKmRldiA9IHZkcGFfdG9fdmR1c2UodmRwYSk7Cj4+PiArICAgICBzdHJ1Y3Qgdmhv c3RfaW90bGJfbWFwICptYXA7Cj4+PiArICAgICBzdHJ1Y3Qgdmhvc3RfaW90bGJfZmlsZSAqaW90 bGJfZmlsZTsKPj4+ICsgICAgIHU2NCBzdGFydCA9IDBVTEwsIGxhc3QgPSAwVUxMIC0gMTsKPj4+ ICsgICAgIGludCByZXQgPSAwOwo+Pj4gKwo+Pj4gKyAgICAgdmR1c2VfaW90bGJfZGVsX3Jhbmdl KGRldiwgc3RhcnQsIGxhc3QpOwo+Pj4gKwo+Pj4gKyAgICAgZm9yIChtYXAgPSB2aG9zdF9pb3Rs Yl9pdHJlZV9maXJzdChpb3RsYiwgc3RhcnQsIGxhc3QpOyBtYXA7Cj4+PiArICAgICAgICAgICAg IG1hcCA9IHZob3N0X2lvdGxiX2l0cmVlX25leHQobWFwLCBzdGFydCwgbGFzdCkpIHsKPj4+ICsg ICAgICAgICAgICAgaWYgKCFtYXAtPm9wYXF1ZSkKPj4+ICsgICAgICAgICAgICAgICAgICAgICBj b250aW51ZTsKPj4KPj4gV2hhdCB3aWxsIGhhcHBlbiBpZiB3ZSBzaW1wbHkgYWNjZXB0IE5VTEwg b3BhcXVlIGhlcmU/Cj4+Cj4gTm8gZmlsZSB0byBtbWFwIGluIHVzZXJzcGFjZS4gU28gaXQncyB1 c2VsZXNzLgo+Cj4+PiArCj4+PiArICAgICAgICAgICAgIGlvdGxiX2ZpbGUgPSAoc3RydWN0IHZo b3N0X2lvdGxiX2ZpbGUgKiltYXAtPm9wYXF1ZTsKPj4+ICsgICAgICAgICAgICAgcmV0ID0gdmR1 c2VfaW90bGJfYWRkX3JhbmdlKGRldiwgbWFwLT5zdGFydCwgbWFwLT5sYXN0LAo+Pj4gKyAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwLT5hZGRyLCBtYXAtPnBlcm0s Cj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpb3RsYl9maWxl LT5maWxlLAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW90 bGJfZmlsZS0+b2Zmc2V0KTsKPj4+ICsgICAgICAgICAgICAgaWYgKHJldCkKPj4+ICsgICAgICAg ICAgICAgICAgICAgICBicmVhazsKPj4+ICsgICAgIH0KPj4+ICsgICAgIHZkdXNlX2Rldl91cGRh dGVfaW90bGIoZGV2LCBzdGFydCwgbGFzdCk7Cj4+PiArCj4+PiArICAgICByZXR1cm4gcmV0Owo+ Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgdm9pZCB2ZHVzZV92ZHBhX2ZyZWUoc3RydWN0IHZkcGFf ZGV2aWNlICp2ZHBhKQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXYgKmRldiA9IHZk cGFfdG9fdmR1c2UodmRwYSk7Cj4+PiArCj4+PiArICAgICBXQVJOX09OKCFsaXN0X2VtcHR5KCZk ZXYtPnNlbmRfbGlzdCkpOwo+Pj4gKyAgICAgV0FSTl9PTighbGlzdF9lbXB0eSgmZGV2LT5yZWN2 X2xpc3QpKTsKPj4+ICsgICAgIGRldi0+dmRldiA9IE5VTEw7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0 YXRpYyBjb25zdCBzdHJ1Y3QgdmRwYV9jb25maWdfb3BzIHZkdXNlX3ZkcGFfY29uZmlnX29wcyA9 IHsKPj4+ICsgICAgIC5zZXRfdnFfYWRkcmVzcyAgICAgICAgID0gdmR1c2VfdmRwYV9zZXRfdnFf YWRkcmVzcywKPj4+ICsgICAgIC5raWNrX3ZxICAgICAgICAgICAgICAgID0gdmR1c2VfdmRwYV9r aWNrX3ZxLAo+Pj4gKyAgICAgLnNldF92cV9jYiAgICAgICAgICAgICAgPSB2ZHVzZV92ZHBhX3Nl dF92cV9jYiwKPj4+ICsgICAgIC5zZXRfdnFfbnVtICAgICAgICAgICAgID0gdmR1c2VfdmRwYV9z ZXRfdnFfbnVtLAo+Pj4gKyAgICAgLnNldF92cV9yZWFkeSAgICAgICAgICAgPSB2ZHVzZV92ZHBh X3NldF92cV9yZWFkeSwKPj4+ICsgICAgIC5nZXRfdnFfcmVhZHkgICAgICAgICAgID0gdmR1c2Vf dmRwYV9nZXRfdnFfcmVhZHksCj4+PiArICAgICAuc2V0X3ZxX3N0YXRlICAgICAgICAgICA9IHZk dXNlX3ZkcGFfc2V0X3ZxX3N0YXRlLAo+Pj4gKyAgICAgLmdldF92cV9zdGF0ZSAgICAgICAgICAg PSB2ZHVzZV92ZHBhX2dldF92cV9zdGF0ZSwKPj4+ICsgICAgIC5nZXRfdnFfYWxpZ24gICAgICAg ICAgID0gdmR1c2VfdmRwYV9nZXRfdnFfYWxpZ24sCj4+PiArICAgICAuZ2V0X2ZlYXR1cmVzICAg ICAgICAgICA9IHZkdXNlX3ZkcGFfZ2V0X2ZlYXR1cmVzLAo+Pj4gKyAgICAgLnNldF9mZWF0dXJl cyAgICAgICAgICAgPSB2ZHVzZV92ZHBhX3NldF9mZWF0dXJlcywKPj4+ICsgICAgIC5zZXRfY29u ZmlnX2NiICAgICAgICAgID0gdmR1c2VfdmRwYV9zZXRfY29uZmlnX2NiLAo+Pj4gKyAgICAgLmdl dF92cV9udW1fbWF4ICAgICAgICAgPSB2ZHVzZV92ZHBhX2dldF92cV9udW1fbWF4LAo+Pj4gKyAg ICAgLmdldF9kZXZpY2VfaWQgICAgICAgICAgPSB2ZHVzZV92ZHBhX2dldF9kZXZpY2VfaWQsCj4+ PiArICAgICAuZ2V0X3ZlbmRvcl9pZCAgICAgICAgICA9IHZkdXNlX3ZkcGFfZ2V0X3ZlbmRvcl9p ZCwKPj4+ICsgICAgIC5nZXRfc3RhdHVzICAgICAgICAgICAgID0gdmR1c2VfdmRwYV9nZXRfc3Rh dHVzLAo+Pj4gKyAgICAgLnNldF9zdGF0dXMgICAgICAgICAgICAgPSB2ZHVzZV92ZHBhX3NldF9z dGF0dXMsCj4+PiArICAgICAuZ2V0X2NvbmZpZyAgICAgICAgICAgICA9IHZkdXNlX3ZkcGFfZ2V0 X2NvbmZpZywKPj4+ICsgICAgIC5zZXRfY29uZmlnICAgICAgICAgICAgID0gdmR1c2VfdmRwYV9z ZXRfY29uZmlnLAo+Pj4gKyAgICAgLnNldF9tYXAgICAgICAgICAgICAgICAgPSB2ZHVzZV92ZHBh X3NldF9tYXAsCj4+PiArICAgICAuZnJlZSAgICAgICAgICAgICAgICAgICA9IHZkdXNlX3ZkcGFf ZnJlZSwKPj4+ICt9Owo+Pj4gKwo+Pj4gK3N0YXRpYyBkbWFfYWRkcl90IHZkdXNlX2Rldl9tYXBf cGFnZShzdHJ1Y3QgZGV2aWNlICpkZXYsIHN0cnVjdCBwYWdlICpwYWdlLAo+Pj4gKyAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bnNpZ25lZCBsb25nIG9mZnNldCwgc2l6ZV90 IHNpemUsCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVudW0gZG1h X2RhdGFfZGlyZWN0aW9uIGRpciwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgdW5zaWduZWQgbG9uZyBhdHRycykKPj4+ICt7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2Vf ZGV2ICp2ZGV2ID0gZGV2X3RvX3ZkdXNlKGRldik7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfaW92 YV9kb21haW4gKmRvbWFpbiA9IHZkZXYtPmRvbWFpbjsKPj4+ICsKPj4+ICsgICAgIGlmIChhdG9t aWNfeGNoZygmdmRldi0+Ym91bmNlX21hcCwgMSkgPT0gMCAmJgo+Pj4gKyAgICAgICAgICAgICB2 ZHVzZV9pb3RsYl9hZGRfcmFuZ2UodmRldiwgMCwgZG9tYWluLT5ib3VuY2Vfc2l6ZSAtIDEsCj4+ PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAwLCBWRFVTRV9BQ0NFU1NfUlcs Cj4+Cj4+IElzIHRoaXMgc2FmZSB0byB1c2UgVkRVU0VfQUNDRVNTX1JXIGhlcmUsIGNvbnNpZGVy IHdlIG1pZ2h0IGhhdmUgZGV2aWNlCj4+IHJlYWRvbmx5IG1hcHBpbmdzLgo+Pgo+IFRoaXMgbWFw cGluZyBpcyBmb3IgdGhlIHdob2xlIGJvdW5jZSBidWZmZXIuIE1heWJlIHVzZXJzcGFjZSBuZWVk cyB0bwo+IHRlbGwgdXMgaWYgaXQgb25seSBzdXBwb3J0IHJlYWRvbmx5IG1hcHBpbmdzLgoKClJp Z2h0LCBzbyBJIHRoaW5rIHdlIGRvbid0IG5lZWQgdG8gY2FyZSBhYm91dCB0aGlzLgoKCj4KPj4+ ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZkdXNlX2RvbWFpbl9maWxlKGRv bWFpbiksCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZHVzZV9kb21h aW5fZ2V0X29mZnNldChkb21haW4sIDApKSkgewo+Pj4gKyAgICAgICAgICAgICBhdG9taWNfc2V0 KCZ2ZGV2LT5ib3VuY2VfbWFwLCAwKTsKPj4+ICsgICAgICAgICAgICAgcmV0dXJuIERNQV9NQVBQ SU5HX0VSUk9SOwo+Pj4gKyAgICAgfQo+Pj4gKwo+Pj4gKyAgICAgcmV0dXJuIHZkdXNlX2RvbWFp bl9tYXBfcGFnZShkb21haW4sIHBhZ2UsIG9mZnNldCwgc2l6ZSwgZGlyLCBhdHRycyk7Cj4+PiAr fQo+Pj4gKwo+Pj4gK3N0YXRpYyB2b2lkIHZkdXNlX2Rldl91bm1hcF9wYWdlKHN0cnVjdCBkZXZp Y2UgKmRldiwgZG1hX2FkZHJfdCBkbWFfYWRkciwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIHNpemVfdCBzaXplLCBlbnVtIGRtYV9kYXRhX2RpcmVjdGlvbiBkaXIsCj4+PiArICAg ICAgICAgICAgICAgICAgICAgICAgICAgICB1bnNpZ25lZCBsb25nIGF0dHJzKQo+Pj4gK3sKPj4+ ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXYgKnZkZXYgPSBkZXZfdG9fdmR1c2UoZGV2KTsKPj4+ICsg ICAgIHN0cnVjdCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluID0gdmRldi0+ZG9tYWluOwo+Pj4g Kwo+Pj4gKyAgICAgcmV0dXJuIHZkdXNlX2RvbWFpbl91bm1hcF9wYWdlKGRvbWFpbiwgZG1hX2Fk ZHIsIHNpemUsIGRpciwgYXR0cnMpOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgdm9pZCAqdmR1 c2VfZGV2X2FsbG9jX2NvaGVyZW50KHN0cnVjdCBkZXZpY2UgKmRldiwgc2l6ZV90IHNpemUsCj4+ PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRtYV9hZGRyX3QgKmRtYV9h ZGRyLCBnZnBfdCBmbGFnLAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICB1bnNpZ25lZCBsb25nIGF0dHJzKQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXYg KnZkZXYgPSBkZXZfdG9fdmR1c2UoZGV2KTsKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9pb3ZhX2Rv bWFpbiAqZG9tYWluID0gdmRldi0+ZG9tYWluOwo+Pj4gKyAgICAgdW5zaWduZWQgbG9uZyBpb3Zh Owo+Pj4gKyAgICAgdm9pZCAqYWRkcjsKPj4+ICsKPj4+ICsgICAgICpkbWFfYWRkciA9IERNQV9N QVBQSU5HX0VSUk9SOwo+Pj4gKyAgICAgYWRkciA9IHZkdXNlX2RvbWFpbl9hbGxvY19jb2hlcmVu dChkb21haW4sIHNpemUsCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZG1hX2Fk ZHJfdCAqKSZpb3ZhLCBmbGFnLCBhdHRycyk7Cj4+PiArICAgICBpZiAoIWFkZHIpCj4+PiArICAg ICAgICAgICAgIHJldHVybiBOVUxMOwo+Pj4gKwo+Pj4gKyAgICAgaWYgKHZkdXNlX2lvdGxiX2Fk ZF9yYW5nZSh2ZGV2LCBpb3ZhLCBpb3ZhICsgc2l6ZSAtIDEsCj4+PiArICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgIGlvdmEsIFZEVVNFX0FDQ0VTU19SVywKPj4+ICsgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgdmR1c2VfZG9tYWluX2ZpbGUoZG9tYWluKSwKPj4+ICsgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgdmR1c2VfZG9tYWluX2dldF9vZmZzZXQoZG9tYWluLCBp b3ZhKSkpIHsKPj4+ICsgICAgICAgICAgICAgdmR1c2VfZG9tYWluX2ZyZWVfY29oZXJlbnQoZG9t YWluLCBzaXplLCBhZGRyLCBpb3ZhLCBhdHRycyk7Cj4+PiArICAgICAgICAgICAgIHJldHVybiBO VUxMOwo+Pj4gKyAgICAgfQo+Pj4gKyAgICAgKmRtYV9hZGRyID0gKGRtYV9hZGRyX3QpaW92YTsK Pj4+ICsKPj4+ICsgICAgIHJldHVybiBhZGRyOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgdm9p ZCB2ZHVzZV9kZXZfZnJlZV9jb2hlcmVudChzdHJ1Y3QgZGV2aWNlICpkZXYsIHNpemVfdCBzaXpl LAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2b2lkICp2YWRkciwg ZG1hX2FkZHJfdCBkbWFfYWRkciwKPj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgdW5zaWduZWQgbG9uZyBhdHRycykKPj4+ICt7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2Vf ZGV2ICp2ZGV2ID0gZGV2X3RvX3ZkdXNlKGRldik7Cj4+PiArICAgICBzdHJ1Y3QgdmR1c2VfaW92 YV9kb21haW4gKmRvbWFpbiA9IHZkZXYtPmRvbWFpbjsKPj4+ICsgICAgIHVuc2lnbmVkIGxvbmcg c3RhcnQgPSAodW5zaWduZWQgbG9uZylkbWFfYWRkcjsKPj4+ICsgICAgIHVuc2lnbmVkIGxvbmcg bGFzdCA9IHN0YXJ0ICsgc2l6ZSAtIDE7Cj4+PiArCj4+PiArICAgICB2ZHVzZV9pb3RsYl9kZWxf cmFuZ2UodmRldiwgc3RhcnQsIGxhc3QpOwo+Pj4gKyAgICAgdmR1c2VfZGV2X3VwZGF0ZV9pb3Rs Yih2ZGV2LCBzdGFydCwgbGFzdCk7Cj4+PiArICAgICB2ZHVzZV9kb21haW5fZnJlZV9jb2hlcmVu dChkb21haW4sIHNpemUsIHZhZGRyLCBkbWFfYWRkciwgYXR0cnMpOwo+Pj4gK30KPj4+ICsKPj4+ ICtzdGF0aWMgY29uc3Qgc3RydWN0IGRtYV9tYXBfb3BzIHZkdXNlX2Rldl9kbWFfb3BzID0gewo+ Pj4gKyAgICAgLm1hcF9wYWdlID0gdmR1c2VfZGV2X21hcF9wYWdlLAo+Pj4gKyAgICAgLnVubWFw X3BhZ2UgPSB2ZHVzZV9kZXZfdW5tYXBfcGFnZSwKPj4+ICsgICAgIC5hbGxvYyA9IHZkdXNlX2Rl dl9hbGxvY19jb2hlcmVudCwKPj4+ICsgICAgIC5mcmVlID0gdmR1c2VfZGV2X2ZyZWVfY29oZXJl bnQsCj4+PiArfTsKPj4+ICsKPj4+ICtzdGF0aWMgdW5zaWduZWQgaW50IHBlcm1fdG9fZmlsZV9m bGFncyh1OCBwZXJtKQo+Pj4gK3sKPj4+ICsgICAgIHVuc2lnbmVkIGludCBmbGFncyA9IDA7Cj4+ PiArCj4+PiArICAgICBzd2l0Y2ggKHBlcm0pIHsKPj4+ICsgICAgIGNhc2UgVkRVU0VfQUNDRVNT X1dPOgo+Pj4gKyAgICAgICAgICAgICBmbGFncyB8PSBPX1dST05MWTsKPj4+ICsgICAgICAgICAg ICAgYnJlYWs7Cj4+PiArICAgICBjYXNlIFZEVVNFX0FDQ0VTU19STzoKPj4+ICsgICAgICAgICAg ICAgZmxhZ3MgfD0gT19SRE9OTFk7Cj4+PiArICAgICAgICAgICAgIGJyZWFrOwo+Pj4gKyAgICAg Y2FzZSBWRFVTRV9BQ0NFU1NfUlc6Cj4+PiArICAgICAgICAgICAgIGZsYWdzIHw9IE9fUkRXUjsK Pj4+ICsgICAgICAgICAgICAgYnJlYWs7Cj4+PiArICAgICBkZWZhdWx0Ogo+Pj4gKyAgICAgICAg ICAgICBXQVJOKDEsICJpbnZhbGlkYXRlIHZob3N0IElPVExCIHBlcm1pc3Npb25cbiIpOwo+Pj4g KyAgICAgICAgICAgICBicmVhazsKPj4+ICsgICAgIH0KPj4+ICsKPj4+ICsgICAgIHJldHVybiBm bGFnczsKPj4+ICt9Cj4+PiArCj4+PiArc3RhdGljIGxvbmcgdmR1c2VfZGV2X2lvY3RsKHN0cnVj dCBmaWxlICpmaWxlLCB1bnNpZ25lZCBpbnQgY21kLAo+Pj4gKyAgICAgICAgICAgICAgICAgICAg IHVuc2lnbmVkIGxvbmcgYXJnKQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXYgKmRl diA9IGZpbGUtPnByaXZhdGVfZGF0YTsKPj4+ICsgICAgIHZvaWQgX191c2VyICphcmdwID0gKHZv aWQgX191c2VyICopYXJnOwo+Pj4gKyAgICAgaW50IHJldDsKPj4+ICsKPj4+ICsgICAgIG11dGV4 X2xvY2soJmRldi0+bG9jayk7Cj4+PiArICAgICBzd2l0Y2ggKGNtZCkgewo+Pj4gKyAgICAgY2Fz ZSBWRFVTRV9JT1RMQl9HRVRfRkQ6IHsKPj4+ICsgICAgICAgICAgICAgc3RydWN0IHZkdXNlX2lv dGxiX2VudHJ5IGVudHJ5Owo+Pj4gKyAgICAgICAgICAgICBzdHJ1Y3Qgdmhvc3RfaW90bGJfbWFw ICptYXA7Cj4+PiArICAgICAgICAgICAgIHN0cnVjdCB2aG9zdF9pb3RsYl9maWxlICppb3RsYl9m aWxlOwo+Pj4gKyAgICAgICAgICAgICBzdHJ1Y3QgZmlsZSAqZiA9IE5VTEw7Cj4+PiArCj4+PiAr ICAgICAgICAgICAgIHJldCA9IC1FRkFVTFQ7Cj4+PiArICAgICAgICAgICAgIGlmIChjb3B5X2Zy b21fdXNlcigmZW50cnksIGFyZ3AsIHNpemVvZihlbnRyeSkpKQo+Pj4gKyAgICAgICAgICAgICAg ICAgICAgIGJyZWFrOwo+Pj4gKwo+Pj4gKyAgICAgICAgICAgICBzcGluX2xvY2soJmRldi0+aW9t bXVfbG9jayk7Cj4+PiArICAgICAgICAgICAgIG1hcCA9IHZob3N0X2lvdGxiX2l0cmVlX2ZpcnN0 KGRldi0+aW9tbXUsIGVudHJ5LnN0YXJ0LAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICBlbnRyeS5sYXN0KTsKPj4+ICsgICAgICAgICAgICAgaWYgKG1hcCkg ewo+Pj4gKyAgICAgICAgICAgICAgICAgICAgIGlvdGxiX2ZpbGUgPSAoc3RydWN0IHZob3N0X2lv dGxiX2ZpbGUgKiltYXAtPm9wYXF1ZTsKPj4+ICsgICAgICAgICAgICAgICAgICAgICBmID0gZ2V0 X2ZpbGUoaW90bGJfZmlsZS0+ZmlsZSk7Cj4+PiArICAgICAgICAgICAgICAgICAgICAgZW50cnku b2Zmc2V0ID0gaW90bGJfZmlsZS0+b2Zmc2V0Owo+Pj4gKyAgICAgICAgICAgICAgICAgICAgIGVu dHJ5LnN0YXJ0ID0gbWFwLT5zdGFydDsKPj4+ICsgICAgICAgICAgICAgICAgICAgICBlbnRyeS5s YXN0ID0gbWFwLT5sYXN0Owo+Pj4gKyAgICAgICAgICAgICAgICAgICAgIGVudHJ5LnBlcm0gPSBt YXAtPnBlcm07Cj4+PiArICAgICAgICAgICAgIH0KPj4+ICsgICAgICAgICAgICAgc3Bpbl91bmxv Y2soJmRldi0+aW9tbXVfbG9jayk7Cj4+PiArICAgICAgICAgICAgIGlmICghZikgewo+Pj4gKyAg ICAgICAgICAgICAgICAgICAgIHJldCA9IC1FSU5WQUw7Cj4+PiArICAgICAgICAgICAgICAgICAg ICAgYnJlYWs7Cj4+PiArICAgICAgICAgICAgIH0KPj4+ICsgICAgICAgICAgICAgaWYgKGNvcHlf dG9fdXNlcihhcmdwLCAmZW50cnksIHNpemVvZihlbnRyeSkpKSB7Cj4+PiArICAgICAgICAgICAg ICAgICAgICAgZnB1dChmKTsKPj4+ICsgICAgICAgICAgICAgICAgICAgICByZXQgPSAtRUZBVUxU Owo+Pj4gKyAgICAgICAgICAgICAgICAgICAgIGJyZWFrOwo+Pj4gKyAgICAgICAgICAgICB9Cj4+ PiArICAgICAgICAgICAgIHJldCA9IGdldF91bnVzZWRfZmRfZmxhZ3MocGVybV90b19maWxlX2Zs YWdzKGVudHJ5LnBlcm0pKTsKPj4+ICsgICAgICAgICAgICAgaWYgKHJldCA8IDApIHsKPj4+ICsg ICAgICAgICAgICAgICAgICAgICBmcHV0KGYpOwo+Pj4gKyAgICAgICAgICAgICAgICAgICAgIGJy ZWFrOwo+Pj4gKyAgICAgICAgICAgICB9Cj4+PiArICAgICAgICAgICAgIGZkX2luc3RhbGwocmV0 LCBmKTsKPj4+ICsgICAgICAgICAgICAgYnJlYWs7Cj4+PiArICAgICB9Cj4+PiArICAgICBjYXNl IFZEVVNFX1ZRX1NFVFVQX0tJQ0tGRDogewo+Pj4gKyAgICAgICAgICAgICBzdHJ1Y3QgdmR1c2Vf dnFfZXZlbnRmZCBldmVudGZkOwo+Pj4gKwo+Pj4gKyAgICAgICAgICAgICByZXQgPSAtRUZBVUxU Owo+Pj4gKyAgICAgICAgICAgICBpZiAoY29weV9mcm9tX3VzZXIoJmV2ZW50ZmQsIGFyZ3AsIHNp emVvZihldmVudGZkKSkpCj4+PiArICAgICAgICAgICAgICAgICAgICAgYnJlYWs7Cj4+PiArCj4+ PiArICAgICAgICAgICAgIHJldCA9IHZkdXNlX2tpY2tmZF9zZXR1cChkZXYsICZldmVudGZkKTsK Pj4+ICsgICAgICAgICAgICAgYnJlYWs7Cj4+PiArICAgICB9Cj4+PiArICAgICBjYXNlIFZEVVNF X1ZRX1NFVFVQX0lSUUZEOiB7Cj4+PiArICAgICAgICAgICAgIHN0cnVjdCB2ZHVzZV92cV9ldmVu dGZkIGV2ZW50ZmQ7Cj4+PiArCj4+PiArICAgICAgICAgICAgIHJldCA9IC1FRkFVTFQ7Cj4+PiAr ICAgICAgICAgICAgIGlmIChjb3B5X2Zyb21fdXNlcigmZXZlbnRmZCwgYXJncCwgc2l6ZW9mKGV2 ZW50ZmQpKSkKPj4+ICsgICAgICAgICAgICAgICAgICAgICBicmVhazsKPj4+ICsKPj4+ICsgICAg ICAgICAgICAgcmV0ID0gdmR1c2VfdmlycWZkX3NldHVwKGRldiwgJmV2ZW50ZmQpOwo+Pj4gKyAg ICAgICAgICAgICBicmVhazsKPj4+ICsgICAgIH0KPj4+ICsgICAgIH0KPj4+ICsgICAgIG11dGV4 X3VubG9jaygmZGV2LT5sb2NrKTsKPj4+ICsKPj4+ICsgICAgIHJldHVybiByZXQ7Cj4+PiArfQo+ Pj4gKwo+Pj4gK3N0YXRpYyBpbnQgdmR1c2VfZGV2X3JlbGVhc2Uoc3RydWN0IGlub2RlICppbm9k ZSwgc3RydWN0IGZpbGUgKmZpbGUpCj4+PiArewo+Pj4gKyAgICAgc3RydWN0IHZkdXNlX2RldiAq ZGV2ID0gZmlsZS0+cHJpdmF0ZV9kYXRhOwo+Pj4gKwo+Pj4gKyAgICAgdmR1c2Vfa2lja2ZkX3Jl bGVhc2UoZGV2KTsKPj4+ICsgICAgIHZkdXNlX3ZpcnFmZF9yZWxlYXNlKGRldik7Cj4+PiArICAg ICBkZXYtPmNvbm5lY3RlZCA9IGZhbHNlOwo+Pj4gKwo+Pj4gKyAgICAgcmV0dXJuIDA7Cj4+PiAr fQo+Pj4gKwo+Pj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgZmlsZV9vcGVyYXRpb25zIHZkdXNlX2Rl dl9mb3BzID0gewo+Pj4gKyAgICAgLm93bmVyICAgICAgICAgID0gVEhJU19NT0RVTEUsCj4+PiAr ICAgICAucmVsZWFzZSAgICAgICAgPSB2ZHVzZV9kZXZfcmVsZWFzZSwKPj4+ICsgICAgIC5yZWFk X2l0ZXIgICAgICA9IHZkdXNlX2Rldl9yZWFkX2l0ZXIsCj4+PiArICAgICAud3JpdGVfaXRlciAg ICAgPSB2ZHVzZV9kZXZfd3JpdGVfaXRlciwKPj4+ICsgICAgIC5wb2xsICAgICAgICAgICA9IHZk dXNlX2Rldl9wb2xsLAo+Pj4gKyAgICAgLnVubG9ja2VkX2lvY3RsID0gdmR1c2VfZGV2X2lvY3Rs LAo+Pj4gKyAgICAgLmNvbXBhdF9pb2N0bCAgID0gY29tcGF0X3B0cl9pb2N0bCwKPj4+ICsgICAg IC5sbHNlZWsgICAgICAgICA9IG5vb3BfbGxzZWVrLAo+Pj4gK307Cj4+PiArCj4+PiArc3RhdGlj IHN0cnVjdCB2ZHVzZV9kZXYgKnZkdXNlX2Rldl9jcmVhdGUodm9pZCkKPj4+ICt7Cj4+PiArICAg ICBzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYgPSBremFsbG9jKHNpemVvZigqZGV2KSwgR0ZQX0tFUk5F TCk7Cj4+PiArCj4+PiArICAgICBpZiAoIWRldikKPj4+ICsgICAgICAgICAgICAgcmV0dXJuIE5V TEw7Cj4+PiArCj4+PiArICAgICBkZXYtPmlvbW11ID0gdmhvc3RfaW90bGJfYWxsb2MoMjA0OCwg MCk7Cj4+Cj4+IElzIDIwNDggc3VmZmljaWVudCBoZXJlPwo+Pgo+IEhvdyBhYm91dCBsZXR0aW5n IHVzZXJzcGFjZSB0byBkZWZpbmUgaXQ/CgoKRmluZSB3aXRoIG1lLgoKCj4KPgo+Pj4gKyAgICAg aWYgKCFkZXYtPmlvbW11KSB7Cj4+PiArICAgICAgICAgICAgIGtmcmVlKGRldik7Cj4+PiArICAg ICAgICAgICAgIHJldHVybiBOVUxMOwo+Pj4gKyAgICAgfQo+Pj4gKwo+Pj4gKyAgICAgbXV0ZXhf aW5pdCgmZGV2LT5sb2NrKTsKPj4+ICsgICAgIHNwaW5fbG9ja19pbml0KCZkZXYtPm1zZ19sb2Nr KTsKPj4+ICsgICAgIElOSVRfTElTVF9IRUFEKCZkZXYtPnNlbmRfbGlzdCk7Cj4+PiArICAgICBJ TklUX0xJU1RfSEVBRCgmZGV2LT5yZWN2X2xpc3QpOwo+Pj4gKyAgICAgYXRvbWljNjRfc2V0KCZk ZXYtPm1zZ191bmlxdWUsIDApOwo+Pj4gKyAgICAgc3Bpbl9sb2NrX2luaXQoJmRldi0+aW9tbXVf bG9jayk7Cj4+PiArICAgICBhdG9taWNfc2V0KCZkZXYtPmJvdW5jZV9tYXAsIDApOwo+Pj4gKwo+ Pj4gKyAgICAgaW5pdF93YWl0cXVldWVfaGVhZCgmZGV2LT53YWl0cSk7Cj4+PiArCj4+PiArICAg ICByZXR1cm4gZGV2Owo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgdm9pZCB2ZHVzZV9kZXZfZGVz dHJveShzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYpCj4+PiArewo+Pj4gKyAgICAgdmhvc3RfaW90bGJf ZnJlZShkZXYtPmlvbW11KTsKPj4+ICsgICAgIG11dGV4X2Rlc3Ryb3koJmRldi0+bG9jayk7Cj4+ PiArICAgICBrZnJlZShkZXYpOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgc3RydWN0IHZkdXNl X2RldiAqdmR1c2VfZmluZF9kZXYodTMyIGlkKQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVz ZV9kZXYgKnRtcCwgKmRldiA9IE5VTEw7Cj4+PiArCj4+PiArICAgICBsaXN0X2Zvcl9lYWNoX2Vu dHJ5KHRtcCwgJnZkdXNlX2RldnMsIGxpc3QpIHsKPj4+ICsgICAgICAgICAgICAgaWYgKHRtcC0+ aWQgPT0gaWQpIHsKPj4+ICsgICAgICAgICAgICAgICAgICAgICBkZXYgPSB0bXA7Cj4+PiArICAg ICAgICAgICAgICAgICAgICAgYnJlYWs7Cj4+PiArICAgICAgICAgICAgIH0KPj4+ICsgICAgIH0K Pj4+ICsgICAgIHJldHVybiBkZXY7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyBpbnQgdmR1c2Vf ZGVzdHJveV9kZXYodTMyIGlkKQo+Pj4gK3sKPj4+ICsgICAgIHN0cnVjdCB2ZHVzZV9kZXYgKmRl diA9IHZkdXNlX2ZpbmRfZGV2KGlkKTsKPj4+ICsKPj4+ICsgICAgIGlmICghZGV2KQo+Pj4gKyAg ICAgICAgICAgICByZXR1cm4gLUVJTlZBTDsKPj4+ICsKPj4+ICsgICAgIGlmIChkZXYtPnZkZXYg fHwgZGV2LT5jb25uZWN0ZWQpCj4+PiArICAgICAgICAgICAgIHJldHVybiAtRUJVU1k7Cj4+PiAr Cj4+PiArICAgICBsaXN0X2RlbCgmZGV2LT5saXN0KTsKPj4+ICsgICAgIGtmcmVlKGRldi0+dnFz KTsKPj4+ICsgICAgIHZkdXNlX2RvbWFpbl9kZXN0cm95KGRldi0+ZG9tYWluKTsKPj4+ICsgICAg IHZkdXNlX2Rldl9kZXN0cm95KGRldik7Cj4+PiArCj4+PiArICAgICByZXR1cm4gMDsKPj4+ICt9 Cj4+PiArCj4+PiArc3RhdGljIGludCB2ZHVzZV9jcmVhdGVfZGV2KHN0cnVjdCB2ZHVzZV9kZXZf Y29uZmlnICpjb25maWcpCj4+PiArewo+Pj4gKyAgICAgaW50IGksIGZkOwo+Pj4gKyAgICAgc3Ry dWN0IHZkdXNlX2RldiAqZGV2Owo+Pj4gKyAgICAgY2hhciBuYW1lWzY0XTsKPj4+ICsKPj4+ICsg ICAgIGlmICh2ZHVzZV9maW5kX2Rldihjb25maWctPmlkKSkKPj4+ICsgICAgICAgICAgICAgcmV0 dXJuIC1FRVhJU1Q7Cj4+PiArCj4+PiArICAgICBkZXYgPSB2ZHVzZV9kZXZfY3JlYXRlKCk7Cj4+ PiArICAgICBpZiAoIWRldikKPj4+ICsgICAgICAgICAgICAgcmV0dXJuIC1FTk9NRU07Cj4+PiAr Cj4+PiArICAgICBkZXYtPmlkID0gY29uZmlnLT5pZDsKPj4+ICsgICAgIGRldi0+ZGV2aWNlX2lk ID0gY29uZmlnLT5kZXZpY2VfaWQ7Cj4+PiArICAgICBkZXYtPnZlbmRvcl9pZCA9IGNvbmZpZy0+ dmVuZG9yX2lkOwo+Pj4gKyAgICAgZGV2LT5kb21haW4gPSB2ZHVzZV9kb21haW5fY3JlYXRlKGNv bmZpZy0+Ym91bmNlX3NpemUpOwo+Pgo+PiBEbyB3ZSBuZWVkIGEgdXBwZXIgbGltaXQgb2YgYm91 bmNlX3NpemU/Cj4+Cj4gSSBhZ3JlZS4gQW55IGNvbW1lbnQgZm9yIHRoZSB2YWx1ZT8KCgpTb21l dGhpbmcgbGlrZSBzd2lvdGxiIGRlZmF1bHQgdmFsdWUgKDY0TSk/CgoKPgo+Pj4gKyAgICAgaWYg KCFkZXYtPmRvbWFpbikKPj4+ICsgICAgICAgICAgICAgZ290byBlcnJfZG9tYWluOwo+Pj4gKwo+ Pj4gKyAgICAgZGV2LT52cV9hbGlnbiA9IGNvbmZpZy0+dnFfYWxpZ247Cj4+PiArICAgICBkZXYt PnZxX3NpemVfbWF4ID0gY29uZmlnLT52cV9zaXplX21heDsKPj4+ICsgICAgIGRldi0+dnFfbnVt ID0gY29uZmlnLT52cV9udW07Cj4+PiArICAgICBkZXYtPnZxcyA9IGtjYWxsb2MoZGV2LT52cV9u dW0sIHNpemVvZigqZGV2LT52cXMpLCBHRlBfS0VSTkVMKTsKPj4+ICsgICAgIGlmICghZGV2LT52 cXMpCj4+PiArICAgICAgICAgICAgIGdvdG8gZXJyX3ZxczsKPj4+ICsKPj4+ICsgICAgIGZvciAo aSA9IDA7IGkgPCBkZXYtPnZxX251bTsgaSsrKSB7Cj4+PiArICAgICAgICAgICAgIGRldi0+dnFz W2ldLmluZGV4ID0gaTsKPj4+ICsgICAgICAgICAgICAgc3Bpbl9sb2NrX2luaXQoJmRldi0+dnFz W2ldLmtpY2tfbG9jayk7Cj4+PiArICAgICAgICAgICAgIHNwaW5fbG9ja19pbml0KCZkZXYtPnZx c1tpXS5pcnFfbG9jayk7Cj4+PiArICAgICB9Cj4+PiArCj4+PiArICAgICBzbnByaW50ZihuYW1l LCBzaXplb2YobmFtZSksICJbdmR1c2UtZGV2OiV1XSIsIGNvbmZpZy0+aWQpOwo+Pj4gKyAgICAg ZmQgPSBhbm9uX2lub2RlX2dldGZkKG5hbWUsICZ2ZHVzZV9kZXZfZm9wcywgZGV2LCBPX1JEV1Ig fCBPX0NMT0VYRUMpOwo+Pgo+PiBBbnkgcmVhc29uIGZvciBjbG9zaW5nIG9uIGV4ZWMgaGVyZT8K Pj4KPiBMb29rcyBsaWtlIHdlIGNhbiByZW1vdmUgdGhpcyBmbGFnLgo+Cj4+PiArICAgICBpZiAo ZmQgPCAwKQo+Pj4gKyAgICAgICAgICAgICBnb3RvIGVycl9mZDsKPj4+ICsKPj4+ICsgICAgIGRl di0+Y29ubmVjdGVkID0gdHJ1ZTsKPj4+ICsgICAgIGxpc3RfYWRkKCZkZXYtPmxpc3QsICZ2ZHVz ZV9kZXZzKTsKPj4+ICsKPj4+ICsgICAgIHJldHVybiBmZDsKPj4+ICtlcnJfZmQ6Cj4+PiArICAg ICBrZnJlZShkZXYtPnZxcyk7Cj4+PiArZXJyX3ZxczoKPj4+ICsgICAgIHZkdXNlX2RvbWFpbl9k ZXN0cm95KGRldi0+ZG9tYWluKTsKPj4+ICtlcnJfZG9tYWluOgo+Pj4gKyAgICAgdmR1c2VfZGV2 X2Rlc3Ryb3koZGV2KTsKPj4+ICsgICAgIHJldHVybiBmZDsKPj4+ICt9Cj4+PiArCj4+PiArc3Rh dGljIGxvbmcgdmR1c2VfaW9jdGwoc3RydWN0IGZpbGUgKmZpbGUsIHVuc2lnbmVkIGludCBjbWQs Cj4+PiArICAgICAgICAgICAgICAgICAgICAgdW5zaWduZWQgbG9uZyBhcmcpCj4+PiArewo+Pj4g KyAgICAgaW50IHJldDsKPj4+ICsgICAgIHZvaWQgX191c2VyICphcmdwID0gKHZvaWQgX191c2Vy ICopYXJnOwo+Pj4gKwo+Pj4gKyAgICAgbXV0ZXhfbG9jaygmdmR1c2VfbG9jayk7Cj4+PiArICAg ICBzd2l0Y2ggKGNtZCkgewo+Pj4gKyAgICAgY2FzZSBWRFVTRV9DUkVBVEVfREVWOiB7Cj4+PiAr ICAgICAgICAgICAgIHN0cnVjdCB2ZHVzZV9kZXZfY29uZmlnIGNvbmZpZzsKPj4+ICsKPj4+ICsg ICAgICAgICAgICAgcmV0ID0gLUVGQVVMVDsKPj4+ICsgICAgICAgICAgICAgaWYgKGNvcHlfZnJv bV91c2VyKCZjb25maWcsIGFyZ3AsIHNpemVvZihjb25maWcpKSkKPj4+ICsgICAgICAgICAgICAg ICAgICAgICBicmVhazsKPj4+ICsKPj4+ICsgICAgICAgICAgICAgcmV0ID0gdmR1c2VfY3JlYXRl X2RldigmY29uZmlnKTsKPj4+ICsgICAgICAgICAgICAgYnJlYWs7Cj4+PiArICAgICB9Cj4+PiAr ICAgICBjYXNlIFZEVVNFX0RFU1RST1lfREVWOgo+Pj4gKyAgICAgICAgICAgICByZXQgPSB2ZHVz ZV9kZXN0cm95X2RldihhcmcpOwo+Pj4gKyAgICAgICAgICAgICBicmVhazsKPj4+ICsgICAgIGRl ZmF1bHQ6Cj4+PiArICAgICAgICAgICAgIHJldCA9IC1FSU5WQUw7Cj4+PiArICAgICAgICAgICAg IGJyZWFrOwo+Pj4gKyAgICAgfQo+Pj4gKyAgICAgbXV0ZXhfdW5sb2NrKCZ2ZHVzZV9sb2NrKTsK Pj4+ICsKPj4+ICsgICAgIHJldHVybiByZXQ7Cj4+PiArfQo+Pj4gKwo+Pj4gK3N0YXRpYyBjb25z dCBzdHJ1Y3QgZmlsZV9vcGVyYXRpb25zIHZkdXNlX2ZvcHMgPSB7Cj4+PiArICAgICAub3duZXIg ICAgICAgICAgPSBUSElTX01PRFVMRSwKPj4+ICsgICAgIC51bmxvY2tlZF9pb2N0bCA9IHZkdXNl X2lvY3RsLAo+Pj4gKyAgICAgLmNvbXBhdF9pb2N0bCAgID0gY29tcGF0X3B0cl9pb2N0bCwKPj4+ ICsgICAgIC5sbHNlZWsgICAgICAgICA9IG5vb3BfbGxzZWVrLAo+Pj4gK307Cj4+PiArCj4+PiAr c3RhdGljIHN0cnVjdCBtaXNjZGV2aWNlIHZkdXNlX21pc2MgPSB7Cj4+PiArICAgICAuZm9wcyA9 ICZ2ZHVzZV9mb3BzLAo+Pj4gKyAgICAgLm1pbm9yID0gTUlTQ19EWU5BTUlDX01JTk9SLAo+Pj4g KyAgICAgLm5hbWUgPSAidmR1c2UiLAo+Pj4gK307Cj4+PiArCj4+PiArc3RhdGljIHZvaWQgdmR1 c2VfcGFyZW50X3JlbGVhc2Uoc3RydWN0IGRldmljZSAqZGV2KQo+Pj4gK3sKPj4+ICt9Cj4+PiAr Cj4+PiArc3RhdGljIHN0cnVjdCBkZXZpY2UgdmR1c2VfcGFyZW50ID0gewo+Pj4gKyAgICAgLmlu aXRfbmFtZSA9ICJ2ZHVzZSIsCj4+PiArICAgICAucmVsZWFzZSA9IHZkdXNlX3BhcmVudF9yZWxl YXNlLAo+Pj4gK307Cj4+PiArCj4+PiArc3RhdGljIHN0cnVjdCB2ZHBhX3BhcmVudF9kZXYgcGFy ZW50X2RldjsKPj4+ICsKPj4+ICtzdGF0aWMgaW50IHZkdXNlX2Rldl9hZGRfdmRwYShzdHJ1Y3Qg dmR1c2VfZGV2ICpkZXYsIGNvbnN0IGNoYXIgKm5hbWUpCj4+PiArewo+Pj4gKyAgICAgc3RydWN0 IHZkdXNlX3ZkcGEgKnZkZXYgPSBkZXYtPnZkZXY7Cj4+PiArICAgICBpbnQgcmV0Owo+Pj4gKwo+ Pj4gKyAgICAgaWYgKHZkZXYpCj4+PiArICAgICAgICAgICAgIHJldHVybiAtRUVYSVNUOwo+Pj4g Kwo+Pj4gKyAgICAgdmRldiA9IHZkcGFfYWxsb2NfZGV2aWNlKHN0cnVjdCB2ZHVzZV92ZHBhLCB2 ZHBhLCBOVUxMLAo+Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICZ2ZHVzZV92ZHBh X2NvbmZpZ19vcHMsCj4+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2LT52cV9u dW0sIG5hbWUsIHRydWUpOwo+Pj4gKyAgICAgaWYgKCF2ZGV2KQo+Pj4gKyAgICAgICAgICAgICBy ZXR1cm4gLUVOT01FTTsKPj4+ICsKPj4+ICsgICAgIHZkZXYtPmRldiA9IGRldjsKPj4+ICsgICAg IHZkZXYtPnZkcGEuZGV2LmRtYV9tYXNrID0gJnZkZXYtPnZkcGEuZGV2LmNvaGVyZW50X2RtYV9t YXNrOwo+Pj4gKyAgICAgcmV0ID0gZG1hX3NldF9tYXNrX2FuZF9jb2hlcmVudCgmdmRldi0+dmRw YS5kZXYsIERNQV9CSVRfTUFTSyg2NCkpOwo+Pj4gKyAgICAgaWYgKHJldCkKPj4+ICsgICAgICAg ICAgICAgZ290byBlcnI7Cj4+PiArCj4+PiArICAgICBzZXRfZG1hX29wcygmdmRldi0+dmRwYS5k ZXYsICZ2ZHVzZV9kZXZfZG1hX29wcyk7Cj4+PiArICAgICB2ZGV2LT52ZHBhLmRtYV9kZXYgPSAm dmRldi0+dmRwYS5kZXY7Cj4+PiArICAgICB2ZGV2LT52ZHBhLnBkZXYgPSAmcGFyZW50X2RldjsK Pj4+ICsKPj4+ICsgICAgIHJldCA9IF92ZHBhX3JlZ2lzdGVyX2RldmljZSgmdmRldi0+dmRwYSk7 Cj4+PiArICAgICBpZiAocmV0KQo+Pj4gKyAgICAgICAgICAgICBnb3RvIGVycjsKPj4+ICsKPj4+ ICsgICAgIGRldi0+dmRldiA9IHZkZXY7Cj4+PiArCj4+PiArICAgICByZXR1cm4gMDsKPj4+ICtl cnI6Cj4+PiArICAgICBwdXRfZGV2aWNlKCZ2ZGV2LT52ZHBhLmRldik7Cj4+PiArICAgICByZXR1 cm4gcmV0Owo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgc3RydWN0IHZkcGFfZGV2aWNlICp2ZHBh X2Rldl9hZGQoc3RydWN0IHZkcGFfcGFyZW50X2RldiAqcGRldiwKPj4+ICsgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2hhciAqbmFtZSwgdTMyIGRldmljZV9pZCwK Pj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IG5sYXR0ciAq KmF0dHJzKQo+Pj4gK3sKPj4+ICsgICAgIHUzMiB2ZHVzZV9pZDsKPj4+ICsgICAgIHN0cnVjdCB2 ZHVzZV9kZXYgKmRldjsKPj4+ICsgICAgIGludCByZXQgPSAtRUlOVkFMOwo+Pj4gKwo+Pj4gKyAg ICAgaWYgKCFhdHRyc1tWRFBBX0FUVFJfQkFDS0VORF9JRF0pCj4+PiArICAgICAgICAgICAgIHJl dHVybiBFUlJfUFRSKC1FSU5WQUwpOwo+Pj4gKwo+Pj4gKyAgICAgbXV0ZXhfbG9jaygmdmR1c2Vf bG9jayk7Cj4+PiArICAgICB2ZHVzZV9pZCA9IG5sYV9nZXRfdTMyKGF0dHJzW1ZEUEFfQVRUUl9C QUNLRU5EX0lEXSk7Cj4+Cj4+IEkgd29uZGVyIHdoeSBub3QgdXNpbmcgbmFtZSBoZXJlPwo+Pgo+ IERvIHlvdSBtZWFuIHVzZSB0aGUgc2FtZSBuYW1lIGZvciBib3RoIGJhY2tlbmQgYW5kIGZyb250 ZW5kPyBJZiBzbywgd2UKPiBuZWVkIHRvIGFkZCBhIG5hbWUgZm9yIHZkdXNlIGRldmljZSBvciBy ZXBsYWNlIGlkIHdpdGggbmFtZSB0bwo+IGlkZW50aWZ5IGEgdmR1c2UgZGV2aWNlLiBXaGljaCB3 YXkgZG8geW91IHByZWZlcj8KCgpJIHRoaW5rIGlmIHdlIGNhbiBkbyBpdCBpbiBuYW1lLCBpdCdz IGJldHRlciBub3QgaW50cm9kdWNlIGFueSBvdGhlciAKdGhpbmcgbGlrZSAiaWQiLiBJdCB3aWxs IGNvbXBsaWNhdGUgdGhlIG1hbmFnZW1lbnQgc29mdHdhcmUuCgoKPgo+PiBBbmQgaXQgbG9va3Mg dG8gbWUgaXQgd291bGQgYmUgZWFzaWVyIGlmIHdlIGNyZWF0ZSBhIGNoYXIgZGV2aWNlIHBlcgo+ PiB2ZHVzZS4gVGhpcyBtYWtlcyB0aGUgZGV2aWNlIGFkZHJlc3NpbmcgbW9yZSByb2J1c3QgdGhh biBwYXNzaW5nIGlkCj4+IHNpbGVudGx5IGFtb25nIHByb2Nlc3Nlcy4KPj4KPiBJdCdzIE9LIHRv IG1lLgo+Cj4+PiArICAgICBkZXYgPSB2ZHVzZV9maW5kX2Rldih2ZHVzZV9pZCk7Cj4+PiArICAg ICBpZiAoIWRldikKPj4+ICsgICAgICAgICAgICAgZ290byB1bmxvY2s7Cj4+PiArCj4+PiArICAg ICBpZiAoZGV2LT5kZXZpY2VfaWQgIT0gZGV2aWNlX2lkKQo+Pj4gKyAgICAgICAgICAgICBnb3Rv IHVubG9jazsKPj4+ICsKPj4+ICsgICAgIHJldCA9IHZkdXNlX2Rldl9hZGRfdmRwYShkZXYsIG5h bWUpOwo+Pj4gK3VubG9jazoKPj4+ICsgICAgIG11dGV4X3VubG9jaygmdmR1c2VfbG9jayk7Cj4+ PiArICAgICBpZiAocmV0KQo+Pj4gKyAgICAgICAgICAgICByZXR1cm4gRVJSX1BUUihyZXQpOwo+ Pj4gKwo+Pj4gKyAgICAgcmV0dXJuICZkZXYtPnZkZXYtPnZkcGE7Cj4+PiArfQo+Pj4gKwo+Pj4g K3N0YXRpYyB2b2lkIHZkcGFfZGV2X2RlbChzdHJ1Y3QgdmRwYV9wYXJlbnRfZGV2ICpwZGV2LCBz dHJ1Y3QgdmRwYV9kZXZpY2UgKmRldikKPj4+ICt7Cj4+PiArICAgICBfdmRwYV91bnJlZ2lzdGVy X2RldmljZShkZXYpOwo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgY29uc3Qgc3RydWN0IHZkcGFf ZGV2X29wcyB2ZHBhX2Rldl9wYXJlbnRfb3BzID0gewo+Pj4gKyAgICAgLmRldl9hZGQgPSB2ZHBh X2Rldl9hZGQsCj4+PiArICAgICAuZGV2X2RlbCA9IHZkcGFfZGV2X2RlbAo+Pj4gK307Cj4+PiAr Cj4+PiArc3RhdGljIHN0cnVjdCB2aXJ0aW9fZGV2aWNlX2lkIGlkX3RhYmxlW10gPSB7Cj4+PiAr ICAgICB7IFZJUlRJT19ERVZfQU5ZX0lELCBWSVJUSU9fREVWX0FOWV9JRCB9LAo+Pj4gKyAgICAg eyAwIH0sCj4+PiArfTsKPj4+ICsKPj4+ICtzdGF0aWMgc3RydWN0IHZkcGFfcGFyZW50X2RldiBw YXJlbnRfZGV2ID0gewo+Pj4gKyAgICAgLmRldmljZSA9ICZ2ZHVzZV9wYXJlbnQsCj4+PiArICAg ICAuaWRfdGFibGUgPSBpZF90YWJsZSwKPj4+ICsgICAgIC5vcHMgPSAmdmRwYV9kZXZfcGFyZW50 X29wcywKPj4+ICt9Owo+Pj4gKwo+Pj4gK3N0YXRpYyBpbnQgdmR1c2VfcGFyZW50ZGV2X2luaXQo dm9pZCkKPj4+ICt7Cj4+PiArICAgICBpbnQgcmV0Owo+Pj4gKwo+Pj4gKyAgICAgcmV0ID0gZGV2 aWNlX3JlZ2lzdGVyKCZ2ZHVzZV9wYXJlbnQpOwo+Pj4gKyAgICAgaWYgKHJldCkKPj4+ICsgICAg ICAgICAgICAgcmV0dXJuIHJldDsKPj4+ICsKPj4+ICsgICAgIHJldCA9IHZkcGFfcGFyZW50ZGV2 X3JlZ2lzdGVyKCZwYXJlbnRfZGV2KTsKPj4+ICsgICAgIGlmIChyZXQpCj4+PiArICAgICAgICAg ICAgIGdvdG8gZXJyOwo+Pj4gKwo+Pj4gKyAgICAgcmV0dXJuIDA7Cj4+PiArZXJyOgo+Pj4gKyAg ICAgZGV2aWNlX3VucmVnaXN0ZXIoJnZkdXNlX3BhcmVudCk7Cj4+PiArICAgICByZXR1cm4gcmV0 Owo+Pj4gK30KPj4+ICsKPj4+ICtzdGF0aWMgdm9pZCB2ZHVzZV9wYXJlbnRkZXZfZXhpdCh2b2lk KQo+Pj4gK3sKPj4+ICsgICAgIHZkcGFfcGFyZW50ZGV2X3VucmVnaXN0ZXIoJnBhcmVudF9kZXYp Owo+Pj4gKyAgICAgZGV2aWNlX3VucmVnaXN0ZXIoJnZkdXNlX3BhcmVudCk7Cj4+PiArfQo+Pj4g Kwo+Pj4gK3N0YXRpYyBpbnQgdmR1c2VfaW5pdCh2b2lkKQo+Pj4gK3sKPj4+ICsgICAgIGludCBy ZXQ7Cj4+PiArCj4+PiArICAgICByZXQgPSBtaXNjX3JlZ2lzdGVyKCZ2ZHVzZV9taXNjKTsKPj4+ ICsgICAgIGlmIChyZXQpCj4+PiArICAgICAgICAgICAgIHJldHVybiByZXQ7Cj4+PiArCj4+PiAr ICAgICByZXQgPSAtRU5PTUVNOwo+Pj4gKyAgICAgdmR1c2VfdmRwYV93cSA9IGFsbG9jX3dvcmtx dWV1ZSgidmR1c2UtdmRwYSIsIFdRX1VOQk9VTkQsIDEpOwo+Pj4gKyAgICAgaWYgKCF2ZHVzZV92 ZHBhX3dxKQo+Pj4gKyAgICAgICAgICAgICBnb3RvIGVycl92ZHBhX3dxOwo+Pj4gKwo+Pj4gKyAg ICAgcmV0ID0gdmR1c2VfdmlycWZkX2luaXQoKTsKPj4+ICsgICAgIGlmIChyZXQpCj4+PiArICAg ICAgICAgICAgIGdvdG8gZXJyX2lycWZkOwo+Pj4gKwo+Pj4gKyAgICAgcmV0ID0gdmR1c2VfcGFy ZW50ZGV2X2luaXQoKTsKPj4+ICsgICAgIGlmIChyZXQpCj4+PiArICAgICAgICAgICAgIGdvdG8g ZXJyX3BhcmVudGRldjsKPj4+ICsKPj4+ICsgICAgIHJldHVybiAwOwo+Pj4gK2Vycl9wYXJlbnRk ZXY6Cj4+PiArICAgICB2ZHVzZV92aXJxZmRfZXhpdCgpOwo+Pj4gK2Vycl9pcnFmZDoKPj4+ICsg ICAgIGRlc3Ryb3lfd29ya3F1ZXVlKHZkdXNlX3ZkcGFfd3EpOwo+Pj4gK2Vycl92ZHBhX3dxOgo+ Pj4gKyAgICAgbWlzY19kZXJlZ2lzdGVyKCZ2ZHVzZV9taXNjKTsKPj4+ICsgICAgIHJldHVybiBy ZXQ7Cj4+PiArfQo+Pj4gK21vZHVsZV9pbml0KHZkdXNlX2luaXQpOwo+Pj4gKwo+Pj4gK3N0YXRp YyB2b2lkIHZkdXNlX2V4aXQodm9pZCkKPj4+ICt7Cj4+PiArICAgICBtaXNjX2RlcmVnaXN0ZXIo JnZkdXNlX21pc2MpOwo+Pj4gKyAgICAgZGVzdHJveV93b3JrcXVldWUodmR1c2VfdmRwYV93cSk7 Cj4+PiArICAgICB2ZHVzZV92aXJxZmRfZXhpdCgpOwo+Pj4gKyAgICAgdmR1c2VfcGFyZW50ZGV2 X2V4aXQoKTsKPj4+ICt9Cj4+PiArbW9kdWxlX2V4aXQodmR1c2VfZXhpdCk7Cj4+PiArCj4+PiAr TU9EVUxFX1ZFUlNJT04oRFJWX1ZFUlNJT04pOwo+Pj4gK01PRFVMRV9MSUNFTlNFKERSVl9MSUNF TlNFKTsKPj4+ICtNT0RVTEVfQVVUSE9SKERSVl9BVVRIT1IpOwo+Pj4gK01PRFVMRV9ERVNDUklQ VElPTihEUlZfREVTQyk7Cj4+PiBkaWZmIC0tZ2l0IGEvaW5jbHVkZS91YXBpL2xpbnV4L3ZkcGEu aCBiL2luY2x1ZGUvdWFwaS9saW51eC92ZHBhLmgKPj4+IGluZGV4IGJiYThiODNhOTRiNS4uYTdh ODQxZTVmZmM3IDEwMDY0NAo+Pj4gLS0tIGEvaW5jbHVkZS91YXBpL2xpbnV4L3ZkcGEuaAo+Pj4g KysrIGIvaW5jbHVkZS91YXBpL2xpbnV4L3ZkcGEuaAo+Pj4gQEAgLTMzLDYgKzMzLDcgQEAgZW51 bSB2ZHBhX2F0dHIgewo+Pj4gICAgICAgIFZEUEFfQVRUUl9ERVZfVkVORE9SX0lELCAgICAgICAg ICAgICAgICAvKiB1MzIgKi8KPj4+ICAgICAgICBWRFBBX0FUVFJfREVWX01BWF9WUVMsICAgICAg ICAgICAgICAgICAgLyogdTMyICovCj4+PiAgICAgICAgVkRQQV9BVFRSX0RFVl9NQVhfVlFfU0la RSwgICAgICAgICAgICAgIC8qIHUxNiAqLwo+Pj4gKyAgICAgVkRQQV9BVFRSX0JBQ0tFTkRfSUQs ICAgICAgICAgICAgICAgICAgIC8qIHUzMiAqLwo+Pgo+PiBBcyBkaXNjdXNzZWQsIHRoaXMgbmVl ZHMgbW9yZSB0aG91Z2h0LiBCdXQgaWYgbmVjZXNzYXJ5LCB3ZSBuZWVkIGEKPj4gc2VwYXJhdGUg cGF0Y2ggZm9yIHRoaXMuCj4+Cj4gT0suCj4KPj4+ICAgICAgICAvKiBuZXcgYXR0cmlidXRlcyBt dXN0IGJlIGFkZGVkIGFib3ZlIGhlcmUgKi8KPj4+ICAgICAgICBWRFBBX0FUVFJfTUFYLAo+Pj4g ZGlmZiAtLWdpdCBhL2luY2x1ZGUvdWFwaS9saW51eC92ZHVzZS5oIGIvaW5jbHVkZS91YXBpL2xp bnV4L3ZkdXNlLmgKPj4+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4+PiBpbmRleCAwMDAwMDAwMDAw MDAuLjlmYjU1NWRkY2ZiZAo+Pj4gLS0tIC9kZXYvbnVsbAo+Pj4gKysrIGIvaW5jbHVkZS91YXBp L2xpbnV4L3ZkdXNlLmgKPj4+IEBAIC0wLDAgKzEsMTI1IEBACj4+PiArLyogU1BEWC1MaWNlbnNl LUlkZW50aWZpZXI6IEdQTC0yLjAgV0lUSCBMaW51eC1zeXNjYWxsLW5vdGUgKi8KPj4+ICsjaWZu ZGVmIF9VQVBJX1ZEVVNFX0hfCj4+PiArI2RlZmluZSBfVUFQSV9WRFVTRV9IXwo+Pj4gKwo+Pj4g KyNpbmNsdWRlIDxsaW51eC90eXBlcy5oPgo+Pj4gKwo+Pj4gKy8qIHRoZSBjb250cm9sIG1lc3Nh Z2VzIGRlZmluaXRpb24gZm9yIHJlYWQvd3JpdGUgKi8KPj4+ICsKPj4+ICsjZGVmaW5lIFZEVVNF X0NPTkZJR19EQVRBX0xFTiAgICAgICAgMjU2Cj4+PiArCj4+PiArZW51bSB2ZHVzZV9yZXFfdHlw ZSB7Cj4+PiArICAgICBWRFVTRV9TRVRfVlFfTlVNLAo+Pj4gKyAgICAgVkRVU0VfU0VUX1ZRX0FE RFIsCj4+PiArICAgICBWRFVTRV9TRVRfVlFfUkVBRFksCj4+PiArICAgICBWRFVTRV9HRVRfVlFf UkVBRFksCj4+PiArICAgICBWRFVTRV9TRVRfVlFfU1RBVEUsCj4+PiArICAgICBWRFVTRV9HRVRf VlFfU1RBVEUsCj4+PiArICAgICBWRFVTRV9TRVRfRkVBVFVSRVMsCj4+PiArICAgICBWRFVTRV9H RVRfRkVBVFVSRVMsCj4+PiArICAgICBWRFVTRV9TRVRfU1RBVFVTLAo+Pj4gKyAgICAgVkRVU0Vf R0VUX1NUQVRVUywKPj4+ICsgICAgIFZEVVNFX1NFVF9DT05GSUcsCj4+PiArICAgICBWRFVTRV9H RVRfQ09ORklHLAo+Pj4gKyAgICAgVkRVU0VfVVBEQVRFX0lPVExCLAo+Pj4gK307Cj4+PiArCj4+ PiArc3RydWN0IHZkdXNlX3ZxX251bSB7Cj4+PiArICAgICBfX3UzMiBpbmRleDsKPj4+ICsgICAg IF9fdTMyIG51bTsKPj4+ICt9Owo+Pj4gKwo+Pj4gK3N0cnVjdCB2ZHVzZV92cV9hZGRyIHsKPj4+ ICsgICAgIF9fdTMyIGluZGV4Owo+Pj4gKyAgICAgX191NjQgZGVzY19hZGRyOwo+Pj4gKyAgICAg X191NjQgZHJpdmVyX2FkZHI7Cj4+PiArICAgICBfX3U2NCBkZXZpY2VfYWRkcjsKPj4+ICt9Owo+ Pj4gKwo+Pj4gK3N0cnVjdCB2ZHVzZV92cV9yZWFkeSB7Cj4+PiArICAgICBfX3UzMiBpbmRleDsK Pj4+ICsgICAgIF9fdTggcmVhZHk7Cj4+PiArfTsKPj4+ICsKPj4+ICtzdHJ1Y3QgdmR1c2VfdnFf c3RhdGUgewo+Pj4gKyAgICAgX191MzIgaW5kZXg7Cj4+PiArICAgICBfX3UxNiBhdmFpbF9pZHg7 Cj4+PiArfTsKPj4+ICsKPj4+ICtzdHJ1Y3QgdmR1c2VfZGV2X2NvbmZpZ19kYXRhIHsKPj4+ICsg ICAgIF9fdTMyIG9mZnNldDsKPj4+ICsgICAgIF9fdTMyIGxlbjsKPj4+ICsgICAgIF9fdTggZGF0 YVtWRFVTRV9DT05GSUdfREFUQV9MRU5dOwo+Pgo+PiBUaGlzIG5vIGd1YXJhbnRlZSB0aGF0IDI1 NiBpcyBzdWZmaWNpZW50IGhlcmUuCj4+Cj4gSWYgdGhlIHNpemUgaXMgbGFyZ2VyIHRoYW4gMjU2 LCB3ZSBjYW4gdHJ5IHRvIHNwbGl0IHRoZSBvcmlnaW5hbCByZXF1ZXN0LgoKCkZpbmUsIHRoZW4g d2UgbmVlZCBkb2N1bWVudCBoZXJlIG9yIGluIHRoZSBkb2MuCgoKPgo+Pj4gK307Cj4+PiArCj4+ PiArc3RydWN0IHZkdXNlX2lvdmFfcmFuZ2Ugewo+Pj4gKyAgICAgX191NjQgc3RhcnQ7Cj4+PiAr ICAgICBfX3U2NCBsYXN0Owo+Pj4gK307Cj4+PiArCj4+PiArc3RydWN0IHZkdXNlX2Rldl9yZXF1 ZXN0IHsKPj4+ICsgICAgIF9fdTMyIHR5cGU7IC8qIHJlcXVlc3QgdHlwZSAqLwo+Pj4gKyAgICAg X191MzIgdW5pcXVlOyAvKiByZXF1ZXN0IGlkICovCj4+PiArICAgICBfX3UzMiBmbGFnczsgLyog cmVxdWVzdCBmbGFncyAqLwo+Pgo+PiBTZWVtcyB1bnVzZWQgaW4gdGhpcyBzZXJpZXMuCj4+Cj4g VGhpcyBpcyBmb3IgZnV0dXJlIHVzZS4KCgpTbyBsZXQncyB1c2UgcGFkIG9yIG90aGVyIG5hbWUu CgoKPgo+Pj4gKyAgICAgX191MzIgc2l6ZTsgLyogdGhlIHBheWxvYWQgc2l6ZSAqLwo+Pgo+PiBV bnVzZWQuCj4+Cj4gV2lsbCByZW1vdmUgaXQuCj4KPj4+ICsgICAgIHVuaW9uIHsKPj4+ICsgICAg ICAgICAgICAgc3RydWN0IHZkdXNlX3ZxX251bSB2cV9udW07IC8qIHZpcnRxdWV1ZSBudW0gKi8K Pj4+ICsgICAgICAgICAgICAgc3RydWN0IHZkdXNlX3ZxX2FkZHIgdnFfYWRkcjsgLyogdmlydHF1 ZXVlIGFkZHJlc3MgKi8KPj4+ICsgICAgICAgICAgICAgc3RydWN0IHZkdXNlX3ZxX3JlYWR5IHZx X3JlYWR5OyAvKiB2aXJ0cXVldWUgcmVhZHkgc3RhdHVzICovCj4+PiArICAgICAgICAgICAgIHN0 cnVjdCB2ZHVzZV92cV9zdGF0ZSB2cV9zdGF0ZTsgLyogdmlydHF1ZXVlIHN0YXRlICovCj4+PiAr ICAgICAgICAgICAgIHN0cnVjdCB2ZHVzZV9kZXZfY29uZmlnX2RhdGEgY29uZmlnOyAvKiB2aXJ0 aW8gZGV2aWNlIGNvbmZpZyBzcGFjZSAqLwo+Pj4gKyAgICAgICAgICAgICBzdHJ1Y3QgdmR1c2Vf aW92YV9yYW5nZSBpb3ZhOyAvKiBpb3ZhIHJhbmdlIGZvciB1cGRhdGluZyAqLwo+Pj4gKyAgICAg ICAgICAgICBfX3U2NCBmZWF0dXJlczsgLyogdmlydGlvIGZlYXR1cmVzICovCj4+PiArICAgICAg ICAgICAgIF9fdTggc3RhdHVzOyAvKiBkZXZpY2Ugc3RhdHVzICovCj4+Cj4+IExldCdzIGFkZCBz b21lIHBhZGRpbmcgZm9yIGZ1dHVyZSBleHRlbnNpb25zLgo+Pgo+IElzIHNpemVvZih2ZHVzZV9k ZXZfY29uZmlnX2RhdGEpIG9rPyBPciBjaGFyWzEwMjRdPwoKCjEwMjQgc2VlbXMgdG9vIGxhcmdl LCAxMjggb3IgMjU2IGxvb2tzIGJldHRlci4KCgo+Cj4+PiArICAgICB9Owo+Pj4gK307Cj4+PiAr Cj4+PiArc3RydWN0IHZkdXNlX2Rldl9yZXNwb25zZSB7Cj4+PiArICAgICBfX3UzMiB1bmlxdWU7 IC8qIGNvcnJlc3BvbmRpbmcgcmVxdWVzdCBpZCAqLwo+Pgo+PiBMZXQncyB1c2UgcmVxdWVzdCBp ZC4KPj4KPiBGaW5lLgo+Cj4+PiArICAgICBfX3MzMiByZXN1bHQ7IC8qIHRoZSByZXN1bHQgb2Yg cmVxdWVzdCAqLwo+Pgo+PiBMZXQncyB1c2UgbWFjcm8gb3IgZW51bSB0byBkZWZpbmUgdGhlIHN1 Y2Nlc3MgYW5kIGZhaWx1cmUgdmFsdWUuCj4+Cj4gV2lsbCBkbyBpdC4KPgo+Pj4gKyAgICAgdW5p b24gewo+Pj4gKyAgICAgICAgICAgICBzdHJ1Y3QgdmR1c2VfdnFfcmVhZHkgdnFfcmVhZHk7IC8q IHZpcnRxdWV1ZSByZWFkeSBzdGF0dXMgKi8KPj4+ICsgICAgICAgICAgICAgc3RydWN0IHZkdXNl X3ZxX3N0YXRlIHZxX3N0YXRlOyAvKiB2aXJ0cXVldWUgc3RhdGUgKi8KPj4+ICsgICAgICAgICAg ICAgc3RydWN0IHZkdXNlX2Rldl9jb25maWdfZGF0YSBjb25maWc7IC8qIHZpcnRpbyBkZXZpY2Ug Y29uZmlnIHNwYWNlICovCj4+PiArICAgICAgICAgICAgIF9fdTY0IGZlYXR1cmVzOyAvKiB2aXJ0 aW8gZmVhdHVyZXMgKi8KPj4+ICsgICAgICAgICAgICAgX191OCBzdGF0dXM7IC8qIGRldmljZSBz dGF0dXMgKi8KPj4+ICsgICAgIH07Cj4+PiArfTsKPj4+ICsKPj4+ICsvKiBpb2N0bHMgKi8KPj4+ ICsKPj4+ICtzdHJ1Y3QgdmR1c2VfZGV2X2NvbmZpZyB7Cj4+PiArICAgICBfX3UzMiBpZDsgLyog dmR1c2UgZGV2aWNlIGlkICovCj4+PiArICAgICBfX3UzMiB2ZW5kb3JfaWQ7IC8qIHZpcnRpbyB2 ZW5kb3IgaWQgKi8KPj4+ICsgICAgIF9fdTMyIGRldmljZV9pZDsgLyogdmlydGlvIGRldmljZSBp ZCAqLwo+Pj4gKyAgICAgX191NjQgYm91bmNlX3NpemU7IC8qIGJvdW5jZSBidWZmZXIgc2l6ZSBm b3IgaW9tbXUgKi8KPj4+ICsgICAgIF9fdTE2IHZxX251bTsgLyogdGhlIG51bWJlciBvZiB2aXJ0 cXVldWVzICovCj4+PiArICAgICBfX3UxNiB2cV9zaXplX21heDsgLyogdGhlIG1heCBzaXplIG9m IHZpcnRxdWV1ZSAqLwo+Pj4gKyAgICAgX191MzIgdnFfYWxpZ247IC8qIHRoZSBhbGxvY2F0aW9u IGFsaWdubWVudCBvZiB2aXJ0cXVldWUncyBtZXRhZGF0YSAqLwo+Pj4gK307Cj4+PiArCj4+PiAr c3RydWN0IHZkdXNlX2lvdGxiX2VudHJ5IHsKPj4+ICsgICAgIF9fdTY0IG9mZnNldDsgLyogdGhl IG1tYXAgb2Zmc2V0IG9uIGZkICovCj4+PiArICAgICBfX3U2NCBzdGFydDsgLyogc3RhcnQgb2Yg dGhlIElPVkEgcmFuZ2UgKi8KPj4+ICsgICAgIF9fdTY0IGxhc3Q7IC8qIGxhc3Qgb2YgdGhlIElP VkEgcmFuZ2UgKi8KPj4+ICsjZGVmaW5lIFZEVVNFX0FDQ0VTU19STyAweDEKPj4+ICsjZGVmaW5l IFZEVVNFX0FDQ0VTU19XTyAweDIKPj4+ICsjZGVmaW5lIFZEVVNFX0FDQ0VTU19SVyAweDMKPj4+ ICsgICAgIF9fdTggcGVybTsgLyogYWNjZXNzIHBlcm1pc3Npb24gb2YgdGhpcyByYW5nZSAqLwo+ Pj4gK307Cj4+PiArCj4+PiArc3RydWN0IHZkdXNlX3ZxX2V2ZW50ZmQgewo+Pj4gKyAgICAgX191 MzIgaW5kZXg7IC8qIHZpcnRxdWV1ZSBpbmRleCAqLwo+Pj4gKyAgICAgX191MzIgZmQ7IC8qIGV2 ZW50ZmQgKi8KPj4KPj4gQW55IHJlYXNvbiBmb3Igbm90IHVzaW5nIGludCBoZXJlPwo+Pgo+IFdp bGwgdXNlIF9fczMyIGluc3RlYWQuCgoKTGV0J3MgdXNlICJpbnQiIGhlcmUsIHNvIC0xIGNhbiBi ZSB1c2VkIGZvciBkZS1hc3NpZ25pbmcgdGhlIGV2ZW50ZmQuCgoKPgo+Pj4gK307Cj4+PiArCj4+ PiArI2RlZmluZSBWRFVTRV9CQVNFICAgMHg4MQo+Pj4gKwo+Pj4gKyNkZWZpbmUgVkRVU0VfQ1JF QVRFX0RFViAgICAgX0lPVyhWRFVTRV9CQVNFLCAweDAxLCBzdHJ1Y3QgdmR1c2VfZGV2X2NvbmZp ZykKPj4+ICsjZGVmaW5lIFZEVVNFX0RFU1RST1lfREVWICAgIF9JTyhWRFVTRV9CQVNFLCAweDAy KQo+Pj4gKwo+Pj4gKyNkZWZpbmUgVkRVU0VfSU9UTEJfR0VUX0ZEICAgX0lPV1IoVkRVU0VfQkFT RSwgMHgwNCwgc3RydWN0IHZkdXNlX2lvdGxiX2VudHJ5KQo+Pj4gKyNkZWZpbmUgVkRVU0VfVlFf U0VUVVBfS0lDS0ZEICAgICAgICBfSU9XKFZEVVNFX0JBU0UsIDB4MDUsIHN0cnVjdCB2ZHVzZV92 cV9ldmVudGZkKQo+Pj4gKyNkZWZpbmUgVkRVU0VfVlFfU0VUVVBfSVJRRkQgX0lPVyhWRFVTRV9C QVNFLCAweDA2LCBzdHJ1Y3QgdmR1c2VfdnFfZXZlbnRmZCkKPj4KPj4gQmV0dGVyIHdpdGggZG9j dW1lbnRhdGlvbiB0byBleHBsYWluIHRob3NlIGlvY3Rscy4KPj4KPiBXaWxsIGRvIGl0Lgo+Cj4g VGhhbmtzLAo+IFlvbmdqaQoKClRoYW5rcwoKPgoKX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX18KVmlydHVhbGl6YXRpb24gbWFpbGluZyBsaXN0ClZpcnR1YWxp emF0aW9uQGxpc3RzLmxpbnV4LWZvdW5kYXRpb24ub3JnCmh0dHBzOi8vbGlzdHMubGludXhmb3Vu ZGF0aW9uLm9yZy9tYWlsbWFuL2xpc3RpbmZvL3ZpcnR1YWxpemF0aW9u