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=unavailable 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 9CA05C433DB for ; Tue, 26 Jan 2021 19:03:44 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4CE4F206CC for ; Tue, 26 Jan 2021 19:03:44 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730109AbhAZREa (ORCPT ); Tue, 26 Jan 2021 12:04:30 -0500 Received: from us-smtp-delivery-124.mimecast.com ([216.205.24.124]:21826 "EHLO us-smtp-delivery-124.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2389702AbhAZIKz (ORCPT ); Tue, 26 Jan 2021 03:10:55 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1611648562; 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=KvMTNukmS0AnWsFcd0FnVwZKUh81DEUWq7vcN7H5ZxI=; b=ILz2sT32fJH4etI7X1C3iUL5j0JwBe1OWK5GHrHbARTlgVlO8LaPbAj90kYmauJ7JiqOt7 1yhncDmzlF38djKWTXnYM2VLJZDxd0Mu7xCGud1A5mbNOcU0owC2fSrLPDKybKGW81HV06 p9Iq2Vd5XyrmPfHbKk3bB1KoxRAi7us= 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-159-AS5h8lmwPXOMdAlxfjZCqg-1; Tue, 26 Jan 2021 03:09:18 -0500 X-MC-Unique: AS5h8lmwPXOMdAlxfjZCqg-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 604B310509DA; Tue, 26 Jan 2021 08:09:03 +0000 (UTC) Received: from [10.72.12.70] (ovpn-12-70.pek2.redhat.com [10.72.12.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8073A1002382; Tue, 26 Jan 2021 08:08:54 +0000 (UTC) Subject: Re: [RFC v3 08/11] vduse: Introduce VDUSE - vDPA Device in Userspace To: Xie Yongji , mst@redhat.com, stefanha@redhat.com, sgarzare@redhat.com, parav@nvidia.com, bob.liu@oracle.com, hch@infradead.org, rdunlap@infradead.org, willy@infradead.org, viro@zeniv.linux.org.uk, axboe@kernel.dk, bcrl@kvack.org, corbet@lwn.net Cc: 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> From: Jason Wang Message-ID: <1bb3af07-0ec2-109c-d6d1-83d4d1f410c3@redhat.com> Date: Tue, 26 Jan 2021 16:08:52 +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: <20210119050756.600-2-xieyongji@bytedance.com> 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/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. > +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. > + > +- 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. > + > +- 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. > + 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)? > + > +#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. > + 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? > + 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. > + > +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"? > + 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? > + 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. > +}; > + > +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. > + 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. > + /* coupled with smp_wmb() in vduse_dev_msg_complete() */ > + smp_rmb(); Instead of using barriers, I wonder why not simply use msg lock here? > + 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. > + 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? > + > + 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. > + > + 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. > +} > + > +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? > + > + 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? > + > + 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. > + 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? > + 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? > + 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? > + 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? 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. > + 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. > > /* 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. > +}; > + > +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. > + __u32 size; /* the payload size */ Unused. > + 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. > + }; > +}; > + > +struct vduse_dev_response { > + __u32 unique; /* corresponding request id */ Let's use request id. > + __s32 result; /* the result of request */ Let's use macro or enum to define the success and failure value. > + 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? > +}; > + > +#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. Thanks > + > +#endif /* _UAPI_VDUSE_H_ */ 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 5F780C433DB for ; Tue, 26 Jan 2021 08:10:04 +0000 (UTC) Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (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 BF656206FB for ; Tue, 26 Jan 2021 08:10:03 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org BF656206FB 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 fraxinus.osuosl.org (Postfix) with ESMTP id 1DCB785078; Tue, 26 Jan 2021 08:10:03 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id hsW6oU-8Fsv4; Tue, 26 Jan 2021 08:09:57 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by fraxinus.osuosl.org (Postfix) with ESMTP id 9ED8A85008; Tue, 26 Jan 2021 08:09:30 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 7AE86C0FA7; Tue, 26 Jan 2021 08:09:30 +0000 (UTC) Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 7A330C013A for ; Tue, 26 Jan 2021 08:09:29 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 51C6C87006 for ; Tue, 26 Jan 2021 08:09:29 +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 cHeFX3yxny3q for ; Tue, 26 Jan 2021 08:09:25 +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 AA58487005 for ; Tue, 26 Jan 2021 08:09:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1611648563; 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=KvMTNukmS0AnWsFcd0FnVwZKUh81DEUWq7vcN7H5ZxI=; b=ggEaRsjbKXZ5ZiglICg+heylespdy/ugs3D8Mtxv/AndYW2SFJpk1BP+c2RDNaHFJv+MMF 7C0PDHswVX93SDcWh+jVLtlagqadw0LV/Xue2+so8eXMhwgAIS7WFvj8Kq4vkZ5znO7dBh DC38iUui0Cz8qBGtDAERnqsNbwEj56A= 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-159-AS5h8lmwPXOMdAlxfjZCqg-1; Tue, 26 Jan 2021 03:09:18 -0500 X-MC-Unique: AS5h8lmwPXOMdAlxfjZCqg-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 604B310509DA; Tue, 26 Jan 2021 08:09:03 +0000 (UTC) Received: from [10.72.12.70] (ovpn-12-70.pek2.redhat.com [10.72.12.70]) by smtp.corp.redhat.com (Postfix) with ESMTP id 8073A1002382; Tue, 26 Jan 2021 08:08:54 +0000 (UTC) Subject: Re: [RFC v3 08/11] vduse: Introduce VDUSE - vDPA Device in Userspace To: Xie Yongji , mst@redhat.com, stefanha@redhat.com, sgarzare@redhat.com, parav@nvidia.com, bob.liu@oracle.com, hch@infradead.org, rdunlap@infradead.org, willy@infradead.org, viro@zeniv.linux.org.uk, axboe@kernel.dk, bcrl@kvack.org, corbet@lwn.net References: <20210119045920.447-1-xieyongji@bytedance.com> <20210119050756.600-1-xieyongji@bytedance.com> <20210119050756.600-2-xieyongji@bytedance.com> From: Jason Wang Message-ID: <1bb3af07-0ec2-109c-d6d1-83d4d1f410c3@redhat.com> Date: Tue, 26 Jan 2021 16:08:52 +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: <20210119050756.600-2-xieyongji@bytedance.com> Content-Language: en-US X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 Cc: linux-aio@kvack.org, netdev@vger.kernel.org, linux-fsdevel@vger.kernel.org, kvm@vger.kernel.org, virtualization@lists.linux-foundation.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" Ck9uIDIwMjEvMS8xOSDkuIvljYgxOjA3LCBYaWUgWW9uZ2ppIHdyb3RlOgo+IFRoaXMgVkRVU0Ug ZHJpdmVyIGVuYWJsZXMgaW1wbGVtZW50aW5nIHZEUEEgZGV2aWNlcyBpbiB1c2Vyc3BhY2UuCj4g Qm90aCBjb250cm9sIHBhdGggYW5kIGRhdGEgcGF0aCBvZiB2RFBBIGRldmljZXMgd2lsbCBiZSBh YmxlIHRvCj4gYmUgaGFuZGxlZCBpbiB1c2Vyc3BhY2UuCj4KPiBJbiB0aGUgY29udHJvbCBwYXRo LCB0aGUgVkRVU0UgZHJpdmVyIHdpbGwgbWFrZSB1c2Ugb2YgbWVzc2FnZQo+IG1lY2huaXNtIHRv IGZvcndhcmQgdGhlIGNvbmZpZyBvcGVyYXRpb24gZnJvbSB2ZHBhIGJ1cyBkcml2ZXIKPiB0byB1 c2Vyc3BhY2UuIFVzZXJzcGFjZSBjYW4gdXNlIHJlYWQoKS93cml0ZSgpIHRvIHJlY2VpdmUvcmVw bHkKPiB0aG9zZSBjb250cm9sIG1lc3NhZ2VzLgo+Cj4gSW4gdGhlIGRhdGEgcGF0aCwgVkRVU0Vf SU9UTEJfR0VUX0ZEIGlvY3RsIHdpbGwgYmUgdXNlZCB0byBnZXQKPiB0aGUgZmlsZSBkZXNjcmlw dG9ycyByZWZlcnJpbmcgdG8gdkRQQSBkZXZpY2UncyBpb3ZhIHJlZ2lvbnMuIFRoZW4KPiB1c2Vy c3BhY2UgY2FuIHVzZSBtbWFwKCkgdG8gYWNjZXNzIHRob3NlIGlvdmEgcmVnaW9ucy4gQmVzaWRl cywKPiB0aGUgZXZlbnRmZCBtZWNoYW5pc20gaXMgdXNlZCB0byB0cmlnZ2VyIGludGVycnVwdCBj YWxsYmFja3MgYW5kCj4gcmVjZWl2ZSB2aXJ0cXVldWUga2lja3MgaW4gdXNlcnNwYWNlLgo+Cj4g U2lnbmVkLW9mZi1ieTogWGllIFlvbmdqaSA8eGlleW9uZ2ppQGJ5dGVkYW5jZS5jb20+Cj4gLS0t Cj4gICBEb2N1bWVudGF0aW9uL2RyaXZlci1hcGkvdmR1c2UucnN0ICAgICAgICAgICAgICAgICB8 ICAgODUgKysKPiAgIERvY3VtZW50YXRpb24vdXNlcnNwYWNlLWFwaS9pb2N0bC9pb2N0bC1udW1i ZXIucnN0IHwgICAgMSArCj4gICBkcml2ZXJzL3ZkcGEvS2NvbmZpZyAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICB8ICAgIDcgKwo+ICAgZHJpdmVycy92ZHBhL01ha2VmaWxlICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgfCAgICAxICsKPiAgIGRyaXZlcnMvdmRwYS92ZHBhX3VzZXIv TWFrZWZpbGUgICAgICAgICAgICAgICAgICAgIHwgICAgNSArCj4gICBkcml2ZXJzL3ZkcGEvdmRw YV91c2VyL2V2ZW50ZmQuYyAgICAgICAgICAgICAgICAgICB8ICAyMjEgKysrKwo+ICAgZHJpdmVy cy92ZHBhL3ZkcGFfdXNlci9ldmVudGZkLmggICAgICAgICAgICAgICAgICAgfCAgIDQ4ICsKPiAg IGRyaXZlcnMvdmRwYS92ZHBhX3VzZXIvaW92YV9kb21haW4uYyAgICAgICAgICAgICAgIHwgIDQy NiArKysrKysrCj4gICBkcml2ZXJzL3ZkcGEvdmRwYV91c2VyL2lvdmFfZG9tYWluLmggICAgICAg ICAgICAgICB8ICAgNjggKysKPiAgIGRyaXZlcnMvdmRwYS92ZHBhX3VzZXIvdmR1c2UuaCAgICAg ICAgICAgICAgICAgICAgIHwgICA2MiArCj4gICBkcml2ZXJzL3ZkcGEvdmRwYV91c2VyL3ZkdXNl X2Rldi5jICAgICAgICAgICAgICAgICB8IDEyMTcgKysrKysrKysrKysrKysrKysrKysKPiAgIGlu Y2x1ZGUvdWFwaS9saW51eC92ZHBhLmggICAgICAgICAgICAgICAgICAgICAgICAgIHwgICAgMSAr Cj4gICBpbmNsdWRlL3VhcGkvbGludXgvdmR1c2UuaCAgICAgICAgICAgICAgICAgICAgICAgICB8 ICAxMjUgKysKPiAgIDEzIGZpbGVzIGNoYW5nZWQsIDIyNjcgaW5zZXJ0aW9ucygrKQo+ICAgY3Jl YXRlIG1vZGUgMTAwNjQ0IERvY3VtZW50YXRpb24vZHJpdmVyLWFwaS92ZHVzZS5yc3QKPiAgIGNy ZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL3ZkcGEvdmRwYV91c2VyL01ha2VmaWxlCj4gICBjcmVh dGUgbW9kZSAxMDA2NDQgZHJpdmVycy92ZHBhL3ZkcGFfdXNlci9ldmVudGZkLmMKPiAgIGNyZWF0 ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL3ZkcGEvdmRwYV91c2VyL2V2ZW50ZmQuaAo+ICAgY3JlYXRl IG1vZGUgMTAwNjQ0IGRyaXZlcnMvdmRwYS92ZHBhX3VzZXIvaW92YV9kb21haW4uYwo+ICAgY3Jl YXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvdmRwYS92ZHBhX3VzZXIvaW92YV9kb21haW4uaAo+ICAg Y3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvdmRwYS92ZHBhX3VzZXIvdmR1c2UuaAo+ICAgY3Jl YXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvdmRwYS92ZHBhX3VzZXIvdmR1c2VfZGV2LmMKPiAgIGNy ZWF0ZSBtb2RlIDEwMDY0NCBpbmNsdWRlL3VhcGkvbGludXgvdmR1c2UuaAo+Cj4gZGlmZiAtLWdp dCBhL0RvY3VtZW50YXRpb24vZHJpdmVyLWFwaS92ZHVzZS5yc3QgYi9Eb2N1bWVudGF0aW9uL2Ry aXZlci1hcGkvdmR1c2UucnN0Cj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAw MDAwMDAuLjk0MThhN2Y2NjQ2Ygo+IC0tLSAvZGV2L251bGwKPiArKysgYi9Eb2N1bWVudGF0aW9u L2RyaXZlci1hcGkvdmR1c2UucnN0Cj4gQEAgLTAsMCArMSw4NSBAQAo+ICs9PT09PT09PT09PT09 PT09PT09PT09PT09PT09PT09PT09Cj4gK1ZEVVNFIC0gInZEUEEgRGV2aWNlIGluIFVzZXJzcGFj ZSIKPiArPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQo+ICsKPiArdkRQQSAodmly dGlvIGRhdGEgcGF0aCBhY2NlbGVyYXRpb24pIGRldmljZSBpcyBhIGRldmljZSB0aGF0IHVzZXMg YQo+ICtkYXRhcGF0aCB3aGljaCBjb21wbGllcyB3aXRoIHRoZSB2aXJ0aW8gc3BlY2lmaWNhdGlv bnMgd2l0aCB2ZW5kb3IKPiArc3BlY2lmaWMgY29udHJvbCBwYXRoLiB2RFBBIGRldmljZXMgY2Fu IGJlIGJvdGggcGh5c2ljYWxseSBsb2NhdGVkIG9uCj4gK3RoZSBoYXJkd2FyZSBvciBlbXVsYXRl ZCBieSBzb2Z0d2FyZS4gVkRVU0UgaXMgYSBmcmFtZXdvcmsgdGhhdCBtYWtlcyBpdAo+ICtwb3Nz aWJsZSB0byBpbXBsZW1lbnQgc29mdHdhcmUtZW11bGF0ZWQgdkRQQSBkZXZpY2VzIGluIHVzZXJz cGFjZS4KPiArCj4gK0hvdyBWRFVTRSB3b3Jrcwo+ICstLS0tLS0tLS0tLS0KPiArRWFjaCB1c2Vy c3BhY2UgdkRQQSBkZXZpY2UgaXMgY3JlYXRlZCBieSB0aGUgVkRVU0VfQ1JFQVRFX0RFViBpb2N0 bCBvbgo+ICt0aGUgVkRVU0UgY2hhcmFjdGVyIGRldmljZSAoL2Rldi92ZHVzZSkuIFRoZW4gYSBm aWxlIGRlc2NyaXB0b3IgcG9pbnRpbmcKPiArdG8gdGhlIG5ldyByZXNvdXJjZXMgd2lsbCBiZSBy ZXR1cm5lZCwgd2hpY2ggY2FuIGJlIHVzZWQgdG8gaW1wbGVtZW50IHRoZQo+ICt1c2Vyc3BhY2Ug dkRQQSBkZXZpY2UncyBjb250cm9sIHBhdGggYW5kIGRhdGEgcGF0aC4KPiArCj4gK1RvIGltcGxl bWVudCBjb250cm9sIHBhdGgsIHRoZSByZWFkL3dyaXRlIG9wZXJhdGlvbnMgdG8gdGhlIGZpbGUg ZGVzY3JpcHRvcgo+ICt3aWxsIGJlIHVzZWQgdG8gcmVjZWl2ZS9yZXBseSB0aGUgY29udHJvbCBt ZXNzYWdlcyBmcm9tL3RvIFZEVVNFIGRyaXZlci4KCgpJdCdzIGJldHRlciB0byBkb2N1bWVudCB0 aGUgcHJvdG9jb2wgaGVyZS4gRS5nIHRoZSBpZGVudGlmaWVyIHN0dWZmcy4KCgo+ICtUaG9zZSBj b250cm9sIG1lc3NhZ2VzIGFyZSBtb3N0bHkgYmFzZWQgb24gdGhlIHZkcGFfY29uZmlnX29wcyB3 aGljaCBkZWZpbmVzCj4gK2EgdW5pZmllZCBpbnRlcmZhY2UgdG8gY29udHJvbCBkaWZmZXJlbnQg dHlwZXMgb2YgdkRQQSBkZXZpY2UuCj4gKwo+ICtUaGUgZm9sbG93aW5nIHR5cGVzIG9mIG1lc3Nh Z2VzIGFyZSBwcm92aWRlZCBieSB0aGUgVkRVU0UgZnJhbWV3b3JrIG5vdzoKPiArCj4gKy0gVkRV U0VfU0VUX1ZRX0FERFI6IFNldCB0aGUgYWRkcmVzc2VzIG9mIHRoZSBkaWZmZXJlbnQgYXNwZWN0 cyBvZiB2aXJ0cXVldWUuCgoKIlNldCB0aGUgdnJpbmcgYWRkcmVzcyBvZiBhIHZpcnRxdWV1ZSIg bWlnaHQgYmUgYmV0dGVyIGhlcmUuCgoKPiArCj4gKy0gVkRVU0VfU0VUX1ZRX05VTTogU2V0IHRo ZSBzaXplIG9mIHZpcnRxdWV1ZQo+ICsKPiArLSBWRFVTRV9TRVRfVlFfUkVBRFk6IFNldCByZWFk eSBzdGF0dXMgb2YgdmlydHF1ZXVlCj4gKwo+ICstIFZEVVNFX0dFVF9WUV9SRUFEWTogR2V0IHJl YWR5IHN0YXR1cyBvZiB2aXJ0cXVldWUKPiArCj4gKy0gVkRVU0VfU0VUX1ZRX1NUQVRFOiBTZXQg dGhlIHN0YXRlIChsYXN0X2F2YWlsX2lkeCkgZm9yIHZpcnRxdWV1ZQo+ICsKPiArLSBWRFVTRV9H RVRfVlFfU1RBVEU6IEdldCB0aGUgc3RhdGUgKGxhc3RfYXZhaWxfaWR4KSBmb3IgdmlydHF1ZXVl CgoKSXQncyBiZXR0ZXIgbm90IHRvIG1lbnRpb24gbGF5b3V0IHNwZWNpZmljIHN0dWZmcyBoZXJl IChsYXN0X2F2YWlsX2lkeCkuIApDb25zaWRlciB3ZSBzaG91bGQgc3VwcG9ydCBwYWNrZWQgdmly dHF1ZXVlIGluIHRoZSBmdXR1cmUuCgoKPiArCj4gKy0gVkRVU0VfU0VUX0ZFQVRVUkVTOiBTZXQg dmlydGlvIGZlYXR1cmVzIHN1cHBvcnRlZCBieSB0aGUgZHJpdmVyCj4gKwo+ICstIFZEVVNFX0dF VF9GRUFUVVJFUzogR2V0IHZpcnRpbyBmZWF0dXJlcyBzdXBwb3J0ZWQgYnkgdGhlIGRldmljZQo+ ICsKPiArLSBWRFVTRV9TRVRfU1RBVFVTOiBTZXQgdGhlIGRldmljZSBzdGF0dXMKPiArCj4gKy0g VkRVU0VfR0VUX1NUQVRVUzogR2V0IHRoZSBkZXZpY2Ugc3RhdHVzCj4gKwo+ICstIFZEVVNFX1NF VF9DT05GSUc6IFdyaXRlIHRvIGRldmljZSBzcGVjaWZpYyBjb25maWd1cmF0aW9uIHNwYWNlCj4g Kwo+ICstIFZEVVNFX0dFVF9DT05GSUc6IFJlYWQgZnJvbSBkZXZpY2Ugc3BlY2lmaWMgY29uZmln dXJhdGlvbiBzcGFjZQo+ICsKPiArLSBWRFVTRV9VUERBVEVfSU9UTEI6IE5vdGlmeSB1c2Vyc3Bh Y2UgdG8gdXBkYXRlIHRoZSBtZW1vcnkgbWFwcGluZyBpbiBkZXZpY2UgSU9UTEIKPiArCj4gK1Bs ZWFzZSBzZWUgaW5jbHVkZS9saW51eC92ZHBhLmggZm9yIGRldGFpbHMuCj4gKwo+ICtJbiB0aGUg ZGF0YSBwYXRoLCB2RFBBIGRldmljZSdzIGlvdmEgcmVnaW9ucyB3aWxsIGJlIG1hcHBlZCBpbnRv IHVzZXJzcGFjZSB3aXRoCj4gK3RoZSBoZWxwIG9mIFZEVVNFX0lPVExCX0dFVF9GRCBpb2N0bCBv biB0aGUgdXNlcnNwYWNlIHZEUEEgZGV2aWNlIGZkOgo+ICsKPiArLSBWRFVTRV9JT1RMQl9HRVRf RkQ6IGdldCB0aGUgZmlsZSBkZXNjcmlwdG9yIHRvIGlvdmEgcmVnaW9uLiBVc2Vyc3BhY2UgY2Fu Cj4gKyAgYWNjZXNzIHRoaXMgaW92YSByZWdpb24gYnkgcGFzc2luZyB0aGUgZmQgdG8gbW1hcCgy KS4KPiArCj4gK0Jlc2lkZXMsIHRoZSBldmVudGZkIG1lY2hhbmlzbSBpcyB1c2VkIHRvIHRyaWdn ZXIgaW50ZXJydXB0IGNhbGxiYWNrcyBhbmQKPiArcmVjZWl2ZSB2aXJ0cXVldWUga2lja3MgaW4g dXNlcnNwYWNlLiBUaGUgZm9sbG93aW5nIGlvY3RscyBvbiB0aGUgdXNlcnNwYWNlCj4gK3ZEUEEg ZGV2aWNlIGZkIGFyZSBwcm92aWRlZCB0byBzdXBwb3J0IHRoYXQ6Cj4gKwo+ICstIFZEVVNFX1ZR X1NFVFVQX0tJQ0tGRDogc2V0IHRoZSBraWNrZmQgZm9yIHZpcnRxdWV1ZSwgdGhpcyBldmVudGZk IGlzIHVzZWQKPiArICBieSBWRFVTRSBkcml2ZXIgdG8gbm90aWZ5IHVzZXJzcGFjZSB0byBjb25z dW1lIHRoZSB2cmluZy4KPiArCj4gKy0gVkRVU0VfVlFfU0VUVVBfSVJRRkQ6IHNldCB0aGUgaXJx ZmQgZm9yIHZpcnRxdWV1ZSwgdGhpcyBldmVudGZkIGlzIHVzZWQKPiArICBieSB1c2Vyc3BhY2Ug dG8gbm90aWZ5IFZEVVNFIGRyaXZlciB0byB0cmlnZ2VyIGludGVycnVwdCBjYWxsYmFja3MuCj4g Kwo+ICtNTVUtYmFzZWQgSU9NTVUgRHJpdmVyCj4gKy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KPiAr SW4gdmlydGlvLXZkcGEgY2FzZSwgVkRVU0UgZnJhbWV3b3JrIGltcGxlbWVudHMgYSBNTVUtYmFz ZWQgb24tY2hpcCBJT01NVQo+ICtkcml2ZXIgdG8gc3VwcG9ydCBtYXBwaW5nIHRoZSBrZXJuZWwg ZG1hIGJ1ZmZlciBpbnRvIHRoZSB1c2Vyc3BhY2UgaW92YQo+ICtyZWdpb24gZHluYW1pY2FsbHku Cj4gKwo+ICtUaGUgYmFzaWMgaWRlYSBiZWhpbmQgdGhpcyBkcml2ZXIgaXMgdHJlYXRpbmcgTU1V IChWQS0+UEEpIGFzIElPTU1VIChJT1ZBLT5QQSkuCj4gK1RoZSBkcml2ZXIgd2lsbCBzZXQgdXAg TU1VIG1hcHBpbmcgaW5zdGVhZCBvZiBJT01NVSBtYXBwaW5nIGZvciB0aGUgRE1BIHRyYW5zZmVy Cj4gK3NvIHRoYXQgdGhlIHVzZXJzcGFjZSBwcm9jZXNzIGlzIGFibGUgdG8gdXNlIGl0cyB2aXJ0 dWFsIGFkZHJlc3MgdG8gYWNjZXNzCj4gK3RoZSBkbWEgYnVmZmVyIGluIGtlcm5lbC4KPiArCj4g K0FuZCB0byBhdm9pZCBzZWN1cml0eSBpc3N1ZSwgYSBib3VuY2UtYnVmZmVyaW5nIG1lY2hhbmlz bSBpcyBpbnRyb2R1Y2VkIHRvCj4gK3ByZXZlbnQgdXNlcnNwYWNlIGFjY2Vzc2luZyB0aGUgb3Jp Z2luYWwgYnVmZmVyIGRpcmVjdGx5IHdoaWNoIG1heSBjb250YWluIG90aGVyCj4gK2tlcm5lbCBk YXRhLiBEdXJpbmcgdGhlIG1hcHBpbmcsIHVubWFwcGluZywgdGhlIGRyaXZlciB3aWxsIGNvcHkg dGhlIGRhdGEgZnJvbQo+ICt0aGUgb3JpZ2luYWwgYnVmZmVyIHRvIHRoZSBib3VuY2UgYnVmZmVy IGFuZCBiYWNrLCBkZXBlbmRpbmcgb24gdGhlIGRpcmVjdGlvbiBvZgo+ICt0aGUgdHJhbnNmZXIu IEFuZCB0aGUgYm91bmNlLWJ1ZmZlciBhZGRyZXNzZXMgd2lsbCBiZSBtYXBwZWQgaW50byB0aGUg dXNlciBhZGRyZXNzCj4gK3NwYWNlIGluc3RlYWQgb2YgdGhlIG9yaWdpbmFsIG9uZS4KPiBkaWZm IC0tZ2l0IGEvRG9jdW1lbnRhdGlvbi91c2Vyc3BhY2UtYXBpL2lvY3RsL2lvY3RsLW51bWJlci5y c3QgYi9Eb2N1bWVudGF0aW9uL3VzZXJzcGFjZS1hcGkvaW9jdGwvaW9jdGwtbnVtYmVyLnJzdAo+ IGluZGV4IGE0Yzc1YTI4YzgzOS4uNzE3MjJlNmY4ZjIzIDEwMDY0NAo+IC0tLSBhL0RvY3VtZW50 YXRpb24vdXNlcnNwYWNlLWFwaS9pb2N0bC9pb2N0bC1udW1iZXIucnN0Cj4gKysrIGIvRG9jdW1l bnRhdGlvbi91c2Vyc3BhY2UtYXBpL2lvY3RsL2lvY3RsLW51bWJlci5yc3QKPiBAQCAtMzAwLDYg KzMwMCw3IEBAIENvZGUgIFNlcSMgICAgSW5jbHVkZSBGaWxlICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIENvbW1lbnRzCj4gICAneicgICAxMC00RiAgZHJpdmVycy9z MzkwL2NyeXB0by96Y3J5cHRfYXBpLmggICAgICAgICAgICAgICAgICAgICAgICBjb25mbGljdCEK PiAgICd8JyAgIDAwLTdGICBsaW51eC9tZWRpYS5oCj4gICAweDgwICAwMC0xRiAgbGludXgvZmIu aAo+ICsweDgxICAwMC0xRiAgbGludXgvdmR1c2UuaAo+ICAgMHg4OSAgMDAtMDYgIGFyY2gveDg2 L2luY2x1ZGUvYXNtL3NvY2tpb3MuaAo+ICAgMHg4OSAgMEItREYgIGxpbnV4L3NvY2tpb3MuaAo+ ICAgMHg4OSAgRTAtRUYgIGxpbnV4L3NvY2tpb3MuaCAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgU0lPQ1BST1RPUFJJVkFURSByYW5nZQo+IGRpZmYgLS1naXQgYS9kcml2 ZXJzL3ZkcGEvS2NvbmZpZyBiL2RyaXZlcnMvdmRwYS9LY29uZmlnCj4gaW5kZXggNGJlN2JlMzli ZTI2Li42NjczNTQzMDliZjQgMTAwNjQ0Cj4gLS0tIGEvZHJpdmVycy92ZHBhL0tjb25maWcKPiAr KysgYi9kcml2ZXJzL3ZkcGEvS2NvbmZpZwo+IEBAIC0yMSw2ICsyMSwxMyBAQCBjb25maWcgVkRQ QV9TSU0KPiAgIAkgIHRvIFJYLiBUaGlzIGRldmljZSBpcyB1c2VkIGZvciB0ZXN0aW5nLCBwcm90 b3R5cGluZyBhbmQKPiAgIAkgIGRldmVsb3BtZW50IG9mIHZEUEEuCj4gICAKPiArY29uZmlnIFZE UEFfVVNFUgo+ICsJdHJpc3RhdGUgIlZEVVNFICh2RFBBIERldmljZSBpbiBVc2Vyc3BhY2UpIHN1 cHBvcnQiCj4gKwlkZXBlbmRzIG9uIEVWRU5URkQgJiYgTU1VICYmIEhBU19ETUEKCgpOZWVkIHNl bGVjdCBWSE9TVF9JT1RMQi4KCgo+ICsJaGVscAo+ICsJICBXaXRoIFZEVVNFIGl0IGlzIHBvc3Np YmxlIHRvIGVtdWxhdGUgYSB2RFBBIERldmljZQo+ICsJICBpbiBhIHVzZXJzcGFjZSBwcm9ncmFt Lgo+ICsKPiAgIGNvbmZpZyBJRkNWRgo+ICAgCXRyaXN0YXRlICJJbnRlbCBJRkMgVkYgdkRQQSBk cml2ZXIiCj4gICAJZGVwZW5kcyBvbiBQQ0lfTVNJCj4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvdmRw YS9NYWtlZmlsZSBiL2RyaXZlcnMvdmRwYS9NYWtlZmlsZQo+IGluZGV4IGQxNjBlOWI2M2E2Ni4u NjZlOTc3NzhhZDAzIDEwMDY0NAo+IC0tLSBhL2RyaXZlcnMvdmRwYS9NYWtlZmlsZQo+ICsrKyBi L2RyaXZlcnMvdmRwYS9NYWtlZmlsZQo+IEBAIC0xLDUgKzEsNiBAQAo+ICAgIyBTUERYLUxpY2Vu c2UtSWRlbnRpZmllcjogR1BMLTIuMAo+ICAgb2JqLSQoQ09ORklHX1ZEUEEpICs9IHZkcGEubwo+ ICAgb2JqLSQoQ09ORklHX1ZEUEFfU0lNKSArPSB2ZHBhX3NpbS8KPiArb2JqLSQoQ09ORklHX1ZE UEFfVVNFUikgKz0gdmRwYV91c2VyLwo+ICAgb2JqLSQoQ09ORklHX0lGQ1ZGKSAgICArPSBpZmN2 Zi8KPiAgIG9iai0kKENPTkZJR19NTFg1X1ZEUEEpICs9IG1seDUvCj4gZGlmZiAtLWdpdCBhL2Ry aXZlcnMvdmRwYS92ZHBhX3VzZXIvTWFrZWZpbGUgYi9kcml2ZXJzL3ZkcGEvdmRwYV91c2VyL01h a2VmaWxlCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAwMDAuLmI3NjQ1 ZTM2OTkyYgo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL3ZkcGEvdmRwYV91c2VyL01h a2VmaWxlCj4gQEAgLTAsMCArMSw1IEBACj4gKyMgU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQ TC0yLjAKPiArCj4gK3ZkdXNlLXkgOj0gdmR1c2VfZGV2Lm8gaW92YV9kb21haW4ubyBldmVudGZk Lm8KPiArCj4gK29iai0kKENPTkZJR19WRFBBX1VTRVIpICs9IHZkdXNlLm8KPiBkaWZmIC0tZ2l0 IGEvZHJpdmVycy92ZHBhL3ZkcGFfdXNlci9ldmVudGZkLmMgYi9kcml2ZXJzL3ZkcGEvdmRwYV91 c2VyL2V2ZW50ZmQuYwo+IG5ldyBmaWxlIG1vZGUgMTAwNjQ0Cj4gaW5kZXggMDAwMDAwMDAwMDAw Li5kYmZmZGRiMDg5MDgKPiAtLS0gL2Rldi9udWxsCj4gKysrIGIvZHJpdmVycy92ZHBhL3ZkcGFf dXNlci9ldmVudGZkLmMKPiBAQCAtMCwwICsxLDIyMSBAQAo+ICsvLyBTUERYLUxpY2Vuc2UtSWRl bnRpZmllcjogR1BMLTIuMC1vbmx5Cj4gKy8qCj4gKyAqIEV2ZW50ZmQgc3VwcG9ydCBmb3IgVkRV U0UKPiArICoKPiArICogQ29weXJpZ2h0IChDKSAyMDIwIEJ5dGVkYW5jZSBJbmMuIGFuZC9vciBp dHMgYWZmaWxpYXRlcy4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KPiArICoKPiArICogQXV0aG9yOiBY aWUgWW9uZ2ppIDx4aWV5b25namlAYnl0ZWRhbmNlLmNvbT4KPiArICoKPiArICovCj4gKwo+ICsj aW5jbHVkZSA8bGludXgvZXZlbnRmZC5oPgo+ICsjaW5jbHVkZSA8bGludXgvcG9sbC5oPgo+ICsj aW5jbHVkZSA8bGludXgvd2FpdC5oPgo+ICsjaW5jbHVkZSA8bGludXgvc2xhYi5oPgo+ICsjaW5j bHVkZSA8bGludXgvZmlsZS5oPgo+ICsjaW5jbHVkZSA8dWFwaS9saW51eC92ZHVzZS5oPgo+ICsK PiArI2luY2x1ZGUgImV2ZW50ZmQuaCIKPiArCj4gK3N0YXRpYyBzdHJ1Y3Qgd29ya3F1ZXVlX3N0 cnVjdCAqdmR1c2VfaXJxZmRfY2xlYW51cF93cTsKPiArCj4gK3N0YXRpYyB2b2lkIHZkdXNlX3Zp cnFmZF9zaHV0ZG93bihzdHJ1Y3Qgd29ya19zdHJ1Y3QgKndvcmspCj4gK3sKPiArCXU2NCBjbnQ7 Cj4gKwlzdHJ1Y3QgdmR1c2VfdmlycWZkICp2aXJxZmQgPSBjb250YWluZXJfb2Yod29yaywKPiAr CQkJCQlzdHJ1Y3QgdmR1c2VfdmlycWZkLCBzaHV0ZG93bik7Cj4gKwo+ICsJZXZlbnRmZF9jdHhf cmVtb3ZlX3dhaXRfcXVldWUodmlycWZkLT5jdHgsICZ2aXJxZmQtPndhaXQsICZjbnQpOwo+ICsJ Zmx1c2hfd29yaygmdmlycWZkLT5pbmplY3QpOwo+ICsJZXZlbnRmZF9jdHhfcHV0KHZpcnFmZC0+ Y3R4KTsKPiArCWtmcmVlKHZpcnFmZCk7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHZkdXNlX3Zp cnFmZF9pbmplY3Qoc3RydWN0IHdvcmtfc3RydWN0ICp3b3JrKQo+ICt7Cj4gKwlzdHJ1Y3QgdmR1 c2VfdmlycWZkICp2aXJxZmQgPSBjb250YWluZXJfb2Yod29yaywKPiArCQkJCQlzdHJ1Y3QgdmR1 c2VfdmlycWZkLCBpbmplY3QpOwo+ICsJc3RydWN0IHZkdXNlX3ZpcnRxdWV1ZSAqdnEgPSB2aXJx ZmQtPnZxOwo+ICsKPiArCXNwaW5fbG9ja19pcnEoJnZxLT5pcnFfbG9jayk7Cj4gKwlpZiAodnEt PnJlYWR5ICYmIHZxLT5jYikKPiArCQl2cS0+Y2IodnEtPnByaXZhdGUpOwo+ICsJc3Bpbl91bmxv Y2tfaXJxKCZ2cS0+aXJxX2xvY2spOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2aXJxZmRfZGVh Y3RpdmF0ZShzdHJ1Y3QgdmR1c2VfdmlycWZkICp2aXJxZmQpCj4gK3sKPiArCXF1ZXVlX3dvcmso dmR1c2VfaXJxZmRfY2xlYW51cF93cSwgJnZpcnFmZC0+c2h1dGRvd24pOwo+ICt9Cj4gKwo+ICtz dGF0aWMgaW50IHZkdXNlX3ZpcnFmZF93YWtldXAod2FpdF9xdWV1ZV9lbnRyeV90ICp3YWl0LCB1 bnNpZ25lZCBpbnQgbW9kZSwKPiArCQkJCWludCBzeW5jLCB2b2lkICprZXkpCj4gK3sKPiArCXN0 cnVjdCB2ZHVzZV92aXJxZmQgKnZpcnFmZCA9IGNvbnRhaW5lcl9vZih3YWl0LCBzdHJ1Y3QgdmR1 c2VfdmlycWZkLCB3YWl0KTsKPiArCXN0cnVjdCB2ZHVzZV92aXJ0cXVldWUgKnZxID0gdmlycWZk LT52cTsKPiArCj4gKwlfX3BvbGxfdCBmbGFncyA9IGtleV90b19wb2xsKGtleSk7Cj4gKwo+ICsJ aWYgKGZsYWdzICYgRVBPTExJTikKPiArCQlzY2hlZHVsZV93b3JrKCZ2aXJxZmQtPmluamVjdCk7 Cj4gKwo+ICsJaWYgKGZsYWdzICYgRVBPTExIVVApIHsKPiArCQlzcGluX2xvY2soJnZxLT5pcnFf bG9jayk7Cj4gKwkJaWYgKHZxLT52aXJxZmQgPT0gdmlycWZkKSB7Cj4gKwkJCXZxLT52aXJxZmQg PSBOVUxMOwo+ICsJCQl2aXJxZmRfZGVhY3RpdmF0ZSh2aXJxZmQpOwo+ICsJCX0KPiArCQlzcGlu X3VubG9jaygmdnEtPmlycV9sb2NrKTsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsK PiArc3RhdGljIHZvaWQgdmR1c2VfdmlycWZkX3B0YWJsZV9xdWV1ZV9wcm9jKHN0cnVjdCBmaWxl ICpmaWxlLAo+ICsJCQl3YWl0X3F1ZXVlX2hlYWRfdCAqd3FoLCBwb2xsX3RhYmxlICpwdCkKPiAr ewo+ICsJc3RydWN0IHZkdXNlX3ZpcnFmZCAqdmlycWZkID0gY29udGFpbmVyX29mKHB0LCBzdHJ1 Y3QgdmR1c2VfdmlycWZkLCBwdCk7Cj4gKwo+ICsJYWRkX3dhaXRfcXVldWUod3FoLCAmdmlycWZk LT53YWl0KTsKPiArfQo+ICsKPiAraW50IHZkdXNlX3ZpcnFmZF9zZXR1cChzdHJ1Y3QgdmR1c2Vf ZGV2ICpkZXYsCj4gKwkJCXN0cnVjdCB2ZHVzZV92cV9ldmVudGZkICpldmVudGZkKQo+ICt7Cj4g KwlzdHJ1Y3QgdmR1c2VfdmlycWZkICp2aXJxZmQ7Cj4gKwlzdHJ1Y3QgZmQgaXJxZmQ7Cj4gKwlz dHJ1Y3QgZXZlbnRmZF9jdHggKmN0eDsKPiArCXN0cnVjdCB2ZHVzZV92aXJ0cXVldWUgKnZxOwo+ ICsJX19wb2xsX3QgZXZlbnRzOwo+ICsJaW50IHJldDsKPiArCj4gKwlpZiAoZXZlbnRmZC0+aW5k ZXggPj0gZGV2LT52cV9udW0pCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJdnEgPSAmZGV2 LT52cXNbZXZlbnRmZC0+aW5kZXhdOwo+ICsJdmlycWZkID0ga3phbGxvYyhzaXplb2YoKnZpcnFm ZCksIEdGUF9LRVJORUwpOwo+ICsJaWYgKCF2aXJxZmQpCj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4g Kwo+ICsJSU5JVF9XT1JLKCZ2aXJxZmQtPnNodXRkb3duLCB2ZHVzZV92aXJxZmRfc2h1dGRvd24p Owo+ICsJSU5JVF9XT1JLKCZ2aXJxZmQtPmluamVjdCwgdmR1c2VfdmlycWZkX2luamVjdCk7Cj4g Kwo+ICsJcmV0ID0gLUVCQURGOwo+ICsJaXJxZmQgPSBmZGdldChldmVudGZkLT5mZCk7Cj4gKwlp ZiAoIWlycWZkLmZpbGUpCj4gKwkJZ290byBlcnJfZmQ7Cj4gKwo+ICsJY3R4ID0gZXZlbnRmZF9j dHhfZmlsZWdldChpcnFmZC5maWxlKTsKPiArCWlmIChJU19FUlIoY3R4KSkgewo+ICsJCXJldCA9 IFBUUl9FUlIoY3R4KTsKPiArCQlnb3RvIGVycl9jdHg7Cj4gKwl9Cj4gKwo+ICsJdmlycWZkLT52 cSA9IHZxOwo+ICsJdmlycWZkLT5jdHggPSBjdHg7Cj4gKwlzcGluX2xvY2soJnZxLT5pcnFfbG9j ayk7Cj4gKwlpZiAodnEtPnZpcnFmZCkKPiArCQl2aXJxZmRfZGVhY3RpdmF0ZSh2aXJxZmQpOwo+ ICsJdnEtPnZpcnFmZCA9IHZpcnFmZDsKPiArCXNwaW5fdW5sb2NrKCZ2cS0+aXJxX2xvY2spOwo+ ICsKPiArCWluaXRfd2FpdHF1ZXVlX2Z1bmNfZW50cnkoJnZpcnFmZC0+d2FpdCwgdmR1c2Vfdmly cWZkX3dha2V1cCk7Cj4gKwlpbml0X3BvbGxfZnVuY3B0cigmdmlycWZkLT5wdCwgdmR1c2Vfdmly cWZkX3B0YWJsZV9xdWV1ZV9wcm9jKTsKPiArCj4gKwlldmVudHMgPSB2ZnNfcG9sbChpcnFmZC5m aWxlLCAmdmlycWZkLT5wdCk7Cj4gKwo+ICsJLyoKPiArCSAqIENoZWNrIGlmIHRoZXJlIHdhcyBh biBldmVudCBhbHJlYWR5IHBlbmRpbmcgb24gdGhlIGV2ZW50ZmQKPiArCSAqIGJlZm9yZSB3ZSBy ZWdpc3RlcmVkIGFuZCB0cmlnZ2VyIGl0IGFzIGlmIHdlIGRpZG4ndCBtaXNzIGl0Lgo+ICsJICov Cj4gKwlpZiAoZXZlbnRzICYgRVBPTExJTikKPiArCQlzY2hlZHVsZV93b3JrKCZ2aXJxZmQtPmlu amVjdCk7Cj4gKwo+ICsJZmRwdXQoaXJxZmQpOwo+ICsKPiArCXJldHVybiAwOwo+ICtlcnJfY3R4 Ogo+ICsJZmRwdXQoaXJxZmQpOwo+ICtlcnJfZmQ6Cj4gKwlrZnJlZSh2aXJxZmQpOwo+ICsJcmV0 dXJuIHJldDsKPiArfQo+ICsKPiArdm9pZCB2ZHVzZV92aXJxZmRfcmVsZWFzZShzdHJ1Y3QgdmR1 c2VfZGV2ICpkZXYpCj4gK3sKPiArCWludCBpOwo+ICsKPiArCWZvciAoaSA9IDA7IGkgPCBkZXYt PnZxX251bTsgaSsrKSB7Cj4gKwkJc3RydWN0IHZkdXNlX3ZpcnRxdWV1ZSAqdnEgPSAmZGV2LT52 cXNbaV07Cj4gKwo+ICsJCXNwaW5fbG9jaygmdnEtPmlycV9sb2NrKTsKPiArCQlpZiAodnEtPnZp cnFmZCkgewo+ICsJCQl2aXJxZmRfZGVhY3RpdmF0ZSh2cS0+dmlycWZkKTsKPiArCQkJdnEtPnZp cnFmZCA9IE5VTEw7Cj4gKwkJfQo+ICsJCXNwaW5fdW5sb2NrKCZ2cS0+aXJxX2xvY2spOwo+ICsJ fQo+ICsJZmx1c2hfd29ya3F1ZXVlKHZkdXNlX2lycWZkX2NsZWFudXBfd3EpOwo+ICt9Cj4gKwo+ ICtpbnQgdmR1c2VfdmlycWZkX2luaXQodm9pZCkKPiArewo+ICsJdmR1c2VfaXJxZmRfY2xlYW51 cF93cSA9IGFsbG9jX3dvcmtxdWV1ZSgidmR1c2UtaXJxZmQtY2xlYW51cCIsCj4gKwkJCQkJCVdR X1VOQk9VTkQsIDApOwo+ICsJaWYgKCF2ZHVzZV9pcnFmZF9jbGVhbnVwX3dxKQo+ICsJCXJldHVy biAtRU5PTUVNOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICt2b2lkIHZkdXNlX3ZpcnFm ZF9leGl0KHZvaWQpCj4gK3sKPiArCWRlc3Ryb3lfd29ya3F1ZXVlKHZkdXNlX2lycWZkX2NsZWFu dXBfd3EpOwo+ICt9Cj4gKwo+ICt2b2lkIHZkdXNlX3ZxX2tpY2soc3RydWN0IHZkdXNlX3ZpcnRx dWV1ZSAqdnEpCj4gK3sKPiArCXNwaW5fbG9jaygmdnEtPmtpY2tfbG9jayk7Cj4gKwlpZiAodnEt PnJlYWR5ICYmIHZxLT5raWNrZmQpCj4gKwkJZXZlbnRmZF9zaWduYWwodnEtPmtpY2tmZCwgMSk7 Cj4gKwlzcGluX3VubG9jaygmdnEtPmtpY2tfbG9jayk7Cj4gK30KPiArCj4gK2ludCB2ZHVzZV9r aWNrZmRfc2V0dXAoc3RydWN0IHZkdXNlX2RldiAqZGV2LAo+ICsJCQlzdHJ1Y3QgdmR1c2VfdnFf ZXZlbnRmZCAqZXZlbnRmZCkKPiArewo+ICsJc3RydWN0IGV2ZW50ZmRfY3R4ICpjdHg7Cj4gKwlz dHJ1Y3QgdmR1c2VfdmlydHF1ZXVlICp2cTsKPiArCj4gKwlpZiAoZXZlbnRmZC0+aW5kZXggPj0g ZGV2LT52cV9udW0pCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJdnEgPSAmZGV2LT52cXNb ZXZlbnRmZC0+aW5kZXhdOwo+ICsJY3R4ID0gZXZlbnRmZF9jdHhfZmRnZXQoZXZlbnRmZC0+ZmQp Owo+ICsJaWYgKElTX0VSUihjdHgpKQo+ICsJCXJldHVybiBQVFJfRVJSKGN0eCk7Cj4gKwo+ICsJ c3Bpbl9sb2NrKCZ2cS0+a2lja19sb2NrKTsKPiArCWlmICh2cS0+a2lja2ZkKQo+ICsJCWV2ZW50 ZmRfY3R4X3B1dCh2cS0+a2lja2ZkKTsKPiArCXZxLT5raWNrZmQgPSBjdHg7Cj4gKwlzcGluX3Vu bG9jaygmdnEtPmtpY2tfbG9jayk7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3ZvaWQg dmR1c2Vfa2lja2ZkX3JlbGVhc2Uoc3RydWN0IHZkdXNlX2RldiAqZGV2KQo+ICt7Cj4gKwlpbnQg aTsKPiArCj4gKwlmb3IgKGkgPSAwOyBpIDwgZGV2LT52cV9udW07IGkrKykgewo+ICsJCXN0cnVj dCB2ZHVzZV92aXJ0cXVldWUgKnZxID0gJmRldi0+dnFzW2ldOwo+ICsKPiArCQlzcGluX2xvY2so JnZxLT5raWNrX2xvY2spOwo+ICsJCWlmICh2cS0+a2lja2ZkKSB7Cj4gKwkJCWV2ZW50ZmRfY3R4 X3B1dCh2cS0+a2lja2ZkKTsKPiArCQkJdnEtPmtpY2tmZCA9IE5VTEw7Cj4gKwkJfQo+ICsJCXNw aW5fdW5sb2NrKCZ2cS0+a2lja19sb2NrKTsKPiArCX0KPiArfQo+IGRpZmYgLS1naXQgYS9kcml2 ZXJzL3ZkcGEvdmRwYV91c2VyL2V2ZW50ZmQuaCBiL2RyaXZlcnMvdmRwYS92ZHBhX3VzZXIvZXZl bnRmZC5oCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAwMDAuLjE0MjY5 ZmYyN2Y0Nwo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL3ZkcGEvdmRwYV91c2VyL2V2 ZW50ZmQuaAo+IEBAIC0wLDAgKzEsNDggQEAKPiArLyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6 IEdQTC0yLjAtb25seSAqLwo+ICsvKgo+ICsgKiBFdmVudGZkIHN1cHBvcnQgZm9yIFZEVVNFCj4g KyAqCj4gKyAqIENvcHlyaWdodCAoQykgMjAyMCBCeXRlZGFuY2UgSW5jLiBhbmQvb3IgaXRzIGFm ZmlsaWF0ZXMuIEFsbCByaWdodHMgcmVzZXJ2ZWQuCj4gKyAqCj4gKyAqIEF1dGhvcjogWGllIFlv bmdqaSA8eGlleW9uZ2ppQGJ5dGVkYW5jZS5jb20+Cj4gKyAqCj4gKyAqLwo+ICsKPiArI2lmbmRl ZiBfVkRVU0VfRVZFTlRGRF9ICj4gKyNkZWZpbmUgX1ZEVVNFX0VWRU5URkRfSAo+ICsKPiArI2lu Y2x1ZGUgPGxpbnV4L2V2ZW50ZmQuaD4KPiArI2luY2x1ZGUgPGxpbnV4L3BvbGwuaD4KPiArI2lu Y2x1ZGUgPGxpbnV4L3dhaXQuaD4KPiArI2luY2x1ZGUgPHVhcGkvbGludXgvdmR1c2UuaD4KPiAr Cj4gKyNpbmNsdWRlICJ2ZHVzZS5oIgo+ICsKPiArc3RydWN0IHZkdXNlX2RldjsKPiArCj4gK3N0 cnVjdCB2ZHVzZV92aXJxZmQgewo+ICsJc3RydWN0IGV2ZW50ZmRfY3R4ICpjdHg7Cj4gKwlzdHJ1 Y3QgdmR1c2VfdmlydHF1ZXVlICp2cTsKPiArCXN0cnVjdCB3b3JrX3N0cnVjdCBpbmplY3Q7Cj4g KwlzdHJ1Y3Qgd29ya19zdHJ1Y3Qgc2h1dGRvd247Cj4gKwl3YWl0X3F1ZXVlX2VudHJ5X3Qgd2Fp dDsKPiArCXBvbGxfdGFibGUgcHQ7Cj4gK307Cj4gKwo+ICtpbnQgdmR1c2VfdmlycWZkX3NldHVw KHN0cnVjdCB2ZHVzZV9kZXYgKmRldiwKPiArCQkJc3RydWN0IHZkdXNlX3ZxX2V2ZW50ZmQgKmV2 ZW50ZmQpOwo+ICsKPiArdm9pZCB2ZHVzZV92aXJxZmRfcmVsZWFzZShzdHJ1Y3QgdmR1c2VfZGV2 ICpkZXYpOwo+ICsKPiAraW50IHZkdXNlX3ZpcnFmZF9pbml0KHZvaWQpOwo+ICsKPiArdm9pZCB2 ZHVzZV92aXJxZmRfZXhpdCh2b2lkKTsKPiArCj4gK3ZvaWQgdmR1c2VfdnFfa2ljayhzdHJ1Y3Qg dmR1c2VfdmlydHF1ZXVlICp2cSk7Cj4gKwo+ICtpbnQgdmR1c2Vfa2lja2ZkX3NldHVwKHN0cnVj dCB2ZHVzZV9kZXYgKmRldiwKPiArCQkJc3RydWN0IHZkdXNlX3ZxX2V2ZW50ZmQgKmV2ZW50ZmQp Owo+ICsKPiArdm9pZCB2ZHVzZV9raWNrZmRfcmVsZWFzZShzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYp Owo+ICsKPiArI2VuZGlmIC8qIF9WRFVTRV9FVkVOVEZEX0ggKi8KPiBkaWZmIC0tZ2l0IGEvZHJp dmVycy92ZHBhL3ZkcGFfdXNlci9pb3ZhX2RvbWFpbi5jIGIvZHJpdmVycy92ZHBhL3ZkcGFfdXNl ci9pb3ZhX2RvbWFpbi5jCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwMDAw MDAuLmNkZmVmOGU5ZjlkNgo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL3ZkcGEvdmRw YV91c2VyL2lvdmFfZG9tYWluLmMKPiBAQCAtMCwwICsxLDQyNiBAQAo+ICsvLyBTUERYLUxpY2Vu c2UtSWRlbnRpZmllcjogR1BMLTIuMC1vbmx5Cj4gKy8qCj4gKyAqIE1NVS1iYXNlZCBJT01NVSBp bXBsZW1lbnRhdGlvbgo+ICsgKgo+ICsgKiBDb3B5cmlnaHQgKEMpIDIwMjAgQnl0ZWRhbmNlIElu Yy4gYW5kL29yIGl0cyBhZmZpbGlhdGVzLiBBbGwgcmlnaHRzIHJlc2VydmVkLgo+ICsgKgo+ICsg KiBBdXRob3I6IFhpZSBZb25namkgPHhpZXlvbmdqaUBieXRlZGFuY2UuY29tPgo+ICsgKgo+ICsg Ki8KPiArCj4gKyNpbmNsdWRlIDxsaW51eC9zbGFiLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9maWxl Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9hbm9uX2lub2Rlcy5oPgo+ICsKPiArI2luY2x1ZGUgImlv dmFfZG9tYWluLmgiCj4gKwo+ICsjZGVmaW5lIElPVkFfU1RBUlRfUEZOIDEKPiArI2RlZmluZSBJ T1ZBX0FMTE9DX09SREVSIDEyCj4gKyNkZWZpbmUgSU9WQV9BTExPQ19TSVpFICgxIDw8IElPVkFf QUxMT0NfT1JERVIpCgoKQ2FuIHRoaXMgd29yayBmb3IgYWxsIGFyY2hzIChlLmcgd2h5IG5vdCB1 c2UgUEFHRV9TSVpFKT8KCgo+ICsKPiArI2RlZmluZSBDT05TSVNURU5UX0RNQV9TSVpFICgxMDI0 ICogMTAyNCAqIDEwMjQpCj4gKwo+ICtzdGF0aWMgaW5saW5lIHN0cnVjdCBwYWdlICoKPiArdmR1 c2VfZG9tYWluX2dldF9ib3VuY2VfcGFnZShzdHJ1Y3QgdmR1c2VfaW92YV9kb21haW4gKmRvbWFp biwKPiArCQkJCXVuc2lnbmVkIGxvbmcgaW92YSkKPiArewo+ICsJdW5zaWduZWQgbG9uZyBpbmRl eCA9IGlvdmEgPj4gUEFHRV9TSElGVDsKPiArCj4gKwlyZXR1cm4gZG9tYWluLT5ib3VuY2VfcGFn ZXNbaW5kZXhdOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIHZvaWQKPiArdmR1c2VfZG9tYWlu X3NldF9ib3VuY2VfcGFnZShzdHJ1Y3QgdmR1c2VfaW92YV9kb21haW4gKmRvbWFpbiwKPiArCQkJ CXVuc2lnbmVkIGxvbmcgaW92YSwgc3RydWN0IHBhZ2UgKnBhZ2UpCj4gK3sKPiArCXVuc2lnbmVk IGxvbmcgaW5kZXggPSBpb3ZhID4+IFBBR0VfU0hJRlQ7Cj4gKwo+ICsJZG9tYWluLT5ib3VuY2Vf cGFnZXNbaW5kZXhdID0gcGFnZTsKPiArfQo+ICsKPiArc3RhdGljIHN0cnVjdCB2ZHVzZV9pb3Zh X21hcCAqCj4gK3ZkdXNlX2RvbWFpbl9hbGxvY19pb3ZhX21hcChzdHJ1Y3QgdmR1c2VfaW92YV9k b21haW4gKmRvbWFpbiwKPiArCQkJdW5zaWduZWQgbG9uZyBpb3ZhLCB1bnNpZ25lZCBsb25nIG9y aWcsCj4gKwkJCXNpemVfdCBzaXplLCBlbnVtIGRtYV9kYXRhX2RpcmVjdGlvbiBkaXIpCj4gK3sK PiArCXN0cnVjdCB2ZHVzZV9pb3ZhX21hcCAqbWFwOwo+ICsKPiArCW1hcCA9IGt6YWxsb2Moc2l6 ZW9mKHN0cnVjdCB2ZHVzZV9pb3ZhX21hcCksIEdGUF9BVE9NSUMpOwo+ICsJaWYgKCFtYXApCj4g KwkJcmV0dXJuIE5VTEw7Cj4gKwo+ICsJbWFwLT5pb3ZhLnN0YXJ0ID0gaW92YTsKPiArCW1hcC0+ aW92YS5sYXN0ID0gaW92YSArIHNpemUgLSAxOwo+ICsJbWFwLT5vcmlnID0gb3JpZzsKPiArCW1h cC0+c2l6ZSA9IHNpemU7Cj4gKwltYXAtPmRpciA9IGRpcjsKPiArCj4gKwlyZXR1cm4gbWFwOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IHBhZ2UgKgo+ICt2ZHVzZV9kb21haW5fZ2V0X21hcHBp bmdfcGFnZShzdHJ1Y3QgdmR1c2VfaW92YV9kb21haW4gKmRvbWFpbiwKPiArCQkJCXVuc2lnbmVk IGxvbmcgaW92YSkKPiArewo+ICsJdW5zaWduZWQgbG9uZyBzdGFydCA9IGlvdmEgJiBQQUdFX01B U0s7Cj4gKwl1bnNpZ25lZCBsb25nIGxhc3QgPSBzdGFydCArIFBBR0VfU0laRSAtIDE7Cj4gKwlz dHJ1Y3QgdmR1c2VfaW92YV9tYXAgKm1hcDsKPiArCXN0cnVjdCBpbnRlcnZhbF90cmVlX25vZGUg Km5vZGU7Cj4gKwlzdHJ1Y3QgcGFnZSAqcGFnZSA9IE5VTEw7Cj4gKwo+ICsJc3Bpbl9sb2NrKCZk b21haW4tPm1hcF9sb2NrKTsKPiArCW5vZGUgPSBpbnRlcnZhbF90cmVlX2l0ZXJfZmlyc3QoJmRv bWFpbi0+bWFwcGluZ3MsIHN0YXJ0LCBsYXN0KTsKPiArCWlmICghbm9kZSkKPiArCQlnb3RvIG91 dDsKPiArCj4gKwltYXAgPSBjb250YWluZXJfb2Yobm9kZSwgc3RydWN0IHZkdXNlX2lvdmFfbWFw LCBpb3ZhKTsKPiArCXBhZ2UgPSB2aXJ0X3RvX3BhZ2UobWFwLT5vcmlnICsgaW92YSAtIG1hcC0+ aW92YS5zdGFydCk7Cj4gKwlnZXRfcGFnZShwYWdlKTsKPiArb3V0Ogo+ICsJc3Bpbl91bmxvY2so JmRvbWFpbi0+bWFwX2xvY2spOwo+ICsKPiArCXJldHVybiBwYWdlOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgc3RydWN0IHBhZ2UgKgo+ICt2ZHVzZV9kb21haW5fYWxsb2NfYm91bmNlX3BhZ2Uoc3RydWN0 IHZkdXNlX2lvdmFfZG9tYWluICpkb21haW4sCj4gKwkJCQl1bnNpZ25lZCBsb25nIGlvdmEpCj4g K3sKPiArCXVuc2lnbmVkIGxvbmcgc3RhcnQgPSBpb3ZhICYgUEFHRV9NQVNLOwo+ICsJdW5zaWdu ZWQgbG9uZyBsYXN0ID0gc3RhcnQgKyBQQUdFX1NJWkUgLSAxOwo+ICsJc3RydWN0IHZkdXNlX2lv dmFfbWFwICptYXA7Cj4gKwlzdHJ1Y3QgaW50ZXJ2YWxfdHJlZV9ub2RlICpub2RlOwo+ICsJc3Ry dWN0IHBhZ2UgKnBhZ2UgPSBOVUxMLCAqbmV3X3BhZ2UgPSBhbGxvY19wYWdlKEdGUF9LRVJORUwp Owo+ICsKPiArCWlmICghbmV3X3BhZ2UpCj4gKwkJcmV0dXJuIE5VTEw7Cj4gKwo+ICsJc3Bpbl9s b2NrKCZkb21haW4tPm1hcF9sb2NrKTsKPiArCW5vZGUgPSBpbnRlcnZhbF90cmVlX2l0ZXJfZmly c3QoJmRvbWFpbi0+bWFwcGluZ3MsIHN0YXJ0LCBsYXN0KTsKPiArCWlmICghbm9kZSkgewo+ICsJ CV9fZnJlZV9wYWdlKG5ld19wYWdlKTsKPiArCQlnb3RvIG91dDsKPiArCX0KPiArCXBhZ2UgPSB2 ZHVzZV9kb21haW5fZ2V0X2JvdW5jZV9wYWdlKGRvbWFpbiwgaW92YSk7Cj4gKwlpZiAocGFnZSkg ewo+ICsJCWdldF9wYWdlKHBhZ2UpOwo+ICsJCV9fZnJlZV9wYWdlKG5ld19wYWdlKTsKCgpMZXQn cyBkZWxheSB0aGUgYWxsb2NhdGlvbiBvZiBuZXdfcGFnZSB1bnRpbCBpdCBpcyByZWFsbHkgcmVx dWlyZWQuCgoKPiArCQlnb3RvIG91dDsKPiArCX0KPiArCXZkdXNlX2RvbWFpbl9zZXRfYm91bmNl X3BhZ2UoZG9tYWluLCBpb3ZhLCBuZXdfcGFnZSk7Cj4gKwlnZXRfcGFnZShuZXdfcGFnZSk7Cj4g KwlwYWdlID0gbmV3X3BhZ2U7Cj4gKwo+ICsJd2hpbGUgKG5vZGUpIHsKCgpJIG1heSBtaXNzIHNv bWV0aGluZyBidXQgd2hpY2ggY2FzZSBzaG91bGQgd2UgZG8gdGhlIGxvb3AgaGVyZT8KCgo+ICsJ CXVuc2lnbmVkIGludCBzcmNfb2Zmc2V0ID0gMCwgZHN0X29mZnNldCA9IDA7Cj4gKwkJdm9pZCAq c3JjLCAqZHN0Owo+ICsJCXNpemVfdCBjb3B5X2xlbjsKPiArCj4gKwkJbWFwID0gY29udGFpbmVy X29mKG5vZGUsIHN0cnVjdCB2ZHVzZV9pb3ZhX21hcCwgaW92YSk7Cj4gKwkJbm9kZSA9IGludGVy dmFsX3RyZWVfaXRlcl9uZXh0KG5vZGUsIHN0YXJ0LCBsYXN0KTsKPiArCQlpZiAobWFwLT5kaXIg PT0gRE1BX0ZST01fREVWSUNFKQo+ICsJCQljb250aW51ZTsKPiArCj4gKwkJaWYgKHN0YXJ0ID4g bWFwLT5pb3ZhLnN0YXJ0KQo+ICsJCQlzcmNfb2Zmc2V0ID0gc3RhcnQgLSBtYXAtPmlvdmEuc3Rh cnQ7Cj4gKwkJZWxzZQo+ICsJCQlkc3Rfb2Zmc2V0ID0gbWFwLT5pb3ZhLnN0YXJ0IC0gc3RhcnQ7 Cj4gKwo+ICsJCXNyYyA9ICh2b2lkICopKG1hcC0+b3JpZyArIHNyY19vZmZzZXQpOwo+ICsJCWRz dCA9IHBhZ2VfYWRkcmVzcyhwYWdlKSArIGRzdF9vZmZzZXQ7Cj4gKwkJY29weV9sZW4gPSBtaW5f dChzaXplX3QsIG1hcC0+c2l6ZSAtIHNyY19vZmZzZXQsCj4gKwkJCQlQQUdFX1NJWkUgLSBkc3Rf b2Zmc2V0KTsKPiArCQltZW1jcHkoZHN0LCBzcmMsIGNvcHlfbGVuKTsKPiArCX0KPiArb3V0Ogo+ ICsJc3Bpbl91bmxvY2soJmRvbWFpbi0+bWFwX2xvY2spOwo+ICsKPiArCXJldHVybiBwYWdlOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZAo+ICt2ZHVzZV9kb21haW5fZnJlZV9ib3VuY2VfcGFnZXMo c3RydWN0IHZkdXNlX2lvdmFfZG9tYWluICpkb21haW4sCj4gKwkJCQl1bnNpZ25lZCBsb25nIGlv dmEsIHNpemVfdCBzaXplKQo+ICt7Cj4gKwlzdHJ1Y3QgcGFnZSAqcGFnZTsKPiArCXN0cnVjdCBp bnRlcnZhbF90cmVlX25vZGUgKm5vZGU7Cj4gKwl1bnNpZ25lZCBsb25nIGxhc3QgPSBpb3ZhICsg c2l6ZSAtIDE7Cj4gKwo+ICsJc3Bpbl9sb2NrKCZkb21haW4tPm1hcF9sb2NrKTsKPiArCW5vZGUg PSBpbnRlcnZhbF90cmVlX2l0ZXJfZmlyc3QoJmRvbWFpbi0+bWFwcGluZ3MsIGlvdmEsIGxhc3Qp Owo+ICsJaWYgKFdBUk5fT04obm9kZSkpCj4gKwkJZ290byBvdXQ7Cj4gKwo+ICsJd2hpbGUgKHNp emUgPiAwKSB7Cj4gKwkJcGFnZSA9IHZkdXNlX2RvbWFpbl9nZXRfYm91bmNlX3BhZ2UoZG9tYWlu LCBpb3ZhKTsKPiArCQlpZiAocGFnZSkgewo+ICsJCQl2ZHVzZV9kb21haW5fc2V0X2JvdW5jZV9w YWdlKGRvbWFpbiwgaW92YSwgTlVMTCk7Cj4gKwkJCV9fZnJlZV9wYWdlKHBhZ2UpOwo+ICsJCX0K PiArCQlzaXplIC09IFBBR0VfU0laRTsKPiArCQlpb3ZhICs9IFBBR0VfU0laRTsKPiArCX0KPiAr b3V0Ogo+ICsJc3Bpbl91bmxvY2soJmRvbWFpbi0+bWFwX2xvY2spOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgdm9pZCB2ZHVzZV9kb21haW5fYm91bmNlKHN0cnVjdCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9t YWluLAo+ICsJCQkJdW5zaWduZWQgbG9uZyBpb3ZhLCB1bnNpZ25lZCBsb25nIG9yaWcsCj4gKwkJ CQlzaXplX3Qgc2l6ZSwgZW51bSBkbWFfZGF0YV9kaXJlY3Rpb24gZGlyKQo+ICt7Cj4gKwl1bnNp Z25lZCBpbnQgb2Zmc2V0ID0gb2Zmc2V0X2luX3BhZ2UoaW92YSk7Cj4gKwo+ICsJd2hpbGUgKHNp emUpIHsKPiArCQlzdHJ1Y3QgcGFnZSAqcCA9IHZkdXNlX2RvbWFpbl9nZXRfYm91bmNlX3BhZ2Uo ZG9tYWluLCBpb3ZhKTsKPiArCQlzaXplX3QgY29weV9sZW4gPSBtaW5fdChzaXplX3QsIFBBR0Vf U0laRSAtIG9mZnNldCwgc2l6ZSk7Cj4gKwkJdm9pZCAqYWRkcjsKPiArCj4gKwkJV0FSTl9PTigh cCAmJiBkaXIgPT0gRE1BX0ZST01fREVWSUNFKTsKPiArCj4gKwkJaWYgKHApIHsKPiArCQkJYWRk ciA9IHBhZ2VfYWRkcmVzcyhwKSArIG9mZnNldDsKPiArCQkJaWYgKGRpciA9PSBETUFfVE9fREVW SUNFKQo+ICsJCQkJbWVtY3B5KGFkZHIsICh2b2lkICopb3JpZywgY29weV9sZW4pOwo+ICsJCQll bHNlIGlmIChkaXIgPT0gRE1BX0ZST01fREVWSUNFKQo+ICsJCQkJbWVtY3B5KCh2b2lkICopb3Jp ZywgYWRkciwgY29weV9sZW4pOwo+ICsJCX0KPiArCj4gKwkJc2l6ZSAtPSBjb3B5X2xlbjsKPiAr CQlvcmlnICs9IGNvcHlfbGVuOwo+ICsJCWlvdmEgKz0gY29weV9sZW47Cj4gKwkJb2Zmc2V0ID0g MDsKPiArCX0KPiArfQo+ICsKPiArc3RhdGljIHVuc2lnbmVkIGxvbmcgdmR1c2VfZG9tYWluX2Fs bG9jX2lvdmEoc3RydWN0IGlvdmFfZG9tYWluICppb3ZhZCwKPiArCQkJCXVuc2lnbmVkIGxvbmcg c2l6ZSwgdW5zaWduZWQgbG9uZyBsaW1pdCkKPiArewo+ICsJdW5zaWduZWQgbG9uZyBzaGlmdCA9 IGlvdmFfc2hpZnQoaW92YWQpOwo+ICsJdW5zaWduZWQgbG9uZyBpb3ZhX2xlbiA9IGlvdmFfYWxp Z24oaW92YWQsIHNpemUpID4+IHNoaWZ0Owo+ICsJdW5zaWduZWQgbG9uZyBpb3ZhX3BmbjsKPiAr Cj4gKwlpZiAoaW92YV9sZW4gPCAoMSA8PCAoSU9WQV9SQU5HRV9DQUNIRV9NQVhfU0laRSAtIDEp KSkKPiArCQlpb3ZhX2xlbiA9IHJvdW5kdXBfcG93X29mX3R3byhpb3ZhX2xlbik7Cj4gKwlpb3Zh X3BmbiA9IGFsbG9jX2lvdmFfZmFzdChpb3ZhZCwgaW92YV9sZW4sIGxpbWl0ID4+IHNoaWZ0LCB0 cnVlKTsKPiArCj4gKwlyZXR1cm4gaW92YV9wZm4gPDwgc2hpZnQ7Cj4gK30KPiArCj4gK3N0YXRp YyB2b2lkIHZkdXNlX2RvbWFpbl9mcmVlX2lvdmEoc3RydWN0IGlvdmFfZG9tYWluICppb3ZhZCwK PiArCQkJCXVuc2lnbmVkIGxvbmcgaW92YSwgc2l6ZV90IHNpemUpCj4gK3sKPiArCXVuc2lnbmVk IGxvbmcgc2hpZnQgPSBpb3ZhX3NoaWZ0KGlvdmFkKTsKPiArCXVuc2lnbmVkIGxvbmcgaW92YV9s ZW4gPSBpb3ZhX2FsaWduKGlvdmFkLCBzaXplKSA+PiBzaGlmdDsKPiArCj4gKwlmcmVlX2lvdmFf ZmFzdChpb3ZhZCwgaW92YSA+PiBzaGlmdCwgaW92YV9sZW4pOwo+ICt9Cj4gKwo+ICtkbWFfYWRk cl90IHZkdXNlX2RvbWFpbl9tYXBfcGFnZShzdHJ1Y3QgdmR1c2VfaW92YV9kb21haW4gKmRvbWFp biwKPiArCQkJCXN0cnVjdCBwYWdlICpwYWdlLCB1bnNpZ25lZCBsb25nIG9mZnNldCwKPiArCQkJ CXNpemVfdCBzaXplLCBlbnVtIGRtYV9kYXRhX2RpcmVjdGlvbiBkaXIsCj4gKwkJCQl1bnNpZ25l ZCBsb25nIGF0dHJzKQo+ICt7Cj4gKwlzdHJ1Y3QgaW92YV9kb21haW4gKmlvdmFkID0gJmRvbWFp bi0+c3RyZWFtX2lvdmFkOwo+ICsJdW5zaWduZWQgbG9uZyBsaW1pdCA9IGRvbWFpbi0+Ym91bmNl X3NpemUgLSAxOwo+ICsJdW5zaWduZWQgbG9uZyBpb3ZhID0gdmR1c2VfZG9tYWluX2FsbG9jX2lv dmEoaW92YWQsIHNpemUsIGxpbWl0KTsKPiArCXVuc2lnbmVkIGxvbmcgb3JpZyA9ICh1bnNpZ25l ZCBsb25nKXBhZ2VfYWRkcmVzcyhwYWdlKSArIG9mZnNldDsKPiArCXN0cnVjdCB2ZHVzZV9pb3Zh X21hcCAqbWFwOwo+ICsKPiArCWlmICghaW92YSkKPiArCQlyZXR1cm4gRE1BX01BUFBJTkdfRVJS T1I7Cj4gKwo+ICsJbWFwID0gdmR1c2VfZG9tYWluX2FsbG9jX2lvdmFfbWFwKGRvbWFpbiwgaW92 YSwgb3JpZywgc2l6ZSwgZGlyKTsKPiArCWlmICghbWFwKSB7Cj4gKwkJdmR1c2VfZG9tYWluX2Zy ZWVfaW92YShpb3ZhZCwgaW92YSwgc2l6ZSk7Cj4gKwkJcmV0dXJuIERNQV9NQVBQSU5HX0VSUk9S Owo+ICsJfQo+ICsKPiArCXNwaW5fbG9jaygmZG9tYWluLT5tYXBfbG9jayk7Cj4gKwlpbnRlcnZh bF90cmVlX2luc2VydCgmbWFwLT5pb3ZhLCAmZG9tYWluLT5tYXBwaW5ncyk7Cj4gKwlzcGluX3Vu bG9jaygmZG9tYWluLT5tYXBfbG9jayk7Cj4gKwo+ICsJaWYgKGRpciA9PSBETUFfVE9fREVWSUNF IHx8IGRpciA9PSBETUFfQklESVJFQ1RJT05BTCkKPiArCQl2ZHVzZV9kb21haW5fYm91bmNlKGRv bWFpbiwgaW92YSwgb3JpZywgc2l6ZSwgRE1BX1RPX0RFVklDRSk7Cj4gKwo+ICsJcmV0dXJuIChk bWFfYWRkcl90KWlvdmE7Cj4gK30KPiArCj4gK3ZvaWQgdmR1c2VfZG9tYWluX3VubWFwX3BhZ2Uo c3RydWN0IHZkdXNlX2lvdmFfZG9tYWluICpkb21haW4sCj4gKwkJCWRtYV9hZGRyX3QgZG1hX2Fk ZHIsIHNpemVfdCBzaXplLAo+ICsJCQllbnVtIGRtYV9kYXRhX2RpcmVjdGlvbiBkaXIsIHVuc2ln bmVkIGxvbmcgYXR0cnMpCj4gK3sKPiArCXN0cnVjdCBpb3ZhX2RvbWFpbiAqaW92YWQgPSAmZG9t YWluLT5zdHJlYW1faW92YWQ7Cj4gKwl1bnNpZ25lZCBsb25nIGlvdmEgPSAodW5zaWduZWQgbG9u ZylkbWFfYWRkcjsKPiArCXN0cnVjdCBpbnRlcnZhbF90cmVlX25vZGUgKm5vZGU7Cj4gKwlzdHJ1 Y3QgdmR1c2VfaW92YV9tYXAgKm1hcDsKPiArCj4gKwlzcGluX2xvY2soJmRvbWFpbi0+bWFwX2xv Y2spOwo+ICsJbm9kZSA9IGludGVydmFsX3RyZWVfaXRlcl9maXJzdCgmZG9tYWluLT5tYXBwaW5n cywgaW92YSwgaW92YSArIDEpOwo+ICsJaWYgKFdBUk5fT04oIW5vZGUpKSB7Cj4gKwkJc3Bpbl91 bmxvY2soJmRvbWFpbi0+bWFwX2xvY2spOwo+ICsJCXJldHVybjsKPiArCX0KPiArCWludGVydmFs X3RyZWVfcmVtb3ZlKG5vZGUsICZkb21haW4tPm1hcHBpbmdzKTsKPiArCXNwaW5fdW5sb2NrKCZk b21haW4tPm1hcF9sb2NrKTsKPiArCj4gKwltYXAgPSBjb250YWluZXJfb2Yobm9kZSwgc3RydWN0 IHZkdXNlX2lvdmFfbWFwLCBpb3ZhKTsKPiArCWlmIChkaXIgPT0gRE1BX0ZST01fREVWSUNFIHx8 IGRpciA9PSBETUFfQklESVJFQ1RJT05BTCkKPiArCQl2ZHVzZV9kb21haW5fYm91bmNlKGRvbWFp biwgaW92YSwgbWFwLT5vcmlnLAo+ICsJCQkJCXNpemUsIERNQV9GUk9NX0RFVklDRSk7Cj4gKwl2 ZHVzZV9kb21haW5fZnJlZV9pb3ZhKGlvdmFkLCBpb3ZhLCBzaXplKTsKPiArCWtmcmVlKG1hcCk7 Cj4gK30KPiArCj4gK3ZvaWQgKnZkdXNlX2RvbWFpbl9hbGxvY19jb2hlcmVudChzdHJ1Y3QgdmR1 c2VfaW92YV9kb21haW4gKmRvbWFpbiwKPiArCQkJCXNpemVfdCBzaXplLCBkbWFfYWRkcl90ICpk bWFfYWRkciwKPiArCQkJCWdmcF90IGZsYWcsIHVuc2lnbmVkIGxvbmcgYXR0cnMpCj4gK3sKPiAr CXN0cnVjdCBpb3ZhX2RvbWFpbiAqaW92YWQgPSAmZG9tYWluLT5jb25zaXN0ZW50X2lvdmFkOwo+ ICsJdW5zaWduZWQgbG9uZyBsaW1pdCA9IGRvbWFpbi0+Ym91bmNlX3NpemUgKyBDT05TSVNURU5U X0RNQV9TSVpFIC0gMTsKPiArCXVuc2lnbmVkIGxvbmcgaW92YSA9IHZkdXNlX2RvbWFpbl9hbGxv Y19pb3ZhKGlvdmFkLCBzaXplLCBsaW1pdCk7Cj4gKwl2b2lkICpvcmlnID0gYWxsb2NfcGFnZXNf ZXhhY3Qoc2l6ZSwgZmxhZyk7Cj4gKwlzdHJ1Y3QgdmR1c2VfaW92YV9tYXAgKm1hcDsKPiArCj4g KwlpZiAoIWlvdmEgfHwgIW9yaWcpCj4gKwkJZ290byBlcnI7Cj4gKwo+ICsJbWFwID0gdmR1c2Vf ZG9tYWluX2FsbG9jX2lvdmFfbWFwKGRvbWFpbiwgaW92YSwgKHVuc2lnbmVkIGxvbmcpb3JpZywK PiArCQkJCQlzaXplLCBETUFfQklESVJFQ1RJT05BTCk7Cj4gKwlpZiAoIW1hcCkKPiArCQlnb3Rv IGVycjsKPiArCj4gKwlzcGluX2xvY2soJmRvbWFpbi0+bWFwX2xvY2spOwo+ICsJaW50ZXJ2YWxf dHJlZV9pbnNlcnQoJm1hcC0+aW92YSwgJmRvbWFpbi0+bWFwcGluZ3MpOwo+ICsJc3Bpbl91bmxv Y2soJmRvbWFpbi0+bWFwX2xvY2spOwo+ICsJKmRtYV9hZGRyID0gKGRtYV9hZGRyX3QpaW92YTsK PiArCj4gKwlyZXR1cm4gb3JpZzsKPiArZXJyOgo+ICsJKmRtYV9hZGRyID0gRE1BX01BUFBJTkdf RVJST1I7Cj4gKwlpZiAob3JpZykKPiArCQlmcmVlX3BhZ2VzX2V4YWN0KG9yaWcsIHNpemUpOwo+ ICsJaWYgKGlvdmEpCj4gKwkJdmR1c2VfZG9tYWluX2ZyZWVfaW92YShpb3ZhZCwgaW92YSwgc2l6 ZSk7Cj4gKwo+ICsJcmV0dXJuIE5VTEw7Cj4gK30KPiArCj4gK3ZvaWQgdmR1c2VfZG9tYWluX2Zy ZWVfY29oZXJlbnQoc3RydWN0IHZkdXNlX2lvdmFfZG9tYWluICpkb21haW4sIHNpemVfdCBzaXpl LAo+ICsJCQkJdm9pZCAqdmFkZHIsIGRtYV9hZGRyX3QgZG1hX2FkZHIsCj4gKwkJCQl1bnNpZ25l ZCBsb25nIGF0dHJzKQo+ICt7Cj4gKwlzdHJ1Y3QgaW92YV9kb21haW4gKmlvdmFkID0gJmRvbWFp bi0+Y29uc2lzdGVudF9pb3ZhZDsKPiArCXVuc2lnbmVkIGxvbmcgaW92YSA9ICh1bnNpZ25lZCBs b25nKWRtYV9hZGRyOwo+ICsJc3RydWN0IGludGVydmFsX3RyZWVfbm9kZSAqbm9kZTsKPiArCXN0 cnVjdCB2ZHVzZV9pb3ZhX21hcCAqbWFwOwo+ICsKPiArCXNwaW5fbG9jaygmZG9tYWluLT5tYXBf bG9jayk7Cj4gKwlub2RlID0gaW50ZXJ2YWxfdHJlZV9pdGVyX2ZpcnN0KCZkb21haW4tPm1hcHBp bmdzLCBpb3ZhLCBpb3ZhICsgMSk7Cj4gKwlpZiAoV0FSTl9PTighbm9kZSkpIHsKPiArCQlzcGlu X3VubG9jaygmZG9tYWluLT5tYXBfbG9jayk7Cj4gKwkJcmV0dXJuOwo+ICsJfQo+ICsJaW50ZXJ2 YWxfdHJlZV9yZW1vdmUobm9kZSwgJmRvbWFpbi0+bWFwcGluZ3MpOwo+ICsJc3Bpbl91bmxvY2so JmRvbWFpbi0+bWFwX2xvY2spOwo+ICsKPiArCW1hcCA9IGNvbnRhaW5lcl9vZihub2RlLCBzdHJ1 Y3QgdmR1c2VfaW92YV9tYXAsIGlvdmEpOwo+ICsJdmR1c2VfZG9tYWluX2ZyZWVfaW92YShpb3Zh ZCwgaW92YSwgc2l6ZSk7Cj4gKwlmcmVlX3BhZ2VzX2V4YWN0KHZhZGRyLCBzaXplKTsKPiArCWtm cmVlKG1hcCk7Cj4gK30KPiArCj4gK3N0YXRpYyB2bV9mYXVsdF90IHZkdXNlX2RvbWFpbl9tbWFw X2ZhdWx0KHN0cnVjdCB2bV9mYXVsdCAqdm1mKQo+ICt7Cj4gKwlzdHJ1Y3QgdmR1c2VfaW92YV9k b21haW4gKmRvbWFpbiA9IHZtZi0+dm1hLT52bV9wcml2YXRlX2RhdGE7Cj4gKwl1bnNpZ25lZCBs b25nIGlvdmEgPSB2bWYtPnBnb2ZmIDw8IFBBR0VfU0hJRlQ7Cj4gKwlzdHJ1Y3QgcGFnZSAqcGFn ZTsKPiArCj4gKwlpZiAoIWRvbWFpbikKPiArCQlyZXR1cm4gVk1fRkFVTFRfU0lHQlVTOwo+ICsK PiArCWlmIChpb3ZhIDwgZG9tYWluLT5ib3VuY2Vfc2l6ZSkKPiArCQlwYWdlID0gdmR1c2VfZG9t YWluX2FsbG9jX2JvdW5jZV9wYWdlKGRvbWFpbiwgaW92YSk7Cj4gKwllbHNlCj4gKwkJcGFnZSA9 IHZkdXNlX2RvbWFpbl9nZXRfbWFwcGluZ19wYWdlKGRvbWFpbiwgaW92YSk7Cj4gKwo+ICsJaWYg KCFwYWdlKQo+ICsJCXJldHVybiBWTV9GQVVMVF9TSUdCVVM7Cj4gKwo+ICsJdm1mLT5wYWdlID0g cGFnZTsKPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCB2 bV9vcGVyYXRpb25zX3N0cnVjdCB2ZHVzZV9kb21haW5fbW1hcF9vcHMgPSB7Cj4gKwkuZmF1bHQg PSB2ZHVzZV9kb21haW5fbW1hcF9mYXVsdCwKPiArfTsKPiArCj4gK3N0YXRpYyBpbnQgdmR1c2Vf ZG9tYWluX21tYXAoc3RydWN0IGZpbGUgKmZpbGUsIHN0cnVjdCB2bV9hcmVhX3N0cnVjdCAqdm1h KQo+ICt7Cj4gKwlzdHJ1Y3QgdmR1c2VfaW92YV9kb21haW4gKmRvbWFpbiA9IGZpbGUtPnByaXZh dGVfZGF0YTsKPiArCj4gKwl2bWEtPnZtX2ZsYWdzIHw9IFZNX0RPTlRDT1BZIHwgVk1fRE9OVERV TVAgfCBWTV9ET05URVhQQU5EOwo+ICsJdm1hLT52bV9wcml2YXRlX2RhdGEgPSBkb21haW47Cj4g Kwl2bWEtPnZtX29wcyA9ICZ2ZHVzZV9kb21haW5fbW1hcF9vcHM7Cj4gKwo+ICsJcmV0dXJuIDA7 Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgdmR1c2VfZG9tYWluX3JlbGVhc2Uoc3RydWN0IGlub2Rl ICppbm9kZSwgc3RydWN0IGZpbGUgKmZpbGUpCj4gK3sKPiArCXN0cnVjdCB2ZHVzZV9pb3ZhX2Rv bWFpbiAqZG9tYWluID0gZmlsZS0+cHJpdmF0ZV9kYXRhOwo+ICsKPiArCXZkdXNlX2RvbWFpbl9m cmVlX2JvdW5jZV9wYWdlcyhkb21haW4sIDAsIGRvbWFpbi0+Ym91bmNlX3NpemUpOwo+ICsJcHV0 X2lvdmFfZG9tYWluKCZkb21haW4tPnN0cmVhbV9pb3ZhZCk7Cj4gKwlwdXRfaW92YV9kb21haW4o JmRvbWFpbi0+Y29uc2lzdGVudF9pb3ZhZCk7Cj4gKwl2ZnJlZShkb21haW4tPmJvdW5jZV9wYWdl cyk7Cj4gKwlrZnJlZShkb21haW4pOwo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtzdGF0 aWMgY29uc3Qgc3RydWN0IGZpbGVfb3BlcmF0aW9ucyB2ZHVzZV9kb21haW5fZm9wcyA9IHsKPiAr CS5tbWFwID0gdmR1c2VfZG9tYWluX21tYXAsCj4gKwkucmVsZWFzZSA9IHZkdXNlX2RvbWFpbl9y ZWxlYXNlLAo+ICt9OwoKCkl0J3MgYmV0dGVyIHRvIGV4cGxhaW4gdGhlIHJlYXNvbiBmb3IgaW50 cm9kdWNpbmcgYSBkZWRpY2F0ZWQgZmlsZSBmb3IgCm1tYXAoKSBoZXJlLgoKCj4gKwo+ICt2b2lk IHZkdXNlX2RvbWFpbl9kZXN0cm95KHN0cnVjdCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluKQo+ ICt7Cj4gKwlmcHV0KGRvbWFpbi0+ZmlsZSk7Cj4gK30KPiArCj4gK3N0cnVjdCB2ZHVzZV9pb3Zh X2RvbWFpbiAqdmR1c2VfZG9tYWluX2NyZWF0ZShzaXplX3QgYm91bmNlX3NpemUpCj4gK3sKPiAr CXN0cnVjdCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluOwo+ICsJc3RydWN0IGZpbGUgKmZpbGU7 Cj4gKwl1bnNpZ25lZCBsb25nIGJvdW5jZV9wZm5zID0gUEFHRV9BTElHTihib3VuY2Vfc2l6ZSkg Pj4gUEFHRV9TSElGVDsKPiArCj4gKwlkb21haW4gPSBremFsbG9jKHNpemVvZigqZG9tYWluKSwg R0ZQX0tFUk5FTCk7Cj4gKwlpZiAoIWRvbWFpbikKPiArCQlyZXR1cm4gTlVMTDsKPiArCj4gKwlk b21haW4tPmJvdW5jZV9zaXplID0gUEFHRV9BTElHTihib3VuY2Vfc2l6ZSk7Cj4gKwlkb21haW4t PmJvdW5jZV9wYWdlcyA9IHZ6YWxsb2MoYm91bmNlX3BmbnMgKiBzaXplb2Yoc3RydWN0IHBhZ2Ug KikpOwo+ICsJaWYgKCFkb21haW4tPmJvdW5jZV9wYWdlcykKPiArCQlnb3RvIGVycl9wYWdlOwo+ ICsKPiArCWZpbGUgPSBhbm9uX2lub2RlX2dldGZpbGUoIlt2ZHVzZS1kb21haW5dIiwgJnZkdXNl X2RvbWFpbl9mb3BzLAo+ICsJCQkJZG9tYWluLCBPX1JEV1IpOwo+ICsJaWYgKElTX0VSUihmaWxl KSkKPiArCQlnb3RvIGVycl9maWxlOwo+ICsKPiArCWRvbWFpbi0+ZmlsZSA9IGZpbGU7Cj4gKwlz cGluX2xvY2tfaW5pdCgmZG9tYWluLT5tYXBfbG9jayk7Cj4gKwlkb21haW4tPm1hcHBpbmdzID0g UkJfUk9PVF9DQUNIRUQ7Cj4gKwlpbml0X2lvdmFfZG9tYWluKCZkb21haW4tPnN0cmVhbV9pb3Zh ZCwKPiArCQkJSU9WQV9BTExPQ19TSVpFLCBJT1ZBX1NUQVJUX1BGTik7Cj4gKwlpbml0X2lvdmFf ZG9tYWluKCZkb21haW4tPmNvbnNpc3RlbnRfaW92YWQsCj4gKwkJCVBBR0VfU0laRSwgYm91bmNl X3BmbnMpOwo+ICsKPiArCXJldHVybiBkb21haW47Cj4gK2Vycl9maWxlOgo+ICsJdmZyZWUoZG9t YWluLT5ib3VuY2VfcGFnZXMpOwo+ICtlcnJfcGFnZToKPiArCWtmcmVlKGRvbWFpbik7Cj4gKwly ZXR1cm4gTlVMTDsKPiArfQo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3ZkcGEvdmRwYV91c2VyL2lv dmFfZG9tYWluLmggYi9kcml2ZXJzL3ZkcGEvdmRwYV91c2VyL2lvdmFfZG9tYWluLmgKPiBuZXcg ZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAwMDAwMC4uY2M2MTg2NmFjYjU2Cj4gLS0t IC9kZXYvbnVsbAo+ICsrKyBiL2RyaXZlcnMvdmRwYS92ZHBhX3VzZXIvaW92YV9kb21haW4uaAo+ IEBAIC0wLDAgKzEsNjggQEAKPiArLyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAt b25seSAqLwo+ICsvKgo+ICsgKiBNTVUtYmFzZWQgSU9NTVUgaW1wbGVtZW50YXRpb24KPiArICoK PiArICogQ29weXJpZ2h0IChDKSAyMDIwIEJ5dGVkYW5jZSBJbmMuIGFuZC9vciBpdHMgYWZmaWxp YXRlcy4gQWxsIHJpZ2h0cyByZXNlcnZlZC4KPiArICoKPiArICogQXV0aG9yOiBYaWUgWW9uZ2pp IDx4aWV5b25namlAYnl0ZWRhbmNlLmNvbT4KPiArICoKPiArICovCj4gKwo+ICsjaWZuZGVmIF9W RFVTRV9JT1ZBX0RPTUFJTl9ICj4gKyNkZWZpbmUgX1ZEVVNFX0lPVkFfRE9NQUlOX0gKPiArCj4g KyNpbmNsdWRlIDxsaW51eC9pb3ZhLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9pbnRlcnZhbF90cmVl Lmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9kbWEtbWFwcGluZy5oPgo+ICsKPiArc3RydWN0IHZkdXNl X2lvdmFfbWFwIHsKPiArCXN0cnVjdCBpbnRlcnZhbF90cmVlX25vZGUgaW92YTsKPiArCXVuc2ln bmVkIGxvbmcgb3JpZzsKCgpOZWVkIGEgYmV0dGVyIG5hbWUsIHByb2JhYmx5ICJ2YSI/CgoKPiAr CXNpemVfdCBzaXplOwo+ICsJZW51bSBkbWFfZGF0YV9kaXJlY3Rpb24gZGlyOwo+ICt9Owo+ICsK PiArc3RydWN0IHZkdXNlX2lvdmFfZG9tYWluIHsKPiArCXN0cnVjdCBpb3ZhX2RvbWFpbiBzdHJl YW1faW92YWQ7Cj4gKwlzdHJ1Y3QgaW92YV9kb21haW4gY29uc2lzdGVudF9pb3ZhZDsKPiArCXN0 cnVjdCBwYWdlICoqYm91bmNlX3BhZ2VzOwo+ICsJc2l6ZV90IGJvdW5jZV9zaXplOwo+ICsJc3Ry dWN0IHJiX3Jvb3RfY2FjaGVkIG1hcHBpbmdzOwoKCldlIGhhZCBJT1RMQiwgYW55IHJlYXNvbiBm b3IgdGhpcyBleHRyYSBtYXBwaW5ncyBoZXJlPwoKCj4gKwlzcGlubG9ja190IG1hcF9sb2NrOwo+ ICsJc3RydWN0IGZpbGUgKmZpbGU7Cj4gK307Cj4gKwo+ICtzdGF0aWMgaW5saW5lIHN0cnVjdCBm aWxlICoKPiArdmR1c2VfZG9tYWluX2ZpbGUoc3RydWN0IHZkdXNlX2lvdmFfZG9tYWluICpkb21h aW4pCj4gK3sKPiArCXJldHVybiBkb21haW4tPmZpbGU7Cj4gK30KPiArCj4gK3N0YXRpYyBpbmxp bmUgdW5zaWduZWQgbG9uZwo+ICt2ZHVzZV9kb21haW5fZ2V0X29mZnNldChzdHJ1Y3QgdmR1c2Vf aW92YV9kb21haW4gKmRvbWFpbiwgdW5zaWduZWQgbG9uZyBpb3ZhKQo+ICt7Cj4gKwlyZXR1cm4g aW92YTsKPiArfQo+ICsKPiArZG1hX2FkZHJfdCB2ZHVzZV9kb21haW5fbWFwX3BhZ2Uoc3RydWN0 IHZkdXNlX2lvdmFfZG9tYWluICpkb21haW4sCj4gKwkJCQlzdHJ1Y3QgcGFnZSAqcGFnZSwgdW5z aWduZWQgbG9uZyBvZmZzZXQsCj4gKwkJCQlzaXplX3Qgc2l6ZSwgZW51bSBkbWFfZGF0YV9kaXJl Y3Rpb24gZGlyLAo+ICsJCQkJdW5zaWduZWQgbG9uZyBhdHRycyk7Cj4gKwo+ICt2b2lkIHZkdXNl X2RvbWFpbl91bm1hcF9wYWdlKHN0cnVjdCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluLAo+ICsJ CQlkbWFfYWRkcl90IGRtYV9hZGRyLCBzaXplX3Qgc2l6ZSwKPiArCQkJZW51bSBkbWFfZGF0YV9k aXJlY3Rpb24gZGlyLCB1bnNpZ25lZCBsb25nIGF0dHJzKTsKPiArCj4gK3ZvaWQgKnZkdXNlX2Rv bWFpbl9hbGxvY19jb2hlcmVudChzdHJ1Y3QgdmR1c2VfaW92YV9kb21haW4gKmRvbWFpbiwKPiAr CQkJCXNpemVfdCBzaXplLCBkbWFfYWRkcl90ICpkbWFfYWRkciwKPiArCQkJCWdmcF90IGZsYWcs IHVuc2lnbmVkIGxvbmcgYXR0cnMpOwo+ICsKPiArdm9pZCB2ZHVzZV9kb21haW5fZnJlZV9jb2hl cmVudChzdHJ1Y3QgdmR1c2VfaW92YV9kb21haW4gKmRvbWFpbiwgc2l6ZV90IHNpemUsCj4gKwkJ CQl2b2lkICp2YWRkciwgZG1hX2FkZHJfdCBkbWFfYWRkciwKPiArCQkJCXVuc2lnbmVkIGxvbmcg YXR0cnMpOwo+ICsKPiArdm9pZCB2ZHVzZV9kb21haW5fZGVzdHJveShzdHJ1Y3QgdmR1c2VfaW92 YV9kb21haW4gKmRvbWFpbik7Cj4gKwo+ICtzdHJ1Y3QgdmR1c2VfaW92YV9kb21haW4gKnZkdXNl X2RvbWFpbl9jcmVhdGUoc2l6ZV90IGJvdW5jZV9zaXplKTsKPiArCj4gKyNlbmRpZiAvKiBfVkRV U0VfSU9WQV9ET01BSU5fSCAqLwo+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3ZkcGEvdmRwYV91c2Vy L3ZkdXNlLmggYi9kcml2ZXJzL3ZkcGEvdmRwYV91c2VyL3ZkdXNlLmgKPiBuZXcgZmlsZSBtb2Rl IDEwMDY0NAo+IGluZGV4IDAwMDAwMDAwMDAwMC4uMzU2NmQyMjkzODJlCj4gLS0tIC9kZXYvbnVs bAo+ICsrKyBiL2RyaXZlcnMvdmRwYS92ZHBhX3VzZXIvdmR1c2UuaAo+IEBAIC0wLDAgKzEsNjIg QEAKPiArLyogU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEdQTC0yLjAtb25seSAqLwo+ICsvKgo+ ICsgKiBWRFVTRTogdkRQQSBEZXZpY2UgaW4gVXNlcnNwYWNlCj4gKyAqCj4gKyAqIENvcHlyaWdo dCAoQykgMjAyMCBCeXRlZGFuY2UgSW5jLiBhbmQvb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCByaWdo dHMgcmVzZXJ2ZWQuCj4gKyAqCj4gKyAqIEF1dGhvcjogWGllIFlvbmdqaSA8eGlleW9uZ2ppQGJ5 dGVkYW5jZS5jb20+Cj4gKyAqCj4gKyAqLwo+ICsKPiArI2lmbmRlZiBfVkRVU0VfSAo+ICsjZGVm aW5lIF9WRFVTRV9ICj4gKwo+ICsjaW5jbHVkZSA8bGludXgvZXZlbnRmZC5oPgo+ICsjaW5jbHVk ZSA8bGludXgvd2FpdC5oPgo+ICsjaW5jbHVkZSA8bGludXgvdmRwYS5oPgo+ICsKPiArI2luY2x1 ZGUgImlvdmFfZG9tYWluLmgiCj4gKyNpbmNsdWRlICJldmVudGZkLmgiCj4gKwo+ICtzdHJ1Y3Qg dmR1c2VfdmlydHF1ZXVlIHsKPiArCXUxNiBpbmRleDsKPiArCWJvb2wgcmVhZHk7Cj4gKwlzcGlu bG9ja190IGtpY2tfbG9jazsKPiArCXNwaW5sb2NrX3QgaXJxX2xvY2s7Cj4gKwlzdHJ1Y3QgZXZl bnRmZF9jdHggKmtpY2tmZDsKPiArCXN0cnVjdCB2ZHVzZV92aXJxZmQgKnZpcnFmZDsKPiArCXZv aWQgKnByaXZhdGU7Cj4gKwlpcnFyZXR1cm5fdCAoKmNiKSh2b2lkICpkYXRhKTsKPiArfTsKPiAr Cj4gK3N0cnVjdCB2ZHVzZV9kZXY7Cj4gKwo+ICtzdHJ1Y3QgdmR1c2VfdmRwYSB7Cj4gKwlzdHJ1 Y3QgdmRwYV9kZXZpY2UgdmRwYTsKPiArCXN0cnVjdCB2ZHVzZV9kZXYgKmRldjsKPiArfTsKPiAr Cj4gK3N0cnVjdCB2ZHVzZV9kZXYgewo+ICsJc3RydWN0IHZkdXNlX3ZkcGEgKnZkZXY7Cj4gKwlz dHJ1Y3QgbXV0ZXggbG9jazsKPiArCXN0cnVjdCB2ZHVzZV92aXJ0cXVldWUgKnZxczsKPiArCXN0 cnVjdCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluOwo+ICsJc3RydWN0IHZob3N0X2lvdGxiICpp b21tdTsKPiArCXNwaW5sb2NrX3QgaW9tbXVfbG9jazsKPiArCWF0b21pY190IGJvdW5jZV9tYXA7 Cj4gKwlzcGlubG9ja190IG1zZ19sb2NrOwo+ICsJYXRvbWljNjRfdCBtc2dfdW5pcXVlOwo+ICsJ d2FpdF9xdWV1ZV9oZWFkX3Qgd2FpdHE7Cj4gKwlzdHJ1Y3QgbGlzdF9oZWFkIHNlbmRfbGlzdDsK PiArCXN0cnVjdCBsaXN0X2hlYWQgcmVjdl9saXN0Owo+ICsJc3RydWN0IGxpc3RfaGVhZCBsaXN0 Owo+ICsJYm9vbCBjb25uZWN0ZWQ7Cj4gKwl1MzIgaWQ7Cj4gKwl1MTYgdnFfc2l6ZV9tYXg7Cj4g Kwl1MTYgdnFfbnVtOwo+ICsJdTMyIHZxX2FsaWduOwo+ICsJdTMyIGRldmljZV9pZDsKPiArCXUz MiB2ZW5kb3JfaWQ7Cj4gK307Cj4gKwo+ICsjZW5kaWYgLyogX1ZEVVNFX0hfICovCj4gZGlmZiAt LWdpdCBhL2RyaXZlcnMvdmRwYS92ZHBhX3VzZXIvdmR1c2VfZGV2LmMgYi9kcml2ZXJzL3ZkcGEv dmRwYV91c2VyL3ZkdXNlX2Rldi5jCj4gbmV3IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAw MDAwMDAwMDAuLjFjZjc1OWJjNTkxNAo+IC0tLSAvZGV2L251bGwKPiArKysgYi9kcml2ZXJzL3Zk cGEvdmRwYV91c2VyL3ZkdXNlX2Rldi5jCj4gQEAgLTAsMCArMSwxMjE3IEBACj4gKy8vIFNQRFgt TGljZW5zZS1JZGVudGlmaWVyOiBHUEwtMi4wLW9ubHkKPiArLyoKPiArICogVkRVU0U6IHZEUEEg RGV2aWNlIGluIFVzZXJzcGFjZQo+ICsgKgo+ICsgKiBDb3B5cmlnaHQgKEMpIDIwMjAgQnl0ZWRh bmNlIEluYy4gYW5kL29yIGl0cyBhZmZpbGlhdGVzLiBBbGwgcmlnaHRzIHJlc2VydmVkLgo+ICsg Kgo+ICsgKiBBdXRob3I6IFhpZSBZb25namkgPHhpZXlvbmdqaUBieXRlZGFuY2UuY29tPgo+ICsg Kgo+ICsgKi8KPiArCj4gKyNpbmNsdWRlIDxsaW51eC9pbml0Lmg+Cj4gKyNpbmNsdWRlIDxsaW51 eC9tb2R1bGUuaD4KPiArI2luY2x1ZGUgPGxpbnV4L21pc2NkZXZpY2UuaD4KPiArI2luY2x1ZGUg PGxpbnV4L2RldmljZS5oPgo+ICsjaW5jbHVkZSA8bGludXgvZXZlbnRmZC5oPgo+ICsjaW5jbHVk ZSA8bGludXgvc2xhYi5oPgo+ICsjaW5jbHVkZSA8bGludXgvd2FpdC5oPgo+ICsjaW5jbHVkZSA8 bGludXgvZG1hLW1hcC1vcHMuaD4KPiArI2luY2x1ZGUgPGxpbnV4L2Fub25faW5vZGVzLmg+Cj4g KyNpbmNsdWRlIDxsaW51eC9maWxlLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC91aW8uaD4KPiArI2lu Y2x1ZGUgPGxpbnV4L3ZkcGEuaD4KPiArI2luY2x1ZGUgPHVhcGkvbGludXgvdmR1c2UuaD4KPiAr I2luY2x1ZGUgPHVhcGkvbGludXgvdmRwYS5oPgo+ICsjaW5jbHVkZSA8dWFwaS9saW51eC92aXJ0 aW9fY29uZmlnLmg+Cj4gKyNpbmNsdWRlIDxsaW51eC9tb2RfZGV2aWNldGFibGUuaD4KPiArCj4g KyNpbmNsdWRlICJ2ZHVzZS5oIgo+ICsKPiArI2RlZmluZSBEUlZfVkVSU0lPTiAgIjEuMCIKPiAr I2RlZmluZSBEUlZfQVVUSE9SICAgIllvbmdqaSBYaWUgPHhpZXlvbmdqaUBieXRlZGFuY2UuY29t PiIKPiArI2RlZmluZSBEUlZfREVTQyAgICAgInZEUEEgRGV2aWNlIGluIFVzZXJzcGFjZSIKPiAr I2RlZmluZSBEUlZfTElDRU5TRSAgIkdQTCB2MiIKPiArCj4gK3N0cnVjdCB2ZHVzZV9kZXZfbXNn IHsKPiArCXN0cnVjdCB2ZHVzZV9kZXZfcmVxdWVzdCByZXE7Cj4gKwlzdHJ1Y3QgdmR1c2VfZGV2 X3Jlc3BvbnNlIHJlc3A7Cj4gKwlzdHJ1Y3QgbGlzdF9oZWFkIGxpc3Q7Cj4gKwl3YWl0X3F1ZXVl X2hlYWRfdCB3YWl0cTsKPiArCWJvb2wgY29tcGxldGVkOwo+ICsJcmVmY291bnRfdCByZWZjbnQ7 CgoKVGhlIHJlZmVyZW5jZSBjb3VudCBoZXJlIHdpbGwgYnJpbmcgZXh0cmEgY29tcGxleGl0eS4g SSB0aGluayB3ZSBjYW4gCnN5bmMgdGhyb3VnaCBtc2dfbG9jay4KCgoKPiArfTsKPiArCj4gK3N0 YXRpYyBzdHJ1Y3Qgd29ya3F1ZXVlX3N0cnVjdCAqdmR1c2VfdmRwYV93cTsKPiArc3RhdGljIERF RklORV9NVVRFWCh2ZHVzZV9sb2NrKTsKPiArc3RhdGljIExJU1RfSEVBRCh2ZHVzZV9kZXZzKTsK PiArCj4gK3N0YXRpYyBpbmxpbmUgc3RydWN0IHZkdXNlX2RldiAqdmRwYV90b192ZHVzZShzdHJ1 Y3QgdmRwYV9kZXZpY2UgKnZkcGEpCj4gK3sKPiArCXN0cnVjdCB2ZHVzZV92ZHBhICp2ZGV2ID0g Y29udGFpbmVyX29mKHZkcGEsIHN0cnVjdCB2ZHVzZV92ZHBhLCB2ZHBhKTsKPiArCj4gKwlyZXR1 cm4gdmRldi0+ZGV2Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW5saW5lIHN0cnVjdCB2ZHVzZV9kZXYg KmRldl90b192ZHVzZShzdHJ1Y3QgZGV2aWNlICpkZXYpCj4gK3sKPiArCXN0cnVjdCB2ZHBhX2Rl dmljZSAqdmRwYSA9IGRldl90b192ZHBhKGRldik7Cj4gKwo+ICsJcmV0dXJuIHZkcGFfdG9fdmR1 c2UodmRwYSk7Cj4gK30KPiArCj4gK3N0YXRpYyBzdHJ1Y3QgdmR1c2VfZGV2X21zZyAqdmR1c2Vf ZGV2X25ld19tc2coc3RydWN0IHZkdXNlX2RldiAqZGV2LCBpbnQgdHlwZSkKPiArewo+ICsJc3Ry dWN0IHZkdXNlX2Rldl9tc2cgKm1zZyA9IGt6YWxsb2Moc2l6ZW9mKCptc2cpLAo+ICsJCQkJCUdG UF9LRVJORUwgfCBfX0dGUF9OT0ZBSUwpOwo+ICsKPiArCW1zZy0+cmVxLnR5cGUgPSB0eXBlOwo+ ICsJbXNnLT5yZXEudW5pcXVlID0gYXRvbWljNjRfZmV0Y2hfaW5jKCZkZXYtPm1zZ191bmlxdWUp OwoKClRoaXMgbG9va3Mgbm90IHNhZmUsIGxldCdzIHVzZSBpZHIgaGVyZS4KCgo+ICsJaW5pdF93 YWl0cXVldWVfaGVhZCgmbXNnLT53YWl0cSk7Cj4gKwlyZWZjb3VudF9zZXQoJm1zZy0+cmVmY250 LCAxKTsKPiArCj4gKwlyZXR1cm4gbXNnOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2ZHVzZV9k ZXZfbXNnX2dldChzdHJ1Y3QgdmR1c2VfZGV2X21zZyAqbXNnKQo+ICt7Cj4gKwlyZWZjb3VudF9p bmMoJm1zZy0+cmVmY250KTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgdmR1c2VfZGV2X21zZ19w dXQoc3RydWN0IHZkdXNlX2Rldl9tc2cgKm1zZykKPiArewo+ICsJaWYgKHJlZmNvdW50X2RlY19h bmRfdGVzdCgmbXNnLT5yZWZjbnQpKQo+ICsJCWtmcmVlKG1zZyk7Cj4gK30KPiArCj4gK3N0YXRp YyBzdHJ1Y3QgdmR1c2VfZGV2X21zZyAqdmR1c2VfZGV2X2ZpbmRfbXNnKHN0cnVjdCB2ZHVzZV9k ZXYgKmRldiwKPiArCQkJCQkJc3RydWN0IGxpc3RfaGVhZCAqaGVhZCwKPiArCQkJCQkJdWludDMy X3QgdW5pcXVlKQo+ICt7Cj4gKwlzdHJ1Y3QgdmR1c2VfZGV2X21zZyAqdG1wLCAqbXNnID0gTlVM TDsKPiArCj4gKwlzcGluX2xvY2soJmRldi0+bXNnX2xvY2spOwo+ICsJbGlzdF9mb3JfZWFjaF9l bnRyeSh0bXAsIGhlYWQsIGxpc3QpIHsKPiArCQlpZiAodG1wLT5yZXEudW5pcXVlID09IHVuaXF1 ZSkgewo+ICsJCQltc2cgPSB0bXA7Cj4gKwkJCWxpc3RfZGVsKCZ0bXAtPmxpc3QpOwo+ICsJCQli cmVhazsKPiArCQl9Cj4gKwl9Cj4gKwlzcGluX3VubG9jaygmZGV2LT5tc2dfbG9jayk7Cj4gKwo+ ICsJcmV0dXJuIG1zZzsKPiArfQo+ICsKPiArc3RhdGljIHN0cnVjdCB2ZHVzZV9kZXZfbXNnICp2 ZHVzZV9kZXZfZGVxdWV1ZV9tc2coc3RydWN0IHZkdXNlX2RldiAqZGV2LAo+ICsJCQkJCQlzdHJ1 Y3QgbGlzdF9oZWFkICpoZWFkKQo+ICt7Cj4gKwlzdHJ1Y3QgdmR1c2VfZGV2X21zZyAqbXNnID0g TlVMTDsKPiArCj4gKwlzcGluX2xvY2soJmRldi0+bXNnX2xvY2spOwo+ICsJaWYgKCFsaXN0X2Vt cHR5KGhlYWQpKSB7Cj4gKwkJbXNnID0gbGlzdF9maXJzdF9lbnRyeShoZWFkLCBzdHJ1Y3QgdmR1 c2VfZGV2X21zZywgbGlzdCk7Cj4gKwkJbGlzdF9kZWwoJm1zZy0+bGlzdCk7Cj4gKwl9Cj4gKwlz cGluX3VubG9jaygmZGV2LT5tc2dfbG9jayk7Cj4gKwo+ICsJcmV0dXJuIG1zZzsKPiArfQo+ICsK PiArc3RhdGljIHZvaWQgdmR1c2VfZGV2X2VucXVldWVfbXNnKHN0cnVjdCB2ZHVzZV9kZXYgKmRl diwKPiArCQkJc3RydWN0IHZkdXNlX2Rldl9tc2cgKm1zZywgc3RydWN0IGxpc3RfaGVhZCAqaGVh ZCkKPiArewo+ICsJc3Bpbl9sb2NrKCZkZXYtPm1zZ19sb2NrKTsKPiArCWxpc3RfYWRkX3RhaWwo Jm1zZy0+bGlzdCwgaGVhZCk7Cj4gKwlzcGluX3VubG9jaygmZGV2LT5tc2dfbG9jayk7Cj4gK30K PiArCj4gK3N0YXRpYyBpbnQgdmR1c2VfZGV2X21zZ19zeW5jKHN0cnVjdCB2ZHVzZV9kZXYgKmRl diwgc3RydWN0IHZkdXNlX2Rldl9tc2cgKm1zZykKPiArewo+ICsJaW50IHJldDsKPiArCj4gKwl2 ZHVzZV9kZXZfZW5xdWV1ZV9tc2coZGV2LCBtc2csICZkZXYtPnNlbmRfbGlzdCk7Cj4gKwl3YWtl X3VwKCZkZXYtPndhaXRxKTsKPiArCXdhaXRfZXZlbnQobXNnLT53YWl0cSwgbXNnLT5jb21wbGV0 ZWQpOwoKClRoaXMgaXMgdW5pbnRlcnJ1cHRpYmxlIHdhaXQsIGl0IG1lYW5zIGlmIHRoZSB1c2Vy c3BhY2UgZm9yZ2V0IHRvIApwcm9jZXNzIHRoZSBjb21tYW5kLCB3ZSB3aWxsIHN0dWNrIGhlcmUg Zm9yZXZlci4KCgo+ICsJLyogY291cGxlZCB3aXRoIHNtcF93bWIoKSBpbiB2ZHVzZV9kZXZfbXNn X2NvbXBsZXRlKCkgKi8KPiArCXNtcF9ybWIoKTsKCgpJbnN0ZWFkIG9mIHVzaW5nIGJhcnJpZXJz LCBJIHdvbmRlciB3aHkgbm90IHNpbXBseSB1c2UgbXNnIGxvY2sgaGVyZT8KCgo+ICsJcmV0ID0g bXNnLT5yZXNwLnJlc3VsdDsKPiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMg dm9pZCB2ZHVzZV9kZXZfbXNnX2NvbXBsZXRlKHN0cnVjdCB2ZHVzZV9kZXZfbXNnICptc2csCj4g KwkJCQkJc3RydWN0IHZkdXNlX2Rldl9yZXNwb25zZSAqcmVzcCkKPiArewo+ICsJdmR1c2VfZGV2 X21zZ19nZXQobXNnKTsKPiArCW1lbWNweSgmbXNnLT5yZXNwLCByZXNwLCBzaXplb2YoKnJlc3Ap KTsKPiArCS8qIGNvdXBsZWQgd2l0aCBzbXBfcm1iKCkgaW4gdmR1c2VfZGV2X21zZ19zeW5jKCkg Ki8KPiArCXNtcF93bWIoKTsKPiArCW1zZy0+Y29tcGxldGVkID0gMTsKPiArCXdha2VfdXAoJm1z Zy0+d2FpdHEpOwo+ICsJdmR1c2VfZGV2X21zZ19wdXQobXNnKTsKPiArfQo+ICsKPiArc3RhdGlj IHU2NCB2ZHVzZV9kZXZfZ2V0X2ZlYXR1cmVzKHN0cnVjdCB2ZHVzZV9kZXYgKmRldikKPiArewo+ ICsJc3RydWN0IHZkdXNlX2Rldl9tc2cgKm1zZyA9IHZkdXNlX2Rldl9uZXdfbXNnKGRldiwgVkRV U0VfR0VUX0ZFQVRVUkVTKTsKPiArCXU2NCBmZWF0dXJlczsKPiArCj4gKwl2ZHVzZV9kZXZfbXNn X3N5bmMoZGV2LCBtc2cpOwo+ICsJZmVhdHVyZXMgPSBtc2ctPnJlc3AuZmVhdHVyZXM7Cj4gKwl2 ZHVzZV9kZXZfbXNnX3B1dChtc2cpOwo+ICsKPiArCXJldHVybiBmZWF0dXJlczsKPiArfQo+ICsK PiArc3RhdGljIGludCB2ZHVzZV9kZXZfc2V0X2ZlYXR1cmVzKHN0cnVjdCB2ZHVzZV9kZXYgKmRl diwgdTY0IGZlYXR1cmVzKQo+ICt7Cj4gKwlzdHJ1Y3QgdmR1c2VfZGV2X21zZyAqbXNnID0gdmR1 c2VfZGV2X25ld19tc2coZGV2LCBWRFVTRV9TRVRfRkVBVFVSRVMpOwo+ICsJaW50IHJldDsKPiAr Cj4gKwltc2ctPnJlcS5zaXplID0gc2l6ZW9mKGZlYXR1cmVzKTsKPiArCW1zZy0+cmVxLmZlYXR1 cmVzID0gZmVhdHVyZXM7Cj4gKwo+ICsJcmV0ID0gdmR1c2VfZGV2X21zZ19zeW5jKGRldiwgbXNn KTsKPiArCXZkdXNlX2Rldl9tc2dfcHV0KG1zZyk7Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ ICsKPiArc3RhdGljIHU4IHZkdXNlX2Rldl9nZXRfc3RhdHVzKHN0cnVjdCB2ZHVzZV9kZXYgKmRl dikKPiArewo+ICsJc3RydWN0IHZkdXNlX2Rldl9tc2cgKm1zZyA9IHZkdXNlX2Rldl9uZXdfbXNn KGRldiwgVkRVU0VfR0VUX1NUQVRVUyk7Cj4gKwl1OCBzdGF0dXM7Cj4gKwo+ICsJdmR1c2VfZGV2 X21zZ19zeW5jKGRldiwgbXNnKTsKPiArCXN0YXR1cyA9IG1zZy0+cmVzcC5zdGF0dXM7Cj4gKwl2 ZHVzZV9kZXZfbXNnX3B1dChtc2cpOwo+ICsKPiArCXJldHVybiBzdGF0dXM7Cj4gK30KPiArCj4g K3N0YXRpYyB2b2lkIHZkdXNlX2Rldl9zZXRfc3RhdHVzKHN0cnVjdCB2ZHVzZV9kZXYgKmRldiwg dTggc3RhdHVzKQo+ICt7Cj4gKwlzdHJ1Y3QgdmR1c2VfZGV2X21zZyAqbXNnID0gdmR1c2VfZGV2 X25ld19tc2coZGV2LCBWRFVTRV9TRVRfU1RBVFVTKTsKPiArCj4gKwltc2ctPnJlcS5zaXplID0g c2l6ZW9mKHN0YXR1cyk7Cj4gKwltc2ctPnJlcS5zdGF0dXMgPSBzdGF0dXM7Cj4gKwo+ICsJdmR1 c2VfZGV2X21zZ19zeW5jKGRldiwgbXNnKTsKPiArCXZkdXNlX2Rldl9tc2dfcHV0KG1zZyk7Cj4g K30KPiArCj4gK3N0YXRpYyB2b2lkIHZkdXNlX2Rldl9nZXRfY29uZmlnKHN0cnVjdCB2ZHVzZV9k ZXYgKmRldiwgdW5zaWduZWQgaW50IG9mZnNldCwKPiArCQkJCQl2b2lkICpidWYsIHVuc2lnbmVk IGludCBsZW4pCj4gK3sKPiArCXN0cnVjdCB2ZHVzZV9kZXZfbXNnICptc2cgPSB2ZHVzZV9kZXZf bmV3X21zZyhkZXYsIFZEVVNFX0dFVF9DT05GSUcpOwo+ICsKPiArCVdBUk5fT04obGVuID4gc2l6 ZW9mKG1zZy0+cmVxLmNvbmZpZy5kYXRhKSk7Cj4gKwo+ICsJbXNnLT5yZXEuc2l6ZSA9IHNpemVv ZihzdHJ1Y3QgdmR1c2VfZGV2X2NvbmZpZ19kYXRhKTsKPiArCW1zZy0+cmVxLmNvbmZpZy5vZmZz ZXQgPSBvZmZzZXQ7Cj4gKwltc2ctPnJlcS5jb25maWcubGVuID0gbGVuOwo+ICsJdmR1c2VfZGV2 X21zZ19zeW5jKGRldiwgbXNnKTsKPiArCW1lbWNweShidWYsIG1zZy0+cmVzcC5jb25maWcuZGF0 YSwgbGVuKTsKPiArCXZkdXNlX2Rldl9tc2dfcHV0KG1zZyk7Cj4gK30KPiArCj4gK3N0YXRpYyB2 b2lkIHZkdXNlX2Rldl9zZXRfY29uZmlnKHN0cnVjdCB2ZHVzZV9kZXYgKmRldiwgdW5zaWduZWQg aW50IG9mZnNldCwKPiArCQkJCQljb25zdCB2b2lkICpidWYsIHVuc2lnbmVkIGludCBsZW4pCj4g K3sKPiArCXN0cnVjdCB2ZHVzZV9kZXZfbXNnICptc2cgPSB2ZHVzZV9kZXZfbmV3X21zZyhkZXYs IFZEVVNFX1NFVF9DT05GSUcpOwo+ICsKPiArCVdBUk5fT04obGVuID4gc2l6ZW9mKG1zZy0+cmVx LmNvbmZpZy5kYXRhKSk7Cj4gKwo+ICsJbXNnLT5yZXEuc2l6ZSA9IHNpemVvZihzdHJ1Y3QgdmR1 c2VfZGV2X2NvbmZpZ19kYXRhKTsKPiArCW1zZy0+cmVxLmNvbmZpZy5vZmZzZXQgPSBvZmZzZXQ7 Cj4gKwltc2ctPnJlcS5jb25maWcubGVuID0gbGVuOwo+ICsJbWVtY3B5KG1zZy0+cmVxLmNvbmZp Zy5kYXRhLCBidWYsIGxlbik7Cj4gKwl2ZHVzZV9kZXZfbXNnX3N5bmMoZGV2LCBtc2cpOwo+ICsJ dmR1c2VfZGV2X21zZ19wdXQobXNnKTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgdmR1c2VfZGV2 X3NldF92cV9udW0oc3RydWN0IHZkdXNlX2RldiAqZGV2LAo+ICsJCQkJc3RydWN0IHZkdXNlX3Zp cnRxdWV1ZSAqdnEsIHUzMiBudW0pCj4gK3sKPiArCXN0cnVjdCB2ZHVzZV9kZXZfbXNnICptc2cg PSB2ZHVzZV9kZXZfbmV3X21zZyhkZXYsIFZEVVNFX1NFVF9WUV9OVU0pOwo+ICsKPiArCW1zZy0+ cmVxLnNpemUgPSBzaXplb2Yoc3RydWN0IHZkdXNlX3ZxX251bSk7Cj4gKwltc2ctPnJlcS52cV9u dW0uaW5kZXggPSB2cS0+aW5kZXg7Cj4gKwltc2ctPnJlcS52cV9udW0ubnVtID0gbnVtOwo+ICsK PiArCXZkdXNlX2Rldl9tc2dfc3luYyhkZXYsIG1zZyk7Cj4gKwl2ZHVzZV9kZXZfbXNnX3B1dCht c2cpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHZkdXNlX2Rldl9zZXRfdnFfYWRkcihzdHJ1Y3Qg dmR1c2VfZGV2ICpkZXYsCj4gKwkJCQlzdHJ1Y3QgdmR1c2VfdmlydHF1ZXVlICp2cSwgdTY0IGRl c2NfYWRkciwKPiArCQkJCXU2NCBkcml2ZXJfYWRkciwgdTY0IGRldmljZV9hZGRyKQo+ICt7Cj4g KwlzdHJ1Y3QgdmR1c2VfZGV2X21zZyAqbXNnID0gdmR1c2VfZGV2X25ld19tc2coZGV2LCBWRFVT RV9TRVRfVlFfQUREUik7Cj4gKwlpbnQgcmV0Owo+ICsKPiArCW1zZy0+cmVxLnNpemUgPSBzaXpl b2Yoc3RydWN0IHZkdXNlX3ZxX2FkZHIpOwo+ICsJbXNnLT5yZXEudnFfYWRkci5pbmRleCA9IHZx LT5pbmRleDsKPiArCW1zZy0+cmVxLnZxX2FkZHIuZGVzY19hZGRyID0gZGVzY19hZGRyOwo+ICsJ bXNnLT5yZXEudnFfYWRkci5kcml2ZXJfYWRkciA9IGRyaXZlcl9hZGRyOwo+ICsJbXNnLT5yZXEu dnFfYWRkci5kZXZpY2VfYWRkciA9IGRldmljZV9hZGRyOwo+ICsKPiArCXJldCA9IHZkdXNlX2Rl dl9tc2dfc3luYyhkZXYsIG1zZyk7Cj4gKwl2ZHVzZV9kZXZfbXNnX3B1dChtc2cpOwo+ICsKPiAr CXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHZkdXNlX2Rldl9zZXRfdnFfcmVh ZHkoc3RydWN0IHZkdXNlX2RldiAqZGV2LAo+ICsJCQkJc3RydWN0IHZkdXNlX3ZpcnRxdWV1ZSAq dnEsIGJvb2wgcmVhZHkpCj4gK3sKPiArCXN0cnVjdCB2ZHVzZV9kZXZfbXNnICptc2cgPSB2ZHVz ZV9kZXZfbmV3X21zZyhkZXYsIFZEVVNFX1NFVF9WUV9SRUFEWSk7Cj4gKwo+ICsJbXNnLT5yZXEu c2l6ZSA9IHNpemVvZihzdHJ1Y3QgdmR1c2VfdnFfcmVhZHkpOwo+ICsJbXNnLT5yZXEudnFfcmVh ZHkuaW5kZXggPSB2cS0+aW5kZXg7Cj4gKwltc2ctPnJlcS52cV9yZWFkeS5yZWFkeSA9IHJlYWR5 Owo+ICsKPiArCXZkdXNlX2Rldl9tc2dfc3luYyhkZXYsIG1zZyk7Cj4gKwl2ZHVzZV9kZXZfbXNn X3B1dChtc2cpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgYm9vbCB2ZHVzZV9kZXZfZ2V0X3ZxX3JlYWR5 KHN0cnVjdCB2ZHVzZV9kZXYgKmRldiwKPiArCQkJCSAgIHN0cnVjdCB2ZHVzZV92aXJ0cXVldWUg KnZxKQo+ICt7Cj4gKwlzdHJ1Y3QgdmR1c2VfZGV2X21zZyAqbXNnID0gdmR1c2VfZGV2X25ld19t c2coZGV2LCBWRFVTRV9HRVRfVlFfUkVBRFkpOwo+ICsJYm9vbCByZWFkeTsKPiArCj4gKwltc2ct PnJlcS5zaXplID0gc2l6ZW9mKHN0cnVjdCB2ZHVzZV92cV9yZWFkeSk7Cj4gKwltc2ctPnJlcS52 cV9yZWFkeS5pbmRleCA9IHZxLT5pbmRleDsKPiArCj4gKwl2ZHVzZV9kZXZfbXNnX3N5bmMoZGV2 LCBtc2cpOwo+ICsJcmVhZHkgPSBtc2ctPnJlc3AudnFfcmVhZHkucmVhZHk7Cj4gKwl2ZHVzZV9k ZXZfbXNnX3B1dChtc2cpOwo+ICsKPiArCXJldHVybiByZWFkeTsKPiArfQo+ICsKPiArc3RhdGlj IGludCB2ZHVzZV9kZXZfZ2V0X3ZxX3N0YXRlKHN0cnVjdCB2ZHVzZV9kZXYgKmRldiwKPiArCQkJ CXN0cnVjdCB2ZHVzZV92aXJ0cXVldWUgKnZxLAo+ICsJCQkJc3RydWN0IHZkcGFfdnFfc3RhdGUg KnN0YXRlKQo+ICt7Cj4gKwlzdHJ1Y3QgdmR1c2VfZGV2X21zZyAqbXNnID0gdmR1c2VfZGV2X25l d19tc2coZGV2LCBWRFVTRV9HRVRfVlFfU1RBVEUpOwo+ICsJaW50IHJldDsKPiArCj4gKwltc2ct PnJlcS5zaXplID0gc2l6ZW9mKHN0cnVjdCB2ZHVzZV92cV9zdGF0ZSk7Cj4gKwltc2ctPnJlcS52 cV9zdGF0ZS5pbmRleCA9IHZxLT5pbmRleDsKPiArCj4gKwlyZXQgPSB2ZHVzZV9kZXZfbXNnX3N5 bmMoZGV2LCBtc2cpOwo+ICsJc3RhdGUtPmF2YWlsX2luZGV4ID0gbXNnLT5yZXNwLnZxX3N0YXRl LmF2YWlsX2lkeDsKPiArCXZkdXNlX2Rldl9tc2dfcHV0KG1zZyk7Cj4gKwo+ICsJcmV0dXJuIHJl dDsKPiArfQo+ICsKPiArc3RhdGljIGludCB2ZHVzZV9kZXZfc2V0X3ZxX3N0YXRlKHN0cnVjdCB2 ZHVzZV9kZXYgKmRldiwKPiArCQkJCXN0cnVjdCB2ZHVzZV92aXJ0cXVldWUgKnZxLAo+ICsJCQkJ Y29uc3Qgc3RydWN0IHZkcGFfdnFfc3RhdGUgKnN0YXRlKQo+ICt7Cj4gKwlzdHJ1Y3QgdmR1c2Vf ZGV2X21zZyAqbXNnID0gdmR1c2VfZGV2X25ld19tc2coZGV2LCBWRFVTRV9TRVRfVlFfU1RBVEUp Owo+ICsJaW50IHJldDsKPiArCj4gKwltc2ctPnJlcS5zaXplID0gc2l6ZW9mKHN0cnVjdCB2ZHVz ZV92cV9zdGF0ZSk7Cj4gKwltc2ctPnJlcS52cV9zdGF0ZS5pbmRleCA9IHZxLT5pbmRleDsKPiAr CW1zZy0+cmVxLnZxX3N0YXRlLmF2YWlsX2lkeCA9IHN0YXRlLT5hdmFpbF9pbmRleDsKPiArCj4g KwlyZXQgPSB2ZHVzZV9kZXZfbXNnX3N5bmMoZGV2LCBtc2cpOwo+ICsJdmR1c2VfZGV2X21zZ19w dXQobXNnKTsKPiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHZkdXNl X2Rldl91cGRhdGVfaW90bGIoc3RydWN0IHZkdXNlX2RldiAqZGV2LAo+ICsJCQkJCXU2NCBzdGFy dCwgdTY0IGxhc3QpCj4gK3sKPiArCXN0cnVjdCB2ZHVzZV9kZXZfbXNnICptc2c7Cj4gKwlpbnQg cmV0Owo+ICsKPiArCWlmIChsYXN0IDwgc3RhcnQpCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ ICsJbXNnID0gdmR1c2VfZGV2X25ld19tc2coZGV2LCBWRFVTRV9VUERBVEVfSU9UTEIpOwoKClRo aXMgaXMgYWN0dWFsbHkgYSBJT1RMQiBpbnZhbGlkYXRpb24uIFNvIGxldCdzIHJlbmFtZSB0aGUg ZnVuY3Rpb24gYW5kIAptZXNzYWdlIHR5cGUuCgoKPiArCW1zZy0+cmVxLnNpemUgPSBzaXplb2Yo c3RydWN0IHZkdXNlX2lvdmFfcmFuZ2UpOwo+ICsJbXNnLT5yZXEuaW92YS5zdGFydCA9IHN0YXJ0 Owo+ICsJbXNnLT5yZXEuaW92YS5sYXN0ID0gbGFzdDsKPiArCj4gKwlyZXQgPSB2ZHVzZV9kZXZf bXNnX3N5bmMoZGV2LCBtc2cpOwo+ICsJdmR1c2VfZGV2X21zZ19wdXQobXNnKTsKPiArCj4gKwly ZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgc3NpemVfdCB2ZHVzZV9kZXZfcmVhZF9pdGVy KHN0cnVjdCBraW9jYiAqaW9jYiwgc3RydWN0IGlvdl9pdGVyICp0bykKPiArewo+ICsJc3RydWN0 IGZpbGUgKmZpbGUgPSBpb2NiLT5raV9maWxwOwo+ICsJc3RydWN0IHZkdXNlX2RldiAqZGV2ID0g ZmlsZS0+cHJpdmF0ZV9kYXRhOwo+ICsJc3RydWN0IHZkdXNlX2Rldl9tc2cgKm1zZzsKPiArCWlu dCBzaXplID0gc2l6ZW9mKHN0cnVjdCB2ZHVzZV9kZXZfcmVxdWVzdCk7Cj4gKwlzc2l6ZV90IHJl dCA9IDA7Cj4gKwo+ICsJaWYgKGlvdl9pdGVyX2NvdW50KHRvKSA8IHNpemUpCj4gKwkJcmV0dXJu IDA7Cj4gKwo+ICsJd2hpbGUgKDEpIHsKPiArCQltc2cgPSB2ZHVzZV9kZXZfZGVxdWV1ZV9tc2co ZGV2LCAmZGV2LT5zZW5kX2xpc3QpOwo+ICsJCWlmIChtc2cpCj4gKwkJCWJyZWFrOwo+ICsKPiAr CQlpZiAoZmlsZS0+Zl9mbGFncyAmIE9fTk9OQkxPQ0spCj4gKwkJCXJldHVybiAtRUFHQUlOOwo+ ICsKPiArCQlyZXQgPSB3YWl0X2V2ZW50X2ludGVycnVwdGlibGVfZXhjbHVzaXZlKGRldi0+d2Fp dHEsCj4gKwkJCQkJIWxpc3RfZW1wdHkoJmRldi0+c2VuZF9saXN0KSk7Cj4gKwkJaWYgKHJldCkK PiArCQkJcmV0dXJuIHJldDsKPiArCX0KPiArCXJldCA9IGNvcHlfdG9faXRlcigmbXNnLT5yZXEs IHNpemUsIHRvKTsKPiArCWlmIChyZXQgIT0gc2l6ZSkgewo+ICsJCXZkdXNlX2Rldl9lbnF1ZXVl X21zZyhkZXYsIG1zZywgJmRldi0+c2VuZF9saXN0KTsKPiArCQlyZXR1cm4gLUVGQVVMVDsKPiAr CX0KPiArCXZkdXNlX2Rldl9lbnF1ZXVlX21zZyhkZXYsIG1zZywgJmRldi0+cmVjdl9saXN0KTsK PiArCj4gKwlyZXR1cm4gcmV0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgc3NpemVfdCB2ZHVzZV9kZXZf d3JpdGVfaXRlcihzdHJ1Y3Qga2lvY2IgKmlvY2IsIHN0cnVjdCBpb3ZfaXRlciAqZnJvbSkKPiAr ewo+ICsJc3RydWN0IGZpbGUgKmZpbGUgPSBpb2NiLT5raV9maWxwOwo+ICsJc3RydWN0IHZkdXNl X2RldiAqZGV2ID0gZmlsZS0+cHJpdmF0ZV9kYXRhOwo+ICsJc3RydWN0IHZkdXNlX2Rldl9yZXNw b25zZSByZXNwOwo+ICsJc3RydWN0IHZkdXNlX2Rldl9tc2cgKm1zZzsKPiArCXNpemVfdCByZXQ7 Cj4gKwo+ICsJcmV0ID0gY29weV9mcm9tX2l0ZXIoJnJlc3AsIHNpemVvZihyZXNwKSwgZnJvbSk7 Cj4gKwlpZiAocmV0ICE9IHNpemVvZihyZXNwKSkKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCj4g Kwltc2cgPSB2ZHVzZV9kZXZfZmluZF9tc2coZGV2LCAmZGV2LT5yZWN2X2xpc3QsIHJlc3AudW5p cXVlKTsKPiArCWlmICghbXNnKQo+ICsJCXJldHVybiAtRUlOVkFMOwo+ICsKPiArCXZkdXNlX2Rl dl9tc2dfY29tcGxldGUobXNnLCAmcmVzcCk7CgoKU28gd2UgaGFkIG11bHRpcGxlIHR5cGVzIG9m IHJlcXVlc3RzL3Jlc3BvbnNlcywgaXMgdGhpcyBiZXR0ZXIgdG8gCmludHJvZHVjZSBhIHF1ZXVl IGJhc2VkIGFkbWluIGludGVyZmFjZSBvdGhlciB0aGFuIGlvY3RsPwoKCj4gKwo+ICsJcmV0dXJu IHJldDsKPiArfQo+ICsKPiArc3RhdGljIF9fcG9sbF90IHZkdXNlX2Rldl9wb2xsKHN0cnVjdCBm aWxlICpmaWxlLCBwb2xsX3RhYmxlICp3YWl0KQo+ICt7Cj4gKwlzdHJ1Y3QgdmR1c2VfZGV2ICpk ZXYgPSBmaWxlLT5wcml2YXRlX2RhdGE7Cj4gKwlfX3BvbGxfdCBtYXNrID0gMDsKPiArCj4gKwlw b2xsX3dhaXQoZmlsZSwgJmRldi0+d2FpdHEsIHdhaXQpOwo+ICsKPiArCWlmICghbGlzdF9lbXB0 eSgmZGV2LT5zZW5kX2xpc3QpKQo+ICsJCW1hc2sgfD0gRVBPTExJTiB8IEVQT0xMUkROT1JNOwo+ ICsKPiArCXJldHVybiBtYXNrOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHZkdXNlX2lvdGxiX2Fk ZF9yYW5nZShzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYsCj4gKwkJCQkgdTY0IHN0YXJ0LCB1NjQgbGFz dCwKPiArCQkJCSB1NjQgYWRkciwgdW5zaWduZWQgaW50IHBlcm0sCj4gKwkJCQkgc3RydWN0IGZp bGUgKmZpbGUsIHU2NCBvZmZzZXQpCj4gK3sKPiArCXN0cnVjdCB2aG9zdF9pb3RsYl9maWxlICpp b3RsYl9maWxlOwo+ICsJaW50IHJldDsKPiArCj4gKwlpb3RsYl9maWxlID0ga21hbGxvYyhzaXpl b2YoKmlvdGxiX2ZpbGUpLCBHRlBfQVRPTUlDKTsKPiArCWlmICghaW90bGJfZmlsZSkKPiArCQly ZXR1cm4gLUVOT01FTTsKPiArCj4gKwlpb3RsYl9maWxlLT5maWxlID0gZ2V0X2ZpbGUoZmlsZSk7 Cj4gKwlpb3RsYl9maWxlLT5vZmZzZXQgPSBvZmZzZXQ7Cj4gKwo+ICsJc3Bpbl9sb2NrKCZkZXYt PmlvbW11X2xvY2spOwo+ICsJcmV0ID0gdmhvc3RfaW90bGJfYWRkX3JhbmdlKGRldi0+aW9tbXUs IHN0YXJ0LCBsYXN0LAo+ICsJCQkJCWFkZHIsIHBlcm0sIGlvdGxiX2ZpbGUpOwo+ICsJc3Bpbl91 bmxvY2soJmRldi0+aW9tbXVfbG9jayk7Cj4gKwlpZiAocmV0KSB7Cj4gKwkJZnB1dChpb3RsYl9m aWxlLT5maWxlKTsKPiArCQlrZnJlZShpb3RsYl9maWxlKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJ fQo+ICsJcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lkIHZkdXNlX2lvdGxiX2RlbF9y YW5nZShzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYsIHU2NCBzdGFydCwgdTY0IGxhc3QpCj4gK3sKPiAr CXN0cnVjdCB2aG9zdF9pb3RsYl9maWxlICppb3RsYl9maWxlOwo+ICsJc3RydWN0IHZob3N0X2lv dGxiX21hcCAqbWFwOwo+ICsKPiArCXNwaW5fbG9jaygmZGV2LT5pb21tdV9sb2NrKTsKPiArCXdo aWxlICgobWFwID0gdmhvc3RfaW90bGJfaXRyZWVfZmlyc3QoZGV2LT5pb21tdSwgc3RhcnQsIGxh c3QpKSkgewo+ICsJCWlvdGxiX2ZpbGUgPSAoc3RydWN0IHZob3N0X2lvdGxiX2ZpbGUgKiltYXAt Pm9wYXF1ZTsKPiArCQlmcHV0KGlvdGxiX2ZpbGUtPmZpbGUpOwo+ICsJCWtmcmVlKGlvdGxiX2Zp bGUpOwo+ICsJCXZob3N0X2lvdGxiX21hcF9mcmVlKGRldi0+aW9tbXUsIG1hcCk7Cj4gKwl9Cj4g KwlzcGluX3VubG9jaygmZGV2LT5pb21tdV9sb2NrKTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQg dmR1c2VfZGV2X3Jlc2V0KHN0cnVjdCB2ZHVzZV9kZXYgKmRldikKPiArewo+ICsJaW50IGk7Cj4g Kwo+ICsJYXRvbWljX3NldCgmZGV2LT5ib3VuY2VfbWFwLCAwKTsKPiArCXZkdXNlX2lvdGxiX2Rl bF9yYW5nZShkZXYsIDBVTEwsIDBVTEwgLSAxKTsKPiArCXZkdXNlX2Rldl91cGRhdGVfaW90bGIo ZGV2LCAwVUxMLCAwVUxMIC0gMSk7CgoKVUxMT05HX01BWCBwbGVhc2UuCgoKPiArCj4gKwlmb3Ig KGkgPSAwOyBpIDwgZGV2LT52cV9udW07IGkrKykgewo+ICsJCXN0cnVjdCB2ZHVzZV92aXJ0cXVl dWUgKnZxID0gJmRldi0+dnFzW2ldOwo+ICsKPiArCQlzcGluX2xvY2soJnZxLT5pcnFfbG9jayk7 Cj4gKwkJdnEtPnJlYWR5ID0gZmFsc2U7Cj4gKwkJdnEtPmNiID0gTlVMTDsKPiArCQl2cS0+cHJp dmF0ZSA9IE5VTEw7Cj4gKwkJc3Bpbl91bmxvY2soJnZxLT5pcnFfbG9jayk7Cj4gKwl9Cj4gK30K PiArCj4gK3N0YXRpYyBpbnQgdmR1c2VfdmRwYV9zZXRfdnFfYWRkcmVzcyhzdHJ1Y3QgdmRwYV9k ZXZpY2UgKnZkcGEsIHUxNiBpZHgsCj4gKwkJCQl1NjQgZGVzY19hcmVhLCB1NjQgZHJpdmVyX2Fy ZWEsCj4gKwkJCQl1NjQgZGV2aWNlX2FyZWEpCj4gK3sKPiArCXN0cnVjdCB2ZHVzZV9kZXYgKmRl diA9IHZkcGFfdG9fdmR1c2UodmRwYSk7Cj4gKwlzdHJ1Y3QgdmR1c2VfdmlydHF1ZXVlICp2cSA9 ICZkZXYtPnZxc1tpZHhdOwo+ICsKPiArCXJldHVybiB2ZHVzZV9kZXZfc2V0X3ZxX2FkZHIoZGV2 LCB2cSwgZGVzY19hcmVhLAo+ICsJCQkJCWRyaXZlcl9hcmVhLCBkZXZpY2VfYXJlYSk7Cj4gK30K PiArCj4gK3N0YXRpYyB2b2lkIHZkdXNlX3ZkcGFfa2lja192cShzdHJ1Y3QgdmRwYV9kZXZpY2Ug KnZkcGEsIHUxNiBpZHgpCj4gK3sKPiArCXN0cnVjdCB2ZHVzZV9kZXYgKmRldiA9IHZkcGFfdG9f dmR1c2UodmRwYSk7Cj4gKwlzdHJ1Y3QgdmR1c2VfdmlydHF1ZXVlICp2cSA9ICZkZXYtPnZxc1tp ZHhdOwo+ICsKPiArCXZkdXNlX3ZxX2tpY2sodnEpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2 ZHVzZV92ZHBhX3NldF92cV9jYihzdHJ1Y3QgdmRwYV9kZXZpY2UgKnZkcGEsIHUxNiBpZHgsCj4g KwkJCSAgICAgIHN0cnVjdCB2ZHBhX2NhbGxiYWNrICpjYikKPiArewo+ICsJc3RydWN0IHZkdXNl X2RldiAqZGV2ID0gdmRwYV90b192ZHVzZSh2ZHBhKTsKPiArCXN0cnVjdCB2ZHVzZV92aXJ0cXVl dWUgKnZxID0gJmRldi0+dnFzW2lkeF07Cj4gKwo+ICsJdnEtPmNiID0gY2ItPmNhbGxiYWNrOwo+ ICsJdnEtPnByaXZhdGUgPSBjYi0+cHJpdmF0ZTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgdmR1 c2VfdmRwYV9zZXRfdnFfbnVtKHN0cnVjdCB2ZHBhX2RldmljZSAqdmRwYSwgdTE2IGlkeCwgdTMy IG51bSkKPiArewo+ICsJc3RydWN0IHZkdXNlX2RldiAqZGV2ID0gdmRwYV90b192ZHVzZSh2ZHBh KTsKPiArCXN0cnVjdCB2ZHVzZV92aXJ0cXVldWUgKnZxID0gJmRldi0+dnFzW2lkeF07Cj4gKwo+ ICsJdmR1c2VfZGV2X3NldF92cV9udW0oZGV2LCB2cSwgbnVtKTsKPiArfQo+ICsKPiArc3RhdGlj IHZvaWQgdmR1c2VfdmRwYV9zZXRfdnFfcmVhZHkoc3RydWN0IHZkcGFfZGV2aWNlICp2ZHBhLAo+ ICsJCQkJCXUxNiBpZHgsIGJvb2wgcmVhZHkpCj4gK3sKPiArCXN0cnVjdCB2ZHVzZV9kZXYgKmRl diA9IHZkcGFfdG9fdmR1c2UodmRwYSk7Cj4gKwlzdHJ1Y3QgdmR1c2VfdmlydHF1ZXVlICp2cSA9 ICZkZXYtPnZxc1tpZHhdOwo+ICsKPiArCXZkdXNlX2Rldl9zZXRfdnFfcmVhZHkoZGV2LCB2cSwg cmVhZHkpOwo+ICsJdnEtPnJlYWR5ID0gcmVhZHk7Cj4gK30KPiArCj4gK3N0YXRpYyBib29sIHZk dXNlX3ZkcGFfZ2V0X3ZxX3JlYWR5KHN0cnVjdCB2ZHBhX2RldmljZSAqdmRwYSwgdTE2IGlkeCkK PiArewo+ICsJc3RydWN0IHZkdXNlX2RldiAqZGV2ID0gdmRwYV90b192ZHVzZSh2ZHBhKTsKPiAr CXN0cnVjdCB2ZHVzZV92aXJ0cXVldWUgKnZxID0gJmRldi0+dnFzW2lkeF07Cj4gKwo+ICsJdnEt PnJlYWR5ID0gdmR1c2VfZGV2X2dldF92cV9yZWFkeShkZXYsIHZxKTsKPiArCj4gKwlyZXR1cm4g dnEtPnJlYWR5Owo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHZkdXNlX3ZkcGFfc2V0X3ZxX3N0YXRl KHN0cnVjdCB2ZHBhX2RldmljZSAqdmRwYSwgdTE2IGlkeCwKPiArCQkJCWNvbnN0IHN0cnVjdCB2 ZHBhX3ZxX3N0YXRlICpzdGF0ZSkKPiArewo+ICsJc3RydWN0IHZkdXNlX2RldiAqZGV2ID0gdmRw YV90b192ZHVzZSh2ZHBhKTsKPiArCXN0cnVjdCB2ZHVzZV92aXJ0cXVldWUgKnZxID0gJmRldi0+ dnFzW2lkeF07Cj4gKwo+ICsJcmV0dXJuIHZkdXNlX2Rldl9zZXRfdnFfc3RhdGUoZGV2LCB2cSwg c3RhdGUpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgaW50IHZkdXNlX3ZkcGFfZ2V0X3ZxX3N0YXRlKHN0 cnVjdCB2ZHBhX2RldmljZSAqdmRwYSwgdTE2IGlkeCwKPiArCQkJCXN0cnVjdCB2ZHBhX3ZxX3N0 YXRlICpzdGF0ZSkKPiArewo+ICsJc3RydWN0IHZkdXNlX2RldiAqZGV2ID0gdmRwYV90b192ZHVz ZSh2ZHBhKTsKPiArCXN0cnVjdCB2ZHVzZV92aXJ0cXVldWUgKnZxID0gJmRldi0+dnFzW2lkeF07 Cj4gKwo+ICsJcmV0dXJuIHZkdXNlX2Rldl9nZXRfdnFfc3RhdGUoZGV2LCB2cSwgc3RhdGUpOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgdTMyIHZkdXNlX3ZkcGFfZ2V0X3ZxX2FsaWduKHN0cnVjdCB2ZHBh X2RldmljZSAqdmRwYSkKPiArewo+ICsJc3RydWN0IHZkdXNlX2RldiAqZGV2ID0gdmRwYV90b192 ZHVzZSh2ZHBhKTsKPiArCj4gKwlyZXR1cm4gZGV2LT52cV9hbGlnbjsKPiArfQo+ICsKPiArc3Rh dGljIHU2NCB2ZHVzZV92ZHBhX2dldF9mZWF0dXJlcyhzdHJ1Y3QgdmRwYV9kZXZpY2UgKnZkcGEp Cj4gK3sKPiArCXN0cnVjdCB2ZHVzZV9kZXYgKmRldiA9IHZkcGFfdG9fdmR1c2UodmRwYSk7Cj4g Kwl1NjQgZml4ZWQgPSAoMVVMTCA8PCBWSVJUSU9fRl9BQ0NFU1NfUExBVEZPUk0pOwo+ICsKPiAr CXJldHVybiAodmR1c2VfZGV2X2dldF9mZWF0dXJlcyhkZXYpIHwgZml4ZWQpOwo+ICt9Cj4gKwo+ ICtzdGF0aWMgaW50IHZkdXNlX3ZkcGFfc2V0X2ZlYXR1cmVzKHN0cnVjdCB2ZHBhX2RldmljZSAq dmRwYSwgdTY0IGZlYXR1cmVzKQo+ICt7Cj4gKwlzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYgPSB2ZHBh X3RvX3ZkdXNlKHZkcGEpOwo+ICsKPiArCXJldHVybiB2ZHVzZV9kZXZfc2V0X2ZlYXR1cmVzKGRl diwgZmVhdHVyZXMpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2ZHVzZV92ZHBhX3NldF9jb25m aWdfY2Ioc3RydWN0IHZkcGFfZGV2aWNlICp2ZHBhLAo+ICsJCQkJICBzdHJ1Y3QgdmRwYV9jYWxs YmFjayAqY2IpCj4gK3sKPiArCS8qIFdlIGRvbid0IHN1cHBvcnQgY29uZmlnIGludGVycnVwdCAq LwoKCklmIGl0J3Mgbm90IGhhcmQsIGxldCdzIGFkZCB0aGlzLiBPdGhlcndpc2Ugd2UgbmVlZCBh IHBlciBkZXZpY2UgZmVhdHVyZSAKYmxhY2tsaXN0IHRvIGZpbHRlciBvdXQgYWxsIGZlYXR1cmVz IHRoYXQgZGVwZW5kcyBvbiBjb25maWcgaW50ZXJydXB0LgoKCj4gK30KPiArCj4gK3N0YXRpYyB1 MTYgdmR1c2VfdmRwYV9nZXRfdnFfbnVtX21heChzdHJ1Y3QgdmRwYV9kZXZpY2UgKnZkcGEpCj4g K3sKPiArCXN0cnVjdCB2ZHVzZV9kZXYgKmRldiA9IHZkcGFfdG9fdmR1c2UodmRwYSk7Cj4gKwo+ ICsJcmV0dXJuIGRldi0+dnFfc2l6ZV9tYXg7Cj4gK30KPiArCj4gK3N0YXRpYyB1MzIgdmR1c2Vf dmRwYV9nZXRfZGV2aWNlX2lkKHN0cnVjdCB2ZHBhX2RldmljZSAqdmRwYSkKPiArewo+ICsJc3Ry dWN0IHZkdXNlX2RldiAqZGV2ID0gdmRwYV90b192ZHVzZSh2ZHBhKTsKPiArCj4gKwlyZXR1cm4g ZGV2LT5kZXZpY2VfaWQ7Cj4gK30KPiArCj4gK3N0YXRpYyB1MzIgdmR1c2VfdmRwYV9nZXRfdmVu ZG9yX2lkKHN0cnVjdCB2ZHBhX2RldmljZSAqdmRwYSkKPiArewo+ICsJc3RydWN0IHZkdXNlX2Rl diAqZGV2ID0gdmRwYV90b192ZHVzZSh2ZHBhKTsKPiArCj4gKwlyZXR1cm4gZGV2LT52ZW5kb3Jf aWQ7Cj4gK30KPiArCj4gK3N0YXRpYyB1OCB2ZHVzZV92ZHBhX2dldF9zdGF0dXMoc3RydWN0IHZk cGFfZGV2aWNlICp2ZHBhKQo+ICt7Cj4gKwlzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYgPSB2ZHBhX3Rv X3ZkdXNlKHZkcGEpOwo+ICsKPiArCXJldHVybiB2ZHVzZV9kZXZfZ2V0X3N0YXR1cyhkZXYpOwo+ ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2ZHVzZV92ZHBhX3NldF9zdGF0dXMoc3RydWN0IHZkcGFf ZGV2aWNlICp2ZHBhLCB1OCBzdGF0dXMpCj4gK3sKPiArCXN0cnVjdCB2ZHVzZV9kZXYgKmRldiA9 IHZkcGFfdG9fdmR1c2UodmRwYSk7Cj4gKwo+ICsJaWYgKHN0YXR1cyA9PSAwKQo+ICsJCXZkdXNl X2Rldl9yZXNldChkZXYpOwo+ICsJZWxzZQo+ICsJCXZkdXNlX2Rldl91cGRhdGVfaW90bGIoZGV2 LCAwVUxMLCAwVUxMIC0gMSk7CgoKQW55IHJlYXNvbiBmb3Igc3VjaCBJT1RMQiBpbnZhbGlkYXRp b24gaGVyZT8KCgo+ICsKPiArCXZkdXNlX2Rldl9zZXRfc3RhdHVzKGRldiwgc3RhdHVzKTsKPiAr fQo+ICsKPiArc3RhdGljIHZvaWQgdmR1c2VfdmRwYV9nZXRfY29uZmlnKHN0cnVjdCB2ZHBhX2Rl dmljZSAqdmRwYSwgdW5zaWduZWQgaW50IG9mZnNldCwKPiArCQkJICAgICB2b2lkICpidWYsIHVu c2lnbmVkIGludCBsZW4pCj4gK3sKPiArCXN0cnVjdCB2ZHVzZV9kZXYgKmRldiA9IHZkcGFfdG9f dmR1c2UodmRwYSk7Cj4gKwo+ICsJdmR1c2VfZGV2X2dldF9jb25maWcoZGV2LCBvZmZzZXQsIGJ1 ZiwgbGVuKTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgdmR1c2VfdmRwYV9zZXRfY29uZmlnKHN0 cnVjdCB2ZHBhX2RldmljZSAqdmRwYSwgdW5zaWduZWQgaW50IG9mZnNldCwKPiArCQkJY29uc3Qg dm9pZCAqYnVmLCB1bnNpZ25lZCBpbnQgbGVuKQo+ICt7Cj4gKwlzdHJ1Y3QgdmR1c2VfZGV2ICpk ZXYgPSB2ZHBhX3RvX3ZkdXNlKHZkcGEpOwo+ICsKPiArCXZkdXNlX2Rldl9zZXRfY29uZmlnKGRl diwgb2Zmc2V0LCBidWYsIGxlbik7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgdmR1c2VfdmRwYV9z ZXRfbWFwKHN0cnVjdCB2ZHBhX2RldmljZSAqdmRwYSwKPiArCQkJCXN0cnVjdCB2aG9zdF9pb3Rs YiAqaW90bGIpCj4gK3sKPiArCXN0cnVjdCB2ZHVzZV9kZXYgKmRldiA9IHZkcGFfdG9fdmR1c2Uo dmRwYSk7Cj4gKwlzdHJ1Y3Qgdmhvc3RfaW90bGJfbWFwICptYXA7Cj4gKwlzdHJ1Y3Qgdmhvc3Rf aW90bGJfZmlsZSAqaW90bGJfZmlsZTsKPiArCXU2NCBzdGFydCA9IDBVTEwsIGxhc3QgPSAwVUxM IC0gMTsKPiArCWludCByZXQgPSAwOwo+ICsKPiArCXZkdXNlX2lvdGxiX2RlbF9yYW5nZShkZXYs IHN0YXJ0LCBsYXN0KTsKPiArCj4gKwlmb3IgKG1hcCA9IHZob3N0X2lvdGxiX2l0cmVlX2ZpcnN0 KGlvdGxiLCBzdGFydCwgbGFzdCk7IG1hcDsKPiArCQltYXAgPSB2aG9zdF9pb3RsYl9pdHJlZV9u ZXh0KG1hcCwgc3RhcnQsIGxhc3QpKSB7Cj4gKwkJaWYgKCFtYXAtPm9wYXF1ZSkKPiArCQkJY29u dGludWU7CgoKV2hhdCB3aWxsIGhhcHBlbiBpZiB3ZSBzaW1wbHkgYWNjZXB0IE5VTEwgb3BhcXVl IGhlcmU/CgoKPiArCj4gKwkJaW90bGJfZmlsZSA9IChzdHJ1Y3Qgdmhvc3RfaW90bGJfZmlsZSAq KW1hcC0+b3BhcXVlOwo+ICsJCXJldCA9IHZkdXNlX2lvdGxiX2FkZF9yYW5nZShkZXYsIG1hcC0+ c3RhcnQsIG1hcC0+bGFzdCwKPiArCQkJCQkgICAgbWFwLT5hZGRyLCBtYXAtPnBlcm0sCj4gKwkJ CQkJICAgIGlvdGxiX2ZpbGUtPmZpbGUsCj4gKwkJCQkJICAgIGlvdGxiX2ZpbGUtPm9mZnNldCk7 Cj4gKwkJaWYgKHJldCkKPiArCQkJYnJlYWs7Cj4gKwl9Cj4gKwl2ZHVzZV9kZXZfdXBkYXRlX2lv dGxiKGRldiwgc3RhcnQsIGxhc3QpOwo+ICsKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0 YXRpYyB2b2lkIHZkdXNlX3ZkcGFfZnJlZShzdHJ1Y3QgdmRwYV9kZXZpY2UgKnZkcGEpCj4gK3sK PiArCXN0cnVjdCB2ZHVzZV9kZXYgKmRldiA9IHZkcGFfdG9fdmR1c2UodmRwYSk7Cj4gKwo+ICsJ V0FSTl9PTighbGlzdF9lbXB0eSgmZGV2LT5zZW5kX2xpc3QpKTsKPiArCVdBUk5fT04oIWxpc3Rf ZW1wdHkoJmRldi0+cmVjdl9saXN0KSk7Cj4gKwlkZXYtPnZkZXYgPSBOVUxMOwo+ICt9Cj4gKwo+ ICtzdGF0aWMgY29uc3Qgc3RydWN0IHZkcGFfY29uZmlnX29wcyB2ZHVzZV92ZHBhX2NvbmZpZ19v cHMgPSB7Cj4gKwkuc2V0X3ZxX2FkZHJlc3MJCT0gdmR1c2VfdmRwYV9zZXRfdnFfYWRkcmVzcywK PiArCS5raWNrX3ZxCQk9IHZkdXNlX3ZkcGFfa2lja192cSwKPiArCS5zZXRfdnFfY2IJCT0gdmR1 c2VfdmRwYV9zZXRfdnFfY2IsCj4gKwkuc2V0X3ZxX251bSAgICAgICAgICAgICA9IHZkdXNlX3Zk cGFfc2V0X3ZxX251bSwKPiArCS5zZXRfdnFfcmVhZHkJCT0gdmR1c2VfdmRwYV9zZXRfdnFfcmVh ZHksCj4gKwkuZ2V0X3ZxX3JlYWR5CQk9IHZkdXNlX3ZkcGFfZ2V0X3ZxX3JlYWR5LAo+ICsJLnNl dF92cV9zdGF0ZQkJPSB2ZHVzZV92ZHBhX3NldF92cV9zdGF0ZSwKPiArCS5nZXRfdnFfc3RhdGUJ CT0gdmR1c2VfdmRwYV9nZXRfdnFfc3RhdGUsCj4gKwkuZ2V0X3ZxX2FsaWduCQk9IHZkdXNlX3Zk cGFfZ2V0X3ZxX2FsaWduLAo+ICsJLmdldF9mZWF0dXJlcwkJPSB2ZHVzZV92ZHBhX2dldF9mZWF0 dXJlcywKPiArCS5zZXRfZmVhdHVyZXMJCT0gdmR1c2VfdmRwYV9zZXRfZmVhdHVyZXMsCj4gKwku c2V0X2NvbmZpZ19jYgkJPSB2ZHVzZV92ZHBhX3NldF9jb25maWdfY2IsCj4gKwkuZ2V0X3ZxX251 bV9tYXgJCT0gdmR1c2VfdmRwYV9nZXRfdnFfbnVtX21heCwKPiArCS5nZXRfZGV2aWNlX2lkCQk9 IHZkdXNlX3ZkcGFfZ2V0X2RldmljZV9pZCwKPiArCS5nZXRfdmVuZG9yX2lkCQk9IHZkdXNlX3Zk cGFfZ2V0X3ZlbmRvcl9pZCwKPiArCS5nZXRfc3RhdHVzCQk9IHZkdXNlX3ZkcGFfZ2V0X3N0YXR1 cywKPiArCS5zZXRfc3RhdHVzCQk9IHZkdXNlX3ZkcGFfc2V0X3N0YXR1cywKPiArCS5nZXRfY29u ZmlnCQk9IHZkdXNlX3ZkcGFfZ2V0X2NvbmZpZywKPiArCS5zZXRfY29uZmlnCQk9IHZkdXNlX3Zk cGFfc2V0X2NvbmZpZywKPiArCS5zZXRfbWFwCQk9IHZkdXNlX3ZkcGFfc2V0X21hcCwKPiArCS5m cmVlCQkJPSB2ZHVzZV92ZHBhX2ZyZWUsCj4gK307Cj4gKwo+ICtzdGF0aWMgZG1hX2FkZHJfdCB2 ZHVzZV9kZXZfbWFwX3BhZ2Uoc3RydWN0IGRldmljZSAqZGV2LCBzdHJ1Y3QgcGFnZSAqcGFnZSwK PiArCQkJCQl1bnNpZ25lZCBsb25nIG9mZnNldCwgc2l6ZV90IHNpemUsCj4gKwkJCQkJZW51bSBk bWFfZGF0YV9kaXJlY3Rpb24gZGlyLAo+ICsJCQkJCXVuc2lnbmVkIGxvbmcgYXR0cnMpCj4gK3sK PiArCXN0cnVjdCB2ZHVzZV9kZXYgKnZkZXYgPSBkZXZfdG9fdmR1c2UoZGV2KTsKPiArCXN0cnVj dCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluID0gdmRldi0+ZG9tYWluOwo+ICsKPiArCWlmIChh dG9taWNfeGNoZygmdmRldi0+Ym91bmNlX21hcCwgMSkgPT0gMCAmJgo+ICsJCXZkdXNlX2lvdGxi X2FkZF9yYW5nZSh2ZGV2LCAwLCBkb21haW4tPmJvdW5jZV9zaXplIC0gMSwKPiArCQkJCSAgICAg IDAsIFZEVVNFX0FDQ0VTU19SVywKCgpJcyB0aGlzIHNhZmUgdG8gdXNlIFZEVVNFX0FDQ0VTU19S VyBoZXJlLCBjb25zaWRlciB3ZSBtaWdodCBoYXZlIGRldmljZSAKcmVhZG9ubHkgbWFwcGluZ3Mu CgoKPiArCQkJCSAgICAgIHZkdXNlX2RvbWFpbl9maWxlKGRvbWFpbiksCj4gKwkJCQkgICAgICB2 ZHVzZV9kb21haW5fZ2V0X29mZnNldChkb21haW4sIDApKSkgewo+ICsJCWF0b21pY19zZXQoJnZk ZXYtPmJvdW5jZV9tYXAsIDApOwo+ICsJCXJldHVybiBETUFfTUFQUElOR19FUlJPUjsKPiArCX0K PiArCj4gKwlyZXR1cm4gdmR1c2VfZG9tYWluX21hcF9wYWdlKGRvbWFpbiwgcGFnZSwgb2Zmc2V0 LCBzaXplLCBkaXIsIGF0dHJzKTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgdmR1c2VfZGV2X3Vu bWFwX3BhZ2Uoc3RydWN0IGRldmljZSAqZGV2LCBkbWFfYWRkcl90IGRtYV9hZGRyLAo+ICsJCQkJ c2l6ZV90IHNpemUsIGVudW0gZG1hX2RhdGFfZGlyZWN0aW9uIGRpciwKPiArCQkJCXVuc2lnbmVk IGxvbmcgYXR0cnMpCj4gK3sKPiArCXN0cnVjdCB2ZHVzZV9kZXYgKnZkZXYgPSBkZXZfdG9fdmR1 c2UoZGV2KTsKPiArCXN0cnVjdCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluID0gdmRldi0+ZG9t YWluOwo+ICsKPiArCXJldHVybiB2ZHVzZV9kb21haW5fdW5tYXBfcGFnZShkb21haW4sIGRtYV9h ZGRyLCBzaXplLCBkaXIsIGF0dHJzKTsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgKnZkdXNlX2Rl dl9hbGxvY19jb2hlcmVudChzdHJ1Y3QgZGV2aWNlICpkZXYsIHNpemVfdCBzaXplLAo+ICsJCQkJ CWRtYV9hZGRyX3QgKmRtYV9hZGRyLCBnZnBfdCBmbGFnLAo+ICsJCQkJCXVuc2lnbmVkIGxvbmcg YXR0cnMpCj4gK3sKPiArCXN0cnVjdCB2ZHVzZV9kZXYgKnZkZXYgPSBkZXZfdG9fdmR1c2UoZGV2 KTsKPiArCXN0cnVjdCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluID0gdmRldi0+ZG9tYWluOwo+ ICsJdW5zaWduZWQgbG9uZyBpb3ZhOwo+ICsJdm9pZCAqYWRkcjsKPiArCj4gKwkqZG1hX2FkZHIg PSBETUFfTUFQUElOR19FUlJPUjsKPiArCWFkZHIgPSB2ZHVzZV9kb21haW5fYWxsb2NfY29oZXJl bnQoZG9tYWluLCBzaXplLAo+ICsJCQkJKGRtYV9hZGRyX3QgKikmaW92YSwgZmxhZywgYXR0cnMp Owo+ICsJaWYgKCFhZGRyKQo+ICsJCXJldHVybiBOVUxMOwo+ICsKPiArCWlmICh2ZHVzZV9pb3Rs Yl9hZGRfcmFuZ2UodmRldiwgaW92YSwgaW92YSArIHNpemUgLSAxLAo+ICsJCQkJICBpb3ZhLCBW RFVTRV9BQ0NFU1NfUlcsCj4gKwkJCQkgIHZkdXNlX2RvbWFpbl9maWxlKGRvbWFpbiksCj4gKwkJ CQkgIHZkdXNlX2RvbWFpbl9nZXRfb2Zmc2V0KGRvbWFpbiwgaW92YSkpKSB7Cj4gKwkJdmR1c2Vf ZG9tYWluX2ZyZWVfY29oZXJlbnQoZG9tYWluLCBzaXplLCBhZGRyLCBpb3ZhLCBhdHRycyk7Cj4g KwkJcmV0dXJuIE5VTEw7Cj4gKwl9Cj4gKwkqZG1hX2FkZHIgPSAoZG1hX2FkZHJfdClpb3ZhOwo+ ICsKPiArCXJldHVybiBhZGRyOwo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2ZHVzZV9kZXZfZnJl ZV9jb2hlcmVudChzdHJ1Y3QgZGV2aWNlICpkZXYsIHNpemVfdCBzaXplLAo+ICsJCQkJCXZvaWQg KnZhZGRyLCBkbWFfYWRkcl90IGRtYV9hZGRyLAo+ICsJCQkJCXVuc2lnbmVkIGxvbmcgYXR0cnMp Cj4gK3sKPiArCXN0cnVjdCB2ZHVzZV9kZXYgKnZkZXYgPSBkZXZfdG9fdmR1c2UoZGV2KTsKPiAr CXN0cnVjdCB2ZHVzZV9pb3ZhX2RvbWFpbiAqZG9tYWluID0gdmRldi0+ZG9tYWluOwo+ICsJdW5z aWduZWQgbG9uZyBzdGFydCA9ICh1bnNpZ25lZCBsb25nKWRtYV9hZGRyOwo+ICsJdW5zaWduZWQg bG9uZyBsYXN0ID0gc3RhcnQgKyBzaXplIC0gMTsKPiArCj4gKwl2ZHVzZV9pb3RsYl9kZWxfcmFu Z2UodmRldiwgc3RhcnQsIGxhc3QpOwo+ICsJdmR1c2VfZGV2X3VwZGF0ZV9pb3RsYih2ZGV2LCBz dGFydCwgbGFzdCk7Cj4gKwl2ZHVzZV9kb21haW5fZnJlZV9jb2hlcmVudChkb21haW4sIHNpemUs IHZhZGRyLCBkbWFfYWRkciwgYXR0cnMpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgY29uc3Qgc3RydWN0 IGRtYV9tYXBfb3BzIHZkdXNlX2Rldl9kbWFfb3BzID0gewo+ICsJLm1hcF9wYWdlID0gdmR1c2Vf ZGV2X21hcF9wYWdlLAo+ICsJLnVubWFwX3BhZ2UgPSB2ZHVzZV9kZXZfdW5tYXBfcGFnZSwKPiAr CS5hbGxvYyA9IHZkdXNlX2Rldl9hbGxvY19jb2hlcmVudCwKPiArCS5mcmVlID0gdmR1c2VfZGV2 X2ZyZWVfY29oZXJlbnQsCj4gK307Cj4gKwo+ICtzdGF0aWMgdW5zaWduZWQgaW50IHBlcm1fdG9f ZmlsZV9mbGFncyh1OCBwZXJtKQo+ICt7Cj4gKwl1bnNpZ25lZCBpbnQgZmxhZ3MgPSAwOwo+ICsK PiArCXN3aXRjaCAocGVybSkgewo+ICsJY2FzZSBWRFVTRV9BQ0NFU1NfV086Cj4gKwkJZmxhZ3Mg fD0gT19XUk9OTFk7Cj4gKwkJYnJlYWs7Cj4gKwljYXNlIFZEVVNFX0FDQ0VTU19STzoKPiArCQlm bGFncyB8PSBPX1JET05MWTsKPiArCQlicmVhazsKPiArCWNhc2UgVkRVU0VfQUNDRVNTX1JXOgo+ ICsJCWZsYWdzIHw9IE9fUkRXUjsKPiArCQlicmVhazsKPiArCWRlZmF1bHQ6Cj4gKwkJV0FSTigx LCAiaW52YWxpZGF0ZSB2aG9zdCBJT1RMQiBwZXJtaXNzaW9uXG4iKTsKPiArCQlicmVhazsKPiAr CX0KPiArCj4gKwlyZXR1cm4gZmxhZ3M7Cj4gK30KPiArCj4gK3N0YXRpYyBsb25nIHZkdXNlX2Rl dl9pb2N0bChzdHJ1Y3QgZmlsZSAqZmlsZSwgdW5zaWduZWQgaW50IGNtZCwKPiArCQkJdW5zaWdu ZWQgbG9uZyBhcmcpCj4gK3sKPiArCXN0cnVjdCB2ZHVzZV9kZXYgKmRldiA9IGZpbGUtPnByaXZh dGVfZGF0YTsKPiArCXZvaWQgX191c2VyICphcmdwID0gKHZvaWQgX191c2VyICopYXJnOwo+ICsJ aW50IHJldDsKPiArCj4gKwltdXRleF9sb2NrKCZkZXYtPmxvY2spOwo+ICsJc3dpdGNoIChjbWQp IHsKPiArCWNhc2UgVkRVU0VfSU9UTEJfR0VUX0ZEOiB7Cj4gKwkJc3RydWN0IHZkdXNlX2lvdGxi X2VudHJ5IGVudHJ5Owo+ICsJCXN0cnVjdCB2aG9zdF9pb3RsYl9tYXAgKm1hcDsKPiArCQlzdHJ1 Y3Qgdmhvc3RfaW90bGJfZmlsZSAqaW90bGJfZmlsZTsKPiArCQlzdHJ1Y3QgZmlsZSAqZiA9IE5V TEw7Cj4gKwo+ICsJCXJldCA9IC1FRkFVTFQ7Cj4gKwkJaWYgKGNvcHlfZnJvbV91c2VyKCZlbnRy eSwgYXJncCwgc2l6ZW9mKGVudHJ5KSkpCj4gKwkJCWJyZWFrOwo+ICsKPiArCQlzcGluX2xvY2so JmRldi0+aW9tbXVfbG9jayk7Cj4gKwkJbWFwID0gdmhvc3RfaW90bGJfaXRyZWVfZmlyc3QoZGV2 LT5pb21tdSwgZW50cnkuc3RhcnQsCj4gKwkJCQkJICAgICAgZW50cnkubGFzdCk7Cj4gKwkJaWYg KG1hcCkgewo+ICsJCQlpb3RsYl9maWxlID0gKHN0cnVjdCB2aG9zdF9pb3RsYl9maWxlICopbWFw LT5vcGFxdWU7Cj4gKwkJCWYgPSBnZXRfZmlsZShpb3RsYl9maWxlLT5maWxlKTsKPiArCQkJZW50 cnkub2Zmc2V0ID0gaW90bGJfZmlsZS0+b2Zmc2V0Owo+ICsJCQllbnRyeS5zdGFydCA9IG1hcC0+ c3RhcnQ7Cj4gKwkJCWVudHJ5Lmxhc3QgPSBtYXAtPmxhc3Q7Cj4gKwkJCWVudHJ5LnBlcm0gPSBt YXAtPnBlcm07Cj4gKwkJfQo+ICsJCXNwaW5fdW5sb2NrKCZkZXYtPmlvbW11X2xvY2spOwo+ICsJ CWlmICghZikgewo+ICsJCQlyZXQgPSAtRUlOVkFMOwo+ICsJCQlicmVhazsKPiArCQl9Cj4gKwkJ aWYgKGNvcHlfdG9fdXNlcihhcmdwLCAmZW50cnksIHNpemVvZihlbnRyeSkpKSB7Cj4gKwkJCWZw dXQoZik7Cj4gKwkJCXJldCA9IC1FRkFVTFQ7Cj4gKwkJCWJyZWFrOwo+ICsJCX0KPiArCQlyZXQg PSBnZXRfdW51c2VkX2ZkX2ZsYWdzKHBlcm1fdG9fZmlsZV9mbGFncyhlbnRyeS5wZXJtKSk7Cj4g KwkJaWYgKHJldCA8IDApIHsKPiArCQkJZnB1dChmKTsKPiArCQkJYnJlYWs7Cj4gKwkJfQo+ICsJ CWZkX2luc3RhbGwocmV0LCBmKTsKPiArCQlicmVhazsKPiArCX0KPiArCWNhc2UgVkRVU0VfVlFf U0VUVVBfS0lDS0ZEOiB7Cj4gKwkJc3RydWN0IHZkdXNlX3ZxX2V2ZW50ZmQgZXZlbnRmZDsKPiAr Cj4gKwkJcmV0ID0gLUVGQVVMVDsKPiArCQlpZiAoY29weV9mcm9tX3VzZXIoJmV2ZW50ZmQsIGFy Z3AsIHNpemVvZihldmVudGZkKSkpCj4gKwkJCWJyZWFrOwo+ICsKPiArCQlyZXQgPSB2ZHVzZV9r aWNrZmRfc2V0dXAoZGV2LCAmZXZlbnRmZCk7Cj4gKwkJYnJlYWs7Cj4gKwl9Cj4gKwljYXNlIFZE VVNFX1ZRX1NFVFVQX0lSUUZEOiB7Cj4gKwkJc3RydWN0IHZkdXNlX3ZxX2V2ZW50ZmQgZXZlbnRm ZDsKPiArCj4gKwkJcmV0ID0gLUVGQVVMVDsKPiArCQlpZiAoY29weV9mcm9tX3VzZXIoJmV2ZW50 ZmQsIGFyZ3AsIHNpemVvZihldmVudGZkKSkpCj4gKwkJCWJyZWFrOwo+ICsKPiArCQlyZXQgPSB2 ZHVzZV92aXJxZmRfc2V0dXAoZGV2LCAmZXZlbnRmZCk7Cj4gKwkJYnJlYWs7Cj4gKwl9Cj4gKwl9 Cj4gKwltdXRleF91bmxvY2soJmRldi0+bG9jayk7Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ ICsKPiArc3RhdGljIGludCB2ZHVzZV9kZXZfcmVsZWFzZShzdHJ1Y3QgaW5vZGUgKmlub2RlLCBz dHJ1Y3QgZmlsZSAqZmlsZSkKPiArewo+ICsJc3RydWN0IHZkdXNlX2RldiAqZGV2ID0gZmlsZS0+ cHJpdmF0ZV9kYXRhOwo+ICsKPiArCXZkdXNlX2tpY2tmZF9yZWxlYXNlKGRldik7Cj4gKwl2ZHVz ZV92aXJxZmRfcmVsZWFzZShkZXYpOwo+ICsJZGV2LT5jb25uZWN0ZWQgPSBmYWxzZTsKPiArCj4g KwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCBmaWxlX29wZXJhdGlv bnMgdmR1c2VfZGV2X2ZvcHMgPSB7Cj4gKwkub3duZXIJCT0gVEhJU19NT0RVTEUsCj4gKwkucmVs ZWFzZQk9IHZkdXNlX2Rldl9yZWxlYXNlLAo+ICsJLnJlYWRfaXRlcgk9IHZkdXNlX2Rldl9yZWFk X2l0ZXIsCj4gKwkud3JpdGVfaXRlcgk9IHZkdXNlX2Rldl93cml0ZV9pdGVyLAo+ICsJLnBvbGwJ CT0gdmR1c2VfZGV2X3BvbGwsCj4gKwkudW5sb2NrZWRfaW9jdGwJPSB2ZHVzZV9kZXZfaW9jdGws Cj4gKwkuY29tcGF0X2lvY3RsCT0gY29tcGF0X3B0cl9pb2N0bCwKPiArCS5sbHNlZWsJCT0gbm9v cF9sbHNlZWssCj4gK307Cj4gKwo+ICtzdGF0aWMgc3RydWN0IHZkdXNlX2RldiAqdmR1c2VfZGV2 X2NyZWF0ZSh2b2lkKQo+ICt7Cj4gKwlzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYgPSBremFsbG9jKHNp emVvZigqZGV2KSwgR0ZQX0tFUk5FTCk7Cj4gKwo+ICsJaWYgKCFkZXYpCj4gKwkJcmV0dXJuIE5V TEw7Cj4gKwo+ICsJZGV2LT5pb21tdSA9IHZob3N0X2lvdGxiX2FsbG9jKDIwNDgsIDApOwoKCklz IDIwNDggc3VmZmljaWVudCBoZXJlPwoKCj4gKwlpZiAoIWRldi0+aW9tbXUpIHsKPiArCQlrZnJl ZShkZXYpOwo+ICsJCXJldHVybiBOVUxMOwo+ICsJfQo+ICsKPiArCW11dGV4X2luaXQoJmRldi0+ bG9jayk7Cj4gKwlzcGluX2xvY2tfaW5pdCgmZGV2LT5tc2dfbG9jayk7Cj4gKwlJTklUX0xJU1Rf SEVBRCgmZGV2LT5zZW5kX2xpc3QpOwo+ICsJSU5JVF9MSVNUX0hFQUQoJmRldi0+cmVjdl9saXN0 KTsKPiArCWF0b21pYzY0X3NldCgmZGV2LT5tc2dfdW5pcXVlLCAwKTsKPiArCXNwaW5fbG9ja19p bml0KCZkZXYtPmlvbW11X2xvY2spOwo+ICsJYXRvbWljX3NldCgmZGV2LT5ib3VuY2VfbWFwLCAw KTsKPiArCj4gKwlpbml0X3dhaXRxdWV1ZV9oZWFkKCZkZXYtPndhaXRxKTsKPiArCj4gKwlyZXR1 cm4gZGV2Owo+ICt9Cj4gKwo+ICtzdGF0aWMgdm9pZCB2ZHVzZV9kZXZfZGVzdHJveShzdHJ1Y3Qg dmR1c2VfZGV2ICpkZXYpCj4gK3sKPiArCXZob3N0X2lvdGxiX2ZyZWUoZGV2LT5pb21tdSk7Cj4g KwltdXRleF9kZXN0cm95KCZkZXYtPmxvY2spOwo+ICsJa2ZyZWUoZGV2KTsKPiArfQo+ICsKPiAr c3RhdGljIHN0cnVjdCB2ZHVzZV9kZXYgKnZkdXNlX2ZpbmRfZGV2KHUzMiBpZCkKPiArewo+ICsJ c3RydWN0IHZkdXNlX2RldiAqdG1wLCAqZGV2ID0gTlVMTDsKPiArCj4gKwlsaXN0X2Zvcl9lYWNo X2VudHJ5KHRtcCwgJnZkdXNlX2RldnMsIGxpc3QpIHsKPiArCQlpZiAodG1wLT5pZCA9PSBpZCkg ewo+ICsJCQlkZXYgPSB0bXA7Cj4gKwkJCWJyZWFrOwo+ICsJCX0KPiArCX0KPiArCXJldHVybiBk ZXY7Cj4gK30KPiArCj4gK3N0YXRpYyBpbnQgdmR1c2VfZGVzdHJveV9kZXYodTMyIGlkKQo+ICt7 Cj4gKwlzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYgPSB2ZHVzZV9maW5kX2RldihpZCk7Cj4gKwo+ICsJ aWYgKCFkZXYpCj4gKwkJcmV0dXJuIC1FSU5WQUw7Cj4gKwo+ICsJaWYgKGRldi0+dmRldiB8fCBk ZXYtPmNvbm5lY3RlZCkKPiArCQlyZXR1cm4gLUVCVVNZOwo+ICsKPiArCWxpc3RfZGVsKCZkZXYt Pmxpc3QpOwo+ICsJa2ZyZWUoZGV2LT52cXMpOwo+ICsJdmR1c2VfZG9tYWluX2Rlc3Ryb3koZGV2 LT5kb21haW4pOwo+ICsJdmR1c2VfZGV2X2Rlc3Ryb3koZGV2KTsKPiArCj4gKwlyZXR1cm4gMDsK PiArfQo+ICsKPiArc3RhdGljIGludCB2ZHVzZV9jcmVhdGVfZGV2KHN0cnVjdCB2ZHVzZV9kZXZf Y29uZmlnICpjb25maWcpCj4gK3sKPiArCWludCBpLCBmZDsKPiArCXN0cnVjdCB2ZHVzZV9kZXYg KmRldjsKPiArCWNoYXIgbmFtZVs2NF07Cj4gKwo+ICsJaWYgKHZkdXNlX2ZpbmRfZGV2KGNvbmZp Zy0+aWQpKQo+ICsJCXJldHVybiAtRUVYSVNUOwo+ICsKPiArCWRldiA9IHZkdXNlX2Rldl9jcmVh dGUoKTsKPiArCWlmICghZGV2KQo+ICsJCXJldHVybiAtRU5PTUVNOwo+ICsKPiArCWRldi0+aWQg PSBjb25maWctPmlkOwo+ICsJZGV2LT5kZXZpY2VfaWQgPSBjb25maWctPmRldmljZV9pZDsKPiAr CWRldi0+dmVuZG9yX2lkID0gY29uZmlnLT52ZW5kb3JfaWQ7Cj4gKwlkZXYtPmRvbWFpbiA9IHZk dXNlX2RvbWFpbl9jcmVhdGUoY29uZmlnLT5ib3VuY2Vfc2l6ZSk7CgoKRG8gd2UgbmVlZCBhIHVw cGVyIGxpbWl0IG9mIGJvdW5jZV9zaXplPwoKCj4gKwlpZiAoIWRldi0+ZG9tYWluKQo+ICsJCWdv dG8gZXJyX2RvbWFpbjsKPiArCj4gKwlkZXYtPnZxX2FsaWduID0gY29uZmlnLT52cV9hbGlnbjsK PiArCWRldi0+dnFfc2l6ZV9tYXggPSBjb25maWctPnZxX3NpemVfbWF4Owo+ICsJZGV2LT52cV9u dW0gPSBjb25maWctPnZxX251bTsKPiArCWRldi0+dnFzID0ga2NhbGxvYyhkZXYtPnZxX251bSwg c2l6ZW9mKCpkZXYtPnZxcyksIEdGUF9LRVJORUwpOwo+ICsJaWYgKCFkZXYtPnZxcykKPiArCQln b3RvIGVycl92cXM7Cj4gKwo+ICsJZm9yIChpID0gMDsgaSA8IGRldi0+dnFfbnVtOyBpKyspIHsK PiArCQlkZXYtPnZxc1tpXS5pbmRleCA9IGk7Cj4gKwkJc3Bpbl9sb2NrX2luaXQoJmRldi0+dnFz W2ldLmtpY2tfbG9jayk7Cj4gKwkJc3Bpbl9sb2NrX2luaXQoJmRldi0+dnFzW2ldLmlycV9sb2Nr KTsKPiArCX0KPiArCj4gKwlzbnByaW50ZihuYW1lLCBzaXplb2YobmFtZSksICJbdmR1c2UtZGV2 OiV1XSIsIGNvbmZpZy0+aWQpOwo+ICsJZmQgPSBhbm9uX2lub2RlX2dldGZkKG5hbWUsICZ2ZHVz ZV9kZXZfZm9wcywgZGV2LCBPX1JEV1IgfCBPX0NMT0VYRUMpOwoKCkFueSByZWFzb24gZm9yIGNs b3Npbmcgb24gZXhlYyBoZXJlPwoKCj4gKwlpZiAoZmQgPCAwKQo+ICsJCWdvdG8gZXJyX2ZkOwo+ ICsKPiArCWRldi0+Y29ubmVjdGVkID0gdHJ1ZTsKPiArCWxpc3RfYWRkKCZkZXYtPmxpc3QsICZ2 ZHVzZV9kZXZzKTsKPiArCj4gKwlyZXR1cm4gZmQ7Cj4gK2Vycl9mZDoKPiArCWtmcmVlKGRldi0+ dnFzKTsKPiArZXJyX3ZxczoKPiArCXZkdXNlX2RvbWFpbl9kZXN0cm95KGRldi0+ZG9tYWluKTsK PiArZXJyX2RvbWFpbjoKPiArCXZkdXNlX2Rldl9kZXN0cm95KGRldik7Cj4gKwlyZXR1cm4gZmQ7 Cj4gK30KPiArCj4gK3N0YXRpYyBsb25nIHZkdXNlX2lvY3RsKHN0cnVjdCBmaWxlICpmaWxlLCB1 bnNpZ25lZCBpbnQgY21kLAo+ICsJCQl1bnNpZ25lZCBsb25nIGFyZykKPiArewo+ICsJaW50IHJl dDsKPiArCXZvaWQgX191c2VyICphcmdwID0gKHZvaWQgX191c2VyICopYXJnOwo+ICsKPiArCW11 dGV4X2xvY2soJnZkdXNlX2xvY2spOwo+ICsJc3dpdGNoIChjbWQpIHsKPiArCWNhc2UgVkRVU0Vf Q1JFQVRFX0RFVjogewo+ICsJCXN0cnVjdCB2ZHVzZV9kZXZfY29uZmlnIGNvbmZpZzsKPiArCj4g KwkJcmV0ID0gLUVGQVVMVDsKPiArCQlpZiAoY29weV9mcm9tX3VzZXIoJmNvbmZpZywgYXJncCwg c2l6ZW9mKGNvbmZpZykpKQo+ICsJCQlicmVhazsKPiArCj4gKwkJcmV0ID0gdmR1c2VfY3JlYXRl X2RldigmY29uZmlnKTsKPiArCQlicmVhazsKPiArCX0KPiArCWNhc2UgVkRVU0VfREVTVFJPWV9E RVY6Cj4gKwkJcmV0ID0gdmR1c2VfZGVzdHJveV9kZXYoYXJnKTsKPiArCQlicmVhazsKPiArCWRl ZmF1bHQ6Cj4gKwkJcmV0ID0gLUVJTlZBTDsKPiArCQlicmVhazsKPiArCX0KPiArCW11dGV4X3Vu bG9jaygmdmR1c2VfbG9jayk7Cj4gKwo+ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGlj IGNvbnN0IHN0cnVjdCBmaWxlX29wZXJhdGlvbnMgdmR1c2VfZm9wcyA9IHsKPiArCS5vd25lcgkJ PSBUSElTX01PRFVMRSwKPiArCS51bmxvY2tlZF9pb2N0bAk9IHZkdXNlX2lvY3RsLAo+ICsJLmNv bXBhdF9pb2N0bAk9IGNvbXBhdF9wdHJfaW9jdGwsCj4gKwkubGxzZWVrCQk9IG5vb3BfbGxzZWVr LAo+ICt9Owo+ICsKPiArc3RhdGljIHN0cnVjdCBtaXNjZGV2aWNlIHZkdXNlX21pc2MgPSB7Cj4g KwkuZm9wcyA9ICZ2ZHVzZV9mb3BzLAo+ICsJLm1pbm9yID0gTUlTQ19EWU5BTUlDX01JTk9SLAo+ ICsJLm5hbWUgPSAidmR1c2UiLAo+ICt9Owo+ICsKPiArc3RhdGljIHZvaWQgdmR1c2VfcGFyZW50 X3JlbGVhc2Uoc3RydWN0IGRldmljZSAqZGV2KQo+ICt7Cj4gK30KPiArCj4gK3N0YXRpYyBzdHJ1 Y3QgZGV2aWNlIHZkdXNlX3BhcmVudCA9IHsKPiArCS5pbml0X25hbWUgPSAidmR1c2UiLAo+ICsJ LnJlbGVhc2UgPSB2ZHVzZV9wYXJlbnRfcmVsZWFzZSwKPiArfTsKPiArCj4gK3N0YXRpYyBzdHJ1 Y3QgdmRwYV9wYXJlbnRfZGV2IHBhcmVudF9kZXY7Cj4gKwo+ICtzdGF0aWMgaW50IHZkdXNlX2Rl dl9hZGRfdmRwYShzdHJ1Y3QgdmR1c2VfZGV2ICpkZXYsIGNvbnN0IGNoYXIgKm5hbWUpCj4gK3sK PiArCXN0cnVjdCB2ZHVzZV92ZHBhICp2ZGV2ID0gZGV2LT52ZGV2Owo+ICsJaW50IHJldDsKPiAr Cj4gKwlpZiAodmRldikKPiArCQlyZXR1cm4gLUVFWElTVDsKPiArCj4gKwl2ZGV2ID0gdmRwYV9h bGxvY19kZXZpY2Uoc3RydWN0IHZkdXNlX3ZkcGEsIHZkcGEsIE5VTEwsCj4gKwkJCQkgJnZkdXNl X3ZkcGFfY29uZmlnX29wcywKPiArCQkJCSBkZXYtPnZxX251bSwgbmFtZSwgdHJ1ZSk7Cj4gKwlp ZiAoIXZkZXYpCj4gKwkJcmV0dXJuIC1FTk9NRU07Cj4gKwo+ICsJdmRldi0+ZGV2ID0gZGV2Owo+ ICsJdmRldi0+dmRwYS5kZXYuZG1hX21hc2sgPSAmdmRldi0+dmRwYS5kZXYuY29oZXJlbnRfZG1h X21hc2s7Cj4gKwlyZXQgPSBkbWFfc2V0X21hc2tfYW5kX2NvaGVyZW50KCZ2ZGV2LT52ZHBhLmRl diwgRE1BX0JJVF9NQVNLKDY0KSk7Cj4gKwlpZiAocmV0KQo+ICsJCWdvdG8gZXJyOwo+ICsKPiAr CXNldF9kbWFfb3BzKCZ2ZGV2LT52ZHBhLmRldiwgJnZkdXNlX2Rldl9kbWFfb3BzKTsKPiArCXZk ZXYtPnZkcGEuZG1hX2RldiA9ICZ2ZGV2LT52ZHBhLmRldjsKPiArCXZkZXYtPnZkcGEucGRldiA9 ICZwYXJlbnRfZGV2Owo+ICsKPiArCXJldCA9IF92ZHBhX3JlZ2lzdGVyX2RldmljZSgmdmRldi0+ dmRwYSk7Cj4gKwlpZiAocmV0KQo+ICsJCWdvdG8gZXJyOwo+ICsKPiArCWRldi0+dmRldiA9IHZk ZXY7Cj4gKwo+ICsJcmV0dXJuIDA7Cj4gK2VycjoKPiArCXB1dF9kZXZpY2UoJnZkZXYtPnZkcGEu ZGV2KTsKPiArCXJldHVybiByZXQ7Cj4gK30KPiArCj4gK3N0YXRpYyBzdHJ1Y3QgdmRwYV9kZXZp Y2UgKnZkcGFfZGV2X2FkZChzdHJ1Y3QgdmRwYV9wYXJlbnRfZGV2ICpwZGV2LAo+ICsJCQkJCWNv bnN0IGNoYXIgKm5hbWUsIHUzMiBkZXZpY2VfaWQsCj4gKwkJCQkJc3RydWN0IG5sYXR0ciAqKmF0 dHJzKQo+ICt7Cj4gKwl1MzIgdmR1c2VfaWQ7Cj4gKwlzdHJ1Y3QgdmR1c2VfZGV2ICpkZXY7Cj4g KwlpbnQgcmV0ID0gLUVJTlZBTDsKPiArCj4gKwlpZiAoIWF0dHJzW1ZEUEFfQVRUUl9CQUNLRU5E X0lEXSkKPiArCQlyZXR1cm4gRVJSX1BUUigtRUlOVkFMKTsKPiArCj4gKwltdXRleF9sb2NrKCZ2 ZHVzZV9sb2NrKTsKPiArCXZkdXNlX2lkID0gbmxhX2dldF91MzIoYXR0cnNbVkRQQV9BVFRSX0JB Q0tFTkRfSURdKTsKCgpJIHdvbmRlciB3aHkgbm90IHVzaW5nIG5hbWUgaGVyZT8KCkFuZCBpdCBs b29rcyB0byBtZSBpdCB3b3VsZCBiZSBlYXNpZXIgaWYgd2UgY3JlYXRlIGEgY2hhciBkZXZpY2Ug cGVyIAp2ZHVzZS4gVGhpcyBtYWtlcyB0aGUgZGV2aWNlIGFkZHJlc3NpbmcgbW9yZSByb2J1c3Qg dGhhbiBwYXNzaW5nIGlkIApzaWxlbnRseSBhbW9uZyBwcm9jZXNzZXMuCgoKPiArCWRldiA9IHZk dXNlX2ZpbmRfZGV2KHZkdXNlX2lkKTsKPiArCWlmICghZGV2KQo+ICsJCWdvdG8gdW5sb2NrOwo+ ICsKPiArCWlmIChkZXYtPmRldmljZV9pZCAhPSBkZXZpY2VfaWQpCj4gKwkJZ290byB1bmxvY2s7 Cj4gKwo+ICsJcmV0ID0gdmR1c2VfZGV2X2FkZF92ZHBhKGRldiwgbmFtZSk7Cj4gK3VubG9jazoK PiArCW11dGV4X3VubG9jaygmdmR1c2VfbG9jayk7Cj4gKwlpZiAocmV0KQo+ICsJCXJldHVybiBF UlJfUFRSKHJldCk7Cj4gKwo+ICsJcmV0dXJuICZkZXYtPnZkZXYtPnZkcGE7Cj4gK30KPiArCj4g K3N0YXRpYyB2b2lkIHZkcGFfZGV2X2RlbChzdHJ1Y3QgdmRwYV9wYXJlbnRfZGV2ICpwZGV2LCBz dHJ1Y3QgdmRwYV9kZXZpY2UgKmRldikKPiArewo+ICsJX3ZkcGFfdW5yZWdpc3Rlcl9kZXZpY2Uo ZGV2KTsKPiArfQo+ICsKPiArc3RhdGljIGNvbnN0IHN0cnVjdCB2ZHBhX2Rldl9vcHMgdmRwYV9k ZXZfcGFyZW50X29wcyA9IHsKPiArCS5kZXZfYWRkID0gdmRwYV9kZXZfYWRkLAo+ICsJLmRldl9k ZWwgPSB2ZHBhX2Rldl9kZWwKPiArfTsKPiArCj4gK3N0YXRpYyBzdHJ1Y3QgdmlydGlvX2Rldmlj ZV9pZCBpZF90YWJsZVtdID0gewo+ICsJeyBWSVJUSU9fREVWX0FOWV9JRCwgVklSVElPX0RFVl9B TllfSUQgfSwKPiArCXsgMCB9LAo+ICt9Owo+ICsKPiArc3RhdGljIHN0cnVjdCB2ZHBhX3BhcmVu dF9kZXYgcGFyZW50X2RldiA9IHsKPiArCS5kZXZpY2UgPSAmdmR1c2VfcGFyZW50LAo+ICsJLmlk X3RhYmxlID0gaWRfdGFibGUsCj4gKwkub3BzID0gJnZkcGFfZGV2X3BhcmVudF9vcHMsCj4gK307 Cj4gKwo+ICtzdGF0aWMgaW50IHZkdXNlX3BhcmVudGRldl9pbml0KHZvaWQpCj4gK3sKPiArCWlu dCByZXQ7Cj4gKwo+ICsJcmV0ID0gZGV2aWNlX3JlZ2lzdGVyKCZ2ZHVzZV9wYXJlbnQpOwo+ICsJ aWYgKHJldCkKPiArCQlyZXR1cm4gcmV0Owo+ICsKPiArCXJldCA9IHZkcGFfcGFyZW50ZGV2X3Jl Z2lzdGVyKCZwYXJlbnRfZGV2KTsKPiArCWlmIChyZXQpCj4gKwkJZ290byBlcnI7Cj4gKwo+ICsJ cmV0dXJuIDA7Cj4gK2VycjoKPiArCWRldmljZV91bnJlZ2lzdGVyKCZ2ZHVzZV9wYXJlbnQpOwo+ ICsJcmV0dXJuIHJldDsKPiArfQo+ICsKPiArc3RhdGljIHZvaWQgdmR1c2VfcGFyZW50ZGV2X2V4 aXQodm9pZCkKPiArewo+ICsJdmRwYV9wYXJlbnRkZXZfdW5yZWdpc3RlcigmcGFyZW50X2Rldik7 Cj4gKwlkZXZpY2VfdW5yZWdpc3RlcigmdmR1c2VfcGFyZW50KTsKPiArfQo+ICsKPiArc3RhdGlj IGludCB2ZHVzZV9pbml0KHZvaWQpCj4gK3sKPiArCWludCByZXQ7Cj4gKwo+ICsJcmV0ID0gbWlz Y19yZWdpc3RlcigmdmR1c2VfbWlzYyk7Cj4gKwlpZiAocmV0KQo+ICsJCXJldHVybiByZXQ7Cj4g Kwo+ICsJcmV0ID0gLUVOT01FTTsKPiArCXZkdXNlX3ZkcGFfd3EgPSBhbGxvY193b3JrcXVldWUo InZkdXNlLXZkcGEiLCBXUV9VTkJPVU5ELCAxKTsKPiArCWlmICghdmR1c2VfdmRwYV93cSkKPiAr CQlnb3RvIGVycl92ZHBhX3dxOwo+ICsKPiArCXJldCA9IHZkdXNlX3ZpcnFmZF9pbml0KCk7Cj4g KwlpZiAocmV0KQo+ICsJCWdvdG8gZXJyX2lycWZkOwo+ICsKPiArCXJldCA9IHZkdXNlX3BhcmVu dGRldl9pbml0KCk7Cj4gKwlpZiAocmV0KQo+ICsJCWdvdG8gZXJyX3BhcmVudGRldjsKPiArCj4g KwlyZXR1cm4gMDsKPiArZXJyX3BhcmVudGRldjoKPiArCXZkdXNlX3ZpcnFmZF9leGl0KCk7Cj4g K2Vycl9pcnFmZDoKPiArCWRlc3Ryb3lfd29ya3F1ZXVlKHZkdXNlX3ZkcGFfd3EpOwo+ICtlcnJf dmRwYV93cToKPiArCW1pc2NfZGVyZWdpc3RlcigmdmR1c2VfbWlzYyk7Cj4gKwlyZXR1cm4gcmV0 Owo+ICt9Cj4gK21vZHVsZV9pbml0KHZkdXNlX2luaXQpOwo+ICsKPiArc3RhdGljIHZvaWQgdmR1 c2VfZXhpdCh2b2lkKQo+ICt7Cj4gKwltaXNjX2RlcmVnaXN0ZXIoJnZkdXNlX21pc2MpOwo+ICsJ ZGVzdHJveV93b3JrcXVldWUodmR1c2VfdmRwYV93cSk7Cj4gKwl2ZHVzZV92aXJxZmRfZXhpdCgp Owo+ICsJdmR1c2VfcGFyZW50ZGV2X2V4aXQoKTsKPiArfQo+ICttb2R1bGVfZXhpdCh2ZHVzZV9l eGl0KTsKPiArCj4gK01PRFVMRV9WRVJTSU9OKERSVl9WRVJTSU9OKTsKPiArTU9EVUxFX0xJQ0VO U0UoRFJWX0xJQ0VOU0UpOwo+ICtNT0RVTEVfQVVUSE9SKERSVl9BVVRIT1IpOwo+ICtNT0RVTEVf REVTQ1JJUFRJT04oRFJWX0RFU0MpOwo+IGRpZmYgLS1naXQgYS9pbmNsdWRlL3VhcGkvbGludXgv dmRwYS5oIGIvaW5jbHVkZS91YXBpL2xpbnV4L3ZkcGEuaAo+IGluZGV4IGJiYThiODNhOTRiNS4u YTdhODQxZTVmZmM3IDEwMDY0NAo+IC0tLSBhL2luY2x1ZGUvdWFwaS9saW51eC92ZHBhLmgKPiAr KysgYi9pbmNsdWRlL3VhcGkvbGludXgvdmRwYS5oCj4gQEAgLTMzLDYgKzMzLDcgQEAgZW51bSB2 ZHBhX2F0dHIgewo+ICAgCVZEUEFfQVRUUl9ERVZfVkVORE9SX0lELAkJLyogdTMyICovCj4gICAJ VkRQQV9BVFRSX0RFVl9NQVhfVlFTLAkJCS8qIHUzMiAqLwo+ICAgCVZEUEFfQVRUUl9ERVZfTUFY X1ZRX1NJWkUsCQkvKiB1MTYgKi8KPiArCVZEUEFfQVRUUl9CQUNLRU5EX0lELAkJCS8qIHUzMiAq LwoKCkFzIGRpc2N1c3NlZCwgdGhpcyBuZWVkcyBtb3JlIHRob3VnaHQuIEJ1dCBpZiBuZWNlc3Nh cnksIHdlIG5lZWQgYSAKc2VwYXJhdGUgcGF0Y2ggZm9yIHRoaXMuCgoKPiAgIAo+ICAgCS8qIG5l dyBhdHRyaWJ1dGVzIG11c3QgYmUgYWRkZWQgYWJvdmUgaGVyZSAqLwo+ICAgCVZEUEFfQVRUUl9N QVgsCj4gZGlmZiAtLWdpdCBhL2luY2x1ZGUvdWFwaS9saW51eC92ZHVzZS5oIGIvaW5jbHVkZS91 YXBpL2xpbnV4L3ZkdXNlLmgKPiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+IGluZGV4IDAwMDAwMDAw MDAwMC4uOWZiNTU1ZGRjZmJkCj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBiL2luY2x1ZGUvdWFwaS9s aW51eC92ZHVzZS5oCj4gQEAgLTAsMCArMSwxMjUgQEAKPiArLyogU1BEWC1MaWNlbnNlLUlkZW50 aWZpZXI6IEdQTC0yLjAgV0lUSCBMaW51eC1zeXNjYWxsLW5vdGUgKi8KPiArI2lmbmRlZiBfVUFQ SV9WRFVTRV9IXwo+ICsjZGVmaW5lIF9VQVBJX1ZEVVNFX0hfCj4gKwo+ICsjaW5jbHVkZSA8bGlu dXgvdHlwZXMuaD4KPiArCj4gKy8qIHRoZSBjb250cm9sIG1lc3NhZ2VzIGRlZmluaXRpb24gZm9y IHJlYWQvd3JpdGUgKi8KPiArCj4gKyNkZWZpbmUgVkRVU0VfQ09ORklHX0RBVEFfTEVOCTI1Ngo+ ICsKPiArZW51bSB2ZHVzZV9yZXFfdHlwZSB7Cj4gKwlWRFVTRV9TRVRfVlFfTlVNLAo+ICsJVkRV U0VfU0VUX1ZRX0FERFIsCj4gKwlWRFVTRV9TRVRfVlFfUkVBRFksCj4gKwlWRFVTRV9HRVRfVlFf UkVBRFksCj4gKwlWRFVTRV9TRVRfVlFfU1RBVEUsCj4gKwlWRFVTRV9HRVRfVlFfU1RBVEUsCj4g KwlWRFVTRV9TRVRfRkVBVFVSRVMsCj4gKwlWRFVTRV9HRVRfRkVBVFVSRVMsCj4gKwlWRFVTRV9T RVRfU1RBVFVTLAo+ICsJVkRVU0VfR0VUX1NUQVRVUywKPiArCVZEVVNFX1NFVF9DT05GSUcsCj4g KwlWRFVTRV9HRVRfQ09ORklHLAo+ICsJVkRVU0VfVVBEQVRFX0lPVExCLAo+ICt9Owo+ICsKPiAr c3RydWN0IHZkdXNlX3ZxX251bSB7Cj4gKwlfX3UzMiBpbmRleDsKPiArCV9fdTMyIG51bTsKPiAr fTsKPiArCj4gK3N0cnVjdCB2ZHVzZV92cV9hZGRyIHsKPiArCV9fdTMyIGluZGV4Owo+ICsJX191 NjQgZGVzY19hZGRyOwo+ICsJX191NjQgZHJpdmVyX2FkZHI7Cj4gKwlfX3U2NCBkZXZpY2VfYWRk cjsKPiArfTsKPiArCj4gK3N0cnVjdCB2ZHVzZV92cV9yZWFkeSB7Cj4gKwlfX3UzMiBpbmRleDsK PiArCV9fdTggcmVhZHk7Cj4gK307Cj4gKwo+ICtzdHJ1Y3QgdmR1c2VfdnFfc3RhdGUgewo+ICsJ X191MzIgaW5kZXg7Cj4gKwlfX3UxNiBhdmFpbF9pZHg7Cj4gK307Cj4gKwo+ICtzdHJ1Y3QgdmR1 c2VfZGV2X2NvbmZpZ19kYXRhIHsKPiArCV9fdTMyIG9mZnNldDsKPiArCV9fdTMyIGxlbjsKPiAr CV9fdTggZGF0YVtWRFVTRV9DT05GSUdfREFUQV9MRU5dOwoKClRoaXMgbm8gZ3VhcmFudGVlIHRo YXQgMjU2IGlzIHN1ZmZpY2llbnQgaGVyZS4KCgo+ICt9Owo+ICsKPiArc3RydWN0IHZkdXNlX2lv dmFfcmFuZ2Ugewo+ICsJX191NjQgc3RhcnQ7Cj4gKwlfX3U2NCBsYXN0Owo+ICt9Owo+ICsKPiAr c3RydWN0IHZkdXNlX2Rldl9yZXF1ZXN0IHsKPiArCV9fdTMyIHR5cGU7IC8qIHJlcXVlc3QgdHlw ZSAqLwo+ICsJX191MzIgdW5pcXVlOyAvKiByZXF1ZXN0IGlkICovCj4gKwlfX3UzMiBmbGFnczsg LyogcmVxdWVzdCBmbGFncyAqLwoKClNlZW1zIHVudXNlZCBpbiB0aGlzIHNlcmllcy4KCgo+ICsJ X191MzIgc2l6ZTsgLyogdGhlIHBheWxvYWQgc2l6ZSAqLwoKClVudXNlZC4KCgo+ICsJdW5pb24g ewo+ICsJCXN0cnVjdCB2ZHVzZV92cV9udW0gdnFfbnVtOyAvKiB2aXJ0cXVldWUgbnVtICovCj4g KwkJc3RydWN0IHZkdXNlX3ZxX2FkZHIgdnFfYWRkcjsgLyogdmlydHF1ZXVlIGFkZHJlc3MgKi8K PiArCQlzdHJ1Y3QgdmR1c2VfdnFfcmVhZHkgdnFfcmVhZHk7IC8qIHZpcnRxdWV1ZSByZWFkeSBz dGF0dXMgKi8KPiArCQlzdHJ1Y3QgdmR1c2VfdnFfc3RhdGUgdnFfc3RhdGU7IC8qIHZpcnRxdWV1 ZSBzdGF0ZSAqLwo+ICsJCXN0cnVjdCB2ZHVzZV9kZXZfY29uZmlnX2RhdGEgY29uZmlnOyAvKiB2 aXJ0aW8gZGV2aWNlIGNvbmZpZyBzcGFjZSAqLwo+ICsJCXN0cnVjdCB2ZHVzZV9pb3ZhX3Jhbmdl IGlvdmE7IC8qIGlvdmEgcmFuZ2UgZm9yIHVwZGF0aW5nICovCj4gKwkJX191NjQgZmVhdHVyZXM7 IC8qIHZpcnRpbyBmZWF0dXJlcyAqLwo+ICsJCV9fdTggc3RhdHVzOyAvKiBkZXZpY2Ugc3RhdHVz ICovCgoKTGV0J3MgYWRkIHNvbWUgcGFkZGluZyBmb3IgZnV0dXJlIGV4dGVuc2lvbnMuCgoKPiAr CX07Cj4gK307Cj4gKwo+ICtzdHJ1Y3QgdmR1c2VfZGV2X3Jlc3BvbnNlIHsKPiArCV9fdTMyIHVu aXF1ZTsgLyogY29ycmVzcG9uZGluZyByZXF1ZXN0IGlkICovCgoKTGV0J3MgdXNlIHJlcXVlc3Qg aWQuCgoKPiArCV9fczMyIHJlc3VsdDsgLyogdGhlIHJlc3VsdCBvZiByZXF1ZXN0ICovCgoKTGV0 J3MgdXNlIG1hY3JvIG9yIGVudW0gdG8gZGVmaW5lIHRoZSBzdWNjZXNzIGFuZCBmYWlsdXJlIHZh bHVlLgoKCj4gKwl1bmlvbiB7Cj4gKwkJc3RydWN0IHZkdXNlX3ZxX3JlYWR5IHZxX3JlYWR5OyAv KiB2aXJ0cXVldWUgcmVhZHkgc3RhdHVzICovCj4gKwkJc3RydWN0IHZkdXNlX3ZxX3N0YXRlIHZx X3N0YXRlOyAvKiB2aXJ0cXVldWUgc3RhdGUgKi8KPiArCQlzdHJ1Y3QgdmR1c2VfZGV2X2NvbmZp Z19kYXRhIGNvbmZpZzsgLyogdmlydGlvIGRldmljZSBjb25maWcgc3BhY2UgKi8KPiArCQlfX3U2 NCBmZWF0dXJlczsgLyogdmlydGlvIGZlYXR1cmVzICovCj4gKwkJX191OCBzdGF0dXM7IC8qIGRl dmljZSBzdGF0dXMgKi8KPiArCX07Cj4gK307Cj4gKwo+ICsvKiBpb2N0bHMgKi8KPiArCj4gK3N0 cnVjdCB2ZHVzZV9kZXZfY29uZmlnIHsKPiArCV9fdTMyIGlkOyAvKiB2ZHVzZSBkZXZpY2UgaWQg Ki8KPiArCV9fdTMyIHZlbmRvcl9pZDsgLyogdmlydGlvIHZlbmRvciBpZCAqLwo+ICsJX191MzIg ZGV2aWNlX2lkOyAvKiB2aXJ0aW8gZGV2aWNlIGlkICovCj4gKwlfX3U2NCBib3VuY2Vfc2l6ZTsg LyogYm91bmNlIGJ1ZmZlciBzaXplIGZvciBpb21tdSAqLwo+ICsJX191MTYgdnFfbnVtOyAvKiB0 aGUgbnVtYmVyIG9mIHZpcnRxdWV1ZXMgKi8KPiArCV9fdTE2IHZxX3NpemVfbWF4OyAvKiB0aGUg bWF4IHNpemUgb2YgdmlydHF1ZXVlICovCj4gKwlfX3UzMiB2cV9hbGlnbjsgLyogdGhlIGFsbG9j YXRpb24gYWxpZ25tZW50IG9mIHZpcnRxdWV1ZSdzIG1ldGFkYXRhICovCj4gK307Cj4gKwo+ICtz dHJ1Y3QgdmR1c2VfaW90bGJfZW50cnkgewo+ICsJX191NjQgb2Zmc2V0OyAvKiB0aGUgbW1hcCBv ZmZzZXQgb24gZmQgKi8KPiArCV9fdTY0IHN0YXJ0OyAvKiBzdGFydCBvZiB0aGUgSU9WQSByYW5n ZSAqLwo+ICsJX191NjQgbGFzdDsgLyogbGFzdCBvZiB0aGUgSU9WQSByYW5nZSAqLwo+ICsjZGVm aW5lIFZEVVNFX0FDQ0VTU19STyAweDEKPiArI2RlZmluZSBWRFVTRV9BQ0NFU1NfV08gMHgyCj4g KyNkZWZpbmUgVkRVU0VfQUNDRVNTX1JXIDB4Mwo+ICsJX191OCBwZXJtOyAvKiBhY2Nlc3MgcGVy bWlzc2lvbiBvZiB0aGlzIHJhbmdlICovCj4gK307Cj4gKwo+ICtzdHJ1Y3QgdmR1c2VfdnFfZXZl bnRmZCB7Cj4gKwlfX3UzMiBpbmRleDsgLyogdmlydHF1ZXVlIGluZGV4ICovCj4gKwlfX3UzMiBm ZDsgLyogZXZlbnRmZCAqLwoKCkFueSByZWFzb24gZm9yIG5vdCB1c2luZyBpbnQgaGVyZT8KCgo+ ICt9Owo+ICsKPiArI2RlZmluZSBWRFVTRV9CQVNFCTB4ODEKPiArCj4gKyNkZWZpbmUgVkRVU0Vf Q1JFQVRFX0RFVglfSU9XKFZEVVNFX0JBU0UsIDB4MDEsIHN0cnVjdCB2ZHVzZV9kZXZfY29uZmln KQo+ICsjZGVmaW5lIFZEVVNFX0RFU1RST1lfREVWCV9JTyhWRFVTRV9CQVNFLCAweDAyKQo+ICsK PiArI2RlZmluZSBWRFVTRV9JT1RMQl9HRVRfRkQJX0lPV1IoVkRVU0VfQkFTRSwgMHgwNCwgc3Ry dWN0IHZkdXNlX2lvdGxiX2VudHJ5KQo+ICsjZGVmaW5lIFZEVVNFX1ZRX1NFVFVQX0tJQ0tGRAlf SU9XKFZEVVNFX0JBU0UsIDB4MDUsIHN0cnVjdCB2ZHVzZV92cV9ldmVudGZkKQo+ICsjZGVmaW5l IFZEVVNFX1ZRX1NFVFVQX0lSUUZECV9JT1coVkRVU0VfQkFTRSwgMHgwNiwgc3RydWN0IHZkdXNl X3ZxX2V2ZW50ZmQpCgoKQmV0dGVyIHdpdGggZG9jdW1lbnRhdGlvbiB0byBleHBsYWluIHRob3Nl IGlvY3Rscy4KClRoYW5rcwoKCj4gKwo+ICsjZW5kaWYgLyogX1VBUElfVkRVU0VfSF8gKi8KCl9f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fClZpcnR1YWxpemF0 aW9uIG1haWxpbmcgbGlzdApWaXJ0dWFsaXphdGlvbkBsaXN0cy5saW51eC1mb3VuZGF0aW9uLm9y ZwpodHRwczovL2xpc3RzLmxpbnV4Zm91bmRhdGlvbi5vcmcvbWFpbG1hbi9saXN0aW5mby92aXJ0 dWFsaXphdGlvbg==