From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1165119AbdD1KIz (ORCPT ); Fri, 28 Apr 2017 06:08:55 -0400 Received: from mail.fireflyinternet.com ([109.228.58.192]:55232 "EHLO fireflyinternet.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S968171AbdD1KIq (ORCPT ); Fri, 28 Apr 2017 06:08:46 -0400 X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Date: Fri, 28 Apr 2017 11:08:36 +0100 From: Chris Wilson To: Xiaoguang Chen Cc: kraxel@redhat.com, alex.williamson@redhat.com, intel-gfx@lists.freedesktop.org, intel-gvt-dev@lists.freedesktop.org, zhi.a.wang@intel.com, zhenyuw@linux.intel.com, linux-kernel@vger.kernel.org, zhiyuan.lv@intel.com, kevin.tian@intel.com Subject: Re: [Intel-gfx] [RFC PATCH 5/6] drm/i915/gvt: dmabuf support for GVT-g Message-ID: <20170428100836.GM3390@nuc-i3427.alporthouse.com> Mail-Followup-To: Chris Wilson , Xiaoguang Chen , kraxel@redhat.com, alex.williamson@redhat.com, intel-gfx@lists.freedesktop.org, intel-gvt-dev@lists.freedesktop.org, zhi.a.wang@intel.com, zhenyuw@linux.intel.com, linux-kernel@vger.kernel.org, zhiyuan.lv@intel.com, kevin.tian@intel.com References: <1493372130-27727-1-git-send-email-xiaoguang.chen@intel.com> <1493372130-27727-6-git-send-email-xiaoguang.chen@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1493372130-27727-6-git-send-email-xiaoguang.chen@intel.com> User-Agent: Mutt/1.5.21 (2010-09-15) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Fri, Apr 28, 2017 at 05:35:29PM +0800, Xiaoguang Chen wrote: > dmabuf for GVT-g can be exported to users who can use the dmabuf to show > the desktop of vm which use intel vgpu. > > Currently we provide query and create new dmabuf operations. > > Users of dmabuf can cache some created dmabufs and related information such > as the framebuffer's address, size, tiling mode, width, height etc. When > refresh the screen first query the currnet vgpu's frambuffer and compare > with the cached ones(address, size, tiling, width, height etc) if found one > then reuse the found dmabuf to gain performance improvment. > > If there is no dmabuf created yet or not found in the cached dmabufs then > need to create a new dmabuf. To create a dmabuf first a gem object will > be created and the backing storage of this gem object is the vgpu's > framebuffer(primary/cursor). Then associate this gem object to a dmabuf > and export this dmabuf. A file descriptor will be generated for this dmabuf > and this file descriptor can be sent to user space to do display. > > Signed-off-by: Xiaoguang Chen > --- > drivers/gpu/drm/i915/gvt/Makefile | 2 +- > drivers/gpu/drm/i915/gvt/dmabuf.c | 268 ++++++++++++++++++++++++++++++++++++++ > drivers/gpu/drm/i915/gvt/dmabuf.h | 50 +++++++ > drivers/gpu/drm/i915/gvt/gvt.h | 1 + > 4 files changed, 320 insertions(+), 1 deletion(-) > create mode 100644 drivers/gpu/drm/i915/gvt/dmabuf.c > create mode 100644 drivers/gpu/drm/i915/gvt/dmabuf.h > > diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile > index 192ca26..e480f7d 100644 > --- a/drivers/gpu/drm/i915/gvt/Makefile > +++ b/drivers/gpu/drm/i915/gvt/Makefile > @@ -2,7 +2,7 @@ GVT_DIR := gvt > GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \ > interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \ > execlist.o scheduler.o sched_policy.o render.o cmd_parser.o \ > - fb_decoder.o > + fb_decoder.o dmabuf.o > > ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall > i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) > diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c > new file mode 100644 > index 0000000..d776dfa > --- /dev/null > +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c > @@ -0,0 +1,268 @@ > +/* > + * Copyright 2017 Intel Corporation. All rights reserved. > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER > + * DEALINGS IN THE SOFTWARE. > + * > + * Authors: > + * Zhiyuan Lv > + * > + * Contributors: > + * Xiaoguang Chen > + */ > + > +#include > +#include > + > +#include "i915_drv.h" > +#include "gvt.h" > + > +static struct sg_table *intel_vgpu_gem_get_pages( > + struct drm_i915_gem_object *obj) > +{ > + WARN_ON(1); > + return NULL; > +} > + > +static void intel_vgpu_gem_put_pages(struct drm_i915_gem_object *obj, > + struct sg_table *pages) > +{ > + /* like stolen memory, this should only be called during free > + * after clearing pin count. > + */ Time to re-read how stolen works (see get_pages and pinning on creation). > + sg_free_table(pages); > + kfree(pages); > +} > + > +static const struct drm_i915_gem_object_ops intel_vgpu_gem_ops = { > + .get_pages = intel_vgpu_gem_get_pages, > + .put_pages = intel_vgpu_gem_put_pages, > +}; > + > +#define GEN8_DECODE_PTE(pte) \ > + ((dma_addr_t)(((((u64)pte) >> 12) & 0x7ffffffULL) << 12)) > + > +#define GEN7_DECODE_PTE(pte) \ > + ((dma_addr_t)(((((u64)pte) & 0x7f0) << 28) | (u64)(pte & 0xfffff000))) > + > +static struct sg_table * > +intel_vgpu_create_sg_pages(struct drm_device *dev, u32 start, u32 num_pages) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct sg_table *st; > + struct scatterlist *sg; > + int i; > + gen8_pte_t __iomem *gtt_entries; > + > + st = kmalloc(sizeof(*st), GFP_KERNEL); > + if (st == NULL) > + return NULL; > + > + if (sg_alloc_table(st, num_pages, GFP_KERNEL)) { > + kfree(st); > + return NULL; > + } > + > + gtt_entries = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + > + (start >> PAGE_SHIFT); > + for_each_sg(st->sgl, sg, num_pages, i) { > + sg->offset = 0; > + sg->length = PAGE_SIZE; > + sg_dma_address(sg) = > + GEN8_DECODE_PTE(readq(>t_entries[i])); > + sg_dma_len(sg) = PAGE_SIZE; > + } This should be get_pages. > + return st; > +} > + > +static struct drm_i915_gem_object *intel_vgpu_create_gem(struct drm_device *dev, > + struct intel_vgpu_dmabuf *info) > +{ > + struct drm_i915_gem_object *obj; > + struct drm_i915_private *pri = dev->dev_private; > + > + obj = i915_gem_object_alloc(pri); > + if (obj == NULL) > + return NULL; > + > + drm_gem_private_object_init(dev, &obj->base, info->size << PAGE_SHIFT); > + i915_gem_object_init(obj, &intel_vgpu_gem_ops); > + obj->mm.pages = intel_vgpu_create_sg_pages(dev, info->start, > + info->size); > + if (obj->mm.pages == NULL) { > + i915_gem_object_free(obj); > + return NULL; > + } Having created the obj, just call i915_gem_object_pin_pages(). Or better yet, don't pin the pages upon creation and just defer it to first use - which be very soon. > + obj->cache_level = I915_CACHE_L3_LLC; Are you sure? > + if (IS_SKYLAKE(pri)) { > + unsigned int tiling_mode = 0; > + > + switch (info->tiled << 10) { > + case PLANE_CTL_TILED_LINEAR: > + tiling_mode = I915_TILING_NONE; > + break; > + case PLANE_CTL_TILED_X: > + tiling_mode = I915_TILING_X; > + break; > + case PLANE_CTL_TILED_Y: > + tiling_mode = I915_TILING_Y; > + break; > + default: > + gvt_dbg_core("tile %d not supported\n", info->tiled); > + } > + obj->tiling_and_stride = tiling_mode | info->stride; If tiling_mode == 0, stride must be zero. Is that enforced? > + } else { > + obj->tiling_and_stride = (info->tiled ? I915_TILING_X : > + I915_TILING_NONE) | (info->tiled ? info->stride : 0); Rewrite this neatly. Hint obj->tiling_and_stride starts as zero and you don't need to do any of this if !tiled. > + } > + > + return obj; > +} > + > +static int intel_vgpu_get_plane_info(struct drm_device *dev, > + struct intel_vgpu *vgpu, > + struct intel_vgpu_dmabuf *info) > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct intel_vgpu_primary_plane_format *p; > + struct intel_vgpu_cursor_plane_format *c; > + > + if (info->plane_id == INTEL_GVT_PLANE_PRIMARY) { > + p = (struct intel_vgpu_primary_plane_format *) > + intel_vgpu_decode_plane(dev, vgpu, info->plane_id); > + if (p != NULL) { > + info->start = p->base; > + info->width = p->width; > + info->height = p->height; > + info->stride = p->stride; > + info->drm_format = p->drm_format; > + info->tiled = p->tiled; > + info->size = (((p->stride * p->height * p->bpp) / 8) + > + (PAGE_SIZE - 1)) >> PAGE_SHIFT; > + } else { > + gvt_dbg_core("invalid primary plane\n"); > + return -EINVAL; > + } > + } else if (info->plane_id == INTEL_GVT_PLANE_CURSOR) { > + c = (struct intel_vgpu_cursor_plane_format *) > + intel_vgpu_decode_plane(dev, vgpu, info->plane_id); > + if (c != NULL) { > + info->start = c->base; > + info->width = c->width; > + info->height = c->height; > + info->stride = c->width * (c->bpp / 8); > + info->tiled = 0; > + info->x_pos = c->x_pos; > + info->y_pos = c->y_pos; > + info->size = (((info->stride * c->height * c->bpp) / 8) + > + (PAGE_SIZE - 1)) >> PAGE_SHIFT; > + } else { > + gvt_dbg_core("invalid cursor plane\n"); > + return -EINVAL; > + } > + } else { > + gvt_vgpu_err("invalid plane id:%d\n", info->plane_id); > + return -EINVAL; > + } > + > + if (info->start & (PAGE_SIZE - 1)) { > + gvt_vgpu_err("Not aligned fb address:0x%x\n", info->start); > + return -EINVAL; > + } > + if (((info->start >> PAGE_SHIFT) + info->size) > > + ggtt_total_entries(&dev_priv->ggtt)) { > + gvt_vgpu_err("Invalid GTT offset or size\n"); > + return -EINVAL; > + } > + > + return 0; > +} > + > +static struct drm_i915_gem_object *intel_vgpu_create_gem_from_vgpuid( > + struct drm_device *dev, struct intel_vgpu *vgpu, > + struct intel_vgpu_dmabuf *info) > +{ > + struct drm_i915_gem_object *obj; > + int ret; > + > + ret = intel_vgpu_get_plane_info(dev, vgpu, info); > + if (ret) { > + gvt_vgpu_err("get plane info failed:%d\n", info->plane_id); > + return NULL; Propagate errors. > + } > + obj = intel_vgpu_create_gem(dev, info); > + > + return obj; > +} > + > +int intel_vgpu_query_dmabuf(struct intel_vgpu *vgpu, void *args) > +{ > + struct drm_device *dev = &vgpu->gvt->dev_priv->drm; > + int ret; > + struct intel_vgpu_dmabuf *info = args; > + > + ret = intel_vgpu_get_plane_info(dev, vgpu, info); > + if (ret) { > + gvt_vgpu_err("get plane info failed:%d\n", info->plane_id); > + return -EINVAL; > + } > + > + return 0; > +} > + > +int intel_vgpu_generate_dmabuf(struct intel_vgpu *vgpu, void *args) > +{ > + struct dma_buf *dmabuf; > + struct drm_i915_gem_object *obj; > + struct drm_device *dev = &vgpu->gvt->dev_priv->drm; > + int ret; > + struct intel_vgpu_dmabuf *info = args; > + struct dma_buf_export_info exp_info = { > + .exp_name = KBUILD_MODNAME, > + .owner = THIS_MODULE }; > + > + obj = intel_vgpu_create_gem_from_vgpuid(dev, vgpu, info); > + if (obj == NULL) { > + gvt_vgpu_err("create gvt gem obj failed:%d\n", vgpu->id); > + return -EINVAL; > + } > + > + exp_info.ops = &i915_dmabuf_ops; Please put back my private i915_dmabuf_ops from where you stole it from. Just call dmabuf = i915_gem_prime_export(dev, obj, DRM_CLOEXEC | DRM_RDWR); > + exp_info.size = obj->base.size; > + exp_info.flags = DRM_CLOEXEC | DRM_RDWR; > + exp_info.priv = &obj->base; > + exp_info.resv = obj->resv; > + > + dmabuf = drm_gem_dmabuf_export(dev, &exp_info); > + if (IS_ERR(dmabuf)) { > + gvt_vgpu_err("intel vgpu export dma-buf failed\n"); > + mutex_unlock(&dev->object_name_lock); > + return -EINVAL; > + } > + > + ret = dma_buf_fd(dmabuf, exp_info.flags); > + if (ret < 0) { > + gvt_vgpu_err("intel vgpu create dma-buf fd failed\n"); > + return ret; > + } > + info->fd = ret; > + > + return 0; > +} > diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h b/drivers/gpu/drm/i915/gvt/dmabuf.h > new file mode 100644 > index 0000000..c590f4a > --- /dev/null > +++ b/drivers/gpu/drm/i915/gvt/dmabuf.h > @@ -0,0 +1,50 @@ > +/* > + * Copyright(c) 2017 Intel Corporation. All rights reserved. > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice (including the next > + * paragraph) shall be included in all copies or substantial portions of the > + * Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE > + * SOFTWARE. > + * > + */ > + > +#ifndef _GVT_DMABUF_H_ > +#define _GVT_DMABUF_H_ > + > +#define INTEL_VGPU_QUERY_DMABUF 0 > +#define INTEL_VGPU_GENERATE_DMABUF 1 > + > +struct intel_vgpu_dmabuf { This looks to be uapi. What's it doing here? -Chris -- Chris Wilson, Intel Open Source Technology Centre From mboxrd@z Thu Jan 1 00:00:00 1970 From: Chris Wilson Subject: Re: [RFC PATCH 5/6] drm/i915/gvt: dmabuf support for GVT-g Date: Fri, 28 Apr 2017 11:08:36 +0100 Message-ID: <20170428100836.GM3390@nuc-i3427.alporthouse.com> References: <1493372130-27727-1-git-send-email-xiaoguang.chen@intel.com> <1493372130-27727-6-git-send-email-xiaoguang.chen@intel.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: Content-Disposition: inline In-Reply-To: <1493372130-27727-6-git-send-email-xiaoguang.chen@intel.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" To: Xiaoguang Chen Cc: intel-gfx@lists.freedesktop.org, linux-kernel@vger.kernel.org, kraxel@redhat.com, intel-gvt-dev@lists.freedesktop.org, zhiyuan.lv@intel.com List-Id: intel-gfx@lists.freedesktop.org T24gRnJpLCBBcHIgMjgsIDIwMTcgYXQgMDU6MzU6MjlQTSArMDgwMCwgWGlhb2d1YW5nIENoZW4g d3JvdGU6Cj4gZG1hYnVmIGZvciBHVlQtZyBjYW4gYmUgZXhwb3J0ZWQgdG8gdXNlcnMgd2hvIGNh biB1c2UgdGhlIGRtYWJ1ZiB0byBzaG93Cj4gdGhlIGRlc2t0b3Agb2Ygdm0gd2hpY2ggdXNlIGlu dGVsIHZncHUuCj4gCj4gQ3VycmVudGx5IHdlIHByb3ZpZGUgcXVlcnkgYW5kIGNyZWF0ZSBuZXcg ZG1hYnVmIG9wZXJhdGlvbnMuCj4gCj4gVXNlcnMgb2YgZG1hYnVmIGNhbiBjYWNoZSBzb21lIGNy ZWF0ZWQgZG1hYnVmcyBhbmQgcmVsYXRlZCBpbmZvcm1hdGlvbiBzdWNoCj4gYXMgdGhlIGZyYW1l YnVmZmVyJ3MgYWRkcmVzcywgc2l6ZSwgdGlsaW5nIG1vZGUsIHdpZHRoLCBoZWlnaHQgZXRjLiBX aGVuCj4gcmVmcmVzaCB0aGUgc2NyZWVuIGZpcnN0IHF1ZXJ5IHRoZSBjdXJybmV0IHZncHUncyBm cmFtYnVmZmVyIGFuZCBjb21wYXJlCj4gd2l0aCB0aGUgY2FjaGVkIG9uZXMoYWRkcmVzcywgc2l6 ZSwgdGlsaW5nLCB3aWR0aCwgaGVpZ2h0IGV0YykgaWYgZm91bmQgb25lCj4gdGhlbiByZXVzZSB0 aGUgZm91bmQgZG1hYnVmIHRvIGdhaW4gcGVyZm9ybWFuY2UgaW1wcm92bWVudC4KPiAKPiBJZiB0 aGVyZSBpcyBubyBkbWFidWYgY3JlYXRlZCB5ZXQgb3Igbm90IGZvdW5kIGluIHRoZSBjYWNoZWQg ZG1hYnVmcyB0aGVuCj4gbmVlZCB0byBjcmVhdGUgYSBuZXcgZG1hYnVmLiBUbyBjcmVhdGUgYSBk bWFidWYgZmlyc3QgYSBnZW0gb2JqZWN0IHdpbGwKPiBiZSBjcmVhdGVkIGFuZCB0aGUgYmFja2lu ZyBzdG9yYWdlIG9mIHRoaXMgZ2VtIG9iamVjdCBpcyB0aGUgdmdwdSdzCj4gZnJhbWVidWZmZXIo cHJpbWFyeS9jdXJzb3IpLiBUaGVuIGFzc29jaWF0ZSB0aGlzIGdlbSBvYmplY3QgdG8gYSBkbWFi dWYKPiBhbmQgZXhwb3J0IHRoaXMgZG1hYnVmLiBBIGZpbGUgZGVzY3JpcHRvciB3aWxsIGJlIGdl bmVyYXRlZCBmb3IgdGhpcyBkbWFidWYKPiBhbmQgdGhpcyBmaWxlIGRlc2NyaXB0b3IgY2FuIGJl IHNlbnQgdG8gdXNlciBzcGFjZSB0byBkbyBkaXNwbGF5Lgo+IAo+IFNpZ25lZC1vZmYtYnk6IFhp YW9ndWFuZyBDaGVuIDx4aWFvZ3VhbmcuY2hlbkBpbnRlbC5jb20+Cj4gLS0tCj4gIGRyaXZlcnMv Z3B1L2RybS9pOTE1L2d2dC9NYWtlZmlsZSB8ICAgMiArLQo+ICBkcml2ZXJzL2dwdS9kcm0vaTkx NS9ndnQvZG1hYnVmLmMgfCAyNjggKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysr KysKPiAgZHJpdmVycy9ncHUvZHJtL2k5MTUvZ3Z0L2RtYWJ1Zi5oIHwgIDUwICsrKysrKysKPiAg ZHJpdmVycy9ncHUvZHJtL2k5MTUvZ3Z0L2d2dC5oICAgIHwgICAxICsKPiAgNCBmaWxlcyBjaGFu Z2VkLCAzMjAgaW5zZXJ0aW9ucygrKSwgMSBkZWxldGlvbigtKQo+ICBjcmVhdGUgbW9kZSAxMDA2 NDQgZHJpdmVycy9ncHUvZHJtL2k5MTUvZ3Z0L2RtYWJ1Zi5jCj4gIGNyZWF0ZSBtb2RlIDEwMDY0 NCBkcml2ZXJzL2dwdS9kcm0vaTkxNS9ndnQvZG1hYnVmLmgKPiAKPiBkaWZmIC0tZ2l0IGEvZHJp dmVycy9ncHUvZHJtL2k5MTUvZ3Z0L01ha2VmaWxlIGIvZHJpdmVycy9ncHUvZHJtL2k5MTUvZ3Z0 L01ha2VmaWxlCj4gaW5kZXggMTkyY2EyNi4uZTQ4MGY3ZCAxMDA2NDQKPiAtLS0gYS9kcml2ZXJz L2dwdS9kcm0vaTkxNS9ndnQvTWFrZWZpbGUKPiArKysgYi9kcml2ZXJzL2dwdS9kcm0vaTkxNS9n dnQvTWFrZWZpbGUKPiBAQCAtMiw3ICsyLDcgQEAgR1ZUX0RJUiA6PSBndnQKPiAgR1ZUX1NPVVJD RSA6PSBndnQubyBhcGVydHVyZV9nbS5vIGhhbmRsZXJzLm8gdmdwdS5vIHRyYWNlX3BvaW50cy5v IGZpcm13YXJlLm8gXAo+ICAJaW50ZXJydXB0Lm8gZ3R0Lm8gY2ZnX3NwYWNlLm8gb3ByZWdpb24u byBtbWlvLm8gZGlzcGxheS5vIGVkaWQubyBcCj4gIAlleGVjbGlzdC5vIHNjaGVkdWxlci5vIHNj aGVkX3BvbGljeS5vIHJlbmRlci5vIGNtZF9wYXJzZXIubyBcCj4gLQlmYl9kZWNvZGVyLm8KPiAr CWZiX2RlY29kZXIubyBkbWFidWYubwo+ICAKPiAgY2NmbGFncy15CQkJCSs9IC1JJChzcmMpIC1J JChzcmMpLyQoR1ZUX0RJUikgLVdhbGwKPiAgaTkxNS15CQkJCQkrPSAkKGFkZHByZWZpeCAkKEdW VF9ESVIpLywgJChHVlRfU09VUkNFKSkKPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL2k5 MTUvZ3Z0L2RtYWJ1Zi5jIGIvZHJpdmVycy9ncHUvZHJtL2k5MTUvZ3Z0L2RtYWJ1Zi5jCj4gbmV3 IGZpbGUgbW9kZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwLi5kNzc2ZGZhCj4gLS0tIC9kZXYvbnVs bAo+ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS9pOTE1L2d2dC9kbWFidWYuYwo+IEBAIC0wLDAgKzEs MjY4IEBACj4gKy8qCj4gKyAqIENvcHlyaWdodCAyMDE3IEludGVsIENvcnBvcmF0aW9uLiBBbGwg cmlnaHRzIHJlc2VydmVkLgo+ICsgKgo+ICsgKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVk LCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYQo+ICsgKiBjb3B5IG9m IHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlICJT b2Z0d2FyZSIpLAo+ICsgKiB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0 aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uCj4gKyAqIHRoZSByaWdodHMgdG8gdXNl LCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLAo+ ICsgKiBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBl cnNvbnMgdG8gd2hvbSB0aGUKPiArICogU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBz dWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoKPiArICoKPiArICogVGhlIGFib3Zl IGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2UgKGluY2x1ZGluZyB0 aGUgbmV4dAo+ICsgKiBwYXJhZ3JhcGgpIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMg b3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlCj4gKyAqIFNvZnR3YXJlLgo+ICsgKgo+ICsg KiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgIkFTIElTIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBB TlkgS0lORCwgRVhQUkVTUyBPUgo+ICsgKiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1J VEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSwKPiArICogRklUTkVTUyBG T1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gIElOIE5PIEVWRU5U IFNIQUxMCj4gKyAqIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBG T1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSCj4gKyAqIExJQUJJTElUWSwgV0hFVEhFUiBJ TiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HCj4gKyAq IEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBV U0UgT1IgT1RIRVIKPiArICogREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLgo+ICsgKgo+ICsgKiBB dXRob3JzOgo+ICsgKiAgICBaaGl5dWFuIEx2IDx6aGl5dWFuLmx2QGludGVsLmNvbT4KPiArICoK PiArICogQ29udHJpYnV0b3JzOgo+ICsgKiAgICBYaWFvZ3VhbmcgQ2hlbiA8eGlhb2d1YW5nLmNo ZW5AaW50ZWwuY29tPgo+ICsgKi8KPiArCj4gKyNpbmNsdWRlIDxsaW51eC9kbWEtYnVmLmg+Cj4g KyNpbmNsdWRlIDxkcm0vZHJtUC5oPgo+ICsKPiArI2luY2x1ZGUgImk5MTVfZHJ2LmgiCj4gKyNp bmNsdWRlICJndnQuaCIKPiArCj4gK3N0YXRpYyBzdHJ1Y3Qgc2dfdGFibGUgKmludGVsX3ZncHVf Z2VtX2dldF9wYWdlcygKPiArCQlzdHJ1Y3QgZHJtX2k5MTVfZ2VtX29iamVjdCAqb2JqKQo+ICt7 Cj4gKwlXQVJOX09OKDEpOwo+ICsJcmV0dXJuIE5VTEw7Cj4gK30KPiArCj4gK3N0YXRpYyB2b2lk IGludGVsX3ZncHVfZ2VtX3B1dF9wYWdlcyhzdHJ1Y3QgZHJtX2k5MTVfZ2VtX29iamVjdCAqb2Jq LAo+ICsJCXN0cnVjdCBzZ190YWJsZSAqcGFnZXMpCj4gK3sKPiArCS8qIGxpa2Ugc3RvbGVuIG1l bW9yeSwgdGhpcyBzaG91bGQgb25seSBiZSBjYWxsZWQgZHVyaW5nIGZyZWUKPiArCSAqIGFmdGVy IGNsZWFyaW5nIHBpbiBjb3VudC4KPiArCSAqLwoKVGltZSB0byByZS1yZWFkIGhvdyBzdG9sZW4g d29ya3MgKHNlZSBnZXRfcGFnZXMgYW5kIHBpbm5pbmcgb24KY3JlYXRpb24pLgoKPiArCXNnX2Zy ZWVfdGFibGUocGFnZXMpOwo+ICsJa2ZyZWUocGFnZXMpOwo+ICt9Cj4gKwo+ICtzdGF0aWMgY29u c3Qgc3RydWN0IGRybV9pOTE1X2dlbV9vYmplY3Rfb3BzIGludGVsX3ZncHVfZ2VtX29wcyA9IHsK PiArCS5nZXRfcGFnZXMgPSBpbnRlbF92Z3B1X2dlbV9nZXRfcGFnZXMsCj4gKwkucHV0X3BhZ2Vz ID0gaW50ZWxfdmdwdV9nZW1fcHV0X3BhZ2VzLAo+ICt9Owo+ICsKPiArI2RlZmluZSBHRU44X0RF Q09ERV9QVEUocHRlKSBcCj4gKwkoKGRtYV9hZGRyX3QpKCgoKCh1NjQpcHRlKSA+PiAxMikgJiAw eDdmZmZmZmZVTEwpIDw8IDEyKSkKPiArCj4gKyNkZWZpbmUgR0VON19ERUNPREVfUFRFKHB0ZSkg XAo+ICsJKChkbWFfYWRkcl90KSgoKCgodTY0KXB0ZSkgJiAweDdmMCkgPDwgMjgpIHwgKHU2NCko cHRlICYgMHhmZmZmZjAwMCkpKQo+ICsKPiArc3RhdGljIHN0cnVjdCBzZ190YWJsZSAqCj4gK2lu dGVsX3ZncHVfY3JlYXRlX3NnX3BhZ2VzKHN0cnVjdCBkcm1fZGV2aWNlICpkZXYsIHUzMiBzdGFy dCwgdTMyIG51bV9wYWdlcykKPiArewo+ICsJc3RydWN0IGRybV9pOTE1X3ByaXZhdGUgKmRldl9w cml2ID0gZGV2LT5kZXZfcHJpdmF0ZTsKPiArCXN0cnVjdCBzZ190YWJsZSAqc3Q7Cj4gKwlzdHJ1 Y3Qgc2NhdHRlcmxpc3QgKnNnOwo+ICsJaW50IGk7Cj4gKwlnZW44X3B0ZV90IF9faW9tZW0gKmd0 dF9lbnRyaWVzOwo+ICsKPiArCXN0ID0ga21hbGxvYyhzaXplb2YoKnN0KSwgR0ZQX0tFUk5FTCk7 Cj4gKwlpZiAoc3QgPT0gTlVMTCkKPiArCQlyZXR1cm4gTlVMTDsKPiArCj4gKwlpZiAoc2dfYWxs b2NfdGFibGUoc3QsIG51bV9wYWdlcywgR0ZQX0tFUk5FTCkpIHsKPiArCQlrZnJlZShzdCk7Cj4g KwkJcmV0dXJuIE5VTEw7Cj4gKwl9Cj4gKwo+ICsJZ3R0X2VudHJpZXMgPSAoZ2VuOF9wdGVfdCBf X2lvbWVtICopZGV2X3ByaXYtPmdndHQuZ3NtICsKPiArCQkoc3RhcnQgPj4gUEFHRV9TSElGVCk7 Cj4gKwlmb3JfZWFjaF9zZyhzdC0+c2dsLCBzZywgbnVtX3BhZ2VzLCBpKSB7Cj4gKwkJc2ctPm9m ZnNldCA9IDA7Cj4gKwkJc2ctPmxlbmd0aCA9IFBBR0VfU0laRTsKPiArCQlzZ19kbWFfYWRkcmVz cyhzZykgPQo+ICsJCQlHRU44X0RFQ09ERV9QVEUocmVhZHEoJmd0dF9lbnRyaWVzW2ldKSk7Cj4g KwkJc2dfZG1hX2xlbihzZykgPSBQQUdFX1NJWkU7Cj4gKwl9CgpUaGlzIHNob3VsZCBiZSBnZXRf cGFnZXMuCgo+ICsJcmV0dXJuIHN0Owo+ICt9Cj4gKwo+ICtzdGF0aWMgc3RydWN0IGRybV9pOTE1 X2dlbV9vYmplY3QgKmludGVsX3ZncHVfY3JlYXRlX2dlbShzdHJ1Y3QgZHJtX2RldmljZSAqZGV2 LAo+ICsJCXN0cnVjdCBpbnRlbF92Z3B1X2RtYWJ1ZiAqaW5mbykKPiArewo+ICsJc3RydWN0IGRy bV9pOTE1X2dlbV9vYmplY3QgKm9iajsKPiArCXN0cnVjdCBkcm1faTkxNV9wcml2YXRlICpwcmkg PSBkZXYtPmRldl9wcml2YXRlOwo+ICsKPiArCW9iaiA9IGk5MTVfZ2VtX29iamVjdF9hbGxvYyhw cmkpOwo+ICsJaWYgKG9iaiA9PSBOVUxMKQo+ICsJCXJldHVybiBOVUxMOwo+ICsKPiArCWRybV9n ZW1fcHJpdmF0ZV9vYmplY3RfaW5pdChkZXYsICZvYmotPmJhc2UsIGluZm8tPnNpemUgPDwgUEFH RV9TSElGVCk7Cj4gKwlpOTE1X2dlbV9vYmplY3RfaW5pdChvYmosICZpbnRlbF92Z3B1X2dlbV9v cHMpOwo+ICsJb2JqLT5tbS5wYWdlcyA9IGludGVsX3ZncHVfY3JlYXRlX3NnX3BhZ2VzKGRldiwg aW5mby0+c3RhcnQsCj4gKwkJCWluZm8tPnNpemUpOwo+ICsJaWYgKG9iai0+bW0ucGFnZXMgPT0g TlVMTCkgewo+ICsJCWk5MTVfZ2VtX29iamVjdF9mcmVlKG9iaik7Cj4gKwkJcmV0dXJuIE5VTEw7 Cj4gKwl9CgpIYXZpbmcgY3JlYXRlZCB0aGUgb2JqLCBqdXN0IGNhbGwgaTkxNV9nZW1fb2JqZWN0 X3Bpbl9wYWdlcygpLiBPciBiZXR0ZXIKeWV0LCBkb24ndCBwaW4gdGhlIHBhZ2VzIHVwb24gY3Jl YXRpb24gYW5kIGp1c3QgZGVmZXIgaXQgdG8gZmlyc3QgdXNlIC0Kd2hpY2ggYmUgdmVyeSBzb29u LgoKPiArCW9iai0+Y2FjaGVfbGV2ZWwgPSBJOTE1X0NBQ0hFX0wzX0xMQzsKCkFyZSB5b3Ugc3Vy ZT8KCgo+ICsJaWYgKElTX1NLWUxBS0UocHJpKSkgewo+ICsJCXVuc2lnbmVkIGludCB0aWxpbmdf bW9kZSA9IDA7Cj4gKwo+ICsJCXN3aXRjaCAoaW5mby0+dGlsZWQgPDwgMTApIHsKPiArCQljYXNl IFBMQU5FX0NUTF9USUxFRF9MSU5FQVI6Cj4gKwkJCXRpbGluZ19tb2RlID0gSTkxNV9USUxJTkdf Tk9ORTsKPiArCQkJYnJlYWs7Cj4gKwkJY2FzZSBQTEFORV9DVExfVElMRURfWDoKPiArCQkJdGls aW5nX21vZGUgPSBJOTE1X1RJTElOR19YOwo+ICsJCQlicmVhazsKPiArCQljYXNlIFBMQU5FX0NU TF9USUxFRF9ZOgo+ICsJCQl0aWxpbmdfbW9kZSA9IEk5MTVfVElMSU5HX1k7Cj4gKwkJCWJyZWFr Owo+ICsJCWRlZmF1bHQ6Cj4gKwkJCWd2dF9kYmdfY29yZSgidGlsZSAlZCBub3Qgc3VwcG9ydGVk XG4iLCBpbmZvLT50aWxlZCk7Cj4gKwkJfQo+ICsJCW9iai0+dGlsaW5nX2FuZF9zdHJpZGUgPSB0 aWxpbmdfbW9kZSB8IGluZm8tPnN0cmlkZTsKCklmIHRpbGluZ19tb2RlID09IDAsIHN0cmlkZSBt dXN0IGJlIHplcm8uIElzIHRoYXQgZW5mb3JjZWQ/Cgo+ICsJfSBlbHNlIHsKPiArCQlvYmotPnRp bGluZ19hbmRfc3RyaWRlID0gKGluZm8tPnRpbGVkID8gSTkxNV9USUxJTkdfWCA6Cj4gKwkJCUk5 MTVfVElMSU5HX05PTkUpIHwgKGluZm8tPnRpbGVkID8gaW5mby0+c3RyaWRlIDogMCk7CgpSZXdy aXRlIHRoaXMgbmVhdGx5LgpIaW50IG9iai0+dGlsaW5nX2FuZF9zdHJpZGUgc3RhcnRzIGFzIHpl cm8gYW5kIHlvdSBkb24ndCBuZWVkIHRvIGRvIGFueQpvZiB0aGlzIGlmICF0aWxlZC4KCj4gKwl9 Cj4gKwo+ICsJcmV0dXJuIG9iajsKPiArfQo+ICsKPiArc3RhdGljIGludCBpbnRlbF92Z3B1X2dl dF9wbGFuZV9pbmZvKHN0cnVjdCBkcm1fZGV2aWNlICpkZXYsCj4gKwkJc3RydWN0IGludGVsX3Zn cHUgKnZncHUsCj4gKwkJc3RydWN0IGludGVsX3ZncHVfZG1hYnVmICppbmZvKQo+ICt7Cj4gKwlz dHJ1Y3QgZHJtX2k5MTVfcHJpdmF0ZSAqZGV2X3ByaXYgPSBkZXYtPmRldl9wcml2YXRlOwo+ICsJ c3RydWN0IGludGVsX3ZncHVfcHJpbWFyeV9wbGFuZV9mb3JtYXQgKnA7Cj4gKwlzdHJ1Y3QgaW50 ZWxfdmdwdV9jdXJzb3JfcGxhbmVfZm9ybWF0ICpjOwo+ICsKPiArCWlmIChpbmZvLT5wbGFuZV9p ZCA9PSBJTlRFTF9HVlRfUExBTkVfUFJJTUFSWSkgewo+ICsJCXAgPSAoc3RydWN0IGludGVsX3Zn cHVfcHJpbWFyeV9wbGFuZV9mb3JtYXQgKikKPiArCQkJaW50ZWxfdmdwdV9kZWNvZGVfcGxhbmUo ZGV2LCB2Z3B1LCBpbmZvLT5wbGFuZV9pZCk7Cj4gKwkJaWYgKHAgIT0gTlVMTCkgewo+ICsJCQlp bmZvLT5zdGFydCA9IHAtPmJhc2U7Cj4gKwkJCWluZm8tPndpZHRoID0gcC0+d2lkdGg7Cj4gKwkJ CWluZm8tPmhlaWdodCA9IHAtPmhlaWdodDsKPiArCQkJaW5mby0+c3RyaWRlID0gcC0+c3RyaWRl Owo+ICsJCQlpbmZvLT5kcm1fZm9ybWF0ID0gcC0+ZHJtX2Zvcm1hdDsKPiArCQkJaW5mby0+dGls ZWQgPSBwLT50aWxlZDsKPiArCQkJaW5mby0+c2l6ZSA9ICgoKHAtPnN0cmlkZSAqIHAtPmhlaWdo dCAqIHAtPmJwcCkgLyA4KSArCj4gKwkJCQkJKFBBR0VfU0laRSAtIDEpKSA+PiBQQUdFX1NISUZU Owo+ICsJCX0gZWxzZSB7Cj4gKwkJCWd2dF9kYmdfY29yZSgiaW52YWxpZCBwcmltYXJ5IHBsYW5l XG4iKTsKPiArCQkJcmV0dXJuIC1FSU5WQUw7Cj4gKwkJfQo+ICsJfSBlbHNlIGlmIChpbmZvLT5w bGFuZV9pZCA9PSBJTlRFTF9HVlRfUExBTkVfQ1VSU09SKSB7Cj4gKwkJYyA9IChzdHJ1Y3QgaW50 ZWxfdmdwdV9jdXJzb3JfcGxhbmVfZm9ybWF0ICopCj4gKwkJCWludGVsX3ZncHVfZGVjb2RlX3Bs YW5lKGRldiwgdmdwdSwgaW5mby0+cGxhbmVfaWQpOwo+ICsJCWlmIChjICE9IE5VTEwpIHsKPiAr CQkJaW5mby0+c3RhcnQgPSBjLT5iYXNlOwo+ICsJCQlpbmZvLT53aWR0aCA9IGMtPndpZHRoOwo+ ICsJCQlpbmZvLT5oZWlnaHQgPSBjLT5oZWlnaHQ7Cj4gKwkJCWluZm8tPnN0cmlkZSA9IGMtPndp ZHRoICogKGMtPmJwcCAvIDgpOwo+ICsJCQlpbmZvLT50aWxlZCA9IDA7Cj4gKwkJCWluZm8tPnhf cG9zID0gYy0+eF9wb3M7Cj4gKwkJCWluZm8tPnlfcG9zID0gYy0+eV9wb3M7Cj4gKwkJCWluZm8t PnNpemUgPSAoKChpbmZvLT5zdHJpZGUgKiBjLT5oZWlnaHQgKiBjLT5icHApIC8gOCkgKwo+ICsJ CQkJCShQQUdFX1NJWkUgLSAxKSkgPj4gUEFHRV9TSElGVDsKPiArCQl9IGVsc2Ugewo+ICsJCQln dnRfZGJnX2NvcmUoImludmFsaWQgY3Vyc29yIHBsYW5lXG4iKTsKPiArCQkJcmV0dXJuIC1FSU5W QUw7Cj4gKwkJfQo+ICsJfSBlbHNlIHsKPiArCQlndnRfdmdwdV9lcnIoImludmFsaWQgcGxhbmUg aWQ6JWRcbiIsIGluZm8tPnBsYW5lX2lkKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiAr Cj4gKwlpZiAoaW5mby0+c3RhcnQgJiAoUEFHRV9TSVpFIC0gMSkpIHsKPiArCQlndnRfdmdwdV9l cnIoIk5vdCBhbGlnbmVkIGZiIGFkZHJlc3M6MHgleFxuIiwgaW5mby0+c3RhcnQpOwo+ICsJCXJl dHVybiAtRUlOVkFMOwo+ICsJfQo+ICsJaWYgKCgoaW5mby0+c3RhcnQgPj4gUEFHRV9TSElGVCkg KyBpbmZvLT5zaXplKSA+Cj4gKwkJZ2d0dF90b3RhbF9lbnRyaWVzKCZkZXZfcHJpdi0+Z2d0dCkp IHsKPiArCQlndnRfdmdwdV9lcnIoIkludmFsaWQgR1RUIG9mZnNldCBvciBzaXplXG4iKTsKPiAr CQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwlyZXR1cm4gMDsKPiArfQo+ICsKPiArc3Rh dGljIHN0cnVjdCBkcm1faTkxNV9nZW1fb2JqZWN0ICppbnRlbF92Z3B1X2NyZWF0ZV9nZW1fZnJv bV92Z3B1aWQoCj4gKwkJc3RydWN0IGRybV9kZXZpY2UgKmRldiwgc3RydWN0IGludGVsX3ZncHUg KnZncHUsCj4gKwkJc3RydWN0IGludGVsX3ZncHVfZG1hYnVmICppbmZvKQo+ICt7Cj4gKwlzdHJ1 Y3QgZHJtX2k5MTVfZ2VtX29iamVjdCAqb2JqOwo+ICsJaW50IHJldDsKPiArCj4gKwlyZXQgPSBp bnRlbF92Z3B1X2dldF9wbGFuZV9pbmZvKGRldiwgdmdwdSwgaW5mbyk7Cj4gKwlpZiAocmV0KSB7 Cj4gKwkJZ3Z0X3ZncHVfZXJyKCJnZXQgcGxhbmUgaW5mbyBmYWlsZWQ6JWRcbiIsIGluZm8tPnBs YW5lX2lkKTsKPiArCQlyZXR1cm4gTlVMTDsKClByb3BhZ2F0ZSBlcnJvcnMuCgo+ICsJfQo+ICsJ b2JqID0gaW50ZWxfdmdwdV9jcmVhdGVfZ2VtKGRldiwgaW5mbyk7Cj4gKwo+ICsJcmV0dXJuIG9i ajsKPiArfQo+ICsKPiAraW50IGludGVsX3ZncHVfcXVlcnlfZG1hYnVmKHN0cnVjdCBpbnRlbF92 Z3B1ICp2Z3B1LCB2b2lkICphcmdzKQo+ICt7Cj4gKwlzdHJ1Y3QgZHJtX2RldmljZSAqZGV2ID0g JnZncHUtPmd2dC0+ZGV2X3ByaXYtPmRybTsKPiArCWludCByZXQ7Cj4gKwlzdHJ1Y3QgaW50ZWxf dmdwdV9kbWFidWYgKmluZm8gPSBhcmdzOwo+ICsKPiArCXJldCA9IGludGVsX3ZncHVfZ2V0X3Bs YW5lX2luZm8oZGV2LCB2Z3B1LCBpbmZvKTsKPiArCWlmIChyZXQpIHsKPiArCQlndnRfdmdwdV9l cnIoImdldCBwbGFuZSBpbmZvIGZhaWxlZDolZFxuIiwgaW5mby0+cGxhbmVfaWQpOwo+ICsJCXJl dHVybiAtRUlOVkFMOwo+ICsJfQo+ICsKPiArCXJldHVybiAwOwo+ICt9Cj4gKwo+ICtpbnQgaW50 ZWxfdmdwdV9nZW5lcmF0ZV9kbWFidWYoc3RydWN0IGludGVsX3ZncHUgKnZncHUsIHZvaWQgKmFy Z3MpCj4gK3sKPiArCXN0cnVjdCBkbWFfYnVmICpkbWFidWY7Cj4gKwlzdHJ1Y3QgZHJtX2k5MTVf Z2VtX29iamVjdCAqb2JqOwo+ICsJc3RydWN0IGRybV9kZXZpY2UgKmRldiA9ICZ2Z3B1LT5ndnQt PmRldl9wcml2LT5kcm07Cj4gKwlpbnQgcmV0Owo+ICsJc3RydWN0IGludGVsX3ZncHVfZG1hYnVm ICppbmZvID0gYXJnczsKPiArCXN0cnVjdCBkbWFfYnVmX2V4cG9ydF9pbmZvIGV4cF9pbmZvID0g ewo+ICsJCS5leHBfbmFtZSA9IEtCVUlMRF9NT0ROQU1FLAo+ICsJCS5vd25lciA9IFRISVNfTU9E VUxFIH07Cj4gKwo+ICsJb2JqID0gaW50ZWxfdmdwdV9jcmVhdGVfZ2VtX2Zyb21fdmdwdWlkKGRl diwgdmdwdSwgaW5mbyk7Cj4gKwlpZiAob2JqID09IE5VTEwpIHsKPiArCQlndnRfdmdwdV9lcnIo ImNyZWF0ZSBndnQgZ2VtIG9iaiBmYWlsZWQ6JWRcbiIsIHZncHUtPmlkKTsKPiArCQlyZXR1cm4g LUVJTlZBTDsKPiArCX0KPiArCj4gKwlleHBfaW5mby5vcHMgPSAmaTkxNV9kbWFidWZfb3BzOwoK UGxlYXNlIHB1dCBiYWNrIG15IHByaXZhdGUgaTkxNV9kbWFidWZfb3BzIGZyb20gd2hlcmUgeW91 IHN0b2xlIGl0IGZyb20uCgpKdXN0IGNhbGwgZG1hYnVmID0gaTkxNV9nZW1fcHJpbWVfZXhwb3J0 KGRldiwgb2JqLCBEUk1fQ0xPRVhFQyB8IERSTV9SRFdSKTsKCj4gKwlleHBfaW5mby5zaXplID0g b2JqLT5iYXNlLnNpemU7Cj4gKwlleHBfaW5mby5mbGFncyA9IERSTV9DTE9FWEVDIHwgRFJNX1JE V1I7Cj4gKwlleHBfaW5mby5wcml2ID0gJm9iai0+YmFzZTsKPiArCWV4cF9pbmZvLnJlc3YgPSBv YmotPnJlc3Y7Cj4gKwo+ICsJZG1hYnVmID0gZHJtX2dlbV9kbWFidWZfZXhwb3J0KGRldiwgJmV4 cF9pbmZvKTsKPiArCWlmIChJU19FUlIoZG1hYnVmKSkgewo+ICsJCWd2dF92Z3B1X2VycigiaW50 ZWwgdmdwdSBleHBvcnQgZG1hLWJ1ZiBmYWlsZWRcbiIpOwo+ICsJCW11dGV4X3VubG9jaygmZGV2 LT5vYmplY3RfbmFtZV9sb2NrKTsKPiArCQlyZXR1cm4gLUVJTlZBTDsKPiArCX0KPiArCj4gKwly ZXQgPSBkbWFfYnVmX2ZkKGRtYWJ1ZiwgZXhwX2luZm8uZmxhZ3MpOwo+ICsJaWYgKHJldCA8IDAp IHsKPiArCQlndnRfdmdwdV9lcnIoImludGVsIHZncHUgY3JlYXRlIGRtYS1idWYgZmQgZmFpbGVk XG4iKTsKPiArCQlyZXR1cm4gcmV0Owo+ICsJfQo+ICsJaW5mby0+ZmQgPSByZXQ7Cj4gKwo+ICsJ cmV0dXJuIDA7Cj4gK30KPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL2k5MTUvZ3Z0L2Rt YWJ1Zi5oIGIvZHJpdmVycy9ncHUvZHJtL2k5MTUvZ3Z0L2RtYWJ1Zi5oCj4gbmV3IGZpbGUgbW9k ZSAxMDA2NDQKPiBpbmRleCAwMDAwMDAwLi5jNTkwZjRhCj4gLS0tIC9kZXYvbnVsbAo+ICsrKyBi L2RyaXZlcnMvZ3B1L2RybS9pOTE1L2d2dC9kbWFidWYuaAo+IEBAIC0wLDAgKzEsNTAgQEAKPiAr LyoKPiArICogQ29weXJpZ2h0KGMpIDIwMTcgSW50ZWwgQ29ycG9yYXRpb24uIEFsbCByaWdodHMg cmVzZXJ2ZWQuCj4gKyAqCj4gKyAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUg b2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhCj4gKyAqIGNvcHkgb2YgdGhpcyBz b2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgIlNvZnR3YXJl IiksCj4gKyAqIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGlu Y2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24KPiArICogdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHks IG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsCj4gKyAqIGFu ZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0 byB3aG9tIHRoZQo+ICsgKiBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3Qg dG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOgo+ICsgKgo+ICsgKiBUaGUgYWJvdmUgY29weXJp Z2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSAoaW5jbHVkaW5nIHRoZSBuZXh0 Cj4gKyAqIHBhcmFncmFwaCkgc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJz dGFudGlhbCBwb3J0aW9ucyBvZiB0aGUKPiArICogU29mdHdhcmUuCj4gKyAqCj4gKyAqIFRIRSBT T0ZUV0FSRSBJUyBQUk9WSURFRCAiQVMgSVMiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5E LCBFWFBSRVNTIE9SCj4gKyAqIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8g VEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLAo+ICsgKiBGSVRORVNTIEZPUiBBIFBB UlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiAgSU4gTk8gRVZFTlQgU0hBTEwK PiArICogVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkg Q0xBSU0sIERBTUFHRVMgT1IgT1RIRVIKPiArICogTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFD VElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwKPiArICog T1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBP VEhFUiBERUFMSU5HUyBJTiBUSEUKPiArICogU09GVFdBUkUuCj4gKyAqCj4gKyAqLwo+ICsKPiAr I2lmbmRlZiBfR1ZUX0RNQUJVRl9IXwo+ICsjZGVmaW5lIF9HVlRfRE1BQlVGX0hfCj4gKwo+ICsj ZGVmaW5lIElOVEVMX1ZHUFVfUVVFUllfRE1BQlVGCQkwCj4gKyNkZWZpbmUgSU5URUxfVkdQVV9H RU5FUkFURV9ETUFCVUYJMQo+ICsKPiArc3RydWN0IGludGVsX3ZncHVfZG1hYnVmIHsKClRoaXMg bG9va3MgdG8gYmUgdWFwaS4gV2hhdCdzIGl0IGRvaW5nIGhlcmU/Ci1DaHJpcwoKLS0gCkNocmlz IFdpbHNvbiwgSW50ZWwgT3BlbiBTb3VyY2UgVGVjaG5vbG9neSBDZW50cmUKX19fX19fX19fX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KSW50ZWwtZ2Z4IG1haWxpbmcgbGlz dApJbnRlbC1nZnhAbGlzdHMuZnJlZWRlc2t0b3Aub3JnCmh0dHBzOi8vbGlzdHMuZnJlZWRlc2t0 b3Aub3JnL21haWxtYW4vbGlzdGluZm8vaW50ZWwtZ2Z4Cg==