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 Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DCA48C433F5 for ; Thu, 7 Apr 2022 03:17:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240140AbiDGDTf (ORCPT ); Wed, 6 Apr 2022 23:19:35 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44276 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239965AbiDGDS0 (ORCPT ); Wed, 6 Apr 2022 23:18:26 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 02505AACA1 for ; Wed, 6 Apr 2022 20:16:06 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id p15-20020a25818f000000b0063daf5f7957so3275140ybk.12 for ; Wed, 06 Apr 2022 20:16:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc:content-transfer-encoding; bh=2FVgzTnmb2JeqfQyoTBFNGi6zNu2jJ43Oxn+apD3DdM=; b=hmkrwsxtdydOk31u9v7YwlgLkL4/gZGYZUGZXCUEg69rTyuixL+pnWsIkFA0IB/0PE g2syqfrTzL6xNqJyxOZmRCpShXAvslX2buMI85IfypBDjMAp4WhSyymedXMFf3Dz1l6l /quvMcJLBkI4Nmsf2h79u21Gd0YzwDqFxYJUmZfIP8Ucg/KZQ+mSK1bBuyFdh+Pm+DeC VCgB1rX+RhWnJxxEjzTnNFgVtVRHLbsearw0unTTo8iiSk9KYvj41UyvnyswJn87DTAU 1iChhmiL5w3jYToh9GeD8agkee1Ok8MHxtK5sdg+31o9kpwmAycCzvUNv7jIsCmGifyq gY4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc:content-transfer-encoding; bh=2FVgzTnmb2JeqfQyoTBFNGi6zNu2jJ43Oxn+apD3DdM=; b=U9Gol9TEYkjmolTsZFCfdp+bdKKRhIKk/FBW7dS9j3ELhGrzKJJJVSucoVomUu+9cD MYv1Bpd4DkqYFhJWVRVnhXImU1C/9+9+lKhjwnsR8/B6uKEh0ITBORPOa4b9YqowTyjn Te7G2sAScLCH++cVcK+hF+WyLAwOzI6dQzb/mKlpV++WReDQsxFXrAD3IjfVDQp7h29P 80Zeo6xP8+6akGgr34t+ZyF009c9DhCROEyF9iBzg2fX/uf6UFZmT2fVTmG44pMGhMPU EXCLtR2zI5qq10nGo+4a7h0P3+mEVzNx8s4/gnJEzQHHj4NBmyOf0MauqW+hnewUkJFf EzeA== X-Gm-Message-State: AOAM533tqqHBWw6gqklYd2oBIbtJN+N0DDr0SUx7f5m3G4uU/MYt6DFs W1aiiwgm83cNsF7jUECdriLok3oL2Iw= X-Google-Smtp-Source: ABdhPJwb/kFQSSyXRQuXuCiEhLpFhfCD+ZGa12jHRxQR469lOgwSlQltO6Amf8P1HoYy/R9f+MpnivDRFHM= X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:9ea2:c755:ae22:6862]) (user=yuzhao job=sendgmr) by 2002:a25:59c3:0:b0:63d:8ccc:37b0 with SMTP id n186-20020a2559c3000000b0063d8ccc37b0mr8744785ybb.612.1649301365790; Wed, 06 Apr 2022 20:16:05 -0700 (PDT) Date: Wed, 6 Apr 2022 21:15:18 -0600 In-Reply-To: <20220407031525.2368067-1-yuzhao@google.com> Message-Id: <20220407031525.2368067-7-yuzhao@google.com> Mime-Version: 1.0 References: <20220407031525.2368067-1-yuzhao@google.com> X-Mailer: git-send-email 2.35.1.1094.g7c7d902a7c-goog Subject: [PATCH v10 06/14] mm: multi-gen LRU: minimal implementation From: Yu Zhao To: Stephen Rothwell , linux-mm@kvack.org Cc: Andi Kleen , Andrew Morton , Aneesh Kumar , Barry Song <21cnbao@gmail.com>, Catalin Marinas , Dave Hansen , Hillf Danton , Jens Axboe , Jesse Barnes , Johannes Weiner , Jonathan Corbet , Linus Torvalds , Matthew Wilcox , Mel Gorman , Michael Larabel , Michal Hocko , Mike Rapoport , Rik van Riel , Vlastimil Babka , Will Deacon , Ying Huang , linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, page-reclaim@google.com, x86@kernel.org, Yu Zhao , Brian Geffon , Jan Alexander Steffens , Oleksandr Natalenko , Steven Barrett , Suleiman Souhlal , Daniel Byrne , Donald Carr , "=?UTF-8?q?Holger=20Hoffst=C3=A4tte?=" , Konstantin Kharlamov , Shuang Zhai , Sofia Trinh , Vaibhav Jain Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org To avoid confusion, the terms "promotion" and "demotion" will be applied to the multi-gen LRU, as a new convention; the terms "activation" and "deactivation" will be applied to the active/inactive LRU, as usual. The aging produces young generations. Given an lruvec, it increments max_seq when max_seq-min_seq+1 approaches MIN_NR_GENS. The aging promotes hot pages to the youngest generation when it finds them accessed through page tables; the demotion of cold pages happens consequently when it increments max_seq. The aging has the complexity O(nr_hot_pages), since it is only interested in hot pages. Promotion in the aging path does not require any LRU list operations, only the updates of the gen counter and lrugen->nr_pages[]; demotion, unless as the result of the increment of max_seq, requires LRU list operations, e.g., lru_deactivate_fn(). The eviction consumes old generations. Given an lruvec, it increments min_seq when the lists indexed by min_seq%MAX_NR_GENS become empty. A feedback loop modeled after the PID controller monitors refaults over anon and file types and decides which type to evict when both types are available from the same generation. Each generation is divided into multiple tiers. Tiers represent different ranges of numbers of accesses through file descriptors. A page accessed N times through file descriptors is in tier order_base_2(N). Tiers do not have dedicated lrugen->lists[], only bits in folio->flags. In contrast to moving across generations, which requires the LRU lock, moving across tiers only involves operations on folio->flags. The feedback loop also monitors refaults over all tiers and decides when to protect pages in which tiers (N>1), using the first tier (N=3D0,1) as a baseline. The first tier contains single-use unmapped clean pages, which are most likely the best choices. The eviction moves a page to the next generation, i.e., min_seq+1, if the feedback loop decides so. This approach has the following advantages: 1. It removes the cost of activation in the buffered access path by inferring whether pages accessed multiple times through file descriptors are statistically hot and thus worth protecting in the eviction path. 2. It takes pages accessed through page tables into account and avoids overprotecting pages accessed multiple times through file descriptors. (Pages accessed through page tables are in the first tier, since N=3D0.) 3. More tiers provide better protection for pages accessed more than twice through file descriptors, when under heavy buffered I/O workloads. Server benchmark results: Single workload: fio (buffered I/O): +[40, 42]% IOPS BW 5.18-rc1: 2463k 9621MiB/s patch1-6: 3484k 13.3GiB/s Single workload: memcached (anon): +[44, 46]% Ops/sec KB/sec 5.18-rc1: 771403.27 30004.17 patch1-6: 1120643.70 43588.06 Configurations: CPU: two Xeon 6154 Mem: total 256G Node 1 was only used as a ram disk to reduce the variance in the results. patch drivers/block/brd.c < gfp_flags =3D GFP_NOIO | __GFP_ZERO | __GFP_HIGHMEM | __GFP_THISNODE= ; > page =3D alloc_pages_node(1, gfp_flags, 0); EOF cat >>/etc/systemd/system.conf <>/etc/memcached.conf </sys/fs/cgroup/user.slice/test/memory.max echo $$ >/sys/fs/cgroup/user.slice/test/cgroup.procs fio -name=3Dmglru --numjobs=3D72 --directory=3D/mnt --size=3D1408m \ --buffered=3D1 --ioengine=3Dio_uring --iodepth=3D128 \ --iodepth_batch_submit=3D32 --iodepth_batch_complete=3D32 \ --rw=3Drandread --random_distribution=3Drandom --norandommap \ --time_based --ramp_time=3D10m --runtime=3D5m --group_reporting cat memcached.sh modprobe brd rd_nr=3D1 rd_size=3D113246208 swapoff -a mkswap /dev/ram0 swapon /dev/ram0 memtier_benchmark -S /var/run/memcached/memcached.sock \ -P memcache_binary -n allkeys --key-minimum=3D1 \ --key-maximum=3D65000000 --key-pattern=3DP:P -c 1 -t 36 \ --ratio 1:0 --pipeline 8 -d 2000 memtier_benchmark -S /var/run/memcached/memcached.sock \ -P memcache_binary -n allkeys --key-minimum=3D1 \ --key-maximum=3D65000000 --key-pattern=3DR:R -c 1 -t 36 \ --ratio 0:1 --pipeline 8 --randomize --distinct-client-seed Client benchmark results: kswapd profiles: 5.18-rc1 40.53% page_vma_mapped_walk 20.37% lzo1x_1_do_compress (real work) 6.99% do_raw_spin_lock 3.93% _raw_spin_unlock_irq 2.08% vma_interval_tree_subtree_search 2.06% vma_interval_tree_iter_next 1.95% folio_referenced_one 1.93% anon_vma_interval_tree_iter_first 1.51% ptep_clear_flush 1.35% __anon_vma_interval_tree_subtree_search patch1-6 35.99% lzo1x_1_do_compress (real work) 19.40% page_vma_mapped_walk 6.31% _raw_spin_unlock_irq 3.95% do_raw_spin_lock 2.39% anon_vma_interval_tree_iter_first 2.25% ptep_clear_flush 1.92% __anon_vma_interval_tree_subtree_search 1.70% folio_referenced_one 1.68% __zram_bvec_write 1.43% anon_vma_interval_tree_iter_next Configurations: CPU: single Snapdragon 7c Mem: total 4G Chrome OS MemoryPressure [1] [1] https://chromium.googlesource.com/chromiumos/platform/tast-tests/ Signed-off-by: Yu Zhao Acked-by: Brian Geffon Acked-by: Jan Alexander Steffens (heftig) Acked-by: Oleksandr Natalenko Acked-by: Steven Barrett Acked-by: Suleiman Souhlal Tested-by: Daniel Byrne Tested-by: Donald Carr Tested-by: Holger Hoffst=C3=A4tte Tested-by: Konstantin Kharlamov Tested-by: Shuang Zhai Tested-by: Sofia Trinh Tested-by: Vaibhav Jain --- include/linux/mm_inline.h | 24 ++ include/linux/mmzone.h | 41 ++ kernel/bounds.c | 2 +- mm/Kconfig | 11 + mm/swap.c | 42 ++ mm/vmscan.c | 805 +++++++++++++++++++++++++++++++++++++- mm/workingset.c | 119 +++++- 7 files changed, 1040 insertions(+), 4 deletions(-) diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 9abd72a95462..8a8f87b72540 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h @@ -119,6 +119,19 @@ static inline int lru_gen_from_seq(unsigned long seq) return seq % MAX_NR_GENS; } =20 +static inline int lru_hist_from_seq(unsigned long seq) +{ + return seq % NR_HIST_GENS; +} + +static inline int lru_tier_from_refs(int refs) +{ + VM_BUG_ON(refs > BIT(LRU_REFS_WIDTH)); + + /* see the comment on MAX_NR_TIERS */ + return order_base_2(refs + 1); +} + static inline bool lru_gen_is_active(struct lruvec *lruvec, int gen) { unsigned long max_seq =3D lruvec->lrugen.max_seq; @@ -164,6 +177,15 @@ static inline void lru_gen_update_size(struct lruvec *= lruvec, struct folio *foli __update_lru_size(lruvec, lru, zone, -delta); return; } + + /* promotion */ + if (!lru_gen_is_active(lruvec, old_gen) && lru_gen_is_active(lruvec, new_= gen)) { + __update_lru_size(lruvec, lru, zone, -delta); + __update_lru_size(lruvec, lru + LRU_ACTIVE, zone, delta); + } + + /* demotion requires isolation, e.g., lru_deactivate_fn() */ + VM_BUG_ON(lru_gen_is_active(lruvec, old_gen) && !lru_gen_is_active(lruvec= , new_gen)); } =20 static inline bool lru_gen_add_folio(struct lruvec *lruvec, struct folio *= folio, bool reclaiming) @@ -229,6 +251,8 @@ static inline bool lru_gen_del_folio(struct lruvec *lru= vec, struct folio *folio, gen =3D ((new_flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1; =20 new_flags &=3D ~LRU_GEN_MASK; + if (!(new_flags & BIT(PG_referenced))) + new_flags &=3D ~(LRU_REFS_MASK | LRU_REFS_FLAGS); /* for shrink_page_list() */ if (reclaiming) new_flags &=3D ~(BIT(PG_referenced) | BIT(PG_reclaim)); diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index bde05427e2bb..c8a7ceee7a0a 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -347,12 +347,34 @@ enum lruvec_flags { #define MIN_NR_GENS 2U #define MAX_NR_GENS 4U =20 +/* + * Each generation is divided into multiple tiers. Tiers represent differe= nt + * ranges of numbers of accesses through file descriptors. A page accessed= N + * times through file descriptors is in tier order_base_2(N). A page in th= e + * first tier (N=3D0,1) is marked by PG_referenced unless it was faulted i= n + * though page tables or read ahead. A page in any other tier (N>1) is mar= ked + * by PG_referenced and PG_workingset. + * + * In contrast to moving across generations which requires the LRU lock, m= oving + * across tiers only requires operations on folio->flags and therefore has= a + * negligible cost in the buffered access path. In the eviction path, + * comparisons of refaulted/(evicted+protected) from the first tier and th= e + * rest infer whether pages accessed multiple times through file descripto= rs + * are statistically hot and thus worth protecting. + * + * MAX_NR_TIERS is set to 4 so that the multi-gen LRU can support twice of= the + * categories of the active/inactive LRU when keeping track of accesses th= rough + * file descriptors. It requires MAX_NR_TIERS-2 additional bits in folio->= flags. + */ +#define MAX_NR_TIERS 4U + #ifndef __GENERATING_BOUNDS_H =20 struct lruvec; =20 #define LRU_GEN_MASK ((BIT(LRU_GEN_WIDTH) - 1) << LRU_GEN_PGOFF) #define LRU_REFS_MASK ((BIT(LRU_REFS_WIDTH) - 1) << LRU_REFS_PGOFF) +#define LRU_REFS_FLAGS (BIT(PG_referenced) | BIT(PG_workingset)) =20 #ifdef CONFIG_LRU_GEN =20 @@ -361,6 +383,16 @@ enum { LRU_GEN_FILE, }; =20 +#define MIN_LRU_BATCH BITS_PER_LONG +#define MAX_LRU_BATCH (MIN_LRU_BATCH * 128) + +/* whether to keep historical stats from evicted generations */ +#ifdef CONFIG_LRU_GEN_STATS +#define NR_HIST_GENS MAX_NR_GENS +#else +#define NR_HIST_GENS 1U +#endif + /* * The youngest generation number is stored in max_seq for both anon and f= ile * types as they are aged on an equal footing. The oldest generation numbe= rs are @@ -380,6 +412,15 @@ struct lru_gen_struct { struct list_head lists[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES]; /* the sizes of the above lists */ unsigned long nr_pages[MAX_NR_GENS][ANON_AND_FILE][MAX_NR_ZONES]; + /* the exponential moving average of refaulted */ + unsigned long avg_refaulted[ANON_AND_FILE][MAX_NR_TIERS]; + /* the exponential moving average of evicted+protected */ + unsigned long avg_total[ANON_AND_FILE][MAX_NR_TIERS]; + /* the first tier doesn't need protection, hence the minus one */ + unsigned long protected[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS - 1]; + /* can be modified without holding the LRU lock */ + atomic_long_t evicted[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS]; + atomic_long_t refaulted[NR_HIST_GENS][ANON_AND_FILE][MAX_NR_TIERS]; }; =20 void lru_gen_init_lruvec(struct lruvec *lruvec); diff --git a/kernel/bounds.c b/kernel/bounds.c index e08fb89f87f4..10dd9e6b03e5 100644 --- a/kernel/bounds.c +++ b/kernel/bounds.c @@ -24,7 +24,7 @@ int main(void) DEFINE(SPINLOCK_SIZE, sizeof(spinlock_t)); #ifdef CONFIG_LRU_GEN DEFINE(LRU_GEN_WIDTH, order_base_2(MAX_NR_GENS + 1)); - DEFINE(LRU_REFS_WIDTH, 0); + DEFINE(LRU_REFS_WIDTH, MAX_NR_TIERS - 2); #else DEFINE(LRU_GEN_WIDTH, 0); DEFINE(LRU_REFS_WIDTH, 0); diff --git a/mm/Kconfig b/mm/Kconfig index 4595fc654181..c40777d098a8 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -909,6 +909,7 @@ config ANON_VMA_NAME area from being merged with adjacent virtual memory areas due to the difference in their name. =20 +# multi-gen LRU { config LRU_GEN bool "Multi-Gen LRU" depends on MMU @@ -917,6 +918,16 @@ config LRU_GEN help A high performance LRU implementation to overcommit memory. =20 +config LRU_GEN_STATS + bool "Full stats for debugging" + depends on LRU_GEN + help + Do not enable this option unless you plan to look at historical stats + from evicted generations for debugging purpose. + + This option has a per-memcg and per-node memory overhead. +# } + source "mm/damon/Kconfig" =20 endmenu diff --git a/mm/swap.c b/mm/swap.c index a6870ba0bd83..6a5203f18b0a 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -405,6 +405,43 @@ static void __lru_cache_activate_folio(struct folio *f= olio) local_unlock(&lru_pvecs.lock); } =20 +#ifdef CONFIG_LRU_GEN +static void folio_inc_refs(struct folio *folio) +{ + unsigned long refs; + unsigned long old_flags, new_flags; + + if (folio_test_unevictable(folio)) + return; + + /* see the comment on MAX_NR_TIERS */ + do { + new_flags =3D old_flags =3D READ_ONCE(folio->flags); + + if (!(new_flags & BIT(PG_referenced))) { + new_flags |=3D BIT(PG_referenced); + continue; + } + + if (!(new_flags & BIT(PG_workingset))) { + new_flags |=3D BIT(PG_workingset); + continue; + } + + refs =3D new_flags & LRU_REFS_MASK; + refs =3D min(refs + BIT(LRU_REFS_PGOFF), LRU_REFS_MASK); + + new_flags &=3D ~LRU_REFS_MASK; + new_flags |=3D refs; + } while (new_flags !=3D old_flags && + cmpxchg(&folio->flags, old_flags, new_flags) !=3D old_flags); +} +#else +static void folio_inc_refs(struct folio *folio) +{ +} +#endif /* CONFIG_LRU_GEN */ + /* * Mark a page as having seen activity. * @@ -417,6 +454,11 @@ static void __lru_cache_activate_folio(struct folio *f= olio) */ void folio_mark_accessed(struct folio *folio) { + if (lru_gen_enabled()) { + folio_inc_refs(folio); + return; + } + if (!folio_test_referenced(folio)) { folio_set_referenced(folio); } else if (folio_test_unevictable(folio)) { diff --git a/mm/vmscan.c b/mm/vmscan.c index 37dd5d1c3d07..bb3d705c5282 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1275,9 +1275,11 @@ static int __remove_mapping(struct address_space *ma= pping, struct folio *folio, =20 if (folio_test_swapcache(folio)) { swp_entry_t swap =3D folio_swap_entry(folio); - mem_cgroup_swapout(folio, swap); + + /* get a shadow entry before mem_cgroup_swapout() clears folio_memcg() *= / if (reclaimed && !mapping_exiting(mapping)) shadow =3D workingset_eviction(folio, target_memcg); + mem_cgroup_swapout(folio, swap); __delete_from_swap_cache(&folio->page, swap, shadow); xa_unlock_irq(&mapping->i_pages); put_swap_page(&folio->page, swap); @@ -2649,6 +2651,9 @@ static void prepare_scan_count(pg_data_t *pgdat, stru= ct scan_control *sc) unsigned long file; struct lruvec *target_lruvec; =20 + if (lru_gen_enabled()) + return; + target_lruvec =3D mem_cgroup_lruvec(sc->target_mem_cgroup, pgdat); =20 /* @@ -2974,11 +2979,38 @@ static bool can_age_anon_pages(struct pglist_data *= pgdat, * shorthand helpers *************************************************************************= *****/ =20 +#define DEFINE_MAX_SEQ(lruvec) \ + unsigned long max_seq =3D READ_ONCE((lruvec)->lrugen.max_seq) + +#define DEFINE_MIN_SEQ(lruvec) \ + unsigned long min_seq[ANON_AND_FILE] =3D { \ + READ_ONCE((lruvec)->lrugen.min_seq[LRU_GEN_ANON]), \ + READ_ONCE((lruvec)->lrugen.min_seq[LRU_GEN_FILE]), \ + } + #define for_each_gen_type_zone(gen, type, zone) \ for ((gen) =3D 0; (gen) < MAX_NR_GENS; (gen)++) \ for ((type) =3D 0; (type) < ANON_AND_FILE; (type)++) \ for ((zone) =3D 0; (zone) < MAX_NR_ZONES; (zone)++) =20 +static int folio_lru_gen(struct folio *folio) +{ + unsigned long flags =3D READ_ONCE(folio->flags); + + return ((flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1; +} + +static int folio_lru_tier(struct folio *folio) +{ + int refs; + unsigned long flags =3D READ_ONCE(folio->flags); + + refs =3D (flags & LRU_REFS_FLAGS) =3D=3D LRU_REFS_FLAGS ? + ((flags & LRU_REFS_MASK) >> LRU_REFS_PGOFF) + 1 : 0; + + return lru_tier_from_refs(refs); +} + static struct lruvec __maybe_unused *get_lruvec(struct mem_cgroup *memcg, = int nid) { struct pglist_data *pgdat =3D NODE_DATA(nid); @@ -2999,6 +3031,754 @@ static struct lruvec __maybe_unused *get_lruvec(str= uct mem_cgroup *memcg, int ni return pgdat ? &pgdat->__lruvec : NULL; } =20 +static int get_swappiness(struct lruvec *lruvec, struct scan_control *sc) +{ + struct mem_cgroup *memcg =3D lruvec_memcg(lruvec); + struct pglist_data *pgdat =3D lruvec_pgdat(lruvec); + + if (!can_demote(pgdat->node_id, sc) && + mem_cgroup_get_nr_swap_pages(memcg) < MIN_LRU_BATCH) + return 0; + + return mem_cgroup_swappiness(memcg); +} + +static int get_nr_gens(struct lruvec *lruvec, int type) +{ + return lruvec->lrugen.max_seq - lruvec->lrugen.min_seq[type] + 1; +} + +static bool __maybe_unused seq_is_valid(struct lruvec *lruvec) +{ + /* see the comment on lru_gen_struct */ + return get_nr_gens(lruvec, LRU_GEN_FILE) >=3D MIN_NR_GENS && + get_nr_gens(lruvec, LRU_GEN_FILE) <=3D get_nr_gens(lruvec, LRU_GEN= _ANON) && + get_nr_gens(lruvec, LRU_GEN_ANON) <=3D MAX_NR_GENS; +} + +/*************************************************************************= ***** + * refault feedback loop + *************************************************************************= *****/ + +/* + * A feedback loop based on Proportional-Integral-Derivative (PID) control= ler. + * + * The P term is refaulted/(evicted+protected) from a tier in the generati= on + * currently being evicted; the I term is the exponential moving average o= f the + * P term over the generations previously evicted, using the smoothing fac= tor + * 1/2; the D term isn't supported. + * + * The setpoint (SP) is always the first tier of one type; the process var= iable + * (PV) is either any tier of the other type or any other tier of the same + * type. + * + * The error is the difference between the SP and the PV; the correction i= s + * turn off protection when SP>PV or turn on protection when SPlrugen; + int hist =3D lru_hist_from_seq(lrugen->min_seq[type]); + + pos->refaulted =3D lrugen->avg_refaulted[type][tier] + + atomic_long_read(&lrugen->refaulted[hist][type][tier]); + pos->total =3D lrugen->avg_total[type][tier] + + atomic_long_read(&lrugen->evicted[hist][type][tier]); + if (tier) + pos->total +=3D lrugen->protected[hist][type][tier - 1]; + pos->gain =3D gain; +} + +static void reset_ctrl_pos(struct lruvec *lruvec, int type, bool carryover= ) +{ + int hist, tier; + struct lru_gen_struct *lrugen =3D &lruvec->lrugen; + bool clear =3D carryover ? NR_HIST_GENS =3D=3D 1 : NR_HIST_GENS > 1; + unsigned long seq =3D carryover ? lrugen->min_seq[type] : lrugen->max_seq= + 1; + + lockdep_assert_held(&lruvec->lru_lock); + + if (!carryover && !clear) + return; + + hist =3D lru_hist_from_seq(seq); + + for (tier =3D 0; tier < MAX_NR_TIERS; tier++) { + if (carryover) { + unsigned long sum; + + sum =3D lrugen->avg_refaulted[type][tier] + + atomic_long_read(&lrugen->refaulted[hist][type][tier]); + WRITE_ONCE(lrugen->avg_refaulted[type][tier], sum / 2); + + sum =3D lrugen->avg_total[type][tier] + + atomic_long_read(&lrugen->evicted[hist][type][tier]); + if (tier) + sum +=3D lrugen->protected[hist][type][tier - 1]; + WRITE_ONCE(lrugen->avg_total[type][tier], sum / 2); + } + + if (clear) { + atomic_long_set(&lrugen->refaulted[hist][type][tier], 0); + atomic_long_set(&lrugen->evicted[hist][type][tier], 0); + if (tier) + WRITE_ONCE(lrugen->protected[hist][type][tier - 1], 0); + } + } +} + +static bool positive_ctrl_err(struct ctrl_pos *sp, struct ctrl_pos *pv) +{ + /* + * Return true if the PV has a limited number of refaults or a lower + * refaulted/total than the SP. + */ + return pv->refaulted < MIN_LRU_BATCH || + pv->refaulted * (sp->total + MIN_LRU_BATCH) * sp->gain <=3D + (sp->refaulted + 1) * pv->total * pv->gain; +} + +/*************************************************************************= ***** + * the aging + *************************************************************************= *****/ + +static int folio_inc_gen(struct lruvec *lruvec, struct folio *folio, bool = reclaiming) +{ + unsigned long old_flags, new_flags; + int type =3D folio_is_file_lru(folio); + struct lru_gen_struct *lrugen =3D &lruvec->lrugen; + int new_gen, old_gen =3D lru_gen_from_seq(lrugen->min_seq[type]); + + do { + new_flags =3D old_flags =3D READ_ONCE(folio->flags); + VM_BUG_ON_FOLIO(!(new_flags & LRU_GEN_MASK), folio); + + new_gen =3D (old_gen + 1) % MAX_NR_GENS; + + new_flags &=3D ~LRU_GEN_MASK; + new_flags |=3D (new_gen + 1UL) << LRU_GEN_PGOFF; + new_flags &=3D ~(LRU_REFS_MASK | LRU_REFS_FLAGS); + /* for folio_end_writeback() */ + if (reclaiming) + new_flags |=3D BIT(PG_reclaim); + } while (cmpxchg(&folio->flags, old_flags, new_flags) !=3D old_flags); + + lru_gen_update_size(lruvec, folio, old_gen, new_gen); + + return new_gen; +} + +static void inc_min_seq(struct lruvec *lruvec) +{ + int type; + struct lru_gen_struct *lrugen =3D &lruvec->lrugen; + + VM_BUG_ON(!seq_is_valid(lruvec)); + + for (type =3D 0; type < ANON_AND_FILE; type++) { + if (get_nr_gens(lruvec, type) !=3D MAX_NR_GENS) + continue; + + reset_ctrl_pos(lruvec, type, true); + WRITE_ONCE(lrugen->min_seq[type], lrugen->min_seq[type] + 1); + } +} + +static bool try_to_inc_min_seq(struct lruvec *lruvec, bool can_swap) +{ + int gen, type, zone; + bool success =3D false; + struct lru_gen_struct *lrugen =3D &lruvec->lrugen; + DEFINE_MIN_SEQ(lruvec); + + VM_BUG_ON(!seq_is_valid(lruvec)); + + for (type =3D !can_swap; type < ANON_AND_FILE; type++) { + while (min_seq[type] + MIN_NR_GENS <=3D lrugen->max_seq) { + gen =3D lru_gen_from_seq(min_seq[type]); + + for (zone =3D 0; zone < MAX_NR_ZONES; zone++) { + if (!list_empty(&lrugen->lists[gen][type][zone])) + goto next; + } + + min_seq[type]++; + } +next: + ; + } + + /* see the comment on lru_gen_struct */ + if (can_swap) { + min_seq[LRU_GEN_ANON] =3D min(min_seq[LRU_GEN_ANON], min_seq[LRU_GEN_FIL= E]); + min_seq[LRU_GEN_FILE] =3D max(min_seq[LRU_GEN_ANON], lrugen->min_seq[LRU= _GEN_FILE]); + } + + for (type =3D !can_swap; type < ANON_AND_FILE; type++) { + if (min_seq[type] =3D=3D lrugen->min_seq[type]) + continue; + + reset_ctrl_pos(lruvec, type, true); + WRITE_ONCE(lrugen->min_seq[type], min_seq[type]); + success =3D true; + } + + return success; +} + +static void inc_max_seq(struct lruvec *lruvec, unsigned long max_seq) +{ + int prev, next; + int type, zone; + struct lru_gen_struct *lrugen =3D &lruvec->lrugen; + + spin_lock_irq(&lruvec->lru_lock); + + VM_BUG_ON(!seq_is_valid(lruvec)); + + if (max_seq !=3D lrugen->max_seq) + goto unlock; + + inc_min_seq(lruvec); + + /* + * Update the active/inactive LRU sizes for compatibility. Both sides of + * the current max_seq need to be covered, since max_seq+1 can overlap + * with min_seq[LRU_GEN_ANON] if swapping is constrained. And if they do + * overlap, cold/hot inversion happens. This can be solved by moving + * pages from min_seq to min_seq+1 but is omitted for simplicity. + */ + prev =3D lru_gen_from_seq(lrugen->max_seq - 1); + next =3D lru_gen_from_seq(lrugen->max_seq + 1); + + for (type =3D 0; type < ANON_AND_FILE; type++) { + for (zone =3D 0; zone < MAX_NR_ZONES; zone++) { + enum lru_list lru =3D type * LRU_INACTIVE_FILE; + long delta =3D lrugen->nr_pages[prev][type][zone] - + lrugen->nr_pages[next][type][zone]; + + if (!delta) + continue; + + __update_lru_size(lruvec, lru, zone, delta); + __update_lru_size(lruvec, lru + LRU_ACTIVE, zone, -delta); + } + } + + for (type =3D 0; type < ANON_AND_FILE; type++) + reset_ctrl_pos(lruvec, type, false); + + /* make sure preceding modifications appear */ + smp_store_release(&lrugen->max_seq, lrugen->max_seq + 1); +unlock: + spin_unlock_irq(&lruvec->lru_lock); +} + +static long get_nr_evictable(struct lruvec *lruvec, unsigned long max_seq, + unsigned long *min_seq, bool can_swap, bool *need_aging) +{ + int gen, type, zone; + long old =3D 0; + long young =3D 0; + long total =3D 0; + struct lru_gen_struct *lrugen =3D &lruvec->lrugen; + + for (type =3D !can_swap; type < ANON_AND_FILE; type++) { + unsigned long seq; + + for (seq =3D min_seq[type]; seq <=3D max_seq; seq++) { + long size =3D 0; + + gen =3D lru_gen_from_seq(seq); + + for (zone =3D 0; zone < MAX_NR_ZONES; zone++) + size +=3D READ_ONCE(lrugen->nr_pages[gen][type][zone]); + + total +=3D size; + if (seq =3D=3D max_seq) + young +=3D size; + if (seq + MIN_NR_GENS =3D=3D max_seq) + old +=3D size; + } + } + + /* + * The aging and the eviction is a typical producer-consumer model. The + * aging tries to be lazy to reduce the unnecessary overhead. On the + * other hand, the eviction stalls when the number of generations + * reaches MIN_NR_GENS. So ideally, there should be MIN_NR_GENS+1 + * generations, hence the first two if's. + * + * In addition, it's ideal to spread pages out evenly, meaning + * 1/(MIN_NR_GENS+1) of the total number of pages for each generation. A + * reasonable range for this average portion would [1/MIN_NR_GENS, + * 1/(MIN_NR_GENS+2)]. From the consumer's POV, the eviction only cares + * about the lower bound of cold pages, i.e., 1/(MIN_NR_GENS+2), whereas + * from the producer's POV, the aging only cares about the upper bound + * of hot pages, i.e., 1/MIN_NR_GENS. + */ + if (min_seq[LRU_GEN_FILE] + MIN_NR_GENS > max_seq) + *need_aging =3D true; + else if (min_seq[LRU_GEN_FILE] + MIN_NR_GENS < max_seq) + *need_aging =3D false; + else if (young * MIN_NR_GENS > total) + *need_aging =3D true; + else if (old * (MIN_NR_GENS + 2) < total) + *need_aging =3D true; + else + *need_aging =3D false; + + return total > 0 ? total : 0; +} + +static void age_lruvec(struct lruvec *lruvec, struct scan_control *sc) +{ + bool need_aging; + long nr_to_scan; + int swappiness =3D get_swappiness(lruvec, sc); + struct mem_cgroup *memcg =3D lruvec_memcg(lruvec); + DEFINE_MAX_SEQ(lruvec); + DEFINE_MIN_SEQ(lruvec); + + mem_cgroup_calculate_protection(NULL, memcg); + + if (mem_cgroup_below_min(memcg)) + return; + + nr_to_scan =3D get_nr_evictable(lruvec, max_seq, min_seq, swappiness, &ne= ed_aging); + if (!nr_to_scan) + return; + + nr_to_scan >>=3D sc->priority; + + if (!mem_cgroup_online(memcg)) + nr_to_scan++; + + if (nr_to_scan && need_aging && (!mem_cgroup_below_low(memcg) || sc->memc= g_low_reclaim)) + inc_max_seq(lruvec, max_seq); +} + +static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_contro= l *sc) +{ + struct mem_cgroup *memcg; + + VM_BUG_ON(!current_is_kswapd()); + + memcg =3D mem_cgroup_iter(NULL, NULL, NULL); + do { + struct lruvec *lruvec =3D mem_cgroup_lruvec(memcg, pgdat); + + age_lruvec(lruvec, sc); + + cond_resched(); + } while ((memcg =3D mem_cgroup_iter(NULL, memcg, NULL))); +} + +/*************************************************************************= ***** + * the eviction + *************************************************************************= *****/ + +static bool sort_folio(struct lruvec *lruvec, struct folio *folio, int tie= r_idx) +{ + bool success; + int gen =3D folio_lru_gen(folio); + int type =3D folio_is_file_lru(folio); + int zone =3D folio_zonenum(folio); + int tier =3D folio_lru_tier(folio); + int delta =3D folio_nr_pages(folio); + struct lru_gen_struct *lrugen =3D &lruvec->lrugen; + + VM_BUG_ON_FOLIO(gen >=3D MAX_NR_GENS, folio); + + if (!folio_evictable(folio)) { + success =3D lru_gen_del_folio(lruvec, folio, true); + VM_BUG_ON_FOLIO(!success, folio); + folio_set_unevictable(folio); + lruvec_add_folio(lruvec, folio); + __count_vm_events(UNEVICTABLE_PGCULLED, delta); + return true; + } + + if (type =3D=3D LRU_GEN_FILE && folio_test_anon(folio) && folio_test_dirt= y(folio)) { + success =3D lru_gen_del_folio(lruvec, folio, true); + VM_BUG_ON_FOLIO(!success, folio); + folio_set_swapbacked(folio); + lruvec_add_folio_tail(lruvec, folio); + return true; + } + + if (tier > tier_idx) { + int hist =3D lru_hist_from_seq(lrugen->min_seq[type]); + + gen =3D folio_inc_gen(lruvec, folio, false); + list_move_tail(&folio->lru, &lrugen->lists[gen][type][zone]); + + WRITE_ONCE(lrugen->protected[hist][type][tier - 1], + lrugen->protected[hist][type][tier - 1] + delta); + __mod_lruvec_state(lruvec, WORKINGSET_ACTIVATE_BASE + type, delta); + return true; + } + + if (folio_test_locked(folio) || folio_test_writeback(folio) || + (type =3D=3D LRU_GEN_FILE && folio_test_dirty(folio))) { + gen =3D folio_inc_gen(lruvec, folio, true); + list_move(&folio->lru, &lrugen->lists[gen][type][zone]); + return true; + } + + return false; +} + +static bool isolate_folio(struct lruvec *lruvec, struct folio *folio, stru= ct scan_control *sc) +{ + bool success; + + if (!sc->may_unmap && folio_mapped(folio)) + return false; + + if (!(sc->may_writepage && (sc->gfp_mask & __GFP_IO)) && + (folio_test_dirty(folio) || + (folio_test_anon(folio) && !folio_test_swapcache(folio)))) + return false; + + if (!folio_try_get(folio)) + return false; + + if (!folio_test_clear_lru(folio)) { + folio_put(folio); + return false; + } + + success =3D lru_gen_del_folio(lruvec, folio, true); + VM_BUG_ON_FOLIO(!success, folio); + + return true; +} + +static int scan_folios(struct lruvec *lruvec, struct scan_control *sc, + int type, int tier, struct list_head *list) +{ + int gen, zone; + enum vm_event_item item; + int sorted =3D 0; + int scanned =3D 0; + int isolated =3D 0; + int remaining =3D MAX_LRU_BATCH; + struct lru_gen_struct *lrugen =3D &lruvec->lrugen; + struct mem_cgroup *memcg =3D lruvec_memcg(lruvec); + + VM_BUG_ON(!list_empty(list)); + + if (get_nr_gens(lruvec, type) =3D=3D MIN_NR_GENS) + return 0; + + gen =3D lru_gen_from_seq(lrugen->min_seq[type]); + + for (zone =3D sc->reclaim_idx; zone >=3D 0; zone--) { + LIST_HEAD(moved); + int skipped =3D 0; + struct list_head *head =3D &lrugen->lists[gen][type][zone]; + + while (!list_empty(head)) { + struct folio *folio =3D lru_to_folio(head); + int delta =3D folio_nr_pages(folio); + + VM_BUG_ON_FOLIO(folio_test_unevictable(folio), folio); + VM_BUG_ON_FOLIO(folio_test_active(folio), folio); + VM_BUG_ON_FOLIO(folio_is_file_lru(folio) !=3D type, folio); + VM_BUG_ON_FOLIO(folio_zonenum(folio) !=3D zone, folio); + + scanned +=3D delta; + + if (sort_folio(lruvec, folio, tier)) + sorted +=3D delta; + else if (isolate_folio(lruvec, folio, sc)) { + list_add(&folio->lru, list); + isolated +=3D delta; + } else { + list_move(&folio->lru, &moved); + skipped +=3D delta; + } + + if (!--remaining || max(isolated, skipped) >=3D MIN_LRU_BATCH) + break; + } + + if (skipped) { + list_splice(&moved, head); + __count_zid_vm_events(PGSCAN_SKIP, zone, skipped); + } + + if (!remaining || isolated >=3D MIN_LRU_BATCH) + break; + } + + item =3D current_is_kswapd() ? PGSCAN_KSWAPD : PGSCAN_DIRECT; + if (!cgroup_reclaim(sc)) { + __count_vm_events(item, isolated); + __count_vm_events(PGREFILL, sorted); + } + __count_memcg_events(memcg, item, isolated); + __count_memcg_events(memcg, PGREFILL, sorted); + __count_vm_events(PGSCAN_ANON + type, isolated); + + /* + * There might not be eligible pages due to reclaim_idx, may_unmap and + * may_writepage. Check the remaining to prevent livelock if there is no + * progress. + */ + return isolated || !remaining ? scanned : 0; +} + +static int get_tier_idx(struct lruvec *lruvec, int type) +{ + int tier; + struct ctrl_pos sp, pv; + + /* + * To leave a margin for fluctuations, use a larger gain factor (1:2). + * This value is chosen because any other tier would have at least twice + * as many refaults as the first tier. + */ + read_ctrl_pos(lruvec, type, 0, 1, &sp); + for (tier =3D 1; tier < MAX_NR_TIERS; tier++) { + read_ctrl_pos(lruvec, type, tier, 2, &pv); + if (!positive_ctrl_err(&sp, &pv)) + break; + } + + return tier - 1; +} + +static int get_type_to_scan(struct lruvec *lruvec, int swappiness, int *ti= er_idx) +{ + int type, tier; + struct ctrl_pos sp, pv; + int gain[ANON_AND_FILE] =3D { swappiness, 200 - swappiness }; + + /* + * Compare the first tier of anon with that of file to determine which + * type to scan. Also need to compare other tiers of the selected type + * with the first tier of the other type to determine the last tier (of + * the selected type) to evict. + */ + read_ctrl_pos(lruvec, LRU_GEN_ANON, 0, gain[LRU_GEN_ANON], &sp); + read_ctrl_pos(lruvec, LRU_GEN_FILE, 0, gain[LRU_GEN_FILE], &pv); + type =3D positive_ctrl_err(&sp, &pv); + + read_ctrl_pos(lruvec, !type, 0, gain[!type], &sp); + for (tier =3D 1; tier < MAX_NR_TIERS; tier++) { + read_ctrl_pos(lruvec, type, tier, gain[type], &pv); + if (!positive_ctrl_err(&sp, &pv)) + break; + } + + *tier_idx =3D tier - 1; + + return type; +} + +static int isolate_folios(struct lruvec *lruvec, struct scan_control *sc, = int swappiness, + int *type_scanned, struct list_head *list) +{ + int i; + int type; + int scanned; + int tier =3D -1; + DEFINE_MIN_SEQ(lruvec); + + VM_BUG_ON(!seq_is_valid(lruvec)); + + /* + * Try to make the obvious choice first. When anon and file are both + * available from the same generation, interpret swappiness 1 as file + * first and 200 as anon first. + */ + if (!swappiness) + type =3D LRU_GEN_FILE; + else if (min_seq[LRU_GEN_ANON] < min_seq[LRU_GEN_FILE]) + type =3D LRU_GEN_ANON; + else if (swappiness =3D=3D 1) + type =3D LRU_GEN_FILE; + else if (swappiness =3D=3D 200) + type =3D LRU_GEN_ANON; + else + type =3D get_type_to_scan(lruvec, swappiness, &tier); + + for (i =3D !swappiness; i < ANON_AND_FILE; i++) { + if (tier < 0) + tier =3D get_tier_idx(lruvec, type); + + scanned =3D scan_folios(lruvec, sc, type, tier, list); + if (scanned) + break; + + type =3D !type; + tier =3D -1; + } + + *type_scanned =3D type; + + return scanned; +} + +static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, in= t swappiness) +{ + int type; + int scanned; + int reclaimed; + LIST_HEAD(list); + struct folio *folio; + enum vm_event_item item; + struct reclaim_stat stat; + struct mem_cgroup *memcg =3D lruvec_memcg(lruvec); + struct pglist_data *pgdat =3D lruvec_pgdat(lruvec); + + spin_lock_irq(&lruvec->lru_lock); + + scanned =3D isolate_folios(lruvec, sc, swappiness, &type, &list); + + if (try_to_inc_min_seq(lruvec, swappiness)) + scanned++; + + if (get_nr_gens(lruvec, LRU_GEN_FILE) =3D=3D MIN_NR_GENS) + scanned =3D 0; + + spin_unlock_irq(&lruvec->lru_lock); + + if (list_empty(&list)) + return scanned; + + reclaimed =3D shrink_page_list(&list, pgdat, sc, &stat, false); + + /* + * To avoid livelock, don't add rejected pages back to the same lists + * they were isolated from. See lru_gen_add_folio(). + */ + list_for_each_entry(folio, &list, lru) { + folio_clear_referenced(folio); + folio_clear_workingset(folio); + + if (folio_test_reclaim(folio) && + (folio_test_dirty(folio) || folio_test_writeback(folio))) + folio_clear_active(folio); + else + folio_set_active(folio); + } + + spin_lock_irq(&lruvec->lru_lock); + + move_pages_to_lru(lruvec, &list); + + item =3D current_is_kswapd() ? PGSTEAL_KSWAPD : PGSTEAL_DIRECT; + if (!cgroup_reclaim(sc)) + __count_vm_events(item, reclaimed); + __count_memcg_events(memcg, item, reclaimed); + __count_vm_events(PGSTEAL_ANON + type, reclaimed); + + spin_unlock_irq(&lruvec->lru_lock); + + mem_cgroup_uncharge_list(&list); + free_unref_page_list(&list); + + sc->nr_reclaimed +=3D reclaimed; + + return scanned; +} + +static long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *sc,= bool can_swap) +{ + bool need_aging; + long nr_to_scan; + struct mem_cgroup *memcg =3D lruvec_memcg(lruvec); + DEFINE_MAX_SEQ(lruvec); + DEFINE_MIN_SEQ(lruvec); + + if (mem_cgroup_below_min(memcg) || + (mem_cgroup_below_low(memcg) && !sc->memcg_low_reclaim)) + return 0; + + nr_to_scan =3D get_nr_evictable(lruvec, max_seq, min_seq, can_swap, &need= _aging); + if (!nr_to_scan) + return 0; + + /* reset the priority if the target has been met */ + nr_to_scan >>=3D sc->nr_reclaimed < sc->nr_to_reclaim ? sc->priority : DE= F_PRIORITY; + + if (!mem_cgroup_online(memcg)) + nr_to_scan++; + + if (!nr_to_scan) + return 0; + + if (!need_aging) + return nr_to_scan; + + /* leave the work to lru_gen_age_node() */ + if (current_is_kswapd()) + return 0; + + /* try other memcgs before going to the aging path */ + if (!cgroup_reclaim(sc) && !sc->force_deactivate) { + sc->skipped_deactivate =3D true; + return 0; + } + + inc_max_seq(lruvec, max_seq); + + return nr_to_scan; +} + +static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_contr= ol *sc) +{ + struct blk_plug plug; + long scanned =3D 0; + + lru_add_drain(); + + blk_start_plug(&plug); + + while (true) { + int delta; + int swappiness; + long nr_to_scan; + + if (sc->may_swap) + swappiness =3D get_swappiness(lruvec, sc); + else if (!cgroup_reclaim(sc) && get_swappiness(lruvec, sc)) + swappiness =3D 1; + else + swappiness =3D 0; + + nr_to_scan =3D get_nr_to_scan(lruvec, sc, swappiness); + if (!nr_to_scan) + break; + + delta =3D evict_folios(lruvec, sc, swappiness); + if (!delta) + break; + + scanned +=3D delta; + if (scanned >=3D nr_to_scan) + break; + + cond_resched(); + } + + blk_finish_plug(&plug); +} + /*************************************************************************= ***** * initialization *************************************************************************= *****/ @@ -3041,6 +3821,16 @@ static int __init init_lru_gen(void) }; late_initcall(init_lru_gen); =20 +#else + +static void lru_gen_age_node(struct pglist_data *pgdat, struct scan_contro= l *sc) +{ +} + +static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_contr= ol *sc) +{ +} + #endif /* CONFIG_LRU_GEN */ =20 static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc) @@ -3054,6 +3844,11 @@ static void shrink_lruvec(struct lruvec *lruvec, str= uct scan_control *sc) struct blk_plug plug; bool scan_adjusted; =20 + if (lru_gen_enabled()) { + lru_gen_shrink_lruvec(lruvec, sc); + return; + } + get_scan_count(lruvec, sc, nr); =20 /* Record the original scan target for proportional adjustments later */ @@ -3558,6 +4353,9 @@ static void snapshot_refaults(struct mem_cgroup *targ= et_memcg, pg_data_t *pgdat) struct lruvec *target_lruvec; unsigned long refaults; =20 + if (lru_gen_enabled()) + return; + target_lruvec =3D mem_cgroup_lruvec(target_memcg, pgdat); refaults =3D lruvec_page_state(target_lruvec, WORKINGSET_ACTIVATE_ANON); target_lruvec->refaults[0] =3D refaults; @@ -3928,6 +4726,11 @@ static void age_active_anon(struct pglist_data *pgda= t, struct mem_cgroup *memcg; struct lruvec *lruvec; =20 + if (lru_gen_enabled()) { + lru_gen_age_node(pgdat, sc); + return; + } + if (!can_age_anon_pages(pgdat, sc)) return; =20 diff --git a/mm/workingset.c b/mm/workingset.c index 8a3828acc0bf..89b46af74eef 100644 --- a/mm/workingset.c +++ b/mm/workingset.c @@ -187,7 +187,6 @@ static unsigned int bucket_order __read_mostly; static void *pack_shadow(int memcgid, pg_data_t *pgdat, unsigned long evic= tion, bool workingset) { - eviction >>=3D bucket_order; eviction &=3D EVICTION_MASK; eviction =3D (eviction << MEM_CGROUP_ID_SHIFT) | memcgid; eviction =3D (eviction << NODES_SHIFT) | pgdat->node_id; @@ -212,10 +211,116 @@ static void unpack_shadow(void *shadow, int *memcgid= p, pg_data_t **pgdat, =20 *memcgidp =3D memcgid; *pgdat =3D NODE_DATA(nid); - *evictionp =3D entry << bucket_order; + *evictionp =3D entry; *workingsetp =3D workingset; } =20 +#ifdef CONFIG_LRU_GEN + +static int folio_lru_refs(struct folio *folio) +{ + unsigned long flags =3D READ_ONCE(folio->flags); + + BUILD_BUG_ON(LRU_GEN_WIDTH + LRU_REFS_WIDTH > BITS_PER_LONG - EVICTION_SH= IFT); + + /* see the comment on MAX_NR_TIERS */ + return flags & BIT(PG_workingset) ? (flags & LRU_REFS_MASK) >> LRU_REFS_P= GOFF : 0; +} + +static void *lru_gen_eviction(struct folio *folio) +{ + int hist, tier; + unsigned long token; + unsigned long min_seq; + struct lruvec *lruvec; + struct lru_gen_struct *lrugen; + int type =3D folio_is_file_lru(folio); + int refs =3D folio_lru_refs(folio); + int delta =3D folio_nr_pages(folio); + bool workingset =3D folio_test_workingset(folio); + struct mem_cgroup *memcg =3D folio_memcg(folio); + struct pglist_data *pgdat =3D folio_pgdat(folio); + + lruvec =3D mem_cgroup_lruvec(memcg, pgdat); + lrugen =3D &lruvec->lrugen; + min_seq =3D READ_ONCE(lrugen->min_seq[type]); + token =3D (min_seq << LRU_REFS_WIDTH) | refs; + + hist =3D lru_hist_from_seq(min_seq); + tier =3D lru_tier_from_refs(refs + workingset); + atomic_long_add(delta, &lrugen->evicted[hist][type][tier]); + + return pack_shadow(mem_cgroup_id(memcg), pgdat, token, workingset); +} + +static void lru_gen_refault(struct folio *folio, void *shadow) +{ + int hist, tier, refs; + int memcg_id; + bool workingset; + unsigned long token; + unsigned long min_seq; + struct lruvec *lruvec; + struct lru_gen_struct *lrugen; + struct mem_cgroup *memcg; + struct pglist_data *pgdat; + int type =3D folio_is_file_lru(folio); + int delta =3D folio_nr_pages(folio); + + unpack_shadow(shadow, &memcg_id, &pgdat, &token, &workingset); + + refs =3D token & (BIT(LRU_REFS_WIDTH) - 1); + if (refs && !workingset) + return; + + if (folio_pgdat(folio) !=3D pgdat) + return; + + rcu_read_lock(); + memcg =3D folio_memcg_rcu(folio); + if (mem_cgroup_id(memcg) !=3D memcg_id) + goto unlock; + + token >>=3D LRU_REFS_WIDTH; + lruvec =3D mem_cgroup_lruvec(memcg, pgdat); + lrugen =3D &lruvec->lrugen; + min_seq =3D READ_ONCE(lrugen->min_seq[type]); + if (token !=3D (min_seq & (EVICTION_MASK >> LRU_REFS_WIDTH))) + goto unlock; + + hist =3D lru_hist_from_seq(min_seq); + tier =3D lru_tier_from_refs(refs + workingset); + atomic_long_add(delta, &lrugen->refaulted[hist][type][tier]); + mod_lruvec_state(lruvec, WORKINGSET_REFAULT_BASE + type, delta); + + /* + * Count the following two cases as stalls: + * 1. For pages accessed through page tables, hotter pages pushed out + * hot pages which refaulted immediately. + * 2. For pages accessed through file descriptors, numbers of accesses + * might have been beyond the limit. + */ + if (lru_gen_in_fault() || refs + workingset =3D=3D BIT(LRU_REFS_WIDTH)) { + folio_set_workingset(folio); + mod_lruvec_state(lruvec, WORKINGSET_RESTORE_BASE + type, delta); + } +unlock: + rcu_read_unlock(); +} + +#else + +static void *lru_gen_eviction(struct folio *folio) +{ + return NULL; +} + +static void lru_gen_refault(struct folio *folio, void *shadow) +{ +} + +#endif /* CONFIG_LRU_GEN */ + /** * workingset_age_nonresident - age non-resident entries as LRU ages * @lruvec: the lruvec that was aged @@ -264,10 +369,14 @@ void *workingset_eviction(struct folio *folio, struct= mem_cgroup *target_memcg) VM_BUG_ON_FOLIO(folio_ref_count(folio), folio); VM_BUG_ON_FOLIO(!folio_test_locked(folio), folio); =20 + if (lru_gen_enabled()) + return lru_gen_eviction(folio); + lruvec =3D mem_cgroup_lruvec(target_memcg, pgdat); /* XXX: target_memcg can be NULL, go through lruvec */ memcgid =3D mem_cgroup_id(lruvec_memcg(lruvec)); eviction =3D atomic_long_read(&lruvec->nonresident_age); + eviction >>=3D bucket_order; workingset_age_nonresident(lruvec, folio_nr_pages(folio)); return pack_shadow(memcgid, pgdat, eviction, folio_test_workingset(folio)); @@ -298,7 +407,13 @@ void workingset_refault(struct folio *folio, void *sha= dow) int memcgid; long nr; =20 + if (lru_gen_enabled()) { + lru_gen_refault(folio, shadow); + return; + } + unpack_shadow(shadow, &memcgid, &pgdat, &eviction, &workingset); + eviction <<=3D bucket_order; =20 rcu_read_lock(); /* --=20 2.35.1.1094.g7c7d902a7c-goog 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 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 267D2C433EF for ; Thu, 7 Apr 2022 03:30:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Cc:To:From:Subject:References: Mime-Version:Message-Id:In-Reply-To:Date:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=aZyoTIpZHUE5X3XJyMZjCwpez+e6sfEj4V5ujM5VrW0=; b=eNKI0g88kXn/jiYykWBGpYhY66 Pfr4GGF9GYUM0iMLkYO4lLU3XF5W0heT12OvDZOiVAutBZEbxQqWNXvjHnbOw1VRSQlaX9O0AJ2rB Z3VIIjLhR75n3cYPqw4ols9NlqYtZj6qVHimplDPkoYLp5CjuwQL/Vyc15/83EyBpzty7gwcoyyo7 76WWryY4Gswz3vUlWMZjcx6kgqpEMaLZ7+Wql+4SxRxmKRWXPe8ACTLn73/Y9woLko6RiskwJT0qv nsdu489zKDZJQRqWdfEbMmNZnUAhUnHoO3agYe4Y/xR9cULQKe/60ovcxzkKv+nCSrcpPnet/maCm almhiaLQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1ncIok-0096EY-6p; Thu, 07 Apr 2022 03:28:19 +0000 Received: from desiato.infradead.org ([90.155.92.199]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1ncId9-0091iG-TN for linux-arm-kernel@bombadil.infradead.org; Thu, 07 Apr 2022 03:16:20 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Transfer-Encoding:Content-Type :Cc:To:From:Subject:References:Mime-Version:Message-Id:In-Reply-To:Date: Sender:Reply-To:Content-ID:Content-Description; bh=2FVgzTnmb2JeqfQyoTBFNGi6zNu2jJ43Oxn+apD3DdM=; b=elKpgjOyHYvPMz8HI/DGky0Zrv N9gjfgTlu5Rjv9wUC2QDPTQwqcwpLPKSgi6LWdvwRrFtUUSnJReUfA7XQfjXGuPaEWUSdHl74SWve PaVKXVR167TOh6NKYq0WJ1Iyp14Ulylbj3Tt0/JPOA1Lv425DOoXdoLNCYYmHxGOBR0XZs6W77k3F eHvUDYW8LezgmOV36N1VLKJfpmWrWtZHBYOyr2o+02oDYe2iHIF3es0qg7qakHKQhBwRnpfaKh5ly rJi0SpEPYH9tfRThz1uuo2N7YTzRpZdn07MlMpiEC3zPiVp8ByMA84OFg/m0HrSieAgybznnhZlS6 AJuzRYCQ==; Received: from mail-yw1-x114a.google.com ([2607:f8b0:4864:20::114a]) by desiato.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1ncId0-002MjK-9Y for linux-arm-kernel@lists.infradead.org; Thu, 07 Apr 2022 03:16:16 +0000 Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-2d11b6259adso38250997b3.19 for ; Wed, 06 Apr 2022 20:16:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc:content-transfer-encoding; bh=2FVgzTnmb2JeqfQyoTBFNGi6zNu2jJ43Oxn+apD3DdM=; b=hmkrwsxtdydOk31u9v7YwlgLkL4/gZGYZUGZXCUEg69rTyuixL+pnWsIkFA0IB/0PE g2syqfrTzL6xNqJyxOZmRCpShXAvslX2buMI85IfypBDjMAp4WhSyymedXMFf3Dz1l6l /quvMcJLBkI4Nmsf2h79u21Gd0YzwDqFxYJUmZfIP8Ucg/KZQ+mSK1bBuyFdh+Pm+DeC VCgB1rX+RhWnJxxEjzTnNFgVtVRHLbsearw0unTTo8iiSk9KYvj41UyvnyswJn87DTAU 1iChhmiL5w3jYToh9GeD8agkee1Ok8MHxtK5sdg+31o9kpwmAycCzvUNv7jIsCmGifyq gY4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc:content-transfer-encoding; bh=2FVgzTnmb2JeqfQyoTBFNGi6zNu2jJ43Oxn+apD3DdM=; b=v0NBJuM9/rz6F3IGnj88xziuelbeh+LNcJfw93zMJWNmWVfa5NhJ4AkSb1GzEU3jb8 YlUK+Cz+oOGmM1ey4SC05/W1bSleliJRNEpxaIgNnxdsDmwDbJc7D91AqKK0wBtf50is VSTYeB6Rs/lqKyAiZrHlwyDT65XG8BeiIUa7Rc77m5iqcqg+6vxBAnGu2cCyapxMI27I 3g+7zUdxWJh+DYNl3Og9RP9aW5Vi4jAtjO4CE7BDkpeNOaPMUlE9bQu6ymtgeSAeJSe/ ZNH6IiIA1Zo2c987HYcIuzUTJdzkbTVI7fNsvHOi4ojjF4fvEMKIj2EX5nk0vRvQ8GrX 8jrw== X-Gm-Message-State: AOAM531CiqPKtA8A0cRzTzdYvT0JMsuBH4n6eQgbvmDWW+hIoFTn8ADj /9Pb35bn+osZKilZIwOpdm+1CeK6Btk= X-Google-Smtp-Source: ABdhPJwb/kFQSSyXRQuXuCiEhLpFhfCD+ZGa12jHRxQR469lOgwSlQltO6Amf8P1HoYy/R9f+MpnivDRFHM= X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:9ea2:c755:ae22:6862]) (user=yuzhao job=sendgmr) by 2002:a25:59c3:0:b0:63d:8ccc:37b0 with SMTP id n186-20020a2559c3000000b0063d8ccc37b0mr8744785ybb.612.1649301365790; Wed, 06 Apr 2022 20:16:05 -0700 (PDT) Date: Wed, 6 Apr 2022 21:15:18 -0600 In-Reply-To: <20220407031525.2368067-1-yuzhao@google.com> Message-Id: <20220407031525.2368067-7-yuzhao@google.com> Mime-Version: 1.0 References: <20220407031525.2368067-1-yuzhao@google.com> X-Mailer: git-send-email 2.35.1.1094.g7c7d902a7c-goog Subject: [PATCH v10 06/14] mm: multi-gen LRU: minimal implementation From: Yu Zhao To: Stephen Rothwell , linux-mm@kvack.org Cc: Andi Kleen , Andrew Morton , Aneesh Kumar , Barry Song <21cnbao@gmail.com>, Catalin Marinas , Dave Hansen , Hillf Danton , Jens Axboe , Jesse Barnes , Johannes Weiner , Jonathan Corbet , Linus Torvalds , Matthew Wilcox , Mel Gorman , Michael Larabel , Michal Hocko , Mike Rapoport , Rik van Riel , Vlastimil Babka , Will Deacon , Ying Huang , linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, page-reclaim@google.com, x86@kernel.org, Yu Zhao , Brian Geffon , Jan Alexander Steffens , Oleksandr Natalenko , Steven Barrett , Suleiman Souhlal , Daniel Byrne , Donald Carr , "=?UTF-8?q?Holger=20Hoffst=C3=A4tte?=" , Konstantin Kharlamov , Shuang Zhai , Sofia Trinh , Vaibhav Jain X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220407_041610_924729_390BA990 X-CRM114-Status: GOOD ( 24.27 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org VG8gYXZvaWQgY29uZnVzaW9uLCB0aGUgdGVybXMgInByb21vdGlvbiIgYW5kICJkZW1vdGlvbiIg d2lsbCBiZQphcHBsaWVkIHRvIHRoZSBtdWx0aS1nZW4gTFJVLCBhcyBhIG5ldyBjb252ZW50aW9u OyB0aGUgdGVybXMKImFjdGl2YXRpb24iIGFuZCAiZGVhY3RpdmF0aW9uIiB3aWxsIGJlIGFwcGxp ZWQgdG8gdGhlIGFjdGl2ZS9pbmFjdGl2ZQpMUlUsIGFzIHVzdWFsLgoKVGhlIGFnaW5nIHByb2R1 Y2VzIHlvdW5nIGdlbmVyYXRpb25zLiBHaXZlbiBhbiBscnV2ZWMsIGl0IGluY3JlbWVudHMKbWF4 X3NlcSB3aGVuIG1heF9zZXEtbWluX3NlcSsxIGFwcHJvYWNoZXMgTUlOX05SX0dFTlMuIFRoZSBh Z2luZwpwcm9tb3RlcyBob3QgcGFnZXMgdG8gdGhlIHlvdW5nZXN0IGdlbmVyYXRpb24gd2hlbiBp dCBmaW5kcyB0aGVtCmFjY2Vzc2VkIHRocm91Z2ggcGFnZSB0YWJsZXM7IHRoZSBkZW1vdGlvbiBv ZiBjb2xkIHBhZ2VzIGhhcHBlbnMKY29uc2VxdWVudGx5IHdoZW4gaXQgaW5jcmVtZW50cyBtYXhf c2VxLiBUaGUgYWdpbmcgaGFzIHRoZSBjb21wbGV4aXR5Ck8obnJfaG90X3BhZ2VzKSwgc2luY2Ug aXQgaXMgb25seSBpbnRlcmVzdGVkIGluIGhvdCBwYWdlcy4gUHJvbW90aW9uCmluIHRoZSBhZ2lu ZyBwYXRoIGRvZXMgbm90IHJlcXVpcmUgYW55IExSVSBsaXN0IG9wZXJhdGlvbnMsIG9ubHkgdGhl CnVwZGF0ZXMgb2YgdGhlIGdlbiBjb3VudGVyIGFuZCBscnVnZW4tPm5yX3BhZ2VzW107IGRlbW90 aW9uLCB1bmxlc3MgYXMKdGhlIHJlc3VsdCBvZiB0aGUgaW5jcmVtZW50IG9mIG1heF9zZXEsIHJl cXVpcmVzIExSVSBsaXN0IG9wZXJhdGlvbnMsCmUuZy4sIGxydV9kZWFjdGl2YXRlX2ZuKCkuCgpU aGUgZXZpY3Rpb24gY29uc3VtZXMgb2xkIGdlbmVyYXRpb25zLiBHaXZlbiBhbiBscnV2ZWMsIGl0 IGluY3JlbWVudHMKbWluX3NlcSB3aGVuIHRoZSBsaXN0cyBpbmRleGVkIGJ5IG1pbl9zZXElTUFY X05SX0dFTlMgYmVjb21lIGVtcHR5LiBBCmZlZWRiYWNrIGxvb3AgbW9kZWxlZCBhZnRlciB0aGUg UElEIGNvbnRyb2xsZXIgbW9uaXRvcnMgcmVmYXVsdHMgb3Zlcgphbm9uIGFuZCBmaWxlIHR5cGVz IGFuZCBkZWNpZGVzIHdoaWNoIHR5cGUgdG8gZXZpY3Qgd2hlbiBib3RoIHR5cGVzCmFyZSBhdmFp bGFibGUgZnJvbSB0aGUgc2FtZSBnZW5lcmF0aW9uLgoKRWFjaCBnZW5lcmF0aW9uIGlzIGRpdmlk ZWQgaW50byBtdWx0aXBsZSB0aWVycy4gVGllcnMgcmVwcmVzZW50CmRpZmZlcmVudCByYW5nZXMg b2YgbnVtYmVycyBvZiBhY2Nlc3NlcyB0aHJvdWdoIGZpbGUgZGVzY3JpcHRvcnMuIEEKcGFnZSBh Y2Nlc3NlZCBOIHRpbWVzIHRocm91Z2ggZmlsZSBkZXNjcmlwdG9ycyBpcyBpbiB0aWVyCm9yZGVy X2Jhc2VfMihOKS4gVGllcnMgZG8gbm90IGhhdmUgZGVkaWNhdGVkIGxydWdlbi0+bGlzdHNbXSwg b25seQpiaXRzIGluIGZvbGlvLT5mbGFncy4gSW4gY29udHJhc3QgdG8gbW92aW5nIGFjcm9zcyBn ZW5lcmF0aW9ucywgd2hpY2gKcmVxdWlyZXMgdGhlIExSVSBsb2NrLCBtb3ZpbmcgYWNyb3NzIHRp ZXJzIG9ubHkgaW52b2x2ZXMgb3BlcmF0aW9ucyBvbgpmb2xpby0+ZmxhZ3MuIFRoZSBmZWVkYmFj ayBsb29wIGFsc28gbW9uaXRvcnMgcmVmYXVsdHMgb3ZlciBhbGwgdGllcnMKYW5kIGRlY2lkZXMg d2hlbiB0byBwcm90ZWN0IHBhZ2VzIGluIHdoaWNoIHRpZXJzIChOPjEpLCB1c2luZyB0aGUKZmly c3QgdGllciAoTj0wLDEpIGFzIGEgYmFzZWxpbmUuIFRoZSBmaXJzdCB0aWVyIGNvbnRhaW5zIHNp bmdsZS11c2UKdW5tYXBwZWQgY2xlYW4gcGFnZXMsIHdoaWNoIGFyZSBtb3N0IGxpa2VseSB0aGUg YmVzdCBjaG9pY2VzLiBUaGUKZXZpY3Rpb24gbW92ZXMgYSBwYWdlIHRvIHRoZSBuZXh0IGdlbmVy YXRpb24sIGkuZS4sIG1pbl9zZXErMSwgaWYgdGhlCmZlZWRiYWNrIGxvb3AgZGVjaWRlcyBzby4g VGhpcyBhcHByb2FjaCBoYXMgdGhlIGZvbGxvd2luZyBhZHZhbnRhZ2VzOgoxLiBJdCByZW1vdmVz IHRoZSBjb3N0IG9mIGFjdGl2YXRpb24gaW4gdGhlIGJ1ZmZlcmVkIGFjY2VzcyBwYXRoIGJ5CiAg IGluZmVycmluZyB3aGV0aGVyIHBhZ2VzIGFjY2Vzc2VkIG11bHRpcGxlIHRpbWVzIHRocm91Z2gg ZmlsZQogICBkZXNjcmlwdG9ycyBhcmUgc3RhdGlzdGljYWxseSBob3QgYW5kIHRodXMgd29ydGgg cHJvdGVjdGluZyBpbiB0aGUKICAgZXZpY3Rpb24gcGF0aC4KMi4gSXQgdGFrZXMgcGFnZXMgYWNj ZXNzZWQgdGhyb3VnaCBwYWdlIHRhYmxlcyBpbnRvIGFjY291bnQgYW5kIGF2b2lkcwogICBvdmVy cHJvdGVjdGluZyBwYWdlcyBhY2Nlc3NlZCBtdWx0aXBsZSB0aW1lcyB0aHJvdWdoIGZpbGUKICAg ZGVzY3JpcHRvcnMuIChQYWdlcyBhY2Nlc3NlZCB0aHJvdWdoIHBhZ2UgdGFibGVzIGFyZSBpbiB0 aGUgZmlyc3QKICAgdGllciwgc2luY2UgTj0wLikKMy4gTW9yZSB0aWVycyBwcm92aWRlIGJldHRl ciBwcm90ZWN0aW9uIGZvciBwYWdlcyBhY2Nlc3NlZCBtb3JlIHRoYW4KICAgdHdpY2UgdGhyb3Vn aCBmaWxlIGRlc2NyaXB0b3JzLCB3aGVuIHVuZGVyIGhlYXZ5IGJ1ZmZlcmVkIEkvTwogICB3b3Jr bG9hZHMuCgpTZXJ2ZXIgYmVuY2htYXJrIHJlc3VsdHM6CiAgU2luZ2xlIHdvcmtsb2FkOgogICAg ZmlvIChidWZmZXJlZCBJL08pOiArWzQwLCA0Ml0lCiAgICAgICAgICAgICAgICBJT1BTICAgICAg ICAgQlcKICAgICAgNS4xOC1yYzE6IDI0NjNrICAgICAgICA5NjIxTWlCL3MKICAgICAgcGF0Y2gx LTY6IDM0ODRrICAgICAgICAxMy4zR2lCL3MKCiAgU2luZ2xlIHdvcmtsb2FkOgogICAgbWVtY2Fj aGVkIChhbm9uKTogK1s0NCwgNDZdJQogICAgICAgICAgICAgICAgT3BzL3NlYyAgICAgIEtCL3Nl YwogICAgICA1LjE4LXJjMTogNzcxNDAzLjI3ICAgIDMwMDA0LjE3CiAgICAgIHBhdGNoMS02OiAx MTIwNjQzLjcwICAgNDM1ODguMDYKCiAgQ29uZmlndXJhdGlvbnM6CiAgICBDUFU6IHR3byBYZW9u IDYxNTQKICAgIE1lbTogdG90YWwgMjU2RwoKICAgIE5vZGUgMSB3YXMgb25seSB1c2VkIGFzIGEg cmFtIGRpc2sgdG8gcmVkdWNlIHRoZSB2YXJpYW5jZSBpbiB0aGUKICAgIHJlc3VsdHMuCgogICAg cGF0Y2ggZHJpdmVycy9ibG9jay9icmQuYyA8PEVPRgogICAgOTksMTAwYzk5LDEwMAogICAgPCAJ Z2ZwX2ZsYWdzID0gR0ZQX05PSU8gfCBfX0dGUF9aRVJPIHwgX19HRlBfSElHSE1FTTsKICAgIDwg CXBhZ2UgPSBhbGxvY19wYWdlKGdmcF9mbGFncyk7CiAgICAtLS0KICAgID4gCWdmcF9mbGFncyA9 IEdGUF9OT0lPIHwgX19HRlBfWkVSTyB8IF9fR0ZQX0hJR0hNRU0gfCBfX0dGUF9USElTTk9ERTsK ICAgID4gCXBhZ2UgPSBhbGxvY19wYWdlc19ub2RlKDEsIGdmcF9mbGFncywgMCk7CiAgICBFT0YK CiAgICBjYXQgPj4vZXRjL3N5c3RlbWQvc3lzdGVtLmNvbmYgPDxFT0YKICAgIENQVUFmZmluaXR5 PW51bWEKICAgIE5VTUFQb2xpY3k9YmluZAogICAgTlVNQU1hc2s9MAogICAgRU9GCgogICAgY2F0 ID4+L2V0Yy9tZW1jYWNoZWQuY29uZiA8PEVPRgogICAgLW0gMTg0MzIwCiAgICAtcyAvdmFyL3J1 bi9tZW1jYWNoZWQvbWVtY2FjaGVkLnNvY2sKICAgIC1hIDA3NjYKICAgIC10IDM2CiAgICAtQiBi aW5hcnkKICAgIEVPRgoKICAgIGNhdCBmaW8uc2gKICAgIG1vZHByb2JlIGJyZCByZF9ucj0xIHJk X3NpemU9MTEzMjQ2MjA4CiAgICBzd2Fwb2ZmIC1hCiAgICBta2ZzLmV4dDQgL2Rldi9yYW0wCiAg ICBtb3VudCAtdCBleHQ0IC9kZXYvcmFtMCAvbW50CgogICAgbWtkaXIgL3N5cy9mcy9jZ3JvdXAv dXNlci5zbGljZS90ZXN0CiAgICBlY2hvIDM4NjU0NzA1NjY0ID4vc3lzL2ZzL2Nncm91cC91c2Vy LnNsaWNlL3Rlc3QvbWVtb3J5Lm1heAogICAgZWNobyAkJCA+L3N5cy9mcy9jZ3JvdXAvdXNlci5z bGljZS90ZXN0L2Nncm91cC5wcm9jcwogICAgZmlvIC1uYW1lPW1nbHJ1IC0tbnVtam9icz03MiAt LWRpcmVjdG9yeT0vbW50IC0tc2l6ZT0xNDA4bSBcCiAgICAgIC0tYnVmZmVyZWQ9MSAtLWlvZW5n aW5lPWlvX3VyaW5nIC0taW9kZXB0aD0xMjggXAogICAgICAtLWlvZGVwdGhfYmF0Y2hfc3VibWl0 PTMyIC0taW9kZXB0aF9iYXRjaF9jb21wbGV0ZT0zMiBcCiAgICAgIC0tcnc9cmFuZHJlYWQgLS1y YW5kb21fZGlzdHJpYnV0aW9uPXJhbmRvbSAtLW5vcmFuZG9tbWFwIFwKICAgICAgLS10aW1lX2Jh c2VkIC0tcmFtcF90aW1lPTEwbSAtLXJ1bnRpbWU9NW0gLS1ncm91cF9yZXBvcnRpbmcKCiAgICBj YXQgbWVtY2FjaGVkLnNoCiAgICBtb2Rwcm9iZSBicmQgcmRfbnI9MSByZF9zaXplPTExMzI0NjIw OAogICAgc3dhcG9mZiAtYQogICAgbWtzd2FwIC9kZXYvcmFtMAogICAgc3dhcG9uIC9kZXYvcmFt MAoKICAgIG1lbXRpZXJfYmVuY2htYXJrIC1TIC92YXIvcnVuL21lbWNhY2hlZC9tZW1jYWNoZWQu c29jayBcCiAgICAgIC1QIG1lbWNhY2hlX2JpbmFyeSAtbiBhbGxrZXlzIC0ta2V5LW1pbmltdW09 MSBcCiAgICAgIC0ta2V5LW1heGltdW09NjUwMDAwMDAgLS1rZXktcGF0dGVybj1QOlAgLWMgMSAt dCAzNiBcCiAgICAgIC0tcmF0aW8gMTowIC0tcGlwZWxpbmUgOCAtZCAyMDAwCgogICAgbWVtdGll cl9iZW5jaG1hcmsgLVMgL3Zhci9ydW4vbWVtY2FjaGVkL21lbWNhY2hlZC5zb2NrIFwKICAgICAg LVAgbWVtY2FjaGVfYmluYXJ5IC1uIGFsbGtleXMgLS1rZXktbWluaW11bT0xIFwKICAgICAgLS1r ZXktbWF4aW11bT02NTAwMDAwMCAtLWtleS1wYXR0ZXJuPVI6UiAtYyAxIC10IDM2IFwKICAgICAg LS1yYXRpbyAwOjEgLS1waXBlbGluZSA4IC0tcmFuZG9taXplIC0tZGlzdGluY3QtY2xpZW50LXNl ZWQKCkNsaWVudCBiZW5jaG1hcmsgcmVzdWx0czoKICBrc3dhcGQgcHJvZmlsZXM6CiAgICA1LjE4 LXJjMQogICAgICA0MC41MyUgIHBhZ2Vfdm1hX21hcHBlZF93YWxrCiAgICAgIDIwLjM3JSAgbHpv MXhfMV9kb19jb21wcmVzcyAocmVhbCB3b3JrKQogICAgICAgNi45OSUgIGRvX3Jhd19zcGluX2xv Y2sKICAgICAgIDMuOTMlICBfcmF3X3NwaW5fdW5sb2NrX2lycQogICAgICAgMi4wOCUgIHZtYV9p bnRlcnZhbF90cmVlX3N1YnRyZWVfc2VhcmNoCiAgICAgICAyLjA2JSAgdm1hX2ludGVydmFsX3Ry ZWVfaXRlcl9uZXh0CiAgICAgICAxLjk1JSAgZm9saW9fcmVmZXJlbmNlZF9vbmUKICAgICAgIDEu OTMlICBhbm9uX3ZtYV9pbnRlcnZhbF90cmVlX2l0ZXJfZmlyc3QKICAgICAgIDEuNTElICBwdGVw X2NsZWFyX2ZsdXNoCiAgICAgICAxLjM1JSAgX19hbm9uX3ZtYV9pbnRlcnZhbF90cmVlX3N1YnRy ZWVfc2VhcmNoCgogICAgcGF0Y2gxLTYKICAgICAgMzUuOTklICBsem8xeF8xX2RvX2NvbXByZXNz IChyZWFsIHdvcmspCiAgICAgIDE5LjQwJSAgcGFnZV92bWFfbWFwcGVkX3dhbGsKICAgICAgIDYu MzElICBfcmF3X3NwaW5fdW5sb2NrX2lycQogICAgICAgMy45NSUgIGRvX3Jhd19zcGluX2xvY2sK ICAgICAgIDIuMzklICBhbm9uX3ZtYV9pbnRlcnZhbF90cmVlX2l0ZXJfZmlyc3QKICAgICAgIDIu MjUlICBwdGVwX2NsZWFyX2ZsdXNoCiAgICAgICAxLjkyJSAgX19hbm9uX3ZtYV9pbnRlcnZhbF90 cmVlX3N1YnRyZWVfc2VhcmNoCiAgICAgICAxLjcwJSAgZm9saW9fcmVmZXJlbmNlZF9vbmUKICAg ICAgIDEuNjglICBfX3pyYW1fYnZlY193cml0ZQogICAgICAgMS40MyUgIGFub25fdm1hX2ludGVy dmFsX3RyZWVfaXRlcl9uZXh0CgogIENvbmZpZ3VyYXRpb25zOgogICAgQ1BVOiBzaW5nbGUgU25h cGRyYWdvbiA3YwogICAgTWVtOiB0b3RhbCA0RwoKICAgIENocm9tZSBPUyBNZW1vcnlQcmVzc3Vy ZSBbMV0KClsxXSBodHRwczovL2Nocm9taXVtLmdvb2dsZXNvdXJjZS5jb20vY2hyb21pdW1vcy9w bGF0Zm9ybS90YXN0LXRlc3RzLwoKU2lnbmVkLW9mZi1ieTogWXUgWmhhbyA8eXV6aGFvQGdvb2ds ZS5jb20+CkFja2VkLWJ5OiBCcmlhbiBHZWZmb24gPGJnZWZmb25AZ29vZ2xlLmNvbT4KQWNrZWQt Ynk6IEphbiBBbGV4YW5kZXIgU3RlZmZlbnMgKGhlZnRpZykgPGhlZnRpZ0BhcmNobGludXgub3Jn PgpBY2tlZC1ieTogT2xla3NhbmRyIE5hdGFsZW5rbyA8b2xla3NhbmRyQG5hdGFsZW5rby5uYW1l PgpBY2tlZC1ieTogU3RldmVuIEJhcnJldHQgPHN0ZXZlbkBsaXF1b3JpeC5uZXQ+CkFja2VkLWJ5 OiBTdWxlaW1hbiBTb3VobGFsIDxzdWxlaW1hbkBnb29nbGUuY29tPgpUZXN0ZWQtYnk6IERhbmll bCBCeXJuZSA8ZGpieXJuZUBtdHUuZWR1PgpUZXN0ZWQtYnk6IERvbmFsZCBDYXJyIDxkQGNoYW9z LXJlaW5zLmNvbT4KVGVzdGVkLWJ5OiBIb2xnZXIgSG9mZnN0w6R0dGUgPGhvbGdlckBhcHBsaWVk LWFzeW5jaHJvbnkuY29tPgpUZXN0ZWQtYnk6IEtvbnN0YW50aW4gS2hhcmxhbW92IDxIaS1Bbmdl bEB5YW5kZXgucnU+ClRlc3RlZC1ieTogU2h1YW5nIFpoYWkgPHN6aGFpMkBjcy5yb2NoZXN0ZXIu ZWR1PgpUZXN0ZWQtYnk6IFNvZmlhIFRyaW5oIDxzb2ZpYS50cmluaEBlZGkud29ya3M+ClRlc3Rl ZC1ieTogVmFpYmhhdiBKYWluIDx2YWliaGF2QGxpbnV4LmlibS5jb20+Ci0tLQogaW5jbHVkZS9s aW51eC9tbV9pbmxpbmUuaCB8ICAyNCArKwogaW5jbHVkZS9saW51eC9tbXpvbmUuaCAgICB8ICA0 MSArKwoga2VybmVsL2JvdW5kcy5jICAgICAgICAgICB8ICAgMiArLQogbW0vS2NvbmZpZyAgICAg ICAgICAgICAgICB8ICAxMSArCiBtbS9zd2FwLmMgICAgICAgICAgICAgICAgIHwgIDQyICsrCiBt bS92bXNjYW4uYyAgICAgICAgICAgICAgIHwgODA1ICsrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysrKysrKystCiBtbS93b3JraW5nc2V0LmMgICAgICAgICAgIHwgMTE5ICsrKysrLQogNyBm aWxlcyBjaGFuZ2VkLCAxMDQwIGluc2VydGlvbnMoKyksIDQgZGVsZXRpb25zKC0pCgpkaWZmIC0t Z2l0IGEvaW5jbHVkZS9saW51eC9tbV9pbmxpbmUuaCBiL2luY2x1ZGUvbGludXgvbW1faW5saW5l LmgKaW5kZXggOWFiZDcyYTk1NDYyLi44YThmODdiNzI1NDAgMTAwNjQ0Ci0tLSBhL2luY2x1ZGUv bGludXgvbW1faW5saW5lLmgKKysrIGIvaW5jbHVkZS9saW51eC9tbV9pbmxpbmUuaApAQCAtMTE5 LDYgKzExOSwxOSBAQCBzdGF0aWMgaW5saW5lIGludCBscnVfZ2VuX2Zyb21fc2VxKHVuc2lnbmVk IGxvbmcgc2VxKQogCXJldHVybiBzZXEgJSBNQVhfTlJfR0VOUzsKIH0KIAorc3RhdGljIGlubGlu ZSBpbnQgbHJ1X2hpc3RfZnJvbV9zZXEodW5zaWduZWQgbG9uZyBzZXEpCit7CisJcmV0dXJuIHNl cSAlIE5SX0hJU1RfR0VOUzsKK30KKworc3RhdGljIGlubGluZSBpbnQgbHJ1X3RpZXJfZnJvbV9y ZWZzKGludCByZWZzKQoreworCVZNX0JVR19PTihyZWZzID4gQklUKExSVV9SRUZTX1dJRFRIKSk7 CisKKwkvKiBzZWUgdGhlIGNvbW1lbnQgb24gTUFYX05SX1RJRVJTICovCisJcmV0dXJuIG9yZGVy X2Jhc2VfMihyZWZzICsgMSk7Cit9CisKIHN0YXRpYyBpbmxpbmUgYm9vbCBscnVfZ2VuX2lzX2Fj dGl2ZShzdHJ1Y3QgbHJ1dmVjICpscnV2ZWMsIGludCBnZW4pCiB7CiAJdW5zaWduZWQgbG9uZyBt YXhfc2VxID0gbHJ1dmVjLT5scnVnZW4ubWF4X3NlcTsKQEAgLTE2NCw2ICsxNzcsMTUgQEAgc3Rh dGljIGlubGluZSB2b2lkIGxydV9nZW5fdXBkYXRlX3NpemUoc3RydWN0IGxydXZlYyAqbHJ1dmVj LCBzdHJ1Y3QgZm9saW8gKmZvbGkKIAkJX191cGRhdGVfbHJ1X3NpemUobHJ1dmVjLCBscnUsIHpv bmUsIC1kZWx0YSk7CiAJCXJldHVybjsKIAl9CisKKwkvKiBwcm9tb3Rpb24gKi8KKwlpZiAoIWxy dV9nZW5faXNfYWN0aXZlKGxydXZlYywgb2xkX2dlbikgJiYgbHJ1X2dlbl9pc19hY3RpdmUobHJ1 dmVjLCBuZXdfZ2VuKSkgeworCQlfX3VwZGF0ZV9scnVfc2l6ZShscnV2ZWMsIGxydSwgem9uZSwg LWRlbHRhKTsKKwkJX191cGRhdGVfbHJ1X3NpemUobHJ1dmVjLCBscnUgKyBMUlVfQUNUSVZFLCB6 b25lLCBkZWx0YSk7CisJfQorCisJLyogZGVtb3Rpb24gcmVxdWlyZXMgaXNvbGF0aW9uLCBlLmcu LCBscnVfZGVhY3RpdmF0ZV9mbigpICovCisJVk1fQlVHX09OKGxydV9nZW5faXNfYWN0aXZlKGxy dXZlYywgb2xkX2dlbikgJiYgIWxydV9nZW5faXNfYWN0aXZlKGxydXZlYywgbmV3X2dlbikpOwog fQogCiBzdGF0aWMgaW5saW5lIGJvb2wgbHJ1X2dlbl9hZGRfZm9saW8oc3RydWN0IGxydXZlYyAq bHJ1dmVjLCBzdHJ1Y3QgZm9saW8gKmZvbGlvLCBib29sIHJlY2xhaW1pbmcpCkBAIC0yMjksNiAr MjUxLDggQEAgc3RhdGljIGlubGluZSBib29sIGxydV9nZW5fZGVsX2ZvbGlvKHN0cnVjdCBscnV2 ZWMgKmxydXZlYywgc3RydWN0IGZvbGlvICpmb2xpbywKIAkJZ2VuID0gKChuZXdfZmxhZ3MgJiBM UlVfR0VOX01BU0spID4+IExSVV9HRU5fUEdPRkYpIC0gMTsKIAogCQluZXdfZmxhZ3MgJj0gfkxS VV9HRU5fTUFTSzsKKwkJaWYgKCEobmV3X2ZsYWdzICYgQklUKFBHX3JlZmVyZW5jZWQpKSkKKwkJ CW5ld19mbGFncyAmPSB+KExSVV9SRUZTX01BU0sgfCBMUlVfUkVGU19GTEFHUyk7CiAJCS8qIGZv ciBzaHJpbmtfcGFnZV9saXN0KCkgKi8KIAkJaWYgKHJlY2xhaW1pbmcpCiAJCQluZXdfZmxhZ3Mg Jj0gfihCSVQoUEdfcmVmZXJlbmNlZCkgfCBCSVQoUEdfcmVjbGFpbSkpOwpkaWZmIC0tZ2l0IGEv aW5jbHVkZS9saW51eC9tbXpvbmUuaCBiL2luY2x1ZGUvbGludXgvbW16b25lLmgKaW5kZXggYmRl MDU0MjdlMmJiLi5jOGE3Y2VlZTdhMGEgMTAwNjQ0Ci0tLSBhL2luY2x1ZGUvbGludXgvbW16b25l LmgKKysrIGIvaW5jbHVkZS9saW51eC9tbXpvbmUuaApAQCAtMzQ3LDEyICszNDcsMzQgQEAgZW51 bSBscnV2ZWNfZmxhZ3MgewogI2RlZmluZSBNSU5fTlJfR0VOUwkJMlUKICNkZWZpbmUgTUFYX05S X0dFTlMJCTRVCiAKKy8qCisgKiBFYWNoIGdlbmVyYXRpb24gaXMgZGl2aWRlZCBpbnRvIG11bHRp cGxlIHRpZXJzLiBUaWVycyByZXByZXNlbnQgZGlmZmVyZW50CisgKiByYW5nZXMgb2YgbnVtYmVy cyBvZiBhY2Nlc3NlcyB0aHJvdWdoIGZpbGUgZGVzY3JpcHRvcnMuIEEgcGFnZSBhY2Nlc3NlZCBO CisgKiB0aW1lcyB0aHJvdWdoIGZpbGUgZGVzY3JpcHRvcnMgaXMgaW4gdGllciBvcmRlcl9iYXNl XzIoTikuIEEgcGFnZSBpbiB0aGUKKyAqIGZpcnN0IHRpZXIgKE49MCwxKSBpcyBtYXJrZWQgYnkg UEdfcmVmZXJlbmNlZCB1bmxlc3MgaXQgd2FzIGZhdWx0ZWQgaW4KKyAqIHRob3VnaCBwYWdlIHRh YmxlcyBvciByZWFkIGFoZWFkLiBBIHBhZ2UgaW4gYW55IG90aGVyIHRpZXIgKE4+MSkgaXMgbWFy a2VkCisgKiBieSBQR19yZWZlcmVuY2VkIGFuZCBQR193b3JraW5nc2V0LgorICoKKyAqIEluIGNv bnRyYXN0IHRvIG1vdmluZyBhY3Jvc3MgZ2VuZXJhdGlvbnMgd2hpY2ggcmVxdWlyZXMgdGhlIExS VSBsb2NrLCBtb3ZpbmcKKyAqIGFjcm9zcyB0aWVycyBvbmx5IHJlcXVpcmVzIG9wZXJhdGlvbnMg b24gZm9saW8tPmZsYWdzIGFuZCB0aGVyZWZvcmUgaGFzIGEKKyAqIG5lZ2xpZ2libGUgY29zdCBp biB0aGUgYnVmZmVyZWQgYWNjZXNzIHBhdGguIEluIHRoZSBldmljdGlvbiBwYXRoLAorICogY29t cGFyaXNvbnMgb2YgcmVmYXVsdGVkLyhldmljdGVkK3Byb3RlY3RlZCkgZnJvbSB0aGUgZmlyc3Qg dGllciBhbmQgdGhlCisgKiByZXN0IGluZmVyIHdoZXRoZXIgcGFnZXMgYWNjZXNzZWQgbXVsdGlw bGUgdGltZXMgdGhyb3VnaCBmaWxlIGRlc2NyaXB0b3JzCisgKiBhcmUgc3RhdGlzdGljYWxseSBo b3QgYW5kIHRodXMgd29ydGggcHJvdGVjdGluZy4KKyAqCisgKiBNQVhfTlJfVElFUlMgaXMgc2V0 IHRvIDQgc28gdGhhdCB0aGUgbXVsdGktZ2VuIExSVSBjYW4gc3VwcG9ydCB0d2ljZSBvZiB0aGUK KyAqIGNhdGVnb3JpZXMgb2YgdGhlIGFjdGl2ZS9pbmFjdGl2ZSBMUlUgd2hlbiBrZWVwaW5nIHRy YWNrIG9mIGFjY2Vzc2VzIHRocm91Z2gKKyAqIGZpbGUgZGVzY3JpcHRvcnMuIEl0IHJlcXVpcmVz IE1BWF9OUl9USUVSUy0yIGFkZGl0aW9uYWwgYml0cyBpbiBmb2xpby0+ZmxhZ3MuCisgKi8KKyNk ZWZpbmUgTUFYX05SX1RJRVJTCQk0VQorCiAjaWZuZGVmIF9fR0VORVJBVElOR19CT1VORFNfSAog CiBzdHJ1Y3QgbHJ1dmVjOwogCiAjZGVmaW5lIExSVV9HRU5fTUFTSwkJKChCSVQoTFJVX0dFTl9X SURUSCkgLSAxKSA8PCBMUlVfR0VOX1BHT0ZGKQogI2RlZmluZSBMUlVfUkVGU19NQVNLCQkoKEJJ VChMUlVfUkVGU19XSURUSCkgLSAxKSA8PCBMUlVfUkVGU19QR09GRikKKyNkZWZpbmUgTFJVX1JF RlNfRkxBR1MJCShCSVQoUEdfcmVmZXJlbmNlZCkgfCBCSVQoUEdfd29ya2luZ3NldCkpCiAKICNp ZmRlZiBDT05GSUdfTFJVX0dFTgogCkBAIC0zNjEsNiArMzgzLDE2IEBAIGVudW0gewogCUxSVV9H RU5fRklMRSwKIH07CiAKKyNkZWZpbmUgTUlOX0xSVV9CQVRDSAkJQklUU19QRVJfTE9ORworI2Rl ZmluZSBNQVhfTFJVX0JBVENICQkoTUlOX0xSVV9CQVRDSCAqIDEyOCkKKworLyogd2hldGhlciB0 byBrZWVwIGhpc3RvcmljYWwgc3RhdHMgZnJvbSBldmljdGVkIGdlbmVyYXRpb25zICovCisjaWZk ZWYgQ09ORklHX0xSVV9HRU5fU1RBVFMKKyNkZWZpbmUgTlJfSElTVF9HRU5TCQlNQVhfTlJfR0VO UworI2Vsc2UKKyNkZWZpbmUgTlJfSElTVF9HRU5TCQkxVQorI2VuZGlmCisKIC8qCiAgKiBUaGUg eW91bmdlc3QgZ2VuZXJhdGlvbiBudW1iZXIgaXMgc3RvcmVkIGluIG1heF9zZXEgZm9yIGJvdGgg YW5vbiBhbmQgZmlsZQogICogdHlwZXMgYXMgdGhleSBhcmUgYWdlZCBvbiBhbiBlcXVhbCBmb290 aW5nLiBUaGUgb2xkZXN0IGdlbmVyYXRpb24gbnVtYmVycyBhcmUKQEAgLTM4MCw2ICs0MTIsMTUg QEAgc3RydWN0IGxydV9nZW5fc3RydWN0IHsKIAlzdHJ1Y3QgbGlzdF9oZWFkIGxpc3RzW01BWF9O Ul9HRU5TXVtBTk9OX0FORF9GSUxFXVtNQVhfTlJfWk9ORVNdOwogCS8qIHRoZSBzaXplcyBvZiB0 aGUgYWJvdmUgbGlzdHMgKi8KIAl1bnNpZ25lZCBsb25nIG5yX3BhZ2VzW01BWF9OUl9HRU5TXVtB Tk9OX0FORF9GSUxFXVtNQVhfTlJfWk9ORVNdOworCS8qIHRoZSBleHBvbmVudGlhbCBtb3Zpbmcg YXZlcmFnZSBvZiByZWZhdWx0ZWQgKi8KKwl1bnNpZ25lZCBsb25nIGF2Z19yZWZhdWx0ZWRbQU5P Tl9BTkRfRklMRV1bTUFYX05SX1RJRVJTXTsKKwkvKiB0aGUgZXhwb25lbnRpYWwgbW92aW5nIGF2 ZXJhZ2Ugb2YgZXZpY3RlZCtwcm90ZWN0ZWQgKi8KKwl1bnNpZ25lZCBsb25nIGF2Z190b3RhbFtB Tk9OX0FORF9GSUxFXVtNQVhfTlJfVElFUlNdOworCS8qIHRoZSBmaXJzdCB0aWVyIGRvZXNuJ3Qg bmVlZCBwcm90ZWN0aW9uLCBoZW5jZSB0aGUgbWludXMgb25lICovCisJdW5zaWduZWQgbG9uZyBw cm90ZWN0ZWRbTlJfSElTVF9HRU5TXVtBTk9OX0FORF9GSUxFXVtNQVhfTlJfVElFUlMgLSAxXTsK KwkvKiBjYW4gYmUgbW9kaWZpZWQgd2l0aG91dCBob2xkaW5nIHRoZSBMUlUgbG9jayAqLworCWF0 b21pY19sb25nX3QgZXZpY3RlZFtOUl9ISVNUX0dFTlNdW0FOT05fQU5EX0ZJTEVdW01BWF9OUl9U SUVSU107CisJYXRvbWljX2xvbmdfdCByZWZhdWx0ZWRbTlJfSElTVF9HRU5TXVtBTk9OX0FORF9G SUxFXVtNQVhfTlJfVElFUlNdOwogfTsKIAogdm9pZCBscnVfZ2VuX2luaXRfbHJ1dmVjKHN0cnVj dCBscnV2ZWMgKmxydXZlYyk7CmRpZmYgLS1naXQgYS9rZXJuZWwvYm91bmRzLmMgYi9rZXJuZWwv Ym91bmRzLmMKaW5kZXggZTA4ZmI4OWY4N2Y0Li4xMGRkOWU2YjAzZTUgMTAwNjQ0Ci0tLSBhL2tl cm5lbC9ib3VuZHMuYworKysgYi9rZXJuZWwvYm91bmRzLmMKQEAgLTI0LDcgKzI0LDcgQEAgaW50 IG1haW4odm9pZCkKIAlERUZJTkUoU1BJTkxPQ0tfU0laRSwgc2l6ZW9mKHNwaW5sb2NrX3QpKTsK ICNpZmRlZiBDT05GSUdfTFJVX0dFTgogCURFRklORShMUlVfR0VOX1dJRFRILCBvcmRlcl9iYXNl XzIoTUFYX05SX0dFTlMgKyAxKSk7Ci0JREVGSU5FKExSVV9SRUZTX1dJRFRILCAwKTsKKwlERUZJ TkUoTFJVX1JFRlNfV0lEVEgsIE1BWF9OUl9USUVSUyAtIDIpOwogI2Vsc2UKIAlERUZJTkUoTFJV X0dFTl9XSURUSCwgMCk7CiAJREVGSU5FKExSVV9SRUZTX1dJRFRILCAwKTsKZGlmZiAtLWdpdCBh L21tL0tjb25maWcgYi9tbS9LY29uZmlnCmluZGV4IDQ1OTVmYzY1NDE4MS4uYzQwNzc3ZDA5OGE4 IDEwMDY0NAotLS0gYS9tbS9LY29uZmlnCisrKyBiL21tL0tjb25maWcKQEAgLTkwOSw2ICs5MDks NyBAQCBjb25maWcgQU5PTl9WTUFfTkFNRQogCSAgYXJlYSBmcm9tIGJlaW5nIG1lcmdlZCB3aXRo IGFkamFjZW50IHZpcnR1YWwgbWVtb3J5IGFyZWFzIGR1ZSB0byB0aGUKIAkgIGRpZmZlcmVuY2Ug aW4gdGhlaXIgbmFtZS4KIAorIyBtdWx0aS1nZW4gTFJVIHsKIGNvbmZpZyBMUlVfR0VOCiAJYm9v bCAiTXVsdGktR2VuIExSVSIKIAlkZXBlbmRzIG9uIE1NVQpAQCAtOTE3LDYgKzkxOCwxNiBAQCBj b25maWcgTFJVX0dFTgogCWhlbHAKIAkgIEEgaGlnaCBwZXJmb3JtYW5jZSBMUlUgaW1wbGVtZW50 YXRpb24gdG8gb3ZlcmNvbW1pdCBtZW1vcnkuCiAKK2NvbmZpZyBMUlVfR0VOX1NUQVRTCisJYm9v bCAiRnVsbCBzdGF0cyBmb3IgZGVidWdnaW5nIgorCWRlcGVuZHMgb24gTFJVX0dFTgorCWhlbHAK KwkgIERvIG5vdCBlbmFibGUgdGhpcyBvcHRpb24gdW5sZXNzIHlvdSBwbGFuIHRvIGxvb2sgYXQg aGlzdG9yaWNhbCBzdGF0cworCSAgZnJvbSBldmljdGVkIGdlbmVyYXRpb25zIGZvciBkZWJ1Z2dp bmcgcHVycG9zZS4KKworCSAgVGhpcyBvcHRpb24gaGFzIGEgcGVyLW1lbWNnIGFuZCBwZXItbm9k ZSBtZW1vcnkgb3ZlcmhlYWQuCisjIH0KKwogc291cmNlICJtbS9kYW1vbi9LY29uZmlnIgogCiBl bmRtZW51CmRpZmYgLS1naXQgYS9tbS9zd2FwLmMgYi9tbS9zd2FwLmMKaW5kZXggYTY4NzBiYTBi ZDgzLi42YTUyMDNmMThiMGEgMTAwNjQ0Ci0tLSBhL21tL3N3YXAuYworKysgYi9tbS9zd2FwLmMK QEAgLTQwNSw2ICs0MDUsNDMgQEAgc3RhdGljIHZvaWQgX19scnVfY2FjaGVfYWN0aXZhdGVfZm9s aW8oc3RydWN0IGZvbGlvICpmb2xpbykKIAlsb2NhbF91bmxvY2soJmxydV9wdmVjcy5sb2NrKTsK IH0KIAorI2lmZGVmIENPTkZJR19MUlVfR0VOCitzdGF0aWMgdm9pZCBmb2xpb19pbmNfcmVmcyhz dHJ1Y3QgZm9saW8gKmZvbGlvKQoreworCXVuc2lnbmVkIGxvbmcgcmVmczsKKwl1bnNpZ25lZCBs b25nIG9sZF9mbGFncywgbmV3X2ZsYWdzOworCisJaWYgKGZvbGlvX3Rlc3RfdW5ldmljdGFibGUo Zm9saW8pKQorCQlyZXR1cm47CisKKwkvKiBzZWUgdGhlIGNvbW1lbnQgb24gTUFYX05SX1RJRVJT ICovCisJZG8geworCQluZXdfZmxhZ3MgPSBvbGRfZmxhZ3MgPSBSRUFEX09OQ0UoZm9saW8tPmZs YWdzKTsKKworCQlpZiAoIShuZXdfZmxhZ3MgJiBCSVQoUEdfcmVmZXJlbmNlZCkpKSB7CisJCQlu ZXdfZmxhZ3MgfD0gQklUKFBHX3JlZmVyZW5jZWQpOworCQkJY29udGludWU7CisJCX0KKworCQlp ZiAoIShuZXdfZmxhZ3MgJiBCSVQoUEdfd29ya2luZ3NldCkpKSB7CisJCQluZXdfZmxhZ3MgfD0g QklUKFBHX3dvcmtpbmdzZXQpOworCQkJY29udGludWU7CisJCX0KKworCQlyZWZzID0gbmV3X2Zs YWdzICYgTFJVX1JFRlNfTUFTSzsKKwkJcmVmcyA9IG1pbihyZWZzICsgQklUKExSVV9SRUZTX1BH T0ZGKSwgTFJVX1JFRlNfTUFTSyk7CisKKwkJbmV3X2ZsYWdzICY9IH5MUlVfUkVGU19NQVNLOwor CQluZXdfZmxhZ3MgfD0gcmVmczsKKwl9IHdoaWxlIChuZXdfZmxhZ3MgIT0gb2xkX2ZsYWdzICYm CisJCSBjbXB4Y2hnKCZmb2xpby0+ZmxhZ3MsIG9sZF9mbGFncywgbmV3X2ZsYWdzKSAhPSBvbGRf ZmxhZ3MpOworfQorI2Vsc2UKK3N0YXRpYyB2b2lkIGZvbGlvX2luY19yZWZzKHN0cnVjdCBmb2xp byAqZm9saW8pCit7Cit9CisjZW5kaWYgLyogQ09ORklHX0xSVV9HRU4gKi8KKwogLyoKICAqIE1h cmsgYSBwYWdlIGFzIGhhdmluZyBzZWVuIGFjdGl2aXR5LgogICoKQEAgLTQxNyw2ICs0NTQsMTEg QEAgc3RhdGljIHZvaWQgX19scnVfY2FjaGVfYWN0aXZhdGVfZm9saW8oc3RydWN0IGZvbGlvICpm b2xpbykKICAqLwogdm9pZCBmb2xpb19tYXJrX2FjY2Vzc2VkKHN0cnVjdCBmb2xpbyAqZm9saW8p CiB7CisJaWYgKGxydV9nZW5fZW5hYmxlZCgpKSB7CisJCWZvbGlvX2luY19yZWZzKGZvbGlvKTsK KwkJcmV0dXJuOworCX0KKwogCWlmICghZm9saW9fdGVzdF9yZWZlcmVuY2VkKGZvbGlvKSkgewog CQlmb2xpb19zZXRfcmVmZXJlbmNlZChmb2xpbyk7CiAJfSBlbHNlIGlmIChmb2xpb190ZXN0X3Vu ZXZpY3RhYmxlKGZvbGlvKSkgewpkaWZmIC0tZ2l0IGEvbW0vdm1zY2FuLmMgYi9tbS92bXNjYW4u YwppbmRleCAzN2RkNWQxYzNkMDcuLmJiM2Q3MDVjNTI4MiAxMDA2NDQKLS0tIGEvbW0vdm1zY2Fu LmMKKysrIGIvbW0vdm1zY2FuLmMKQEAgLTEyNzUsOSArMTI3NSwxMSBAQCBzdGF0aWMgaW50IF9f cmVtb3ZlX21hcHBpbmcoc3RydWN0IGFkZHJlc3Nfc3BhY2UgKm1hcHBpbmcsIHN0cnVjdCBmb2xp byAqZm9saW8sCiAKIAlpZiAoZm9saW9fdGVzdF9zd2FwY2FjaGUoZm9saW8pKSB7CiAJCXN3cF9l bnRyeV90IHN3YXAgPSBmb2xpb19zd2FwX2VudHJ5KGZvbGlvKTsKLQkJbWVtX2Nncm91cF9zd2Fw b3V0KGZvbGlvLCBzd2FwKTsKKworCQkvKiBnZXQgYSBzaGFkb3cgZW50cnkgYmVmb3JlIG1lbV9j Z3JvdXBfc3dhcG91dCgpIGNsZWFycyBmb2xpb19tZW1jZygpICovCiAJCWlmIChyZWNsYWltZWQg JiYgIW1hcHBpbmdfZXhpdGluZyhtYXBwaW5nKSkKIAkJCXNoYWRvdyA9IHdvcmtpbmdzZXRfZXZp Y3Rpb24oZm9saW8sIHRhcmdldF9tZW1jZyk7CisJCW1lbV9jZ3JvdXBfc3dhcG91dChmb2xpbywg c3dhcCk7CiAJCV9fZGVsZXRlX2Zyb21fc3dhcF9jYWNoZSgmZm9saW8tPnBhZ2UsIHN3YXAsIHNo YWRvdyk7CiAJCXhhX3VubG9ja19pcnEoJm1hcHBpbmctPmlfcGFnZXMpOwogCQlwdXRfc3dhcF9w YWdlKCZmb2xpby0+cGFnZSwgc3dhcCk7CkBAIC0yNjQ5LDYgKzI2NTEsOSBAQCBzdGF0aWMgdm9p ZCBwcmVwYXJlX3NjYW5fY291bnQocGdfZGF0YV90ICpwZ2RhdCwgc3RydWN0IHNjYW5fY29udHJv bCAqc2MpCiAJdW5zaWduZWQgbG9uZyBmaWxlOwogCXN0cnVjdCBscnV2ZWMgKnRhcmdldF9scnV2 ZWM7CiAKKwlpZiAobHJ1X2dlbl9lbmFibGVkKCkpCisJCXJldHVybjsKKwogCXRhcmdldF9scnV2 ZWMgPSBtZW1fY2dyb3VwX2xydXZlYyhzYy0+dGFyZ2V0X21lbV9jZ3JvdXAsIHBnZGF0KTsKIAog CS8qCkBAIC0yOTc0LDExICsyOTc5LDM4IEBAIHN0YXRpYyBib29sIGNhbl9hZ2VfYW5vbl9wYWdl cyhzdHJ1Y3QgcGdsaXN0X2RhdGEgKnBnZGF0LAogICogICAgICAgICAgICAgICAgICAgICAgICAg IHNob3J0aGFuZCBoZWxwZXJzCiAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwogCisjZGVmaW5lIERF RklORV9NQVhfU0VRKGxydXZlYykJCQkJCQlcCisJdW5zaWduZWQgbG9uZyBtYXhfc2VxID0gUkVB RF9PTkNFKChscnV2ZWMpLT5scnVnZW4ubWF4X3NlcSkKKworI2RlZmluZSBERUZJTkVfTUlOX1NF UShscnV2ZWMpCQkJCQkJXAorCXVuc2lnbmVkIGxvbmcgbWluX3NlcVtBTk9OX0FORF9GSUxFXSA9 IHsJCQlcCisJCVJFQURfT05DRSgobHJ1dmVjKS0+bHJ1Z2VuLm1pbl9zZXFbTFJVX0dFTl9BTk9O XSksCVwKKwkJUkVBRF9PTkNFKChscnV2ZWMpLT5scnVnZW4ubWluX3NlcVtMUlVfR0VOX0ZJTEVd KSwJXAorCX0KKwogI2RlZmluZSBmb3JfZWFjaF9nZW5fdHlwZV96b25lKGdlbiwgdHlwZSwgem9u ZSkJCQkJXAogCWZvciAoKGdlbikgPSAwOyAoZ2VuKSA8IE1BWF9OUl9HRU5TOyAoZ2VuKSsrKQkJ CVwKIAkJZm9yICgodHlwZSkgPSAwOyAodHlwZSkgPCBBTk9OX0FORF9GSUxFOyAodHlwZSkrKykJ XAogCQkJZm9yICgoem9uZSkgPSAwOyAoem9uZSkgPCBNQVhfTlJfWk9ORVM7ICh6b25lKSsrKQog CitzdGF0aWMgaW50IGZvbGlvX2xydV9nZW4oc3RydWN0IGZvbGlvICpmb2xpbykKK3sKKwl1bnNp Z25lZCBsb25nIGZsYWdzID0gUkVBRF9PTkNFKGZvbGlvLT5mbGFncyk7CisKKwlyZXR1cm4gKChm bGFncyAmIExSVV9HRU5fTUFTSykgPj4gTFJVX0dFTl9QR09GRikgLSAxOworfQorCitzdGF0aWMg aW50IGZvbGlvX2xydV90aWVyKHN0cnVjdCBmb2xpbyAqZm9saW8pCit7CisJaW50IHJlZnM7CisJ dW5zaWduZWQgbG9uZyBmbGFncyA9IFJFQURfT05DRShmb2xpby0+ZmxhZ3MpOworCisJcmVmcyA9 IChmbGFncyAmIExSVV9SRUZTX0ZMQUdTKSA9PSBMUlVfUkVGU19GTEFHUyA/CisJICAgICAgICgo ZmxhZ3MgJiBMUlVfUkVGU19NQVNLKSA+PiBMUlVfUkVGU19QR09GRikgKyAxIDogMDsKKworCXJl dHVybiBscnVfdGllcl9mcm9tX3JlZnMocmVmcyk7Cit9CisKIHN0YXRpYyBzdHJ1Y3QgbHJ1dmVj IF9fbWF5YmVfdW51c2VkICpnZXRfbHJ1dmVjKHN0cnVjdCBtZW1fY2dyb3VwICptZW1jZywgaW50 IG5pZCkKIHsKIAlzdHJ1Y3QgcGdsaXN0X2RhdGEgKnBnZGF0ID0gTk9ERV9EQVRBKG5pZCk7CkBA IC0yOTk5LDYgKzMwMzEsNzU0IEBAIHN0YXRpYyBzdHJ1Y3QgbHJ1dmVjIF9fbWF5YmVfdW51c2Vk ICpnZXRfbHJ1dmVjKHN0cnVjdCBtZW1fY2dyb3VwICptZW1jZywgaW50IG5pCiAJcmV0dXJuIHBn ZGF0ID8gJnBnZGF0LT5fX2xydXZlYyA6IE5VTEw7CiB9CiAKK3N0YXRpYyBpbnQgZ2V0X3N3YXBw aW5lc3Moc3RydWN0IGxydXZlYyAqbHJ1dmVjLCBzdHJ1Y3Qgc2Nhbl9jb250cm9sICpzYykKK3sK KwlzdHJ1Y3QgbWVtX2Nncm91cCAqbWVtY2cgPSBscnV2ZWNfbWVtY2cobHJ1dmVjKTsKKwlzdHJ1 Y3QgcGdsaXN0X2RhdGEgKnBnZGF0ID0gbHJ1dmVjX3BnZGF0KGxydXZlYyk7CisKKwlpZiAoIWNh bl9kZW1vdGUocGdkYXQtPm5vZGVfaWQsIHNjKSAmJgorCSAgICBtZW1fY2dyb3VwX2dldF9ucl9z d2FwX3BhZ2VzKG1lbWNnKSA8IE1JTl9MUlVfQkFUQ0gpCisJCXJldHVybiAwOworCisJcmV0dXJu IG1lbV9jZ3JvdXBfc3dhcHBpbmVzcyhtZW1jZyk7Cit9CisKK3N0YXRpYyBpbnQgZ2V0X25yX2dl bnMoc3RydWN0IGxydXZlYyAqbHJ1dmVjLCBpbnQgdHlwZSkKK3sKKwlyZXR1cm4gbHJ1dmVjLT5s cnVnZW4ubWF4X3NlcSAtIGxydXZlYy0+bHJ1Z2VuLm1pbl9zZXFbdHlwZV0gKyAxOworfQorCitz dGF0aWMgYm9vbCBfX21heWJlX3VudXNlZCBzZXFfaXNfdmFsaWQoc3RydWN0IGxydXZlYyAqbHJ1 dmVjKQoreworCS8qIHNlZSB0aGUgY29tbWVudCBvbiBscnVfZ2VuX3N0cnVjdCAqLworCXJldHVy biBnZXRfbnJfZ2VucyhscnV2ZWMsIExSVV9HRU5fRklMRSkgPj0gTUlOX05SX0dFTlMgJiYKKwkg ICAgICAgZ2V0X25yX2dlbnMobHJ1dmVjLCBMUlVfR0VOX0ZJTEUpIDw9IGdldF9ucl9nZW5zKGxy dXZlYywgTFJVX0dFTl9BTk9OKSAmJgorCSAgICAgICBnZXRfbnJfZ2VucyhscnV2ZWMsIExSVV9H RU5fQU5PTikgPD0gTUFYX05SX0dFTlM7Cit9CisKKy8qKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKKyAq ICAgICAgICAgICAgICAgICAgICAgICAgICByZWZhdWx0IGZlZWRiYWNrIGxvb3AKKyAqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKiovCisKKy8qCisgKiBBIGZlZWRiYWNrIGxvb3AgYmFzZWQgb24gUHJvcG9y dGlvbmFsLUludGVncmFsLURlcml2YXRpdmUgKFBJRCkgY29udHJvbGxlci4KKyAqCisgKiBUaGUg UCB0ZXJtIGlzIHJlZmF1bHRlZC8oZXZpY3RlZCtwcm90ZWN0ZWQpIGZyb20gYSB0aWVyIGluIHRo ZSBnZW5lcmF0aW9uCisgKiBjdXJyZW50bHkgYmVpbmcgZXZpY3RlZDsgdGhlIEkgdGVybSBpcyB0 aGUgZXhwb25lbnRpYWwgbW92aW5nIGF2ZXJhZ2Ugb2YgdGhlCisgKiBQIHRlcm0gb3ZlciB0aGUg Z2VuZXJhdGlvbnMgcHJldmlvdXNseSBldmljdGVkLCB1c2luZyB0aGUgc21vb3RoaW5nIGZhY3Rv cgorICogMS8yOyB0aGUgRCB0ZXJtIGlzbid0IHN1cHBvcnRlZC4KKyAqCisgKiBUaGUgc2V0cG9p bnQgKFNQKSBpcyBhbHdheXMgdGhlIGZpcnN0IHRpZXIgb2Ygb25lIHR5cGU7IHRoZSBwcm9jZXNz IHZhcmlhYmxlCisgKiAoUFYpIGlzIGVpdGhlciBhbnkgdGllciBvZiB0aGUgb3RoZXIgdHlwZSBv ciBhbnkgb3RoZXIgdGllciBvZiB0aGUgc2FtZQorICogdHlwZS4KKyAqCisgKiBUaGUgZXJyb3Ig aXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgU1AgYW5kIHRoZSBQVjsgdGhlIGNvcnJlY3Rp b24gaXMKKyAqIHR1cm4gb2ZmIHByb3RlY3Rpb24gd2hlbiBTUD5QViBvciB0dXJuIG9uIHByb3Rl Y3Rpb24gd2hlbiBTUDxQVi4KKyAqCisgKiBGb3IgZnV0dXJlIG9wdGltaXphdGlvbnM6CisgKiAx LiBUaGUgRCB0ZXJtIG1heSBkaXNjb3VudCB0aGUgb3RoZXIgdHdvIHRlcm1zIG92ZXIgdGltZSBz byB0aGF0IGxvbmctbGl2ZWQKKyAqICAgIGdlbmVyYXRpb25zIGNhbiByZXNpc3Qgc3RhbGUgaW5m b3JtYXRpb24uCisgKi8KK3N0cnVjdCBjdHJsX3BvcyB7CisJdW5zaWduZWQgbG9uZyByZWZhdWx0 ZWQ7CisJdW5zaWduZWQgbG9uZyB0b3RhbDsKKwlpbnQgZ2FpbjsKK307CisKK3N0YXRpYyB2b2lk IHJlYWRfY3RybF9wb3Moc3RydWN0IGxydXZlYyAqbHJ1dmVjLCBpbnQgdHlwZSwgaW50IHRpZXIs IGludCBnYWluLAorCQkJICBzdHJ1Y3QgY3RybF9wb3MgKnBvcykKK3sKKwlzdHJ1Y3QgbHJ1X2dl bl9zdHJ1Y3QgKmxydWdlbiA9ICZscnV2ZWMtPmxydWdlbjsKKwlpbnQgaGlzdCA9IGxydV9oaXN0 X2Zyb21fc2VxKGxydWdlbi0+bWluX3NlcVt0eXBlXSk7CisKKwlwb3MtPnJlZmF1bHRlZCA9IGxy dWdlbi0+YXZnX3JlZmF1bHRlZFt0eXBlXVt0aWVyXSArCisJCQkgYXRvbWljX2xvbmdfcmVhZCgm bHJ1Z2VuLT5yZWZhdWx0ZWRbaGlzdF1bdHlwZV1bdGllcl0pOworCXBvcy0+dG90YWwgPSBscnVn ZW4tPmF2Z190b3RhbFt0eXBlXVt0aWVyXSArCisJCSAgICAgYXRvbWljX2xvbmdfcmVhZCgmbHJ1 Z2VuLT5ldmljdGVkW2hpc3RdW3R5cGVdW3RpZXJdKTsKKwlpZiAodGllcikKKwkJcG9zLT50b3Rh bCArPSBscnVnZW4tPnByb3RlY3RlZFtoaXN0XVt0eXBlXVt0aWVyIC0gMV07CisJcG9zLT5nYWlu ID0gZ2FpbjsKK30KKworc3RhdGljIHZvaWQgcmVzZXRfY3RybF9wb3Moc3RydWN0IGxydXZlYyAq bHJ1dmVjLCBpbnQgdHlwZSwgYm9vbCBjYXJyeW92ZXIpCit7CisJaW50IGhpc3QsIHRpZXI7CisJ c3RydWN0IGxydV9nZW5fc3RydWN0ICpscnVnZW4gPSAmbHJ1dmVjLT5scnVnZW47CisJYm9vbCBj bGVhciA9IGNhcnJ5b3ZlciA/IE5SX0hJU1RfR0VOUyA9PSAxIDogTlJfSElTVF9HRU5TID4gMTsK Kwl1bnNpZ25lZCBsb25nIHNlcSA9IGNhcnJ5b3ZlciA/IGxydWdlbi0+bWluX3NlcVt0eXBlXSA6 IGxydWdlbi0+bWF4X3NlcSArIDE7CisKKwlsb2NrZGVwX2Fzc2VydF9oZWxkKCZscnV2ZWMtPmxy dV9sb2NrKTsKKworCWlmICghY2FycnlvdmVyICYmICFjbGVhcikKKwkJcmV0dXJuOworCisJaGlz dCA9IGxydV9oaXN0X2Zyb21fc2VxKHNlcSk7CisKKwlmb3IgKHRpZXIgPSAwOyB0aWVyIDwgTUFY X05SX1RJRVJTOyB0aWVyKyspIHsKKwkJaWYgKGNhcnJ5b3ZlcikgeworCQkJdW5zaWduZWQgbG9u ZyBzdW07CisKKwkJCXN1bSA9IGxydWdlbi0+YXZnX3JlZmF1bHRlZFt0eXBlXVt0aWVyXSArCisJ CQkgICAgICBhdG9taWNfbG9uZ19yZWFkKCZscnVnZW4tPnJlZmF1bHRlZFtoaXN0XVt0eXBlXVt0 aWVyXSk7CisJCQlXUklURV9PTkNFKGxydWdlbi0+YXZnX3JlZmF1bHRlZFt0eXBlXVt0aWVyXSwg c3VtIC8gMik7CisKKwkJCXN1bSA9IGxydWdlbi0+YXZnX3RvdGFsW3R5cGVdW3RpZXJdICsKKwkJ CSAgICAgIGF0b21pY19sb25nX3JlYWQoJmxydWdlbi0+ZXZpY3RlZFtoaXN0XVt0eXBlXVt0aWVy XSk7CisJCQlpZiAodGllcikKKwkJCQlzdW0gKz0gbHJ1Z2VuLT5wcm90ZWN0ZWRbaGlzdF1bdHlw ZV1bdGllciAtIDFdOworCQkJV1JJVEVfT05DRShscnVnZW4tPmF2Z190b3RhbFt0eXBlXVt0aWVy XSwgc3VtIC8gMik7CisJCX0KKworCQlpZiAoY2xlYXIpIHsKKwkJCWF0b21pY19sb25nX3NldCgm bHJ1Z2VuLT5yZWZhdWx0ZWRbaGlzdF1bdHlwZV1bdGllcl0sIDApOworCQkJYXRvbWljX2xvbmdf c2V0KCZscnVnZW4tPmV2aWN0ZWRbaGlzdF1bdHlwZV1bdGllcl0sIDApOworCQkJaWYgKHRpZXIp CisJCQkJV1JJVEVfT05DRShscnVnZW4tPnByb3RlY3RlZFtoaXN0XVt0eXBlXVt0aWVyIC0gMV0s IDApOworCQl9CisJfQorfQorCitzdGF0aWMgYm9vbCBwb3NpdGl2ZV9jdHJsX2VycihzdHJ1Y3Qg Y3RybF9wb3MgKnNwLCBzdHJ1Y3QgY3RybF9wb3MgKnB2KQoreworCS8qCisJICogUmV0dXJuIHRy dWUgaWYgdGhlIFBWIGhhcyBhIGxpbWl0ZWQgbnVtYmVyIG9mIHJlZmF1bHRzIG9yIGEgbG93ZXIK KwkgKiByZWZhdWx0ZWQvdG90YWwgdGhhbiB0aGUgU1AuCisJICovCisJcmV0dXJuIHB2LT5yZWZh dWx0ZWQgPCBNSU5fTFJVX0JBVENIIHx8CisJICAgICAgIHB2LT5yZWZhdWx0ZWQgKiAoc3AtPnRv dGFsICsgTUlOX0xSVV9CQVRDSCkgKiBzcC0+Z2FpbiA8PQorCSAgICAgICAoc3AtPnJlZmF1bHRl ZCArIDEpICogcHYtPnRvdGFsICogcHYtPmdhaW47Cit9CisKKy8qKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioKKyAqICAgICAgICAgICAgICAgICAgICAgICAgICB0aGUgYWdpbmcKKyAqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKiovCisKK3N0YXRpYyBpbnQgZm9saW9faW5jX2dlbihzdHJ1Y3QgbHJ1dmVjICpscnV2 ZWMsIHN0cnVjdCBmb2xpbyAqZm9saW8sIGJvb2wgcmVjbGFpbWluZykKK3sKKwl1bnNpZ25lZCBs b25nIG9sZF9mbGFncywgbmV3X2ZsYWdzOworCWludCB0eXBlID0gZm9saW9faXNfZmlsZV9scnUo Zm9saW8pOworCXN0cnVjdCBscnVfZ2VuX3N0cnVjdCAqbHJ1Z2VuID0gJmxydXZlYy0+bHJ1Z2Vu OworCWludCBuZXdfZ2VuLCBvbGRfZ2VuID0gbHJ1X2dlbl9mcm9tX3NlcShscnVnZW4tPm1pbl9z ZXFbdHlwZV0pOworCisJZG8geworCQluZXdfZmxhZ3MgPSBvbGRfZmxhZ3MgPSBSRUFEX09OQ0Uo Zm9saW8tPmZsYWdzKTsKKwkJVk1fQlVHX09OX0ZPTElPKCEobmV3X2ZsYWdzICYgTFJVX0dFTl9N QVNLKSwgZm9saW8pOworCisJCW5ld19nZW4gPSAob2xkX2dlbiArIDEpICUgTUFYX05SX0dFTlM7 CisKKwkJbmV3X2ZsYWdzICY9IH5MUlVfR0VOX01BU0s7CisJCW5ld19mbGFncyB8PSAobmV3X2dl biArIDFVTCkgPDwgTFJVX0dFTl9QR09GRjsKKwkJbmV3X2ZsYWdzICY9IH4oTFJVX1JFRlNfTUFT SyB8IExSVV9SRUZTX0ZMQUdTKTsKKwkJLyogZm9yIGZvbGlvX2VuZF93cml0ZWJhY2soKSAqLwor CQlpZiAocmVjbGFpbWluZykKKwkJCW5ld19mbGFncyB8PSBCSVQoUEdfcmVjbGFpbSk7CisJfSB3 aGlsZSAoY21weGNoZygmZm9saW8tPmZsYWdzLCBvbGRfZmxhZ3MsIG5ld19mbGFncykgIT0gb2xk X2ZsYWdzKTsKKworCWxydV9nZW5fdXBkYXRlX3NpemUobHJ1dmVjLCBmb2xpbywgb2xkX2dlbiwg bmV3X2dlbik7CisKKwlyZXR1cm4gbmV3X2dlbjsKK30KKworc3RhdGljIHZvaWQgaW5jX21pbl9z ZXEoc3RydWN0IGxydXZlYyAqbHJ1dmVjKQoreworCWludCB0eXBlOworCXN0cnVjdCBscnVfZ2Vu X3N0cnVjdCAqbHJ1Z2VuID0gJmxydXZlYy0+bHJ1Z2VuOworCisJVk1fQlVHX09OKCFzZXFfaXNf dmFsaWQobHJ1dmVjKSk7CisKKwlmb3IgKHR5cGUgPSAwOyB0eXBlIDwgQU5PTl9BTkRfRklMRTsg dHlwZSsrKSB7CisJCWlmIChnZXRfbnJfZ2VucyhscnV2ZWMsIHR5cGUpICE9IE1BWF9OUl9HRU5T KQorCQkJY29udGludWU7CisKKwkJcmVzZXRfY3RybF9wb3MobHJ1dmVjLCB0eXBlLCB0cnVlKTsK KwkJV1JJVEVfT05DRShscnVnZW4tPm1pbl9zZXFbdHlwZV0sIGxydWdlbi0+bWluX3NlcVt0eXBl XSArIDEpOworCX0KK30KKworc3RhdGljIGJvb2wgdHJ5X3RvX2luY19taW5fc2VxKHN0cnVjdCBs cnV2ZWMgKmxydXZlYywgYm9vbCBjYW5fc3dhcCkKK3sKKwlpbnQgZ2VuLCB0eXBlLCB6b25lOwor CWJvb2wgc3VjY2VzcyA9IGZhbHNlOworCXN0cnVjdCBscnVfZ2VuX3N0cnVjdCAqbHJ1Z2VuID0g JmxydXZlYy0+bHJ1Z2VuOworCURFRklORV9NSU5fU0VRKGxydXZlYyk7CisKKwlWTV9CVUdfT04o IXNlcV9pc192YWxpZChscnV2ZWMpKTsKKworCWZvciAodHlwZSA9ICFjYW5fc3dhcDsgdHlwZSA8 IEFOT05fQU5EX0ZJTEU7IHR5cGUrKykgeworCQl3aGlsZSAobWluX3NlcVt0eXBlXSArIE1JTl9O Ul9HRU5TIDw9IGxydWdlbi0+bWF4X3NlcSkgeworCQkJZ2VuID0gbHJ1X2dlbl9mcm9tX3NlcSht aW5fc2VxW3R5cGVdKTsKKworCQkJZm9yICh6b25lID0gMDsgem9uZSA8IE1BWF9OUl9aT05FUzsg em9uZSsrKSB7CisJCQkJaWYgKCFsaXN0X2VtcHR5KCZscnVnZW4tPmxpc3RzW2dlbl1bdHlwZV1b em9uZV0pKQorCQkJCQlnb3RvIG5leHQ7CisJCQl9CisKKwkJCW1pbl9zZXFbdHlwZV0rKzsKKwkJ fQorbmV4dDoKKwkJOworCX0KKworCS8qIHNlZSB0aGUgY29tbWVudCBvbiBscnVfZ2VuX3N0cnVj dCAqLworCWlmIChjYW5fc3dhcCkgeworCQltaW5fc2VxW0xSVV9HRU5fQU5PTl0gPSBtaW4obWlu X3NlcVtMUlVfR0VOX0FOT05dLCBtaW5fc2VxW0xSVV9HRU5fRklMRV0pOworCQltaW5fc2VxW0xS VV9HRU5fRklMRV0gPSBtYXgobWluX3NlcVtMUlVfR0VOX0FOT05dLCBscnVnZW4tPm1pbl9zZXFb TFJVX0dFTl9GSUxFXSk7CisJfQorCisJZm9yICh0eXBlID0gIWNhbl9zd2FwOyB0eXBlIDwgQU5P Tl9BTkRfRklMRTsgdHlwZSsrKSB7CisJCWlmIChtaW5fc2VxW3R5cGVdID09IGxydWdlbi0+bWlu X3NlcVt0eXBlXSkKKwkJCWNvbnRpbnVlOworCisJCXJlc2V0X2N0cmxfcG9zKGxydXZlYywgdHlw ZSwgdHJ1ZSk7CisJCVdSSVRFX09OQ0UobHJ1Z2VuLT5taW5fc2VxW3R5cGVdLCBtaW5fc2VxW3R5 cGVdKTsKKwkJc3VjY2VzcyA9IHRydWU7CisJfQorCisJcmV0dXJuIHN1Y2Nlc3M7Cit9CisKK3N0 YXRpYyB2b2lkIGluY19tYXhfc2VxKHN0cnVjdCBscnV2ZWMgKmxydXZlYywgdW5zaWduZWQgbG9u ZyBtYXhfc2VxKQoreworCWludCBwcmV2LCBuZXh0OworCWludCB0eXBlLCB6b25lOworCXN0cnVj dCBscnVfZ2VuX3N0cnVjdCAqbHJ1Z2VuID0gJmxydXZlYy0+bHJ1Z2VuOworCisJc3Bpbl9sb2Nr X2lycSgmbHJ1dmVjLT5scnVfbG9jayk7CisKKwlWTV9CVUdfT04oIXNlcV9pc192YWxpZChscnV2 ZWMpKTsKKworCWlmIChtYXhfc2VxICE9IGxydWdlbi0+bWF4X3NlcSkKKwkJZ290byB1bmxvY2s7 CisKKwlpbmNfbWluX3NlcShscnV2ZWMpOworCisJLyoKKwkgKiBVcGRhdGUgdGhlIGFjdGl2ZS9p bmFjdGl2ZSBMUlUgc2l6ZXMgZm9yIGNvbXBhdGliaWxpdHkuIEJvdGggc2lkZXMgb2YKKwkgKiB0 aGUgY3VycmVudCBtYXhfc2VxIG5lZWQgdG8gYmUgY292ZXJlZCwgc2luY2UgbWF4X3NlcSsxIGNh biBvdmVybGFwCisJICogd2l0aCBtaW5fc2VxW0xSVV9HRU5fQU5PTl0gaWYgc3dhcHBpbmcgaXMg Y29uc3RyYWluZWQuIEFuZCBpZiB0aGV5IGRvCisJICogb3ZlcmxhcCwgY29sZC9ob3QgaW52ZXJz aW9uIGhhcHBlbnMuIFRoaXMgY2FuIGJlIHNvbHZlZCBieSBtb3ZpbmcKKwkgKiBwYWdlcyBmcm9t IG1pbl9zZXEgdG8gbWluX3NlcSsxIGJ1dCBpcyBvbWl0dGVkIGZvciBzaW1wbGljaXR5LgorCSAq LworCXByZXYgPSBscnVfZ2VuX2Zyb21fc2VxKGxydWdlbi0+bWF4X3NlcSAtIDEpOworCW5leHQg PSBscnVfZ2VuX2Zyb21fc2VxKGxydWdlbi0+bWF4X3NlcSArIDEpOworCisJZm9yICh0eXBlID0g MDsgdHlwZSA8IEFOT05fQU5EX0ZJTEU7IHR5cGUrKykgeworCQlmb3IgKHpvbmUgPSAwOyB6b25l IDwgTUFYX05SX1pPTkVTOyB6b25lKyspIHsKKwkJCWVudW0gbHJ1X2xpc3QgbHJ1ID0gdHlwZSAq IExSVV9JTkFDVElWRV9GSUxFOworCQkJbG9uZyBkZWx0YSA9IGxydWdlbi0+bnJfcGFnZXNbcHJl dl1bdHlwZV1bem9uZV0gLQorCQkJCSAgICAgbHJ1Z2VuLT5ucl9wYWdlc1tuZXh0XVt0eXBlXVt6 b25lXTsKKworCQkJaWYgKCFkZWx0YSkKKwkJCQljb250aW51ZTsKKworCQkJX191cGRhdGVfbHJ1 X3NpemUobHJ1dmVjLCBscnUsIHpvbmUsIGRlbHRhKTsKKwkJCV9fdXBkYXRlX2xydV9zaXplKGxy dXZlYywgbHJ1ICsgTFJVX0FDVElWRSwgem9uZSwgLWRlbHRhKTsKKwkJfQorCX0KKworCWZvciAo dHlwZSA9IDA7IHR5cGUgPCBBTk9OX0FORF9GSUxFOyB0eXBlKyspCisJCXJlc2V0X2N0cmxfcG9z KGxydXZlYywgdHlwZSwgZmFsc2UpOworCisJLyogbWFrZSBzdXJlIHByZWNlZGluZyBtb2RpZmlj YXRpb25zIGFwcGVhciAqLworCXNtcF9zdG9yZV9yZWxlYXNlKCZscnVnZW4tPm1heF9zZXEsIGxy dWdlbi0+bWF4X3NlcSArIDEpOwordW5sb2NrOgorCXNwaW5fdW5sb2NrX2lycSgmbHJ1dmVjLT5s cnVfbG9jayk7Cit9CisKK3N0YXRpYyBsb25nIGdldF9ucl9ldmljdGFibGUoc3RydWN0IGxydXZl YyAqbHJ1dmVjLCB1bnNpZ25lZCBsb25nIG1heF9zZXEsCisJCQkgICAgIHVuc2lnbmVkIGxvbmcg Km1pbl9zZXEsIGJvb2wgY2FuX3N3YXAsIGJvb2wgKm5lZWRfYWdpbmcpCit7CisJaW50IGdlbiwg dHlwZSwgem9uZTsKKwlsb25nIG9sZCA9IDA7CisJbG9uZyB5b3VuZyA9IDA7CisJbG9uZyB0b3Rh bCA9IDA7CisJc3RydWN0IGxydV9nZW5fc3RydWN0ICpscnVnZW4gPSAmbHJ1dmVjLT5scnVnZW47 CisKKwlmb3IgKHR5cGUgPSAhY2FuX3N3YXA7IHR5cGUgPCBBTk9OX0FORF9GSUxFOyB0eXBlKysp IHsKKwkJdW5zaWduZWQgbG9uZyBzZXE7CisKKwkJZm9yIChzZXEgPSBtaW5fc2VxW3R5cGVdOyBz ZXEgPD0gbWF4X3NlcTsgc2VxKyspIHsKKwkJCWxvbmcgc2l6ZSA9IDA7CisKKwkJCWdlbiA9IGxy dV9nZW5fZnJvbV9zZXEoc2VxKTsKKworCQkJZm9yICh6b25lID0gMDsgem9uZSA8IE1BWF9OUl9a T05FUzsgem9uZSsrKQorCQkJCXNpemUgKz0gUkVBRF9PTkNFKGxydWdlbi0+bnJfcGFnZXNbZ2Vu XVt0eXBlXVt6b25lXSk7CisKKwkJCXRvdGFsICs9IHNpemU7CisJCQlpZiAoc2VxID09IG1heF9z ZXEpCisJCQkJeW91bmcgKz0gc2l6ZTsKKwkJCWlmIChzZXEgKyBNSU5fTlJfR0VOUyA9PSBtYXhf c2VxKQorCQkJCW9sZCArPSBzaXplOworCQl9CisJfQorCisJLyoKKwkgKiBUaGUgYWdpbmcgYW5k IHRoZSBldmljdGlvbiBpcyBhIHR5cGljYWwgcHJvZHVjZXItY29uc3VtZXIgbW9kZWwuIFRoZQor CSAqIGFnaW5nIHRyaWVzIHRvIGJlIGxhenkgdG8gcmVkdWNlIHRoZSB1bm5lY2Vzc2FyeSBvdmVy aGVhZC4gT24gdGhlCisJICogb3RoZXIgaGFuZCwgdGhlIGV2aWN0aW9uIHN0YWxscyB3aGVuIHRo ZSBudW1iZXIgb2YgZ2VuZXJhdGlvbnMKKwkgKiByZWFjaGVzIE1JTl9OUl9HRU5TLiBTbyBpZGVh bGx5LCB0aGVyZSBzaG91bGQgYmUgTUlOX05SX0dFTlMrMQorCSAqIGdlbmVyYXRpb25zLCBoZW5j ZSB0aGUgZmlyc3QgdHdvIGlmJ3MuCisJICoKKwkgKiBJbiBhZGRpdGlvbiwgaXQncyBpZGVhbCB0 byBzcHJlYWQgcGFnZXMgb3V0IGV2ZW5seSwgbWVhbmluZworCSAqIDEvKE1JTl9OUl9HRU5TKzEp IG9mIHRoZSB0b3RhbCBudW1iZXIgb2YgcGFnZXMgZm9yIGVhY2ggZ2VuZXJhdGlvbi4gQQorCSAq IHJlYXNvbmFibGUgcmFuZ2UgZm9yIHRoaXMgYXZlcmFnZSBwb3J0aW9uIHdvdWxkIFsxL01JTl9O Ul9HRU5TLAorCSAqIDEvKE1JTl9OUl9HRU5TKzIpXS4gRnJvbSB0aGUgY29uc3VtZXIncyBQT1Ys IHRoZSBldmljdGlvbiBvbmx5IGNhcmVzCisJICogYWJvdXQgdGhlIGxvd2VyIGJvdW5kIG9mIGNv bGQgcGFnZXMsIGkuZS4sIDEvKE1JTl9OUl9HRU5TKzIpLCB3aGVyZWFzCisJICogZnJvbSB0aGUg cHJvZHVjZXIncyBQT1YsIHRoZSBhZ2luZyBvbmx5IGNhcmVzIGFib3V0IHRoZSB1cHBlciBib3Vu ZAorCSAqIG9mIGhvdCBwYWdlcywgaS5lLiwgMS9NSU5fTlJfR0VOUy4KKwkgKi8KKwlpZiAobWlu X3NlcVtMUlVfR0VOX0ZJTEVdICsgTUlOX05SX0dFTlMgPiBtYXhfc2VxKQorCQkqbmVlZF9hZ2lu ZyA9IHRydWU7CisJZWxzZSBpZiAobWluX3NlcVtMUlVfR0VOX0ZJTEVdICsgTUlOX05SX0dFTlMg PCBtYXhfc2VxKQorCQkqbmVlZF9hZ2luZyA9IGZhbHNlOworCWVsc2UgaWYgKHlvdW5nICogTUlO X05SX0dFTlMgPiB0b3RhbCkKKwkJKm5lZWRfYWdpbmcgPSB0cnVlOworCWVsc2UgaWYgKG9sZCAq IChNSU5fTlJfR0VOUyArIDIpIDwgdG90YWwpCisJCSpuZWVkX2FnaW5nID0gdHJ1ZTsKKwllbHNl CisJCSpuZWVkX2FnaW5nID0gZmFsc2U7CisKKwlyZXR1cm4gdG90YWwgPiAwID8gdG90YWwgOiAw OworfQorCitzdGF0aWMgdm9pZCBhZ2VfbHJ1dmVjKHN0cnVjdCBscnV2ZWMgKmxydXZlYywgc3Ry dWN0IHNjYW5fY29udHJvbCAqc2MpCit7CisJYm9vbCBuZWVkX2FnaW5nOworCWxvbmcgbnJfdG9f c2NhbjsKKwlpbnQgc3dhcHBpbmVzcyA9IGdldF9zd2FwcGluZXNzKGxydXZlYywgc2MpOworCXN0 cnVjdCBtZW1fY2dyb3VwICptZW1jZyA9IGxydXZlY19tZW1jZyhscnV2ZWMpOworCURFRklORV9N QVhfU0VRKGxydXZlYyk7CisJREVGSU5FX01JTl9TRVEobHJ1dmVjKTsKKworCW1lbV9jZ3JvdXBf Y2FsY3VsYXRlX3Byb3RlY3Rpb24oTlVMTCwgbWVtY2cpOworCisJaWYgKG1lbV9jZ3JvdXBfYmVs b3dfbWluKG1lbWNnKSkKKwkJcmV0dXJuOworCisJbnJfdG9fc2NhbiA9IGdldF9ucl9ldmljdGFi bGUobHJ1dmVjLCBtYXhfc2VxLCBtaW5fc2VxLCBzd2FwcGluZXNzLCAmbmVlZF9hZ2luZyk7CisJ aWYgKCFucl90b19zY2FuKQorCQlyZXR1cm47CisKKwlucl90b19zY2FuID4+PSBzYy0+cHJpb3Jp dHk7CisKKwlpZiAoIW1lbV9jZ3JvdXBfb25saW5lKG1lbWNnKSkKKwkJbnJfdG9fc2NhbisrOwor CisJaWYgKG5yX3RvX3NjYW4gJiYgbmVlZF9hZ2luZyAmJiAoIW1lbV9jZ3JvdXBfYmVsb3dfbG93 KG1lbWNnKSB8fCBzYy0+bWVtY2dfbG93X3JlY2xhaW0pKQorCQlpbmNfbWF4X3NlcShscnV2ZWMs IG1heF9zZXEpOworfQorCitzdGF0aWMgdm9pZCBscnVfZ2VuX2FnZV9ub2RlKHN0cnVjdCBwZ2xp c3RfZGF0YSAqcGdkYXQsIHN0cnVjdCBzY2FuX2NvbnRyb2wgKnNjKQoreworCXN0cnVjdCBtZW1f Y2dyb3VwICptZW1jZzsKKworCVZNX0JVR19PTighY3VycmVudF9pc19rc3dhcGQoKSk7CisKKwlt ZW1jZyA9IG1lbV9jZ3JvdXBfaXRlcihOVUxMLCBOVUxMLCBOVUxMKTsKKwlkbyB7CisJCXN0cnVj dCBscnV2ZWMgKmxydXZlYyA9IG1lbV9jZ3JvdXBfbHJ1dmVjKG1lbWNnLCBwZ2RhdCk7CisKKwkJ YWdlX2xydXZlYyhscnV2ZWMsIHNjKTsKKworCQljb25kX3Jlc2NoZWQoKTsKKwl9IHdoaWxlICgo bWVtY2cgPSBtZW1fY2dyb3VwX2l0ZXIoTlVMTCwgbWVtY2csIE5VTEwpKSk7Cit9CisKKy8qKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioKKyAqICAgICAgICAgICAgICAgICAgICAgICAgICB0aGUgZXZpY3Rp b24KKyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKiovCisKK3N0YXRpYyBib29sIHNvcnRfZm9saW8oc3Ry dWN0IGxydXZlYyAqbHJ1dmVjLCBzdHJ1Y3QgZm9saW8gKmZvbGlvLCBpbnQgdGllcl9pZHgpCit7 CisJYm9vbCBzdWNjZXNzOworCWludCBnZW4gPSBmb2xpb19scnVfZ2VuKGZvbGlvKTsKKwlpbnQg dHlwZSA9IGZvbGlvX2lzX2ZpbGVfbHJ1KGZvbGlvKTsKKwlpbnQgem9uZSA9IGZvbGlvX3pvbmVu dW0oZm9saW8pOworCWludCB0aWVyID0gZm9saW9fbHJ1X3RpZXIoZm9saW8pOworCWludCBkZWx0 YSA9IGZvbGlvX25yX3BhZ2VzKGZvbGlvKTsKKwlzdHJ1Y3QgbHJ1X2dlbl9zdHJ1Y3QgKmxydWdl biA9ICZscnV2ZWMtPmxydWdlbjsKKworCVZNX0JVR19PTl9GT0xJTyhnZW4gPj0gTUFYX05SX0dF TlMsIGZvbGlvKTsKKworCWlmICghZm9saW9fZXZpY3RhYmxlKGZvbGlvKSkgeworCQlzdWNjZXNz ID0gbHJ1X2dlbl9kZWxfZm9saW8obHJ1dmVjLCBmb2xpbywgdHJ1ZSk7CisJCVZNX0JVR19PTl9G T0xJTyghc3VjY2VzcywgZm9saW8pOworCQlmb2xpb19zZXRfdW5ldmljdGFibGUoZm9saW8pOwor CQlscnV2ZWNfYWRkX2ZvbGlvKGxydXZlYywgZm9saW8pOworCQlfX2NvdW50X3ZtX2V2ZW50cyhV TkVWSUNUQUJMRV9QR0NVTExFRCwgZGVsdGEpOworCQlyZXR1cm4gdHJ1ZTsKKwl9CisKKwlpZiAo dHlwZSA9PSBMUlVfR0VOX0ZJTEUgJiYgZm9saW9fdGVzdF9hbm9uKGZvbGlvKSAmJiBmb2xpb190 ZXN0X2RpcnR5KGZvbGlvKSkgeworCQlzdWNjZXNzID0gbHJ1X2dlbl9kZWxfZm9saW8obHJ1dmVj LCBmb2xpbywgdHJ1ZSk7CisJCVZNX0JVR19PTl9GT0xJTyghc3VjY2VzcywgZm9saW8pOworCQlm b2xpb19zZXRfc3dhcGJhY2tlZChmb2xpbyk7CisJCWxydXZlY19hZGRfZm9saW9fdGFpbChscnV2 ZWMsIGZvbGlvKTsKKwkJcmV0dXJuIHRydWU7CisJfQorCisJaWYgKHRpZXIgPiB0aWVyX2lkeCkg eworCQlpbnQgaGlzdCA9IGxydV9oaXN0X2Zyb21fc2VxKGxydWdlbi0+bWluX3NlcVt0eXBlXSk7 CisKKwkJZ2VuID0gZm9saW9faW5jX2dlbihscnV2ZWMsIGZvbGlvLCBmYWxzZSk7CisJCWxpc3Rf bW92ZV90YWlsKCZmb2xpby0+bHJ1LCAmbHJ1Z2VuLT5saXN0c1tnZW5dW3R5cGVdW3pvbmVdKTsK KworCQlXUklURV9PTkNFKGxydWdlbi0+cHJvdGVjdGVkW2hpc3RdW3R5cGVdW3RpZXIgLSAxXSwK KwkJCSAgIGxydWdlbi0+cHJvdGVjdGVkW2hpc3RdW3R5cGVdW3RpZXIgLSAxXSArIGRlbHRhKTsK KwkJX19tb2RfbHJ1dmVjX3N0YXRlKGxydXZlYywgV09SS0lOR1NFVF9BQ1RJVkFURV9CQVNFICsg dHlwZSwgZGVsdGEpOworCQlyZXR1cm4gdHJ1ZTsKKwl9CisKKwlpZiAoZm9saW9fdGVzdF9sb2Nr ZWQoZm9saW8pIHx8IGZvbGlvX3Rlc3Rfd3JpdGViYWNrKGZvbGlvKSB8fAorCSAgICAodHlwZSA9 PSBMUlVfR0VOX0ZJTEUgJiYgZm9saW9fdGVzdF9kaXJ0eShmb2xpbykpKSB7CisJCWdlbiA9IGZv bGlvX2luY19nZW4obHJ1dmVjLCBmb2xpbywgdHJ1ZSk7CisJCWxpc3RfbW92ZSgmZm9saW8tPmxy dSwgJmxydWdlbi0+bGlzdHNbZ2VuXVt0eXBlXVt6b25lXSk7CisJCXJldHVybiB0cnVlOworCX0K KworCXJldHVybiBmYWxzZTsKK30KKworc3RhdGljIGJvb2wgaXNvbGF0ZV9mb2xpbyhzdHJ1Y3Qg bHJ1dmVjICpscnV2ZWMsIHN0cnVjdCBmb2xpbyAqZm9saW8sIHN0cnVjdCBzY2FuX2NvbnRyb2wg KnNjKQoreworCWJvb2wgc3VjY2VzczsKKworCWlmICghc2MtPm1heV91bm1hcCAmJiBmb2xpb19t YXBwZWQoZm9saW8pKQorCQlyZXR1cm4gZmFsc2U7CisKKwlpZiAoIShzYy0+bWF5X3dyaXRlcGFn ZSAmJiAoc2MtPmdmcF9tYXNrICYgX19HRlBfSU8pKSAmJgorCSAgICAoZm9saW9fdGVzdF9kaXJ0 eShmb2xpbykgfHwKKwkgICAgIChmb2xpb190ZXN0X2Fub24oZm9saW8pICYmICFmb2xpb190ZXN0 X3N3YXBjYWNoZShmb2xpbykpKSkKKwkJcmV0dXJuIGZhbHNlOworCisJaWYgKCFmb2xpb190cnlf Z2V0KGZvbGlvKSkKKwkJcmV0dXJuIGZhbHNlOworCisJaWYgKCFmb2xpb190ZXN0X2NsZWFyX2xy dShmb2xpbykpIHsKKwkJZm9saW9fcHV0KGZvbGlvKTsKKwkJcmV0dXJuIGZhbHNlOworCX0KKwor CXN1Y2Nlc3MgPSBscnVfZ2VuX2RlbF9mb2xpbyhscnV2ZWMsIGZvbGlvLCB0cnVlKTsKKwlWTV9C VUdfT05fRk9MSU8oIXN1Y2Nlc3MsIGZvbGlvKTsKKworCXJldHVybiB0cnVlOworfQorCitzdGF0 aWMgaW50IHNjYW5fZm9saW9zKHN0cnVjdCBscnV2ZWMgKmxydXZlYywgc3RydWN0IHNjYW5fY29u dHJvbCAqc2MsCisJCSAgICAgICBpbnQgdHlwZSwgaW50IHRpZXIsIHN0cnVjdCBsaXN0X2hlYWQg Kmxpc3QpCit7CisJaW50IGdlbiwgem9uZTsKKwllbnVtIHZtX2V2ZW50X2l0ZW0gaXRlbTsKKwlp bnQgc29ydGVkID0gMDsKKwlpbnQgc2Nhbm5lZCA9IDA7CisJaW50IGlzb2xhdGVkID0gMDsKKwlp bnQgcmVtYWluaW5nID0gTUFYX0xSVV9CQVRDSDsKKwlzdHJ1Y3QgbHJ1X2dlbl9zdHJ1Y3QgKmxy dWdlbiA9ICZscnV2ZWMtPmxydWdlbjsKKwlzdHJ1Y3QgbWVtX2Nncm91cCAqbWVtY2cgPSBscnV2 ZWNfbWVtY2cobHJ1dmVjKTsKKworCVZNX0JVR19PTighbGlzdF9lbXB0eShsaXN0KSk7CisKKwlp ZiAoZ2V0X25yX2dlbnMobHJ1dmVjLCB0eXBlKSA9PSBNSU5fTlJfR0VOUykKKwkJcmV0dXJuIDA7 CisKKwlnZW4gPSBscnVfZ2VuX2Zyb21fc2VxKGxydWdlbi0+bWluX3NlcVt0eXBlXSk7CisKKwlm b3IgKHpvbmUgPSBzYy0+cmVjbGFpbV9pZHg7IHpvbmUgPj0gMDsgem9uZS0tKSB7CisJCUxJU1Rf SEVBRChtb3ZlZCk7CisJCWludCBza2lwcGVkID0gMDsKKwkJc3RydWN0IGxpc3RfaGVhZCAqaGVh ZCA9ICZscnVnZW4tPmxpc3RzW2dlbl1bdHlwZV1bem9uZV07CisKKwkJd2hpbGUgKCFsaXN0X2Vt cHR5KGhlYWQpKSB7CisJCQlzdHJ1Y3QgZm9saW8gKmZvbGlvID0gbHJ1X3RvX2ZvbGlvKGhlYWQp OworCQkJaW50IGRlbHRhID0gZm9saW9fbnJfcGFnZXMoZm9saW8pOworCisJCQlWTV9CVUdfT05f Rk9MSU8oZm9saW9fdGVzdF91bmV2aWN0YWJsZShmb2xpbyksIGZvbGlvKTsKKwkJCVZNX0JVR19P Tl9GT0xJTyhmb2xpb190ZXN0X2FjdGl2ZShmb2xpbyksIGZvbGlvKTsKKwkJCVZNX0JVR19PTl9G T0xJTyhmb2xpb19pc19maWxlX2xydShmb2xpbykgIT0gdHlwZSwgZm9saW8pOworCQkJVk1fQlVH X09OX0ZPTElPKGZvbGlvX3pvbmVudW0oZm9saW8pICE9IHpvbmUsIGZvbGlvKTsKKworCQkJc2Nh bm5lZCArPSBkZWx0YTsKKworCQkJaWYgKHNvcnRfZm9saW8obHJ1dmVjLCBmb2xpbywgdGllcikp CisJCQkJc29ydGVkICs9IGRlbHRhOworCQkJZWxzZSBpZiAoaXNvbGF0ZV9mb2xpbyhscnV2ZWMs IGZvbGlvLCBzYykpIHsKKwkJCQlsaXN0X2FkZCgmZm9saW8tPmxydSwgbGlzdCk7CisJCQkJaXNv bGF0ZWQgKz0gZGVsdGE7CisJCQl9IGVsc2UgeworCQkJCWxpc3RfbW92ZSgmZm9saW8tPmxydSwg Jm1vdmVkKTsKKwkJCQlza2lwcGVkICs9IGRlbHRhOworCQkJfQorCisJCQlpZiAoIS0tcmVtYWlu aW5nIHx8IG1heChpc29sYXRlZCwgc2tpcHBlZCkgPj0gTUlOX0xSVV9CQVRDSCkKKwkJCQlicmVh azsKKwkJfQorCisJCWlmIChza2lwcGVkKSB7CisJCQlsaXN0X3NwbGljZSgmbW92ZWQsIGhlYWQp OworCQkJX19jb3VudF96aWRfdm1fZXZlbnRzKFBHU0NBTl9TS0lQLCB6b25lLCBza2lwcGVkKTsK KwkJfQorCisJCWlmICghcmVtYWluaW5nIHx8IGlzb2xhdGVkID49IE1JTl9MUlVfQkFUQ0gpCisJ CQlicmVhazsKKwl9CisKKwlpdGVtID0gY3VycmVudF9pc19rc3dhcGQoKSA/IFBHU0NBTl9LU1dB UEQgOiBQR1NDQU5fRElSRUNUOworCWlmICghY2dyb3VwX3JlY2xhaW0oc2MpKSB7CisJCV9fY291 bnRfdm1fZXZlbnRzKGl0ZW0sIGlzb2xhdGVkKTsKKwkJX19jb3VudF92bV9ldmVudHMoUEdSRUZJ TEwsIHNvcnRlZCk7CisJfQorCV9fY291bnRfbWVtY2dfZXZlbnRzKG1lbWNnLCBpdGVtLCBpc29s YXRlZCk7CisJX19jb3VudF9tZW1jZ19ldmVudHMobWVtY2csIFBHUkVGSUxMLCBzb3J0ZWQpOwor CV9fY291bnRfdm1fZXZlbnRzKFBHU0NBTl9BTk9OICsgdHlwZSwgaXNvbGF0ZWQpOworCisJLyoK KwkgKiBUaGVyZSBtaWdodCBub3QgYmUgZWxpZ2libGUgcGFnZXMgZHVlIHRvIHJlY2xhaW1faWR4 LCBtYXlfdW5tYXAgYW5kCisJICogbWF5X3dyaXRlcGFnZS4gQ2hlY2sgdGhlIHJlbWFpbmluZyB0 byBwcmV2ZW50IGxpdmVsb2NrIGlmIHRoZXJlIGlzIG5vCisJICogcHJvZ3Jlc3MuCisJICovCisJ cmV0dXJuIGlzb2xhdGVkIHx8ICFyZW1haW5pbmcgPyBzY2FubmVkIDogMDsKK30KKworc3RhdGlj IGludCBnZXRfdGllcl9pZHgoc3RydWN0IGxydXZlYyAqbHJ1dmVjLCBpbnQgdHlwZSkKK3sKKwlp bnQgdGllcjsKKwlzdHJ1Y3QgY3RybF9wb3Mgc3AsIHB2OworCisJLyoKKwkgKiBUbyBsZWF2ZSBh IG1hcmdpbiBmb3IgZmx1Y3R1YXRpb25zLCB1c2UgYSBsYXJnZXIgZ2FpbiBmYWN0b3IgKDE6Miku CisJICogVGhpcyB2YWx1ZSBpcyBjaG9zZW4gYmVjYXVzZSBhbnkgb3RoZXIgdGllciB3b3VsZCBo YXZlIGF0IGxlYXN0IHR3aWNlCisJICogYXMgbWFueSByZWZhdWx0cyBhcyB0aGUgZmlyc3QgdGll ci4KKwkgKi8KKwlyZWFkX2N0cmxfcG9zKGxydXZlYywgdHlwZSwgMCwgMSwgJnNwKTsKKwlmb3Ig KHRpZXIgPSAxOyB0aWVyIDwgTUFYX05SX1RJRVJTOyB0aWVyKyspIHsKKwkJcmVhZF9jdHJsX3Bv cyhscnV2ZWMsIHR5cGUsIHRpZXIsIDIsICZwdik7CisJCWlmICghcG9zaXRpdmVfY3RybF9lcnIo JnNwLCAmcHYpKQorCQkJYnJlYWs7CisJfQorCisJcmV0dXJuIHRpZXIgLSAxOworfQorCitzdGF0 aWMgaW50IGdldF90eXBlX3RvX3NjYW4oc3RydWN0IGxydXZlYyAqbHJ1dmVjLCBpbnQgc3dhcHBp bmVzcywgaW50ICp0aWVyX2lkeCkKK3sKKwlpbnQgdHlwZSwgdGllcjsKKwlzdHJ1Y3QgY3RybF9w b3Mgc3AsIHB2OworCWludCBnYWluW0FOT05fQU5EX0ZJTEVdID0geyBzd2FwcGluZXNzLCAyMDAg LSBzd2FwcGluZXNzIH07CisKKwkvKgorCSAqIENvbXBhcmUgdGhlIGZpcnN0IHRpZXIgb2YgYW5v biB3aXRoIHRoYXQgb2YgZmlsZSB0byBkZXRlcm1pbmUgd2hpY2gKKwkgKiB0eXBlIHRvIHNjYW4u IEFsc28gbmVlZCB0byBjb21wYXJlIG90aGVyIHRpZXJzIG9mIHRoZSBzZWxlY3RlZCB0eXBlCisJ ICogd2l0aCB0aGUgZmlyc3QgdGllciBvZiB0aGUgb3RoZXIgdHlwZSB0byBkZXRlcm1pbmUgdGhl IGxhc3QgdGllciAob2YKKwkgKiB0aGUgc2VsZWN0ZWQgdHlwZSkgdG8gZXZpY3QuCisJICovCisJ cmVhZF9jdHJsX3BvcyhscnV2ZWMsIExSVV9HRU5fQU5PTiwgMCwgZ2FpbltMUlVfR0VOX0FOT05d LCAmc3ApOworCXJlYWRfY3RybF9wb3MobHJ1dmVjLCBMUlVfR0VOX0ZJTEUsIDAsIGdhaW5bTFJV X0dFTl9GSUxFXSwgJnB2KTsKKwl0eXBlID0gcG9zaXRpdmVfY3RybF9lcnIoJnNwLCAmcHYpOwor CisJcmVhZF9jdHJsX3BvcyhscnV2ZWMsICF0eXBlLCAwLCBnYWluWyF0eXBlXSwgJnNwKTsKKwlm b3IgKHRpZXIgPSAxOyB0aWVyIDwgTUFYX05SX1RJRVJTOyB0aWVyKyspIHsKKwkJcmVhZF9jdHJs X3BvcyhscnV2ZWMsIHR5cGUsIHRpZXIsIGdhaW5bdHlwZV0sICZwdik7CisJCWlmICghcG9zaXRp dmVfY3RybF9lcnIoJnNwLCAmcHYpKQorCQkJYnJlYWs7CisJfQorCisJKnRpZXJfaWR4ID0gdGll ciAtIDE7CisKKwlyZXR1cm4gdHlwZTsKK30KKworc3RhdGljIGludCBpc29sYXRlX2ZvbGlvcyhz dHJ1Y3QgbHJ1dmVjICpscnV2ZWMsIHN0cnVjdCBzY2FuX2NvbnRyb2wgKnNjLCBpbnQgc3dhcHBp bmVzcywKKwkJCSAgaW50ICp0eXBlX3NjYW5uZWQsIHN0cnVjdCBsaXN0X2hlYWQgKmxpc3QpCit7 CisJaW50IGk7CisJaW50IHR5cGU7CisJaW50IHNjYW5uZWQ7CisJaW50IHRpZXIgPSAtMTsKKwlE RUZJTkVfTUlOX1NFUShscnV2ZWMpOworCisJVk1fQlVHX09OKCFzZXFfaXNfdmFsaWQobHJ1dmVj KSk7CisKKwkvKgorCSAqIFRyeSB0byBtYWtlIHRoZSBvYnZpb3VzIGNob2ljZSBmaXJzdC4gV2hl biBhbm9uIGFuZCBmaWxlIGFyZSBib3RoCisJICogYXZhaWxhYmxlIGZyb20gdGhlIHNhbWUgZ2Vu ZXJhdGlvbiwgaW50ZXJwcmV0IHN3YXBwaW5lc3MgMSBhcyBmaWxlCisJICogZmlyc3QgYW5kIDIw MCBhcyBhbm9uIGZpcnN0LgorCSAqLworCWlmICghc3dhcHBpbmVzcykKKwkJdHlwZSA9IExSVV9H RU5fRklMRTsKKwllbHNlIGlmIChtaW5fc2VxW0xSVV9HRU5fQU5PTl0gPCBtaW5fc2VxW0xSVV9H RU5fRklMRV0pCisJCXR5cGUgPSBMUlVfR0VOX0FOT047CisJZWxzZSBpZiAoc3dhcHBpbmVzcyA9 PSAxKQorCQl0eXBlID0gTFJVX0dFTl9GSUxFOworCWVsc2UgaWYgKHN3YXBwaW5lc3MgPT0gMjAw KQorCQl0eXBlID0gTFJVX0dFTl9BTk9OOworCWVsc2UKKwkJdHlwZSA9IGdldF90eXBlX3RvX3Nj YW4obHJ1dmVjLCBzd2FwcGluZXNzLCAmdGllcik7CisKKwlmb3IgKGkgPSAhc3dhcHBpbmVzczsg aSA8IEFOT05fQU5EX0ZJTEU7IGkrKykgeworCQlpZiAodGllciA8IDApCisJCQl0aWVyID0gZ2V0 X3RpZXJfaWR4KGxydXZlYywgdHlwZSk7CisKKwkJc2Nhbm5lZCA9IHNjYW5fZm9saW9zKGxydXZl Yywgc2MsIHR5cGUsIHRpZXIsIGxpc3QpOworCQlpZiAoc2Nhbm5lZCkKKwkJCWJyZWFrOworCisJ CXR5cGUgPSAhdHlwZTsKKwkJdGllciA9IC0xOworCX0KKworCSp0eXBlX3NjYW5uZWQgPSB0eXBl OworCisJcmV0dXJuIHNjYW5uZWQ7Cit9CisKK3N0YXRpYyBpbnQgZXZpY3RfZm9saW9zKHN0cnVj dCBscnV2ZWMgKmxydXZlYywgc3RydWN0IHNjYW5fY29udHJvbCAqc2MsIGludCBzd2FwcGluZXNz KQoreworCWludCB0eXBlOworCWludCBzY2FubmVkOworCWludCByZWNsYWltZWQ7CisJTElTVF9I RUFEKGxpc3QpOworCXN0cnVjdCBmb2xpbyAqZm9saW87CisJZW51bSB2bV9ldmVudF9pdGVtIGl0 ZW07CisJc3RydWN0IHJlY2xhaW1fc3RhdCBzdGF0OworCXN0cnVjdCBtZW1fY2dyb3VwICptZW1j ZyA9IGxydXZlY19tZW1jZyhscnV2ZWMpOworCXN0cnVjdCBwZ2xpc3RfZGF0YSAqcGdkYXQgPSBs cnV2ZWNfcGdkYXQobHJ1dmVjKTsKKworCXNwaW5fbG9ja19pcnEoJmxydXZlYy0+bHJ1X2xvY2sp OworCisJc2Nhbm5lZCA9IGlzb2xhdGVfZm9saW9zKGxydXZlYywgc2MsIHN3YXBwaW5lc3MsICZ0 eXBlLCAmbGlzdCk7CisKKwlpZiAodHJ5X3RvX2luY19taW5fc2VxKGxydXZlYywgc3dhcHBpbmVz cykpCisJCXNjYW5uZWQrKzsKKworCWlmIChnZXRfbnJfZ2VucyhscnV2ZWMsIExSVV9HRU5fRklM RSkgPT0gTUlOX05SX0dFTlMpCisJCXNjYW5uZWQgPSAwOworCisJc3Bpbl91bmxvY2tfaXJxKCZs cnV2ZWMtPmxydV9sb2NrKTsKKworCWlmIChsaXN0X2VtcHR5KCZsaXN0KSkKKwkJcmV0dXJuIHNj YW5uZWQ7CisKKwlyZWNsYWltZWQgPSBzaHJpbmtfcGFnZV9saXN0KCZsaXN0LCBwZ2RhdCwgc2Ms ICZzdGF0LCBmYWxzZSk7CisKKwkvKgorCSAqIFRvIGF2b2lkIGxpdmVsb2NrLCBkb24ndCBhZGQg cmVqZWN0ZWQgcGFnZXMgYmFjayB0byB0aGUgc2FtZSBsaXN0cworCSAqIHRoZXkgd2VyZSBpc29s YXRlZCBmcm9tLiBTZWUgbHJ1X2dlbl9hZGRfZm9saW8oKS4KKwkgKi8KKwlsaXN0X2Zvcl9lYWNo X2VudHJ5KGZvbGlvLCAmbGlzdCwgbHJ1KSB7CisJCWZvbGlvX2NsZWFyX3JlZmVyZW5jZWQoZm9s aW8pOworCQlmb2xpb19jbGVhcl93b3JraW5nc2V0KGZvbGlvKTsKKworCQlpZiAoZm9saW9fdGVz dF9yZWNsYWltKGZvbGlvKSAmJgorCQkgICAgKGZvbGlvX3Rlc3RfZGlydHkoZm9saW8pIHx8IGZv bGlvX3Rlc3Rfd3JpdGViYWNrKGZvbGlvKSkpCisJCQlmb2xpb19jbGVhcl9hY3RpdmUoZm9saW8p OworCQllbHNlCisJCQlmb2xpb19zZXRfYWN0aXZlKGZvbGlvKTsKKwl9CisKKwlzcGluX2xvY2tf aXJxKCZscnV2ZWMtPmxydV9sb2NrKTsKKworCW1vdmVfcGFnZXNfdG9fbHJ1KGxydXZlYywgJmxp c3QpOworCisJaXRlbSA9IGN1cnJlbnRfaXNfa3N3YXBkKCkgPyBQR1NURUFMX0tTV0FQRCA6IFBH U1RFQUxfRElSRUNUOworCWlmICghY2dyb3VwX3JlY2xhaW0oc2MpKQorCQlfX2NvdW50X3ZtX2V2 ZW50cyhpdGVtLCByZWNsYWltZWQpOworCV9fY291bnRfbWVtY2dfZXZlbnRzKG1lbWNnLCBpdGVt LCByZWNsYWltZWQpOworCV9fY291bnRfdm1fZXZlbnRzKFBHU1RFQUxfQU5PTiArIHR5cGUsIHJl Y2xhaW1lZCk7CisKKwlzcGluX3VubG9ja19pcnEoJmxydXZlYy0+bHJ1X2xvY2spOworCisJbWVt X2Nncm91cF91bmNoYXJnZV9saXN0KCZsaXN0KTsKKwlmcmVlX3VucmVmX3BhZ2VfbGlzdCgmbGlz dCk7CisKKwlzYy0+bnJfcmVjbGFpbWVkICs9IHJlY2xhaW1lZDsKKworCXJldHVybiBzY2FubmVk OworfQorCitzdGF0aWMgbG9uZyBnZXRfbnJfdG9fc2NhbihzdHJ1Y3QgbHJ1dmVjICpscnV2ZWMs IHN0cnVjdCBzY2FuX2NvbnRyb2wgKnNjLCBib29sIGNhbl9zd2FwKQoreworCWJvb2wgbmVlZF9h Z2luZzsKKwlsb25nIG5yX3RvX3NjYW47CisJc3RydWN0IG1lbV9jZ3JvdXAgKm1lbWNnID0gbHJ1 dmVjX21lbWNnKGxydXZlYyk7CisJREVGSU5FX01BWF9TRVEobHJ1dmVjKTsKKwlERUZJTkVfTUlO X1NFUShscnV2ZWMpOworCisJaWYgKG1lbV9jZ3JvdXBfYmVsb3dfbWluKG1lbWNnKSB8fAorCSAg ICAobWVtX2Nncm91cF9iZWxvd19sb3cobWVtY2cpICYmICFzYy0+bWVtY2dfbG93X3JlY2xhaW0p KQorCQlyZXR1cm4gMDsKKworCW5yX3RvX3NjYW4gPSBnZXRfbnJfZXZpY3RhYmxlKGxydXZlYywg bWF4X3NlcSwgbWluX3NlcSwgY2FuX3N3YXAsICZuZWVkX2FnaW5nKTsKKwlpZiAoIW5yX3RvX3Nj YW4pCisJCXJldHVybiAwOworCisJLyogcmVzZXQgdGhlIHByaW9yaXR5IGlmIHRoZSB0YXJnZXQg aGFzIGJlZW4gbWV0ICovCisJbnJfdG9fc2NhbiA+Pj0gc2MtPm5yX3JlY2xhaW1lZCA8IHNjLT5u cl90b19yZWNsYWltID8gc2MtPnByaW9yaXR5IDogREVGX1BSSU9SSVRZOworCisJaWYgKCFtZW1f Y2dyb3VwX29ubGluZShtZW1jZykpCisJCW5yX3RvX3NjYW4rKzsKKworCWlmICghbnJfdG9fc2Nh bikKKwkJcmV0dXJuIDA7CisKKwlpZiAoIW5lZWRfYWdpbmcpCisJCXJldHVybiBucl90b19zY2Fu OworCisJLyogbGVhdmUgdGhlIHdvcmsgdG8gbHJ1X2dlbl9hZ2Vfbm9kZSgpICovCisJaWYgKGN1 cnJlbnRfaXNfa3N3YXBkKCkpCisJCXJldHVybiAwOworCisJLyogdHJ5IG90aGVyIG1lbWNncyBi ZWZvcmUgZ29pbmcgdG8gdGhlIGFnaW5nIHBhdGggKi8KKwlpZiAoIWNncm91cF9yZWNsYWltKHNj KSAmJiAhc2MtPmZvcmNlX2RlYWN0aXZhdGUpIHsKKwkJc2MtPnNraXBwZWRfZGVhY3RpdmF0ZSA9 IHRydWU7CisJCXJldHVybiAwOworCX0KKworCWluY19tYXhfc2VxKGxydXZlYywgbWF4X3NlcSk7 CisKKwlyZXR1cm4gbnJfdG9fc2NhbjsKK30KKworc3RhdGljIHZvaWQgbHJ1X2dlbl9zaHJpbmtf bHJ1dmVjKHN0cnVjdCBscnV2ZWMgKmxydXZlYywgc3RydWN0IHNjYW5fY29udHJvbCAqc2MpCit7 CisJc3RydWN0IGJsa19wbHVnIHBsdWc7CisJbG9uZyBzY2FubmVkID0gMDsKKworCWxydV9hZGRf ZHJhaW4oKTsKKworCWJsa19zdGFydF9wbHVnKCZwbHVnKTsKKworCXdoaWxlICh0cnVlKSB7CisJ CWludCBkZWx0YTsKKwkJaW50IHN3YXBwaW5lc3M7CisJCWxvbmcgbnJfdG9fc2NhbjsKKworCQlp ZiAoc2MtPm1heV9zd2FwKQorCQkJc3dhcHBpbmVzcyA9IGdldF9zd2FwcGluZXNzKGxydXZlYywg c2MpOworCQllbHNlIGlmICghY2dyb3VwX3JlY2xhaW0oc2MpICYmIGdldF9zd2FwcGluZXNzKGxy dXZlYywgc2MpKQorCQkJc3dhcHBpbmVzcyA9IDE7CisJCWVsc2UKKwkJCXN3YXBwaW5lc3MgPSAw OworCisJCW5yX3RvX3NjYW4gPSBnZXRfbnJfdG9fc2NhbihscnV2ZWMsIHNjLCBzd2FwcGluZXNz KTsKKwkJaWYgKCFucl90b19zY2FuKQorCQkJYnJlYWs7CisKKwkJZGVsdGEgPSBldmljdF9mb2xp b3MobHJ1dmVjLCBzYywgc3dhcHBpbmVzcyk7CisJCWlmICghZGVsdGEpCisJCQlicmVhazsKKwor CQlzY2FubmVkICs9IGRlbHRhOworCQlpZiAoc2Nhbm5lZCA+PSBucl90b19zY2FuKQorCQkJYnJl YWs7CisKKwkJY29uZF9yZXNjaGVkKCk7CisJfQorCisJYmxrX2ZpbmlzaF9wbHVnKCZwbHVnKTsK K30KKwogLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKgogICogICAgICAgICAgICAgICAgICAgICAgICAg IGluaXRpYWxpemF0aW9uCiAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqLwpAQCAtMzA0MSw2ICszODIx LDE2IEBAIHN0YXRpYyBpbnQgX19pbml0IGluaXRfbHJ1X2dlbih2b2lkKQogfTsKIGxhdGVfaW5p dGNhbGwoaW5pdF9scnVfZ2VuKTsKIAorI2Vsc2UKKworc3RhdGljIHZvaWQgbHJ1X2dlbl9hZ2Vf bm9kZShzdHJ1Y3QgcGdsaXN0X2RhdGEgKnBnZGF0LCBzdHJ1Y3Qgc2Nhbl9jb250cm9sICpzYykK K3sKK30KKworc3RhdGljIHZvaWQgbHJ1X2dlbl9zaHJpbmtfbHJ1dmVjKHN0cnVjdCBscnV2ZWMg KmxydXZlYywgc3RydWN0IHNjYW5fY29udHJvbCAqc2MpCit7Cit9CisKICNlbmRpZiAvKiBDT05G SUdfTFJVX0dFTiAqLwogCiBzdGF0aWMgdm9pZCBzaHJpbmtfbHJ1dmVjKHN0cnVjdCBscnV2ZWMg KmxydXZlYywgc3RydWN0IHNjYW5fY29udHJvbCAqc2MpCkBAIC0zMDU0LDYgKzM4NDQsMTEgQEAg c3RhdGljIHZvaWQgc2hyaW5rX2xydXZlYyhzdHJ1Y3QgbHJ1dmVjICpscnV2ZWMsIHN0cnVjdCBz Y2FuX2NvbnRyb2wgKnNjKQogCXN0cnVjdCBibGtfcGx1ZyBwbHVnOwogCWJvb2wgc2Nhbl9hZGp1 c3RlZDsKIAorCWlmIChscnVfZ2VuX2VuYWJsZWQoKSkgeworCQlscnVfZ2VuX3Nocmlua19scnV2 ZWMobHJ1dmVjLCBzYyk7CisJCXJldHVybjsKKwl9CisKIAlnZXRfc2Nhbl9jb3VudChscnV2ZWMs IHNjLCBucik7CiAKIAkvKiBSZWNvcmQgdGhlIG9yaWdpbmFsIHNjYW4gdGFyZ2V0IGZvciBwcm9w b3J0aW9uYWwgYWRqdXN0bWVudHMgbGF0ZXIgKi8KQEAgLTM1NTgsNiArNDM1Myw5IEBAIHN0YXRp YyB2b2lkIHNuYXBzaG90X3JlZmF1bHRzKHN0cnVjdCBtZW1fY2dyb3VwICp0YXJnZXRfbWVtY2cs IHBnX2RhdGFfdCAqcGdkYXQpCiAJc3RydWN0IGxydXZlYyAqdGFyZ2V0X2xydXZlYzsKIAl1bnNp Z25lZCBsb25nIHJlZmF1bHRzOwogCisJaWYgKGxydV9nZW5fZW5hYmxlZCgpKQorCQlyZXR1cm47 CisKIAl0YXJnZXRfbHJ1dmVjID0gbWVtX2Nncm91cF9scnV2ZWModGFyZ2V0X21lbWNnLCBwZ2Rh dCk7CiAJcmVmYXVsdHMgPSBscnV2ZWNfcGFnZV9zdGF0ZSh0YXJnZXRfbHJ1dmVjLCBXT1JLSU5H U0VUX0FDVElWQVRFX0FOT04pOwogCXRhcmdldF9scnV2ZWMtPnJlZmF1bHRzWzBdID0gcmVmYXVs dHM7CkBAIC0zOTI4LDYgKzQ3MjYsMTEgQEAgc3RhdGljIHZvaWQgYWdlX2FjdGl2ZV9hbm9uKHN0 cnVjdCBwZ2xpc3RfZGF0YSAqcGdkYXQsCiAJc3RydWN0IG1lbV9jZ3JvdXAgKm1lbWNnOwogCXN0 cnVjdCBscnV2ZWMgKmxydXZlYzsKIAorCWlmIChscnVfZ2VuX2VuYWJsZWQoKSkgeworCQlscnVf Z2VuX2FnZV9ub2RlKHBnZGF0LCBzYyk7CisJCXJldHVybjsKKwl9CisKIAlpZiAoIWNhbl9hZ2Vf YW5vbl9wYWdlcyhwZ2RhdCwgc2MpKQogCQlyZXR1cm47CiAKZGlmZiAtLWdpdCBhL21tL3dvcmtp bmdzZXQuYyBiL21tL3dvcmtpbmdzZXQuYwppbmRleCA4YTM4MjhhY2MwYmYuLjg5YjQ2YWY3NGVl ZiAxMDA2NDQKLS0tIGEvbW0vd29ya2luZ3NldC5jCisrKyBiL21tL3dvcmtpbmdzZXQuYwpAQCAt MTg3LDcgKzE4Nyw2IEBAIHN0YXRpYyB1bnNpZ25lZCBpbnQgYnVja2V0X29yZGVyIF9fcmVhZF9t b3N0bHk7CiBzdGF0aWMgdm9pZCAqcGFja19zaGFkb3coaW50IG1lbWNnaWQsIHBnX2RhdGFfdCAq cGdkYXQsIHVuc2lnbmVkIGxvbmcgZXZpY3Rpb24sCiAJCQkgYm9vbCB3b3JraW5nc2V0KQogewot CWV2aWN0aW9uID4+PSBidWNrZXRfb3JkZXI7CiAJZXZpY3Rpb24gJj0gRVZJQ1RJT05fTUFTSzsK IAlldmljdGlvbiA9IChldmljdGlvbiA8PCBNRU1fQ0dST1VQX0lEX1NISUZUKSB8IG1lbWNnaWQ7 CiAJZXZpY3Rpb24gPSAoZXZpY3Rpb24gPDwgTk9ERVNfU0hJRlQpIHwgcGdkYXQtPm5vZGVfaWQ7 CkBAIC0yMTIsMTAgKzIxMSwxMTYgQEAgc3RhdGljIHZvaWQgdW5wYWNrX3NoYWRvdyh2b2lkICpz aGFkb3csIGludCAqbWVtY2dpZHAsIHBnX2RhdGFfdCAqKnBnZGF0LAogCiAJKm1lbWNnaWRwID0g bWVtY2dpZDsKIAkqcGdkYXQgPSBOT0RFX0RBVEEobmlkKTsKLQkqZXZpY3Rpb25wID0gZW50cnkg PDwgYnVja2V0X29yZGVyOworCSpldmljdGlvbnAgPSBlbnRyeTsKIAkqd29ya2luZ3NldHAgPSB3 b3JraW5nc2V0OwogfQogCisjaWZkZWYgQ09ORklHX0xSVV9HRU4KKworc3RhdGljIGludCBmb2xp b19scnVfcmVmcyhzdHJ1Y3QgZm9saW8gKmZvbGlvKQoreworCXVuc2lnbmVkIGxvbmcgZmxhZ3Mg PSBSRUFEX09OQ0UoZm9saW8tPmZsYWdzKTsKKworCUJVSUxEX0JVR19PTihMUlVfR0VOX1dJRFRI ICsgTFJVX1JFRlNfV0lEVEggPiBCSVRTX1BFUl9MT05HIC0gRVZJQ1RJT05fU0hJRlQpOworCisJ Lyogc2VlIHRoZSBjb21tZW50IG9uIE1BWF9OUl9USUVSUyAqLworCXJldHVybiBmbGFncyAmIEJJ VChQR193b3JraW5nc2V0KSA/IChmbGFncyAmIExSVV9SRUZTX01BU0spID4+IExSVV9SRUZTX1BH T0ZGIDogMDsKK30KKworc3RhdGljIHZvaWQgKmxydV9nZW5fZXZpY3Rpb24oc3RydWN0IGZvbGlv ICpmb2xpbykKK3sKKwlpbnQgaGlzdCwgdGllcjsKKwl1bnNpZ25lZCBsb25nIHRva2VuOworCXVu c2lnbmVkIGxvbmcgbWluX3NlcTsKKwlzdHJ1Y3QgbHJ1dmVjICpscnV2ZWM7CisJc3RydWN0IGxy dV9nZW5fc3RydWN0ICpscnVnZW47CisJaW50IHR5cGUgPSBmb2xpb19pc19maWxlX2xydShmb2xp byk7CisJaW50IHJlZnMgPSBmb2xpb19scnVfcmVmcyhmb2xpbyk7CisJaW50IGRlbHRhID0gZm9s aW9fbnJfcGFnZXMoZm9saW8pOworCWJvb2wgd29ya2luZ3NldCA9IGZvbGlvX3Rlc3Rfd29ya2lu Z3NldChmb2xpbyk7CisJc3RydWN0IG1lbV9jZ3JvdXAgKm1lbWNnID0gZm9saW9fbWVtY2coZm9s aW8pOworCXN0cnVjdCBwZ2xpc3RfZGF0YSAqcGdkYXQgPSBmb2xpb19wZ2RhdChmb2xpbyk7CisK KwlscnV2ZWMgPSBtZW1fY2dyb3VwX2xydXZlYyhtZW1jZywgcGdkYXQpOworCWxydWdlbiA9ICZs cnV2ZWMtPmxydWdlbjsKKwltaW5fc2VxID0gUkVBRF9PTkNFKGxydWdlbi0+bWluX3NlcVt0eXBl XSk7CisJdG9rZW4gPSAobWluX3NlcSA8PCBMUlVfUkVGU19XSURUSCkgfCByZWZzOworCisJaGlz dCA9IGxydV9oaXN0X2Zyb21fc2VxKG1pbl9zZXEpOworCXRpZXIgPSBscnVfdGllcl9mcm9tX3Jl ZnMocmVmcyArIHdvcmtpbmdzZXQpOworCWF0b21pY19sb25nX2FkZChkZWx0YSwgJmxydWdlbi0+ ZXZpY3RlZFtoaXN0XVt0eXBlXVt0aWVyXSk7CisKKwlyZXR1cm4gcGFja19zaGFkb3cobWVtX2Nn cm91cF9pZChtZW1jZyksIHBnZGF0LCB0b2tlbiwgd29ya2luZ3NldCk7Cit9CisKK3N0YXRpYyB2 b2lkIGxydV9nZW5fcmVmYXVsdChzdHJ1Y3QgZm9saW8gKmZvbGlvLCB2b2lkICpzaGFkb3cpCit7 CisJaW50IGhpc3QsIHRpZXIsIHJlZnM7CisJaW50IG1lbWNnX2lkOworCWJvb2wgd29ya2luZ3Nl dDsKKwl1bnNpZ25lZCBsb25nIHRva2VuOworCXVuc2lnbmVkIGxvbmcgbWluX3NlcTsKKwlzdHJ1 Y3QgbHJ1dmVjICpscnV2ZWM7CisJc3RydWN0IGxydV9nZW5fc3RydWN0ICpscnVnZW47CisJc3Ry dWN0IG1lbV9jZ3JvdXAgKm1lbWNnOworCXN0cnVjdCBwZ2xpc3RfZGF0YSAqcGdkYXQ7CisJaW50 IHR5cGUgPSBmb2xpb19pc19maWxlX2xydShmb2xpbyk7CisJaW50IGRlbHRhID0gZm9saW9fbnJf cGFnZXMoZm9saW8pOworCisJdW5wYWNrX3NoYWRvdyhzaGFkb3csICZtZW1jZ19pZCwgJnBnZGF0 LCAmdG9rZW4sICZ3b3JraW5nc2V0KTsKKworCXJlZnMgPSB0b2tlbiAmIChCSVQoTFJVX1JFRlNf V0lEVEgpIC0gMSk7CisJaWYgKHJlZnMgJiYgIXdvcmtpbmdzZXQpCisJCXJldHVybjsKKworCWlm IChmb2xpb19wZ2RhdChmb2xpbykgIT0gcGdkYXQpCisJCXJldHVybjsKKworCXJjdV9yZWFkX2xv Y2soKTsKKwltZW1jZyA9IGZvbGlvX21lbWNnX3JjdShmb2xpbyk7CisJaWYgKG1lbV9jZ3JvdXBf aWQobWVtY2cpICE9IG1lbWNnX2lkKQorCQlnb3RvIHVubG9jazsKKworCXRva2VuID4+PSBMUlVf UkVGU19XSURUSDsKKwlscnV2ZWMgPSBtZW1fY2dyb3VwX2xydXZlYyhtZW1jZywgcGdkYXQpOwor CWxydWdlbiA9ICZscnV2ZWMtPmxydWdlbjsKKwltaW5fc2VxID0gUkVBRF9PTkNFKGxydWdlbi0+ bWluX3NlcVt0eXBlXSk7CisJaWYgKHRva2VuICE9IChtaW5fc2VxICYgKEVWSUNUSU9OX01BU0sg Pj4gTFJVX1JFRlNfV0lEVEgpKSkKKwkJZ290byB1bmxvY2s7CisKKwloaXN0ID0gbHJ1X2hpc3Rf ZnJvbV9zZXEobWluX3NlcSk7CisJdGllciA9IGxydV90aWVyX2Zyb21fcmVmcyhyZWZzICsgd29y a2luZ3NldCk7CisJYXRvbWljX2xvbmdfYWRkKGRlbHRhLCAmbHJ1Z2VuLT5yZWZhdWx0ZWRbaGlz dF1bdHlwZV1bdGllcl0pOworCW1vZF9scnV2ZWNfc3RhdGUobHJ1dmVjLCBXT1JLSU5HU0VUX1JF RkFVTFRfQkFTRSArIHR5cGUsIGRlbHRhKTsKKworCS8qCisJICogQ291bnQgdGhlIGZvbGxvd2lu ZyB0d28gY2FzZXMgYXMgc3RhbGxzOgorCSAqIDEuIEZvciBwYWdlcyBhY2Nlc3NlZCB0aHJvdWdo IHBhZ2UgdGFibGVzLCBob3R0ZXIgcGFnZXMgcHVzaGVkIG91dAorCSAqICAgIGhvdCBwYWdlcyB3 aGljaCByZWZhdWx0ZWQgaW1tZWRpYXRlbHkuCisJICogMi4gRm9yIHBhZ2VzIGFjY2Vzc2VkIHRo cm91Z2ggZmlsZSBkZXNjcmlwdG9ycywgbnVtYmVycyBvZiBhY2Nlc3NlcworCSAqICAgIG1pZ2h0 IGhhdmUgYmVlbiBiZXlvbmQgdGhlIGxpbWl0LgorCSAqLworCWlmIChscnVfZ2VuX2luX2ZhdWx0 KCkgfHwgcmVmcyArIHdvcmtpbmdzZXQgPT0gQklUKExSVV9SRUZTX1dJRFRIKSkgeworCQlmb2xp b19zZXRfd29ya2luZ3NldChmb2xpbyk7CisJCW1vZF9scnV2ZWNfc3RhdGUobHJ1dmVjLCBXT1JL SU5HU0VUX1JFU1RPUkVfQkFTRSArIHR5cGUsIGRlbHRhKTsKKwl9Cit1bmxvY2s6CisJcmN1X3Jl YWRfdW5sb2NrKCk7Cit9CisKKyNlbHNlCisKK3N0YXRpYyB2b2lkICpscnVfZ2VuX2V2aWN0aW9u KHN0cnVjdCBmb2xpbyAqZm9saW8pCit7CisJcmV0dXJuIE5VTEw7Cit9CisKK3N0YXRpYyB2b2lk IGxydV9nZW5fcmVmYXVsdChzdHJ1Y3QgZm9saW8gKmZvbGlvLCB2b2lkICpzaGFkb3cpCit7Cit9 CisKKyNlbmRpZiAvKiBDT05GSUdfTFJVX0dFTiAqLworCiAvKioKICAqIHdvcmtpbmdzZXRfYWdl X25vbnJlc2lkZW50IC0gYWdlIG5vbi1yZXNpZGVudCBlbnRyaWVzIGFzIExSVSBhZ2VzCiAgKiBA bHJ1dmVjOiB0aGUgbHJ1dmVjIHRoYXQgd2FzIGFnZWQKQEAgLTI2NCwxMCArMzY5LDE0IEBAIHZv aWQgKndvcmtpbmdzZXRfZXZpY3Rpb24oc3RydWN0IGZvbGlvICpmb2xpbywgc3RydWN0IG1lbV9j Z3JvdXAgKnRhcmdldF9tZW1jZykKIAlWTV9CVUdfT05fRk9MSU8oZm9saW9fcmVmX2NvdW50KGZv bGlvKSwgZm9saW8pOwogCVZNX0JVR19PTl9GT0xJTyghZm9saW9fdGVzdF9sb2NrZWQoZm9saW8p LCBmb2xpbyk7CiAKKwlpZiAobHJ1X2dlbl9lbmFibGVkKCkpCisJCXJldHVybiBscnVfZ2VuX2V2 aWN0aW9uKGZvbGlvKTsKKwogCWxydXZlYyA9IG1lbV9jZ3JvdXBfbHJ1dmVjKHRhcmdldF9tZW1j ZywgcGdkYXQpOwogCS8qIFhYWDogdGFyZ2V0X21lbWNnIGNhbiBiZSBOVUxMLCBnbyB0aHJvdWdo IGxydXZlYyAqLwogCW1lbWNnaWQgPSBtZW1fY2dyb3VwX2lkKGxydXZlY19tZW1jZyhscnV2ZWMp KTsKIAlldmljdGlvbiA9IGF0b21pY19sb25nX3JlYWQoJmxydXZlYy0+bm9ucmVzaWRlbnRfYWdl KTsKKwlldmljdGlvbiA+Pj0gYnVja2V0X29yZGVyOwogCXdvcmtpbmdzZXRfYWdlX25vbnJlc2lk ZW50KGxydXZlYywgZm9saW9fbnJfcGFnZXMoZm9saW8pKTsKIAlyZXR1cm4gcGFja19zaGFkb3co bWVtY2dpZCwgcGdkYXQsIGV2aWN0aW9uLAogCQkJCWZvbGlvX3Rlc3Rfd29ya2luZ3NldChmb2xp bykpOwpAQCAtMjk4LDcgKzQwNywxMyBAQCB2b2lkIHdvcmtpbmdzZXRfcmVmYXVsdChzdHJ1Y3Qg Zm9saW8gKmZvbGlvLCB2b2lkICpzaGFkb3cpCiAJaW50IG1lbWNnaWQ7CiAJbG9uZyBucjsKIAor CWlmIChscnVfZ2VuX2VuYWJsZWQoKSkgeworCQlscnVfZ2VuX3JlZmF1bHQoZm9saW8sIHNoYWRv dyk7CisJCXJldHVybjsKKwl9CisKIAl1bnBhY2tfc2hhZG93KHNoYWRvdywgJm1lbWNnaWQsICZw Z2RhdCwgJmV2aWN0aW9uLCAmd29ya2luZ3NldCk7CisJZXZpY3Rpb24gPDw9IGJ1Y2tldF9vcmRl cjsKIAogCXJjdV9yZWFkX2xvY2soKTsKIAkvKgotLSAKMi4zNS4xLjEwOTQuZzdjN2Q5MDJhN2Mt Z29vZwoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fCmxp bnV4LWFybS1rZXJuZWwgbWFpbGluZyBsaXN0CmxpbnV4LWFybS1rZXJuZWxAbGlzdHMuaW5mcmFk ZWFkLm9yZwpodHRwOi8vbGlzdHMuaW5mcmFkZWFkLm9yZy9tYWlsbWFuL2xpc3RpbmZvL2xpbnV4 LWFybS1rZXJuZWwK