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=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT 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 98DA0C48BE6 for ; Wed, 16 Jun 2021 15:25:31 +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 621D961351 for ; Wed, 16 Jun 2021 15:25:31 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 621D961351 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=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 A35176E5CA; Wed, 16 Jun 2021 15:25:30 +0000 (UTC) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7AD068993B; Wed, 16 Jun 2021 15:25:29 +0000 (UTC) IronPort-SDR: 9/AtcZ5tg6BxVYcqw7pIsAlNX7QU6iOwJeF866TKRu7rYlTMv+9ohugbzmsNTyXu+Yc2mQNVfU jqn9aP/DLb2A== X-IronPort-AV: E=McAfee;i="6200,9189,10016"; a="206234398" X-IronPort-AV: E=Sophos;i="5.83,278,1616482800"; d="scan'208";a="206234398" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Jun 2021 08:25:28 -0700 IronPort-SDR: ktGkg5x8iBlNv2xC57k+0RqfN29v4g0hwiA2lMBScgkDR8ftD3AdUEiN3tW2LOI7F4nbZt7nTw PdjSpL1Lb5xQ== X-IronPort-AV: E=Sophos;i="5.83,278,1616482800"; d="scan'208";a="479129877" Received: from mrapopor-mobl.ger.corp.intel.com (HELO mwauld-desk1.intel.com) ([10.213.236.122]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Jun 2021 08:25:24 -0700 From: Matthew Auld To: intel-gfx@lists.freedesktop.org Subject: [PATCH v5 1/7] drm/i915/ttm: add ttm_buddy_man Date: Wed, 16 Jun 2021 16:24:55 +0100 Message-Id: <20210616152501.394518-1-matthew.auld@intel.com> X-Mailer: git-send-email 2.26.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , dri-devel@lists.freedesktop.org Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Add back our standalone i915_buddy allocator and integrate it into a ttm_resource_manager. This will plug into our ttm backend for managing device local-memory in the next couple of patches. v2(Thomas): - Return -ENOSPC from the buddy; ttm expects this in order to trigger eviction - Drop the unnecessary inline - bo->page_alignment is in page units Signed-off-by: Matthew Auld Cc: Thomas Hellström Acked-by: Thomas Hellström --- drivers/gpu/drm/i915/Makefile | 2 + drivers/gpu/drm/i915/i915_buddy.c | 412 +++++++++ drivers/gpu/drm/i915/i915_buddy.h | 133 +++ drivers/gpu/drm/i915/i915_ttm_buddy_manager.c | 248 ++++++ drivers/gpu/drm/i915/i915_ttm_buddy_manager.h | 56 ++ drivers/gpu/drm/i915/selftests/i915_buddy.c | 789 ++++++++++++++++++ 6 files changed, 1640 insertions(+) create mode 100644 drivers/gpu/drm/i915/i915_buddy.c create mode 100644 drivers/gpu/drm/i915/i915_buddy.h create mode 100644 drivers/gpu/drm/i915/i915_ttm_buddy_manager.c create mode 100644 drivers/gpu/drm/i915/i915_ttm_buddy_manager.h create mode 100644 drivers/gpu/drm/i915/selftests/i915_buddy.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index f57dfc74d6ce..6c84e96ab26a 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -162,6 +162,7 @@ gem-y += \ i915-y += \ $(gem-y) \ i915_active.o \ + i915_buddy.o \ i915_cmd_parser.o \ i915_gem_evict.o \ i915_gem_gtt.o \ @@ -171,6 +172,7 @@ i915-y += \ i915_request.o \ i915_scheduler.o \ i915_trace_points.o \ + i915_ttm_buddy_manager.o \ i915_vma.o \ intel_wopcm.o diff --git a/drivers/gpu/drm/i915/i915_buddy.c b/drivers/gpu/drm/i915/i915_buddy.c new file mode 100644 index 000000000000..29dd7d0310c1 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_buddy.c @@ -0,0 +1,412 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2021 Intel Corporation + */ + +#include + +#include "i915_buddy.h" + +#include "i915_gem.h" +#include "i915_utils.h" + +static struct i915_buddy_block *i915_block_alloc(struct i915_buddy_mm *mm, + struct i915_buddy_block *parent, + unsigned int order, + u64 offset) +{ + struct i915_buddy_block *block; + + GEM_BUG_ON(order > I915_BUDDY_MAX_ORDER); + + block = kmem_cache_zalloc(mm->slab_blocks, GFP_KERNEL); + if (!block) + return NULL; + + block->header = offset; + block->header |= order; + block->parent = parent; + + GEM_BUG_ON(block->header & I915_BUDDY_HEADER_UNUSED); + return block; +} + +static void i915_block_free(struct i915_buddy_mm *mm, + struct i915_buddy_block *block) +{ + kmem_cache_free(mm->slab_blocks, block); +} + +static void mark_allocated(struct i915_buddy_block *block) +{ + block->header &= ~I915_BUDDY_HEADER_STATE; + block->header |= I915_BUDDY_ALLOCATED; + + list_del(&block->link); +} + +static void mark_free(struct i915_buddy_mm *mm, + struct i915_buddy_block *block) +{ + block->header &= ~I915_BUDDY_HEADER_STATE; + block->header |= I915_BUDDY_FREE; + + list_add(&block->link, + &mm->free_list[i915_buddy_block_order(block)]); +} + +static void mark_split(struct i915_buddy_block *block) +{ + block->header &= ~I915_BUDDY_HEADER_STATE; + block->header |= I915_BUDDY_SPLIT; + + list_del(&block->link); +} + +int i915_buddy_init(struct i915_buddy_mm *mm, u64 size, u64 chunk_size) +{ + unsigned int i; + u64 offset; + + if (size < chunk_size) + return -EINVAL; + + if (chunk_size < PAGE_SIZE) + return -EINVAL; + + if (!is_power_of_2(chunk_size)) + return -EINVAL; + + size = round_down(size, chunk_size); + + mm->size = size; + mm->chunk_size = chunk_size; + mm->max_order = ilog2(size) - ilog2(chunk_size); + + GEM_BUG_ON(mm->max_order > I915_BUDDY_MAX_ORDER); + + mm->slab_blocks = KMEM_CACHE(i915_buddy_block, SLAB_HWCACHE_ALIGN); + if (!mm->slab_blocks) + return -ENOMEM; + + mm->free_list = kmalloc_array(mm->max_order + 1, + sizeof(struct list_head), + GFP_KERNEL); + if (!mm->free_list) + goto out_destroy_slab; + + for (i = 0; i <= mm->max_order; ++i) + INIT_LIST_HEAD(&mm->free_list[i]); + + mm->n_roots = hweight64(size); + + mm->roots = kmalloc_array(mm->n_roots, + sizeof(struct i915_buddy_block *), + GFP_KERNEL); + if (!mm->roots) + goto out_free_list; + + offset = 0; + i = 0; + + /* + * Split into power-of-two blocks, in case we are given a size that is + * not itself a power-of-two. + */ + do { + struct i915_buddy_block *root; + unsigned int order; + u64 root_size; + + root_size = rounddown_pow_of_two(size); + order = ilog2(root_size) - ilog2(chunk_size); + + root = i915_block_alloc(mm, NULL, order, offset); + if (!root) + goto out_free_roots; + + mark_free(mm, root); + + GEM_BUG_ON(i > mm->max_order); + GEM_BUG_ON(i915_buddy_block_size(mm, root) < chunk_size); + + mm->roots[i] = root; + + offset += root_size; + size -= root_size; + i++; + } while (size); + + return 0; + +out_free_roots: + while (i--) + i915_block_free(mm, mm->roots[i]); + kfree(mm->roots); +out_free_list: + kfree(mm->free_list); +out_destroy_slab: + kmem_cache_destroy(mm->slab_blocks); + return -ENOMEM; +} + +void i915_buddy_fini(struct i915_buddy_mm *mm) +{ + int i; + + for (i = 0; i < mm->n_roots; ++i) { + GEM_WARN_ON(!i915_buddy_block_is_free(mm->roots[i])); + i915_block_free(mm, mm->roots[i]); + } + + kfree(mm->roots); + kfree(mm->free_list); + kmem_cache_destroy(mm->slab_blocks); +} + +static int split_block(struct i915_buddy_mm *mm, + struct i915_buddy_block *block) +{ + unsigned int block_order = i915_buddy_block_order(block) - 1; + u64 offset = i915_buddy_block_offset(block); + + GEM_BUG_ON(!i915_buddy_block_is_free(block)); + GEM_BUG_ON(!i915_buddy_block_order(block)); + + block->left = i915_block_alloc(mm, block, block_order, offset); + if (!block->left) + return -ENOMEM; + + block->right = i915_block_alloc(mm, block, block_order, + offset + (mm->chunk_size << block_order)); + if (!block->right) { + i915_block_free(mm, block->left); + return -ENOMEM; + } + + mark_free(mm, block->left); + mark_free(mm, block->right); + + mark_split(block); + + return 0; +} + +static struct i915_buddy_block * +get_buddy(struct i915_buddy_block *block) +{ + struct i915_buddy_block *parent; + + parent = block->parent; + if (!parent) + return NULL; + + if (parent->left == block) + return parent->right; + + return parent->left; +} + +static void __i915_buddy_free(struct i915_buddy_mm *mm, + struct i915_buddy_block *block) +{ + struct i915_buddy_block *parent; + + while ((parent = block->parent)) { + struct i915_buddy_block *buddy; + + buddy = get_buddy(block); + + if (!i915_buddy_block_is_free(buddy)) + break; + + list_del(&buddy->link); + + i915_block_free(mm, block); + i915_block_free(mm, buddy); + + block = parent; + } + + mark_free(mm, block); +} + +void i915_buddy_free(struct i915_buddy_mm *mm, + struct i915_buddy_block *block) +{ + GEM_BUG_ON(!i915_buddy_block_is_allocated(block)); + __i915_buddy_free(mm, block); +} + +void i915_buddy_free_list(struct i915_buddy_mm *mm, struct list_head *objects) +{ + struct i915_buddy_block *block, *on; + + list_for_each_entry_safe(block, on, objects, link) { + i915_buddy_free(mm, block); + cond_resched(); + } + INIT_LIST_HEAD(objects); +} + +/* + * Allocate power-of-two block. The order value here translates to: + * + * 0 = 2^0 * mm->chunk_size + * 1 = 2^1 * mm->chunk_size + * 2 = 2^2 * mm->chunk_size + * ... + */ +struct i915_buddy_block * +i915_buddy_alloc(struct i915_buddy_mm *mm, unsigned int order) +{ + struct i915_buddy_block *block = NULL; + unsigned int i; + int err; + + for (i = order; i <= mm->max_order; ++i) { + block = list_first_entry_or_null(&mm->free_list[i], + struct i915_buddy_block, + link); + if (block) + break; + } + + if (!block) + return ERR_PTR(-ENOSPC); + + GEM_BUG_ON(!i915_buddy_block_is_free(block)); + + while (i != order) { + err = split_block(mm, block); + if (unlikely(err)) + goto out_free; + + /* Go low */ + block = block->left; + i--; + } + + mark_allocated(block); + kmemleak_update_trace(block); + return block; + +out_free: + if (i != order) + __i915_buddy_free(mm, block); + return ERR_PTR(err); +} + +static inline bool overlaps(u64 s1, u64 e1, u64 s2, u64 e2) +{ + return s1 <= e2 && e1 >= s2; +} + +static inline bool contains(u64 s1, u64 e1, u64 s2, u64 e2) +{ + return s1 <= s2 && e1 >= e2; +} + +/* + * Allocate range. Note that it's safe to chain together multiple alloc_ranges + * with the same blocks list. + * + * Intended for pre-allocating portions of the address space, for example to + * reserve a block for the initial framebuffer or similar, hence the expectation + * here is that i915_buddy_alloc() is still the main vehicle for + * allocations, so if that's not the case then the drm_mm range allocator is + * probably a much better fit, and so you should probably go use that instead. + */ +int i915_buddy_alloc_range(struct i915_buddy_mm *mm, + struct list_head *blocks, + u64 start, u64 size) +{ + struct i915_buddy_block *block; + struct i915_buddy_block *buddy; + LIST_HEAD(allocated); + LIST_HEAD(dfs); + u64 end; + int err; + int i; + + if (size < mm->chunk_size) + return -EINVAL; + + if (!IS_ALIGNED(size | start, mm->chunk_size)) + return -EINVAL; + + if (range_overflows(start, size, mm->size)) + return -EINVAL; + + for (i = 0; i < mm->n_roots; ++i) + list_add_tail(&mm->roots[i]->tmp_link, &dfs); + + end = start + size - 1; + + do { + u64 block_start; + u64 block_end; + + block = list_first_entry_or_null(&dfs, + struct i915_buddy_block, + tmp_link); + if (!block) + break; + + list_del(&block->tmp_link); + + block_start = i915_buddy_block_offset(block); + block_end = block_start + i915_buddy_block_size(mm, block) - 1; + + if (!overlaps(start, end, block_start, block_end)) + continue; + + if (i915_buddy_block_is_allocated(block)) { + err = -ENOSPC; + goto err_free; + } + + if (contains(start, end, block_start, block_end)) { + if (!i915_buddy_block_is_free(block)) { + err = -ENOSPC; + goto err_free; + } + + mark_allocated(block); + list_add_tail(&block->link, &allocated); + continue; + } + + if (!i915_buddy_block_is_split(block)) { + err = split_block(mm, block); + if (unlikely(err)) + goto err_undo; + } + + list_add(&block->right->tmp_link, &dfs); + list_add(&block->left->tmp_link, &dfs); + } while (1); + + list_splice_tail(&allocated, blocks); + return 0; + +err_undo: + /* + * We really don't want to leave around a bunch of split blocks, since + * bigger is better, so make sure we merge everything back before we + * free the allocated blocks. + */ + buddy = get_buddy(block); + if (buddy && + (i915_buddy_block_is_free(block) && + i915_buddy_block_is_free(buddy))) + __i915_buddy_free(mm, block); + +err_free: + i915_buddy_free_list(mm, &allocated); + return err; +} + +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftests/i915_buddy.c" +#endif diff --git a/drivers/gpu/drm/i915/i915_buddy.h b/drivers/gpu/drm/i915/i915_buddy.h new file mode 100644 index 000000000000..37f8c42071d1 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_buddy.h @@ -0,0 +1,133 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021 Intel Corporation + */ + +#ifndef __I915_BUDDY_H__ +#define __I915_BUDDY_H__ + +#include +#include +#include + +struct i915_buddy_block { +#define I915_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12) +#define I915_BUDDY_HEADER_STATE GENMASK_ULL(11, 10) +#define I915_BUDDY_ALLOCATED (1 << 10) +#define I915_BUDDY_FREE (2 << 10) +#define I915_BUDDY_SPLIT (3 << 10) +/* Free to be used, if needed in the future */ +#define I915_BUDDY_HEADER_UNUSED GENMASK_ULL(9, 6) +#define I915_BUDDY_HEADER_ORDER GENMASK_ULL(5, 0) + u64 header; + + struct i915_buddy_block *left; + struct i915_buddy_block *right; + struct i915_buddy_block *parent; + + void *private; /* owned by creator */ + + /* + * While the block is allocated by the user through i915_buddy_alloc*, + * the user has ownership of the link, for example to maintain within + * a list, if so desired. As soon as the block is freed with + * i915_buddy_free* ownership is given back to the mm. + */ + struct list_head link; + struct list_head tmp_link; +}; + +/* Order-zero must be at least PAGE_SIZE */ +#define I915_BUDDY_MAX_ORDER (63 - PAGE_SHIFT) + +/* + * Binary Buddy System. + * + * Locking should be handled by the user, a simple mutex around + * i915_buddy_alloc* and i915_buddy_free* should suffice. + */ +struct i915_buddy_mm { + struct kmem_cache *slab_blocks; + /* Maintain a free list for each order. */ + struct list_head *free_list; + + /* + * Maintain explicit binary tree(s) to track the allocation of the + * address space. This gives us a simple way of finding a buddy block + * and performing the potentially recursive merge step when freeing a + * block. Nodes are either allocated or free, in which case they will + * also exist on the respective free list. + */ + struct i915_buddy_block **roots; + + /* + * Anything from here is public, and remains static for the lifetime of + * the mm. Everything above is considered do-not-touch. + */ + unsigned int n_roots; + unsigned int max_order; + + /* Must be at least PAGE_SIZE */ + u64 chunk_size; + u64 size; +}; + +static inline u64 +i915_buddy_block_offset(struct i915_buddy_block *block) +{ + return block->header & I915_BUDDY_HEADER_OFFSET; +} + +static inline unsigned int +i915_buddy_block_order(struct i915_buddy_block *block) +{ + return block->header & I915_BUDDY_HEADER_ORDER; +} + +static inline unsigned int +i915_buddy_block_state(struct i915_buddy_block *block) +{ + return block->header & I915_BUDDY_HEADER_STATE; +} + +static inline bool +i915_buddy_block_is_allocated(struct i915_buddy_block *block) +{ + return i915_buddy_block_state(block) == I915_BUDDY_ALLOCATED; +} + +static inline bool +i915_buddy_block_is_free(struct i915_buddy_block *block) +{ + return i915_buddy_block_state(block) == I915_BUDDY_FREE; +} + +static inline bool +i915_buddy_block_is_split(struct i915_buddy_block *block) +{ + return i915_buddy_block_state(block) == I915_BUDDY_SPLIT; +} + +static inline u64 +i915_buddy_block_size(struct i915_buddy_mm *mm, + struct i915_buddy_block *block) +{ + return mm->chunk_size << i915_buddy_block_order(block); +} + +int i915_buddy_init(struct i915_buddy_mm *mm, u64 size, u64 chunk_size); + +void i915_buddy_fini(struct i915_buddy_mm *mm); + +struct i915_buddy_block * +i915_buddy_alloc(struct i915_buddy_mm *mm, unsigned int order); + +int i915_buddy_alloc_range(struct i915_buddy_mm *mm, + struct list_head *blocks, + u64 start, u64 size); + +void i915_buddy_free(struct i915_buddy_mm *mm, struct i915_buddy_block *block); + +void i915_buddy_free_list(struct i915_buddy_mm *mm, struct list_head *objects); + +#endif diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c new file mode 100644 index 000000000000..fc7ad5c035b8 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2021 Intel Corporation + */ + +#include + +#include +#include + +#include "i915_ttm_buddy_manager.h" + +#include "i915_buddy.h" +#include "i915_gem.h" + +struct i915_ttm_buddy_manager { + struct ttm_resource_manager manager; + struct i915_buddy_mm mm; + struct list_head reserved; + struct mutex lock; +}; + +static struct i915_ttm_buddy_manager * +to_buddy_manager(struct ttm_resource_manager *man) +{ + return container_of(man, struct i915_ttm_buddy_manager, manager); +} + +static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man, + struct ttm_buffer_object *bo, + const struct ttm_place *place, + struct ttm_resource **res) +{ + struct i915_ttm_buddy_manager *bman = to_buddy_manager(man); + struct i915_ttm_buddy_resource *bman_res; + struct i915_buddy_mm *mm = &bman->mm; + unsigned long n_pages; + unsigned int min_order; + u64 min_page_size; + u64 size; + int err; + + GEM_BUG_ON(place->fpfn || place->lpfn); + + bman_res = kzalloc(sizeof(*bman_res), GFP_KERNEL); + if (!bman_res) + return -ENOMEM; + + ttm_resource_init(bo, place, &bman_res->base); + INIT_LIST_HEAD(&bman_res->blocks); + bman_res->mm = mm; + + GEM_BUG_ON(!bman_res->base.num_pages); + size = bman_res->base.num_pages << PAGE_SHIFT; + + min_page_size = bo->page_alignment << PAGE_SHIFT; + GEM_BUG_ON(min_page_size < mm->chunk_size); + min_order = ilog2(min_page_size) - ilog2(mm->chunk_size); + if (place->flags & TTM_PL_FLAG_CONTIGUOUS) { + size = roundup_pow_of_two(size); + min_order = ilog2(size) - ilog2(mm->chunk_size); + } + + if (size > mm->size) { + err = -E2BIG; + goto err_free_res; + } + + n_pages = size >> ilog2(mm->chunk_size); + + do { + struct i915_buddy_block *block; + unsigned int order; + + order = fls(n_pages) - 1; + GEM_BUG_ON(order > mm->max_order); + GEM_BUG_ON(order < min_order); + + do { + mutex_lock(&bman->lock); + block = i915_buddy_alloc(mm, order); + mutex_unlock(&bman->lock); + if (!IS_ERR(block)) + break; + + if (order-- == min_order) { + err = -ENOSPC; + goto err_free_blocks; + } + } while (1); + + n_pages -= BIT(order); + + list_add_tail(&block->link, &bman_res->blocks); + + if (!n_pages) + break; + } while (1); + + *res = &bman_res->base; + return 0; + +err_free_blocks: + mutex_lock(&bman->lock); + i915_buddy_free_list(mm, &bman_res->blocks); + mutex_unlock(&bman->lock); +err_free_res: + kfree(bman_res); + return err; +} + +static void i915_ttm_buddy_man_free(struct ttm_resource_manager *man, + struct ttm_resource *res) +{ + struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res); + struct i915_ttm_buddy_manager *bman = to_buddy_manager(man); + + mutex_lock(&bman->lock); + i915_buddy_free_list(&bman->mm, &bman_res->blocks); + mutex_unlock(&bman->lock); + + kfree(bman_res); +} + +static const struct ttm_resource_manager_func i915_ttm_buddy_manager_func = { + .alloc = i915_ttm_buddy_man_alloc, + .free = i915_ttm_buddy_man_free, +}; + + +/** + * i915_ttm_buddy_man_init - Setup buddy allocator based ttm manager + * @bdev: The ttm device + * @type: Memory type we want to manage + * @use_tt: Set use_tt for the manager + * @size: The size in bytes to manage + * @chunk_size: The minimum page size in bytes for our allocations i.e + * order-zero + * + * Note that the starting address is assumed to be zero here, since this + * simplifies keeping the property where allocated blocks having natural + * power-of-two alignment. So long as the real starting address is some large + * power-of-two, or naturally start from zero, then this should be fine. Also + * the &i915_ttm_buddy_man_reserve interface can be used to preserve alignment + * if say there is some unusable range from the start of the region. We can + * revisit this in the future and make the interface accept an actual starting + * offset and let it take care of the rest. + * + * Note that if the @size is not aligned to the @chunk_size then we perform the + * required rounding to get the usable size. The final size in pages can be + * taken from &ttm_resource_manager.size. + * + * Return: 0 on success, negative error code on failure. + */ +int i915_ttm_buddy_man_init(struct ttm_device *bdev, + unsigned int type, bool use_tt, + u64 size, u64 chunk_size) +{ + struct ttm_resource_manager *man; + struct i915_ttm_buddy_manager *bman; + int err; + + bman = kzalloc(sizeof(*bman), GFP_KERNEL); + if (!bman) + return -ENOMEM; + + err = i915_buddy_init(&bman->mm, size, chunk_size); + if (err) + goto err_free_bman; + + mutex_init(&bman->lock); + INIT_LIST_HEAD(&bman->reserved); + + man = &bman->manager; + man->use_tt = use_tt; + man->func = &i915_ttm_buddy_manager_func; + ttm_resource_manager_init(man, bman->mm.size >> PAGE_SHIFT); + + ttm_resource_manager_set_used(man, true); + ttm_set_driver_manager(bdev, type, man); + + return 0; + +err_free_bman: + kfree(bman); + return err; +} + +/** + * i915_ttm_buddy_man_fini - Destroy the buddy allocator ttm manager + * @bdev: The ttm device + * @type: Memory type we want to manage + * + * Note that if we reserved anything with &i915_ttm_buddy_man_reserve, this will + * also be freed for us here. + * + * Return: 0 on success, negative error code on failure. + */ +int i915_ttm_buddy_man_fini(struct ttm_device *bdev, unsigned int type) +{ + struct ttm_resource_manager *man = ttm_manager_type(bdev, type); + struct i915_ttm_buddy_manager *bman = to_buddy_manager(man); + struct i915_buddy_mm *mm = &bman->mm; + int ret; + + ttm_resource_manager_set_used(man, false); + + ret = ttm_resource_manager_evict_all(bdev, man); + if (ret) + return ret; + + ttm_set_driver_manager(bdev, type, NULL); + + mutex_lock(&bman->lock); + i915_buddy_free_list(mm, &bman->reserved); + i915_buddy_fini(mm); + mutex_unlock(&bman->lock); + + ttm_resource_manager_cleanup(man); + kfree(bman); + + return 0; +} + +/** + * i915_ttm_buddy_man_reserve - Reserve address range + * @man: The buddy allocator ttm manager + * @start: The offset in bytes, where the region start is assumed to be zero + * @size: The size in bytes + * + * Note that the starting address for the region is always assumed to be zero. + * + * Return: 0 on success, negative error code on failure. + */ +int i915_ttm_buddy_man_reserve(struct ttm_resource_manager *man, + u64 start, u64 size) +{ + struct i915_ttm_buddy_manager *bman = to_buddy_manager(man); + struct i915_buddy_mm *mm = &bman->mm; + int ret; + + mutex_lock(&bman->lock); + ret = i915_buddy_alloc_range(mm, &bman->reserved, start, size); + mutex_unlock(&bman->lock); + + return ret; +} + diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h new file mode 100644 index 000000000000..26026213e20a --- /dev/null +++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021 Intel Corporation + */ + +#ifndef __I915_TTM_BUDDY_MANAGER_H__ +#define __I915_TTM_BUDDY_MANAGER_H__ + +#include +#include + +#include + +struct ttm_device; +struct ttm_resource_manager; +struct i915_buddy_mm; + +/** + * struct i915_ttm_buddy_resource + * + * @base: struct ttm_resource base class we extend + * @blocks: the list of struct i915_buddy_block for this resource/allocation + * @mm: the struct i915_buddy_mm for this resource + * + * Extends the struct ttm_resource to manage an address space allocation with + * one or more struct i915_buddy_block. + */ +struct i915_ttm_buddy_resource { + struct ttm_resource base; + struct list_head blocks; + struct i915_buddy_mm *mm; +}; + +/** + * to_ttm_buddy_resource + * + * @res: the resource to upcast + * + * Upcast the struct ttm_resource object into a struct i915_ttm_buddy_resource. + */ +static inline struct i915_ttm_buddy_resource * +to_ttm_buddy_resource(struct ttm_resource *res) +{ + return container_of(res, struct i915_ttm_buddy_resource, base); +} + +int i915_ttm_buddy_man_init(struct ttm_device *bdev, + unsigned type, bool use_tt, + u64 size, u64 chunk_size); +int i915_ttm_buddy_man_fini(struct ttm_device *bdev, + unsigned int type); + +int i915_ttm_buddy_man_reserve(struct ttm_resource_manager *man, + u64 start, u64 size); + +#endif diff --git a/drivers/gpu/drm/i915/selftests/i915_buddy.c b/drivers/gpu/drm/i915/selftests/i915_buddy.c new file mode 100644 index 000000000000..f0f5c4df8dbc --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/i915_buddy.c @@ -0,0 +1,789 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2019 Intel Corporation + */ + +#include + +#include "../i915_selftest.h" +#include "i915_random.h" + +static void __igt_dump_block(struct i915_buddy_mm *mm, + struct i915_buddy_block *block, + bool buddy) +{ + pr_err("block info: header=%llx, state=%u, order=%d, offset=%llx size=%llx root=%s buddy=%s\n", + block->header, + i915_buddy_block_state(block), + i915_buddy_block_order(block), + i915_buddy_block_offset(block), + i915_buddy_block_size(mm, block), + yesno(!block->parent), + yesno(buddy)); +} + +static void igt_dump_block(struct i915_buddy_mm *mm, + struct i915_buddy_block *block) +{ + struct i915_buddy_block *buddy; + + __igt_dump_block(mm, block, false); + + buddy = get_buddy(block); + if (buddy) + __igt_dump_block(mm, buddy, true); +} + +static int igt_check_block(struct i915_buddy_mm *mm, + struct i915_buddy_block *block) +{ + struct i915_buddy_block *buddy; + unsigned int block_state; + u64 block_size; + u64 offset; + int err = 0; + + block_state = i915_buddy_block_state(block); + + if (block_state != I915_BUDDY_ALLOCATED && + block_state != I915_BUDDY_FREE && + block_state != I915_BUDDY_SPLIT) { + pr_err("block state mismatch\n"); + err = -EINVAL; + } + + block_size = i915_buddy_block_size(mm, block); + offset = i915_buddy_block_offset(block); + + if (block_size < mm->chunk_size) { + pr_err("block size smaller than min size\n"); + err = -EINVAL; + } + + if (!is_power_of_2(block_size)) { + pr_err("block size not power of two\n"); + err = -EINVAL; + } + + if (!IS_ALIGNED(block_size, mm->chunk_size)) { + pr_err("block size not aligned to min size\n"); + err = -EINVAL; + } + + if (!IS_ALIGNED(offset, mm->chunk_size)) { + pr_err("block offset not aligned to min size\n"); + err = -EINVAL; + } + + if (!IS_ALIGNED(offset, block_size)) { + pr_err("block offset not aligned to block size\n"); + err = -EINVAL; + } + + buddy = get_buddy(block); + + if (!buddy && block->parent) { + pr_err("buddy has gone fishing\n"); + err = -EINVAL; + } + + if (buddy) { + if (i915_buddy_block_offset(buddy) != (offset ^ block_size)) { + pr_err("buddy has wrong offset\n"); + err = -EINVAL; + } + + if (i915_buddy_block_size(mm, buddy) != block_size) { + pr_err("buddy size mismatch\n"); + err = -EINVAL; + } + + if (i915_buddy_block_state(buddy) == block_state && + block_state == I915_BUDDY_FREE) { + pr_err("block and its buddy are free\n"); + err = -EINVAL; + } + } + + return err; +} + +static int igt_check_blocks(struct i915_buddy_mm *mm, + struct list_head *blocks, + u64 expected_size, + bool is_contiguous) +{ + struct i915_buddy_block *block; + struct i915_buddy_block *prev; + u64 total; + int err = 0; + + block = NULL; + prev = NULL; + total = 0; + + list_for_each_entry(block, blocks, link) { + err = igt_check_block(mm, block); + + if (!i915_buddy_block_is_allocated(block)) { + pr_err("block not allocated\n"), + err = -EINVAL; + } + + if (is_contiguous && prev) { + u64 prev_block_size; + u64 prev_offset; + u64 offset; + + prev_offset = i915_buddy_block_offset(prev); + prev_block_size = i915_buddy_block_size(mm, prev); + offset = i915_buddy_block_offset(block); + + if (offset != (prev_offset + prev_block_size)) { + pr_err("block offset mismatch\n"); + err = -EINVAL; + } + } + + if (err) + break; + + total += i915_buddy_block_size(mm, block); + prev = block; + } + + if (!err) { + if (total != expected_size) { + pr_err("size mismatch, expected=%llx, found=%llx\n", + expected_size, total); + err = -EINVAL; + } + return err; + } + + if (prev) { + pr_err("prev block, dump:\n"); + igt_dump_block(mm, prev); + } + + if (block) { + pr_err("bad block, dump:\n"); + igt_dump_block(mm, block); + } + + return err; +} + +static int igt_check_mm(struct i915_buddy_mm *mm) +{ + struct i915_buddy_block *root; + struct i915_buddy_block *prev; + unsigned int i; + u64 total; + int err = 0; + + if (!mm->n_roots) { + pr_err("n_roots is zero\n"); + return -EINVAL; + } + + if (mm->n_roots != hweight64(mm->size)) { + pr_err("n_roots mismatch, n_roots=%u, expected=%lu\n", + mm->n_roots, hweight64(mm->size)); + return -EINVAL; + } + + root = NULL; + prev = NULL; + total = 0; + + for (i = 0; i < mm->n_roots; ++i) { + struct i915_buddy_block *block; + unsigned int order; + + root = mm->roots[i]; + if (!root) { + pr_err("root(%u) is NULL\n", i); + err = -EINVAL; + break; + } + + err = igt_check_block(mm, root); + + if (!i915_buddy_block_is_free(root)) { + pr_err("root not free\n"); + err = -EINVAL; + } + + order = i915_buddy_block_order(root); + + if (!i) { + if (order != mm->max_order) { + pr_err("max order root missing\n"); + err = -EINVAL; + } + } + + if (prev) { + u64 prev_block_size; + u64 prev_offset; + u64 offset; + + prev_offset = i915_buddy_block_offset(prev); + prev_block_size = i915_buddy_block_size(mm, prev); + offset = i915_buddy_block_offset(root); + + if (offset != (prev_offset + prev_block_size)) { + pr_err("root offset mismatch\n"); + err = -EINVAL; + } + } + + block = list_first_entry_or_null(&mm->free_list[order], + struct i915_buddy_block, + link); + if (block != root) { + pr_err("root mismatch at order=%u\n", order); + err = -EINVAL; + } + + if (err) + break; + + prev = root; + total += i915_buddy_block_size(mm, root); + } + + if (!err) { + if (total != mm->size) { + pr_err("expected mm size=%llx, found=%llx\n", mm->size, + total); + err = -EINVAL; + } + return err; + } + + if (prev) { + pr_err("prev root(%u), dump:\n", i - 1); + igt_dump_block(mm, prev); + } + + if (root) { + pr_err("bad root(%u), dump:\n", i); + igt_dump_block(mm, root); + } + + return err; +} + +static void igt_mm_config(u64 *size, u64 *chunk_size) +{ + I915_RND_STATE(prng); + u32 s, ms; + + /* Nothing fancy, just try to get an interesting bit pattern */ + + prandom_seed_state(&prng, i915_selftest.random_seed); + + /* Let size be a random number of pages up to 8 GB (2M pages) */ + s = 1 + i915_prandom_u32_max_state((BIT(33 - 12)) - 1, &prng); + /* Let the chunk size be a random power of 2 less than size */ + ms = BIT(i915_prandom_u32_max_state(ilog2(s), &prng)); + /* Round size down to the chunk size */ + s &= -ms; + + /* Convert from pages to bytes */ + *chunk_size = (u64)ms << 12; + *size = (u64)s << 12; +} + +static int igt_buddy_alloc_smoke(void *arg) +{ + struct i915_buddy_mm mm; + IGT_TIMEOUT(end_time); + I915_RND_STATE(prng); + u64 chunk_size; + u64 mm_size; + int *order; + int err, i; + + igt_mm_config(&mm_size, &chunk_size); + + pr_info("buddy_init with size=%llx, chunk_size=%llx\n", mm_size, chunk_size); + + err = i915_buddy_init(&mm, mm_size, chunk_size); + if (err) { + pr_err("buddy_init failed(%d)\n", err); + return err; + } + + order = i915_random_order(mm.max_order + 1, &prng); + if (!order) + goto out_fini; + + for (i = 0; i <= mm.max_order; ++i) { + struct i915_buddy_block *block; + int max_order = order[i]; + bool timeout = false; + LIST_HEAD(blocks); + int order; + u64 total; + + err = igt_check_mm(&mm); + if (err) { + pr_err("pre-mm check failed, abort\n"); + break; + } + + pr_info("filling from max_order=%u\n", max_order); + + order = max_order; + total = 0; + + do { +retry: + block = i915_buddy_alloc(&mm, order); + if (IS_ERR(block)) { + err = PTR_ERR(block); + if (err == -ENOMEM) { + pr_info("buddy_alloc hit -ENOMEM with order=%d\n", + order); + } else { + if (order--) { + err = 0; + goto retry; + } + + pr_err("buddy_alloc with order=%d failed(%d)\n", + order, err); + } + + break; + } + + list_add_tail(&block->link, &blocks); + + if (i915_buddy_block_order(block) != order) { + pr_err("buddy_alloc order mismatch\n"); + err = -EINVAL; + break; + } + + total += i915_buddy_block_size(&mm, block); + + if (__igt_timeout(end_time, NULL)) { + timeout = true; + break; + } + } while (total < mm.size); + + if (!err) + err = igt_check_blocks(&mm, &blocks, total, false); + + i915_buddy_free_list(&mm, &blocks); + + if (!err) { + err = igt_check_mm(&mm); + if (err) + pr_err("post-mm check failed\n"); + } + + if (err || timeout) + break; + + cond_resched(); + } + + if (err == -ENOMEM) + err = 0; + + kfree(order); +out_fini: + i915_buddy_fini(&mm); + + return err; +} + +static int igt_buddy_alloc_pessimistic(void *arg) +{ + const unsigned int max_order = 16; + struct i915_buddy_block *block, *bn; + struct i915_buddy_mm mm; + unsigned int order; + LIST_HEAD(blocks); + int err; + + /* + * Create a pot-sized mm, then allocate one of each possible + * order within. This should leave the mm with exactly one + * page left. + */ + + err = i915_buddy_init(&mm, PAGE_SIZE << max_order, PAGE_SIZE); + if (err) { + pr_err("buddy_init failed(%d)\n", err); + return err; + } + GEM_BUG_ON(mm.max_order != max_order); + + for (order = 0; order < max_order; order++) { + block = i915_buddy_alloc(&mm, order); + if (IS_ERR(block)) { + pr_info("buddy_alloc hit -ENOMEM with order=%d\n", + order); + err = PTR_ERR(block); + goto err; + } + + list_add_tail(&block->link, &blocks); + } + + /* And now the last remaining block available */ + block = i915_buddy_alloc(&mm, 0); + if (IS_ERR(block)) { + pr_info("buddy_alloc hit -ENOMEM on final alloc\n"); + err = PTR_ERR(block); + goto err; + } + list_add_tail(&block->link, &blocks); + + /* Should be completely full! */ + for (order = max_order; order--; ) { + block = i915_buddy_alloc(&mm, order); + if (!IS_ERR(block)) { + pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!", + order); + list_add_tail(&block->link, &blocks); + err = -EINVAL; + goto err; + } + } + + block = list_last_entry(&blocks, typeof(*block), link); + list_del(&block->link); + i915_buddy_free(&mm, block); + + /* As we free in increasing size, we make available larger blocks */ + order = 1; + list_for_each_entry_safe(block, bn, &blocks, link) { + list_del(&block->link); + i915_buddy_free(&mm, block); + + block = i915_buddy_alloc(&mm, order); + if (IS_ERR(block)) { + pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n", + order); + err = PTR_ERR(block); + goto err; + } + i915_buddy_free(&mm, block); + order++; + } + + /* To confirm, now the whole mm should be available */ + block = i915_buddy_alloc(&mm, max_order); + if (IS_ERR(block)) { + pr_info("buddy_alloc (realloc) hit -ENOMEM with order=%d\n", + max_order); + err = PTR_ERR(block); + goto err; + } + i915_buddy_free(&mm, block); + +err: + i915_buddy_free_list(&mm, &blocks); + i915_buddy_fini(&mm); + return err; +} + +static int igt_buddy_alloc_optimistic(void *arg) +{ + const int max_order = 16; + struct i915_buddy_block *block; + struct i915_buddy_mm mm; + LIST_HEAD(blocks); + int order; + int err; + + /* + * Create a mm with one block of each order available, and + * try to allocate them all. + */ + + err = i915_buddy_init(&mm, + PAGE_SIZE * ((1 << (max_order + 1)) - 1), + PAGE_SIZE); + if (err) { + pr_err("buddy_init failed(%d)\n", err); + return err; + } + GEM_BUG_ON(mm.max_order != max_order); + + for (order = 0; order <= max_order; order++) { + block = i915_buddy_alloc(&mm, order); + if (IS_ERR(block)) { + pr_info("buddy_alloc hit -ENOMEM with order=%d\n", + order); + err = PTR_ERR(block); + goto err; + } + + list_add_tail(&block->link, &blocks); + } + + /* Should be completely full! */ + block = i915_buddy_alloc(&mm, 0); + if (!IS_ERR(block)) { + pr_info("buddy_alloc unexpectedly succeeded, it should be full!"); + list_add_tail(&block->link, &blocks); + err = -EINVAL; + goto err; + } + +err: + i915_buddy_free_list(&mm, &blocks); + i915_buddy_fini(&mm); + return err; +} + +static int igt_buddy_alloc_pathological(void *arg) +{ + const int max_order = 16; + struct i915_buddy_block *block; + struct i915_buddy_mm mm; + LIST_HEAD(blocks); + LIST_HEAD(holes); + int order, top; + int err; + + /* + * Create a pot-sized mm, then allocate one of each possible + * order within. This should leave the mm with exactly one + * page left. Free the largest block, then whittle down again. + * Eventually we will have a fully 50% fragmented mm. + */ + + err = i915_buddy_init(&mm, PAGE_SIZE << max_order, PAGE_SIZE); + if (err) { + pr_err("buddy_init failed(%d)\n", err); + return err; + } + GEM_BUG_ON(mm.max_order != max_order); + + for (top = max_order; top; top--) { + /* Make room by freeing the largest allocated block */ + block = list_first_entry_or_null(&blocks, typeof(*block), link); + if (block) { + list_del(&block->link); + i915_buddy_free(&mm, block); + } + + for (order = top; order--; ) { + block = i915_buddy_alloc(&mm, order); + if (IS_ERR(block)) { + pr_info("buddy_alloc hit -ENOMEM with order=%d, top=%d\n", + order, top); + err = PTR_ERR(block); + goto err; + } + list_add_tail(&block->link, &blocks); + } + + /* There should be one final page for this sub-allocation */ + block = i915_buddy_alloc(&mm, 0); + if (IS_ERR(block)) { + pr_info("buddy_alloc hit -ENOMEM for hole\n"); + err = PTR_ERR(block); + goto err; + } + list_add_tail(&block->link, &holes); + + block = i915_buddy_alloc(&mm, top); + if (!IS_ERR(block)) { + pr_info("buddy_alloc unexpectedly succeeded at top-order %d/%d, it should be full!", + top, max_order); + list_add_tail(&block->link, &blocks); + err = -EINVAL; + goto err; + } + } + + i915_buddy_free_list(&mm, &holes); + + /* Nothing larger than blocks of chunk_size now available */ + for (order = 1; order <= max_order; order++) { + block = i915_buddy_alloc(&mm, order); + if (!IS_ERR(block)) { + pr_info("buddy_alloc unexpectedly succeeded at order %d, it should be full!", + order); + list_add_tail(&block->link, &blocks); + err = -EINVAL; + goto err; + } + } + +err: + list_splice_tail(&holes, &blocks); + i915_buddy_free_list(&mm, &blocks); + i915_buddy_fini(&mm); + return err; +} + +static int igt_buddy_alloc_range(void *arg) +{ + struct i915_buddy_mm mm; + unsigned long page_num; + LIST_HEAD(blocks); + u64 chunk_size; + u64 offset; + u64 size; + u64 rem; + int err; + + igt_mm_config(&size, &chunk_size); + + pr_info("buddy_init with size=%llx, chunk_size=%llx\n", size, chunk_size); + + err = i915_buddy_init(&mm, size, chunk_size); + if (err) { + pr_err("buddy_init failed(%d)\n", err); + return err; + } + + err = igt_check_mm(&mm); + if (err) { + pr_err("pre-mm check failed, abort, abort, abort!\n"); + goto err_fini; + } + + rem = mm.size; + offset = 0; + + for_each_prime_number_from(page_num, 1, ULONG_MAX - 1) { + struct i915_buddy_block *block; + LIST_HEAD(tmp); + + size = min(page_num * mm.chunk_size, rem); + + err = i915_buddy_alloc_range(&mm, &tmp, offset, size); + if (err) { + if (err == -ENOMEM) { + pr_info("alloc_range hit -ENOMEM with size=%llx\n", + size); + } else { + pr_err("alloc_range with offset=%llx, size=%llx failed(%d)\n", + offset, size, err); + } + + break; + } + + block = list_first_entry_or_null(&tmp, + struct i915_buddy_block, + link); + if (!block) { + pr_err("alloc_range has no blocks\n"); + err = -EINVAL; + break; + } + + if (i915_buddy_block_offset(block) != offset) { + pr_err("alloc_range start offset mismatch, found=%llx, expected=%llx\n", + i915_buddy_block_offset(block), offset); + err = -EINVAL; + } + + if (!err) + err = igt_check_blocks(&mm, &tmp, size, true); + + list_splice_tail(&tmp, &blocks); + + if (err) + break; + + offset += size; + + rem -= size; + if (!rem) + break; + + cond_resched(); + } + + if (err == -ENOMEM) + err = 0; + + i915_buddy_free_list(&mm, &blocks); + + if (!err) { + err = igt_check_mm(&mm); + if (err) + pr_err("post-mm check failed\n"); + } + +err_fini: + i915_buddy_fini(&mm); + + return err; +} + +static int igt_buddy_alloc_limit(void *arg) +{ + struct i915_buddy_block *block; + struct i915_buddy_mm mm; + const u64 size = U64_MAX; + int err; + + err = i915_buddy_init(&mm, size, PAGE_SIZE); + if (err) + return err; + + if (mm.max_order != I915_BUDDY_MAX_ORDER) { + pr_err("mm.max_order(%d) != %d\n", + mm.max_order, I915_BUDDY_MAX_ORDER); + err = -EINVAL; + goto out_fini; + } + + block = i915_buddy_alloc(&mm, mm.max_order); + if (IS_ERR(block)) { + err = PTR_ERR(block); + goto out_fini; + } + + if (i915_buddy_block_order(block) != mm.max_order) { + pr_err("block order(%d) != %d\n", + i915_buddy_block_order(block), mm.max_order); + err = -EINVAL; + goto out_free; + } + + if (i915_buddy_block_size(&mm, block) != + BIT_ULL(mm.max_order) * PAGE_SIZE) { + pr_err("block size(%llu) != %llu\n", + i915_buddy_block_size(&mm, block), + BIT_ULL(mm.max_order) * PAGE_SIZE); + err = -EINVAL; + goto out_free; + } + +out_free: + i915_buddy_free(&mm, block); +out_fini: + i915_buddy_fini(&mm); + return err; +} + +int i915_buddy_mock_selftests(void) +{ + static const struct i915_subtest tests[] = { + SUBTEST(igt_buddy_alloc_pessimistic), + SUBTEST(igt_buddy_alloc_optimistic), + SUBTEST(igt_buddy_alloc_pathological), + SUBTEST(igt_buddy_alloc_smoke), + SUBTEST(igt_buddy_alloc_range), + SUBTEST(igt_buddy_alloc_limit), + }; + + return i915_subtests(tests, NULL); +} -- 2.26.3 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=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT 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 1EF0CC48BE5 for ; Wed, 16 Jun 2021 15:25:36 +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 B3A8C6128B for ; Wed, 16 Jun 2021 15:25:35 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org B3A8C6128B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=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 038478993B; Wed, 16 Jun 2021 15:25:31 +0000 (UTC) Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7AD068993B; Wed, 16 Jun 2021 15:25:29 +0000 (UTC) IronPort-SDR: 9/AtcZ5tg6BxVYcqw7pIsAlNX7QU6iOwJeF866TKRu7rYlTMv+9ohugbzmsNTyXu+Yc2mQNVfU jqn9aP/DLb2A== X-IronPort-AV: E=McAfee;i="6200,9189,10016"; a="206234398" X-IronPort-AV: E=Sophos;i="5.83,278,1616482800"; d="scan'208";a="206234398" Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Jun 2021 08:25:28 -0700 IronPort-SDR: ktGkg5x8iBlNv2xC57k+0RqfN29v4g0hwiA2lMBScgkDR8ftD3AdUEiN3tW2LOI7F4nbZt7nTw PdjSpL1Lb5xQ== X-IronPort-AV: E=Sophos;i="5.83,278,1616482800"; d="scan'208";a="479129877" Received: from mrapopor-mobl.ger.corp.intel.com (HELO mwauld-desk1.intel.com) ([10.213.236.122]) by fmsmga003-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 16 Jun 2021 08:25:24 -0700 From: Matthew Auld To: intel-gfx@lists.freedesktop.org Date: Wed, 16 Jun 2021 16:24:55 +0100 Message-Id: <20210616152501.394518-1-matthew.auld@intel.com> X-Mailer: git-send-email 2.26.3 MIME-Version: 1.0 Subject: [Intel-gfx] [PATCH v5 1/7] drm/i915/ttm: add ttm_buddy_man 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: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= , dri-devel@lists.freedesktop.org Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" QWRkIGJhY2sgb3VyIHN0YW5kYWxvbmUgaTkxNV9idWRkeSBhbGxvY2F0b3IgYW5kIGludGVncmF0 ZSBpdCBpbnRvIGEKdHRtX3Jlc291cmNlX21hbmFnZXIuIFRoaXMgd2lsbCBwbHVnIGludG8gb3Vy IHR0bSBiYWNrZW5kIGZvciBtYW5hZ2luZwpkZXZpY2UgbG9jYWwtbWVtb3J5IGluIHRoZSBuZXh0 IGNvdXBsZSBvZiBwYXRjaGVzLgoKdjIoVGhvbWFzKToKICAgIC0gUmV0dXJuIC1FTk9TUEMgZnJv bSB0aGUgYnVkZHk7IHR0bSBleHBlY3RzIHRoaXMgaW4gb3JkZXIgdG8KICAgICAgdHJpZ2dlciBl dmljdGlvbgogICAgLSBEcm9wIHRoZSB1bm5lY2Vzc2FyeSBpbmxpbmUKICAgIC0gYm8tPnBhZ2Vf YWxpZ25tZW50IGlzIGluIHBhZ2UgdW5pdHMKClNpZ25lZC1vZmYtYnk6IE1hdHRoZXcgQXVsZCA8 bWF0dGhldy5hdWxkQGludGVsLmNvbT4KQ2M6IFRob21hcyBIZWxsc3Ryw7ZtIDx0aG9tYXMuaGVs bHN0cm9tQGxpbnV4LmludGVsLmNvbT4KQWNrZWQtYnk6IFRob21hcyBIZWxsc3Ryw7ZtIDx0aG9t YXMuaGVsbHN0cm9tQGxpbnV4LmludGVsLmNvbT4KLS0tCiBkcml2ZXJzL2dwdS9kcm0vaTkxNS9N YWtlZmlsZSAgICAgICAgICAgICAgICAgfCAgIDIgKwogZHJpdmVycy9ncHUvZHJtL2k5MTUvaTkx NV9idWRkeS5jICAgICAgICAgICAgIHwgNDEyICsrKysrKysrKwogZHJpdmVycy9ncHUvZHJtL2k5 MTUvaTkxNV9idWRkeS5oICAgICAgICAgICAgIHwgMTMzICsrKwogZHJpdmVycy9ncHUvZHJtL2k5 MTUvaTkxNV90dG1fYnVkZHlfbWFuYWdlci5jIHwgMjQ4ICsrKysrKwogZHJpdmVycy9ncHUvZHJt L2k5MTUvaTkxNV90dG1fYnVkZHlfbWFuYWdlci5oIHwgIDU2ICsrCiBkcml2ZXJzL2dwdS9kcm0v aTkxNS9zZWxmdGVzdHMvaTkxNV9idWRkeS5jICAgfCA3ODkgKysrKysrKysrKysrKysrKysrCiA2 IGZpbGVzIGNoYW5nZWQsIDE2NDAgaW5zZXJ0aW9ucygrKQogY3JlYXRlIG1vZGUgMTAwNjQ0IGRy aXZlcnMvZ3B1L2RybS9pOTE1L2k5MTVfYnVkZHkuYwogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZl cnMvZ3B1L2RybS9pOTE1L2k5MTVfYnVkZHkuaAogY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMv Z3B1L2RybS9pOTE1L2k5MTVfdHRtX2J1ZGR5X21hbmFnZXIuYwogY3JlYXRlIG1vZGUgMTAwNjQ0 IGRyaXZlcnMvZ3B1L2RybS9pOTE1L2k5MTVfdHRtX2J1ZGR5X21hbmFnZXIuaAogY3JlYXRlIG1v ZGUgMTAwNjQ0IGRyaXZlcnMvZ3B1L2RybS9pOTE1L3NlbGZ0ZXN0cy9pOTE1X2J1ZGR5LmMKCmRp ZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vaTkxNS9NYWtlZmlsZSBiL2RyaXZlcnMvZ3B1L2Ry bS9pOTE1L01ha2VmaWxlCmluZGV4IGY1N2RmYzc0ZDZjZS4uNmM4NGU5NmFiMjZhIDEwMDY0NAot LS0gYS9kcml2ZXJzL2dwdS9kcm0vaTkxNS9NYWtlZmlsZQorKysgYi9kcml2ZXJzL2dwdS9kcm0v aTkxNS9NYWtlZmlsZQpAQCAtMTYyLDYgKzE2Miw3IEBAIGdlbS15ICs9IFwKIGk5MTUteSArPSBc CiAJICAkKGdlbS15KSBcCiAJICBpOTE1X2FjdGl2ZS5vIFwKKwkgIGk5MTVfYnVkZHkubyBcCiAJ ICBpOTE1X2NtZF9wYXJzZXIubyBcCiAJICBpOTE1X2dlbV9ldmljdC5vIFwKIAkgIGk5MTVfZ2Vt X2d0dC5vIFwKQEAgLTE3MSw2ICsxNzIsNyBAQCBpOTE1LXkgKz0gXAogCSAgaTkxNV9yZXF1ZXN0 Lm8gXAogCSAgaTkxNV9zY2hlZHVsZXIubyBcCiAJICBpOTE1X3RyYWNlX3BvaW50cy5vIFwKKwkg IGk5MTVfdHRtX2J1ZGR5X21hbmFnZXIubyBcCiAJICBpOTE1X3ZtYS5vIFwKIAkgIGludGVsX3dv cGNtLm8KIApkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL2k5MTUvaTkxNV9idWRkeS5jIGIv ZHJpdmVycy9ncHUvZHJtL2k5MTUvaTkxNV9idWRkeS5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0Cmlu ZGV4IDAwMDAwMDAwMDAwMC4uMjlkZDdkMDMxMGMxCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVy cy9ncHUvZHJtL2k5MTUvaTkxNV9idWRkeS5jCkBAIC0wLDAgKzEsNDEyIEBACisvLyBTUERYLUxp Y2Vuc2UtSWRlbnRpZmllcjogTUlUCisvKgorICogQ29weXJpZ2h0IMKpIDIwMjEgSW50ZWwgQ29y cG9yYXRpb24KKyAqLworCisjaW5jbHVkZSA8bGludXgva21lbWxlYWsuaD4KKworI2luY2x1ZGUg Imk5MTVfYnVkZHkuaCIKKworI2luY2x1ZGUgImk5MTVfZ2VtLmgiCisjaW5jbHVkZSAiaTkxNV91 dGlscy5oIgorCitzdGF0aWMgc3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgKmk5MTVfYmxvY2tfYWxs b2Moc3RydWN0IGk5MTVfYnVkZHlfbW0gKm1tLAorCQkJCQkJIHN0cnVjdCBpOTE1X2J1ZGR5X2Js b2NrICpwYXJlbnQsCisJCQkJCQkgdW5zaWduZWQgaW50IG9yZGVyLAorCQkJCQkJIHU2NCBvZmZz ZXQpCit7CisJc3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgKmJsb2NrOworCisJR0VNX0JVR19PTihv cmRlciA+IEk5MTVfQlVERFlfTUFYX09SREVSKTsKKworCWJsb2NrID0ga21lbV9jYWNoZV96YWxs b2MobW0tPnNsYWJfYmxvY2tzLCBHRlBfS0VSTkVMKTsKKwlpZiAoIWJsb2NrKQorCQlyZXR1cm4g TlVMTDsKKworCWJsb2NrLT5oZWFkZXIgPSBvZmZzZXQ7CisJYmxvY2stPmhlYWRlciB8PSBvcmRl cjsKKwlibG9jay0+cGFyZW50ID0gcGFyZW50OworCisJR0VNX0JVR19PTihibG9jay0+aGVhZGVy ICYgSTkxNV9CVUREWV9IRUFERVJfVU5VU0VEKTsKKwlyZXR1cm4gYmxvY2s7Cit9CisKK3N0YXRp YyB2b2lkIGk5MTVfYmxvY2tfZnJlZShzdHJ1Y3QgaTkxNV9idWRkeV9tbSAqbW0sCisJCQkgICAg c3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgKmJsb2NrKQoreworCWttZW1fY2FjaGVfZnJlZShtbS0+ c2xhYl9ibG9ja3MsIGJsb2NrKTsKK30KKworc3RhdGljIHZvaWQgbWFya19hbGxvY2F0ZWQoc3Ry dWN0IGk5MTVfYnVkZHlfYmxvY2sgKmJsb2NrKQoreworCWJsb2NrLT5oZWFkZXIgJj0gfkk5MTVf QlVERFlfSEVBREVSX1NUQVRFOworCWJsb2NrLT5oZWFkZXIgfD0gSTkxNV9CVUREWV9BTExPQ0FU RUQ7CisKKwlsaXN0X2RlbCgmYmxvY2stPmxpbmspOworfQorCitzdGF0aWMgdm9pZCBtYXJrX2Zy ZWUoc3RydWN0IGk5MTVfYnVkZHlfbW0gKm1tLAorCQkgICAgICBzdHJ1Y3QgaTkxNV9idWRkeV9i bG9jayAqYmxvY2spCit7CisJYmxvY2stPmhlYWRlciAmPSB+STkxNV9CVUREWV9IRUFERVJfU1RB VEU7CisJYmxvY2stPmhlYWRlciB8PSBJOTE1X0JVRERZX0ZSRUU7CisKKwlsaXN0X2FkZCgmYmxv Y2stPmxpbmssCisJCSAmbW0tPmZyZWVfbGlzdFtpOTE1X2J1ZGR5X2Jsb2NrX29yZGVyKGJsb2Nr KV0pOworfQorCitzdGF0aWMgdm9pZCBtYXJrX3NwbGl0KHN0cnVjdCBpOTE1X2J1ZGR5X2Jsb2Nr ICpibG9jaykKK3sKKwlibG9jay0+aGVhZGVyICY9IH5JOTE1X0JVRERZX0hFQURFUl9TVEFURTsK KwlibG9jay0+aGVhZGVyIHw9IEk5MTVfQlVERFlfU1BMSVQ7CisKKwlsaXN0X2RlbCgmYmxvY2st PmxpbmspOworfQorCitpbnQgaTkxNV9idWRkeV9pbml0KHN0cnVjdCBpOTE1X2J1ZGR5X21tICpt bSwgdTY0IHNpemUsIHU2NCBjaHVua19zaXplKQoreworCXVuc2lnbmVkIGludCBpOworCXU2NCBv ZmZzZXQ7CisKKwlpZiAoc2l6ZSA8IGNodW5rX3NpemUpCisJCXJldHVybiAtRUlOVkFMOworCisJ aWYgKGNodW5rX3NpemUgPCBQQUdFX1NJWkUpCisJCXJldHVybiAtRUlOVkFMOworCisJaWYgKCFp c19wb3dlcl9vZl8yKGNodW5rX3NpemUpKQorCQlyZXR1cm4gLUVJTlZBTDsKKworCXNpemUgPSBy b3VuZF9kb3duKHNpemUsIGNodW5rX3NpemUpOworCisJbW0tPnNpemUgPSBzaXplOworCW1tLT5j aHVua19zaXplID0gY2h1bmtfc2l6ZTsKKwltbS0+bWF4X29yZGVyID0gaWxvZzIoc2l6ZSkgLSBp bG9nMihjaHVua19zaXplKTsKKworCUdFTV9CVUdfT04obW0tPm1heF9vcmRlciA+IEk5MTVfQlVE RFlfTUFYX09SREVSKTsKKworCW1tLT5zbGFiX2Jsb2NrcyA9IEtNRU1fQ0FDSEUoaTkxNV9idWRk eV9ibG9jaywgU0xBQl9IV0NBQ0hFX0FMSUdOKTsKKwlpZiAoIW1tLT5zbGFiX2Jsb2NrcykKKwkJ cmV0dXJuIC1FTk9NRU07CisKKwltbS0+ZnJlZV9saXN0ID0ga21hbGxvY19hcnJheShtbS0+bWF4 X29yZGVyICsgMSwKKwkJCQkgICAgICBzaXplb2Yoc3RydWN0IGxpc3RfaGVhZCksCisJCQkJICAg ICAgR0ZQX0tFUk5FTCk7CisJaWYgKCFtbS0+ZnJlZV9saXN0KQorCQlnb3RvIG91dF9kZXN0cm95 X3NsYWI7CisKKwlmb3IgKGkgPSAwOyBpIDw9IG1tLT5tYXhfb3JkZXI7ICsraSkKKwkJSU5JVF9M SVNUX0hFQUQoJm1tLT5mcmVlX2xpc3RbaV0pOworCisJbW0tPm5fcm9vdHMgPSBod2VpZ2h0NjQo c2l6ZSk7CisKKwltbS0+cm9vdHMgPSBrbWFsbG9jX2FycmF5KG1tLT5uX3Jvb3RzLAorCQkJCSAg c2l6ZW9mKHN0cnVjdCBpOTE1X2J1ZGR5X2Jsb2NrICopLAorCQkJCSAgR0ZQX0tFUk5FTCk7CisJ aWYgKCFtbS0+cm9vdHMpCisJCWdvdG8gb3V0X2ZyZWVfbGlzdDsKKworCW9mZnNldCA9IDA7CisJ aSA9IDA7CisKKwkvKgorCSAqIFNwbGl0IGludG8gcG93ZXItb2YtdHdvIGJsb2NrcywgaW4gY2Fz ZSB3ZSBhcmUgZ2l2ZW4gYSBzaXplIHRoYXQgaXMKKwkgKiBub3QgaXRzZWxmIGEgcG93ZXItb2Yt dHdvLgorCSAqLworCWRvIHsKKwkJc3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgKnJvb3Q7CisJCXVu c2lnbmVkIGludCBvcmRlcjsKKwkJdTY0IHJvb3Rfc2l6ZTsKKworCQlyb290X3NpemUgPSByb3Vu ZGRvd25fcG93X29mX3R3byhzaXplKTsKKwkJb3JkZXIgPSBpbG9nMihyb290X3NpemUpIC0gaWxv ZzIoY2h1bmtfc2l6ZSk7CisKKwkJcm9vdCA9IGk5MTVfYmxvY2tfYWxsb2MobW0sIE5VTEwsIG9y ZGVyLCBvZmZzZXQpOworCQlpZiAoIXJvb3QpCisJCQlnb3RvIG91dF9mcmVlX3Jvb3RzOworCisJ CW1hcmtfZnJlZShtbSwgcm9vdCk7CisKKwkJR0VNX0JVR19PTihpID4gbW0tPm1heF9vcmRlcik7 CisJCUdFTV9CVUdfT04oaTkxNV9idWRkeV9ibG9ja19zaXplKG1tLCByb290KSA8IGNodW5rX3Np emUpOworCisJCW1tLT5yb290c1tpXSA9IHJvb3Q7CisKKwkJb2Zmc2V0ICs9IHJvb3Rfc2l6ZTsK KwkJc2l6ZSAtPSByb290X3NpemU7CisJCWkrKzsKKwl9IHdoaWxlIChzaXplKTsKKworCXJldHVy biAwOworCitvdXRfZnJlZV9yb290czoKKwl3aGlsZSAoaS0tKQorCQlpOTE1X2Jsb2NrX2ZyZWUo bW0sIG1tLT5yb290c1tpXSk7CisJa2ZyZWUobW0tPnJvb3RzKTsKK291dF9mcmVlX2xpc3Q6CisJ a2ZyZWUobW0tPmZyZWVfbGlzdCk7CitvdXRfZGVzdHJveV9zbGFiOgorCWttZW1fY2FjaGVfZGVz dHJveShtbS0+c2xhYl9ibG9ja3MpOworCXJldHVybiAtRU5PTUVNOworfQorCit2b2lkIGk5MTVf YnVkZHlfZmluaShzdHJ1Y3QgaTkxNV9idWRkeV9tbSAqbW0pCit7CisJaW50IGk7CisKKwlmb3Ig KGkgPSAwOyBpIDwgbW0tPm5fcm9vdHM7ICsraSkgeworCQlHRU1fV0FSTl9PTighaTkxNV9idWRk eV9ibG9ja19pc19mcmVlKG1tLT5yb290c1tpXSkpOworCQlpOTE1X2Jsb2NrX2ZyZWUobW0sIG1t LT5yb290c1tpXSk7CisJfQorCisJa2ZyZWUobW0tPnJvb3RzKTsKKwlrZnJlZShtbS0+ZnJlZV9s aXN0KTsKKwlrbWVtX2NhY2hlX2Rlc3Ryb3kobW0tPnNsYWJfYmxvY2tzKTsKK30KKworc3RhdGlj IGludCBzcGxpdF9ibG9jayhzdHJ1Y3QgaTkxNV9idWRkeV9tbSAqbW0sCisJCSAgICAgICBzdHJ1 Y3QgaTkxNV9idWRkeV9ibG9jayAqYmxvY2spCit7CisJdW5zaWduZWQgaW50IGJsb2NrX29yZGVy ID0gaTkxNV9idWRkeV9ibG9ja19vcmRlcihibG9jaykgLSAxOworCXU2NCBvZmZzZXQgPSBpOTE1 X2J1ZGR5X2Jsb2NrX29mZnNldChibG9jayk7CisKKwlHRU1fQlVHX09OKCFpOTE1X2J1ZGR5X2Js b2NrX2lzX2ZyZWUoYmxvY2spKTsKKwlHRU1fQlVHX09OKCFpOTE1X2J1ZGR5X2Jsb2NrX29yZGVy KGJsb2NrKSk7CisKKwlibG9jay0+bGVmdCA9IGk5MTVfYmxvY2tfYWxsb2MobW0sIGJsb2NrLCBi bG9ja19vcmRlciwgb2Zmc2V0KTsKKwlpZiAoIWJsb2NrLT5sZWZ0KQorCQlyZXR1cm4gLUVOT01F TTsKKworCWJsb2NrLT5yaWdodCA9IGk5MTVfYmxvY2tfYWxsb2MobW0sIGJsb2NrLCBibG9ja19v cmRlciwKKwkJCQkJb2Zmc2V0ICsgKG1tLT5jaHVua19zaXplIDw8IGJsb2NrX29yZGVyKSk7CisJ aWYgKCFibG9jay0+cmlnaHQpIHsKKwkJaTkxNV9ibG9ja19mcmVlKG1tLCBibG9jay0+bGVmdCk7 CisJCXJldHVybiAtRU5PTUVNOworCX0KKworCW1hcmtfZnJlZShtbSwgYmxvY2stPmxlZnQpOwor CW1hcmtfZnJlZShtbSwgYmxvY2stPnJpZ2h0KTsKKworCW1hcmtfc3BsaXQoYmxvY2spOworCisJ cmV0dXJuIDA7Cit9CisKK3N0YXRpYyBzdHJ1Y3QgaTkxNV9idWRkeV9ibG9jayAqCitnZXRfYnVk ZHkoc3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgKmJsb2NrKQoreworCXN0cnVjdCBpOTE1X2J1ZGR5 X2Jsb2NrICpwYXJlbnQ7CisKKwlwYXJlbnQgPSBibG9jay0+cGFyZW50OworCWlmICghcGFyZW50 KQorCQlyZXR1cm4gTlVMTDsKKworCWlmIChwYXJlbnQtPmxlZnQgPT0gYmxvY2spCisJCXJldHVy biBwYXJlbnQtPnJpZ2h0OworCisJcmV0dXJuIHBhcmVudC0+bGVmdDsKK30KKworc3RhdGljIHZv aWQgX19pOTE1X2J1ZGR5X2ZyZWUoc3RydWN0IGk5MTVfYnVkZHlfbW0gKm1tLAorCQkJICAgICAg c3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgKmJsb2NrKQoreworCXN0cnVjdCBpOTE1X2J1ZGR5X2Js b2NrICpwYXJlbnQ7CisKKwl3aGlsZSAoKHBhcmVudCA9IGJsb2NrLT5wYXJlbnQpKSB7CisJCXN0 cnVjdCBpOTE1X2J1ZGR5X2Jsb2NrICpidWRkeTsKKworCQlidWRkeSA9IGdldF9idWRkeShibG9j ayk7CisKKwkJaWYgKCFpOTE1X2J1ZGR5X2Jsb2NrX2lzX2ZyZWUoYnVkZHkpKQorCQkJYnJlYWs7 CisKKwkJbGlzdF9kZWwoJmJ1ZGR5LT5saW5rKTsKKworCQlpOTE1X2Jsb2NrX2ZyZWUobW0sIGJs b2NrKTsKKwkJaTkxNV9ibG9ja19mcmVlKG1tLCBidWRkeSk7CisKKwkJYmxvY2sgPSBwYXJlbnQ7 CisJfQorCisJbWFya19mcmVlKG1tLCBibG9jayk7Cit9CisKK3ZvaWQgaTkxNV9idWRkeV9mcmVl KHN0cnVjdCBpOTE1X2J1ZGR5X21tICptbSwKKwkJICAgICBzdHJ1Y3QgaTkxNV9idWRkeV9ibG9j ayAqYmxvY2spCit7CisJR0VNX0JVR19PTighaTkxNV9idWRkeV9ibG9ja19pc19hbGxvY2F0ZWQo YmxvY2spKTsKKwlfX2k5MTVfYnVkZHlfZnJlZShtbSwgYmxvY2spOworfQorCit2b2lkIGk5MTVf YnVkZHlfZnJlZV9saXN0KHN0cnVjdCBpOTE1X2J1ZGR5X21tICptbSwgc3RydWN0IGxpc3RfaGVh ZCAqb2JqZWN0cykKK3sKKwlzdHJ1Y3QgaTkxNV9idWRkeV9ibG9jayAqYmxvY2ssICpvbjsKKwor CWxpc3RfZm9yX2VhY2hfZW50cnlfc2FmZShibG9jaywgb24sIG9iamVjdHMsIGxpbmspIHsKKwkJ aTkxNV9idWRkeV9mcmVlKG1tLCBibG9jayk7CisJCWNvbmRfcmVzY2hlZCgpOworCX0KKwlJTklU X0xJU1RfSEVBRChvYmplY3RzKTsKK30KKworLyoKKyAqIEFsbG9jYXRlIHBvd2VyLW9mLXR3byBi bG9jay4gVGhlIG9yZGVyIHZhbHVlIGhlcmUgdHJhbnNsYXRlcyB0bzoKKyAqCisgKiAgIDAgPSAy XjAgKiBtbS0+Y2h1bmtfc2l6ZQorICogICAxID0gMl4xICogbW0tPmNodW5rX3NpemUKKyAqICAg MiA9IDJeMiAqIG1tLT5jaHVua19zaXplCisgKiAgIC4uLgorICovCitzdHJ1Y3QgaTkxNV9idWRk eV9ibG9jayAqCitpOTE1X2J1ZGR5X2FsbG9jKHN0cnVjdCBpOTE1X2J1ZGR5X21tICptbSwgdW5z aWduZWQgaW50IG9yZGVyKQoreworCXN0cnVjdCBpOTE1X2J1ZGR5X2Jsb2NrICpibG9jayA9IE5V TEw7CisJdW5zaWduZWQgaW50IGk7CisJaW50IGVycjsKKworCWZvciAoaSA9IG9yZGVyOyBpIDw9 IG1tLT5tYXhfb3JkZXI7ICsraSkgeworCQlibG9jayA9IGxpc3RfZmlyc3RfZW50cnlfb3JfbnVs bCgmbW0tPmZyZWVfbGlzdFtpXSwKKwkJCQkJCSBzdHJ1Y3QgaTkxNV9idWRkeV9ibG9jaywKKwkJ CQkJCSBsaW5rKTsKKwkJaWYgKGJsb2NrKQorCQkJYnJlYWs7CisJfQorCisJaWYgKCFibG9jaykK KwkJcmV0dXJuIEVSUl9QVFIoLUVOT1NQQyk7CisKKwlHRU1fQlVHX09OKCFpOTE1X2J1ZGR5X2Js b2NrX2lzX2ZyZWUoYmxvY2spKTsKKworCXdoaWxlIChpICE9IG9yZGVyKSB7CisJCWVyciA9IHNw bGl0X2Jsb2NrKG1tLCBibG9jayk7CisJCWlmICh1bmxpa2VseShlcnIpKQorCQkJZ290byBvdXRf ZnJlZTsKKworCQkvKiBHbyBsb3cgKi8KKwkJYmxvY2sgPSBibG9jay0+bGVmdDsKKwkJaS0tOwor CX0KKworCW1hcmtfYWxsb2NhdGVkKGJsb2NrKTsKKwlrbWVtbGVha191cGRhdGVfdHJhY2UoYmxv Y2spOworCXJldHVybiBibG9jazsKKworb3V0X2ZyZWU6CisJaWYgKGkgIT0gb3JkZXIpCisJCV9f aTkxNV9idWRkeV9mcmVlKG1tLCBibG9jayk7CisJcmV0dXJuIEVSUl9QVFIoZXJyKTsKK30KKwor c3RhdGljIGlubGluZSBib29sIG92ZXJsYXBzKHU2NCBzMSwgdTY0IGUxLCB1NjQgczIsIHU2NCBl MikKK3sKKwlyZXR1cm4gczEgPD0gZTIgJiYgZTEgPj0gczI7Cit9CisKK3N0YXRpYyBpbmxpbmUg Ym9vbCBjb250YWlucyh1NjQgczEsIHU2NCBlMSwgdTY0IHMyLCB1NjQgZTIpCit7CisJcmV0dXJu IHMxIDw9IHMyICYmIGUxID49IGUyOworfQorCisvKgorICogQWxsb2NhdGUgcmFuZ2UuIE5vdGUg dGhhdCBpdCdzIHNhZmUgdG8gY2hhaW4gdG9nZXRoZXIgbXVsdGlwbGUgYWxsb2NfcmFuZ2VzCisg KiB3aXRoIHRoZSBzYW1lIGJsb2NrcyBsaXN0LgorICoKKyAqIEludGVuZGVkIGZvciBwcmUtYWxs b2NhdGluZyBwb3J0aW9ucyBvZiB0aGUgYWRkcmVzcyBzcGFjZSwgZm9yIGV4YW1wbGUgdG8KKyAq IHJlc2VydmUgYSBibG9jayBmb3IgdGhlIGluaXRpYWwgZnJhbWVidWZmZXIgb3Igc2ltaWxhciwg aGVuY2UgdGhlIGV4cGVjdGF0aW9uCisgKiBoZXJlIGlzIHRoYXQgaTkxNV9idWRkeV9hbGxvYygp IGlzIHN0aWxsIHRoZSBtYWluIHZlaGljbGUgZm9yCisgKiBhbGxvY2F0aW9ucywgc28gaWYgdGhh dCdzIG5vdCB0aGUgY2FzZSB0aGVuIHRoZSBkcm1fbW0gcmFuZ2UgYWxsb2NhdG9yIGlzCisgKiBw cm9iYWJseSBhIG11Y2ggYmV0dGVyIGZpdCwgYW5kIHNvIHlvdSBzaG91bGQgcHJvYmFibHkgZ28g dXNlIHRoYXQgaW5zdGVhZC4KKyAqLworaW50IGk5MTVfYnVkZHlfYWxsb2NfcmFuZ2Uoc3RydWN0 IGk5MTVfYnVkZHlfbW0gKm1tLAorCQkJICAgc3RydWN0IGxpc3RfaGVhZCAqYmxvY2tzLAorCQkJ ICAgdTY0IHN0YXJ0LCB1NjQgc2l6ZSkKK3sKKwlzdHJ1Y3QgaTkxNV9idWRkeV9ibG9jayAqYmxv Y2s7CisJc3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgKmJ1ZGR5OworCUxJU1RfSEVBRChhbGxvY2F0 ZWQpOworCUxJU1RfSEVBRChkZnMpOworCXU2NCBlbmQ7CisJaW50IGVycjsKKwlpbnQgaTsKKwor CWlmIChzaXplIDwgbW0tPmNodW5rX3NpemUpCisJCXJldHVybiAtRUlOVkFMOworCisJaWYgKCFJ U19BTElHTkVEKHNpemUgfCBzdGFydCwgbW0tPmNodW5rX3NpemUpKQorCQlyZXR1cm4gLUVJTlZB TDsKKworCWlmIChyYW5nZV9vdmVyZmxvd3Moc3RhcnQsIHNpemUsIG1tLT5zaXplKSkKKwkJcmV0 dXJuIC1FSU5WQUw7CisKKwlmb3IgKGkgPSAwOyBpIDwgbW0tPm5fcm9vdHM7ICsraSkKKwkJbGlz dF9hZGRfdGFpbCgmbW0tPnJvb3RzW2ldLT50bXBfbGluaywgJmRmcyk7CisKKwllbmQgPSBzdGFy dCArIHNpemUgLSAxOworCisJZG8geworCQl1NjQgYmxvY2tfc3RhcnQ7CisJCXU2NCBibG9ja19l bmQ7CisKKwkJYmxvY2sgPSBsaXN0X2ZpcnN0X2VudHJ5X29yX251bGwoJmRmcywKKwkJCQkJCSBz dHJ1Y3QgaTkxNV9idWRkeV9ibG9jaywKKwkJCQkJCSB0bXBfbGluayk7CisJCWlmICghYmxvY2sp CisJCQlicmVhazsKKworCQlsaXN0X2RlbCgmYmxvY2stPnRtcF9saW5rKTsKKworCQlibG9ja19z dGFydCA9IGk5MTVfYnVkZHlfYmxvY2tfb2Zmc2V0KGJsb2NrKTsKKwkJYmxvY2tfZW5kID0gYmxv Y2tfc3RhcnQgKyBpOTE1X2J1ZGR5X2Jsb2NrX3NpemUobW0sIGJsb2NrKSAtIDE7CisKKwkJaWYg KCFvdmVybGFwcyhzdGFydCwgZW5kLCBibG9ja19zdGFydCwgYmxvY2tfZW5kKSkKKwkJCWNvbnRp bnVlOworCisJCWlmIChpOTE1X2J1ZGR5X2Jsb2NrX2lzX2FsbG9jYXRlZChibG9jaykpIHsKKwkJ CWVyciA9IC1FTk9TUEM7CisJCQlnb3RvIGVycl9mcmVlOworCQl9CisKKwkJaWYgKGNvbnRhaW5z KHN0YXJ0LCBlbmQsIGJsb2NrX3N0YXJ0LCBibG9ja19lbmQpKSB7CisJCQlpZiAoIWk5MTVfYnVk ZHlfYmxvY2tfaXNfZnJlZShibG9jaykpIHsKKwkJCQllcnIgPSAtRU5PU1BDOworCQkJCWdvdG8g ZXJyX2ZyZWU7CisJCQl9CisKKwkJCW1hcmtfYWxsb2NhdGVkKGJsb2NrKTsKKwkJCWxpc3RfYWRk X3RhaWwoJmJsb2NrLT5saW5rLCAmYWxsb2NhdGVkKTsKKwkJCWNvbnRpbnVlOworCQl9CisKKwkJ aWYgKCFpOTE1X2J1ZGR5X2Jsb2NrX2lzX3NwbGl0KGJsb2NrKSkgeworCQkJZXJyID0gc3BsaXRf YmxvY2sobW0sIGJsb2NrKTsKKwkJCWlmICh1bmxpa2VseShlcnIpKQorCQkJCWdvdG8gZXJyX3Vu ZG87CisJCX0KKworCQlsaXN0X2FkZCgmYmxvY2stPnJpZ2h0LT50bXBfbGluaywgJmRmcyk7CisJ CWxpc3RfYWRkKCZibG9jay0+bGVmdC0+dG1wX2xpbmssICZkZnMpOworCX0gd2hpbGUgKDEpOwor CisJbGlzdF9zcGxpY2VfdGFpbCgmYWxsb2NhdGVkLCBibG9ja3MpOworCXJldHVybiAwOworCitl cnJfdW5kbzoKKwkvKgorCSAqIFdlIHJlYWxseSBkb24ndCB3YW50IHRvIGxlYXZlIGFyb3VuZCBh IGJ1bmNoIG9mIHNwbGl0IGJsb2Nrcywgc2luY2UKKwkgKiBiaWdnZXIgaXMgYmV0dGVyLCBzbyBt YWtlIHN1cmUgd2UgbWVyZ2UgZXZlcnl0aGluZyBiYWNrIGJlZm9yZSB3ZQorCSAqIGZyZWUgdGhl IGFsbG9jYXRlZCBibG9ja3MuCisJICovCisJYnVkZHkgPSBnZXRfYnVkZHkoYmxvY2spOworCWlm IChidWRkeSAmJgorCSAgICAoaTkxNV9idWRkeV9ibG9ja19pc19mcmVlKGJsb2NrKSAmJgorCSAg ICAgaTkxNV9idWRkeV9ibG9ja19pc19mcmVlKGJ1ZGR5KSkpCisJCV9faTkxNV9idWRkeV9mcmVl KG1tLCBibG9jayk7CisKK2Vycl9mcmVlOgorCWk5MTVfYnVkZHlfZnJlZV9saXN0KG1tLCAmYWxs b2NhdGVkKTsKKwlyZXR1cm4gZXJyOworfQorCisjaWYgSVNfRU5BQkxFRChDT05GSUdfRFJNX0k5 MTVfU0VMRlRFU1QpCisjaW5jbHVkZSAic2VsZnRlc3RzL2k5MTVfYnVkZHkuYyIKKyNlbmRpZgpk aWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL2k5MTUvaTkxNV9idWRkeS5oIGIvZHJpdmVycy9n cHUvZHJtL2k5MTUvaTkxNV9idWRkeS5oCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAw MDAwMDAwMC4uMzdmOGM0MjA3MWQxCi0tLSAvZGV2L251bGwKKysrIGIvZHJpdmVycy9ncHUvZHJt L2k5MTUvaTkxNV9idWRkeS5oCkBAIC0wLDAgKzEsMTMzIEBACisvKiBTUERYLUxpY2Vuc2UtSWRl bnRpZmllcjogTUlUICovCisvKgorICogQ29weXJpZ2h0IMKpIDIwMjEgSW50ZWwgQ29ycG9yYXRp b24KKyAqLworCisjaWZuZGVmIF9fSTkxNV9CVUREWV9IX18KKyNkZWZpbmUgX19JOTE1X0JVRERZ X0hfXworCisjaW5jbHVkZSA8bGludXgvYml0b3BzLmg+CisjaW5jbHVkZSA8bGludXgvbGlzdC5o PgorI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4KKworc3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgewor I2RlZmluZSBJOTE1X0JVRERZX0hFQURFUl9PRkZTRVQgR0VOTUFTS19VTEwoNjMsIDEyKQorI2Rl ZmluZSBJOTE1X0JVRERZX0hFQURFUl9TVEFURSAgR0VOTUFTS19VTEwoMTEsIDEwKQorI2RlZmlu ZSAgIEk5MTVfQlVERFlfQUxMT0NBVEVECSAgICgxIDw8IDEwKQorI2RlZmluZSAgIEk5MTVfQlVE RFlfRlJFRQkgICAoMiA8PCAxMCkKKyNkZWZpbmUgICBJOTE1X0JVRERZX1NQTElUCSAgICgzIDw8 IDEwKQorLyogRnJlZSB0byBiZSB1c2VkLCBpZiBuZWVkZWQgaW4gdGhlIGZ1dHVyZSAqLworI2Rl ZmluZSBJOTE1X0JVRERZX0hFQURFUl9VTlVTRUQgR0VOTUFTS19VTEwoOSwgNikKKyNkZWZpbmUg STkxNV9CVUREWV9IRUFERVJfT1JERVIgIEdFTk1BU0tfVUxMKDUsIDApCisJdTY0IGhlYWRlcjsK KworCXN0cnVjdCBpOTE1X2J1ZGR5X2Jsb2NrICpsZWZ0OworCXN0cnVjdCBpOTE1X2J1ZGR5X2Js b2NrICpyaWdodDsKKwlzdHJ1Y3QgaTkxNV9idWRkeV9ibG9jayAqcGFyZW50OworCisJdm9pZCAq cHJpdmF0ZTsgLyogb3duZWQgYnkgY3JlYXRvciAqLworCisJLyoKKwkgKiBXaGlsZSB0aGUgYmxv Y2sgaXMgYWxsb2NhdGVkIGJ5IHRoZSB1c2VyIHRocm91Z2ggaTkxNV9idWRkeV9hbGxvYyosCisJ ICogdGhlIHVzZXIgaGFzIG93bmVyc2hpcCBvZiB0aGUgbGluaywgZm9yIGV4YW1wbGUgdG8gbWFp bnRhaW4gd2l0aGluCisJICogYSBsaXN0LCBpZiBzbyBkZXNpcmVkLiBBcyBzb29uIGFzIHRoZSBi bG9jayBpcyBmcmVlZCB3aXRoCisJICogaTkxNV9idWRkeV9mcmVlKiBvd25lcnNoaXAgaXMgZ2l2 ZW4gYmFjayB0byB0aGUgbW0uCisJICovCisJc3RydWN0IGxpc3RfaGVhZCBsaW5rOworCXN0cnVj dCBsaXN0X2hlYWQgdG1wX2xpbms7Cit9OworCisvKiBPcmRlci16ZXJvIG11c3QgYmUgYXQgbGVh c3QgUEFHRV9TSVpFICovCisjZGVmaW5lIEk5MTVfQlVERFlfTUFYX09SREVSICg2MyAtIFBBR0Vf U0hJRlQpCisKKy8qCisgKiBCaW5hcnkgQnVkZHkgU3lzdGVtLgorICoKKyAqIExvY2tpbmcgc2hv dWxkIGJlIGhhbmRsZWQgYnkgdGhlIHVzZXIsIGEgc2ltcGxlIG11dGV4IGFyb3VuZAorICogaTkx NV9idWRkeV9hbGxvYyogYW5kIGk5MTVfYnVkZHlfZnJlZSogc2hvdWxkIHN1ZmZpY2UuCisgKi8K K3N0cnVjdCBpOTE1X2J1ZGR5X21tIHsKKwlzdHJ1Y3Qga21lbV9jYWNoZSAqc2xhYl9ibG9ja3M7 CisJLyogTWFpbnRhaW4gYSBmcmVlIGxpc3QgZm9yIGVhY2ggb3JkZXIuICovCisJc3RydWN0IGxp c3RfaGVhZCAqZnJlZV9saXN0OworCisJLyoKKwkgKiBNYWludGFpbiBleHBsaWNpdCBiaW5hcnkg dHJlZShzKSB0byB0cmFjayB0aGUgYWxsb2NhdGlvbiBvZiB0aGUKKwkgKiBhZGRyZXNzIHNwYWNl LiBUaGlzIGdpdmVzIHVzIGEgc2ltcGxlIHdheSBvZiBmaW5kaW5nIGEgYnVkZHkgYmxvY2sKKwkg KiBhbmQgcGVyZm9ybWluZyB0aGUgcG90ZW50aWFsbHkgcmVjdXJzaXZlIG1lcmdlIHN0ZXAgd2hl biBmcmVlaW5nIGEKKwkgKiBibG9jay4gIE5vZGVzIGFyZSBlaXRoZXIgYWxsb2NhdGVkIG9yIGZy ZWUsIGluIHdoaWNoIGNhc2UgdGhleSB3aWxsCisJICogYWxzbyBleGlzdCBvbiB0aGUgcmVzcGVj dGl2ZSBmcmVlIGxpc3QuCisJICovCisJc3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgKipyb290czsK KworCS8qCisJICogQW55dGhpbmcgZnJvbSBoZXJlIGlzIHB1YmxpYywgYW5kIHJlbWFpbnMgc3Rh dGljIGZvciB0aGUgbGlmZXRpbWUgb2YKKwkgKiB0aGUgbW0uIEV2ZXJ5dGhpbmcgYWJvdmUgaXMg Y29uc2lkZXJlZCBkby1ub3QtdG91Y2guCisJICovCisJdW5zaWduZWQgaW50IG5fcm9vdHM7CisJ dW5zaWduZWQgaW50IG1heF9vcmRlcjsKKworCS8qIE11c3QgYmUgYXQgbGVhc3QgUEFHRV9TSVpF ICovCisJdTY0IGNodW5rX3NpemU7CisJdTY0IHNpemU7Cit9OworCitzdGF0aWMgaW5saW5lIHU2 NAoraTkxNV9idWRkeV9ibG9ja19vZmZzZXQoc3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgKmJsb2Nr KQoreworCXJldHVybiBibG9jay0+aGVhZGVyICYgSTkxNV9CVUREWV9IRUFERVJfT0ZGU0VUOwor fQorCitzdGF0aWMgaW5saW5lIHVuc2lnbmVkIGludAoraTkxNV9idWRkeV9ibG9ja19vcmRlcihz dHJ1Y3QgaTkxNV9idWRkeV9ibG9jayAqYmxvY2spCit7CisJcmV0dXJuIGJsb2NrLT5oZWFkZXIg JiBJOTE1X0JVRERZX0hFQURFUl9PUkRFUjsKK30KKworc3RhdGljIGlubGluZSB1bnNpZ25lZCBp bnQKK2k5MTVfYnVkZHlfYmxvY2tfc3RhdGUoc3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgKmJsb2Nr KQoreworCXJldHVybiBibG9jay0+aGVhZGVyICYgSTkxNV9CVUREWV9IRUFERVJfU1RBVEU7Cit9 CisKK3N0YXRpYyBpbmxpbmUgYm9vbAoraTkxNV9idWRkeV9ibG9ja19pc19hbGxvY2F0ZWQoc3Ry dWN0IGk5MTVfYnVkZHlfYmxvY2sgKmJsb2NrKQoreworCXJldHVybiBpOTE1X2J1ZGR5X2Jsb2Nr X3N0YXRlKGJsb2NrKSA9PSBJOTE1X0JVRERZX0FMTE9DQVRFRDsKK30KKworc3RhdGljIGlubGlu ZSBib29sCitpOTE1X2J1ZGR5X2Jsb2NrX2lzX2ZyZWUoc3RydWN0IGk5MTVfYnVkZHlfYmxvY2sg KmJsb2NrKQoreworCXJldHVybiBpOTE1X2J1ZGR5X2Jsb2NrX3N0YXRlKGJsb2NrKSA9PSBJOTE1 X0JVRERZX0ZSRUU7Cit9CisKK3N0YXRpYyBpbmxpbmUgYm9vbAoraTkxNV9idWRkeV9ibG9ja19p c19zcGxpdChzdHJ1Y3QgaTkxNV9idWRkeV9ibG9jayAqYmxvY2spCit7CisJcmV0dXJuIGk5MTVf YnVkZHlfYmxvY2tfc3RhdGUoYmxvY2spID09IEk5MTVfQlVERFlfU1BMSVQ7Cit9CisKK3N0YXRp YyBpbmxpbmUgdTY0CitpOTE1X2J1ZGR5X2Jsb2NrX3NpemUoc3RydWN0IGk5MTVfYnVkZHlfbW0g Km1tLAorCQkgICAgICBzdHJ1Y3QgaTkxNV9idWRkeV9ibG9jayAqYmxvY2spCit7CisJcmV0dXJu IG1tLT5jaHVua19zaXplIDw8IGk5MTVfYnVkZHlfYmxvY2tfb3JkZXIoYmxvY2spOworfQorCitp bnQgaTkxNV9idWRkeV9pbml0KHN0cnVjdCBpOTE1X2J1ZGR5X21tICptbSwgdTY0IHNpemUsIHU2 NCBjaHVua19zaXplKTsKKwordm9pZCBpOTE1X2J1ZGR5X2Zpbmkoc3RydWN0IGk5MTVfYnVkZHlf bW0gKm1tKTsKKworc3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgKgoraTkxNV9idWRkeV9hbGxvYyhz dHJ1Y3QgaTkxNV9idWRkeV9tbSAqbW0sIHVuc2lnbmVkIGludCBvcmRlcik7CisKK2ludCBpOTE1 X2J1ZGR5X2FsbG9jX3JhbmdlKHN0cnVjdCBpOTE1X2J1ZGR5X21tICptbSwKKwkJCSAgIHN0cnVj dCBsaXN0X2hlYWQgKmJsb2NrcywKKwkJCSAgIHU2NCBzdGFydCwgdTY0IHNpemUpOworCit2b2lk IGk5MTVfYnVkZHlfZnJlZShzdHJ1Y3QgaTkxNV9idWRkeV9tbSAqbW0sIHN0cnVjdCBpOTE1X2J1 ZGR5X2Jsb2NrICpibG9jayk7CisKK3ZvaWQgaTkxNV9idWRkeV9mcmVlX2xpc3Qoc3RydWN0IGk5 MTVfYnVkZHlfbW0gKm1tLCBzdHJ1Y3QgbGlzdF9oZWFkICpvYmplY3RzKTsKKworI2VuZGlmCmRp ZmYgLS1naXQgYS9kcml2ZXJzL2dwdS9kcm0vaTkxNS9pOTE1X3R0bV9idWRkeV9tYW5hZ2VyLmMg Yi9kcml2ZXJzL2dwdS9kcm0vaTkxNS9pOTE1X3R0bV9idWRkeV9tYW5hZ2VyLmMKbmV3IGZpbGUg bW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi5mYzdhZDVjMDM1YjgKLS0tIC9kZXYvbnVs bAorKysgYi9kcml2ZXJzL2dwdS9kcm0vaTkxNS9pOTE1X3R0bV9idWRkeV9tYW5hZ2VyLmMKQEAg LTAsMCArMSwyNDggQEAKKy8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVQKKy8qCisgKiBD b3B5cmlnaHQgwqkgMjAyMSBJbnRlbCBDb3Jwb3JhdGlvbgorICovCisKKyNpbmNsdWRlIDxsaW51 eC9zbGFiLmg+CisKKyNpbmNsdWRlIDxkcm0vdHRtL3R0bV9ib19kcml2ZXIuaD4KKyNpbmNsdWRl IDxkcm0vdHRtL3R0bV9wbGFjZW1lbnQuaD4KKworI2luY2x1ZGUgImk5MTVfdHRtX2J1ZGR5X21h bmFnZXIuaCIKKworI2luY2x1ZGUgImk5MTVfYnVkZHkuaCIKKyNpbmNsdWRlICJpOTE1X2dlbS5o IgorCitzdHJ1Y3QgaTkxNV90dG1fYnVkZHlfbWFuYWdlciB7CisJc3RydWN0IHR0bV9yZXNvdXJj ZV9tYW5hZ2VyIG1hbmFnZXI7CisJc3RydWN0IGk5MTVfYnVkZHlfbW0gbW07CisJc3RydWN0IGxp c3RfaGVhZCByZXNlcnZlZDsKKwlzdHJ1Y3QgbXV0ZXggbG9jazsKK307CisKK3N0YXRpYyBzdHJ1 Y3QgaTkxNV90dG1fYnVkZHlfbWFuYWdlciAqCit0b19idWRkeV9tYW5hZ2VyKHN0cnVjdCB0dG1f cmVzb3VyY2VfbWFuYWdlciAqbWFuKQoreworCXJldHVybiBjb250YWluZXJfb2YobWFuLCBzdHJ1 Y3QgaTkxNV90dG1fYnVkZHlfbWFuYWdlciwgbWFuYWdlcik7Cit9CisKK3N0YXRpYyBpbnQgaTkx NV90dG1fYnVkZHlfbWFuX2FsbG9jKHN0cnVjdCB0dG1fcmVzb3VyY2VfbWFuYWdlciAqbWFuLAor CQkJCSAgICBzdHJ1Y3QgdHRtX2J1ZmZlcl9vYmplY3QgKmJvLAorCQkJCSAgICBjb25zdCBzdHJ1 Y3QgdHRtX3BsYWNlICpwbGFjZSwKKwkJCQkgICAgc3RydWN0IHR0bV9yZXNvdXJjZSAqKnJlcykK K3sKKwlzdHJ1Y3QgaTkxNV90dG1fYnVkZHlfbWFuYWdlciAqYm1hbiA9IHRvX2J1ZGR5X21hbmFn ZXIobWFuKTsKKwlzdHJ1Y3QgaTkxNV90dG1fYnVkZHlfcmVzb3VyY2UgKmJtYW5fcmVzOworCXN0 cnVjdCBpOTE1X2J1ZGR5X21tICptbSA9ICZibWFuLT5tbTsKKwl1bnNpZ25lZCBsb25nIG5fcGFn ZXM7CisJdW5zaWduZWQgaW50IG1pbl9vcmRlcjsKKwl1NjQgbWluX3BhZ2Vfc2l6ZTsKKwl1NjQg c2l6ZTsKKwlpbnQgZXJyOworCisJR0VNX0JVR19PTihwbGFjZS0+ZnBmbiB8fCBwbGFjZS0+bHBm bik7CisKKwlibWFuX3JlcyA9IGt6YWxsb2Moc2l6ZW9mKCpibWFuX3JlcyksIEdGUF9LRVJORUwp OworCWlmICghYm1hbl9yZXMpCisJCXJldHVybiAtRU5PTUVNOworCisJdHRtX3Jlc291cmNlX2lu aXQoYm8sIHBsYWNlLCAmYm1hbl9yZXMtPmJhc2UpOworCUlOSVRfTElTVF9IRUFEKCZibWFuX3Jl cy0+YmxvY2tzKTsKKwlibWFuX3Jlcy0+bW0gPSBtbTsKKworCUdFTV9CVUdfT04oIWJtYW5fcmVz LT5iYXNlLm51bV9wYWdlcyk7CisJc2l6ZSA9IGJtYW5fcmVzLT5iYXNlLm51bV9wYWdlcyA8PCBQ QUdFX1NISUZUOworCisJbWluX3BhZ2Vfc2l6ZSA9IGJvLT5wYWdlX2FsaWdubWVudCA8PCBQQUdF X1NISUZUOworCUdFTV9CVUdfT04obWluX3BhZ2Vfc2l6ZSA8IG1tLT5jaHVua19zaXplKTsKKwlt aW5fb3JkZXIgPSBpbG9nMihtaW5fcGFnZV9zaXplKSAtIGlsb2cyKG1tLT5jaHVua19zaXplKTsK KwlpZiAocGxhY2UtPmZsYWdzICYgVFRNX1BMX0ZMQUdfQ09OVElHVU9VUykgeworCQlzaXplID0g cm91bmR1cF9wb3dfb2ZfdHdvKHNpemUpOworCQltaW5fb3JkZXIgPSBpbG9nMihzaXplKSAtIGls b2cyKG1tLT5jaHVua19zaXplKTsKKwl9CisKKwlpZiAoc2l6ZSA+IG1tLT5zaXplKSB7CisJCWVy ciA9IC1FMkJJRzsKKwkJZ290byBlcnJfZnJlZV9yZXM7CisJfQorCisJbl9wYWdlcyA9IHNpemUg Pj4gaWxvZzIobW0tPmNodW5rX3NpemUpOworCisJZG8geworCQlzdHJ1Y3QgaTkxNV9idWRkeV9i bG9jayAqYmxvY2s7CisJCXVuc2lnbmVkIGludCBvcmRlcjsKKworCQlvcmRlciA9IGZscyhuX3Bh Z2VzKSAtIDE7CisJCUdFTV9CVUdfT04ob3JkZXIgPiBtbS0+bWF4X29yZGVyKTsKKwkJR0VNX0JV R19PTihvcmRlciA8IG1pbl9vcmRlcik7CisKKwkJZG8geworCQkJbXV0ZXhfbG9jaygmYm1hbi0+ bG9jayk7CisJCQlibG9jayA9IGk5MTVfYnVkZHlfYWxsb2MobW0sIG9yZGVyKTsKKwkJCW11dGV4 X3VubG9jaygmYm1hbi0+bG9jayk7CisJCQlpZiAoIUlTX0VSUihibG9jaykpCisJCQkJYnJlYWs7 CisKKwkJCWlmIChvcmRlci0tID09IG1pbl9vcmRlcikgeworCQkJCWVyciA9IC1FTk9TUEM7CisJ CQkJZ290byBlcnJfZnJlZV9ibG9ja3M7CisJCQl9CisJCX0gd2hpbGUgKDEpOworCisJCW5fcGFn ZXMgLT0gQklUKG9yZGVyKTsKKworCQlsaXN0X2FkZF90YWlsKCZibG9jay0+bGluaywgJmJtYW5f cmVzLT5ibG9ja3MpOworCisJCWlmICghbl9wYWdlcykKKwkJCWJyZWFrOworCX0gd2hpbGUgKDEp OworCisJKnJlcyA9ICZibWFuX3Jlcy0+YmFzZTsKKwlyZXR1cm4gMDsKKworZXJyX2ZyZWVfYmxv Y2tzOgorCW11dGV4X2xvY2soJmJtYW4tPmxvY2spOworCWk5MTVfYnVkZHlfZnJlZV9saXN0KG1t LCAmYm1hbl9yZXMtPmJsb2Nrcyk7CisJbXV0ZXhfdW5sb2NrKCZibWFuLT5sb2NrKTsKK2Vycl9m cmVlX3JlczoKKwlrZnJlZShibWFuX3Jlcyk7CisJcmV0dXJuIGVycjsKK30KKworc3RhdGljIHZv aWQgaTkxNV90dG1fYnVkZHlfbWFuX2ZyZWUoc3RydWN0IHR0bV9yZXNvdXJjZV9tYW5hZ2VyICpt YW4sCisJCQkJICAgIHN0cnVjdCB0dG1fcmVzb3VyY2UgKnJlcykKK3sKKwlzdHJ1Y3QgaTkxNV90 dG1fYnVkZHlfcmVzb3VyY2UgKmJtYW5fcmVzID0gdG9fdHRtX2J1ZGR5X3Jlc291cmNlKHJlcyk7 CisJc3RydWN0IGk5MTVfdHRtX2J1ZGR5X21hbmFnZXIgKmJtYW4gPSB0b19idWRkeV9tYW5hZ2Vy KG1hbik7CisKKwltdXRleF9sb2NrKCZibWFuLT5sb2NrKTsKKwlpOTE1X2J1ZGR5X2ZyZWVfbGlz dCgmYm1hbi0+bW0sICZibWFuX3Jlcy0+YmxvY2tzKTsKKwltdXRleF91bmxvY2soJmJtYW4tPmxv Y2spOworCisJa2ZyZWUoYm1hbl9yZXMpOworfQorCitzdGF0aWMgY29uc3Qgc3RydWN0IHR0bV9y ZXNvdXJjZV9tYW5hZ2VyX2Z1bmMgaTkxNV90dG1fYnVkZHlfbWFuYWdlcl9mdW5jID0geworCS5h bGxvYyA9IGk5MTVfdHRtX2J1ZGR5X21hbl9hbGxvYywKKwkuZnJlZSA9IGk5MTVfdHRtX2J1ZGR5 X21hbl9mcmVlLAorfTsKKworCisvKioKKyAqIGk5MTVfdHRtX2J1ZGR5X21hbl9pbml0IC0gU2V0 dXAgYnVkZHkgYWxsb2NhdG9yIGJhc2VkIHR0bSBtYW5hZ2VyCisgKiBAYmRldjogVGhlIHR0bSBk ZXZpY2UKKyAqIEB0eXBlOiBNZW1vcnkgdHlwZSB3ZSB3YW50IHRvIG1hbmFnZQorICogQHVzZV90 dDogU2V0IHVzZV90dCBmb3IgdGhlIG1hbmFnZXIKKyAqIEBzaXplOiBUaGUgc2l6ZSBpbiBieXRl cyB0byBtYW5hZ2UKKyAqIEBjaHVua19zaXplOiBUaGUgbWluaW11bSBwYWdlIHNpemUgaW4gYnl0 ZXMgZm9yIG91ciBhbGxvY2F0aW9ucyBpLmUKKyAqIG9yZGVyLXplcm8KKyAqCisgKiBOb3RlIHRo YXQgdGhlIHN0YXJ0aW5nIGFkZHJlc3MgaXMgYXNzdW1lZCB0byBiZSB6ZXJvIGhlcmUsIHNpbmNl IHRoaXMKKyAqIHNpbXBsaWZpZXMga2VlcGluZyB0aGUgcHJvcGVydHkgd2hlcmUgYWxsb2NhdGVk IGJsb2NrcyBoYXZpbmcgbmF0dXJhbAorICogcG93ZXItb2YtdHdvIGFsaWdubWVudC4gU28gbG9u ZyBhcyB0aGUgcmVhbCBzdGFydGluZyBhZGRyZXNzIGlzIHNvbWUgbGFyZ2UKKyAqIHBvd2VyLW9m LXR3bywgb3IgbmF0dXJhbGx5IHN0YXJ0IGZyb20gemVybywgdGhlbiB0aGlzIHNob3VsZCBiZSBm aW5lLiAgQWxzbworICogdGhlICZpOTE1X3R0bV9idWRkeV9tYW5fcmVzZXJ2ZSBpbnRlcmZhY2Ug Y2FuIGJlIHVzZWQgdG8gcHJlc2VydmUgYWxpZ25tZW50CisgKiBpZiBzYXkgdGhlcmUgaXMgc29t ZSB1bnVzYWJsZSByYW5nZSBmcm9tIHRoZSBzdGFydCBvZiB0aGUgcmVnaW9uLiBXZSBjYW4KKyAq IHJldmlzaXQgdGhpcyBpbiB0aGUgZnV0dXJlIGFuZCBtYWtlIHRoZSBpbnRlcmZhY2UgYWNjZXB0 IGFuIGFjdHVhbCBzdGFydGluZworICogb2Zmc2V0IGFuZCBsZXQgaXQgdGFrZSBjYXJlIG9mIHRo ZSByZXN0LgorICoKKyAqIE5vdGUgdGhhdCBpZiB0aGUgQHNpemUgaXMgbm90IGFsaWduZWQgdG8g dGhlIEBjaHVua19zaXplIHRoZW4gd2UgcGVyZm9ybSB0aGUKKyAqIHJlcXVpcmVkIHJvdW5kaW5n IHRvIGdldCB0aGUgdXNhYmxlIHNpemUuIFRoZSBmaW5hbCBzaXplIGluIHBhZ2VzIGNhbiBiZQor ICogdGFrZW4gZnJvbSAmdHRtX3Jlc291cmNlX21hbmFnZXIuc2l6ZS4KKyAqCisgKiBSZXR1cm46 IDAgb24gc3VjY2VzcywgbmVnYXRpdmUgZXJyb3IgY29kZSBvbiBmYWlsdXJlLgorICovCitpbnQg aTkxNV90dG1fYnVkZHlfbWFuX2luaXQoc3RydWN0IHR0bV9kZXZpY2UgKmJkZXYsCisJCQkgICAg dW5zaWduZWQgaW50IHR5cGUsIGJvb2wgdXNlX3R0LAorCQkJICAgIHU2NCBzaXplLCB1NjQgY2h1 bmtfc2l6ZSkKK3sKKwlzdHJ1Y3QgdHRtX3Jlc291cmNlX21hbmFnZXIgKm1hbjsKKwlzdHJ1Y3Qg aTkxNV90dG1fYnVkZHlfbWFuYWdlciAqYm1hbjsKKwlpbnQgZXJyOworCisJYm1hbiA9IGt6YWxs b2Moc2l6ZW9mKCpibWFuKSwgR0ZQX0tFUk5FTCk7CisJaWYgKCFibWFuKQorCQlyZXR1cm4gLUVO T01FTTsKKworCWVyciA9IGk5MTVfYnVkZHlfaW5pdCgmYm1hbi0+bW0sIHNpemUsIGNodW5rX3Np emUpOworCWlmIChlcnIpCisJCWdvdG8gZXJyX2ZyZWVfYm1hbjsKKworCW11dGV4X2luaXQoJmJt YW4tPmxvY2spOworCUlOSVRfTElTVF9IRUFEKCZibWFuLT5yZXNlcnZlZCk7CisKKwltYW4gPSAm Ym1hbi0+bWFuYWdlcjsKKwltYW4tPnVzZV90dCA9IHVzZV90dDsKKwltYW4tPmZ1bmMgPSAmaTkx NV90dG1fYnVkZHlfbWFuYWdlcl9mdW5jOworCXR0bV9yZXNvdXJjZV9tYW5hZ2VyX2luaXQobWFu LCBibWFuLT5tbS5zaXplID4+IFBBR0VfU0hJRlQpOworCisJdHRtX3Jlc291cmNlX21hbmFnZXJf c2V0X3VzZWQobWFuLCB0cnVlKTsKKwl0dG1fc2V0X2RyaXZlcl9tYW5hZ2VyKGJkZXYsIHR5cGUs IG1hbik7CisKKwlyZXR1cm4gMDsKKworZXJyX2ZyZWVfYm1hbjoKKwlrZnJlZShibWFuKTsKKwly ZXR1cm4gZXJyOworfQorCisvKioKKyAqIGk5MTVfdHRtX2J1ZGR5X21hbl9maW5pIC0gRGVzdHJv eSB0aGUgYnVkZHkgYWxsb2NhdG9yIHR0bSBtYW5hZ2VyCisgKiBAYmRldjogVGhlIHR0bSBkZXZp Y2UKKyAqIEB0eXBlOiBNZW1vcnkgdHlwZSB3ZSB3YW50IHRvIG1hbmFnZQorICoKKyAqIE5vdGUg dGhhdCBpZiB3ZSByZXNlcnZlZCBhbnl0aGluZyB3aXRoICZpOTE1X3R0bV9idWRkeV9tYW5fcmVz ZXJ2ZSwgdGhpcyB3aWxsCisgKiBhbHNvIGJlIGZyZWVkIGZvciB1cyBoZXJlLgorICoKKyAqIFJl dHVybjogMCBvbiBzdWNjZXNzLCBuZWdhdGl2ZSBlcnJvciBjb2RlIG9uIGZhaWx1cmUuCisgKi8K K2ludCBpOTE1X3R0bV9idWRkeV9tYW5fZmluaShzdHJ1Y3QgdHRtX2RldmljZSAqYmRldiwgdW5z aWduZWQgaW50IHR5cGUpCit7CisJc3RydWN0IHR0bV9yZXNvdXJjZV9tYW5hZ2VyICptYW4gPSB0 dG1fbWFuYWdlcl90eXBlKGJkZXYsIHR5cGUpOworCXN0cnVjdCBpOTE1X3R0bV9idWRkeV9tYW5h Z2VyICpibWFuID0gdG9fYnVkZHlfbWFuYWdlcihtYW4pOworCXN0cnVjdCBpOTE1X2J1ZGR5X21t ICptbSA9ICZibWFuLT5tbTsKKwlpbnQgcmV0OworCisJdHRtX3Jlc291cmNlX21hbmFnZXJfc2V0 X3VzZWQobWFuLCBmYWxzZSk7CisKKwlyZXQgPSB0dG1fcmVzb3VyY2VfbWFuYWdlcl9ldmljdF9h bGwoYmRldiwgbWFuKTsKKwlpZiAocmV0KQorCQlyZXR1cm4gcmV0OworCisJdHRtX3NldF9kcml2 ZXJfbWFuYWdlcihiZGV2LCB0eXBlLCBOVUxMKTsKKworCW11dGV4X2xvY2soJmJtYW4tPmxvY2sp OworCWk5MTVfYnVkZHlfZnJlZV9saXN0KG1tLCAmYm1hbi0+cmVzZXJ2ZWQpOworCWk5MTVfYnVk ZHlfZmluaShtbSk7CisJbXV0ZXhfdW5sb2NrKCZibWFuLT5sb2NrKTsKKworCXR0bV9yZXNvdXJj ZV9tYW5hZ2VyX2NsZWFudXAobWFuKTsKKwlrZnJlZShibWFuKTsKKworCXJldHVybiAwOworfQor CisvKioKKyAqIGk5MTVfdHRtX2J1ZGR5X21hbl9yZXNlcnZlIC0gUmVzZXJ2ZSBhZGRyZXNzIHJh bmdlCisgKiBAbWFuOiBUaGUgYnVkZHkgYWxsb2NhdG9yIHR0bSBtYW5hZ2VyCisgKiBAc3RhcnQ6 IFRoZSBvZmZzZXQgaW4gYnl0ZXMsIHdoZXJlIHRoZSByZWdpb24gc3RhcnQgaXMgYXNzdW1lZCB0 byBiZSB6ZXJvCisgKiBAc2l6ZTogVGhlIHNpemUgaW4gYnl0ZXMKKyAqCisgKiBOb3RlIHRoYXQg dGhlIHN0YXJ0aW5nIGFkZHJlc3MgZm9yIHRoZSByZWdpb24gaXMgYWx3YXlzIGFzc3VtZWQgdG8g YmUgemVyby4KKyAqCisgKiBSZXR1cm46IDAgb24gc3VjY2VzcywgbmVnYXRpdmUgZXJyb3IgY29k ZSBvbiBmYWlsdXJlLgorICovCitpbnQgaTkxNV90dG1fYnVkZHlfbWFuX3Jlc2VydmUoc3RydWN0 IHR0bV9yZXNvdXJjZV9tYW5hZ2VyICptYW4sCisJCQkgICAgICAgdTY0IHN0YXJ0LCB1NjQgc2l6 ZSkKK3sKKwlzdHJ1Y3QgaTkxNV90dG1fYnVkZHlfbWFuYWdlciAqYm1hbiA9IHRvX2J1ZGR5X21h bmFnZXIobWFuKTsKKwlzdHJ1Y3QgaTkxNV9idWRkeV9tbSAqbW0gPSAmYm1hbi0+bW07CisJaW50 IHJldDsKKworCW11dGV4X2xvY2soJmJtYW4tPmxvY2spOworCXJldCA9IGk5MTVfYnVkZHlfYWxs b2NfcmFuZ2UobW0sICZibWFuLT5yZXNlcnZlZCwgc3RhcnQsIHNpemUpOworCW11dGV4X3VubG9j aygmYm1hbi0+bG9jayk7CisKKwlyZXR1cm4gcmV0OworfQorCmRpZmYgLS1naXQgYS9kcml2ZXJz L2dwdS9kcm0vaTkxNS9pOTE1X3R0bV9idWRkeV9tYW5hZ2VyLmggYi9kcml2ZXJzL2dwdS9kcm0v aTkxNS9pOTE1X3R0bV9idWRkeV9tYW5hZ2VyLmgKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXgg MDAwMDAwMDAwMDAwLi4yNjAyNjIxM2UyMGEKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL2dw dS9kcm0vaTkxNS9pOTE1X3R0bV9idWRkeV9tYW5hZ2VyLmgKQEAgLTAsMCArMSw1NiBAQAorLyog U1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1JVCAqLworLyoKKyAqIENvcHlyaWdodCDCqSAyMDIx IEludGVsIENvcnBvcmF0aW9uCisgKi8KKworI2lmbmRlZiBfX0k5MTVfVFRNX0JVRERZX01BTkFH RVJfSF9fCisjZGVmaW5lIF9fSTkxNV9UVE1fQlVERFlfTUFOQUdFUl9IX18KKworI2luY2x1ZGUg PGxpbnV4L2xpc3QuaD4KKyNpbmNsdWRlIDxsaW51eC90eXBlcy5oPgorCisjaW5jbHVkZSA8ZHJt L3R0bS90dG1fcmVzb3VyY2UuaD4KKworc3RydWN0IHR0bV9kZXZpY2U7CitzdHJ1Y3QgdHRtX3Jl c291cmNlX21hbmFnZXI7CitzdHJ1Y3QgaTkxNV9idWRkeV9tbTsKKworLyoqCisgKiBzdHJ1Y3Qg aTkxNV90dG1fYnVkZHlfcmVzb3VyY2UKKyAqCisgKiBAYmFzZTogc3RydWN0IHR0bV9yZXNvdXJj ZSBiYXNlIGNsYXNzIHdlIGV4dGVuZAorICogQGJsb2NrczogdGhlIGxpc3Qgb2Ygc3RydWN0IGk5 MTVfYnVkZHlfYmxvY2sgZm9yIHRoaXMgcmVzb3VyY2UvYWxsb2NhdGlvbgorICogQG1tOiB0aGUg c3RydWN0IGk5MTVfYnVkZHlfbW0gZm9yIHRoaXMgcmVzb3VyY2UKKyAqCisgKiBFeHRlbmRzIHRo ZSBzdHJ1Y3QgdHRtX3Jlc291cmNlIHRvIG1hbmFnZSBhbiBhZGRyZXNzIHNwYWNlIGFsbG9jYXRp b24gd2l0aAorICogb25lIG9yIG1vcmUgc3RydWN0IGk5MTVfYnVkZHlfYmxvY2suCisgKi8KK3N0 cnVjdCBpOTE1X3R0bV9idWRkeV9yZXNvdXJjZSB7CisJc3RydWN0IHR0bV9yZXNvdXJjZSBiYXNl OworCXN0cnVjdCBsaXN0X2hlYWQgYmxvY2tzOworCXN0cnVjdCBpOTE1X2J1ZGR5X21tICptbTsK K307CisKKy8qKgorICogdG9fdHRtX2J1ZGR5X3Jlc291cmNlCisgKgorICogQHJlczogdGhlIHJl c291cmNlIHRvIHVwY2FzdAorICoKKyAqIFVwY2FzdCB0aGUgc3RydWN0IHR0bV9yZXNvdXJjZSBv YmplY3QgaW50byBhIHN0cnVjdCBpOTE1X3R0bV9idWRkeV9yZXNvdXJjZS4KKyAqLworc3RhdGlj IGlubGluZSBzdHJ1Y3QgaTkxNV90dG1fYnVkZHlfcmVzb3VyY2UgKgordG9fdHRtX2J1ZGR5X3Jl c291cmNlKHN0cnVjdCB0dG1fcmVzb3VyY2UgKnJlcykKK3sKKwlyZXR1cm4gY29udGFpbmVyX29m KHJlcywgc3RydWN0IGk5MTVfdHRtX2J1ZGR5X3Jlc291cmNlLCBiYXNlKTsKK30KKworaW50IGk5 MTVfdHRtX2J1ZGR5X21hbl9pbml0KHN0cnVjdCB0dG1fZGV2aWNlICpiZGV2LAorCQkJICAgIHVu c2lnbmVkIHR5cGUsIGJvb2wgdXNlX3R0LAorCQkJICAgIHU2NCBzaXplLCB1NjQgY2h1bmtfc2l6 ZSk7CitpbnQgaTkxNV90dG1fYnVkZHlfbWFuX2Zpbmkoc3RydWN0IHR0bV9kZXZpY2UgKmJkZXYs CisJCQkgICAgdW5zaWduZWQgaW50IHR5cGUpOworCitpbnQgaTkxNV90dG1fYnVkZHlfbWFuX3Jl c2VydmUoc3RydWN0IHR0bV9yZXNvdXJjZV9tYW5hZ2VyICptYW4sCisJCQkgICAgICAgdTY0IHN0 YXJ0LCB1NjQgc2l6ZSk7CisKKyNlbmRpZgpkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL2k5 MTUvc2VsZnRlc3RzL2k5MTVfYnVkZHkuYyBiL2RyaXZlcnMvZ3B1L2RybS9pOTE1L3NlbGZ0ZXN0 cy9pOTE1X2J1ZGR5LmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAwLi5m MGY1YzRkZjhkYmMKLS0tIC9kZXYvbnVsbAorKysgYi9kcml2ZXJzL2dwdS9kcm0vaTkxNS9zZWxm dGVzdHMvaTkxNV9idWRkeS5jCkBAIC0wLDAgKzEsNzg5IEBACisvLyBTUERYLUxpY2Vuc2UtSWRl bnRpZmllcjogTUlUCisvKgorICogQ29weXJpZ2h0IMKpIDIwMTkgSW50ZWwgQ29ycG9yYXRpb24K KyAqLworCisjaW5jbHVkZSA8bGludXgvcHJpbWVfbnVtYmVycy5oPgorCisjaW5jbHVkZSAiLi4v aTkxNV9zZWxmdGVzdC5oIgorI2luY2x1ZGUgImk5MTVfcmFuZG9tLmgiCisKK3N0YXRpYyB2b2lk IF9faWd0X2R1bXBfYmxvY2soc3RydWN0IGk5MTVfYnVkZHlfbW0gKm1tLAorCQkJICAgICBzdHJ1 Y3QgaTkxNV9idWRkeV9ibG9jayAqYmxvY2ssCisJCQkgICAgIGJvb2wgYnVkZHkpCit7CisJcHJf ZXJyKCJibG9jayBpbmZvOiBoZWFkZXI9JWxseCwgc3RhdGU9JXUsIG9yZGVyPSVkLCBvZmZzZXQ9 JWxseCBzaXplPSVsbHggcm9vdD0lcyBidWRkeT0lc1xuIiwKKwkgICAgICAgYmxvY2stPmhlYWRl ciwKKwkgICAgICAgaTkxNV9idWRkeV9ibG9ja19zdGF0ZShibG9jayksCisJICAgICAgIGk5MTVf YnVkZHlfYmxvY2tfb3JkZXIoYmxvY2spLAorCSAgICAgICBpOTE1X2J1ZGR5X2Jsb2NrX29mZnNl dChibG9jayksCisJICAgICAgIGk5MTVfYnVkZHlfYmxvY2tfc2l6ZShtbSwgYmxvY2spLAorCSAg ICAgICB5ZXNubyghYmxvY2stPnBhcmVudCksCisJICAgICAgIHllc25vKGJ1ZGR5KSk7Cit9CisK K3N0YXRpYyB2b2lkIGlndF9kdW1wX2Jsb2NrKHN0cnVjdCBpOTE1X2J1ZGR5X21tICptbSwKKwkJ CSAgIHN0cnVjdCBpOTE1X2J1ZGR5X2Jsb2NrICpibG9jaykKK3sKKwlzdHJ1Y3QgaTkxNV9idWRk eV9ibG9jayAqYnVkZHk7CisKKwlfX2lndF9kdW1wX2Jsb2NrKG1tLCBibG9jaywgZmFsc2UpOwor CisJYnVkZHkgPSBnZXRfYnVkZHkoYmxvY2spOworCWlmIChidWRkeSkKKwkJX19pZ3RfZHVtcF9i bG9jayhtbSwgYnVkZHksIHRydWUpOworfQorCitzdGF0aWMgaW50IGlndF9jaGVja19ibG9jayhz dHJ1Y3QgaTkxNV9idWRkeV9tbSAqbW0sCisJCQkgICBzdHJ1Y3QgaTkxNV9idWRkeV9ibG9jayAq YmxvY2spCit7CisJc3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgKmJ1ZGR5OworCXVuc2lnbmVkIGlu dCBibG9ja19zdGF0ZTsKKwl1NjQgYmxvY2tfc2l6ZTsKKwl1NjQgb2Zmc2V0OworCWludCBlcnIg PSAwOworCisJYmxvY2tfc3RhdGUgPSBpOTE1X2J1ZGR5X2Jsb2NrX3N0YXRlKGJsb2NrKTsKKwor CWlmIChibG9ja19zdGF0ZSAhPSBJOTE1X0JVRERZX0FMTE9DQVRFRCAmJgorCSAgICBibG9ja19z dGF0ZSAhPSBJOTE1X0JVRERZX0ZSRUUgJiYKKwkgICAgYmxvY2tfc3RhdGUgIT0gSTkxNV9CVURE WV9TUExJVCkgeworCQlwcl9lcnIoImJsb2NrIHN0YXRlIG1pc21hdGNoXG4iKTsKKwkJZXJyID0g LUVJTlZBTDsKKwl9CisKKwlibG9ja19zaXplID0gaTkxNV9idWRkeV9ibG9ja19zaXplKG1tLCBi bG9jayk7CisJb2Zmc2V0ID0gaTkxNV9idWRkeV9ibG9ja19vZmZzZXQoYmxvY2spOworCisJaWYg KGJsb2NrX3NpemUgPCBtbS0+Y2h1bmtfc2l6ZSkgeworCQlwcl9lcnIoImJsb2NrIHNpemUgc21h bGxlciB0aGFuIG1pbiBzaXplXG4iKTsKKwkJZXJyID0gLUVJTlZBTDsKKwl9CisKKwlpZiAoIWlz X3Bvd2VyX29mXzIoYmxvY2tfc2l6ZSkpIHsKKwkJcHJfZXJyKCJibG9jayBzaXplIG5vdCBwb3dl ciBvZiB0d29cbiIpOworCQllcnIgPSAtRUlOVkFMOworCX0KKworCWlmICghSVNfQUxJR05FRChi bG9ja19zaXplLCBtbS0+Y2h1bmtfc2l6ZSkpIHsKKwkJcHJfZXJyKCJibG9jayBzaXplIG5vdCBh bGlnbmVkIHRvIG1pbiBzaXplXG4iKTsKKwkJZXJyID0gLUVJTlZBTDsKKwl9CisKKwlpZiAoIUlT X0FMSUdORUQob2Zmc2V0LCBtbS0+Y2h1bmtfc2l6ZSkpIHsKKwkJcHJfZXJyKCJibG9jayBvZmZz ZXQgbm90IGFsaWduZWQgdG8gbWluIHNpemVcbiIpOworCQllcnIgPSAtRUlOVkFMOworCX0KKwor CWlmICghSVNfQUxJR05FRChvZmZzZXQsIGJsb2NrX3NpemUpKSB7CisJCXByX2VycigiYmxvY2sg b2Zmc2V0IG5vdCBhbGlnbmVkIHRvIGJsb2NrIHNpemVcbiIpOworCQllcnIgPSAtRUlOVkFMOwor CX0KKworCWJ1ZGR5ID0gZ2V0X2J1ZGR5KGJsb2NrKTsKKworCWlmICghYnVkZHkgJiYgYmxvY2st PnBhcmVudCkgeworCQlwcl9lcnIoImJ1ZGR5IGhhcyBnb25lIGZpc2hpbmdcbiIpOworCQllcnIg PSAtRUlOVkFMOworCX0KKworCWlmIChidWRkeSkgeworCQlpZiAoaTkxNV9idWRkeV9ibG9ja19v ZmZzZXQoYnVkZHkpICE9IChvZmZzZXQgXiBibG9ja19zaXplKSkgeworCQkJcHJfZXJyKCJidWRk eSBoYXMgd3Jvbmcgb2Zmc2V0XG4iKTsKKwkJCWVyciA9IC1FSU5WQUw7CisJCX0KKworCQlpZiAo aTkxNV9idWRkeV9ibG9ja19zaXplKG1tLCBidWRkeSkgIT0gYmxvY2tfc2l6ZSkgeworCQkJcHJf ZXJyKCJidWRkeSBzaXplIG1pc21hdGNoXG4iKTsKKwkJCWVyciA9IC1FSU5WQUw7CisJCX0KKwor CQlpZiAoaTkxNV9idWRkeV9ibG9ja19zdGF0ZShidWRkeSkgPT0gYmxvY2tfc3RhdGUgJiYKKwkJ ICAgIGJsb2NrX3N0YXRlID09IEk5MTVfQlVERFlfRlJFRSkgeworCQkJcHJfZXJyKCJibG9jayBh bmQgaXRzIGJ1ZGR5IGFyZSBmcmVlXG4iKTsKKwkJCWVyciA9IC1FSU5WQUw7CisJCX0KKwl9CisK KwlyZXR1cm4gZXJyOworfQorCitzdGF0aWMgaW50IGlndF9jaGVja19ibG9ja3Moc3RydWN0IGk5 MTVfYnVkZHlfbW0gKm1tLAorCQkJICAgIHN0cnVjdCBsaXN0X2hlYWQgKmJsb2NrcywKKwkJCSAg ICB1NjQgZXhwZWN0ZWRfc2l6ZSwKKwkJCSAgICBib29sIGlzX2NvbnRpZ3VvdXMpCit7CisJc3Ry dWN0IGk5MTVfYnVkZHlfYmxvY2sgKmJsb2NrOworCXN0cnVjdCBpOTE1X2J1ZGR5X2Jsb2NrICpw cmV2OworCXU2NCB0b3RhbDsKKwlpbnQgZXJyID0gMDsKKworCWJsb2NrID0gTlVMTDsKKwlwcmV2 ID0gTlVMTDsKKwl0b3RhbCA9IDA7CisKKwlsaXN0X2Zvcl9lYWNoX2VudHJ5KGJsb2NrLCBibG9j a3MsIGxpbmspIHsKKwkJZXJyID0gaWd0X2NoZWNrX2Jsb2NrKG1tLCBibG9jayk7CisKKwkJaWYg KCFpOTE1X2J1ZGR5X2Jsb2NrX2lzX2FsbG9jYXRlZChibG9jaykpIHsKKwkJCXByX2VycigiYmxv Y2sgbm90IGFsbG9jYXRlZFxuIiksCisJCQllcnIgPSAtRUlOVkFMOworCQl9CisKKwkJaWYgKGlz X2NvbnRpZ3VvdXMgJiYgcHJldikgeworCQkJdTY0IHByZXZfYmxvY2tfc2l6ZTsKKwkJCXU2NCBw cmV2X29mZnNldDsKKwkJCXU2NCBvZmZzZXQ7CisKKwkJCXByZXZfb2Zmc2V0ID0gaTkxNV9idWRk eV9ibG9ja19vZmZzZXQocHJldik7CisJCQlwcmV2X2Jsb2NrX3NpemUgPSBpOTE1X2J1ZGR5X2Js b2NrX3NpemUobW0sIHByZXYpOworCQkJb2Zmc2V0ID0gaTkxNV9idWRkeV9ibG9ja19vZmZzZXQo YmxvY2spOworCisJCQlpZiAob2Zmc2V0ICE9IChwcmV2X29mZnNldCArIHByZXZfYmxvY2tfc2l6 ZSkpIHsKKwkJCQlwcl9lcnIoImJsb2NrIG9mZnNldCBtaXNtYXRjaFxuIik7CisJCQkJZXJyID0g LUVJTlZBTDsKKwkJCX0KKwkJfQorCisJCWlmIChlcnIpCisJCQlicmVhazsKKworCQl0b3RhbCAr PSBpOTE1X2J1ZGR5X2Jsb2NrX3NpemUobW0sIGJsb2NrKTsKKwkJcHJldiA9IGJsb2NrOworCX0K KworCWlmICghZXJyKSB7CisJCWlmICh0b3RhbCAhPSBleHBlY3RlZF9zaXplKSB7CisJCQlwcl9l cnIoInNpemUgbWlzbWF0Y2gsIGV4cGVjdGVkPSVsbHgsIGZvdW5kPSVsbHhcbiIsCisJCQkgICAg ICAgZXhwZWN0ZWRfc2l6ZSwgdG90YWwpOworCQkJZXJyID0gLUVJTlZBTDsKKwkJfQorCQlyZXR1 cm4gZXJyOworCX0KKworCWlmIChwcmV2KSB7CisJCXByX2VycigicHJldiBibG9jaywgZHVtcDpc biIpOworCQlpZ3RfZHVtcF9ibG9jayhtbSwgcHJldik7CisJfQorCisJaWYgKGJsb2NrKSB7CisJ CXByX2VycigiYmFkIGJsb2NrLCBkdW1wOlxuIik7CisJCWlndF9kdW1wX2Jsb2NrKG1tLCBibG9j ayk7CisJfQorCisJcmV0dXJuIGVycjsKK30KKworc3RhdGljIGludCBpZ3RfY2hlY2tfbW0oc3Ry dWN0IGk5MTVfYnVkZHlfbW0gKm1tKQoreworCXN0cnVjdCBpOTE1X2J1ZGR5X2Jsb2NrICpyb290 OworCXN0cnVjdCBpOTE1X2J1ZGR5X2Jsb2NrICpwcmV2OworCXVuc2lnbmVkIGludCBpOworCXU2 NCB0b3RhbDsKKwlpbnQgZXJyID0gMDsKKworCWlmICghbW0tPm5fcm9vdHMpIHsKKwkJcHJfZXJy KCJuX3Jvb3RzIGlzIHplcm9cbiIpOworCQlyZXR1cm4gLUVJTlZBTDsKKwl9CisKKwlpZiAobW0t Pm5fcm9vdHMgIT0gaHdlaWdodDY0KG1tLT5zaXplKSkgeworCQlwcl9lcnIoIm5fcm9vdHMgbWlz bWF0Y2gsIG5fcm9vdHM9JXUsIGV4cGVjdGVkPSVsdVxuIiwKKwkJICAgICAgIG1tLT5uX3Jvb3Rz LCBod2VpZ2h0NjQobW0tPnNpemUpKTsKKwkJcmV0dXJuIC1FSU5WQUw7CisJfQorCisJcm9vdCA9 IE5VTEw7CisJcHJldiA9IE5VTEw7CisJdG90YWwgPSAwOworCisJZm9yIChpID0gMDsgaSA8IG1t LT5uX3Jvb3RzOyArK2kpIHsKKwkJc3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgKmJsb2NrOworCQl1 bnNpZ25lZCBpbnQgb3JkZXI7CisKKwkJcm9vdCA9IG1tLT5yb290c1tpXTsKKwkJaWYgKCFyb290 KSB7CisJCQlwcl9lcnIoInJvb3QoJXUpIGlzIE5VTExcbiIsIGkpOworCQkJZXJyID0gLUVJTlZB TDsKKwkJCWJyZWFrOworCQl9CisKKwkJZXJyID0gaWd0X2NoZWNrX2Jsb2NrKG1tLCByb290KTsK KworCQlpZiAoIWk5MTVfYnVkZHlfYmxvY2tfaXNfZnJlZShyb290KSkgeworCQkJcHJfZXJyKCJy b290IG5vdCBmcmVlXG4iKTsKKwkJCWVyciA9IC1FSU5WQUw7CisJCX0KKworCQlvcmRlciA9IGk5 MTVfYnVkZHlfYmxvY2tfb3JkZXIocm9vdCk7CisKKwkJaWYgKCFpKSB7CisJCQlpZiAob3JkZXIg IT0gbW0tPm1heF9vcmRlcikgeworCQkJCXByX2VycigibWF4IG9yZGVyIHJvb3QgbWlzc2luZ1xu Iik7CisJCQkJZXJyID0gLUVJTlZBTDsKKwkJCX0KKwkJfQorCisJCWlmIChwcmV2KSB7CisJCQl1 NjQgcHJldl9ibG9ja19zaXplOworCQkJdTY0IHByZXZfb2Zmc2V0OworCQkJdTY0IG9mZnNldDsK KworCQkJcHJldl9vZmZzZXQgPSBpOTE1X2J1ZGR5X2Jsb2NrX29mZnNldChwcmV2KTsKKwkJCXBy ZXZfYmxvY2tfc2l6ZSA9IGk5MTVfYnVkZHlfYmxvY2tfc2l6ZShtbSwgcHJldik7CisJCQlvZmZz ZXQgPSBpOTE1X2J1ZGR5X2Jsb2NrX29mZnNldChyb290KTsKKworCQkJaWYgKG9mZnNldCAhPSAo cHJldl9vZmZzZXQgKyBwcmV2X2Jsb2NrX3NpemUpKSB7CisJCQkJcHJfZXJyKCJyb290IG9mZnNl dCBtaXNtYXRjaFxuIik7CisJCQkJZXJyID0gLUVJTlZBTDsKKwkJCX0KKwkJfQorCisJCWJsb2Nr ID0gbGlzdF9maXJzdF9lbnRyeV9vcl9udWxsKCZtbS0+ZnJlZV9saXN0W29yZGVyXSwKKwkJCQkJ CSBzdHJ1Y3QgaTkxNV9idWRkeV9ibG9jaywKKwkJCQkJCSBsaW5rKTsKKwkJaWYgKGJsb2NrICE9 IHJvb3QpIHsKKwkJCXByX2Vycigicm9vdCBtaXNtYXRjaCBhdCBvcmRlcj0ldVxuIiwgb3JkZXIp OworCQkJZXJyID0gLUVJTlZBTDsKKwkJfQorCisJCWlmIChlcnIpCisJCQlicmVhazsKKworCQlw cmV2ID0gcm9vdDsKKwkJdG90YWwgKz0gaTkxNV9idWRkeV9ibG9ja19zaXplKG1tLCByb290KTsK Kwl9CisKKwlpZiAoIWVycikgeworCQlpZiAodG90YWwgIT0gbW0tPnNpemUpIHsKKwkJCXByX2Vy cigiZXhwZWN0ZWQgbW0gc2l6ZT0lbGx4LCBmb3VuZD0lbGx4XG4iLCBtbS0+c2l6ZSwKKwkJCSAg ICAgICB0b3RhbCk7CisJCQllcnIgPSAtRUlOVkFMOworCQl9CisJCXJldHVybiBlcnI7CisJfQor CisJaWYgKHByZXYpIHsKKwkJcHJfZXJyKCJwcmV2IHJvb3QoJXUpLCBkdW1wOlxuIiwgaSAtIDEp OworCQlpZ3RfZHVtcF9ibG9jayhtbSwgcHJldik7CisJfQorCisJaWYgKHJvb3QpIHsKKwkJcHJf ZXJyKCJiYWQgcm9vdCgldSksIGR1bXA6XG4iLCBpKTsKKwkJaWd0X2R1bXBfYmxvY2sobW0sIHJv b3QpOworCX0KKworCXJldHVybiBlcnI7Cit9CisKK3N0YXRpYyB2b2lkIGlndF9tbV9jb25maWco dTY0ICpzaXplLCB1NjQgKmNodW5rX3NpemUpCit7CisJSTkxNV9STkRfU1RBVEUocHJuZyk7CisJ dTMyIHMsIG1zOworCisJLyogTm90aGluZyBmYW5jeSwganVzdCB0cnkgdG8gZ2V0IGFuIGludGVy ZXN0aW5nIGJpdCBwYXR0ZXJuICovCisKKwlwcmFuZG9tX3NlZWRfc3RhdGUoJnBybmcsIGk5MTVf c2VsZnRlc3QucmFuZG9tX3NlZWQpOworCisJLyogTGV0IHNpemUgYmUgYSByYW5kb20gbnVtYmVy IG9mIHBhZ2VzIHVwIHRvIDggR0IgKDJNIHBhZ2VzKSAqLworCXMgPSAxICsgaTkxNV9wcmFuZG9t X3UzMl9tYXhfc3RhdGUoKEJJVCgzMyAtIDEyKSkgLSAxLCAmcHJuZyk7CisJLyogTGV0IHRoZSBj aHVuayBzaXplIGJlIGEgcmFuZG9tIHBvd2VyIG9mIDIgbGVzcyB0aGFuIHNpemUgKi8KKwltcyA9 IEJJVChpOTE1X3ByYW5kb21fdTMyX21heF9zdGF0ZShpbG9nMihzKSwgJnBybmcpKTsKKwkvKiBS b3VuZCBzaXplIGRvd24gdG8gdGhlIGNodW5rIHNpemUgKi8KKwlzICY9IC1tczsKKworCS8qIENv bnZlcnQgZnJvbSBwYWdlcyB0byBieXRlcyAqLworCSpjaHVua19zaXplID0gKHU2NCltcyA8PCAx MjsKKwkqc2l6ZSA9ICh1NjQpcyA8PCAxMjsKK30KKworc3RhdGljIGludCBpZ3RfYnVkZHlfYWxs b2Nfc21va2Uodm9pZCAqYXJnKQoreworCXN0cnVjdCBpOTE1X2J1ZGR5X21tIG1tOworCUlHVF9U SU1FT1VUKGVuZF90aW1lKTsKKwlJOTE1X1JORF9TVEFURShwcm5nKTsKKwl1NjQgY2h1bmtfc2l6 ZTsKKwl1NjQgbW1fc2l6ZTsKKwlpbnQgKm9yZGVyOworCWludCBlcnIsIGk7CisKKwlpZ3RfbW1f Y29uZmlnKCZtbV9zaXplLCAmY2h1bmtfc2l6ZSk7CisKKwlwcl9pbmZvKCJidWRkeV9pbml0IHdp dGggc2l6ZT0lbGx4LCBjaHVua19zaXplPSVsbHhcbiIsIG1tX3NpemUsIGNodW5rX3NpemUpOwor CisJZXJyID0gaTkxNV9idWRkeV9pbml0KCZtbSwgbW1fc2l6ZSwgY2h1bmtfc2l6ZSk7CisJaWYg KGVycikgeworCQlwcl9lcnIoImJ1ZGR5X2luaXQgZmFpbGVkKCVkKVxuIiwgZXJyKTsKKwkJcmV0 dXJuIGVycjsKKwl9CisKKwlvcmRlciA9IGk5MTVfcmFuZG9tX29yZGVyKG1tLm1heF9vcmRlciAr IDEsICZwcm5nKTsKKwlpZiAoIW9yZGVyKQorCQlnb3RvIG91dF9maW5pOworCisJZm9yIChpID0g MDsgaSA8PSBtbS5tYXhfb3JkZXI7ICsraSkgeworCQlzdHJ1Y3QgaTkxNV9idWRkeV9ibG9jayAq YmxvY2s7CisJCWludCBtYXhfb3JkZXIgPSBvcmRlcltpXTsKKwkJYm9vbCB0aW1lb3V0ID0gZmFs c2U7CisJCUxJU1RfSEVBRChibG9ja3MpOworCQlpbnQgb3JkZXI7CisJCXU2NCB0b3RhbDsKKwor CQllcnIgPSBpZ3RfY2hlY2tfbW0oJm1tKTsKKwkJaWYgKGVycikgeworCQkJcHJfZXJyKCJwcmUt bW0gY2hlY2sgZmFpbGVkLCBhYm9ydFxuIik7CisJCQlicmVhazsKKwkJfQorCisJCXByX2luZm8o ImZpbGxpbmcgZnJvbSBtYXhfb3JkZXI9JXVcbiIsIG1heF9vcmRlcik7CisKKwkJb3JkZXIgPSBt YXhfb3JkZXI7CisJCXRvdGFsID0gMDsKKworCQlkbyB7CityZXRyeToKKwkJCWJsb2NrID0gaTkx NV9idWRkeV9hbGxvYygmbW0sIG9yZGVyKTsKKwkJCWlmIChJU19FUlIoYmxvY2spKSB7CisJCQkJ ZXJyID0gUFRSX0VSUihibG9jayk7CisJCQkJaWYgKGVyciA9PSAtRU5PTUVNKSB7CisJCQkJCXBy X2luZm8oImJ1ZGR5X2FsbG9jIGhpdCAtRU5PTUVNIHdpdGggb3JkZXI9JWRcbiIsCisJCQkJCQlv cmRlcik7CisJCQkJfSBlbHNlIHsKKwkJCQkJaWYgKG9yZGVyLS0pIHsKKwkJCQkJCWVyciA9IDA7 CisJCQkJCQlnb3RvIHJldHJ5OworCQkJCQl9CisKKwkJCQkJcHJfZXJyKCJidWRkeV9hbGxvYyB3 aXRoIG9yZGVyPSVkIGZhaWxlZCglZClcbiIsCisJCQkJCSAgICAgICBvcmRlciwgZXJyKTsKKwkJ CQl9CisKKwkJCQlicmVhazsKKwkJCX0KKworCQkJbGlzdF9hZGRfdGFpbCgmYmxvY2stPmxpbmss ICZibG9ja3MpOworCisJCQlpZiAoaTkxNV9idWRkeV9ibG9ja19vcmRlcihibG9jaykgIT0gb3Jk ZXIpIHsKKwkJCQlwcl9lcnIoImJ1ZGR5X2FsbG9jIG9yZGVyIG1pc21hdGNoXG4iKTsKKwkJCQll cnIgPSAtRUlOVkFMOworCQkJCWJyZWFrOworCQkJfQorCisJCQl0b3RhbCArPSBpOTE1X2J1ZGR5 X2Jsb2NrX3NpemUoJm1tLCBibG9jayk7CisKKwkJCWlmIChfX2lndF90aW1lb3V0KGVuZF90aW1l LCBOVUxMKSkgeworCQkJCXRpbWVvdXQgPSB0cnVlOworCQkJCWJyZWFrOworCQkJfQorCQl9IHdo aWxlICh0b3RhbCA8IG1tLnNpemUpOworCisJCWlmICghZXJyKQorCQkJZXJyID0gaWd0X2NoZWNr X2Jsb2NrcygmbW0sICZibG9ja3MsIHRvdGFsLCBmYWxzZSk7CisKKwkJaTkxNV9idWRkeV9mcmVl X2xpc3QoJm1tLCAmYmxvY2tzKTsKKworCQlpZiAoIWVycikgeworCQkJZXJyID0gaWd0X2NoZWNr X21tKCZtbSk7CisJCQlpZiAoZXJyKQorCQkJCXByX2VycigicG9zdC1tbSBjaGVjayBmYWlsZWRc biIpOworCQl9CisKKwkJaWYgKGVyciB8fCB0aW1lb3V0KQorCQkJYnJlYWs7CisKKwkJY29uZF9y ZXNjaGVkKCk7CisJfQorCisJaWYgKGVyciA9PSAtRU5PTUVNKQorCQllcnIgPSAwOworCisJa2Zy ZWUob3JkZXIpOworb3V0X2Zpbmk6CisJaTkxNV9idWRkeV9maW5pKCZtbSk7CisKKwlyZXR1cm4g ZXJyOworfQorCitzdGF0aWMgaW50IGlndF9idWRkeV9hbGxvY19wZXNzaW1pc3RpYyh2b2lkICph cmcpCit7CisJY29uc3QgdW5zaWduZWQgaW50IG1heF9vcmRlciA9IDE2OworCXN0cnVjdCBpOTE1 X2J1ZGR5X2Jsb2NrICpibG9jaywgKmJuOworCXN0cnVjdCBpOTE1X2J1ZGR5X21tIG1tOworCXVu c2lnbmVkIGludCBvcmRlcjsKKwlMSVNUX0hFQUQoYmxvY2tzKTsKKwlpbnQgZXJyOworCisJLyoK KwkgKiBDcmVhdGUgYSBwb3Qtc2l6ZWQgbW0sIHRoZW4gYWxsb2NhdGUgb25lIG9mIGVhY2ggcG9z c2libGUKKwkgKiBvcmRlciB3aXRoaW4uIFRoaXMgc2hvdWxkIGxlYXZlIHRoZSBtbSB3aXRoIGV4 YWN0bHkgb25lCisJICogcGFnZSBsZWZ0LgorCSAqLworCisJZXJyID0gaTkxNV9idWRkeV9pbml0 KCZtbSwgUEFHRV9TSVpFIDw8IG1heF9vcmRlciwgUEFHRV9TSVpFKTsKKwlpZiAoZXJyKSB7CisJ CXByX2VycigiYnVkZHlfaW5pdCBmYWlsZWQoJWQpXG4iLCBlcnIpOworCQlyZXR1cm4gZXJyOwor CX0KKwlHRU1fQlVHX09OKG1tLm1heF9vcmRlciAhPSBtYXhfb3JkZXIpOworCisJZm9yIChvcmRl ciA9IDA7IG9yZGVyIDwgbWF4X29yZGVyOyBvcmRlcisrKSB7CisJCWJsb2NrID0gaTkxNV9idWRk eV9hbGxvYygmbW0sIG9yZGVyKTsKKwkJaWYgKElTX0VSUihibG9jaykpIHsKKwkJCXByX2luZm8o ImJ1ZGR5X2FsbG9jIGhpdCAtRU5PTUVNIHdpdGggb3JkZXI9JWRcbiIsCisJCQkJb3JkZXIpOwor CQkJZXJyID0gUFRSX0VSUihibG9jayk7CisJCQlnb3RvIGVycjsKKwkJfQorCisJCWxpc3RfYWRk X3RhaWwoJmJsb2NrLT5saW5rLCAmYmxvY2tzKTsKKwl9CisKKwkvKiBBbmQgbm93IHRoZSBsYXN0 IHJlbWFpbmluZyBibG9jayBhdmFpbGFibGUgKi8KKwlibG9jayA9IGk5MTVfYnVkZHlfYWxsb2Mo Jm1tLCAwKTsKKwlpZiAoSVNfRVJSKGJsb2NrKSkgeworCQlwcl9pbmZvKCJidWRkeV9hbGxvYyBo aXQgLUVOT01FTSBvbiBmaW5hbCBhbGxvY1xuIik7CisJCWVyciA9IFBUUl9FUlIoYmxvY2spOwor CQlnb3RvIGVycjsKKwl9CisJbGlzdF9hZGRfdGFpbCgmYmxvY2stPmxpbmssICZibG9ja3MpOwor CisJLyogU2hvdWxkIGJlIGNvbXBsZXRlbHkgZnVsbCEgKi8KKwlmb3IgKG9yZGVyID0gbWF4X29y ZGVyOyBvcmRlci0tOyApIHsKKwkJYmxvY2sgPSBpOTE1X2J1ZGR5X2FsbG9jKCZtbSwgb3JkZXIp OworCQlpZiAoIUlTX0VSUihibG9jaykpIHsKKwkJCXByX2luZm8oImJ1ZGR5X2FsbG9jIHVuZXhw ZWN0ZWRseSBzdWNjZWVkZWQgYXQgb3JkZXIgJWQsIGl0IHNob3VsZCBiZSBmdWxsISIsCisJCQkJ b3JkZXIpOworCQkJbGlzdF9hZGRfdGFpbCgmYmxvY2stPmxpbmssICZibG9ja3MpOworCQkJZXJy ID0gLUVJTlZBTDsKKwkJCWdvdG8gZXJyOworCQl9CisJfQorCisJYmxvY2sgPSBsaXN0X2xhc3Rf ZW50cnkoJmJsb2NrcywgdHlwZW9mKCpibG9jayksIGxpbmspOworCWxpc3RfZGVsKCZibG9jay0+ bGluayk7CisJaTkxNV9idWRkeV9mcmVlKCZtbSwgYmxvY2spOworCisJLyogQXMgd2UgZnJlZSBp biBpbmNyZWFzaW5nIHNpemUsIHdlIG1ha2UgYXZhaWxhYmxlIGxhcmdlciBibG9ja3MgKi8KKwlv cmRlciA9IDE7CisJbGlzdF9mb3JfZWFjaF9lbnRyeV9zYWZlKGJsb2NrLCBibiwgJmJsb2Nrcywg bGluaykgeworCQlsaXN0X2RlbCgmYmxvY2stPmxpbmspOworCQlpOTE1X2J1ZGR5X2ZyZWUoJm1t LCBibG9jayk7CisKKwkJYmxvY2sgPSBpOTE1X2J1ZGR5X2FsbG9jKCZtbSwgb3JkZXIpOworCQlp ZiAoSVNfRVJSKGJsb2NrKSkgeworCQkJcHJfaW5mbygiYnVkZHlfYWxsb2MgKHJlYWxsb2MpIGhp dCAtRU5PTUVNIHdpdGggb3JkZXI9JWRcbiIsCisJCQkJb3JkZXIpOworCQkJZXJyID0gUFRSX0VS UihibG9jayk7CisJCQlnb3RvIGVycjsKKwkJfQorCQlpOTE1X2J1ZGR5X2ZyZWUoJm1tLCBibG9j ayk7CisJCW9yZGVyKys7CisJfQorCisJLyogVG8gY29uZmlybSwgbm93IHRoZSB3aG9sZSBtbSBz aG91bGQgYmUgYXZhaWxhYmxlICovCisJYmxvY2sgPSBpOTE1X2J1ZGR5X2FsbG9jKCZtbSwgbWF4 X29yZGVyKTsKKwlpZiAoSVNfRVJSKGJsb2NrKSkgeworCQlwcl9pbmZvKCJidWRkeV9hbGxvYyAo cmVhbGxvYykgaGl0IC1FTk9NRU0gd2l0aCBvcmRlcj0lZFxuIiwKKwkJCW1heF9vcmRlcik7CisJ CWVyciA9IFBUUl9FUlIoYmxvY2spOworCQlnb3RvIGVycjsKKwl9CisJaTkxNV9idWRkeV9mcmVl KCZtbSwgYmxvY2spOworCitlcnI6CisJaTkxNV9idWRkeV9mcmVlX2xpc3QoJm1tLCAmYmxvY2tz KTsKKwlpOTE1X2J1ZGR5X2ZpbmkoJm1tKTsKKwlyZXR1cm4gZXJyOworfQorCitzdGF0aWMgaW50 IGlndF9idWRkeV9hbGxvY19vcHRpbWlzdGljKHZvaWQgKmFyZykKK3sKKwljb25zdCBpbnQgbWF4 X29yZGVyID0gMTY7CisJc3RydWN0IGk5MTVfYnVkZHlfYmxvY2sgKmJsb2NrOworCXN0cnVjdCBp OTE1X2J1ZGR5X21tIG1tOworCUxJU1RfSEVBRChibG9ja3MpOworCWludCBvcmRlcjsKKwlpbnQg ZXJyOworCisJLyoKKwkgKiBDcmVhdGUgYSBtbSB3aXRoIG9uZSBibG9jayBvZiBlYWNoIG9yZGVy IGF2YWlsYWJsZSwgYW5kCisJICogdHJ5IHRvIGFsbG9jYXRlIHRoZW0gYWxsLgorCSAqLworCisJ ZXJyID0gaTkxNV9idWRkeV9pbml0KCZtbSwKKwkJCSAgICAgIFBBR0VfU0laRSAqICgoMSA8PCAo bWF4X29yZGVyICsgMSkpIC0gMSksCisJCQkgICAgICBQQUdFX1NJWkUpOworCWlmIChlcnIpIHsK KwkJcHJfZXJyKCJidWRkeV9pbml0IGZhaWxlZCglZClcbiIsIGVycik7CisJCXJldHVybiBlcnI7 CisJfQorCUdFTV9CVUdfT04obW0ubWF4X29yZGVyICE9IG1heF9vcmRlcik7CisKKwlmb3IgKG9y ZGVyID0gMDsgb3JkZXIgPD0gbWF4X29yZGVyOyBvcmRlcisrKSB7CisJCWJsb2NrID0gaTkxNV9i dWRkeV9hbGxvYygmbW0sIG9yZGVyKTsKKwkJaWYgKElTX0VSUihibG9jaykpIHsKKwkJCXByX2lu Zm8oImJ1ZGR5X2FsbG9jIGhpdCAtRU5PTUVNIHdpdGggb3JkZXI9JWRcbiIsCisJCQkJb3JkZXIp OworCQkJZXJyID0gUFRSX0VSUihibG9jayk7CisJCQlnb3RvIGVycjsKKwkJfQorCisJCWxpc3Rf YWRkX3RhaWwoJmJsb2NrLT5saW5rLCAmYmxvY2tzKTsKKwl9CisKKwkvKiBTaG91bGQgYmUgY29t cGxldGVseSBmdWxsISAqLworCWJsb2NrID0gaTkxNV9idWRkeV9hbGxvYygmbW0sIDApOworCWlm ICghSVNfRVJSKGJsb2NrKSkgeworCQlwcl9pbmZvKCJidWRkeV9hbGxvYyB1bmV4cGVjdGVkbHkg c3VjY2VlZGVkLCBpdCBzaG91bGQgYmUgZnVsbCEiKTsKKwkJbGlzdF9hZGRfdGFpbCgmYmxvY2st PmxpbmssICZibG9ja3MpOworCQllcnIgPSAtRUlOVkFMOworCQlnb3RvIGVycjsKKwl9CisKK2Vy cjoKKwlpOTE1X2J1ZGR5X2ZyZWVfbGlzdCgmbW0sICZibG9ja3MpOworCWk5MTVfYnVkZHlfZmlu aSgmbW0pOworCXJldHVybiBlcnI7Cit9CisKK3N0YXRpYyBpbnQgaWd0X2J1ZGR5X2FsbG9jX3Bh dGhvbG9naWNhbCh2b2lkICphcmcpCit7CisJY29uc3QgaW50IG1heF9vcmRlciA9IDE2OworCXN0 cnVjdCBpOTE1X2J1ZGR5X2Jsb2NrICpibG9jazsKKwlzdHJ1Y3QgaTkxNV9idWRkeV9tbSBtbTsK KwlMSVNUX0hFQUQoYmxvY2tzKTsKKwlMSVNUX0hFQUQoaG9sZXMpOworCWludCBvcmRlciwgdG9w OworCWludCBlcnI7CisKKwkvKgorCSAqIENyZWF0ZSBhIHBvdC1zaXplZCBtbSwgdGhlbiBhbGxv Y2F0ZSBvbmUgb2YgZWFjaCBwb3NzaWJsZQorCSAqIG9yZGVyIHdpdGhpbi4gVGhpcyBzaG91bGQg bGVhdmUgdGhlIG1tIHdpdGggZXhhY3RseSBvbmUKKwkgKiBwYWdlIGxlZnQuIEZyZWUgdGhlIGxh cmdlc3QgYmxvY2ssIHRoZW4gd2hpdHRsZSBkb3duIGFnYWluLgorCSAqIEV2ZW50dWFsbHkgd2Ug d2lsbCBoYXZlIGEgZnVsbHkgNTAlIGZyYWdtZW50ZWQgbW0uCisJICovCisKKwllcnIgPSBpOTE1 X2J1ZGR5X2luaXQoJm1tLCBQQUdFX1NJWkUgPDwgbWF4X29yZGVyLCBQQUdFX1NJWkUpOworCWlm IChlcnIpIHsKKwkJcHJfZXJyKCJidWRkeV9pbml0IGZhaWxlZCglZClcbiIsIGVycik7CisJCXJl dHVybiBlcnI7CisJfQorCUdFTV9CVUdfT04obW0ubWF4X29yZGVyICE9IG1heF9vcmRlcik7CisK Kwlmb3IgKHRvcCA9IG1heF9vcmRlcjsgdG9wOyB0b3AtLSkgeworCQkvKiBNYWtlIHJvb20gYnkg ZnJlZWluZyB0aGUgbGFyZ2VzdCBhbGxvY2F0ZWQgYmxvY2sgKi8KKwkJYmxvY2sgPSBsaXN0X2Zp cnN0X2VudHJ5X29yX251bGwoJmJsb2NrcywgdHlwZW9mKCpibG9jayksIGxpbmspOworCQlpZiAo YmxvY2spIHsKKwkJCWxpc3RfZGVsKCZibG9jay0+bGluayk7CisJCQlpOTE1X2J1ZGR5X2ZyZWUo Jm1tLCBibG9jayk7CisJCX0KKworCQlmb3IgKG9yZGVyID0gdG9wOyBvcmRlci0tOyApIHsKKwkJ CWJsb2NrID0gaTkxNV9idWRkeV9hbGxvYygmbW0sIG9yZGVyKTsKKwkJCWlmIChJU19FUlIoYmxv Y2spKSB7CisJCQkJcHJfaW5mbygiYnVkZHlfYWxsb2MgaGl0IC1FTk9NRU0gd2l0aCBvcmRlcj0l ZCwgdG9wPSVkXG4iLAorCQkJCQlvcmRlciwgdG9wKTsKKwkJCQllcnIgPSBQVFJfRVJSKGJsb2Nr KTsKKwkJCQlnb3RvIGVycjsKKwkJCX0KKwkJCWxpc3RfYWRkX3RhaWwoJmJsb2NrLT5saW5rLCAm YmxvY2tzKTsKKwkJfQorCisJCS8qIFRoZXJlIHNob3VsZCBiZSBvbmUgZmluYWwgcGFnZSBmb3Ig dGhpcyBzdWItYWxsb2NhdGlvbiAqLworCQlibG9jayA9IGk5MTVfYnVkZHlfYWxsb2MoJm1tLCAw KTsKKwkJaWYgKElTX0VSUihibG9jaykpIHsKKwkJCXByX2luZm8oImJ1ZGR5X2FsbG9jIGhpdCAt RU5PTUVNIGZvciBob2xlXG4iKTsKKwkJCWVyciA9IFBUUl9FUlIoYmxvY2spOworCQkJZ290byBl cnI7CisJCX0KKwkJbGlzdF9hZGRfdGFpbCgmYmxvY2stPmxpbmssICZob2xlcyk7CisKKwkJYmxv Y2sgPSBpOTE1X2J1ZGR5X2FsbG9jKCZtbSwgdG9wKTsKKwkJaWYgKCFJU19FUlIoYmxvY2spKSB7 CisJCQlwcl9pbmZvKCJidWRkeV9hbGxvYyB1bmV4cGVjdGVkbHkgc3VjY2VlZGVkIGF0IHRvcC1v cmRlciAlZC8lZCwgaXQgc2hvdWxkIGJlIGZ1bGwhIiwKKwkJCQl0b3AsIG1heF9vcmRlcik7CisJ CQlsaXN0X2FkZF90YWlsKCZibG9jay0+bGluaywgJmJsb2Nrcyk7CisJCQllcnIgPSAtRUlOVkFM OworCQkJZ290byBlcnI7CisJCX0KKwl9CisKKwlpOTE1X2J1ZGR5X2ZyZWVfbGlzdCgmbW0sICZo b2xlcyk7CisKKwkvKiBOb3RoaW5nIGxhcmdlciB0aGFuIGJsb2NrcyBvZiBjaHVua19zaXplIG5v dyBhdmFpbGFibGUgKi8KKwlmb3IgKG9yZGVyID0gMTsgb3JkZXIgPD0gbWF4X29yZGVyOyBvcmRl cisrKSB7CisJCWJsb2NrID0gaTkxNV9idWRkeV9hbGxvYygmbW0sIG9yZGVyKTsKKwkJaWYgKCFJ U19FUlIoYmxvY2spKSB7CisJCQlwcl9pbmZvKCJidWRkeV9hbGxvYyB1bmV4cGVjdGVkbHkgc3Vj Y2VlZGVkIGF0IG9yZGVyICVkLCBpdCBzaG91bGQgYmUgZnVsbCEiLAorCQkJCW9yZGVyKTsKKwkJ CWxpc3RfYWRkX3RhaWwoJmJsb2NrLT5saW5rLCAmYmxvY2tzKTsKKwkJCWVyciA9IC1FSU5WQUw7 CisJCQlnb3RvIGVycjsKKwkJfQorCX0KKworZXJyOgorCWxpc3Rfc3BsaWNlX3RhaWwoJmhvbGVz LCAmYmxvY2tzKTsKKwlpOTE1X2J1ZGR5X2ZyZWVfbGlzdCgmbW0sICZibG9ja3MpOworCWk5MTVf YnVkZHlfZmluaSgmbW0pOworCXJldHVybiBlcnI7Cit9CisKK3N0YXRpYyBpbnQgaWd0X2J1ZGR5 X2FsbG9jX3JhbmdlKHZvaWQgKmFyZykKK3sKKwlzdHJ1Y3QgaTkxNV9idWRkeV9tbSBtbTsKKwl1 bnNpZ25lZCBsb25nIHBhZ2VfbnVtOworCUxJU1RfSEVBRChibG9ja3MpOworCXU2NCBjaHVua19z aXplOworCXU2NCBvZmZzZXQ7CisJdTY0IHNpemU7CisJdTY0IHJlbTsKKwlpbnQgZXJyOworCisJ aWd0X21tX2NvbmZpZygmc2l6ZSwgJmNodW5rX3NpemUpOworCisJcHJfaW5mbygiYnVkZHlfaW5p dCB3aXRoIHNpemU9JWxseCwgY2h1bmtfc2l6ZT0lbGx4XG4iLCBzaXplLCBjaHVua19zaXplKTsK KworCWVyciA9IGk5MTVfYnVkZHlfaW5pdCgmbW0sIHNpemUsIGNodW5rX3NpemUpOworCWlmIChl cnIpIHsKKwkJcHJfZXJyKCJidWRkeV9pbml0IGZhaWxlZCglZClcbiIsIGVycik7CisJCXJldHVy biBlcnI7CisJfQorCisJZXJyID0gaWd0X2NoZWNrX21tKCZtbSk7CisJaWYgKGVycikgeworCQlw cl9lcnIoInByZS1tbSBjaGVjayBmYWlsZWQsIGFib3J0LCBhYm9ydCwgYWJvcnQhXG4iKTsKKwkJ Z290byBlcnJfZmluaTsKKwl9CisKKwlyZW0gPSBtbS5zaXplOworCW9mZnNldCA9IDA7CisKKwlm b3JfZWFjaF9wcmltZV9udW1iZXJfZnJvbShwYWdlX251bSwgMSwgVUxPTkdfTUFYIC0gMSkgewor CQlzdHJ1Y3QgaTkxNV9idWRkeV9ibG9jayAqYmxvY2s7CisJCUxJU1RfSEVBRCh0bXApOworCisJ CXNpemUgPSBtaW4ocGFnZV9udW0gKiBtbS5jaHVua19zaXplLCByZW0pOworCisJCWVyciA9IGk5 MTVfYnVkZHlfYWxsb2NfcmFuZ2UoJm1tLCAmdG1wLCBvZmZzZXQsIHNpemUpOworCQlpZiAoZXJy KSB7CisJCQlpZiAoZXJyID09IC1FTk9NRU0pIHsKKwkJCQlwcl9pbmZvKCJhbGxvY19yYW5nZSBo aXQgLUVOT01FTSB3aXRoIHNpemU9JWxseFxuIiwKKwkJCQkJc2l6ZSk7CisJCQl9IGVsc2Ugewor CQkJCXByX2VycigiYWxsb2NfcmFuZ2Ugd2l0aCBvZmZzZXQ9JWxseCwgc2l6ZT0lbGx4IGZhaWxl ZCglZClcbiIsCisJCQkJICAgICAgIG9mZnNldCwgc2l6ZSwgZXJyKTsKKwkJCX0KKworCQkJYnJl YWs7CisJCX0KKworCQlibG9jayA9IGxpc3RfZmlyc3RfZW50cnlfb3JfbnVsbCgmdG1wLAorCQkJ CQkJIHN0cnVjdCBpOTE1X2J1ZGR5X2Jsb2NrLAorCQkJCQkJIGxpbmspOworCQlpZiAoIWJsb2Nr KSB7CisJCQlwcl9lcnIoImFsbG9jX3JhbmdlIGhhcyBubyBibG9ja3NcbiIpOworCQkJZXJyID0g LUVJTlZBTDsKKwkJCWJyZWFrOworCQl9CisKKwkJaWYgKGk5MTVfYnVkZHlfYmxvY2tfb2Zmc2V0 KGJsb2NrKSAhPSBvZmZzZXQpIHsKKwkJCXByX2VycigiYWxsb2NfcmFuZ2Ugc3RhcnQgb2Zmc2V0 IG1pc21hdGNoLCBmb3VuZD0lbGx4LCBleHBlY3RlZD0lbGx4XG4iLAorCQkJICAgICAgIGk5MTVf YnVkZHlfYmxvY2tfb2Zmc2V0KGJsb2NrKSwgb2Zmc2V0KTsKKwkJCWVyciA9IC1FSU5WQUw7CisJ CX0KKworCQlpZiAoIWVycikKKwkJCWVyciA9IGlndF9jaGVja19ibG9ja3MoJm1tLCAmdG1wLCBz aXplLCB0cnVlKTsKKworCQlsaXN0X3NwbGljZV90YWlsKCZ0bXAsICZibG9ja3MpOworCisJCWlm IChlcnIpCisJCQlicmVhazsKKworCQlvZmZzZXQgKz0gc2l6ZTsKKworCQlyZW0gLT0gc2l6ZTsK KwkJaWYgKCFyZW0pCisJCQlicmVhazsKKworCQljb25kX3Jlc2NoZWQoKTsKKwl9CisKKwlpZiAo ZXJyID09IC1FTk9NRU0pCisJCWVyciA9IDA7CisKKwlpOTE1X2J1ZGR5X2ZyZWVfbGlzdCgmbW0s ICZibG9ja3MpOworCisJaWYgKCFlcnIpIHsKKwkJZXJyID0gaWd0X2NoZWNrX21tKCZtbSk7CisJ CWlmIChlcnIpCisJCQlwcl9lcnIoInBvc3QtbW0gY2hlY2sgZmFpbGVkXG4iKTsKKwl9CisKK2Vy cl9maW5pOgorCWk5MTVfYnVkZHlfZmluaSgmbW0pOworCisJcmV0dXJuIGVycjsKK30KKworc3Rh dGljIGludCBpZ3RfYnVkZHlfYWxsb2NfbGltaXQodm9pZCAqYXJnKQoreworCXN0cnVjdCBpOTE1 X2J1ZGR5X2Jsb2NrICpibG9jazsKKwlzdHJ1Y3QgaTkxNV9idWRkeV9tbSBtbTsKKwljb25zdCB1 NjQgc2l6ZSA9IFU2NF9NQVg7CisJaW50IGVycjsKKworCWVyciA9IGk5MTVfYnVkZHlfaW5pdCgm bW0sIHNpemUsIFBBR0VfU0laRSk7CisJaWYgKGVycikKKwkJcmV0dXJuIGVycjsKKworCWlmICht bS5tYXhfb3JkZXIgIT0gSTkxNV9CVUREWV9NQVhfT1JERVIpIHsKKwkJcHJfZXJyKCJtbS5tYXhf b3JkZXIoJWQpICE9ICVkXG4iLAorCQkgICAgICAgbW0ubWF4X29yZGVyLCBJOTE1X0JVRERZX01B WF9PUkRFUik7CisJCWVyciA9IC1FSU5WQUw7CisJCWdvdG8gb3V0X2Zpbmk7CisJfQorCisJYmxv Y2sgPSBpOTE1X2J1ZGR5X2FsbG9jKCZtbSwgbW0ubWF4X29yZGVyKTsKKwlpZiAoSVNfRVJSKGJs b2NrKSkgeworCQllcnIgPSBQVFJfRVJSKGJsb2NrKTsKKwkJZ290byBvdXRfZmluaTsKKwl9CisK KwlpZiAoaTkxNV9idWRkeV9ibG9ja19vcmRlcihibG9jaykgIT0gbW0ubWF4X29yZGVyKSB7CisJ CXByX2VycigiYmxvY2sgb3JkZXIoJWQpICE9ICVkXG4iLAorCQkgICAgICAgaTkxNV9idWRkeV9i bG9ja19vcmRlcihibG9jayksIG1tLm1heF9vcmRlcik7CisJCWVyciA9IC1FSU5WQUw7CisJCWdv dG8gb3V0X2ZyZWU7CisJfQorCisJaWYgKGk5MTVfYnVkZHlfYmxvY2tfc2l6ZSgmbW0sIGJsb2Nr KSAhPQorCSAgICBCSVRfVUxMKG1tLm1heF9vcmRlcikgKiBQQUdFX1NJWkUpIHsKKwkJcHJfZXJy KCJibG9jayBzaXplKCVsbHUpICE9ICVsbHVcbiIsCisJCSAgICAgICBpOTE1X2J1ZGR5X2Jsb2Nr X3NpemUoJm1tLCBibG9jayksCisJCSAgICAgICBCSVRfVUxMKG1tLm1heF9vcmRlcikgKiBQQUdF X1NJWkUpOworCQllcnIgPSAtRUlOVkFMOworCQlnb3RvIG91dF9mcmVlOworCX0KKworb3V0X2Zy ZWU6CisJaTkxNV9idWRkeV9mcmVlKCZtbSwgYmxvY2spOworb3V0X2Zpbmk6CisJaTkxNV9idWRk eV9maW5pKCZtbSk7CisJcmV0dXJuIGVycjsKK30KKworaW50IGk5MTVfYnVkZHlfbW9ja19zZWxm dGVzdHModm9pZCkKK3sKKwlzdGF0aWMgY29uc3Qgc3RydWN0IGk5MTVfc3VidGVzdCB0ZXN0c1td ID0geworCQlTVUJURVNUKGlndF9idWRkeV9hbGxvY19wZXNzaW1pc3RpYyksCisJCVNVQlRFU1Qo aWd0X2J1ZGR5X2FsbG9jX29wdGltaXN0aWMpLAorCQlTVUJURVNUKGlndF9idWRkeV9hbGxvY19w YXRob2xvZ2ljYWwpLAorCQlTVUJURVNUKGlndF9idWRkeV9hbGxvY19zbW9rZSksCisJCVNVQlRF U1QoaWd0X2J1ZGR5X2FsbG9jX3JhbmdlKSwKKwkJU1VCVEVTVChpZ3RfYnVkZHlfYWxsb2NfbGlt aXQpLAorCX07CisKKwlyZXR1cm4gaTkxNV9zdWJ0ZXN0cyh0ZXN0cywgTlVMTCk7Cit9Ci0tIAoy LjI2LjMKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCklu dGVsLWdmeCBtYWlsaW5nIGxpc3QKSW50ZWwtZ2Z4QGxpc3RzLmZyZWVkZXNrdG9wLm9yZwpodHRw czovL2xpc3RzLmZyZWVkZXNrdG9wLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2ludGVsLWdmeAo=