From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60332) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bXAK8-0002pa-T5 for qemu-devel@nongnu.org; Tue, 09 Aug 2016 12:56:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bXAK2-0001jL-Rr for qemu-devel@nongnu.org; Tue, 09 Aug 2016 12:56:15 -0400 Received: from smtp02.citrix.com ([66.165.176.63]:8538) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bXAK2-0001ii-Hx for qemu-devel@nongnu.org; Tue, 09 Aug 2016 12:56:10 -0400 Date: Tue, 9 Aug 2016 17:56:02 +0100 From: Anthony PERARD Message-ID: <20160809165602.GD1835@perard.uk.xensource.com> References: <1470146790-6168-1-git-send-email-paulinaszubarczyk@gmail.com> <1470146790-6168-3-git-send-email-paulinaszubarczyk@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Disposition: inline In-Reply-To: <1470146790-6168-3-git-send-email-paulinaszubarczyk@gmail.com> Subject: Re: [Qemu-devel] [PATCH v4 2/2] qdisk - hw/block/xen_disk: grant copy implementation List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Paulina Szubarczyk Cc: xen-devel@lists.xenproject.org, roger.pau@citrix.com, wei.liu2@citrix.com, ian.jackson@eu.citrix.com, david.vrabel@citrix.com, sstabellini@kernel.org, qemu-devel@nongnu.org On Tue, Aug 02, 2016 at 04:06:30PM +0200, Paulina Szubarczyk wrote: > Copy data operated on during request from/to local buffers to/from > the grant references. > > Before grant copy operation local buffers must be allocated what is > done by calling ioreq_init_copy_buffers. For the 'read' operation, > first, the qemu device invokes the read operation on local buffers > and on the completion grant copy is called and buffers are freed. > For the 'write' operation grant copy is performed before invoking > write by qemu device. > > A new value 'feature_grant_copy' is added to recognize when the > grant copy operation is supported by a guest. > > Signed-off-by: Paulina Szubarczyk > --- > Changes since v3: > - qemu_memalign/qemu_free is used instead function allocating > memory from xc. > - removed the get_buffer function instead there is a direct call > to qemu_memalign. > - moved ioreq_copy for write operation to ioreq_runio_qemu_aio. > - added struct xengnttab_grant_copy_segment_t and stub in > xen_common.h for version of xen earlier then 480. > - added checking for version 480 to configure. The test repeats > all the operation that are required for version < 480 and > checks if xengnttab_grant_copy() is implemented. > > * I did not change the way of testing if grant_copy operation is > implemented. As far as I understand if the code from > gnttab_unimp.c is used then the gnttab device is unavailable > and the handler to gntdev would be invalid. But if the handler > is valid then the ioctl should return operation unimplemented > if the gntdev does not implement the operation. > --- > configure | 56 +++++++++++++++++ > hw/block/xen_disk.c | 142 ++++++++++++++++++++++++++++++++++++++++++-- > include/hw/xen/xen_common.h | 25 ++++++++ > 3 files changed, 218 insertions(+), 5 deletions(-) > > diff --git a/configure b/configure > index f57fcc6..b5bf7d4 100755 > --- a/configure > +++ b/configure > @@ -1956,6 +1956,62 @@ EOF > /* > * If we have stable libs the we don't want the libxc compat > * layers, regardless of what CFLAGS we may have been given. > + * > + * Also, check if xengnttab_grant_copy_segment_t is defined and > + * grant copy operation is implemented. > + */ > +#undef XC_WANT_COMPAT_EVTCHN_API > +#undef XC_WANT_COMPAT_GNTTAB_API > +#undef XC_WANT_COMPAT_MAP_FOREIGN_API > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#if !defined(HVM_MAX_VCPUS) > +# error HVM_MAX_VCPUS not defined > +#endif > +int main(void) { > + xc_interface *xc = NULL; > + xenforeignmemory_handle *xfmem; > + xenevtchn_handle *xe; > + xengnttab_handle *xg; > + xen_domain_handle_t handle; > + xengnttab_grant_copy_segment_t* seg = NULL; > + > + xs_daemon_open(); > + > + xc = xc_interface_open(0, 0, 0); > + xc_hvm_set_mem_type(0, 0, HVMMEM_ram_ro, 0, 0); > + xc_domain_add_to_physmap(0, 0, XENMAPSPACE_gmfn, 0, 0); > + xc_hvm_inject_msi(xc, 0, 0xf0000000, 0x00000000); > + xc_hvm_create_ioreq_server(xc, 0, HVM_IOREQSRV_BUFIOREQ_ATOMIC, NULL); > + xc_domain_create(xc, 0, handle, 0, NULL, NULL); > + > + xfmem = xenforeignmemory_open(0, 0); > + xenforeignmemory_map(xfmem, 0, 0, 0, 0, 0); > + > + xe = xenevtchn_open(0, 0); > + xenevtchn_fd(xe); > + > + xg = xengnttab_open(0, 0); > + xengnttab_map_grant_ref(xg, 0, 0, 0); > + xengnttab_grant_copy(xg, 0, seg); > + > + return 0; > +} > +EOF > + compile_prog "" "$xen_libs $xen_stable_libs" > + then > + xen_ctrl_version=480 > + xen=yes > + elif > + cat > $TMPC < +/* > + * If we have stable libs the we don't want the libxc compat > + * layers, regardless of what CFLAGS we may have been given. > */ > #undef XC_WANT_COMPAT_EVTCHN_API > #undef XC_WANT_COMPAT_GNTTAB_API > diff --git a/hw/block/xen_disk.c b/hw/block/xen_disk.c > index 3b8ad33..2dd1464 100644 > --- a/hw/block/xen_disk.c > +++ b/hw/block/xen_disk.c > @@ -119,6 +119,9 @@ struct XenBlkDev { > unsigned int persistent_gnt_count; > unsigned int max_grants; > > + /* Grant copy */ > + gboolean feature_grant_copy; > + > /* qemu block driver */ > DriveInfo *dinfo; > BlockBackend *blk; > @@ -489,6 +492,95 @@ static int ioreq_map(struct ioreq *ioreq) > return 0; > } > > +static void free_buffers(struct ioreq *ioreq) > +{ > + int i; > + > + for (i = 0; i < ioreq->v.niov; i++) { > + ioreq->page[i] = NULL; > + } > + > + qemu_vfree(ioreq->pages); > +} > + > +static int ioreq_init_copy_buffers(struct ioreq *ioreq) > +{ > + int i; > + > + if (ioreq->v.niov == 0) { > + return 0; > + } > + > + ioreq->pages = qemu_memalign(XC_PAGE_SIZE, ioreq->v.niov * XC_PAGE_SIZE); > + if (!ioreq->pages) { qemu_memalign never returns NULL, you don't have to check. > + return -1; > + } > + > + for (i = 0; i < ioreq->v.niov; i++) { > + ioreq->page[i] = ioreq->pages + i * XC_PAGE_SIZE; > + ioreq->v.iov[i].iov_base = ioreq->page[i]; > + } > + > + return 0; > +} > + > +static int ioreq_copy(struct ioreq *ioreq) > +{ > + xengnttab_handle *gnt = ioreq->blkdev->xendev.gnttabdev; > + xengnttab_grant_copy_segment_t segs[BLKIF_MAX_SEGMENTS_PER_REQUEST]; > + int i, count = 0, r, rc; > + int64_t file_blk = ioreq->blkdev->file_blk; > + > + if (ioreq->v.niov == 0) { > + return 0; > + } > + > + count = ioreq->v.niov; > + > + for (i = 0; i < count; i++) { > + > + if (ioreq->req.operation == BLKIF_OP_READ) { > + segs[i].flags = GNTCOPY_dest_gref; > + segs[i].dest.foreign.ref = ioreq->refs[i]; > + segs[i].dest.foreign.domid = ioreq->domids[i]; > + segs[i].dest.foreign.offset = ioreq->req.seg[i].first_sect * file_blk; > + segs[i].source.virt = ioreq->v.iov[i].iov_base; > + } else { > + segs[i].flags = GNTCOPY_source_gref; > + segs[i].source.foreign.ref = ioreq->refs[i]; > + segs[i].source.foreign.domid = ioreq->domids[i]; > + segs[i].source.foreign.offset = ioreq->req.seg[i].first_sect * file_blk; > + segs[i].dest.virt = ioreq->v.iov[i].iov_base; > + } > + segs[i].len = (ioreq->req.seg[i].last_sect > + - ioreq->req.seg[i].first_sect + 1) * file_blk; > + > + } > + > + rc = xengnttab_grant_copy(gnt, count, segs); > + > + if (rc) { > + xen_be_printf(&ioreq->blkdev->xendev, 0, > + "failed to copy data %d\n", rc); > + ioreq->aio_errors++; > + return -1; > + } else { > + r = 0; > + } > + > + for (i = 0; i < count; i++) { > + if (segs[i].status != GNTST_okay) { > + xen_be_printf(&ioreq->blkdev->xendev, 3, > + "failed to copy data %d for gref %d, domid %d\n", rc, > + ioreq->refs[i], ioreq->domids[i]); > + ioreq->aio_errors++; > + r = -1; > + } > + } > + > + return r; > +} > + > static int ioreq_runio_qemu_aio(struct ioreq *ioreq); > > static void qemu_aio_complete(void *opaque, int ret) > @@ -511,8 +603,29 @@ static void qemu_aio_complete(void *opaque, int ret) > return; > } > > + if (ioreq->blkdev->feature_grant_copy) { > + switch (ioreq->req.operation) { > + case BLKIF_OP_READ: > + /* in case of failure ioreq->aio_errors is increased */ > + ioreq_copy(ioreq); > + free_buffers(ioreq); > + break; > + case BLKIF_OP_WRITE: > + case BLKIF_OP_FLUSH_DISKCACHE: > + if (!ioreq->req.nr_segments) { > + break; > + } > + free_buffers(ioreq); > + break; > + default: > + break; > + } > + } > + > ioreq->status = ioreq->aio_errors ? BLKIF_RSP_ERROR : BLKIF_RSP_OKAY; > - ioreq_unmap(ioreq); > + if (!ioreq->blkdev->feature_grant_copy) { > + ioreq_unmap(ioreq); > + } > ioreq_finish(ioreq); > switch (ioreq->req.operation) { > case BLKIF_OP_WRITE: > @@ -538,8 +651,20 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) > { > struct XenBlkDev *blkdev = ioreq->blkdev; > > - if (ioreq->req.nr_segments && ioreq_map(ioreq) == -1) { > - goto err_no_map; > + if (ioreq->blkdev->feature_grant_copy) { > + ioreq_init_copy_buffers(ioreq); > + if (ioreq->req.nr_segments && (ioreq->req.operation == BLKIF_OP_WRITE || > + ioreq->req.operation == BLKIF_OP_FLUSH_DISKCACHE)) { > + if (ioreq_copy(ioreq)) { > + free_buffers(ioreq); > + goto err; > + } > + } > + > + } else { > + if (ioreq->req.nr_segments && ioreq_map(ioreq)) { > + goto err; > + } > } > > ioreq->aio_inflight++; > @@ -582,6 +707,9 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) > } > default: > /* unknown operation (shouldn't happen -- parse catches this) */ > + if (!ioreq->blkdev->feature_grant_copy) { > + ioreq_unmap(ioreq); > + } > goto err; > } > > @@ -590,8 +718,6 @@ static int ioreq_runio_qemu_aio(struct ioreq *ioreq) > return 0; > > err: > - ioreq_unmap(ioreq); > -err_no_map: > ioreq_finish(ioreq); > ioreq->status = BLKIF_RSP_ERROR; > return -1; > @@ -1032,6 +1158,12 @@ static int blk_connect(struct XenDevice *xendev) > > xen_be_bind_evtchn(&blkdev->xendev); > > + blkdev->feature_grant_copy = > + (xengnttab_grant_copy(blkdev->xendev.gnttabdev, 0, NULL) == 0); > + > + xen_be_printf(&blkdev->xendev, 3, "grant copy operation %s\n", > + blkdev->feature_grant_copy ? "enabled" : "disabled"); > + > xen_be_printf(&blkdev->xendev, 1, "ok: proto %s, ring-ref %d, " > "remote port %d, local port %d\n", > blkdev->xendev.protocol, blkdev->ring_ref, > diff --git a/include/hw/xen/xen_common.h b/include/hw/xen/xen_common.h > index 640c31e..e80c61f 100644 > --- a/include/hw/xen/xen_common.h > +++ b/include/hw/xen/xen_common.h > @@ -25,6 +25,31 @@ > */ > > /* Xen 4.2 through 4.6 */ > +#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 480 > + > +struct xengnttab_grant_copy_segment { > + union xengnttab_copy_ptr { > + void *virt; > + struct { > + uint32_t ref; > + uint16_t offset; > + uint16_t domid; > + } foreign; > + } source, dest; > + uint16_t len; > + uint16_t flags; > + int16_t status; > +}; I don't think it's a good idee to define a struct that is not going to be used, and does not belong here. The typedef is OK. In xen_disk.c, you could use "#if CONFIG_XEN_CTRL_INTERFACE_VERSION ..." around free_buffers, ioreq_init_copy_buffers and ioreq_copy, and replace them by stubs when Xen does not support grant copy. I think that would be better. Also, could you try to compile again xen unstable, without your other patch? Right now, it does not compile. > +typedef struct xengnttab_grant_copy_segment xengnttab_grant_copy_segment_t; > + > +static inline int xengnttab_grant_copy(xengnttab_handle *xgt, uint32_t count, > + xengnttab_grant_copy_segment_t *segs) > +{ > + return -1; return -ENOSYS would be more appropriate. Otherwise, the patch looks good. Thanks, -- Anthony PERARD From mboxrd@z Thu Jan 1 00:00:00 1970 From: Anthony PERARD Subject: Re: [PATCH v4 2/2] qdisk - hw/block/xen_disk: grant copy implementation Date: Tue, 9 Aug 2016 17:56:02 +0100 Message-ID: <20160809165602.GD1835@perard.uk.xensource.com> References: <1470146790-6168-1-git-send-email-paulinaszubarczyk@gmail.com> <1470146790-6168-3-git-send-email-paulinaszubarczyk@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Received: from mail6.bemta6.messagelabs.com ([85.158.143.247]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bXAK0-0002Ry-Db for xen-devel@lists.xenproject.org; Tue, 09 Aug 2016 16:56:08 +0000 Content-Disposition: inline In-Reply-To: <1470146790-6168-3-git-send-email-paulinaszubarczyk@gmail.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" To: Paulina Szubarczyk Cc: sstabellini@kernel.org, wei.liu2@citrix.com, ian.jackson@eu.citrix.com, qemu-devel@nongnu.org, david.vrabel@citrix.com, xen-devel@lists.xenproject.org, roger.pau@citrix.com List-Id: xen-devel@lists.xenproject.org T24gVHVlLCBBdWcgMDIsIDIwMTYgYXQgMDQ6MDY6MzBQTSArMDIwMCwgUGF1bGluYSBTenViYXJj enlrIHdyb3RlOgo+IENvcHkgZGF0YSBvcGVyYXRlZCBvbiBkdXJpbmcgcmVxdWVzdCBmcm9tL3Rv IGxvY2FsIGJ1ZmZlcnMgdG8vZnJvbQo+IHRoZSBncmFudCByZWZlcmVuY2VzLgo+IAo+IEJlZm9y ZSBncmFudCBjb3B5IG9wZXJhdGlvbiBsb2NhbCBidWZmZXJzIG11c3QgYmUgYWxsb2NhdGVkIHdo YXQgaXMKPiBkb25lIGJ5IGNhbGxpbmcgaW9yZXFfaW5pdF9jb3B5X2J1ZmZlcnMuIEZvciB0aGUg J3JlYWQnIG9wZXJhdGlvbiwKPiBmaXJzdCwgdGhlIHFlbXUgZGV2aWNlIGludm9rZXMgdGhlIHJl YWQgb3BlcmF0aW9uIG9uIGxvY2FsIGJ1ZmZlcnMKPiBhbmQgb24gdGhlIGNvbXBsZXRpb24gZ3Jh bnQgY29weSBpcyBjYWxsZWQgYW5kIGJ1ZmZlcnMgYXJlIGZyZWVkLgo+IEZvciB0aGUgJ3dyaXRl JyBvcGVyYXRpb24gZ3JhbnQgY29weSBpcyBwZXJmb3JtZWQgYmVmb3JlIGludm9raW5nCj4gd3Jp dGUgYnkgcWVtdSBkZXZpY2UuCj4gCj4gQSBuZXcgdmFsdWUgJ2ZlYXR1cmVfZ3JhbnRfY29weScg aXMgYWRkZWQgdG8gcmVjb2duaXplIHdoZW4gdGhlCj4gZ3JhbnQgY29weSBvcGVyYXRpb24gaXMg c3VwcG9ydGVkIGJ5IGEgZ3Vlc3QuCj4gCj4gU2lnbmVkLW9mZi1ieTogUGF1bGluYSBTenViYXJj enlrIDxwYXVsaW5hc3p1YmFyY3p5a0BnbWFpbC5jb20+Cj4gLS0tCj4gQ2hhbmdlcyBzaW5jZSB2 MzoKPiAtIHFlbXVfbWVtYWxpZ24vcWVtdV9mcmVlIGlzIHVzZWQgaW5zdGVhZCBmdW5jdGlvbiBh bGxvY2F0aW5nCj4gICBtZW1vcnkgZnJvbSB4Yy4KPiAtIHJlbW92ZWQgdGhlIGdldF9idWZmZXIg ZnVuY3Rpb24gaW5zdGVhZCB0aGVyZSBpcyBhIGRpcmVjdCBjYWxsCj4gICB0byBxZW11X21lbWFs aWduLgo+IC0gbW92ZWQgaW9yZXFfY29weSBmb3Igd3JpdGUgb3BlcmF0aW9uIHRvIGlvcmVxX3J1 bmlvX3FlbXVfYWlvLgo+IC0gYWRkZWQgc3RydWN0IHhlbmdudHRhYl9ncmFudF9jb3B5X3NlZ21l bnRfdCBhbmQgc3R1YiBpbgo+ICAgeGVuX2NvbW1vbi5oIGZvciB2ZXJzaW9uIG9mIHhlbiBlYXJs aWVyIHRoZW4gNDgwLgo+IC0gYWRkZWQgY2hlY2tpbmcgZm9yIHZlcnNpb24gNDgwIHRvIGNvbmZp Z3VyZS4gVGhlIHRlc3QgcmVwZWF0cwo+ICAgYWxsIHRoZSBvcGVyYXRpb24gdGhhdCBhcmUgcmVx dWlyZWQgZm9yIHZlcnNpb24gPCA0ODAgYW5kCj4gICBjaGVja3MgaWYgeGVuZ250dGFiX2dyYW50 X2NvcHkoKSBpcyBpbXBsZW1lbnRlZC4KPiAKPiAqIEkgZGlkIG5vdCBjaGFuZ2UgdGhlIHdheSBv ZiB0ZXN0aW5nIGlmIGdyYW50X2NvcHkgb3BlcmF0aW9uIGlzCj4gICBpbXBsZW1lbnRlZC4gQXMg ZmFyIGFzIEkgdW5kZXJzdGFuZCBpZiB0aGUgY29kZSBmcm9tCj4gICBnbnR0YWJfdW5pbXAuYyBp cyB1c2VkIHRoZW4gdGhlIGdudHRhYiBkZXZpY2UgaXMgdW5hdmFpbGFibGUKPiAgIGFuZCB0aGUg aGFuZGxlciB0byBnbnRkZXYgd291bGQgYmUgaW52YWxpZC4gQnV0IGlmIHRoZSBoYW5kbGVyCj4g ICBpcyB2YWxpZCB0aGVuIHRoZSBpb2N0bCBzaG91bGQgcmV0dXJuIG9wZXJhdGlvbiB1bmltcGxl bWVudGVkCj4gICBpZiB0aGUgZ250ZGV2IGRvZXMgbm90IGltcGxlbWVudCB0aGUgb3BlcmF0aW9u Lgo+IC0tLQo+ICBjb25maWd1cmUgICAgICAgICAgICAgICAgICAgfCAgNTYgKysrKysrKysrKysr KysrKysKPiAgaHcvYmxvY2sveGVuX2Rpc2suYyAgICAgICAgIHwgMTQyICsrKysrKysrKysrKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKy0tCj4gIGluY2x1ZGUvaHcveGVuL3hlbl9jb21t b24uaCB8ICAyNSArKysrKysrKwo+ICAzIGZpbGVzIGNoYW5nZWQsIDIxOCBpbnNlcnRpb25zKCsp LCA1IGRlbGV0aW9ucygtKQo+IAo+IGRpZmYgLS1naXQgYS9jb25maWd1cmUgYi9jb25maWd1cmUK PiBpbmRleCBmNTdmY2M2Li5iNWJmN2Q0IDEwMDc1NQo+IC0tLSBhL2NvbmZpZ3VyZQo+ICsrKyBi L2NvbmZpZ3VyZQo+IEBAIC0xOTU2LDYgKzE5NTYsNjIgQEAgRU9GCj4gIC8qCj4gICAqIElmIHdl IGhhdmUgc3RhYmxlIGxpYnMgdGhlIHdlIGRvbid0IHdhbnQgdGhlIGxpYnhjIGNvbXBhdAo+ICAg KiBsYXllcnMsIHJlZ2FyZGxlc3Mgb2Ygd2hhdCBDRkxBR1Mgd2UgbWF5IGhhdmUgYmVlbiBnaXZl bi4KPiArICoKPiArICogQWxzbywgY2hlY2sgaWYgeGVuZ250dGFiX2dyYW50X2NvcHlfc2VnbWVu dF90IGlzIGRlZmluZWQgYW5kCj4gKyAqIGdyYW50IGNvcHkgb3BlcmF0aW9uIGlzIGltcGxlbWVu dGVkLgo+ICsgKi8KPiArI3VuZGVmIFhDX1dBTlRfQ09NUEFUX0VWVENITl9BUEkKPiArI3VuZGVm IFhDX1dBTlRfQ09NUEFUX0dOVFRBQl9BUEkKPiArI3VuZGVmIFhDX1dBTlRfQ09NUEFUX01BUF9G T1JFSUdOX0FQSQo+ICsjaW5jbHVkZSA8eGVuY3RybC5oPgo+ICsjaW5jbHVkZSA8eGVuc3RvcmUu aD4KPiArI2luY2x1ZGUgPHhlbmV2dGNobi5oPgo+ICsjaW5jbHVkZSA8eGVuZ250dGFiLmg+Cj4g KyNpbmNsdWRlIDx4ZW5mb3JlaWdubWVtb3J5Lmg+Cj4gKyNpbmNsdWRlIDxzdGRpbnQuaD4KPiAr I2luY2x1ZGUgPHhlbi9odm0vaHZtX2luZm9fdGFibGUuaD4KPiArI2lmICFkZWZpbmVkKEhWTV9N QVhfVkNQVVMpCj4gKyMgZXJyb3IgSFZNX01BWF9WQ1BVUyBub3QgZGVmaW5lZAo+ICsjZW5kaWYK PiAraW50IG1haW4odm9pZCkgewo+ICsgIHhjX2ludGVyZmFjZSAqeGMgPSBOVUxMOwo+ICsgIHhl bmZvcmVpZ25tZW1vcnlfaGFuZGxlICp4Zm1lbTsKPiArICB4ZW5ldnRjaG5faGFuZGxlICp4ZTsK PiArICB4ZW5nbnR0YWJfaGFuZGxlICp4ZzsKPiArICB4ZW5fZG9tYWluX2hhbmRsZV90IGhhbmRs ZTsKPiArICB4ZW5nbnR0YWJfZ3JhbnRfY29weV9zZWdtZW50X3QqIHNlZyA9IE5VTEw7Cj4gKwo+ ICsgIHhzX2RhZW1vbl9vcGVuKCk7Cj4gKwo+ICsgIHhjID0geGNfaW50ZXJmYWNlX29wZW4oMCwg MCwgMCk7Cj4gKyAgeGNfaHZtX3NldF9tZW1fdHlwZSgwLCAwLCBIVk1NRU1fcmFtX3JvLCAwLCAw KTsKPiArICB4Y19kb21haW5fYWRkX3RvX3BoeXNtYXAoMCwgMCwgWEVOTUFQU1BBQ0VfZ21mbiwg MCwgMCk7Cj4gKyAgeGNfaHZtX2luamVjdF9tc2koeGMsIDAsIDB4ZjAwMDAwMDAsIDB4MDAwMDAw MDApOwo+ICsgIHhjX2h2bV9jcmVhdGVfaW9yZXFfc2VydmVyKHhjLCAwLCBIVk1fSU9SRVFTUlZf QlVGSU9SRVFfQVRPTUlDLCBOVUxMKTsKPiArICB4Y19kb21haW5fY3JlYXRlKHhjLCAwLCBoYW5k bGUsIDAsIE5VTEwsIE5VTEwpOwo+ICsKPiArICB4Zm1lbSA9IHhlbmZvcmVpZ25tZW1vcnlfb3Bl bigwLCAwKTsKPiArICB4ZW5mb3JlaWdubWVtb3J5X21hcCh4Zm1lbSwgMCwgMCwgMCwgMCwgMCk7 Cj4gKwo+ICsgIHhlID0geGVuZXZ0Y2huX29wZW4oMCwgMCk7Cj4gKyAgeGVuZXZ0Y2huX2ZkKHhl KTsKPiArCj4gKyAgeGcgPSB4ZW5nbnR0YWJfb3BlbigwLCAwKTsKPiArICB4ZW5nbnR0YWJfbWFw X2dyYW50X3JlZih4ZywgMCwgMCwgMCk7Cj4gKyAgeGVuZ250dGFiX2dyYW50X2NvcHkoeGcsIDAs IHNlZyk7Cj4gKwo+ICsgIHJldHVybiAwOwo+ICt9Cj4gK0VPRgo+ICsgICAgICBjb21waWxlX3By b2cgIiIgIiR4ZW5fbGlicyAkeGVuX3N0YWJsZV9saWJzIgo+ICsgICAgdGhlbgo+ICsgICAgeGVu X2N0cmxfdmVyc2lvbj00ODAKPiArICAgIHhlbj15ZXMKPiArICBlbGlmCj4gKyAgICAgIGNhdCA+ ICRUTVBDIDw8RU9GICYmCj4gKy8qCj4gKyAqIElmIHdlIGhhdmUgc3RhYmxlIGxpYnMgdGhlIHdl IGRvbid0IHdhbnQgdGhlIGxpYnhjIGNvbXBhdAo+ICsgKiBsYXllcnMsIHJlZ2FyZGxlc3Mgb2Yg d2hhdCBDRkxBR1Mgd2UgbWF5IGhhdmUgYmVlbiBnaXZlbi4KPiAgICovCj4gICN1bmRlZiBYQ19X QU5UX0NPTVBBVF9FVlRDSE5fQVBJCj4gICN1bmRlZiBYQ19XQU5UX0NPTVBBVF9HTlRUQUJfQVBJ Cj4gZGlmZiAtLWdpdCBhL2h3L2Jsb2NrL3hlbl9kaXNrLmMgYi9ody9ibG9jay94ZW5fZGlzay5j Cj4gaW5kZXggM2I4YWQzMy4uMmRkMTQ2NCAxMDA2NDQKPiAtLS0gYS9ody9ibG9jay94ZW5fZGlz ay5jCj4gKysrIGIvaHcvYmxvY2sveGVuX2Rpc2suYwo+IEBAIC0xMTksNiArMTE5LDkgQEAgc3Ry dWN0IFhlbkJsa0RldiB7Cj4gICAgICB1bnNpZ25lZCBpbnQgICAgICAgIHBlcnNpc3RlbnRfZ250 X2NvdW50Owo+ICAgICAgdW5zaWduZWQgaW50ICAgICAgICBtYXhfZ3JhbnRzOwo+ICAKPiArICAg IC8qIEdyYW50IGNvcHkgKi8KPiArICAgIGdib29sZWFuICAgICAgICAgICAgZmVhdHVyZV9ncmFu dF9jb3B5Owo+ICsKPiAgICAgIC8qIHFlbXUgYmxvY2sgZHJpdmVyICovCj4gICAgICBEcml2ZUlu Zm8gICAgICAgICAgICpkaW5mbzsKPiAgICAgIEJsb2NrQmFja2VuZCAgICAgICAgKmJsazsKPiBA QCAtNDg5LDYgKzQ5Miw5NSBAQCBzdGF0aWMgaW50IGlvcmVxX21hcChzdHJ1Y3QgaW9yZXEgKmlv cmVxKQo+ICAgICAgcmV0dXJuIDA7Cj4gIH0KPiAgCj4gK3N0YXRpYyB2b2lkIGZyZWVfYnVmZmVy cyhzdHJ1Y3QgaW9yZXEgKmlvcmVxKQo+ICt7Cj4gKyAgICBpbnQgaTsKPiArCj4gKyAgICBmb3Ig KGkgPSAwOyBpIDwgaW9yZXEtPnYubmlvdjsgaSsrKSB7Cj4gKyAgICAgICAgaW9yZXEtPnBhZ2Vb aV0gPSBOVUxMOwo+ICsgICAgfQo+ICsKPiArICAgIHFlbXVfdmZyZWUoaW9yZXEtPnBhZ2VzKTsK PiArfQo+ICsKPiArc3RhdGljIGludCBpb3JlcV9pbml0X2NvcHlfYnVmZmVycyhzdHJ1Y3QgaW9y ZXEgKmlvcmVxKQo+ICt7Cj4gKyAgICBpbnQgaTsKPiArCj4gKyAgICBpZiAoaW9yZXEtPnYubmlv diA9PSAwKSB7Cj4gKyAgICAgICAgcmV0dXJuIDA7Cj4gKyAgICB9Cj4gKwo+ICsgICAgaW9yZXEt PnBhZ2VzID0gcWVtdV9tZW1hbGlnbihYQ19QQUdFX1NJWkUsIGlvcmVxLT52Lm5pb3YgKiBYQ19Q QUdFX1NJWkUpOwo+ICsgICAgaWYgKCFpb3JlcS0+cGFnZXMpIHsKCnFlbXVfbWVtYWxpZ24gbmV2 ZXIgcmV0dXJucyBOVUxMLCB5b3UgZG9uJ3QgaGF2ZSB0byBjaGVjay4KCj4gKyAgICAgICAgcmV0 dXJuIC0xOwo+ICsgICAgfQo+ICsKPiArICAgIGZvciAoaSA9IDA7IGkgPCBpb3JlcS0+di5uaW92 OyBpKyspIHsKPiArICAgICAgICBpb3JlcS0+cGFnZVtpXSA9IGlvcmVxLT5wYWdlcyArIGkgKiBY Q19QQUdFX1NJWkU7Cj4gKyAgICAgICAgaW9yZXEtPnYuaW92W2ldLmlvdl9iYXNlID0gaW9yZXEt PnBhZ2VbaV07Cj4gKyAgICB9Cj4gKwo+ICsgICAgcmV0dXJuIDA7Cj4gK30KPiArCj4gK3N0YXRp YyBpbnQgaW9yZXFfY29weShzdHJ1Y3QgaW9yZXEgKmlvcmVxKQo+ICt7Cj4gKyAgICB4ZW5nbnR0 YWJfaGFuZGxlICpnbnQgPSBpb3JlcS0+YmxrZGV2LT54ZW5kZXYuZ250dGFiZGV2Owo+ICsgICAg eGVuZ250dGFiX2dyYW50X2NvcHlfc2VnbWVudF90IHNlZ3NbQkxLSUZfTUFYX1NFR01FTlRTX1BF Ul9SRVFVRVNUXTsKPiArICAgIGludCBpLCBjb3VudCA9IDAsIHIsIHJjOwo+ICsgICAgaW50NjRf dCBmaWxlX2JsayA9IGlvcmVxLT5ibGtkZXYtPmZpbGVfYmxrOwo+ICsKPiArICAgIGlmIChpb3Jl cS0+di5uaW92ID09IDApIHsKPiArICAgICAgICByZXR1cm4gMDsKPiArICAgIH0KPiArCj4gKyAg ICBjb3VudCA9IGlvcmVxLT52Lm5pb3Y7Cj4gKwo+ICsgICAgZm9yIChpID0gMDsgaSA8IGNvdW50 OyBpKyspIHsKPiArCj4gKyAgICAgICAgaWYgKGlvcmVxLT5yZXEub3BlcmF0aW9uID09IEJMS0lG X09QX1JFQUQpIHsKPiArICAgICAgICAgICAgc2Vnc1tpXS5mbGFncyA9IEdOVENPUFlfZGVzdF9n cmVmOwo+ICsgICAgICAgICAgICBzZWdzW2ldLmRlc3QuZm9yZWlnbi5yZWYgPSBpb3JlcS0+cmVm c1tpXTsKPiArICAgICAgICAgICAgc2Vnc1tpXS5kZXN0LmZvcmVpZ24uZG9taWQgPSBpb3JlcS0+ ZG9taWRzW2ldOwo+ICsgICAgICAgICAgICBzZWdzW2ldLmRlc3QuZm9yZWlnbi5vZmZzZXQgPSBp b3JlcS0+cmVxLnNlZ1tpXS5maXJzdF9zZWN0ICogZmlsZV9ibGs7Cj4gKyAgICAgICAgICAgIHNl Z3NbaV0uc291cmNlLnZpcnQgPSBpb3JlcS0+di5pb3ZbaV0uaW92X2Jhc2U7Cj4gKyAgICAgICAg fSBlbHNlIHsKPiArICAgICAgICAgICAgc2Vnc1tpXS5mbGFncyA9IEdOVENPUFlfc291cmNlX2dy ZWY7Cj4gKyAgICAgICAgICAgIHNlZ3NbaV0uc291cmNlLmZvcmVpZ24ucmVmID0gaW9yZXEtPnJl ZnNbaV07Cj4gKyAgICAgICAgICAgIHNlZ3NbaV0uc291cmNlLmZvcmVpZ24uZG9taWQgPSBpb3Jl cS0+ZG9taWRzW2ldOwo+ICsgICAgICAgICAgICBzZWdzW2ldLnNvdXJjZS5mb3JlaWduLm9mZnNl dCA9IGlvcmVxLT5yZXEuc2VnW2ldLmZpcnN0X3NlY3QgKiBmaWxlX2JsazsKPiArICAgICAgICAg ICAgc2Vnc1tpXS5kZXN0LnZpcnQgPSBpb3JlcS0+di5pb3ZbaV0uaW92X2Jhc2U7Cj4gKyAgICAg ICAgfQo+ICsgICAgICAgIHNlZ3NbaV0ubGVuID0gKGlvcmVxLT5yZXEuc2VnW2ldLmxhc3Rfc2Vj dAo+ICsgICAgICAgICAgICAgICAgICAgICAgIC0gaW9yZXEtPnJlcS5zZWdbaV0uZmlyc3Rfc2Vj dCArIDEpICogZmlsZV9ibGs7Cj4gKwo+ICsgICAgfQo+ICsKPiArICAgIHJjID0geGVuZ250dGFi X2dyYW50X2NvcHkoZ250LCBjb3VudCwgc2Vncyk7Cj4gKwo+ICsgICAgaWYgKHJjKSB7Cj4gKyAg ICAgICAgeGVuX2JlX3ByaW50ZigmaW9yZXEtPmJsa2Rldi0+eGVuZGV2LCAwLAo+ICsgICAgICAg ICAgICAgICAgICAgICAgImZhaWxlZCB0byBjb3B5IGRhdGEgJWRcbiIsIHJjKTsKPiArICAgICAg ICBpb3JlcS0+YWlvX2Vycm9ycysrOwo+ICsgICAgICAgIHJldHVybiAtMTsKPiArICAgIH0gZWxz ZSB7Cj4gKyAgICAgICAgciA9IDA7Cj4gKyAgICB9Cj4gKwo+ICsgICAgZm9yIChpID0gMDsgaSA8 IGNvdW50OyBpKyspIHsKPiArICAgICAgICBpZiAoc2Vnc1tpXS5zdGF0dXMgIT0gR05UU1Rfb2th eSkgewo+ICsgICAgICAgICAgICB4ZW5fYmVfcHJpbnRmKCZpb3JlcS0+YmxrZGV2LT54ZW5kZXYs IDMsCj4gKyAgICAgICAgICAgICAgICAgICAgICAgICAgImZhaWxlZCB0byBjb3B5IGRhdGEgJWQg Zm9yIGdyZWYgJWQsIGRvbWlkICVkXG4iLCByYywKPiArICAgICAgICAgICAgICAgICAgICAgICAg ICBpb3JlcS0+cmVmc1tpXSwgaW9yZXEtPmRvbWlkc1tpXSk7Cj4gKyAgICAgICAgICAgIGlvcmVx LT5haW9fZXJyb3JzKys7Cj4gKyAgICAgICAgICAgIHIgPSAtMTsKPiArICAgICAgICB9Cj4gKyAg ICB9Cj4gKwo+ICsgICAgcmV0dXJuIHI7Cj4gK30KPiArCj4gIHN0YXRpYyBpbnQgaW9yZXFfcnVu aW9fcWVtdV9haW8oc3RydWN0IGlvcmVxICppb3JlcSk7Cj4gIAo+ICBzdGF0aWMgdm9pZCBxZW11 X2Fpb19jb21wbGV0ZSh2b2lkICpvcGFxdWUsIGludCByZXQpCj4gQEAgLTUxMSw4ICs2MDMsMjkg QEAgc3RhdGljIHZvaWQgcWVtdV9haW9fY29tcGxldGUodm9pZCAqb3BhcXVlLCBpbnQgcmV0KQo+ ICAgICAgICAgIHJldHVybjsKPiAgICAgIH0KPiAgCj4gKyAgICBpZiAoaW9yZXEtPmJsa2Rldi0+ ZmVhdHVyZV9ncmFudF9jb3B5KSB7Cj4gKyAgICAgICAgc3dpdGNoIChpb3JlcS0+cmVxLm9wZXJh dGlvbikgewo+ICsgICAgICAgIGNhc2UgQkxLSUZfT1BfUkVBRDoKPiArICAgICAgICAgICAgLyog aW4gY2FzZSBvZiBmYWlsdXJlIGlvcmVxLT5haW9fZXJyb3JzIGlzIGluY3JlYXNlZCAqLwo+ICsg ICAgICAgICAgICBpb3JlcV9jb3B5KGlvcmVxKTsKPiArICAgICAgICAgICAgZnJlZV9idWZmZXJz KGlvcmVxKTsKPiArICAgICAgICAgICAgYnJlYWs7Cj4gKyAgICAgICAgY2FzZSBCTEtJRl9PUF9X UklURToKPiArICAgICAgICBjYXNlIEJMS0lGX09QX0ZMVVNIX0RJU0tDQUNIRToKPiArICAgICAg ICAgICAgaWYgKCFpb3JlcS0+cmVxLm5yX3NlZ21lbnRzKSB7Cj4gKyAgICAgICAgICAgICAgICBi cmVhazsKPiArICAgICAgICAgICAgfQo+ICsgICAgICAgICAgICBmcmVlX2J1ZmZlcnMoaW9yZXEp Owo+ICsgICAgICAgICAgICBicmVhazsKPiArICAgICAgICBkZWZhdWx0Ogo+ICsgICAgICAgICAg ICBicmVhazsKPiArICAgICAgICB9Cj4gKyAgICB9Cj4gKwo+ICAgICAgaW9yZXEtPnN0YXR1cyA9 IGlvcmVxLT5haW9fZXJyb3JzID8gQkxLSUZfUlNQX0VSUk9SIDogQkxLSUZfUlNQX09LQVk7Cj4g LSAgICBpb3JlcV91bm1hcChpb3JlcSk7Cj4gKyAgICBpZiAoIWlvcmVxLT5ibGtkZXYtPmZlYXR1 cmVfZ3JhbnRfY29weSkgewo+ICsgICAgICAgIGlvcmVxX3VubWFwKGlvcmVxKTsKPiArICAgIH0K PiAgICAgIGlvcmVxX2ZpbmlzaChpb3JlcSk7Cj4gICAgICBzd2l0Y2ggKGlvcmVxLT5yZXEub3Bl cmF0aW9uKSB7Cj4gICAgICBjYXNlIEJMS0lGX09QX1dSSVRFOgo+IEBAIC01MzgsOCArNjUxLDIw IEBAIHN0YXRpYyBpbnQgaW9yZXFfcnVuaW9fcWVtdV9haW8oc3RydWN0IGlvcmVxICppb3JlcSkK PiAgewo+ICAgICAgc3RydWN0IFhlbkJsa0RldiAqYmxrZGV2ID0gaW9yZXEtPmJsa2RldjsKPiAg Cj4gLSAgICBpZiAoaW9yZXEtPnJlcS5ucl9zZWdtZW50cyAmJiBpb3JlcV9tYXAoaW9yZXEpID09 IC0xKSB7Cj4gLSAgICAgICAgZ290byBlcnJfbm9fbWFwOwo+ICsgICAgaWYgKGlvcmVxLT5ibGtk ZXYtPmZlYXR1cmVfZ3JhbnRfY29weSkgewo+ICsgICAgICAgIGlvcmVxX2luaXRfY29weV9idWZm ZXJzKGlvcmVxKTsKPiArICAgICAgICBpZiAoaW9yZXEtPnJlcS5ucl9zZWdtZW50cyAmJiAoaW9y ZXEtPnJlcS5vcGVyYXRpb24gPT0gQkxLSUZfT1BfV1JJVEUgfHwKPiArICAgICAgICAgICAgaW9y ZXEtPnJlcS5vcGVyYXRpb24gPT0gQkxLSUZfT1BfRkxVU0hfRElTS0NBQ0hFKSkgewo+ICsgICAg ICAgICAgICBpZiAoaW9yZXFfY29weShpb3JlcSkpIHsKPiArICAgICAgICAgICAgICAgIGZyZWVf YnVmZmVycyhpb3JlcSk7Cj4gKyAgICAgICAgICAgICAgICBnb3RvIGVycjsKPiArICAgICAgICAg ICAgfQo+ICsgICAgICAgIH0KPiArCj4gKyAgICB9IGVsc2Ugewo+ICsgICAgICAgIGlmIChpb3Jl cS0+cmVxLm5yX3NlZ21lbnRzICYmIGlvcmVxX21hcChpb3JlcSkpIHsKPiArICAgICAgICAgICAg Z290byBlcnI7Cj4gKyAgICAgICAgfQo+ICAgICAgfQo+ICAKPiAgICAgIGlvcmVxLT5haW9faW5m bGlnaHQrKzsKPiBAQCAtNTgyLDYgKzcwNyw5IEBAIHN0YXRpYyBpbnQgaW9yZXFfcnVuaW9fcWVt dV9haW8oc3RydWN0IGlvcmVxICppb3JlcSkKPiAgICAgIH0KPiAgICAgIGRlZmF1bHQ6Cj4gICAg ICAgICAgLyogdW5rbm93biBvcGVyYXRpb24gKHNob3VsZG4ndCBoYXBwZW4gLS0gcGFyc2UgY2F0 Y2hlcyB0aGlzKSAqLwo+ICsgICAgICAgIGlmICghaW9yZXEtPmJsa2Rldi0+ZmVhdHVyZV9ncmFu dF9jb3B5KSB7Cj4gKyAgICAgICAgICAgIGlvcmVxX3VubWFwKGlvcmVxKTsKPiArICAgICAgICB9 Cj4gICAgICAgICAgZ290byBlcnI7Cj4gICAgICB9Cj4gIAo+IEBAIC01OTAsOCArNzE4LDYgQEAg c3RhdGljIGludCBpb3JlcV9ydW5pb19xZW11X2FpbyhzdHJ1Y3QgaW9yZXEgKmlvcmVxKQo+ICAg ICAgcmV0dXJuIDA7Cj4gIAo+ICBlcnI6Cj4gLSAgICBpb3JlcV91bm1hcChpb3JlcSk7Cj4gLWVy cl9ub19tYXA6Cj4gICAgICBpb3JlcV9maW5pc2goaW9yZXEpOwo+ICAgICAgaW9yZXEtPnN0YXR1 cyA9IEJMS0lGX1JTUF9FUlJPUjsKPiAgICAgIHJldHVybiAtMTsKPiBAQCAtMTAzMiw2ICsxMTU4 LDEyIEBAIHN0YXRpYyBpbnQgYmxrX2Nvbm5lY3Qoc3RydWN0IFhlbkRldmljZSAqeGVuZGV2KQo+ ICAKPiAgICAgIHhlbl9iZV9iaW5kX2V2dGNobigmYmxrZGV2LT54ZW5kZXYpOwo+ICAKPiArICAg IGJsa2Rldi0+ZmVhdHVyZV9ncmFudF9jb3B5ID0KPiArICAgICAgICAgICAgICAgICh4ZW5nbnR0 YWJfZ3JhbnRfY29weShibGtkZXYtPnhlbmRldi5nbnR0YWJkZXYsIDAsIE5VTEwpID09IDApOwo+ ICsKPiArICAgIHhlbl9iZV9wcmludGYoJmJsa2Rldi0+eGVuZGV2LCAzLCAiZ3JhbnQgY29weSBv cGVyYXRpb24gJXNcbiIsCj4gKyAgICAgICAgICAgICAgICAgIGJsa2Rldi0+ZmVhdHVyZV9ncmFu dF9jb3B5ID8gImVuYWJsZWQiIDogImRpc2FibGVkIik7Cj4gKwo+ICAgICAgeGVuX2JlX3ByaW50 ZigmYmxrZGV2LT54ZW5kZXYsIDEsICJvazogcHJvdG8gJXMsIHJpbmctcmVmICVkLCAiCj4gICAg ICAgICAgICAgICAgICAgICJyZW1vdGUgcG9ydCAlZCwgbG9jYWwgcG9ydCAlZFxuIiwKPiAgICAg ICAgICAgICAgICAgICAgYmxrZGV2LT54ZW5kZXYucHJvdG9jb2wsIGJsa2Rldi0+cmluZ19yZWYs Cj4gZGlmZiAtLWdpdCBhL2luY2x1ZGUvaHcveGVuL3hlbl9jb21tb24uaCBiL2luY2x1ZGUvaHcv eGVuL3hlbl9jb21tb24uaAo+IGluZGV4IDY0MGMzMWUuLmU4MGM2MWYgMTAwNjQ0Cj4gLS0tIGEv aW5jbHVkZS9ody94ZW4veGVuX2NvbW1vbi5oCj4gKysrIGIvaW5jbHVkZS9ody94ZW4veGVuX2Nv bW1vbi5oCj4gQEAgLTI1LDYgKzI1LDMxIEBACj4gICAqLwo+ICAKPiAgLyogWGVuIDQuMiB0aHJv dWdoIDQuNiAqLwo+ICsjaWYgQ09ORklHX1hFTl9DVFJMX0lOVEVSRkFDRV9WRVJTSU9OIDwgNDgw Cj4gKwo+ICtzdHJ1Y3QgeGVuZ250dGFiX2dyYW50X2NvcHlfc2VnbWVudCB7Cj4gKyAgICB1bmlv biB4ZW5nbnR0YWJfY29weV9wdHIgewo+ICsgICAgICAgIHZvaWQgKnZpcnQ7Cj4gKyAgICAgICAg c3RydWN0IHsKPiArICAgICAgICAgICAgdWludDMyX3QgcmVmOwo+ICsgICAgICAgICAgICB1aW50 MTZfdCBvZmZzZXQ7Cj4gKyAgICAgICAgICAgIHVpbnQxNl90IGRvbWlkOwo+ICsgICAgICAgIH0g Zm9yZWlnbjsKPiArICAgIH0gc291cmNlLCBkZXN0Owo+ICsgICAgdWludDE2X3QgbGVuOwo+ICsg ICAgdWludDE2X3QgZmxhZ3M7Cj4gKyAgICBpbnQxNl90IHN0YXR1czsKPiArfTsKCkkgZG9uJ3Qg dGhpbmsgaXQncyBhIGdvb2QgaWRlZSB0byBkZWZpbmUgYSBzdHJ1Y3QgdGhhdCBpcyBub3QgZ29p bmcgdG8KYmUgdXNlZCwgYW5kIGRvZXMgbm90IGJlbG9uZyBoZXJlLiBUaGUgdHlwZWRlZiBpcyBP Sy4KCkluIHhlbl9kaXNrLmMsIHlvdSBjb3VsZCB1c2UgIiNpZiBDT05GSUdfWEVOX0NUUkxfSU5U RVJGQUNFX1ZFUlNJT04gLi4uIgphcm91bmQgZnJlZV9idWZmZXJzLCBpb3JlcV9pbml0X2NvcHlf YnVmZmVycyBhbmQgaW9yZXFfY29weSwgYW5kIHJlcGxhY2UKdGhlbSBieSBzdHVicyB3aGVuIFhl biBkb2VzIG5vdCBzdXBwb3J0IGdyYW50IGNvcHkuIEkgdGhpbmsgdGhhdCB3b3VsZApiZSBiZXR0 ZXIuCgpBbHNvLCBjb3VsZCB5b3UgdHJ5IHRvIGNvbXBpbGUgYWdhaW4geGVuIHVuc3RhYmxlLCB3 aXRob3V0IHlvdXIgb3RoZXIgcGF0Y2g/ClJpZ2h0IG5vdywgaXQgZG9lcyBub3QgY29tcGlsZS4K Cj4gK3R5cGVkZWYgc3RydWN0IHhlbmdudHRhYl9ncmFudF9jb3B5X3NlZ21lbnQgeGVuZ250dGFi X2dyYW50X2NvcHlfc2VnbWVudF90Owo+ICsKPiArc3RhdGljIGlubGluZSBpbnQgeGVuZ250dGFi X2dyYW50X2NvcHkoeGVuZ250dGFiX2hhbmRsZSAqeGd0LCB1aW50MzJfdCBjb3VudCwKPiArICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeGVuZ250dGFiX2dyYW50X2NvcHlf c2VnbWVudF90ICpzZWdzKQo+ICt7Cj4gKyAgICByZXR1cm4gLTE7CgpyZXR1cm4gLUVOT1NZUyB3 b3VsZCBiZSBtb3JlIGFwcHJvcHJpYXRlLgoKCk90aGVyd2lzZSwgdGhlIHBhdGNoIGxvb2tzIGdv b2QuCgpUaGFua3MsCgotLSAKQW50aG9ueSBQRVJBUkQKCl9fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fClhlbi1kZXZlbCBtYWlsaW5nIGxpc3QKWGVuLWRldmVs QGxpc3RzLnhlbi5vcmcKaHR0cHM6Ly9saXN0cy54ZW4ub3JnL3hlbi1kZXZlbAo=