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.3 required=3.0 tests=BAYES_00, 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 14F3FC47084 for ; Tue, 25 May 2021 09:32:59 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (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 C9EC761417 for ; Tue, 25 May 2021 09:32:58 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org C9EC761417 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id EBFAD6E9D5; Tue, 25 May 2021 09:32:57 +0000 (UTC) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5F21989BD2; Tue, 25 May 2021 09:32:45 +0000 (UTC) IronPort-SDR: 98MwlXgL1kAE8gCrcOFLnwgn8FniW1RefopCQprx+i1A67sPPJDnJIdFuO7slhGJP2ZuBMgdqa FzDEl2B8/RnQ== X-IronPort-AV: E=McAfee;i="6200,9189,9994"; a="199096154" X-IronPort-AV: E=Sophos;i="5.82,328,1613462400"; d="scan'208";a="199096154" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 May 2021 02:32:44 -0700 IronPort-SDR: M/owxnVsvpyHZCf99Kw5uXgiVF/TDM/lsdJk03VTyui9zMeqgdNax4OCJzI81k+V31esCQcQ5s v5Fg0sye7ENA== X-IronPort-AV: E=Sophos;i="5.82,328,1613462400"; d="scan'208";a="632966829" Received: from vkubarev-mobl1.ccr.corp.intel.com (HELO [10.249.254.43]) ([10.249.254.43]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 May 2021 02:32:43 -0700 Subject: Re: [Intel-gfx] [PATCH v3 06/12] drm/ttm: Add a generic TTM memcpy move for page-based iomem To: Matthew Auld References: <20210521153253.518037-1-thomas.hellstrom@linux.intel.com> <20210521153253.518037-7-thomas.hellstrom@linux.intel.com> From: =?UTF-8?Q?Thomas_Hellstr=c3=b6m?= Message-ID: <2cc9a60c-4360-40b6-8712-1e50b7bbfd03@linux.intel.com> Date: Tue, 25 May 2021 11:32:40 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.10.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-US X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Intel Graphics Development , =?UTF-8?Q?Christian_K=c3=b6nig?= , ML dri-devel Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" On 5/25/21 11:18 AM, Matthew Auld wrote: > On Fri, 21 May 2021 at 16:33, Thomas Hellström > wrote: >> The internal ttm_bo_util memcpy uses ioremap functionality, and while it >> probably might be possible to use it for copying in- and out of >> sglist represented io memory, using io_mem_reserve() / io_mem_free() >> callbacks, that would cause problems with fault(). >> Instead, implement a method mapping page-by-page using kmap_local() >> semantics. As an additional benefit we then avoid the occasional global >> TLB flushes of ioremap() and consuming ioremap space, elimination of a >> critical point of failure and with a slight change of semantics we could >> also push the memcpy out async for testing and async driver development >> purposes. >> >> A special linear iomem iterator is introduced internally to mimic the >> old ioremap behaviour for code-paths that can't immediately be ported >> over. This adds to the code size and should be considered a temporary >> solution. >> >> Looking at the code we have a lot of checks for iomap tagged pointers. >> Ideally we should extend the core memremap functions to also accept >> uncached memory and kmap_local functionality. Then we could strip a >> lot of code. >> >> Cc: Christian König >> Signed-off-by: Thomas Hellström >> --- >> v3: >> - Split up in various TTM files and addressed review comments by >> Christian König. Tested and fixed legacy iomap memcpy path on i915. >> --- >> drivers/gpu/drm/ttm/ttm_bo_util.c | 278 ++++++++++------------------- >> drivers/gpu/drm/ttm/ttm_module.c | 35 ++++ >> drivers/gpu/drm/ttm/ttm_resource.c | 166 +++++++++++++++++ >> drivers/gpu/drm/ttm/ttm_tt.c | 42 +++++ >> include/drm/ttm/ttm_bo_driver.h | 28 +++ >> include/drm/ttm/ttm_caching.h | 2 + >> include/drm/ttm/ttm_kmap_iter.h | 61 +++++++ >> include/drm/ttm/ttm_resource.h | 61 +++++++ >> include/drm/ttm/ttm_tt.h | 16 ++ >> 9 files changed, 508 insertions(+), 181 deletions(-) >> create mode 100644 include/drm/ttm/ttm_kmap_iter.h >> >> diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c >> index ae8b61460724..912cbe8e60a2 100644 >> --- a/drivers/gpu/drm/ttm/ttm_bo_util.c >> +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c >> @@ -72,190 +72,126 @@ void ttm_mem_io_free(struct ttm_device *bdev, >> mem->bus.addr = NULL; >> } >> >> -static int ttm_resource_ioremap(struct ttm_device *bdev, >> - struct ttm_resource *mem, >> - void **virtual) >> +/** >> + * ttm_move_memcpy - Helper to perform a memcpy ttm move operation. >> + * @bo: The struct ttm_buffer_object. >> + * @new_mem: The struct ttm_resource we're moving to (copy destination). >> + * @new_iter: A struct ttm_kmap_iter representing the destination resource. >> + * @src_iter: A struct ttm_kmap_iter representing the source resource. >> + * >> + * This function is intended to be able to move out async under a >> + * dma-fence if desired. >> + */ >> +void ttm_move_memcpy(struct ttm_buffer_object *bo, >> + struct ttm_resource *dst_mem, >> + struct ttm_kmap_iter *dst_iter, >> + struct ttm_kmap_iter *src_iter) >> { >> - int ret; >> - void *addr; >> - >> - *virtual = NULL; >> - ret = ttm_mem_io_reserve(bdev, mem); >> - if (ret || !mem->bus.is_iomem) >> - return ret; >> + const struct ttm_kmap_iter_ops *dst_ops = dst_iter->ops; >> + const struct ttm_kmap_iter_ops *src_ops = src_iter->ops; >> + struct ttm_tt *ttm = bo->ttm; >> + struct dma_buf_map src_map, dst_map; >> + pgoff_t i; >> >> - if (mem->bus.addr) { >> - addr = mem->bus.addr; >> - } else { >> - size_t bus_size = (size_t)mem->num_pages << PAGE_SHIFT; >> + /* Single TTM move. NOP */ >> + if (dst_ops->maps_tt && src_ops->maps_tt) >> + return; >> >> - if (mem->bus.caching == ttm_write_combined) >> - addr = ioremap_wc(mem->bus.offset, bus_size); >> -#ifdef CONFIG_X86 >> - else if (mem->bus.caching == ttm_cached) >> - addr = ioremap_cache(mem->bus.offset, bus_size); >> -#endif >> - else >> - addr = ioremap(mem->bus.offset, bus_size); >> - if (!addr) { >> - ttm_mem_io_free(bdev, mem); >> - return -ENOMEM; >> + /* Don't move nonexistent data. Clear destination instead. */ >> + if (src_ops->maps_tt && (!ttm || !ttm_tt_is_populated(ttm))) { >> + if (ttm && !(ttm->page_flags & TTM_PAGE_FLAG_ZERO_ALLOC)) >> + return; >> + >> + for (i = 0; i < dst_mem->num_pages; ++i) { >> + dst_ops->map_local(dst_iter, &dst_map, i); >> + if (dst_map.is_iomem) >> + memset_io(dst_map.vaddr_iomem, 0, PAGE_SIZE); >> + else >> + memset(dst_map.vaddr, 0, PAGE_SIZE); >> + if (dst_ops->unmap_local) >> + dst_ops->unmap_local(dst_iter, &dst_map); >> } >> + return; >> } >> - *virtual = addr; >> - return 0; >> -} >> - >> -static void ttm_resource_iounmap(struct ttm_device *bdev, >> - struct ttm_resource *mem, >> - void *virtual) >> -{ >> - if (virtual && mem->bus.addr == NULL) >> - iounmap(virtual); >> - ttm_mem_io_free(bdev, mem); >> -} >> - >> -static int ttm_copy_io_page(void *dst, void *src, unsigned long page) >> -{ >> - uint32_t *dstP = >> - (uint32_t *) ((unsigned long)dst + (page << PAGE_SHIFT)); >> - uint32_t *srcP = >> - (uint32_t *) ((unsigned long)src + (page << PAGE_SHIFT)); >> - >> - int i; >> - for (i = 0; i < PAGE_SIZE / sizeof(uint32_t); ++i) >> - iowrite32(ioread32(srcP++), dstP++); >> - return 0; >> -} >> - >> -static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src, >> - unsigned long page, >> - pgprot_t prot) >> -{ >> - struct page *d = ttm->pages[page]; >> - void *dst; >> - >> - if (!d) >> - return -ENOMEM; >> - >> - src = (void *)((unsigned long)src + (page << PAGE_SHIFT)); >> - dst = kmap_atomic_prot(d, prot); >> - if (!dst) >> - return -ENOMEM; >> - >> - memcpy_fromio(dst, src, PAGE_SIZE); >> - >> - kunmap_atomic(dst); >> - >> - return 0; >> -} >> - >> -static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst, >> - unsigned long page, >> - pgprot_t prot) >> -{ >> - struct page *s = ttm->pages[page]; >> - void *src; >> - >> - if (!s) >> - return -ENOMEM; >> - >> - dst = (void *)((unsigned long)dst + (page << PAGE_SHIFT)); >> - src = kmap_atomic_prot(s, prot); >> - if (!src) >> - return -ENOMEM; >> >> - memcpy_toio(dst, src, PAGE_SIZE); >> - >> - kunmap_atomic(src); >> + for (i = 0; i < dst_mem->num_pages; ++i) { >> + dst_ops->map_local(dst_iter, &dst_map, i); >> + src_ops->map_local(src_iter, &src_map, i); >> + >> + if (!src_map.is_iomem && !dst_map.is_iomem) { >> + memcpy(dst_map.vaddr, src_map.vaddr, PAGE_SIZE); >> + } else if (!src_map.is_iomem) { >> + dma_buf_map_memcpy_to(&dst_map, src_map.vaddr, >> + PAGE_SIZE); >> + } else if (!dst_map.is_iomem) { >> + memcpy_fromio(dst_map.vaddr, src_map.vaddr_iomem, >> + PAGE_SIZE); >> + } else { >> + int j; >> + u32 __iomem *src = src_map.vaddr_iomem; >> + u32 __iomem *dst = dst_map.vaddr_iomem; >> >> - return 0; >> + for (j = 0; j < (PAGE_SIZE >> 2); ++j) > IMO PAGE_SIZE / sizeof(u32) is easier to understand. OK, will fix. > >> + iowrite32(ioread32(src++), dst++); >> + } >> + if (src_ops->unmap_local) >> + src_ops->unmap_local(src_iter, &src_map); >> + if (dst_ops->unmap_local) >> + dst_ops->unmap_local(dst_iter, &dst_map); >> + } >> } >> +EXPORT_SYMBOL(ttm_move_memcpy); >> >> int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, >> struct ttm_operation_ctx *ctx, >> - struct ttm_resource *new_mem) >> + struct ttm_resource *dst_mem) >> { >> struct ttm_device *bdev = bo->bdev; >> - struct ttm_resource_manager *man = ttm_manager_type(bdev, new_mem->mem_type); >> + struct ttm_resource_manager *dst_man = >> + ttm_manager_type(bo->bdev, dst_mem->mem_type); >> struct ttm_tt *ttm = bo->ttm; >> - struct ttm_resource *old_mem = &bo->mem; >> - struct ttm_resource old_copy = *old_mem; >> - void *old_iomap; >> - void *new_iomap; >> + struct ttm_resource *src_mem = &bo->mem; >> + struct ttm_resource_manager *src_man = >> + ttm_manager_type(bdev, src_mem->mem_type); >> + struct ttm_resource src_copy = *src_mem; >> + union { >> + struct ttm_kmap_iter_tt tt; >> + struct ttm_kmap_iter_linear_io io; >> + } _dst_iter, _src_iter; >> + struct ttm_kmap_iter *dst_iter, *src_iter; >> int ret; >> - unsigned long i; >> >> - ret = ttm_bo_wait_ctx(bo, ctx); >> - if (ret) >> - return ret; >> - >> - ret = ttm_resource_ioremap(bdev, old_mem, &old_iomap); >> - if (ret) >> - return ret; >> - ret = ttm_resource_ioremap(bdev, new_mem, &new_iomap); >> - if (ret) >> - goto out; >> - >> - /* >> - * Single TTM move. NOP. >> - */ >> - if (old_iomap == NULL && new_iomap == NULL) >> - goto out2; >> - >> - /* >> - * Don't move nonexistent data. Clear destination instead. >> - */ >> - if (old_iomap == NULL && >> - (ttm == NULL || (!ttm_tt_is_populated(ttm) && >> - !(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)))) { >> - memset_io(new_iomap, 0, new_mem->num_pages*PAGE_SIZE); >> - goto out2; >> - } >> - >> - /* >> - * TTM might be null for moves within the same region. >> - */ >> - if (ttm) { >> + if (ttm && ((ttm->page_flags & TTM_PAGE_FLAG_SWAPPED) || >> + dst_man->use_tt)) { >> ret = ttm_tt_populate(bdev, ttm, ctx); >> if (ret) >> - goto out1; >> + return ret; >> } >> >> - for (i = 0; i < new_mem->num_pages; ++i) { >> - if (old_iomap == NULL) { >> - pgprot_t prot = ttm_io_prot(bo, old_mem, PAGE_KERNEL); >> - ret = ttm_copy_ttm_io_page(ttm, new_iomap, i, >> - prot); >> - } else if (new_iomap == NULL) { >> - pgprot_t prot = ttm_io_prot(bo, new_mem, PAGE_KERNEL); >> - ret = ttm_copy_io_ttm_page(ttm, old_iomap, i, >> - prot); >> - } else { >> - ret = ttm_copy_io_page(new_iomap, old_iomap, i); >> - } >> - if (ret) >> - goto out1; >> + dst_iter = ttm_kmap_iter_linear_io_init(&_dst_iter.io, bdev, dst_mem); >> + if (PTR_ERR(dst_iter) == -EINVAL && dst_man->use_tt) >> + dst_iter = ttm_kmap_iter_tt_init(&_dst_iter.tt, bo->ttm); >> + if (IS_ERR(dst_iter)) >> + return PTR_ERR(dst_iter); >> + >> + src_iter = ttm_kmap_iter_linear_io_init(&_src_iter.io, bdev, src_mem); >> + if (PTR_ERR(src_iter) == -EINVAL && src_man->use_tt) >> + src_iter = ttm_kmap_iter_tt_init(&_src_iter.tt, bo->ttm); >> + if (IS_ERR(src_iter)) { >> + ret = PTR_ERR(src_iter); >> + goto out_src_iter; >> } >> - mb(); >> -out2: >> - old_copy = *old_mem; >> >> - ttm_bo_assign_mem(bo, new_mem); >> - >> - if (!man->use_tt) >> - ttm_bo_tt_destroy(bo); >> + ttm_move_memcpy(bo, dst_mem, dst_iter, src_iter); >> + src_copy = *src_mem; >> + ttm_bo_move_sync_cleanup(bo, dst_mem); >> >> -out1: >> - ttm_resource_iounmap(bdev, old_mem, new_iomap); >> -out: >> - ttm_resource_iounmap(bdev, &old_copy, old_iomap); >> + if (!src_iter->ops->maps_tt) >> + ttm_kmap_iter_linear_io_fini(&_src_iter.io, bdev, &src_copy); >> +out_src_iter: >> + if (!dst_iter->ops->maps_tt) >> + ttm_kmap_iter_linear_io_fini(&_dst_iter.io, bdev, dst_mem); >> >> - /* >> - * On error, keep the mm node! >> - */ >> - if (!ret) >> - ttm_resource_free(bo, &old_copy); >> return ret; >> } >> EXPORT_SYMBOL(ttm_bo_move_memcpy); >> @@ -336,27 +272,7 @@ pgprot_t ttm_io_prot(struct ttm_buffer_object *bo, struct ttm_resource *res, >> man = ttm_manager_type(bo->bdev, res->mem_type); >> caching = man->use_tt ? bo->ttm->caching : res->bus.caching; >> >> - /* Cached mappings need no adjustment */ >> - if (caching == ttm_cached) >> - return tmp; >> - >> -#if defined(__i386__) || defined(__x86_64__) >> - if (caching == ttm_write_combined) >> - tmp = pgprot_writecombine(tmp); >> - else if (boot_cpu_data.x86 > 3) >> - tmp = pgprot_noncached(tmp); >> -#endif >> -#if defined(__ia64__) || defined(__arm__) || defined(__aarch64__) || \ >> - defined(__powerpc__) || defined(__mips__) >> - if (caching == ttm_write_combined) >> - tmp = pgprot_writecombine(tmp); >> - else >> - tmp = pgprot_noncached(tmp); >> -#endif >> -#if defined(__sparc__) >> - tmp = pgprot_noncached(tmp); >> -#endif >> - return tmp; >> + return ttm_prot_from_caching(caching, tmp); >> } >> EXPORT_SYMBOL(ttm_io_prot); >> >> diff --git a/drivers/gpu/drm/ttm/ttm_module.c b/drivers/gpu/drm/ttm/ttm_module.c >> index 56b0efdba1a9..997c458f68a9 100644 >> --- a/drivers/gpu/drm/ttm/ttm_module.c >> +++ b/drivers/gpu/drm/ttm/ttm_module.c >> @@ -31,12 +31,47 @@ >> */ >> #include >> #include >> +#include >> #include >> #include >> #include >> +#include >> >> #include "ttm_module.h" >> >> +/** >> + * ttm_prot_from_caching - Modify the page protection according to the >> + * ttm cacing mode >> + * @caching: The ttm caching mode >> + * @tmp: The original page protection >> + * >> + * Return: The modified page protection >> + */ >> +pgprot_t ttm_prot_from_caching(enum ttm_caching caching, pgprot_t tmp) >> +{ >> + /* Cached mappings need no adjustment */ >> + if (caching == ttm_cached) >> + return tmp; >> + >> +#if defined(__i386__) || defined(__x86_64__) >> + if (caching == ttm_write_combined) >> + tmp = pgprot_writecombine(tmp); >> + else if (boot_cpu_data.x86 > 3) >> + tmp = pgprot_noncached(tmp); >> +#endif >> +#if defined(__ia64__) || defined(__arm__) || defined(__aarch64__) || \ >> + defined(__powerpc__) || defined(__mips__) >> + if (caching == ttm_write_combined) >> + tmp = pgprot_writecombine(tmp); >> + else >> + tmp = pgprot_noncached(tmp); >> +#endif >> +#if defined(__sparc__) >> + tmp = pgprot_noncached(tmp); >> +#endif >> + return tmp; >> +} >> + >> struct dentry *ttm_debugfs_root; >> >> static int __init ttm_init(void) >> diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c >> index 59e2b7157e41..e05ae7e3d477 100644 >> --- a/drivers/gpu/drm/ttm/ttm_resource.c >> +++ b/drivers/gpu/drm/ttm/ttm_resource.c >> @@ -22,6 +22,10 @@ >> * Authors: Christian König >> */ >> >> +#include >> +#include >> +#include >> + >> #include >> #include >> >> @@ -147,3 +151,165 @@ void ttm_resource_manager_debug(struct ttm_resource_manager *man, >> man->func->debug(man, p); >> } >> EXPORT_SYMBOL(ttm_resource_manager_debug); >> + >> +static void ttm_kmap_iter_iomap_map_local(struct ttm_kmap_iter *iter, >> + struct dma_buf_map *dmap, >> + pgoff_t i) >> +{ >> + struct ttm_kmap_iter_iomap *iter_io = >> + container_of(iter, typeof(*iter_io), base); >> + void __iomem *addr; >> + >> +retry: >> + while (i >= iter_io->cache.end) { >> + iter_io->cache.sg = iter_io->cache.sg ? >> + sg_next(iter_io->cache.sg) : iter_io->st->sgl; >> + iter_io->cache.i = iter_io->cache.end; >> + iter_io->cache.end += sg_dma_len(iter_io->cache.sg) >> >> + PAGE_SHIFT; >> + iter_io->cache.offs = sg_dma_address(iter_io->cache.sg) - >> + iter_io->start; >> + } >> + >> + if (i < iter_io->cache.i) { >> + iter_io->cache.end = 0; >> + iter_io->cache.sg = NULL; >> + goto retry; >> + } >> + >> + addr = io_mapping_map_local_wc(iter_io->iomap, iter_io->cache.offs + >> + (((resource_size_t)i - iter_io->cache.i) >> + << PAGE_SHIFT)); >> + dma_buf_map_set_vaddr_iomem(dmap, addr); >> +} >> + >> +static void ttm_kmap_iter_iomap_unmap_local(struct ttm_kmap_iter *iter, >> + struct dma_buf_map *map) >> +{ >> + io_mapping_unmap_local(map->vaddr_iomem); >> +} >> + >> +static const struct ttm_kmap_iter_ops ttm_kmap_iter_io_ops = { >> + .map_local = ttm_kmap_iter_iomap_map_local, >> + .unmap_local = ttm_kmap_iter_iomap_unmap_local, >> + .maps_tt = false, >> +}; >> + >> +/** >> + * ttm_kmap_iter_iomap_init - Initialize a struct ttm_kmap_iter_iomap >> + * @iter_io: The struct ttm_kmap_iter_iomap to initialize. >> + * @iomap: The struct io_mapping representing the underlying linear io_memory. >> + * @st: sg_table into @iomap, representing the memory of the struct >> + * ttm_resource. >> + * @start: Offset that needs to be subtracted from @st to make >> + * sg_dma_address(st->sgl) - @start == 0 for @iomap start. >> + * >> + * Return: Pointer to the embedded struct ttm_kmap_iter. >> + */ >> +struct ttm_kmap_iter * >> +ttm_kmap_iter_iomap_init(struct ttm_kmap_iter_iomap *iter_io, >> + struct io_mapping *iomap, >> + struct sg_table *st, >> + resource_size_t start) >> +{ >> + iter_io->base.ops = &ttm_kmap_iter_io_ops; >> + iter_io->iomap = iomap; >> + iter_io->st = st; >> + iter_io->start = start; >> + memset(&iter_io->cache, 0, sizeof(iter_io->cache)); >> + >> + return &iter_io->base; >> +} >> +EXPORT_SYMBOL(ttm_kmap_iter_iomap_init); >> + >> +/** >> + * DOC: Linear io iterator >> + * >> + * This code should die in the not too near future. Best would be if we could >> + * make io-mapping use memremap for all io memory, and have memremap >> + * implement a kmap_local functionality. We could then strip a huge amount of >> + * code. These linear io iterators are implemented to mimic old functionality, >> + * and they don't use kmap_local semantics at all internally. Rather ioremap or >> + * friends, and at least on 32-bit they add global TLB flushes and points >> + * of failure. >> + */ >> + >> +static void ttm_kmap_iter_linear_io_map_local(struct ttm_kmap_iter *iter, >> + struct dma_buf_map *dmap, >> + pgoff_t i) >> +{ >> + struct ttm_kmap_iter_linear_io *iter_io = >> + container_of(iter, typeof(*iter_io), base); >> + >> + *dmap = iter_io->dmap; >> + dma_buf_map_incr(dmap, i * PAGE_SIZE); >> +} >> + >> +static const struct ttm_kmap_iter_ops ttm_kmap_iter_linear_io_ops = { >> + .map_local = ttm_kmap_iter_linear_io_map_local, >> + .maps_tt = false, >> +}; >> + >> +struct ttm_kmap_iter * >> +ttm_kmap_iter_linear_io_init(struct ttm_kmap_iter_linear_io *iter_io, >> + struct ttm_device *bdev, >> + struct ttm_resource *mem) >> +{ >> + int ret; >> + >> + ret = ttm_mem_io_reserve(bdev, mem); >> + if (ret) >> + goto out_err; >> + if (!mem->bus.is_iomem) { >> + ret = -EINVAL; >> + goto out_io_free; >> + } >> + >> + if (mem->bus.addr) { >> + dma_buf_map_set_vaddr(&iter_io->dmap, mem->bus.addr); >> + iter_io->needs_unmap = false; >> + } else { >> + size_t bus_size = (size_t)mem->num_pages << PAGE_SHIFT; >> + >> + iter_io->needs_unmap = true; >> + if (mem->bus.caching == ttm_write_combined) >> + dma_buf_map_set_vaddr_iomem(&iter_io->dmap, >> + ioremap_wc(mem->bus.offset, >> + bus_size)); >> + else if (mem->bus.caching == ttm_cached) >> + dma_buf_map_set_vaddr(&iter_io->dmap, >> + memremap(mem->bus.offset, bus_size, >> + MEMREMAP_WB)); > The comments in set_vaddr suggest that this is meant for > system-memory. Does that actually matter or is it just about not > losing the __iomem annotation on platforms where it matters? Yes, it's the latter. dma_buf_map() is relatively new and the author probably didn't think about the case of cached iomem, which is used by, for example, vmwgfx. > Apparently cached device local is a thing. Also should this not be > wrapped in CONFIG_X86? Both dma_buf_map() and memremap are generic, I think, I guess memremap would return NULL if it's not supported. /Thomas 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.3 required=3.0 tests=BAYES_00, 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 C273AC2B9F8 for ; Tue, 25 May 2021 09:32:58 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (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 8032F61413 for ; Tue, 25 May 2021 09:32:58 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 8032F61413 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.intel.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=intel-gfx-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id DA88B6E9D4; Tue, 25 May 2021 09:32:57 +0000 (UTC) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5F21989BD2; Tue, 25 May 2021 09:32:45 +0000 (UTC) IronPort-SDR: 98MwlXgL1kAE8gCrcOFLnwgn8FniW1RefopCQprx+i1A67sPPJDnJIdFuO7slhGJP2ZuBMgdqa FzDEl2B8/RnQ== X-IronPort-AV: E=McAfee;i="6200,9189,9994"; a="199096154" X-IronPort-AV: E=Sophos;i="5.82,328,1613462400"; d="scan'208";a="199096154" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 May 2021 02:32:44 -0700 IronPort-SDR: M/owxnVsvpyHZCf99Kw5uXgiVF/TDM/lsdJk03VTyui9zMeqgdNax4OCJzI81k+V31esCQcQ5s v5Fg0sye7ENA== X-IronPort-AV: E=Sophos;i="5.82,328,1613462400"; d="scan'208";a="632966829" Received: from vkubarev-mobl1.ccr.corp.intel.com (HELO [10.249.254.43]) ([10.249.254.43]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 25 May 2021 02:32:43 -0700 To: Matthew Auld References: <20210521153253.518037-1-thomas.hellstrom@linux.intel.com> <20210521153253.518037-7-thomas.hellstrom@linux.intel.com> From: =?UTF-8?Q?Thomas_Hellstr=c3=b6m?= Message-ID: <2cc9a60c-4360-40b6-8712-1e50b7bbfd03@linux.intel.com> Date: Tue, 25 May 2021 11:32:40 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.10.1 MIME-Version: 1.0 In-Reply-To: Content-Language: en-US Subject: Re: [Intel-gfx] [PATCH v3 06/12] drm/ttm: Add a generic TTM memcpy move for page-based iomem X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Intel Graphics Development , =?UTF-8?Q?Christian_K=c3=b6nig?= , ML dri-devel Content-Transfer-Encoding: base64 Content-Type: text/plain; charset="utf-8"; Format="flowed" Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" Ck9uIDUvMjUvMjEgMTE6MTggQU0sIE1hdHRoZXcgQXVsZCB3cm90ZToKPiBPbiBGcmksIDIxIE1h eSAyMDIxIGF0IDE2OjMzLCBUaG9tYXMgSGVsbHN0csO2bQo+IDx0aG9tYXMuaGVsbHN0cm9tQGxp bnV4LmludGVsLmNvbT4gd3JvdGU6Cj4+IFRoZSBpbnRlcm5hbCB0dG1fYm9fdXRpbCBtZW1jcHkg dXNlcyBpb3JlbWFwIGZ1bmN0aW9uYWxpdHksIGFuZCB3aGlsZSBpdAo+PiBwcm9iYWJseSBtaWdo dCBiZSBwb3NzaWJsZSB0byB1c2UgaXQgZm9yIGNvcHlpbmcgaW4tIGFuZCBvdXQgb2YKPj4gc2ds aXN0IHJlcHJlc2VudGVkIGlvIG1lbW9yeSwgdXNpbmcgaW9fbWVtX3Jlc2VydmUoKSAvIGlvX21l bV9mcmVlKCkKPj4gY2FsbGJhY2tzLCB0aGF0IHdvdWxkIGNhdXNlIHByb2JsZW1zIHdpdGggZmF1 bHQoKS4KPj4gSW5zdGVhZCwgaW1wbGVtZW50IGEgbWV0aG9kIG1hcHBpbmcgcGFnZS1ieS1wYWdl IHVzaW5nIGttYXBfbG9jYWwoKQo+PiBzZW1hbnRpY3MuIEFzIGFuIGFkZGl0aW9uYWwgYmVuZWZp dCB3ZSB0aGVuIGF2b2lkIHRoZSBvY2Nhc2lvbmFsIGdsb2JhbAo+PiBUTEIgZmx1c2hlcyBvZiBp b3JlbWFwKCkgYW5kIGNvbnN1bWluZyBpb3JlbWFwIHNwYWNlLCBlbGltaW5hdGlvbiBvZiBhCj4+ IGNyaXRpY2FsIHBvaW50IG9mIGZhaWx1cmUgYW5kIHdpdGggYSBzbGlnaHQgY2hhbmdlIG9mIHNl bWFudGljcyB3ZSBjb3VsZAo+PiBhbHNvIHB1c2ggdGhlIG1lbWNweSBvdXQgYXN5bmMgZm9yIHRl c3RpbmcgYW5kIGFzeW5jIGRyaXZlciBkZXZlbG9wbWVudAo+PiBwdXJwb3Nlcy4KPj4KPj4gQSBz cGVjaWFsIGxpbmVhciBpb21lbSBpdGVyYXRvciBpcyBpbnRyb2R1Y2VkIGludGVybmFsbHkgdG8g bWltaWMgdGhlCj4+IG9sZCBpb3JlbWFwIGJlaGF2aW91ciBmb3IgY29kZS1wYXRocyB0aGF0IGNh bid0IGltbWVkaWF0ZWx5IGJlIHBvcnRlZAo+PiBvdmVyLiBUaGlzIGFkZHMgdG8gdGhlIGNvZGUg c2l6ZSBhbmQgc2hvdWxkIGJlIGNvbnNpZGVyZWQgYSB0ZW1wb3JhcnkKPj4gc29sdXRpb24uCj4+ Cj4+IExvb2tpbmcgYXQgdGhlIGNvZGUgd2UgaGF2ZSBhIGxvdCBvZiBjaGVja3MgZm9yIGlvbWFw IHRhZ2dlZCBwb2ludGVycy4KPj4gSWRlYWxseSB3ZSBzaG91bGQgZXh0ZW5kIHRoZSBjb3JlIG1l bXJlbWFwIGZ1bmN0aW9ucyB0byBhbHNvIGFjY2VwdAo+PiB1bmNhY2hlZCBtZW1vcnkgYW5kIGtt YXBfbG9jYWwgZnVuY3Rpb25hbGl0eS4gVGhlbiB3ZSBjb3VsZCBzdHJpcCBhCj4+IGxvdCBvZiBj b2RlLgo+Pgo+PiBDYzogQ2hyaXN0aWFuIEvDtm5pZyA8Y2hyaXN0aWFuLmtvZW5pZ0BhbWQuY29t Pgo+PiBTaWduZWQtb2ZmLWJ5OiBUaG9tYXMgSGVsbHN0csO2bSA8dGhvbWFzLmhlbGxzdHJvbUBs aW51eC5pbnRlbC5jb20+Cj4+IC0tLQo+PiB2MzoKPj4gLSBTcGxpdCB1cCBpbiB2YXJpb3VzIFRU TSBmaWxlcyBhbmQgYWRkcmVzc2VkIHJldmlldyBjb21tZW50cyBieQo+PiAgICBDaHJpc3RpYW4g S8O2bmlnLiBUZXN0ZWQgYW5kIGZpeGVkIGxlZ2FjeSBpb21hcCBtZW1jcHkgcGF0aCBvbiBpOTE1 Lgo+PiAtLS0KPj4gICBkcml2ZXJzL2dwdS9kcm0vdHRtL3R0bV9ib191dGlsLmMgIHwgMjc4ICsr KysrKysrKystLS0tLS0tLS0tLS0tLS0tLS0tCj4+ICAgZHJpdmVycy9ncHUvZHJtL3R0bS90dG1f bW9kdWxlLmMgICB8ICAzNSArKysrCj4+ICAgZHJpdmVycy9ncHUvZHJtL3R0bS90dG1fcmVzb3Vy Y2UuYyB8IDE2NiArKysrKysrKysrKysrKysrKwo+PiAgIGRyaXZlcnMvZ3B1L2RybS90dG0vdHRt X3R0LmMgICAgICAgfCAgNDIgKysrKysKPj4gICBpbmNsdWRlL2RybS90dG0vdHRtX2JvX2RyaXZl ci5oICAgIHwgIDI4ICsrKwo+PiAgIGluY2x1ZGUvZHJtL3R0bS90dG1fY2FjaGluZy5oICAgICAg fCAgIDIgKwo+PiAgIGluY2x1ZGUvZHJtL3R0bS90dG1fa21hcF9pdGVyLmggICAgfCAgNjEgKysr KysrKwo+PiAgIGluY2x1ZGUvZHJtL3R0bS90dG1fcmVzb3VyY2UuaCAgICAgfCAgNjEgKysrKysr Kwo+PiAgIGluY2x1ZGUvZHJtL3R0bS90dG1fdHQuaCAgICAgICAgICAgfCAgMTYgKysKPj4gICA5 IGZpbGVzIGNoYW5nZWQsIDUwOCBpbnNlcnRpb25zKCspLCAxODEgZGVsZXRpb25zKC0pCj4+ICAg Y3JlYXRlIG1vZGUgMTAwNjQ0IGluY2x1ZGUvZHJtL3R0bS90dG1fa21hcF9pdGVyLmgKPj4KPj4g ZGlmZiAtLWdpdCBhL2RyaXZlcnMvZ3B1L2RybS90dG0vdHRtX2JvX3V0aWwuYyBiL2RyaXZlcnMv Z3B1L2RybS90dG0vdHRtX2JvX3V0aWwuYwo+PiBpbmRleCBhZThiNjE0NjA3MjQuLjkxMmNiZThl NjBhMiAxMDA2NDQKPj4gLS0tIGEvZHJpdmVycy9ncHUvZHJtL3R0bS90dG1fYm9fdXRpbC5jCj4+ ICsrKyBiL2RyaXZlcnMvZ3B1L2RybS90dG0vdHRtX2JvX3V0aWwuYwo+PiBAQCAtNzIsMTkwICs3 MiwxMjYgQEAgdm9pZCB0dG1fbWVtX2lvX2ZyZWUoc3RydWN0IHR0bV9kZXZpY2UgKmJkZXYsCj4+ ICAgICAgICAgIG1lbS0+YnVzLmFkZHIgPSBOVUxMOwo+PiAgIH0KPj4KPj4gLXN0YXRpYyBpbnQg dHRtX3Jlc291cmNlX2lvcmVtYXAoc3RydWN0IHR0bV9kZXZpY2UgKmJkZXYsCj4+IC0gICAgICAg ICAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3QgdHRtX3Jlc291cmNlICptZW0sCj4+IC0gICAg ICAgICAgICAgICAgICAgICAgICAgICAgICB2b2lkICoqdmlydHVhbCkKPj4gKy8qKgo+PiArICog dHRtX21vdmVfbWVtY3B5IC0gSGVscGVyIHRvIHBlcmZvcm0gYSBtZW1jcHkgdHRtIG1vdmUgb3Bl cmF0aW9uLgo+PiArICogQGJvOiBUaGUgc3RydWN0IHR0bV9idWZmZXJfb2JqZWN0Lgo+PiArICog QG5ld19tZW06IFRoZSBzdHJ1Y3QgdHRtX3Jlc291cmNlIHdlJ3JlIG1vdmluZyB0byAoY29weSBk ZXN0aW5hdGlvbikuCj4+ICsgKiBAbmV3X2l0ZXI6IEEgc3RydWN0IHR0bV9rbWFwX2l0ZXIgcmVw cmVzZW50aW5nIHRoZSBkZXN0aW5hdGlvbiByZXNvdXJjZS4KPj4gKyAqIEBzcmNfaXRlcjogQSBz dHJ1Y3QgdHRtX2ttYXBfaXRlciByZXByZXNlbnRpbmcgdGhlIHNvdXJjZSByZXNvdXJjZS4KPj4g KyAqCj4+ICsgKiBUaGlzIGZ1bmN0aW9uIGlzIGludGVuZGVkIHRvIGJlIGFibGUgdG8gbW92ZSBv dXQgYXN5bmMgdW5kZXIgYQo+PiArICogZG1hLWZlbmNlIGlmIGRlc2lyZWQuCj4+ICsgKi8KPj4g K3ZvaWQgdHRtX21vdmVfbWVtY3B5KHN0cnVjdCB0dG1fYnVmZmVyX29iamVjdCAqYm8sCj4+ICsg ICAgICAgICAgICAgICAgICAgIHN0cnVjdCB0dG1fcmVzb3VyY2UgKmRzdF9tZW0sCj4+ICsgICAg ICAgICAgICAgICAgICAgIHN0cnVjdCB0dG1fa21hcF9pdGVyICpkc3RfaXRlciwKPj4gKyAgICAg ICAgICAgICAgICAgICAgc3RydWN0IHR0bV9rbWFwX2l0ZXIgKnNyY19pdGVyKQo+PiAgIHsKPj4g LSAgICAgICBpbnQgcmV0Owo+PiAtICAgICAgIHZvaWQgKmFkZHI7Cj4+IC0KPj4gLSAgICAgICAq dmlydHVhbCA9IE5VTEw7Cj4+IC0gICAgICAgcmV0ID0gdHRtX21lbV9pb19yZXNlcnZlKGJkZXYs IG1lbSk7Cj4+IC0gICAgICAgaWYgKHJldCB8fCAhbWVtLT5idXMuaXNfaW9tZW0pCj4+IC0gICAg ICAgICAgICAgICByZXR1cm4gcmV0Owo+PiArICAgICAgIGNvbnN0IHN0cnVjdCB0dG1fa21hcF9p dGVyX29wcyAqZHN0X29wcyA9IGRzdF9pdGVyLT5vcHM7Cj4+ICsgICAgICAgY29uc3Qgc3RydWN0 IHR0bV9rbWFwX2l0ZXJfb3BzICpzcmNfb3BzID0gc3JjX2l0ZXItPm9wczsKPj4gKyAgICAgICBz dHJ1Y3QgdHRtX3R0ICp0dG0gPSBiby0+dHRtOwo+PiArICAgICAgIHN0cnVjdCBkbWFfYnVmX21h cCBzcmNfbWFwLCBkc3RfbWFwOwo+PiArICAgICAgIHBnb2ZmX3QgaTsKPj4KPj4gLSAgICAgICBp ZiAobWVtLT5idXMuYWRkcikgewo+PiAtICAgICAgICAgICAgICAgYWRkciA9IG1lbS0+YnVzLmFk ZHI7Cj4+IC0gICAgICAgfSBlbHNlIHsKPj4gLSAgICAgICAgICAgICAgIHNpemVfdCBidXNfc2l6 ZSA9IChzaXplX3QpbWVtLT5udW1fcGFnZXMgPDwgUEFHRV9TSElGVDsKPj4gKyAgICAgICAvKiBT aW5nbGUgVFRNIG1vdmUuIE5PUCAqLwo+PiArICAgICAgIGlmIChkc3Rfb3BzLT5tYXBzX3R0ICYm IHNyY19vcHMtPm1hcHNfdHQpCj4+ICsgICAgICAgICAgICAgICByZXR1cm47Cj4+Cj4+IC0gICAg ICAgICAgICAgICBpZiAobWVtLT5idXMuY2FjaGluZyA9PSB0dG1fd3JpdGVfY29tYmluZWQpCj4+ IC0gICAgICAgICAgICAgICAgICAgICAgIGFkZHIgPSBpb3JlbWFwX3djKG1lbS0+YnVzLm9mZnNl dCwgYnVzX3NpemUpOwo+PiAtI2lmZGVmIENPTkZJR19YODYKPj4gLSAgICAgICAgICAgICAgIGVs c2UgaWYgKG1lbS0+YnVzLmNhY2hpbmcgPT0gdHRtX2NhY2hlZCkKPj4gLSAgICAgICAgICAgICAg ICAgICAgICAgYWRkciA9IGlvcmVtYXBfY2FjaGUobWVtLT5idXMub2Zmc2V0LCBidXNfc2l6ZSk7 Cj4+IC0jZW5kaWYKPj4gLSAgICAgICAgICAgICAgIGVsc2UKPj4gLSAgICAgICAgICAgICAgICAg ICAgICAgYWRkciA9IGlvcmVtYXAobWVtLT5idXMub2Zmc2V0LCBidXNfc2l6ZSk7Cj4+IC0gICAg ICAgICAgICAgICBpZiAoIWFkZHIpIHsKPj4gLSAgICAgICAgICAgICAgICAgICAgICAgdHRtX21l bV9pb19mcmVlKGJkZXYsIG1lbSk7Cj4+IC0gICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAt RU5PTUVNOwo+PiArICAgICAgIC8qIERvbid0IG1vdmUgbm9uZXhpc3RlbnQgZGF0YS4gQ2xlYXIg ZGVzdGluYXRpb24gaW5zdGVhZC4gKi8KPj4gKyAgICAgICBpZiAoc3JjX29wcy0+bWFwc190dCAm JiAoIXR0bSB8fCAhdHRtX3R0X2lzX3BvcHVsYXRlZCh0dG0pKSkgewo+PiArICAgICAgICAgICAg ICAgaWYgKHR0bSAmJiAhKHR0bS0+cGFnZV9mbGFncyAmIFRUTV9QQUdFX0ZMQUdfWkVST19BTExP QykpCj4+ICsgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjsKPj4gKwo+PiArICAgICAgICAg ICAgICAgZm9yIChpID0gMDsgaSA8IGRzdF9tZW0tPm51bV9wYWdlczsgKytpKSB7Cj4+ICsgICAg ICAgICAgICAgICAgICAgICAgIGRzdF9vcHMtPm1hcF9sb2NhbChkc3RfaXRlciwgJmRzdF9tYXAs IGkpOwo+PiArICAgICAgICAgICAgICAgICAgICAgICBpZiAoZHN0X21hcC5pc19pb21lbSkKPj4g KyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZW1zZXRfaW8oZHN0X21hcC52YWRkcl9p b21lbSwgMCwgUEFHRV9TSVpFKTsKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgZWxzZQo+PiAr ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lbXNldChkc3RfbWFwLnZhZGRyLCAwLCBQ QUdFX1NJWkUpOwo+PiArICAgICAgICAgICAgICAgICAgICAgICBpZiAoZHN0X29wcy0+dW5tYXBf bG9jYWwpCj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHN0X29wcy0+dW5tYXBf bG9jYWwoZHN0X2l0ZXIsICZkc3RfbWFwKTsKPj4gICAgICAgICAgICAgICAgICB9Cj4+ICsgICAg ICAgICAgICAgICByZXR1cm47Cj4+ICAgICAgICAgIH0KPj4gLSAgICAgICAqdmlydHVhbCA9IGFk ZHI7Cj4+IC0gICAgICAgcmV0dXJuIDA7Cj4+IC19Cj4+IC0KPj4gLXN0YXRpYyB2b2lkIHR0bV9y ZXNvdXJjZV9pb3VubWFwKHN0cnVjdCB0dG1fZGV2aWNlICpiZGV2LAo+PiAtICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgIHN0cnVjdCB0dG1fcmVzb3VyY2UgKm1lbSwKPj4gLSAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICB2b2lkICp2aXJ0dWFsKQo+PiAtewo+PiAtICAgICAgIGlm ICh2aXJ0dWFsICYmIG1lbS0+YnVzLmFkZHIgPT0gTlVMTCkKPj4gLSAgICAgICAgICAgICAgIGlv dW5tYXAodmlydHVhbCk7Cj4+IC0gICAgICAgdHRtX21lbV9pb19mcmVlKGJkZXYsIG1lbSk7Cj4+ IC19Cj4+IC0KPj4gLXN0YXRpYyBpbnQgdHRtX2NvcHlfaW9fcGFnZSh2b2lkICpkc3QsIHZvaWQg KnNyYywgdW5zaWduZWQgbG9uZyBwYWdlKQo+PiAtewo+PiAtICAgICAgIHVpbnQzMl90ICpkc3RQ ID0KPj4gLSAgICAgICAgICAgKHVpbnQzMl90ICopICgodW5zaWduZWQgbG9uZylkc3QgKyAocGFn ZSA8PCBQQUdFX1NISUZUKSk7Cj4+IC0gICAgICAgdWludDMyX3QgKnNyY1AgPQo+PiAtICAgICAg ICAgICAodWludDMyX3QgKikgKCh1bnNpZ25lZCBsb25nKXNyYyArIChwYWdlIDw8IFBBR0VfU0hJ RlQpKTsKPj4gLQo+PiAtICAgICAgIGludCBpOwo+PiAtICAgICAgIGZvciAoaSA9IDA7IGkgPCBQ QUdFX1NJWkUgLyBzaXplb2YodWludDMyX3QpOyArK2kpCj4+IC0gICAgICAgICAgICAgICBpb3dy aXRlMzIoaW9yZWFkMzIoc3JjUCsrKSwgZHN0UCsrKTsKPj4gLSAgICAgICByZXR1cm4gMDsKPj4g LX0KPj4gLQo+PiAtc3RhdGljIGludCB0dG1fY29weV9pb190dG1fcGFnZShzdHJ1Y3QgdHRtX3R0 ICp0dG0sIHZvaWQgKnNyYywKPj4gLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bnNp Z25lZCBsb25nIHBhZ2UsCj4+IC0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGdwcm90 X3QgcHJvdCkKPj4gLXsKPj4gLSAgICAgICBzdHJ1Y3QgcGFnZSAqZCA9IHR0bS0+cGFnZXNbcGFn ZV07Cj4+IC0gICAgICAgdm9pZCAqZHN0Owo+PiAtCj4+IC0gICAgICAgaWYgKCFkKQo+PiAtICAg ICAgICAgICAgICAgcmV0dXJuIC1FTk9NRU07Cj4+IC0KPj4gLSAgICAgICBzcmMgPSAodm9pZCAq KSgodW5zaWduZWQgbG9uZylzcmMgKyAocGFnZSA8PCBQQUdFX1NISUZUKSk7Cj4+IC0gICAgICAg ZHN0ID0ga21hcF9hdG9taWNfcHJvdChkLCBwcm90KTsKPj4gLSAgICAgICBpZiAoIWRzdCkKPj4g LSAgICAgICAgICAgICAgIHJldHVybiAtRU5PTUVNOwo+PiAtCj4+IC0gICAgICAgbWVtY3B5X2Zy b21pbyhkc3QsIHNyYywgUEFHRV9TSVpFKTsKPj4gLQo+PiAtICAgICAgIGt1bm1hcF9hdG9taWMo ZHN0KTsKPj4gLQo+PiAtICAgICAgIHJldHVybiAwOwo+PiAtfQo+PiAtCj4+IC1zdGF0aWMgaW50 IHR0bV9jb3B5X3R0bV9pb19wYWdlKHN0cnVjdCB0dG1fdHQgKnR0bSwgdm9pZCAqZHN0LAo+PiAt ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuc2lnbmVkIGxvbmcgcGFnZSwKPj4gLSAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwZ3Byb3RfdCBwcm90KQo+PiAtewo+PiAtICAg ICAgIHN0cnVjdCBwYWdlICpzID0gdHRtLT5wYWdlc1twYWdlXTsKPj4gLSAgICAgICB2b2lkICpz cmM7Cj4+IC0KPj4gLSAgICAgICBpZiAoIXMpCj4+IC0gICAgICAgICAgICAgICByZXR1cm4gLUVO T01FTTsKPj4gLQo+PiAtICAgICAgIGRzdCA9ICh2b2lkICopKCh1bnNpZ25lZCBsb25nKWRzdCAr IChwYWdlIDw8IFBBR0VfU0hJRlQpKTsKPj4gLSAgICAgICBzcmMgPSBrbWFwX2F0b21pY19wcm90 KHMsIHByb3QpOwo+PiAtICAgICAgIGlmICghc3JjKQo+PiAtICAgICAgICAgICAgICAgcmV0dXJu IC1FTk9NRU07Cj4+Cj4+IC0gICAgICAgbWVtY3B5X3RvaW8oZHN0LCBzcmMsIFBBR0VfU0laRSk7 Cj4+IC0KPj4gLSAgICAgICBrdW5tYXBfYXRvbWljKHNyYyk7Cj4+ICsgICAgICAgZm9yIChpID0g MDsgaSA8IGRzdF9tZW0tPm51bV9wYWdlczsgKytpKSB7Cj4+ICsgICAgICAgICAgICAgICBkc3Rf b3BzLT5tYXBfbG9jYWwoZHN0X2l0ZXIsICZkc3RfbWFwLCBpKTsKPj4gKyAgICAgICAgICAgICAg IHNyY19vcHMtPm1hcF9sb2NhbChzcmNfaXRlciwgJnNyY19tYXAsIGkpOwo+PiArCj4+ICsgICAg ICAgICAgICAgICBpZiAoIXNyY19tYXAuaXNfaW9tZW0gJiYgIWRzdF9tYXAuaXNfaW9tZW0pIHsK Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgbWVtY3B5KGRzdF9tYXAudmFkZHIsIHNyY19tYXAu dmFkZHIsIFBBR0VfU0laRSk7Cj4+ICsgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFzcmNfbWFw LmlzX2lvbWVtKSB7Cj4+ICsgICAgICAgICAgICAgICAgICAgICAgIGRtYV9idWZfbWFwX21lbWNw eV90bygmZHN0X21hcCwgc3JjX21hcC52YWRkciwKPj4gKyAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgIFBBR0VfU0laRSk7Cj4+ICsgICAgICAgICAgICAgICB9IGVs c2UgaWYgKCFkc3RfbWFwLmlzX2lvbWVtKSB7Cj4+ICsgICAgICAgICAgICAgICAgICAgICAgIG1l bWNweV9mcm9taW8oZHN0X21hcC52YWRkciwgc3JjX21hcC52YWRkcl9pb21lbSwKPj4gKyAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQQUdFX1NJWkUpOwo+PiArICAgICAgICAg ICAgICAgfSBlbHNlIHsKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgaW50IGo7Cj4+ICsgICAg ICAgICAgICAgICAgICAgICAgIHUzMiBfX2lvbWVtICpzcmMgPSBzcmNfbWFwLnZhZGRyX2lvbWVt Owo+PiArICAgICAgICAgICAgICAgICAgICAgICB1MzIgX19pb21lbSAqZHN0ID0gZHN0X21hcC52 YWRkcl9pb21lbTsKPj4KPj4gLSAgICAgICByZXR1cm4gMDsKPj4gKyAgICAgICAgICAgICAgICAg ICAgICAgZm9yIChqID0gMDsgaiA8IChQQUdFX1NJWkUgPj4gMik7ICsraikKPiBJTU8gUEFHRV9T SVpFIC8gc2l6ZW9mKHUzMikgaXMgZWFzaWVyIHRvIHVuZGVyc3RhbmQuCgpPSywgd2lsbCBmaXgu CgoKPgo+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlvd3JpdGUzMihpb3JlYWQz MihzcmMrKyksIGRzdCsrKTsKPj4gKyAgICAgICAgICAgICAgIH0KPj4gKyAgICAgICAgICAgICAg IGlmIChzcmNfb3BzLT51bm1hcF9sb2NhbCkKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgc3Jj X29wcy0+dW5tYXBfbG9jYWwoc3JjX2l0ZXIsICZzcmNfbWFwKTsKPj4gKyAgICAgICAgICAgICAg IGlmIChkc3Rfb3BzLT51bm1hcF9sb2NhbCkKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgZHN0 X29wcy0+dW5tYXBfbG9jYWwoZHN0X2l0ZXIsICZkc3RfbWFwKTsKPj4gKyAgICAgICB9Cj4+ICAg fQo+PiArRVhQT1JUX1NZTUJPTCh0dG1fbW92ZV9tZW1jcHkpOwo+Pgo+PiAgIGludCB0dG1fYm9f bW92ZV9tZW1jcHkoc3RydWN0IHR0bV9idWZmZXJfb2JqZWN0ICpibywKPj4gICAgICAgICAgICAg ICAgICAgICAgICAgc3RydWN0IHR0bV9vcGVyYXRpb25fY3R4ICpjdHgsCj4+IC0gICAgICAgICAg ICAgICAgICAgICAgc3RydWN0IHR0bV9yZXNvdXJjZSAqbmV3X21lbSkKPj4gKyAgICAgICAgICAg ICAgICAgICAgICBzdHJ1Y3QgdHRtX3Jlc291cmNlICpkc3RfbWVtKQo+PiAgIHsKPj4gICAgICAg ICAgc3RydWN0IHR0bV9kZXZpY2UgKmJkZXYgPSBiby0+YmRldjsKPj4gLSAgICAgICBzdHJ1Y3Qg dHRtX3Jlc291cmNlX21hbmFnZXIgKm1hbiA9IHR0bV9tYW5hZ2VyX3R5cGUoYmRldiwgbmV3X21l bS0+bWVtX3R5cGUpOwo+PiArICAgICAgIHN0cnVjdCB0dG1fcmVzb3VyY2VfbWFuYWdlciAqZHN0 X21hbiA9Cj4+ICsgICAgICAgICAgICAgICB0dG1fbWFuYWdlcl90eXBlKGJvLT5iZGV2LCBkc3Rf bWVtLT5tZW1fdHlwZSk7Cj4+ICAgICAgICAgIHN0cnVjdCB0dG1fdHQgKnR0bSA9IGJvLT50dG07 Cj4+IC0gICAgICAgc3RydWN0IHR0bV9yZXNvdXJjZSAqb2xkX21lbSA9ICZiby0+bWVtOwo+PiAt ICAgICAgIHN0cnVjdCB0dG1fcmVzb3VyY2Ugb2xkX2NvcHkgPSAqb2xkX21lbTsKPj4gLSAgICAg ICB2b2lkICpvbGRfaW9tYXA7Cj4+IC0gICAgICAgdm9pZCAqbmV3X2lvbWFwOwo+PiArICAgICAg IHN0cnVjdCB0dG1fcmVzb3VyY2UgKnNyY19tZW0gPSAmYm8tPm1lbTsKPj4gKyAgICAgICBzdHJ1 Y3QgdHRtX3Jlc291cmNlX21hbmFnZXIgKnNyY19tYW4gPQo+PiArICAgICAgICAgICAgICAgdHRt X21hbmFnZXJfdHlwZShiZGV2LCBzcmNfbWVtLT5tZW1fdHlwZSk7Cj4+ICsgICAgICAgc3RydWN0 IHR0bV9yZXNvdXJjZSBzcmNfY29weSA9ICpzcmNfbWVtOwo+PiArICAgICAgIHVuaW9uIHsKPj4g KyAgICAgICAgICAgICAgIHN0cnVjdCB0dG1fa21hcF9pdGVyX3R0IHR0Owo+PiArICAgICAgICAg ICAgICAgc3RydWN0IHR0bV9rbWFwX2l0ZXJfbGluZWFyX2lvIGlvOwo+PiArICAgICAgIH0gX2Rz dF9pdGVyLCBfc3JjX2l0ZXI7Cj4+ICsgICAgICAgc3RydWN0IHR0bV9rbWFwX2l0ZXIgKmRzdF9p dGVyLCAqc3JjX2l0ZXI7Cj4+ICAgICAgICAgIGludCByZXQ7Cj4+IC0gICAgICAgdW5zaWduZWQg bG9uZyBpOwo+Pgo+PiAtICAgICAgIHJldCA9IHR0bV9ib193YWl0X2N0eChibywgY3R4KTsKPj4g LSAgICAgICBpZiAocmV0KQo+PiAtICAgICAgICAgICAgICAgcmV0dXJuIHJldDsKPj4gLQo+PiAt ICAgICAgIHJldCA9IHR0bV9yZXNvdXJjZV9pb3JlbWFwKGJkZXYsIG9sZF9tZW0sICZvbGRfaW9t YXApOwo+PiAtICAgICAgIGlmIChyZXQpCj4+IC0gICAgICAgICAgICAgICByZXR1cm4gcmV0Owo+ PiAtICAgICAgIHJldCA9IHR0bV9yZXNvdXJjZV9pb3JlbWFwKGJkZXYsIG5ld19tZW0sICZuZXdf aW9tYXApOwo+PiAtICAgICAgIGlmIChyZXQpCj4+IC0gICAgICAgICAgICAgICBnb3RvIG91dDsK Pj4gLQo+PiAtICAgICAgIC8qCj4+IC0gICAgICAgICogU2luZ2xlIFRUTSBtb3ZlLiBOT1AuCj4+ IC0gICAgICAgICovCj4+IC0gICAgICAgaWYgKG9sZF9pb21hcCA9PSBOVUxMICYmIG5ld19pb21h cCA9PSBOVUxMKQo+PiAtICAgICAgICAgICAgICAgZ290byBvdXQyOwo+PiAtCj4+IC0gICAgICAg LyoKPj4gLSAgICAgICAgKiBEb24ndCBtb3ZlIG5vbmV4aXN0ZW50IGRhdGEuIENsZWFyIGRlc3Rp bmF0aW9uIGluc3RlYWQuCj4+IC0gICAgICAgICovCj4+IC0gICAgICAgaWYgKG9sZF9pb21hcCA9 PSBOVUxMICYmCj4+IC0gICAgICAgICAgICh0dG0gPT0gTlVMTCB8fCAoIXR0bV90dF9pc19wb3B1 bGF0ZWQodHRtKSAmJgo+PiAtICAgICAgICAgICAgICAgICAgICAgICAgICAgICEodHRtLT5wYWdl X2ZsYWdzICYgVFRNX1BBR0VfRkxBR19TV0FQUEVEKSkpKSB7Cj4+IC0gICAgICAgICAgICAgICBt ZW1zZXRfaW8obmV3X2lvbWFwLCAwLCBuZXdfbWVtLT5udW1fcGFnZXMqUEFHRV9TSVpFKTsKPj4g LSAgICAgICAgICAgICAgIGdvdG8gb3V0MjsKPj4gLSAgICAgICB9Cj4+IC0KPj4gLSAgICAgICAv Kgo+PiAtICAgICAgICAqIFRUTSBtaWdodCBiZSBudWxsIGZvciBtb3ZlcyB3aXRoaW4gdGhlIHNh bWUgcmVnaW9uLgo+PiAtICAgICAgICAqLwo+PiAtICAgICAgIGlmICh0dG0pIHsKPj4gKyAgICAg ICBpZiAodHRtICYmICgodHRtLT5wYWdlX2ZsYWdzICYgVFRNX1BBR0VfRkxBR19TV0FQUEVEKSB8 fAo+PiArICAgICAgICAgICAgICAgICAgIGRzdF9tYW4tPnVzZV90dCkpIHsKPj4gICAgICAgICAg ICAgICAgICByZXQgPSB0dG1fdHRfcG9wdWxhdGUoYmRldiwgdHRtLCBjdHgpOwo+PiAgICAgICAg ICAgICAgICAgIGlmIChyZXQpCj4+IC0gICAgICAgICAgICAgICAgICAgICAgIGdvdG8gb3V0MTsK Pj4gKyAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJldDsKPj4gICAgICAgICAgfQo+Pgo+ PiAtICAgICAgIGZvciAoaSA9IDA7IGkgPCBuZXdfbWVtLT5udW1fcGFnZXM7ICsraSkgewo+PiAt ICAgICAgICAgICAgICAgaWYgKG9sZF9pb21hcCA9PSBOVUxMKSB7Cj4+IC0gICAgICAgICAgICAg ICAgICAgICAgIHBncHJvdF90IHByb3QgPSB0dG1faW9fcHJvdChibywgb2xkX21lbSwgUEFHRV9L RVJORUwpOwo+PiAtICAgICAgICAgICAgICAgICAgICAgICByZXQgPSB0dG1fY29weV90dG1faW9f cGFnZSh0dG0sIG5ld19pb21hcCwgaSwKPj4gLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgcHJvdCk7Cj4+IC0gICAgICAgICAgICAgICB9IGVsc2UgaWYg KG5ld19pb21hcCA9PSBOVUxMKSB7Cj4+IC0gICAgICAgICAgICAgICAgICAgICAgIHBncHJvdF90 IHByb3QgPSB0dG1faW9fcHJvdChibywgbmV3X21lbSwgUEFHRV9LRVJORUwpOwo+PiAtICAgICAg ICAgICAgICAgICAgICAgICByZXQgPSB0dG1fY29weV9pb190dG1fcGFnZSh0dG0sIG9sZF9pb21h cCwgaSwKPj4gLSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgcHJvdCk7Cj4+IC0gICAgICAgICAgICAgICB9IGVsc2Ugewo+PiAtICAgICAgICAgICAgICAg ICAgICAgICByZXQgPSB0dG1fY29weV9pb19wYWdlKG5ld19pb21hcCwgb2xkX2lvbWFwLCBpKTsK Pj4gLSAgICAgICAgICAgICAgIH0KPj4gLSAgICAgICAgICAgICAgIGlmIChyZXQpCj4+IC0gICAg ICAgICAgICAgICAgICAgICAgIGdvdG8gb3V0MTsKPj4gKyAgICAgICBkc3RfaXRlciA9IHR0bV9r bWFwX2l0ZXJfbGluZWFyX2lvX2luaXQoJl9kc3RfaXRlci5pbywgYmRldiwgZHN0X21lbSk7Cj4+ ICsgICAgICAgaWYgKFBUUl9FUlIoZHN0X2l0ZXIpID09IC1FSU5WQUwgJiYgZHN0X21hbi0+dXNl X3R0KQo+PiArICAgICAgICAgICAgICAgZHN0X2l0ZXIgPSB0dG1fa21hcF9pdGVyX3R0X2luaXQo Jl9kc3RfaXRlci50dCwgYm8tPnR0bSk7Cj4+ICsgICAgICAgaWYgKElTX0VSUihkc3RfaXRlcikp Cj4+ICsgICAgICAgICAgICAgICByZXR1cm4gUFRSX0VSUihkc3RfaXRlcik7Cj4+ICsKPj4gKyAg ICAgICBzcmNfaXRlciA9IHR0bV9rbWFwX2l0ZXJfbGluZWFyX2lvX2luaXQoJl9zcmNfaXRlci5p bywgYmRldiwgc3JjX21lbSk7Cj4+ICsgICAgICAgaWYgKFBUUl9FUlIoc3JjX2l0ZXIpID09IC1F SU5WQUwgJiYgc3JjX21hbi0+dXNlX3R0KQo+PiArICAgICAgICAgICAgICAgc3JjX2l0ZXIgPSB0 dG1fa21hcF9pdGVyX3R0X2luaXQoJl9zcmNfaXRlci50dCwgYm8tPnR0bSk7Cj4+ICsgICAgICAg aWYgKElTX0VSUihzcmNfaXRlcikpIHsKPj4gKyAgICAgICAgICAgICAgIHJldCA9IFBUUl9FUlIo c3JjX2l0ZXIpOwo+PiArICAgICAgICAgICAgICAgZ290byBvdXRfc3JjX2l0ZXI7Cj4+ICAgICAg ICAgIH0KPj4gLSAgICAgICBtYigpOwo+PiAtb3V0MjoKPj4gLSAgICAgICBvbGRfY29weSA9ICpv bGRfbWVtOwo+Pgo+PiAtICAgICAgIHR0bV9ib19hc3NpZ25fbWVtKGJvLCBuZXdfbWVtKTsKPj4g LQo+PiAtICAgICAgIGlmICghbWFuLT51c2VfdHQpCj4+IC0gICAgICAgICAgICAgICB0dG1fYm9f dHRfZGVzdHJveShibyk7Cj4+ICsgICAgICAgdHRtX21vdmVfbWVtY3B5KGJvLCBkc3RfbWVtLCBk c3RfaXRlciwgc3JjX2l0ZXIpOwo+PiArICAgICAgIHNyY19jb3B5ID0gKnNyY19tZW07Cj4+ICsg ICAgICAgdHRtX2JvX21vdmVfc3luY19jbGVhbnVwKGJvLCBkc3RfbWVtKTsKPj4KPj4gLW91dDE6 Cj4+IC0gICAgICAgdHRtX3Jlc291cmNlX2lvdW5tYXAoYmRldiwgb2xkX21lbSwgbmV3X2lvbWFw KTsKPj4gLW91dDoKPj4gLSAgICAgICB0dG1fcmVzb3VyY2VfaW91bm1hcChiZGV2LCAmb2xkX2Nv cHksIG9sZF9pb21hcCk7Cj4+ICsgICAgICAgaWYgKCFzcmNfaXRlci0+b3BzLT5tYXBzX3R0KQo+ PiArICAgICAgICAgICAgICAgdHRtX2ttYXBfaXRlcl9saW5lYXJfaW9fZmluaSgmX3NyY19pdGVy LmlvLCBiZGV2LCAmc3JjX2NvcHkpOwo+PiArb3V0X3NyY19pdGVyOgo+PiArICAgICAgIGlmICgh ZHN0X2l0ZXItPm9wcy0+bWFwc190dCkKPj4gKyAgICAgICAgICAgICAgIHR0bV9rbWFwX2l0ZXJf bGluZWFyX2lvX2ZpbmkoJl9kc3RfaXRlci5pbywgYmRldiwgZHN0X21lbSk7Cj4+Cj4+IC0gICAg ICAgLyoKPj4gLSAgICAgICAgKiBPbiBlcnJvciwga2VlcCB0aGUgbW0gbm9kZSEKPj4gLSAgICAg ICAgKi8KPj4gLSAgICAgICBpZiAoIXJldCkKPj4gLSAgICAgICAgICAgICAgIHR0bV9yZXNvdXJj ZV9mcmVlKGJvLCAmb2xkX2NvcHkpOwo+PiAgICAgICAgICByZXR1cm4gcmV0Owo+PiAgIH0KPj4g ICBFWFBPUlRfU1lNQk9MKHR0bV9ib19tb3ZlX21lbWNweSk7Cj4+IEBAIC0zMzYsMjcgKzI3Miw3 IEBAIHBncHJvdF90IHR0bV9pb19wcm90KHN0cnVjdCB0dG1fYnVmZmVyX29iamVjdCAqYm8sIHN0 cnVjdCB0dG1fcmVzb3VyY2UgKnJlcywKPj4gICAgICAgICAgbWFuID0gdHRtX21hbmFnZXJfdHlw ZShiby0+YmRldiwgcmVzLT5tZW1fdHlwZSk7Cj4+ICAgICAgICAgIGNhY2hpbmcgPSBtYW4tPnVz ZV90dCA/IGJvLT50dG0tPmNhY2hpbmcgOiByZXMtPmJ1cy5jYWNoaW5nOwo+Pgo+PiAtICAgICAg IC8qIENhY2hlZCBtYXBwaW5ncyBuZWVkIG5vIGFkanVzdG1lbnQgKi8KPj4gLSAgICAgICBpZiAo Y2FjaGluZyA9PSB0dG1fY2FjaGVkKQo+PiAtICAgICAgICAgICAgICAgcmV0dXJuIHRtcDsKPj4g LQo+PiAtI2lmIGRlZmluZWQoX19pMzg2X18pIHx8IGRlZmluZWQoX194ODZfNjRfXykKPj4gLSAg ICAgICBpZiAoY2FjaGluZyA9PSB0dG1fd3JpdGVfY29tYmluZWQpCj4+IC0gICAgICAgICAgICAg ICB0bXAgPSBwZ3Byb3Rfd3JpdGVjb21iaW5lKHRtcCk7Cj4+IC0gICAgICAgZWxzZSBpZiAoYm9v dF9jcHVfZGF0YS54ODYgPiAzKQo+PiAtICAgICAgICAgICAgICAgdG1wID0gcGdwcm90X25vbmNh Y2hlZCh0bXApOwo+PiAtI2VuZGlmCj4+IC0jaWYgZGVmaW5lZChfX2lhNjRfXykgfHwgZGVmaW5l ZChfX2FybV9fKSB8fCBkZWZpbmVkKF9fYWFyY2g2NF9fKSB8fCBcCj4+IC0gICAgZGVmaW5lZChf X3Bvd2VycGNfXykgfHwgZGVmaW5lZChfX21pcHNfXykKPj4gLSAgICAgICBpZiAoY2FjaGluZyA9 PSB0dG1fd3JpdGVfY29tYmluZWQpCj4+IC0gICAgICAgICAgICAgICB0bXAgPSBwZ3Byb3Rfd3Jp dGVjb21iaW5lKHRtcCk7Cj4+IC0gICAgICAgZWxzZQo+PiAtICAgICAgICAgICAgICAgdG1wID0g cGdwcm90X25vbmNhY2hlZCh0bXApOwo+PiAtI2VuZGlmCj4+IC0jaWYgZGVmaW5lZChfX3NwYXJj X18pCj4+IC0gICAgICAgdG1wID0gcGdwcm90X25vbmNhY2hlZCh0bXApOwo+PiAtI2VuZGlmCj4+ IC0gICAgICAgcmV0dXJuIHRtcDsKPj4gKyAgICAgICByZXR1cm4gdHRtX3Byb3RfZnJvbV9jYWNo aW5nKGNhY2hpbmcsIHRtcCk7Cj4+ICAgfQo+PiAgIEVYUE9SVF9TWU1CT0wodHRtX2lvX3Byb3Qp Owo+Pgo+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL3R0bS90dG1fbW9kdWxlLmMgYi9k cml2ZXJzL2dwdS9kcm0vdHRtL3R0bV9tb2R1bGUuYwo+PiBpbmRleCA1NmIwZWZkYmExYTkuLjk5 N2M0NThmNjhhOSAxMDA2NDQKPj4gLS0tIGEvZHJpdmVycy9ncHUvZHJtL3R0bS90dG1fbW9kdWxl LmMKPj4gKysrIGIvZHJpdmVycy9ncHUvZHJtL3R0bS90dG1fbW9kdWxlLmMKPj4gQEAgLTMxLDEy ICszMSw0NyBAQAo+PiAgICAqLwo+PiAgICNpbmNsdWRlIDxsaW51eC9tb2R1bGUuaD4KPj4gICAj aW5jbHVkZSA8bGludXgvZGV2aWNlLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgvcGd0YWJsZS5oPgo+ PiAgICNpbmNsdWRlIDxsaW51eC9zY2hlZC5oPgo+PiAgICNpbmNsdWRlIDxsaW51eC9kZWJ1Z2Zz Lmg+Cj4+ICAgI2luY2x1ZGUgPGRybS9kcm1fc3lzZnMuaD4KPj4gKyNpbmNsdWRlIDxkcm0vdHRt L3R0bV9jYWNoaW5nLmg+Cj4+Cj4+ICAgI2luY2x1ZGUgInR0bV9tb2R1bGUuaCIKPj4KPj4gKy8q Kgo+PiArICogdHRtX3Byb3RfZnJvbV9jYWNoaW5nIC0gTW9kaWZ5IHRoZSBwYWdlIHByb3RlY3Rp b24gYWNjb3JkaW5nIHRvIHRoZQo+PiArICogdHRtIGNhY2luZyBtb2RlCj4+ICsgKiBAY2FjaGlu ZzogVGhlIHR0bSBjYWNoaW5nIG1vZGUKPj4gKyAqIEB0bXA6IFRoZSBvcmlnaW5hbCBwYWdlIHBy b3RlY3Rpb24KPj4gKyAqCj4+ICsgKiBSZXR1cm46IFRoZSBtb2RpZmllZCBwYWdlIHByb3RlY3Rp b24KPj4gKyAqLwo+PiArcGdwcm90X3QgdHRtX3Byb3RfZnJvbV9jYWNoaW5nKGVudW0gdHRtX2Nh Y2hpbmcgY2FjaGluZywgcGdwcm90X3QgdG1wKQo+PiArewo+PiArICAgICAgIC8qIENhY2hlZCBt YXBwaW5ncyBuZWVkIG5vIGFkanVzdG1lbnQgKi8KPj4gKyAgICAgICBpZiAoY2FjaGluZyA9PSB0 dG1fY2FjaGVkKQo+PiArICAgICAgICAgICAgICAgcmV0dXJuIHRtcDsKPj4gKwo+PiArI2lmIGRl ZmluZWQoX19pMzg2X18pIHx8IGRlZmluZWQoX194ODZfNjRfXykKPj4gKyAgICAgICBpZiAoY2Fj aGluZyA9PSB0dG1fd3JpdGVfY29tYmluZWQpCj4+ICsgICAgICAgICAgICAgICB0bXAgPSBwZ3By b3Rfd3JpdGVjb21iaW5lKHRtcCk7Cj4+ICsgICAgICAgZWxzZSBpZiAoYm9vdF9jcHVfZGF0YS54 ODYgPiAzKQo+PiArICAgICAgICAgICAgICAgdG1wID0gcGdwcm90X25vbmNhY2hlZCh0bXApOwo+ PiArI2VuZGlmCj4+ICsjaWYgZGVmaW5lZChfX2lhNjRfXykgfHwgZGVmaW5lZChfX2FybV9fKSB8 fCBkZWZpbmVkKF9fYWFyY2g2NF9fKSB8fCBcCj4+ICsgICAgICAgZGVmaW5lZChfX3Bvd2VycGNf XykgfHwgZGVmaW5lZChfX21pcHNfXykKPj4gKyAgICAgICBpZiAoY2FjaGluZyA9PSB0dG1fd3Jp dGVfY29tYmluZWQpCj4+ICsgICAgICAgICAgICAgICB0bXAgPSBwZ3Byb3Rfd3JpdGVjb21iaW5l KHRtcCk7Cj4+ICsgICAgICAgZWxzZQo+PiArICAgICAgICAgICAgICAgdG1wID0gcGdwcm90X25v bmNhY2hlZCh0bXApOwo+PiArI2VuZGlmCj4+ICsjaWYgZGVmaW5lZChfX3NwYXJjX18pCj4+ICsg ICAgICAgdG1wID0gcGdwcm90X25vbmNhY2hlZCh0bXApOwo+PiArI2VuZGlmCj4+ICsgICAgICAg cmV0dXJuIHRtcDsKPj4gK30KPj4gKwo+PiAgIHN0cnVjdCBkZW50cnkgKnR0bV9kZWJ1Z2ZzX3Jv b3Q7Cj4+Cj4+ICAgc3RhdGljIGludCBfX2luaXQgdHRtX2luaXQodm9pZCkKPj4gZGlmZiAtLWdp dCBhL2RyaXZlcnMvZ3B1L2RybS90dG0vdHRtX3Jlc291cmNlLmMgYi9kcml2ZXJzL2dwdS9kcm0v dHRtL3R0bV9yZXNvdXJjZS5jCj4+IGluZGV4IDU5ZTJiNzE1N2U0MS4uZTA1YWU3ZTNkNDc3IDEw MDY0NAo+PiAtLS0gYS9kcml2ZXJzL2dwdS9kcm0vdHRtL3R0bV9yZXNvdXJjZS5jCj4+ICsrKyBi L2RyaXZlcnMvZ3B1L2RybS90dG0vdHRtX3Jlc291cmNlLmMKPj4gQEAgLTIyLDYgKzIyLDEwIEBA Cj4+ICAgICogQXV0aG9yczogQ2hyaXN0aWFuIEvDtm5pZwo+PiAgICAqLwo+Pgo+PiArI2luY2x1 ZGUgPGxpbnV4L2RtYS1idWYtbWFwLmg+Cj4+ICsjaW5jbHVkZSA8bGludXgvaW8tbWFwcGluZy5o Pgo+PiArI2luY2x1ZGUgPGxpbnV4L3NjYXR0ZXJsaXN0Lmg+Cj4+ICsKPj4gICAjaW5jbHVkZSA8 ZHJtL3R0bS90dG1fcmVzb3VyY2UuaD4KPj4gICAjaW5jbHVkZSA8ZHJtL3R0bS90dG1fYm9fZHJp dmVyLmg+Cj4+Cj4+IEBAIC0xNDcsMyArMTUxLDE2NSBAQCB2b2lkIHR0bV9yZXNvdXJjZV9tYW5h Z2VyX2RlYnVnKHN0cnVjdCB0dG1fcmVzb3VyY2VfbWFuYWdlciAqbWFuLAo+PiAgICAgICAgICAg ICAgICAgIG1hbi0+ZnVuYy0+ZGVidWcobWFuLCBwKTsKPj4gICB9Cj4+ICAgRVhQT1JUX1NZTUJP TCh0dG1fcmVzb3VyY2VfbWFuYWdlcl9kZWJ1Zyk7Cj4+ICsKPj4gK3N0YXRpYyB2b2lkIHR0bV9r bWFwX2l0ZXJfaW9tYXBfbWFwX2xvY2FsKHN0cnVjdCB0dG1fa21hcF9pdGVyICppdGVyLAo+PiAr ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJ1Y3QgZG1hX2J1Zl9t YXAgKmRtYXAsCj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBn b2ZmX3QgaSkKPj4gK3sKPj4gKyAgICAgICBzdHJ1Y3QgdHRtX2ttYXBfaXRlcl9pb21hcCAqaXRl cl9pbyA9Cj4+ICsgICAgICAgICAgICAgICBjb250YWluZXJfb2YoaXRlciwgdHlwZW9mKCppdGVy X2lvKSwgYmFzZSk7Cj4+ICsgICAgICAgdm9pZCBfX2lvbWVtICphZGRyOwo+PiArCj4+ICtyZXRy eToKPj4gKyAgICAgICB3aGlsZSAoaSA+PSBpdGVyX2lvLT5jYWNoZS5lbmQpIHsKPj4gKyAgICAg ICAgICAgICAgIGl0ZXJfaW8tPmNhY2hlLnNnID0gaXRlcl9pby0+Y2FjaGUuc2cgPwo+PiArICAg ICAgICAgICAgICAgICAgICAgICBzZ19uZXh0KGl0ZXJfaW8tPmNhY2hlLnNnKSA6IGl0ZXJfaW8t PnN0LT5zZ2w7Cj4+ICsgICAgICAgICAgICAgICBpdGVyX2lvLT5jYWNoZS5pID0gaXRlcl9pby0+ Y2FjaGUuZW5kOwo+PiArICAgICAgICAgICAgICAgaXRlcl9pby0+Y2FjaGUuZW5kICs9IHNnX2Rt YV9sZW4oaXRlcl9pby0+Y2FjaGUuc2cpID4+Cj4+ICsgICAgICAgICAgICAgICAgICAgICAgIFBB R0VfU0hJRlQ7Cj4+ICsgICAgICAgICAgICAgICBpdGVyX2lvLT5jYWNoZS5vZmZzID0gc2dfZG1h X2FkZHJlc3MoaXRlcl9pby0+Y2FjaGUuc2cpIC0KPj4gKyAgICAgICAgICAgICAgICAgICAgICAg aXRlcl9pby0+c3RhcnQ7Cj4+ICsgICAgICAgfQo+PiArCj4+ICsgICAgICAgaWYgKGkgPCBpdGVy X2lvLT5jYWNoZS5pKSB7Cj4+ICsgICAgICAgICAgICAgICBpdGVyX2lvLT5jYWNoZS5lbmQgPSAw Owo+PiArICAgICAgICAgICAgICAgaXRlcl9pby0+Y2FjaGUuc2cgPSBOVUxMOwo+PiArICAgICAg ICAgICAgICAgZ290byByZXRyeTsKPj4gKyAgICAgICB9Cj4+ICsKPj4gKyAgICAgICBhZGRyID0g aW9fbWFwcGluZ19tYXBfbG9jYWxfd2MoaXRlcl9pby0+aW9tYXAsIGl0ZXJfaW8tPmNhY2hlLm9m ZnMgKwo+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoKChyZXNvdXJj ZV9zaXplX3QpaSAtIGl0ZXJfaW8tPmNhY2hlLmkpCj4+ICsgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICA8PCBQQUdFX1NISUZUKSk7Cj4+ICsgICAgICAgZG1hX2J1Zl9tYXBf c2V0X3ZhZGRyX2lvbWVtKGRtYXAsIGFkZHIpOwo+PiArfQo+PiArCj4+ICtzdGF0aWMgdm9pZCB0 dG1fa21hcF9pdGVyX2lvbWFwX3VubWFwX2xvY2FsKHN0cnVjdCB0dG1fa21hcF9pdGVyICppdGVy LAo+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBk bWFfYnVmX21hcCAqbWFwKQo+PiArewo+PiArICAgICAgIGlvX21hcHBpbmdfdW5tYXBfbG9jYWwo bWFwLT52YWRkcl9pb21lbSk7Cj4+ICt9Cj4+ICsKPj4gK3N0YXRpYyBjb25zdCBzdHJ1Y3QgdHRt X2ttYXBfaXRlcl9vcHMgdHRtX2ttYXBfaXRlcl9pb19vcHMgPSB7Cj4+ICsgICAgICAgLm1hcF9s b2NhbCA9ICB0dG1fa21hcF9pdGVyX2lvbWFwX21hcF9sb2NhbCwKPj4gKyAgICAgICAudW5tYXBf bG9jYWwgPSB0dG1fa21hcF9pdGVyX2lvbWFwX3VubWFwX2xvY2FsLAo+PiArICAgICAgIC5tYXBz X3R0ID0gZmFsc2UsCj4+ICt9Owo+PiArCj4+ICsvKioKPj4gKyAqIHR0bV9rbWFwX2l0ZXJfaW9t YXBfaW5pdCAtIEluaXRpYWxpemUgYSBzdHJ1Y3QgdHRtX2ttYXBfaXRlcl9pb21hcAo+PiArICog QGl0ZXJfaW86IFRoZSBzdHJ1Y3QgdHRtX2ttYXBfaXRlcl9pb21hcCB0byBpbml0aWFsaXplLgo+ PiArICogQGlvbWFwOiBUaGUgc3RydWN0IGlvX21hcHBpbmcgcmVwcmVzZW50aW5nIHRoZSB1bmRl cmx5aW5nIGxpbmVhciBpb19tZW1vcnkuCj4+ICsgKiBAc3Q6IHNnX3RhYmxlIGludG8gQGlvbWFw LCByZXByZXNlbnRpbmcgdGhlIG1lbW9yeSBvZiB0aGUgc3RydWN0Cj4+ICsgKiB0dG1fcmVzb3Vy Y2UuCj4+ICsgKiBAc3RhcnQ6IE9mZnNldCB0aGF0IG5lZWRzIHRvIGJlIHN1YnRyYWN0ZWQgZnJv bSBAc3QgdG8gbWFrZQo+PiArICogc2dfZG1hX2FkZHJlc3Moc3QtPnNnbCkgLSBAc3RhcnQgPT0g MCBmb3IgQGlvbWFwIHN0YXJ0Lgo+PiArICoKPj4gKyAqIFJldHVybjogUG9pbnRlciB0byB0aGUg ZW1iZWRkZWQgc3RydWN0IHR0bV9rbWFwX2l0ZXIuCj4+ICsgKi8KPj4gK3N0cnVjdCB0dG1fa21h cF9pdGVyICoKPj4gK3R0bV9rbWFwX2l0ZXJfaW9tYXBfaW5pdChzdHJ1Y3QgdHRtX2ttYXBfaXRl cl9pb21hcCAqaXRlcl9pbywKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBpb19t YXBwaW5nICppb21hcCwKPj4gKyAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCBzZ190YWJs ZSAqc3QsCj4+ICsgICAgICAgICAgICAgICAgICAgICAgICByZXNvdXJjZV9zaXplX3Qgc3RhcnQp Cj4+ICt7Cj4+ICsgICAgICAgaXRlcl9pby0+YmFzZS5vcHMgPSAmdHRtX2ttYXBfaXRlcl9pb19v cHM7Cj4+ICsgICAgICAgaXRlcl9pby0+aW9tYXAgPSBpb21hcDsKPj4gKyAgICAgICBpdGVyX2lv LT5zdCA9IHN0Owo+PiArICAgICAgIGl0ZXJfaW8tPnN0YXJ0ID0gc3RhcnQ7Cj4+ICsgICAgICAg bWVtc2V0KCZpdGVyX2lvLT5jYWNoZSwgMCwgc2l6ZW9mKGl0ZXJfaW8tPmNhY2hlKSk7Cj4+ICsK Pj4gKyAgICAgICByZXR1cm4gJml0ZXJfaW8tPmJhc2U7Cj4+ICt9Cj4+ICtFWFBPUlRfU1lNQk9M KHR0bV9rbWFwX2l0ZXJfaW9tYXBfaW5pdCk7Cj4+ICsKPj4gKy8qKgo+PiArICogRE9DOiBMaW5l YXIgaW8gaXRlcmF0b3IKPj4gKyAqCj4+ICsgKiBUaGlzIGNvZGUgc2hvdWxkIGRpZSBpbiB0aGUg bm90IHRvbyBuZWFyIGZ1dHVyZS4gQmVzdCB3b3VsZCBiZSBpZiB3ZSBjb3VsZAo+PiArICogbWFr ZSBpby1tYXBwaW5nIHVzZSBtZW1yZW1hcCBmb3IgYWxsIGlvIG1lbW9yeSwgYW5kIGhhdmUgbWVt cmVtYXAKPj4gKyAqIGltcGxlbWVudCBhIGttYXBfbG9jYWwgZnVuY3Rpb25hbGl0eS4gV2UgY291 bGQgdGhlbiBzdHJpcCBhIGh1Z2UgYW1vdW50IG9mCj4+ICsgKiBjb2RlLiBUaGVzZSBsaW5lYXIg aW8gaXRlcmF0b3JzIGFyZSBpbXBsZW1lbnRlZCB0byBtaW1pYyBvbGQgZnVuY3Rpb25hbGl0eSwK Pj4gKyAqIGFuZCB0aGV5IGRvbid0IHVzZSBrbWFwX2xvY2FsIHNlbWFudGljcyBhdCBhbGwgaW50 ZXJuYWxseS4gUmF0aGVyIGlvcmVtYXAgb3IKPj4gKyAqIGZyaWVuZHMsIGFuZCBhdCBsZWFzdCBv biAzMi1iaXQgdGhleSBhZGQgZ2xvYmFsIFRMQiBmbHVzaGVzIGFuZCBwb2ludHMKPj4gKyAqIG9m IGZhaWx1cmUuCj4+ICsgKi8KPj4gKwo+PiArc3RhdGljIHZvaWQgdHRtX2ttYXBfaXRlcl9saW5l YXJfaW9fbWFwX2xvY2FsKHN0cnVjdCB0dG1fa21hcF9pdGVyICppdGVyLAo+PiArICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RydWN0IGRtYV9idWZfbWFwICpk bWFwLAo+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGdv ZmZfdCBpKQo+PiArewo+PiArICAgICAgIHN0cnVjdCB0dG1fa21hcF9pdGVyX2xpbmVhcl9pbyAq aXRlcl9pbyA9Cj4+ICsgICAgICAgICAgICAgICBjb250YWluZXJfb2YoaXRlciwgdHlwZW9mKCpp dGVyX2lvKSwgYmFzZSk7Cj4+ICsKPj4gKyAgICAgICAqZG1hcCA9IGl0ZXJfaW8tPmRtYXA7Cj4+ ICsgICAgICAgZG1hX2J1Zl9tYXBfaW5jcihkbWFwLCBpICogUEFHRV9TSVpFKTsKPj4gK30KPj4g Kwo+PiArc3RhdGljIGNvbnN0IHN0cnVjdCB0dG1fa21hcF9pdGVyX29wcyB0dG1fa21hcF9pdGVy X2xpbmVhcl9pb19vcHMgPSB7Cj4+ICsgICAgICAgLm1hcF9sb2NhbCA9ICB0dG1fa21hcF9pdGVy X2xpbmVhcl9pb19tYXBfbG9jYWwsCj4+ICsgICAgICAgLm1hcHNfdHQgPSBmYWxzZSwKPj4gK307 Cj4+ICsKPj4gK3N0cnVjdCB0dG1fa21hcF9pdGVyICoKPj4gK3R0bV9rbWFwX2l0ZXJfbGluZWFy X2lvX2luaXQoc3RydWN0IHR0bV9rbWFwX2l0ZXJfbGluZWFyX2lvICppdGVyX2lvLAo+PiArICAg ICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCB0dG1fZGV2aWNlICpiZGV2LAo+PiArICAg ICAgICAgICAgICAgICAgICAgICAgICAgIHN0cnVjdCB0dG1fcmVzb3VyY2UgKm1lbSkKPj4gK3sK Pj4gKyAgICAgICBpbnQgcmV0Owo+PiArCj4+ICsgICAgICAgcmV0ID0gdHRtX21lbV9pb19yZXNl cnZlKGJkZXYsIG1lbSk7Cj4+ICsgICAgICAgaWYgKHJldCkKPj4gKyAgICAgICAgICAgICAgIGdv dG8gb3V0X2VycjsKPj4gKyAgICAgICBpZiAoIW1lbS0+YnVzLmlzX2lvbWVtKSB7Cj4+ICsgICAg ICAgICAgICAgICByZXQgPSAtRUlOVkFMOwo+PiArICAgICAgICAgICAgICAgZ290byBvdXRfaW9f ZnJlZTsKPj4gKyAgICAgICB9Cj4+ICsKPj4gKyAgICAgICBpZiAobWVtLT5idXMuYWRkcikgewo+ PiArICAgICAgICAgICAgICAgZG1hX2J1Zl9tYXBfc2V0X3ZhZGRyKCZpdGVyX2lvLT5kbWFwLCBt ZW0tPmJ1cy5hZGRyKTsKPj4gKyAgICAgICAgICAgICAgIGl0ZXJfaW8tPm5lZWRzX3VubWFwID0g ZmFsc2U7Cj4+ICsgICAgICAgfSBlbHNlIHsKPj4gKyAgICAgICAgICAgICAgIHNpemVfdCBidXNf c2l6ZSA9IChzaXplX3QpbWVtLT5udW1fcGFnZXMgPDwgUEFHRV9TSElGVDsKPj4gKwo+PiArICAg ICAgICAgICAgICAgaXRlcl9pby0+bmVlZHNfdW5tYXAgPSB0cnVlOwo+PiArICAgICAgICAgICAg ICAgaWYgKG1lbS0+YnVzLmNhY2hpbmcgPT0gdHRtX3dyaXRlX2NvbWJpbmVkKQo+PiArICAgICAg ICAgICAgICAgICAgICAgICBkbWFfYnVmX21hcF9zZXRfdmFkZHJfaW9tZW0oJml0ZXJfaW8tPmRt YXAsCj4+ICsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICBpb3JlbWFwX3djKG1lbS0+YnVzLm9mZnNldCwKPj4gKyAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnVzX3NpemUpKTsKPj4gKyAg ICAgICAgICAgICAgIGVsc2UgaWYgKG1lbS0+YnVzLmNhY2hpbmcgPT0gdHRtX2NhY2hlZCkKPj4g KyAgICAgICAgICAgICAgICAgICAgICAgZG1hX2J1Zl9tYXBfc2V0X3ZhZGRyKCZpdGVyX2lvLT5k bWFwLAo+PiArICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVt cmVtYXAobWVtLT5idXMub2Zmc2V0LCBidXNfc2l6ZSwKPj4gKyAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE1FTVJFTUFQX1dCKSk7Cj4gVGhlIGNv bW1lbnRzIGluIHNldF92YWRkciBzdWdnZXN0IHRoYXQgdGhpcyBpcyBtZWFudCBmb3IKPiBzeXN0 ZW0tbWVtb3J5LiBEb2VzIHRoYXQgYWN0dWFsbHkgbWF0dGVyIG9yIGlzIGl0IGp1c3QgYWJvdXQg bm90Cj4gbG9zaW5nIHRoZSBfX2lvbWVtIGFubm90YXRpb24gb24gcGxhdGZvcm1zIHdoZXJlIGl0 IG1hdHRlcnM/CgpZZXMsIGl0J3MgdGhlIGxhdHRlci4gZG1hX2J1Zl9tYXAoKSBpcyByZWxhdGl2 ZWx5IG5ldyBhbmQgdGhlIGF1dGhvciAKcHJvYmFibHkgZGlkbid0IHRoaW5rIGFib3V0IHRoZSBj YXNlIG9mIGNhY2hlZCBpb21lbSwgd2hpY2ggaXMgdXNlZCBieSwgCmZvciBleGFtcGxlLCB2bXdn ZnguCgo+IEFwcGFyZW50bHkgY2FjaGVkIGRldmljZSBsb2NhbCBpcyBhIHRoaW5nLiBBbHNvIHNo b3VsZCB0aGlzIG5vdCBiZQo+IHdyYXBwZWQgaW4gQ09ORklHX1g4Nj8KCkJvdGggZG1hX2J1Zl9t YXAoKSBhbmQgbWVtcmVtYXAgYXJlIGdlbmVyaWMsIEkgdGhpbmssIEkgZ3Vlc3MgbWVtcmVtYXAg CndvdWxkIHJldHVybiBOVUxMIGlmIGl0J3Mgbm90IHN1cHBvcnRlZC4KCi9UaG9tYXMKCgpfX19f X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXwpJbnRlbC1nZnggbWFp bGluZyBsaXN0CkludGVsLWdmeEBsaXN0cy5mcmVlZGVza3RvcC5vcmcKaHR0cHM6Ly9saXN0cy5m cmVlZGVza3RvcC5vcmcvbWFpbG1hbi9saXN0aW5mby9pbnRlbC1nZngK