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 BB965C433FE for ; Wed, 9 Mar 2022 01:11:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230215AbiCIBMV (ORCPT ); Tue, 8 Mar 2022 20:12:21 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35586 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230156AbiCIBLw (ORCPT ); Tue, 8 Mar 2022 20:11:52 -0500 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B5CED151D0F for ; Tue, 8 Mar 2022 16:54:23 -0800 (PST) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-2dbd2b5e180so5053997b3.3 for ; Tue, 08 Mar 2022 16:54:23 -0800 (PST) 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=J4iV8TqXH16u/tC95j8R0lEvScYBodg+K2oq/7ewN3M=; b=mX94ozPIM7SjS4QUKbvtFezeiRvLas3xKix72rdcvEwUaSIpIuSOcqui3Iug5heqHk HSfUTPyE3Vhx+fw+LjULVYKXUxf2VmcKlHLi4ZgrZowee7Rx60lAFDw6Xkm2fIBcM7zp WOXB2oc05Pd0Fqv5l1Gl/lsyJZ3F4w+ol/hC3M3uUinwqN3V+NKbu/FkztERIRMw/4u5 BirUe2gKU5QZlM+Dlf3jIeYUfxICzgTCrmkZYSjZwKM+SfeR20qhy6e8o8B5OGKCf0ce gFY0ux+Q8vR1rJEvZEbW6rmJklLj2JWzFQ6DhK1Vv14/M/oTMlPqFWzKQeebqwyk78ce uGWA== 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=J4iV8TqXH16u/tC95j8R0lEvScYBodg+K2oq/7ewN3M=; b=NiEoYMkGRoVuMkrbJ0mIqd+KY9kRR6B7N8kGOJnN6cPEFTvD6kstmN6gvpLFjCo2Ey Q7KCuAIyYmSLBIRVp8ppARNBWSRAtyYtJgDSY6TP9wsScWh7hciycoQQrU7tQf8h5KmX laKPS4G9vc28BRpgfqBRRC/F3HSeEfQzHGHpQKl8UtS1C7nPV3zjNfxZ6Wo6hjFf+BLw d3Qf4o8d6QmkmRFKDCIb66LLEWGOL1KrEDYtjiTN6UlkX9RGI5BAllJOvYJHCv1hTFWw 5JfCorCTVXL5+s7jOKJ3V3tuDRuFW6lMO/oKK6svuzjKmLFmsbZLErksnU18sRai80CX q7OQ== X-Gm-Message-State: AOAM533JZ1zp5FUxkWQdos/8dp0qDiCj60italqvmYwNcRr8FgQFaGDG IRLHj8yWsFnE4FBeq8GupnXuov4jqWw= X-Google-Smtp-Source: ABdhPJzMpfupIYazJ6X8iOdnFy9F/QzQaESvDZm+Xx/asrt7+wuyyeqffmoPwzVJ2TJv4aYHJj68LeNkZ5Q= X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:57a6:54a6:aad1:c0a8]) (user=yuzhao job=sendgmr) by 2002:a25:5187:0:b0:623:e9ba:ba13 with SMTP id f129-20020a255187000000b00623e9baba13mr14304113ybb.311.1646783312530; Tue, 08 Mar 2022 15:48:32 -0800 (PST) Date: Tue, 8 Mar 2022 16:47:16 -0700 In-Reply-To: <20220308234723.3834941-1-yuzhao@google.com> Message-Id: <20220308234723.3834941-7-yuzhao@google.com> Mime-Version: 1.0 References: <20220308234723.3834941-1-yuzhao@google.com> X-Mailer: git-send-email 2.35.1.616.g0bdcbb4464-goog Subject: [PATCH v8 06/14] mm: multi-gen LRU: minimal implementation From: Yu Zhao To: Andrew Morton Cc: Andi Kleen , Aneesh Kumar , 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, linux-mm@kvack.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): +[47, 49]% IOPS BW 5.17-rc2: 2242k 8759MiB/s patch1-5: 3321k 12.7GiB/s Single workload: memcached (anon): +[101, 105]% Ops/sec KB/sec 5.17-rc2: 476771.79 18544.31 patch1-5: 972526.07 37826.95 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.17-rc2 38.05% page_vma_mapped_walk 20.86% lzo1x_1_do_compress (real work) 6.16% do_raw_spin_lock 4.61% _raw_spin_unlock_irq 2.20% vma_interval_tree_iter_next 2.19% vma_interval_tree_subtree_search 2.15% page_referenced_one 1.93% anon_vma_interval_tree_iter_first 1.65% ptep_clear_flush 1.00% __zram_bvec_write patch1-5 39.73% lzo1x_1_do_compress (real work) 14.96% page_vma_mapped_walk 6.97% _raw_spin_unlock_irq 3.07% do_raw_spin_lock 2.53% anon_vma_interval_tree_iter_first 2.04% ptep_clear_flush 1.82% __zram_bvec_write 1.76% __anon_vma_interval_tree_subtree_search 1.57% memmove 1.45% free_unref_page_list 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.h | 1 + include/linux/mm_inline.h | 24 + include/linux/mmzone.h | 38 ++ include/linux/page-flags-layout.h | 2 +- mm/Kconfig | 20 + mm/swap.c | 42 ++ mm/vmscan.c | 786 +++++++++++++++++++++++++++++- mm/workingset.c | 119 ++++- 8 files changed, 1028 insertions(+), 4 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index c1162659d824..1e3e6dd90c0f 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -227,6 +227,7 @@ int overcommit_policy_handler(struct ctl_table *, int, = void *, size_t *, #define PAGE_ALIGNED(addr) IS_ALIGNED((unsigned long)(addr), PAGE_SIZE) =20 #define lru_to_page(head) (list_entry((head)->prev, struct page, lru)) +#define lru_to_folio(head) (list_entry((head)->prev, struct folio, lru)) =20 void setup_initial_init_mm(void *start_code, void *end_code, void *end_data, void *brk); diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index e3594171b421..15a04a9b5560 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 & LRU_REFS_FLAGS) !=3D LRU_REFS_FLAGS) + 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 a8eb619f742c..b92fc0ef8762 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -315,6 +315,9 @@ enum { LRU_GEN_FILE, }; =20 +#define MIN_LRU_BATCH BITS_PER_LONG +#define MAX_LRU_BATCH (MIN_LRU_BATCH * 128) + /* * Evictable pages are divided into multiple generations. The youngest and= the * oldest generation numbers, max_seq and min_seq, are monotonically incre= asing. @@ -339,6 +342,32 @@ enum { #define MIN_NR_GENS 2U #define MAX_NR_GENS ((unsigned int)CONFIG_NR_LRU_GENS) =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. Additional bits in folio->flags are + * required to support more than two tiers. + * + * 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. + */ +#define MAX_NR_TIERS ((unsigned int)CONFIG_TIERS_PER_GEN) +#define LRU_REFS_FLAGS (BIT(PG_referenced) | BIT(PG_workingset)) + +/* whether to keep historical stats from evicted generations */ +#ifdef CONFIG_LRU_GEN_STATS +#define NR_HIST_GENS ((unsigned int)CONFIG_NR_LRU_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 @@ -358,6 +387,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/include/linux/page-flags-layout.h b/include/linux/page-flags-l= ayout.h index db47ebd672e8..8cdbbdccb5ad 100644 --- a/include/linux/page-flags-layout.h +++ b/include/linux/page-flags-layout.h @@ -28,7 +28,7 @@ =20 #ifdef CONFIG_LRU_GEN /* LRU_GEN_WIDTH is generated from order_base_2(CONFIG_NR_LRU_GENS + 1). *= / -#define LRU_REFS_WIDTH 0 +#define LRU_REFS_WIDTH (CONFIG_TIERS_PER_GEN - 2) #else #define LRU_GEN_WIDTH 0 #define LRU_REFS_WIDTH 0 diff --git a/mm/Kconfig b/mm/Kconfig index 4ef67f157374..d4aa3d881269 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -912,6 +912,26 @@ config NR_LRU_GENS scheduling optimizations in data centers. =20 This option uses order_base_2(N+1) bits in page flags. + +config TIERS_PER_GEN + int "Number of tiers per generation" + depends on LRU_GEN + range 2 4 + default 4 + help + Do not decrease this value unless you run out of spare bits in page + flags, i.e., you see the "Not enough bits in page flags" build error. + + This option uses N-2 bits in page flags. + +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. # } =20 source "mm/damon/Kconfig" diff --git a/mm/swap.c b/mm/swap.c index e5f2ab3dab4a..f5c0bcac8dcd 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -407,6 +407,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. * @@ -419,6 +456,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 65eb668abf2d..91a827ff665d 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1287,9 +1287,11 @@ static int __remove_mapping(struct address_space *ma= pping, struct page *page, =20 if (PageSwapCache(page)) { swp_entry_t swap =3D { .val =3D page_private(page) }; - mem_cgroup_swapout(page, swap); + + /* get a shadow entry before mem_cgroup_swapout() clears folio_memcg() *= / if (reclaimed && !mapping_exiting(mapping)) shadow =3D workingset_eviction(page, target_memcg); + mem_cgroup_swapout(page, swap); __delete_from_swap_cache(page, swap, shadow); xa_unlock_irq(&mapping->i_pages); put_swap_page(page, swap); @@ -2723,6 +2725,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 /* @@ -3048,11 +3053,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 *get_lruvec(struct mem_cgroup *memcg, int nid) { struct pglist_data *pgdat =3D NODE_DATA(nid); @@ -3071,6 +3103,735 @@ static struct lruvec *get_lruvec(struct mem_cgroup = *memcg, int nid) 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 ((new_flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1; + 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 */ + 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; + } + } + + /* try to spread pages out across MIN_NR_GENS+1 generations */ + 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) { + if (folio_test_reclaim(folio) && + (folio_test_dirty(folio) || folio_test_writeback(folio))) + folio_clear_active(folio); + else if (folio_is_file_lru(folio) || folio_test_swapcache(folio)) + folio_set_active(folio); + + folio_clear_referenced(folio); + folio_clear_workingset(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 *************************************************************************= *****/ @@ -3113,6 +3874,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) @@ -3126,6 +3897,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 */ @@ -3630,6 +4406,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; @@ -4000,6 +4779,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 8c03afe1d67c..93ee00c7e4d1 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 page *page, struct m= em_cgroup *target_memcg) VM_BUG_ON_PAGE(page_count(page), page); VM_BUG_ON_PAGE(!PageLocked(page), page); =20 + if (lru_gen_enabled()) + return lru_gen_eviction(page_folio(page)); + 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, thp_nr_pages(page)); return pack_shadow(memcgid, pgdat, eviction, PageWorkingset(page)); } @@ -297,7 +406,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.616.g0bdcbb4464-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 DFA78C433EF for ; Tue, 8 Mar 2022 23:52:18 +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=H2H20PunRN7dmdsyJJqL0fyg5WMm8O0sOhIwAc1HLVU=; b=2OzFNlpcNI5ZnLxom7RLo9WvGu EnkvwDJuCFNvD/yfZi+IduGpXm4UGeNUbw5AOsLavAaX7zZzWvHmEQfCWgxvLCO6H2w0kMM97uRCE i5qOL2eXocF8AyJ6k5VfU5R2AYoVZPPRJYfEk0NG8sM/4XlxwRtRDtSxJZnBhFlGFeN7HC7opr3Y6 pLtKYIZZJbBnh3Paxgrhj9HGjk21Ozm+vNpW7M3Kgecc+vKar/qqkgbq3QANBkoauqyTmeaSVgAbz GDhIJRFueX0z22Hjw4/fyvMw6YLJCZmkqGpFTRgPcW6sRdn/VAynv3Giss9XuJ9Mo+4y7205BNpu+ uh4R3aXQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nRjb4-006b7h-Qi; Tue, 08 Mar 2022 23:50:31 +0000 Received: from mail-yb1-xb4a.google.com ([2607:f8b0:4864:20::b4a]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nRjZC-006aM2-3X for linux-arm-kernel@lists.infradead.org; Tue, 08 Mar 2022 23:48:46 +0000 Received: by mail-yb1-xb4a.google.com with SMTP id u103-20020a25ab70000000b00628c6c05d83so410752ybi.11 for ; Tue, 08 Mar 2022 15:48:33 -0800 (PST) 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=J4iV8TqXH16u/tC95j8R0lEvScYBodg+K2oq/7ewN3M=; b=mX94ozPIM7SjS4QUKbvtFezeiRvLas3xKix72rdcvEwUaSIpIuSOcqui3Iug5heqHk HSfUTPyE3Vhx+fw+LjULVYKXUxf2VmcKlHLi4ZgrZowee7Rx60lAFDw6Xkm2fIBcM7zp WOXB2oc05Pd0Fqv5l1Gl/lsyJZ3F4w+ol/hC3M3uUinwqN3V+NKbu/FkztERIRMw/4u5 BirUe2gKU5QZlM+Dlf3jIeYUfxICzgTCrmkZYSjZwKM+SfeR20qhy6e8o8B5OGKCf0ce gFY0ux+Q8vR1rJEvZEbW6rmJklLj2JWzFQ6DhK1Vv14/M/oTMlPqFWzKQeebqwyk78ce uGWA== 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=J4iV8TqXH16u/tC95j8R0lEvScYBodg+K2oq/7ewN3M=; b=b1UYP/225JsMsgS6e5T0JMrjCpI7882sBNmISjHzz9TmUlGOWAARZT0xgaT6qYnXeG DlD0cl2RY2hHVqIamSHjJFGY/z/cMyK96Wpra6edkUNcX5UP1989z3+uNrU3g7T0f+C3 WdgFsC+XTI2Md10Mvw/v5u0pPw+Kk26vUgVutcsrkAK/CKHqS9CJ3G1aKvGg+x6H+Vji 2rQmyId32N9F7sTCZtlhCyivC2sYGKffb+Fd98bQ2Idy42NVmAvPtgd3j2la+7hB/wfV ivTKNwyrcHtSQt7R6zHJ2sdalt8+Sfb0VKcXDBRR6lpekv94MXklZe+mNPwUP1ogGPA8 yGMQ== X-Gm-Message-State: AOAM530rkx45fKjLoc6HB4dPF1q3aCd8iBbQUU7h3y7FtGAxL5eT/hC5 /7vs25b0LqT8Y7b9ElN0OsfSmWYOWyA= X-Google-Smtp-Source: ABdhPJzMpfupIYazJ6X8iOdnFy9F/QzQaESvDZm+Xx/asrt7+wuyyeqffmoPwzVJ2TJv4aYHJj68LeNkZ5Q= X-Received: from yuzhao.bld.corp.google.com ([2620:15c:183:200:57a6:54a6:aad1:c0a8]) (user=yuzhao job=sendgmr) by 2002:a25:5187:0:b0:623:e9ba:ba13 with SMTP id f129-20020a255187000000b00623e9baba13mr14304113ybb.311.1646783312530; Tue, 08 Mar 2022 15:48:32 -0800 (PST) Date: Tue, 8 Mar 2022 16:47:16 -0700 In-Reply-To: <20220308234723.3834941-1-yuzhao@google.com> Message-Id: <20220308234723.3834941-7-yuzhao@google.com> Mime-Version: 1.0 References: <20220308234723.3834941-1-yuzhao@google.com> X-Mailer: git-send-email 2.35.1.616.g0bdcbb4464-goog Subject: [PATCH v8 06/14] mm: multi-gen LRU: minimal implementation From: Yu Zhao To: Andrew Morton Cc: Andi Kleen , Aneesh Kumar , 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, linux-mm@kvack.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-20220308_154834_277481_585A55EB X-CRM114-Status: GOOD ( 25.25 ) 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 ZmlvIChidWZmZXJlZCBJL08pOiArWzQ3LCA0OV0lCiAgICAgICAgICAgICAgICBJT1BTICAgICAg ICAgQlcKICAgICAgNS4xNy1yYzI6IDIyNDJrICAgICAgICA4NzU5TWlCL3MKICAgICAgcGF0Y2gx LTU6IDMzMjFrICAgICAgICAxMi43R2lCL3MKCiAgU2luZ2xlIHdvcmtsb2FkOgogICAgbWVtY2Fj aGVkIChhbm9uKTogK1sxMDEsIDEwNV0lCiAgICAgICAgICAgICAgICBPcHMvc2VjICAgICAgS0Iv c2VjCiAgICAgIDUuMTctcmMyOiA0NzY3NzEuNzkgICAgMTg1NDQuMzEKICAgICAgcGF0Y2gxLTU6 IDk3MjUyNi4wNyAgICAzNzgyNi45NQoKICBDb25maWd1cmF0aW9uczoKICAgIENQVTogdHdvIFhl b24gNjE1NAogICAgTWVtOiB0b3RhbCAyNTZHCgogICAgTm9kZSAxIHdhcyBvbmx5IHVzZWQgYXMg YSByYW0gZGlzayB0byByZWR1Y2UgdGhlIHZhcmlhbmNlIGluIHRoZQogICAgcmVzdWx0cy4KCiAg ICBwYXRjaCBkcml2ZXJzL2Jsb2NrL2JyZC5jIDw8RU9GCiAgICA5OSwxMDBjOTksMTAwCiAgICA8 IAlnZnBfZmxhZ3MgPSBHRlBfTk9JTyB8IF9fR0ZQX1pFUk8gfCBfX0dGUF9ISUdITUVNOwogICAg PCAJcGFnZSA9IGFsbG9jX3BhZ2UoZ2ZwX2ZsYWdzKTsKICAgIC0tLQogICAgPiAJZ2ZwX2ZsYWdz ID0gR0ZQX05PSU8gfCBfX0dGUF9aRVJPIHwgX19HRlBfSElHSE1FTSB8IF9fR0ZQX1RISVNOT0RF OwogICAgPiAJcGFnZSA9IGFsbG9jX3BhZ2VzX25vZGUoMSwgZ2ZwX2ZsYWdzLCAwKTsKICAgIEVP RgoKICAgIGNhdCA+Pi9ldGMvc3lzdGVtZC9zeXN0ZW0uY29uZiA8PEVPRgogICAgQ1BVQWZmaW5p dHk9bnVtYQogICAgTlVNQVBvbGljeT1iaW5kCiAgICBOVU1BTWFzaz0wCiAgICBFT0YKCiAgICBj YXQgPj4vZXRjL21lbWNhY2hlZC5jb25mIDw8RU9GCiAgICAtbSAxODQzMjAKICAgIC1zIC92YXIv cnVuL21lbWNhY2hlZC9tZW1jYWNoZWQuc29jawogICAgLWEgMDc2NgogICAgLXQgMzYKICAgIC1C IGJpbmFyeQogICAgRU9GCgogICAgY2F0IGZpby5zaAogICAgbW9kcHJvYmUgYnJkIHJkX25yPTEg cmRfc2l6ZT0xMTMyNDYyMDgKICAgIG1rZnMuZXh0NCAvZGV2L3JhbTAKICAgIG1vdW50IC10IGV4 dDQgL2Rldi9yYW0wIC9tbnQKCiAgICBta2RpciAvc3lzL2ZzL2Nncm91cC91c2VyLnNsaWNlL3Rl c3QKICAgIGVjaG8gMzg2NTQ3MDU2NjQgPi9zeXMvZnMvY2dyb3VwL3VzZXIuc2xpY2UvdGVzdC9t ZW1vcnkubWF4CiAgICBlY2hvICQkID4vc3lzL2ZzL2Nncm91cC91c2VyLnNsaWNlL3Rlc3QvY2dy b3VwLnByb2NzCiAgICBmaW8gLW5hbWU9bWdscnUgLS1udW1qb2JzPTcyIC0tZGlyZWN0b3J5PS9t bnQgLS1zaXplPTE0MDhtIFwKICAgICAgLS1idWZmZXJlZD0xIC0taW9lbmdpbmU9aW9fdXJpbmcg LS1pb2RlcHRoPTEyOCBcCiAgICAgIC0taW9kZXB0aF9iYXRjaF9zdWJtaXQ9MzIgLS1pb2RlcHRo X2JhdGNoX2NvbXBsZXRlPTMyIFwKICAgICAgLS1ydz1yYW5kcmVhZCAtLXJhbmRvbV9kaXN0cmli dXRpb249cmFuZG9tIC0tbm9yYW5kb21tYXAgXAogICAgICAtLXRpbWVfYmFzZWQgLS1yYW1wX3Rp bWU9MTBtIC0tcnVudGltZT01bSAtLWdyb3VwX3JlcG9ydGluZwoKICAgIGNhdCBtZW1jYWNoZWQu c2gKICAgIG1vZHByb2JlIGJyZCByZF9ucj0xIHJkX3NpemU9MTEzMjQ2MjA4CiAgICBzd2Fwb2Zm IC1hCiAgICBta3N3YXAgL2Rldi9yYW0wCiAgICBzd2Fwb24gL2Rldi9yYW0wCgogICAgbWVtdGll cl9iZW5jaG1hcmsgLVMgL3Zhci9ydW4vbWVtY2FjaGVkL21lbWNhY2hlZC5zb2NrIFwKICAgICAg LVAgbWVtY2FjaGVfYmluYXJ5IC1uIGFsbGtleXMgLS1rZXktbWluaW11bT0xIFwKICAgICAgLS1r ZXktbWF4aW11bT02NTAwMDAwMCAtLWtleS1wYXR0ZXJuPVA6UCAtYyAxIC10IDM2IFwKICAgICAg LS1yYXRpbyAxOjAgLS1waXBlbGluZSA4IC1kIDIwMDAKCiAgICBtZW10aWVyX2JlbmNobWFyayAt UyAvdmFyL3J1bi9tZW1jYWNoZWQvbWVtY2FjaGVkLnNvY2sgXAogICAgICAtUCBtZW1jYWNoZV9i aW5hcnkgLW4gYWxsa2V5cyAtLWtleS1taW5pbXVtPTEgXAogICAgICAtLWtleS1tYXhpbXVtPTY1 MDAwMDAwIC0ta2V5LXBhdHRlcm49UjpSIC1jIDEgLXQgMzYgXAogICAgICAtLXJhdGlvIDA6MSAt LXBpcGVsaW5lIDggLS1yYW5kb21pemUgLS1kaXN0aW5jdC1jbGllbnQtc2VlZAoKQ2xpZW50IGJl bmNobWFyayByZXN1bHRzOgogIGtzd2FwZCBwcm9maWxlczoKICAgIDUuMTctcmMyCiAgICAgIDM4 LjA1JSAgcGFnZV92bWFfbWFwcGVkX3dhbGsKICAgICAgMjAuODYlICBsem8xeF8xX2RvX2NvbXBy ZXNzIChyZWFsIHdvcmspCiAgICAgICA2LjE2JSAgZG9fcmF3X3NwaW5fbG9jawogICAgICAgNC42 MSUgIF9yYXdfc3Bpbl91bmxvY2tfaXJxCiAgICAgICAyLjIwJSAgdm1hX2ludGVydmFsX3RyZWVf aXRlcl9uZXh0CiAgICAgICAyLjE5JSAgdm1hX2ludGVydmFsX3RyZWVfc3VidHJlZV9zZWFyY2gK ICAgICAgIDIuMTUlICBwYWdlX3JlZmVyZW5jZWRfb25lCiAgICAgICAxLjkzJSAgYW5vbl92bWFf aW50ZXJ2YWxfdHJlZV9pdGVyX2ZpcnN0CiAgICAgICAxLjY1JSAgcHRlcF9jbGVhcl9mbHVzaAog ICAgICAgMS4wMCUgIF9fenJhbV9idmVjX3dyaXRlCgogICAgcGF0Y2gxLTUKICAgICAgMzkuNzMl ICBsem8xeF8xX2RvX2NvbXByZXNzIChyZWFsIHdvcmspCiAgICAgIDE0Ljk2JSAgcGFnZV92bWFf bWFwcGVkX3dhbGsKICAgICAgIDYuOTclICBfcmF3X3NwaW5fdW5sb2NrX2lycQogICAgICAgMy4w NyUgIGRvX3Jhd19zcGluX2xvY2sKICAgICAgIDIuNTMlICBhbm9uX3ZtYV9pbnRlcnZhbF90cmVl X2l0ZXJfZmlyc3QKICAgICAgIDIuMDQlICBwdGVwX2NsZWFyX2ZsdXNoCiAgICAgICAxLjgyJSAg X196cmFtX2J2ZWNfd3JpdGUKICAgICAgIDEuNzYlICBfX2Fub25fdm1hX2ludGVydmFsX3RyZWVf c3VidHJlZV9zZWFyY2gKICAgICAgIDEuNTclICBtZW1tb3ZlCiAgICAgICAxLjQ1JSAgZnJlZV91 bnJlZl9wYWdlX2xpc3QKCiAgQ29uZmlndXJhdGlvbnM6CiAgICBDUFU6IHNpbmdsZSBTbmFwZHJh Z29uIDdjCiAgICBNZW06IHRvdGFsIDRHCgogICAgQ2hyb21lIE9TIE1lbW9yeVByZXNzdXJlIFsx XQoKWzFdIGh0dHBzOi8vY2hyb21pdW0uZ29vZ2xlc291cmNlLmNvbS9jaHJvbWl1bW9zL3BsYXRm b3JtL3Rhc3QtdGVzdHMvCgpTaWduZWQtb2ZmLWJ5OiBZdSBaaGFvIDx5dXpoYW9AZ29vZ2xlLmNv bT4KQWNrZWQtYnk6IEJyaWFuIEdlZmZvbiA8YmdlZmZvbkBnb29nbGUuY29tPgpBY2tlZC1ieTog SmFuIEFsZXhhbmRlciBTdGVmZmVucyAoaGVmdGlnKSA8aGVmdGlnQGFyY2hsaW51eC5vcmc+CkFj a2VkLWJ5OiBPbGVrc2FuZHIgTmF0YWxlbmtvIDxvbGVrc2FuZHJAbmF0YWxlbmtvLm5hbWU+CkFj a2VkLWJ5OiBTdGV2ZW4gQmFycmV0dCA8c3RldmVuQGxpcXVvcml4Lm5ldD4KQWNrZWQtYnk6IFN1 bGVpbWFuIFNvdWhsYWwgPHN1bGVpbWFuQGdvb2dsZS5jb20+ClRlc3RlZC1ieTogRGFuaWVsIEJ5 cm5lIDxkamJ5cm5lQG10dS5lZHU+ClRlc3RlZC1ieTogRG9uYWxkIENhcnIgPGRAY2hhb3MtcmVp bnMuY29tPgpUZXN0ZWQtYnk6IEhvbGdlciBIb2Zmc3TDpHR0ZSA8aG9sZ2VyQGFwcGxpZWQtYXN5 bmNocm9ueS5jb20+ClRlc3RlZC1ieTogS29uc3RhbnRpbiBLaGFybGFtb3YgPEhpLUFuZ2VsQHlh bmRleC5ydT4KVGVzdGVkLWJ5OiBTaHVhbmcgWmhhaSA8c3poYWkyQGNzLnJvY2hlc3Rlci5lZHU+ ClRlc3RlZC1ieTogU29maWEgVHJpbmggPHNvZmlhLnRyaW5oQGVkaS53b3Jrcz4KVGVzdGVkLWJ5 OiBWYWliaGF2IEphaW4gPHZhaWJoYXZAbGludXguaWJtLmNvbT4KLS0tCiBpbmNsdWRlL2xpbnV4 L21tLmggICAgICAgICAgICAgICAgfCAgIDEgKwogaW5jbHVkZS9saW51eC9tbV9pbmxpbmUuaCAg ICAgICAgIHwgIDI0ICsKIGluY2x1ZGUvbGludXgvbW16b25lLmggICAgICAgICAgICB8ICAzOCAr KwogaW5jbHVkZS9saW51eC9wYWdlLWZsYWdzLWxheW91dC5oIHwgICAyICstCiBtbS9LY29uZmln ICAgICAgICAgICAgICAgICAgICAgICAgfCAgMjAgKwogbW0vc3dhcC5jICAgICAgICAgICAgICAg ICAgICAgICAgIHwgIDQyICsrCiBtbS92bXNjYW4uYyAgICAgICAgICAgICAgICAgICAgICAgfCA3 ODYgKysrKysrKysrKysrKysrKysrKysrKysrKysrKystCiBtbS93b3JraW5nc2V0LmMgICAgICAg ICAgICAgICAgICAgfCAxMTkgKysrKy0KIDggZmlsZXMgY2hhbmdlZCwgMTAyOCBpbnNlcnRpb25z KCspLCA0IGRlbGV0aW9ucygtKQoKZGlmZiAtLWdpdCBhL2luY2x1ZGUvbGludXgvbW0uaCBiL2lu Y2x1ZGUvbGludXgvbW0uaAppbmRleCBjMTE2MjY1OWQ4MjQuLjFlM2U2ZGQ5MGMwZiAxMDA2NDQK LS0tIGEvaW5jbHVkZS9saW51eC9tbS5oCisrKyBiL2luY2x1ZGUvbGludXgvbW0uaApAQCAtMjI3 LDYgKzIyNyw3IEBAIGludCBvdmVyY29tbWl0X3BvbGljeV9oYW5kbGVyKHN0cnVjdCBjdGxfdGFi bGUgKiwgaW50LCB2b2lkICosIHNpemVfdCAqLAogI2RlZmluZSBQQUdFX0FMSUdORUQoYWRkcikJ SVNfQUxJR05FRCgodW5zaWduZWQgbG9uZykoYWRkciksIFBBR0VfU0laRSkKIAogI2RlZmluZSBs cnVfdG9fcGFnZShoZWFkKSAobGlzdF9lbnRyeSgoaGVhZCktPnByZXYsIHN0cnVjdCBwYWdlLCBs cnUpKQorI2RlZmluZSBscnVfdG9fZm9saW8oaGVhZCkgKGxpc3RfZW50cnkoKGhlYWQpLT5wcmV2 LCBzdHJ1Y3QgZm9saW8sIGxydSkpCiAKIHZvaWQgc2V0dXBfaW5pdGlhbF9pbml0X21tKHZvaWQg KnN0YXJ0X2NvZGUsIHZvaWQgKmVuZF9jb2RlLAogCQkJICAgdm9pZCAqZW5kX2RhdGEsIHZvaWQg KmJyayk7CmRpZmYgLS1naXQgYS9pbmNsdWRlL2xpbnV4L21tX2lubGluZS5oIGIvaW5jbHVkZS9s aW51eC9tbV9pbmxpbmUuaAppbmRleCBlMzU5NDE3MWI0MjEuLjE1YTA0YTliNTU2MCAxMDA2NDQK LS0tIGEvaW5jbHVkZS9saW51eC9tbV9pbmxpbmUuaAorKysgYi9pbmNsdWRlL2xpbnV4L21tX2lu bGluZS5oCkBAIC0xMTksNiArMTE5LDE5IEBAIHN0YXRpYyBpbmxpbmUgaW50IGxydV9nZW5fZnJv bV9zZXEodW5zaWduZWQgbG9uZyBzZXEpCiAJcmV0dXJuIHNlcSAlIE1BWF9OUl9HRU5TOwogfQog CitzdGF0aWMgaW5saW5lIGludCBscnVfaGlzdF9mcm9tX3NlcSh1bnNpZ25lZCBsb25nIHNlcSkK K3sKKwlyZXR1cm4gc2VxICUgTlJfSElTVF9HRU5TOworfQorCitzdGF0aWMgaW5saW5lIGludCBs cnVfdGllcl9mcm9tX3JlZnMoaW50IHJlZnMpCit7CisJVk1fQlVHX09OKHJlZnMgPiBCSVQoTFJV X1JFRlNfV0lEVEgpKTsKKworCS8qIHNlZSB0aGUgY29tbWVudCBvbiBNQVhfTlJfVElFUlMgKi8K KwlyZXR1cm4gb3JkZXJfYmFzZV8yKHJlZnMgKyAxKTsKK30KKwogc3RhdGljIGlubGluZSBib29s IGxydV9nZW5faXNfYWN0aXZlKHN0cnVjdCBscnV2ZWMgKmxydXZlYywgaW50IGdlbikKIHsKIAl1 bnNpZ25lZCBsb25nIG1heF9zZXEgPSBscnV2ZWMtPmxydWdlbi5tYXhfc2VxOwpAQCAtMTY0LDYg KzE3NywxNSBAQCBzdGF0aWMgaW5saW5lIHZvaWQgbHJ1X2dlbl91cGRhdGVfc2l6ZShzdHJ1Y3Qg bHJ1dmVjICpscnV2ZWMsIHN0cnVjdCBmb2xpbyAqZm9saQogCQlfX3VwZGF0ZV9scnVfc2l6ZShs cnV2ZWMsIGxydSwgem9uZSwgLWRlbHRhKTsKIAkJcmV0dXJuOwogCX0KKworCS8qIHByb21vdGlv biAqLworCWlmICghbHJ1X2dlbl9pc19hY3RpdmUobHJ1dmVjLCBvbGRfZ2VuKSAmJiBscnVfZ2Vu X2lzX2FjdGl2ZShscnV2ZWMsIG5ld19nZW4pKSB7CisJCV9fdXBkYXRlX2xydV9zaXplKGxydXZl YywgbHJ1LCB6b25lLCAtZGVsdGEpOworCQlfX3VwZGF0ZV9scnVfc2l6ZShscnV2ZWMsIGxydSAr IExSVV9BQ1RJVkUsIHpvbmUsIGRlbHRhKTsKKwl9CisKKwkvKiBkZW1vdGlvbiByZXF1aXJlcyBp c29sYXRpb24sIGUuZy4sIGxydV9kZWFjdGl2YXRlX2ZuKCkgKi8KKwlWTV9CVUdfT04obHJ1X2dl bl9pc19hY3RpdmUobHJ1dmVjLCBvbGRfZ2VuKSAmJiAhbHJ1X2dlbl9pc19hY3RpdmUobHJ1dmVj LCBuZXdfZ2VuKSk7CiB9CiAKIHN0YXRpYyBpbmxpbmUgYm9vbCBscnVfZ2VuX2FkZF9mb2xpbyhz dHJ1Y3QgbHJ1dmVjICpscnV2ZWMsIHN0cnVjdCBmb2xpbyAqZm9saW8sIGJvb2wgcmVjbGFpbWlu ZykKQEAgLTIyOSw2ICsyNTEsOCBAQCBzdGF0aWMgaW5saW5lIGJvb2wgbHJ1X2dlbl9kZWxfZm9s aW8oc3RydWN0IGxydXZlYyAqbHJ1dmVjLCBzdHJ1Y3QgZm9saW8gKmZvbGlvLAogCQlnZW4gPSAo KG5ld19mbGFncyAmIExSVV9HRU5fTUFTSykgPj4gTFJVX0dFTl9QR09GRikgLSAxOwogCiAJCW5l d19mbGFncyAmPSB+TFJVX0dFTl9NQVNLOworCQlpZiAoKG5ld19mbGFncyAmIExSVV9SRUZTX0ZM QUdTKSAhPSBMUlVfUkVGU19GTEFHUykKKwkJCW5ld19mbGFncyAmPSB+KExSVV9SRUZTX01BU0sg fCBMUlVfUkVGU19GTEFHUyk7CiAJCS8qIGZvciBzaHJpbmtfcGFnZV9saXN0KCkgKi8KIAkJaWYg KHJlY2xhaW1pbmcpCiAJCQluZXdfZmxhZ3MgJj0gfihCSVQoUEdfcmVmZXJlbmNlZCkgfCBCSVQo UEdfcmVjbGFpbSkpOwpkaWZmIC0tZ2l0IGEvaW5jbHVkZS9saW51eC9tbXpvbmUuaCBiL2luY2x1 ZGUvbGludXgvbW16b25lLmgKaW5kZXggYThlYjYxOWY3NDJjLi5iOTJmYzBlZjg3NjIgMTAwNjQ0 Ci0tLSBhL2luY2x1ZGUvbGludXgvbW16b25lLmgKKysrIGIvaW5jbHVkZS9saW51eC9tbXpvbmUu aApAQCAtMzE1LDYgKzMxNSw5IEBAIGVudW0gewogCUxSVV9HRU5fRklMRSwKIH07CiAKKyNkZWZp bmUgTUlOX0xSVV9CQVRDSAkJQklUU19QRVJfTE9ORworI2RlZmluZSBNQVhfTFJVX0JBVENICQko TUlOX0xSVV9CQVRDSCAqIDEyOCkKKwogLyoKICAqIEV2aWN0YWJsZSBwYWdlcyBhcmUgZGl2aWRl ZCBpbnRvIG11bHRpcGxlIGdlbmVyYXRpb25zLiBUaGUgeW91bmdlc3QgYW5kIHRoZQogICogb2xk ZXN0IGdlbmVyYXRpb24gbnVtYmVycywgbWF4X3NlcSBhbmQgbWluX3NlcSwgYXJlIG1vbm90b25p Y2FsbHkgaW5jcmVhc2luZy4KQEAgLTMzOSw2ICszNDIsMzIgQEAgZW51bSB7CiAjZGVmaW5lIE1J Tl9OUl9HRU5TCQkyVQogI2RlZmluZSBNQVhfTlJfR0VOUwkJKCh1bnNpZ25lZCBpbnQpQ09ORklH X05SX0xSVV9HRU5TKQogCisvKgorICogRWFjaCBnZW5lcmF0aW9uIGlzIGRpdmlkZWQgaW50byBt dWx0aXBsZSB0aWVycy4gVGllcnMgcmVwcmVzZW50IGRpZmZlcmVudAorICogcmFuZ2VzIG9mIG51 bWJlcnMgb2YgYWNjZXNzZXMgdGhyb3VnaCBmaWxlIGRlc2NyaXB0b3JzLiBBIHBhZ2UgYWNjZXNz ZWQgTgorICogdGltZXMgdGhyb3VnaCBmaWxlIGRlc2NyaXB0b3JzIGlzIGluIHRpZXIgb3JkZXJf YmFzZV8yKE4pLiBBIHBhZ2UgaW4gdGhlCisgKiBmaXJzdCB0aWVyIChOPTAsMSkgaXMgbWFya2Vk IGJ5IFBHX3JlZmVyZW5jZWQgdW5sZXNzIGl0IHdhcyBmYXVsdGVkIGluCisgKiB0aG91Z2ggcGFn ZSB0YWJsZXMgb3IgcmVhZCBhaGVhZC4gQSBwYWdlIGluIGFueSBvdGhlciB0aWVyIChOPjEpIGlz IG1hcmtlZAorICogYnkgUEdfcmVmZXJlbmNlZCBhbmQgUEdfd29ya2luZ3NldC4gQWRkaXRpb25h bCBiaXRzIGluIGZvbGlvLT5mbGFncyBhcmUKKyAqIHJlcXVpcmVkIHRvIHN1cHBvcnQgbW9yZSB0 aGFuIHR3byB0aWVycy4KKyAqCisgKiBJbiBjb250cmFzdCB0byBtb3ZpbmcgYWNyb3NzIGdlbmVy YXRpb25zIHdoaWNoIHJlcXVpcmVzIHRoZSBMUlUgbG9jaywgbW92aW5nCisgKiBhY3Jvc3MgdGll cnMgb25seSByZXF1aXJlcyBvcGVyYXRpb25zIG9uIGZvbGlvLT5mbGFncyBhbmQgdGhlcmVmb3Jl IGhhcyBhCisgKiBuZWdsaWdpYmxlIGNvc3QgaW4gdGhlIGJ1ZmZlcmVkIGFjY2VzcyBwYXRoLiBJ biB0aGUgZXZpY3Rpb24gcGF0aCwKKyAqIGNvbXBhcmlzb25zIG9mIHJlZmF1bHRlZC8oZXZpY3Rl ZCtwcm90ZWN0ZWQpIGZyb20gdGhlIGZpcnN0IHRpZXIgYW5kIHRoZQorICogcmVzdCBpbmZlciB3 aGV0aGVyIHBhZ2VzIGFjY2Vzc2VkIG11bHRpcGxlIHRpbWVzIHRocm91Z2ggZmlsZSBkZXNjcmlw dG9ycworICogYXJlIHN0YXRpc3RpY2FsbHkgaG90IGFuZCB0aHVzIHdvcnRoIHByb3RlY3Rpbmcu CisgKi8KKyNkZWZpbmUgTUFYX05SX1RJRVJTCQkoKHVuc2lnbmVkIGludClDT05GSUdfVElFUlNf UEVSX0dFTikKKyNkZWZpbmUgTFJVX1JFRlNfRkxBR1MJCShCSVQoUEdfcmVmZXJlbmNlZCkgfCBC SVQoUEdfd29ya2luZ3NldCkpCisKKy8qIHdoZXRoZXIgdG8ga2VlcCBoaXN0b3JpY2FsIHN0YXRz IGZyb20gZXZpY3RlZCBnZW5lcmF0aW9ucyAqLworI2lmZGVmIENPTkZJR19MUlVfR0VOX1NUQVRT CisjZGVmaW5lIE5SX0hJU1RfR0VOUwkJKCh1bnNpZ25lZCBpbnQpQ09ORklHX05SX0xSVV9HRU5T KQorI2Vsc2UKKyNkZWZpbmUgTlJfSElTVF9HRU5TCQkxVQorI2VuZGlmCisKIC8qCiAgKiBUaGUg eW91bmdlc3QgZ2VuZXJhdGlvbiBudW1iZXIgaXMgc3RvcmVkIGluIG1heF9zZXEgZm9yIGJvdGgg YW5vbiBhbmQgZmlsZQogICogdHlwZXMgYXMgdGhleSBhcmUgYWdlZCBvbiBhbiBlcXVhbCBmb290 aW5nLiBUaGUgb2xkZXN0IGdlbmVyYXRpb24gbnVtYmVycyBhcmUKQEAgLTM1OCw2ICszODcsMTUg QEAgc3RydWN0IGxydV9nZW5fc3RydWN0IHsKIAlzdHJ1Y3QgbGlzdF9oZWFkIGxpc3RzW01BWF9O Ul9HRU5TXVtBTk9OX0FORF9GSUxFXVtNQVhfTlJfWk9ORVNdOwogCS8qIHRoZSBzaXplcyBvZiB0 aGUgYWJvdmUgbGlzdHMgKi8KIAl1bnNpZ25lZCBsb25nIG5yX3BhZ2VzW01BWF9OUl9HRU5TXVtB Tk9OX0FORF9GSUxFXVtNQVhfTlJfWk9ORVNdOworCS8qIHRoZSBleHBvbmVudGlhbCBtb3Zpbmcg YXZlcmFnZSBvZiByZWZhdWx0ZWQgKi8KKwl1bnNpZ25lZCBsb25nIGF2Z19yZWZhdWx0ZWRbQU5P Tl9BTkRfRklMRV1bTUFYX05SX1RJRVJTXTsKKwkvKiB0aGUgZXhwb25lbnRpYWwgbW92aW5nIGF2 ZXJhZ2Ugb2YgZXZpY3RlZCtwcm90ZWN0ZWQgKi8KKwl1bnNpZ25lZCBsb25nIGF2Z190b3RhbFtB Tk9OX0FORF9GSUxFXVtNQVhfTlJfVElFUlNdOworCS8qIHRoZSBmaXJzdCB0aWVyIGRvZXNuJ3Qg bmVlZCBwcm90ZWN0aW9uLCBoZW5jZSB0aGUgbWludXMgb25lICovCisJdW5zaWduZWQgbG9uZyBw cm90ZWN0ZWRbTlJfSElTVF9HRU5TXVtBTk9OX0FORF9GSUxFXVtNQVhfTlJfVElFUlMgLSAxXTsK KwkvKiBjYW4gYmUgbW9kaWZpZWQgd2l0aG91dCBob2xkaW5nIHRoZSBMUlUgbG9jayAqLworCWF0 b21pY19sb25nX3QgZXZpY3RlZFtOUl9ISVNUX0dFTlNdW0FOT05fQU5EX0ZJTEVdW01BWF9OUl9U SUVSU107CisJYXRvbWljX2xvbmdfdCByZWZhdWx0ZWRbTlJfSElTVF9HRU5TXVtBTk9OX0FORF9G SUxFXVtNQVhfTlJfVElFUlNdOwogfTsKIAogdm9pZCBscnVfZ2VuX2luaXRfbHJ1dmVjKHN0cnVj dCBscnV2ZWMgKmxydXZlYyk7CmRpZmYgLS1naXQgYS9pbmNsdWRlL2xpbnV4L3BhZ2UtZmxhZ3Mt bGF5b3V0LmggYi9pbmNsdWRlL2xpbnV4L3BhZ2UtZmxhZ3MtbGF5b3V0LmgKaW5kZXggZGI0N2Vi ZDY3MmU4Li44Y2RiYmRjY2I1YWQgMTAwNjQ0Ci0tLSBhL2luY2x1ZGUvbGludXgvcGFnZS1mbGFn cy1sYXlvdXQuaAorKysgYi9pbmNsdWRlL2xpbnV4L3BhZ2UtZmxhZ3MtbGF5b3V0LmgKQEAgLTI4 LDcgKzI4LDcgQEAKIAogI2lmZGVmIENPTkZJR19MUlVfR0VOCiAvKiBMUlVfR0VOX1dJRFRIIGlz IGdlbmVyYXRlZCBmcm9tIG9yZGVyX2Jhc2VfMihDT05GSUdfTlJfTFJVX0dFTlMgKyAxKS4gKi8K LSNkZWZpbmUgTFJVX1JFRlNfV0lEVEgJCTAKKyNkZWZpbmUgTFJVX1JFRlNfV0lEVEgJCShDT05G SUdfVElFUlNfUEVSX0dFTiAtIDIpCiAjZWxzZQogI2RlZmluZSBMUlVfR0VOX1dJRFRICQkwCiAj ZGVmaW5lIExSVV9SRUZTX1dJRFRICQkwCmRpZmYgLS1naXQgYS9tbS9LY29uZmlnIGIvbW0vS2Nv bmZpZwppbmRleCA0ZWY2N2YxNTczNzQuLmQ0YWEzZDg4MTI2OSAxMDA2NDQKLS0tIGEvbW0vS2Nv bmZpZworKysgYi9tbS9LY29uZmlnCkBAIC05MTIsNiArOTEyLDI2IEBAIGNvbmZpZyBOUl9MUlVf R0VOUwogCSAgc2NoZWR1bGluZyBvcHRpbWl6YXRpb25zIGluIGRhdGEgY2VudGVycy4KIAogCSAg VGhpcyBvcHRpb24gdXNlcyBvcmRlcl9iYXNlXzIoTisxKSBiaXRzIGluIHBhZ2UgZmxhZ3MuCisK K2NvbmZpZyBUSUVSU19QRVJfR0VOCisJaW50ICJOdW1iZXIgb2YgdGllcnMgcGVyIGdlbmVyYXRp b24iCisJZGVwZW5kcyBvbiBMUlVfR0VOCisJcmFuZ2UgMiA0CisJZGVmYXVsdCA0CisJaGVscAor CSAgRG8gbm90IGRlY3JlYXNlIHRoaXMgdmFsdWUgdW5sZXNzIHlvdSBydW4gb3V0IG9mIHNwYXJl IGJpdHMgaW4gcGFnZQorCSAgZmxhZ3MsIGkuZS4sIHlvdSBzZWUgdGhlICJOb3QgZW5vdWdoIGJp dHMgaW4gcGFnZSBmbGFncyIgYnVpbGQgZXJyb3IuCisKKwkgIFRoaXMgb3B0aW9uIHVzZXMgTi0y IGJpdHMgaW4gcGFnZSBmbGFncy4KKworY29uZmlnIExSVV9HRU5fU1RBVFMKKwlib29sICJGdWxs IHN0YXRzIGZvciBkZWJ1Z2dpbmciCisJZGVwZW5kcyBvbiBMUlVfR0VOCisJaGVscAorCSAgRG8g bm90IGVuYWJsZSB0aGlzIG9wdGlvbiB1bmxlc3MgeW91IHBsYW4gdG8gbG9vayBhdCBoaXN0b3Jp Y2FsIHN0YXRzCisJICBmcm9tIGV2aWN0ZWQgZ2VuZXJhdGlvbnMgZm9yIGRlYnVnZ2luZyBwdXJw b3NlLgorCisJICBUaGlzIG9wdGlvbiBoYXMgYSBwZXItbWVtY2cgYW5kIHBlci1ub2RlIG1lbW9y eSBvdmVyaGVhZC4KICMgfQogCiBzb3VyY2UgIm1tL2RhbW9uL0tjb25maWciCmRpZmYgLS1naXQg YS9tbS9zd2FwLmMgYi9tbS9zd2FwLmMKaW5kZXggZTVmMmFiM2RhYjRhLi5mNWMwYmNhYzhkY2Qg MTAwNjQ0Ci0tLSBhL21tL3N3YXAuYworKysgYi9tbS9zd2FwLmMKQEAgLTQwNyw2ICs0MDcsNDMg QEAgc3RhdGljIHZvaWQgX19scnVfY2FjaGVfYWN0aXZhdGVfZm9saW8oc3RydWN0IGZvbGlvICpm b2xpbykKIAlsb2NhbF91bmxvY2soJmxydV9wdmVjcy5sb2NrKTsKIH0KIAorI2lmZGVmIENPTkZJ R19MUlVfR0VOCitzdGF0aWMgdm9pZCBmb2xpb19pbmNfcmVmcyhzdHJ1Y3QgZm9saW8gKmZvbGlv KQoreworCXVuc2lnbmVkIGxvbmcgcmVmczsKKwl1bnNpZ25lZCBsb25nIG9sZF9mbGFncywgbmV3 X2ZsYWdzOworCisJaWYgKGZvbGlvX3Rlc3RfdW5ldmljdGFibGUoZm9saW8pKQorCQlyZXR1cm47 CisKKwkvKiBzZWUgdGhlIGNvbW1lbnQgb24gTUFYX05SX1RJRVJTICovCisJZG8geworCQluZXdf ZmxhZ3MgPSBvbGRfZmxhZ3MgPSBSRUFEX09OQ0UoZm9saW8tPmZsYWdzKTsKKworCQlpZiAoIShu ZXdfZmxhZ3MgJiBCSVQoUEdfcmVmZXJlbmNlZCkpKSB7CisJCQluZXdfZmxhZ3MgfD0gQklUKFBH X3JlZmVyZW5jZWQpOworCQkJY29udGludWU7CisJCX0KKworCQlpZiAoIShuZXdfZmxhZ3MgJiBC SVQoUEdfd29ya2luZ3NldCkpKSB7CisJCQluZXdfZmxhZ3MgfD0gQklUKFBHX3dvcmtpbmdzZXQp OworCQkJY29udGludWU7CisJCX0KKworCQlyZWZzID0gbmV3X2ZsYWdzICYgTFJVX1JFRlNfTUFT SzsKKwkJcmVmcyA9IG1pbihyZWZzICsgQklUKExSVV9SRUZTX1BHT0ZGKSwgTFJVX1JFRlNfTUFT Syk7CisKKwkJbmV3X2ZsYWdzICY9IH5MUlVfUkVGU19NQVNLOworCQluZXdfZmxhZ3MgfD0gcmVm czsKKwl9IHdoaWxlIChuZXdfZmxhZ3MgIT0gb2xkX2ZsYWdzICYmCisJCSBjbXB4Y2hnKCZmb2xp by0+ZmxhZ3MsIG9sZF9mbGFncywgbmV3X2ZsYWdzKSAhPSBvbGRfZmxhZ3MpOworfQorI2Vsc2UK K3N0YXRpYyB2b2lkIGZvbGlvX2luY19yZWZzKHN0cnVjdCBmb2xpbyAqZm9saW8pCit7Cit9Cisj ZW5kaWYgLyogQ09ORklHX0xSVV9HRU4gKi8KKwogLyoKICAqIE1hcmsgYSBwYWdlIGFzIGhhdmlu ZyBzZWVuIGFjdGl2aXR5LgogICoKQEAgLTQxOSw2ICs0NTYsMTEgQEAgc3RhdGljIHZvaWQgX19s cnVfY2FjaGVfYWN0aXZhdGVfZm9saW8oc3RydWN0IGZvbGlvICpmb2xpbykKICAqLwogdm9pZCBm b2xpb19tYXJrX2FjY2Vzc2VkKHN0cnVjdCBmb2xpbyAqZm9saW8pCiB7CisJaWYgKGxydV9nZW5f ZW5hYmxlZCgpKSB7CisJCWZvbGlvX2luY19yZWZzKGZvbGlvKTsKKwkJcmV0dXJuOworCX0KKwog CWlmICghZm9saW9fdGVzdF9yZWZlcmVuY2VkKGZvbGlvKSkgewogCQlmb2xpb19zZXRfcmVmZXJl bmNlZChmb2xpbyk7CiAJfSBlbHNlIGlmIChmb2xpb190ZXN0X3VuZXZpY3RhYmxlKGZvbGlvKSkg ewpkaWZmIC0tZ2l0IGEvbW0vdm1zY2FuLmMgYi9tbS92bXNjYW4uYwppbmRleCA2NWViNjY4YWJm MmQuLjkxYTgyN2ZmNjY1ZCAxMDA2NDQKLS0tIGEvbW0vdm1zY2FuLmMKKysrIGIvbW0vdm1zY2Fu LmMKQEAgLTEyODcsOSArMTI4NywxMSBAQCBzdGF0aWMgaW50IF9fcmVtb3ZlX21hcHBpbmcoc3Ry dWN0IGFkZHJlc3Nfc3BhY2UgKm1hcHBpbmcsIHN0cnVjdCBwYWdlICpwYWdlLAogCiAJaWYgKFBh Z2VTd2FwQ2FjaGUocGFnZSkpIHsKIAkJc3dwX2VudHJ5X3Qgc3dhcCA9IHsgLnZhbCA9IHBhZ2Vf cHJpdmF0ZShwYWdlKSB9OwotCQltZW1fY2dyb3VwX3N3YXBvdXQocGFnZSwgc3dhcCk7CisKKwkJ LyogZ2V0IGEgc2hhZG93IGVudHJ5IGJlZm9yZSBtZW1fY2dyb3VwX3N3YXBvdXQoKSBjbGVhcnMg Zm9saW9fbWVtY2coKSAqLwogCQlpZiAocmVjbGFpbWVkICYmICFtYXBwaW5nX2V4aXRpbmcobWFw cGluZykpCiAJCQlzaGFkb3cgPSB3b3JraW5nc2V0X2V2aWN0aW9uKHBhZ2UsIHRhcmdldF9tZW1j Zyk7CisJCW1lbV9jZ3JvdXBfc3dhcG91dChwYWdlLCBzd2FwKTsKIAkJX19kZWxldGVfZnJvbV9z d2FwX2NhY2hlKHBhZ2UsIHN3YXAsIHNoYWRvdyk7CiAJCXhhX3VubG9ja19pcnEoJm1hcHBpbmct PmlfcGFnZXMpOwogCQlwdXRfc3dhcF9wYWdlKHBhZ2UsIHN3YXApOwpAQCAtMjcyMyw2ICsyNzI1 LDkgQEAgc3RhdGljIHZvaWQgcHJlcGFyZV9zY2FuX2NvdW50KHBnX2RhdGFfdCAqcGdkYXQsIHN0 cnVjdCBzY2FuX2NvbnRyb2wgKnNjKQogCXVuc2lnbmVkIGxvbmcgZmlsZTsKIAlzdHJ1Y3QgbHJ1 dmVjICp0YXJnZXRfbHJ1dmVjOwogCisJaWYgKGxydV9nZW5fZW5hYmxlZCgpKQorCQlyZXR1cm47 CisKIAl0YXJnZXRfbHJ1dmVjID0gbWVtX2Nncm91cF9scnV2ZWMoc2MtPnRhcmdldF9tZW1fY2dy b3VwLCBwZ2RhdCk7CiAKIAkvKgpAQCAtMzA0OCwxMSArMzA1MywzOCBAQCBzdGF0aWMgYm9vbCBj YW5fYWdlX2Fub25fcGFnZXMoc3RydWN0IHBnbGlzdF9kYXRhICpwZ2RhdCwKICAqICAgICAgICAg ICAgICAgICAgICAgICAgICBzaG9ydGhhbmQgaGVscGVycwogICoqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq Ki8KIAorI2RlZmluZSBERUZJTkVfTUFYX1NFUShscnV2ZWMpCQkJCQkJXAorCXVuc2lnbmVkIGxv bmcgbWF4X3NlcSA9IFJFQURfT05DRSgobHJ1dmVjKS0+bHJ1Z2VuLm1heF9zZXEpCisKKyNkZWZp bmUgREVGSU5FX01JTl9TRVEobHJ1dmVjKQkJCQkJCVwKKwl1bnNpZ25lZCBsb25nIG1pbl9zZXFb QU5PTl9BTkRfRklMRV0gPSB7CQkJXAorCQlSRUFEX09OQ0UoKGxydXZlYyktPmxydWdlbi5taW5f c2VxW0xSVV9HRU5fQU5PTl0pLAlcCisJCVJFQURfT05DRSgobHJ1dmVjKS0+bHJ1Z2VuLm1pbl9z ZXFbTFJVX0dFTl9GSUxFXSksCVwKKwl9CisKICNkZWZpbmUgZm9yX2VhY2hfZ2VuX3R5cGVfem9u ZShnZW4sIHR5cGUsIHpvbmUpCQkJCVwKIAlmb3IgKChnZW4pID0gMDsgKGdlbikgPCBNQVhfTlJf R0VOUzsgKGdlbikrKykJCQlcCiAJCWZvciAoKHR5cGUpID0gMDsgKHR5cGUpIDwgQU5PTl9BTkRf RklMRTsgKHR5cGUpKyspCVwKIAkJCWZvciAoKHpvbmUpID0gMDsgKHpvbmUpIDwgTUFYX05SX1pP TkVTOyAoem9uZSkrKykKIAorc3RhdGljIGludCBmb2xpb19scnVfZ2VuKHN0cnVjdCBmb2xpbyAq Zm9saW8pCit7CisJdW5zaWduZWQgbG9uZyBmbGFncyA9IFJFQURfT05DRShmb2xpby0+ZmxhZ3Mp OworCisJcmV0dXJuICgoZmxhZ3MgJiBMUlVfR0VOX01BU0spID4+IExSVV9HRU5fUEdPRkYpIC0g MTsKK30KKworc3RhdGljIGludCBmb2xpb19scnVfdGllcihzdHJ1Y3QgZm9saW8gKmZvbGlvKQor eworCWludCByZWZzOworCXVuc2lnbmVkIGxvbmcgZmxhZ3MgPSBSRUFEX09OQ0UoZm9saW8tPmZs YWdzKTsKKworCXJlZnMgPSAoZmxhZ3MgJiBMUlVfUkVGU19GTEFHUykgPT0gTFJVX1JFRlNfRkxB R1MgPworCSAgICAgICAoKGZsYWdzICYgTFJVX1JFRlNfTUFTSykgPj4gTFJVX1JFRlNfUEdPRkYp ICsgMSA6IDA7CisKKwlyZXR1cm4gbHJ1X3RpZXJfZnJvbV9yZWZzKHJlZnMpOworfQorCiBzdGF0 aWMgc3RydWN0IGxydXZlYyAqZ2V0X2xydXZlYyhzdHJ1Y3QgbWVtX2Nncm91cCAqbWVtY2csIGlu dCBuaWQpCiB7CiAJc3RydWN0IHBnbGlzdF9kYXRhICpwZ2RhdCA9IE5PREVfREFUQShuaWQpOwpA QCAtMzA3MSw2ICszMTAzLDczNSBAQCBzdGF0aWMgc3RydWN0IGxydXZlYyAqZ2V0X2xydXZlYyhz dHJ1Y3QgbWVtX2Nncm91cCAqbWVtY2csIGludCBuaWQpCiAJcmV0dXJuIHBnZGF0ID8gJnBnZGF0 LT5fX2xydXZlYyA6IE5VTEw7CiB9CiAKK3N0YXRpYyBpbnQgZ2V0X3N3YXBwaW5lc3Moc3RydWN0 IGxydXZlYyAqbHJ1dmVjLCBzdHJ1Y3Qgc2Nhbl9jb250cm9sICpzYykKK3sKKwlzdHJ1Y3QgbWVt X2Nncm91cCAqbWVtY2cgPSBscnV2ZWNfbWVtY2cobHJ1dmVjKTsKKwlzdHJ1Y3QgcGdsaXN0X2Rh dGEgKnBnZGF0ID0gbHJ1dmVjX3BnZGF0KGxydXZlYyk7CisKKwlpZiAoIWNhbl9kZW1vdGUocGdk YXQtPm5vZGVfaWQsIHNjKSAmJgorCSAgICBtZW1fY2dyb3VwX2dldF9ucl9zd2FwX3BhZ2VzKG1l bWNnKSA8IE1JTl9MUlVfQkFUQ0gpCisJCXJldHVybiAwOworCisJcmV0dXJuIG1lbV9jZ3JvdXBf c3dhcHBpbmVzcyhtZW1jZyk7Cit9CisKK3N0YXRpYyBpbnQgZ2V0X25yX2dlbnMoc3RydWN0IGxy dXZlYyAqbHJ1dmVjLCBpbnQgdHlwZSkKK3sKKwlyZXR1cm4gbHJ1dmVjLT5scnVnZW4ubWF4X3Nl cSAtIGxydXZlYy0+bHJ1Z2VuLm1pbl9zZXFbdHlwZV0gKyAxOworfQorCitzdGF0aWMgYm9vbCBf X21heWJlX3VudXNlZCBzZXFfaXNfdmFsaWQoc3RydWN0IGxydXZlYyAqbHJ1dmVjKQoreworCS8q IHNlZSB0aGUgY29tbWVudCBvbiBscnVfZ2VuX3N0cnVjdCAqLworCXJldHVybiBnZXRfbnJfZ2Vu cyhscnV2ZWMsIExSVV9HRU5fRklMRSkgPj0gTUlOX05SX0dFTlMgJiYKKwkgICAgICAgZ2V0X25y X2dlbnMobHJ1dmVjLCBMUlVfR0VOX0ZJTEUpIDw9IGdldF9ucl9nZW5zKGxydXZlYywgTFJVX0dF Tl9BTk9OKSAmJgorCSAgICAgICBnZXRfbnJfZ2VucyhscnV2ZWMsIExSVV9HRU5fQU5PTikgPD0g TUFYX05SX0dFTlM7Cit9CisKKy8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKKyAqICAgICAgICAgICAg ICAgICAgICAgICAgICByZWZhdWx0IGZlZWRiYWNrIGxvb3AKKyAqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KiovCisKKy8qCisgKiBBIGZlZWRiYWNrIGxvb3AgYmFzZWQgb24gUHJvcG9ydGlvbmFsLUludGVn cmFsLURlcml2YXRpdmUgKFBJRCkgY29udHJvbGxlci4KKyAqCisgKiBUaGUgUCB0ZXJtIGlzIHJl ZmF1bHRlZC8oZXZpY3RlZCtwcm90ZWN0ZWQpIGZyb20gYSB0aWVyIGluIHRoZSBnZW5lcmF0aW9u CisgKiBjdXJyZW50bHkgYmVpbmcgZXZpY3RlZDsgdGhlIEkgdGVybSBpcyB0aGUgZXhwb25lbnRp YWwgbW92aW5nIGF2ZXJhZ2Ugb2YgdGhlCisgKiBQIHRlcm0gb3ZlciB0aGUgZ2VuZXJhdGlvbnMg cHJldmlvdXNseSBldmljdGVkLCB1c2luZyB0aGUgc21vb3RoaW5nIGZhY3RvcgorICogMS8yOyB0 aGUgRCB0ZXJtIGlzbid0IHN1cHBvcnRlZC4KKyAqCisgKiBUaGUgc2V0cG9pbnQgKFNQKSBpcyBh bHdheXMgdGhlIGZpcnN0IHRpZXIgb2Ygb25lIHR5cGU7IHRoZSBwcm9jZXNzIHZhcmlhYmxlCisg KiAoUFYpIGlzIGVpdGhlciBhbnkgdGllciBvZiB0aGUgb3RoZXIgdHlwZSBvciBhbnkgb3RoZXIg dGllciBvZiB0aGUgc2FtZQorICogdHlwZS4KKyAqCisgKiBUaGUgZXJyb3IgaXMgdGhlIGRpZmZl cmVuY2UgYmV0d2VlbiB0aGUgU1AgYW5kIHRoZSBQVjsgdGhlIGNvcnJlY3Rpb24gaXMKKyAqIHR1 cm4gb2ZmIHByb3RlY3Rpb24gd2hlbiBTUD5QViBvciB0dXJuIG9uIHByb3RlY3Rpb24gd2hlbiBT UDxQVi4KKyAqCisgKiBGb3IgZnV0dXJlIG9wdGltaXphdGlvbnM6CisgKiAxLiBUaGUgRCB0ZXJt IG1heSBkaXNjb3VudCB0aGUgb3RoZXIgdHdvIHRlcm1zIG92ZXIgdGltZSBzbyB0aGF0IGxvbmct bGl2ZWQKKyAqICAgIGdlbmVyYXRpb25zIGNhbiByZXNpc3Qgc3RhbGUgaW5mb3JtYXRpb24uCisg Ki8KK3N0cnVjdCBjdHJsX3BvcyB7CisJdW5zaWduZWQgbG9uZyByZWZhdWx0ZWQ7CisJdW5zaWdu ZWQgbG9uZyB0b3RhbDsKKwlpbnQgZ2FpbjsKK307CisKK3N0YXRpYyB2b2lkIHJlYWRfY3RybF9w b3Moc3RydWN0IGxydXZlYyAqbHJ1dmVjLCBpbnQgdHlwZSwgaW50IHRpZXIsIGludCBnYWluLAor CQkJICBzdHJ1Y3QgY3RybF9wb3MgKnBvcykKK3sKKwlzdHJ1Y3QgbHJ1X2dlbl9zdHJ1Y3QgKmxy dWdlbiA9ICZscnV2ZWMtPmxydWdlbjsKKwlpbnQgaGlzdCA9IGxydV9oaXN0X2Zyb21fc2VxKGxy dWdlbi0+bWluX3NlcVt0eXBlXSk7CisKKwlwb3MtPnJlZmF1bHRlZCA9IGxydWdlbi0+YXZnX3Jl ZmF1bHRlZFt0eXBlXVt0aWVyXSArCisJCQkgYXRvbWljX2xvbmdfcmVhZCgmbHJ1Z2VuLT5yZWZh dWx0ZWRbaGlzdF1bdHlwZV1bdGllcl0pOworCXBvcy0+dG90YWwgPSBscnVnZW4tPmF2Z190b3Rh bFt0eXBlXVt0aWVyXSArCisJCSAgICAgYXRvbWljX2xvbmdfcmVhZCgmbHJ1Z2VuLT5ldmljdGVk W2hpc3RdW3R5cGVdW3RpZXJdKTsKKwlpZiAodGllcikKKwkJcG9zLT50b3RhbCArPSBscnVnZW4t PnByb3RlY3RlZFtoaXN0XVt0eXBlXVt0aWVyIC0gMV07CisJcG9zLT5nYWluID0gZ2FpbjsKK30K Kworc3RhdGljIHZvaWQgcmVzZXRfY3RybF9wb3Moc3RydWN0IGxydXZlYyAqbHJ1dmVjLCBpbnQg dHlwZSwgYm9vbCBjYXJyeW92ZXIpCit7CisJaW50IGhpc3QsIHRpZXI7CisJc3RydWN0IGxydV9n ZW5fc3RydWN0ICpscnVnZW4gPSAmbHJ1dmVjLT5scnVnZW47CisJYm9vbCBjbGVhciA9IGNhcnJ5 b3ZlciA/IE5SX0hJU1RfR0VOUyA9PSAxIDogTlJfSElTVF9HRU5TID4gMTsKKwl1bnNpZ25lZCBs b25nIHNlcSA9IGNhcnJ5b3ZlciA/IGxydWdlbi0+bWluX3NlcVt0eXBlXSA6IGxydWdlbi0+bWF4 X3NlcSArIDE7CisKKwlsb2NrZGVwX2Fzc2VydF9oZWxkKCZscnV2ZWMtPmxydV9sb2NrKTsKKwor CWlmICghY2FycnlvdmVyICYmICFjbGVhcikKKwkJcmV0dXJuOworCisJaGlzdCA9IGxydV9oaXN0 X2Zyb21fc2VxKHNlcSk7CisKKwlmb3IgKHRpZXIgPSAwOyB0aWVyIDwgTUFYX05SX1RJRVJTOyB0 aWVyKyspIHsKKwkJaWYgKGNhcnJ5b3ZlcikgeworCQkJdW5zaWduZWQgbG9uZyBzdW07CisKKwkJ CXN1bSA9IGxydWdlbi0+YXZnX3JlZmF1bHRlZFt0eXBlXVt0aWVyXSArCisJCQkgICAgICBhdG9t aWNfbG9uZ19yZWFkKCZscnVnZW4tPnJlZmF1bHRlZFtoaXN0XVt0eXBlXVt0aWVyXSk7CisJCQlX UklURV9PTkNFKGxydWdlbi0+YXZnX3JlZmF1bHRlZFt0eXBlXVt0aWVyXSwgc3VtIC8gMik7CisK KwkJCXN1bSA9IGxydWdlbi0+YXZnX3RvdGFsW3R5cGVdW3RpZXJdICsKKwkJCSAgICAgIGF0b21p Y19sb25nX3JlYWQoJmxydWdlbi0+ZXZpY3RlZFtoaXN0XVt0eXBlXVt0aWVyXSk7CisJCQlpZiAo dGllcikKKwkJCQlzdW0gKz0gbHJ1Z2VuLT5wcm90ZWN0ZWRbaGlzdF1bdHlwZV1bdGllciAtIDFd OworCQkJV1JJVEVfT05DRShscnVnZW4tPmF2Z190b3RhbFt0eXBlXVt0aWVyXSwgc3VtIC8gMik7 CisJCX0KKworCQlpZiAoY2xlYXIpIHsKKwkJCWF0b21pY19sb25nX3NldCgmbHJ1Z2VuLT5yZWZh dWx0ZWRbaGlzdF1bdHlwZV1bdGllcl0sIDApOworCQkJYXRvbWljX2xvbmdfc2V0KCZscnVnZW4t PmV2aWN0ZWRbaGlzdF1bdHlwZV1bdGllcl0sIDApOworCQkJaWYgKHRpZXIpCisJCQkJV1JJVEVf T05DRShscnVnZW4tPnByb3RlY3RlZFtoaXN0XVt0eXBlXVt0aWVyIC0gMV0sIDApOworCQl9CisJ fQorfQorCitzdGF0aWMgYm9vbCBwb3NpdGl2ZV9jdHJsX2VycihzdHJ1Y3QgY3RybF9wb3MgKnNw LCBzdHJ1Y3QgY3RybF9wb3MgKnB2KQoreworCS8qCisJICogUmV0dXJuIHRydWUgaWYgdGhlIFBW IGhhcyBhIGxpbWl0ZWQgbnVtYmVyIG9mIHJlZmF1bHRzIG9yIGEgbG93ZXIKKwkgKiByZWZhdWx0 ZWQvdG90YWwgdGhhbiB0aGUgU1AuCisJICovCisJcmV0dXJuIHB2LT5yZWZhdWx0ZWQgPCBNSU5f TFJVX0JBVENIIHx8CisJICAgICAgIHB2LT5yZWZhdWx0ZWQgKiAoc3AtPnRvdGFsICsgTUlOX0xS VV9CQVRDSCkgKiBzcC0+Z2FpbiA8PQorCSAgICAgICAoc3AtPnJlZmF1bHRlZCArIDEpICogcHYt PnRvdGFsICogcHYtPmdhaW47Cit9CisKKy8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKKyAqICAgICAg ICAgICAgICAgICAgICAgICAgICB0aGUgYWdpbmcKKyAqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCisK K3N0YXRpYyBpbnQgZm9saW9faW5jX2dlbihzdHJ1Y3QgbHJ1dmVjICpscnV2ZWMsIHN0cnVjdCBm b2xpbyAqZm9saW8sIGJvb2wgcmVjbGFpbWluZykKK3sKKwl1bnNpZ25lZCBsb25nIG9sZF9mbGFn cywgbmV3X2ZsYWdzOworCWludCB0eXBlID0gZm9saW9faXNfZmlsZV9scnUoZm9saW8pOworCXN0 cnVjdCBscnVfZ2VuX3N0cnVjdCAqbHJ1Z2VuID0gJmxydXZlYy0+bHJ1Z2VuOworCWludCBuZXdf Z2VuLCBvbGRfZ2VuID0gbHJ1X2dlbl9mcm9tX3NlcShscnVnZW4tPm1pbl9zZXFbdHlwZV0pOwor CisJZG8geworCQluZXdfZmxhZ3MgPSBvbGRfZmxhZ3MgPSBSRUFEX09OQ0UoZm9saW8tPmZsYWdz KTsKKwkJVk1fQlVHX09OX0ZPTElPKCEobmV3X2ZsYWdzICYgTFJVX0dFTl9NQVNLKSwgZm9saW8p OworCisJCW5ld19nZW4gPSAoKG5ld19mbGFncyAmIExSVV9HRU5fTUFTSykgPj4gTFJVX0dFTl9Q R09GRikgLSAxOworCQluZXdfZ2VuID0gKG9sZF9nZW4gKyAxKSAlIE1BWF9OUl9HRU5TOworCisJ CW5ld19mbGFncyAmPSB+TFJVX0dFTl9NQVNLOworCQluZXdfZmxhZ3MgfD0gKG5ld19nZW4gKyAx VUwpIDw8IExSVV9HRU5fUEdPRkY7CisJCW5ld19mbGFncyAmPSB+KExSVV9SRUZTX01BU0sgfCBM UlVfUkVGU19GTEFHUyk7CisJCS8qIGZvciBmb2xpb19lbmRfd3JpdGViYWNrKCkgKi8KKwkJaWYg KHJlY2xhaW1pbmcpCisJCQluZXdfZmxhZ3MgfD0gQklUKFBHX3JlY2xhaW0pOworCX0gd2hpbGUg KGNtcHhjaGcoJmZvbGlvLT5mbGFncywgb2xkX2ZsYWdzLCBuZXdfZmxhZ3MpICE9IG9sZF9mbGFn cyk7CisKKwlscnVfZ2VuX3VwZGF0ZV9zaXplKGxydXZlYywgZm9saW8sIG9sZF9nZW4sIG5ld19n ZW4pOworCisJcmV0dXJuIG5ld19nZW47Cit9CisKK3N0YXRpYyB2b2lkIGluY19taW5fc2VxKHN0 cnVjdCBscnV2ZWMgKmxydXZlYykKK3sKKwlpbnQgdHlwZTsKKwlzdHJ1Y3QgbHJ1X2dlbl9zdHJ1 Y3QgKmxydWdlbiA9ICZscnV2ZWMtPmxydWdlbjsKKworCVZNX0JVR19PTighc2VxX2lzX3ZhbGlk KGxydXZlYykpOworCisJZm9yICh0eXBlID0gMDsgdHlwZSA8IEFOT05fQU5EX0ZJTEU7IHR5cGUr KykgeworCQlpZiAoZ2V0X25yX2dlbnMobHJ1dmVjLCB0eXBlKSAhPSBNQVhfTlJfR0VOUykKKwkJ CWNvbnRpbnVlOworCisJCXJlc2V0X2N0cmxfcG9zKGxydXZlYywgdHlwZSwgdHJ1ZSk7CisJCVdS SVRFX09OQ0UobHJ1Z2VuLT5taW5fc2VxW3R5cGVdLCBscnVnZW4tPm1pbl9zZXFbdHlwZV0gKyAx KTsKKwl9Cit9CisKK3N0YXRpYyBib29sIHRyeV90b19pbmNfbWluX3NlcShzdHJ1Y3QgbHJ1dmVj ICpscnV2ZWMsIGJvb2wgY2FuX3N3YXApCit7CisJaW50IGdlbiwgdHlwZSwgem9uZTsKKwlib29s IHN1Y2Nlc3MgPSBmYWxzZTsKKwlzdHJ1Y3QgbHJ1X2dlbl9zdHJ1Y3QgKmxydWdlbiA9ICZscnV2 ZWMtPmxydWdlbjsKKwlERUZJTkVfTUlOX1NFUShscnV2ZWMpOworCisJVk1fQlVHX09OKCFzZXFf aXNfdmFsaWQobHJ1dmVjKSk7CisKKwlmb3IgKHR5cGUgPSAhY2FuX3N3YXA7IHR5cGUgPCBBTk9O X0FORF9GSUxFOyB0eXBlKyspIHsKKwkJd2hpbGUgKG1pbl9zZXFbdHlwZV0gKyBNSU5fTlJfR0VO UyA8PSBscnVnZW4tPm1heF9zZXEpIHsKKwkJCWdlbiA9IGxydV9nZW5fZnJvbV9zZXEobWluX3Nl cVt0eXBlXSk7CisKKwkJCWZvciAoem9uZSA9IDA7IHpvbmUgPCBNQVhfTlJfWk9ORVM7IHpvbmUr KykgeworCQkJCWlmICghbGlzdF9lbXB0eSgmbHJ1Z2VuLT5saXN0c1tnZW5dW3R5cGVdW3pvbmVd KSkKKwkJCQkJZ290byBuZXh0OworCQkJfQorCisJCQltaW5fc2VxW3R5cGVdKys7CisJCX0KK25l eHQ6CisJCTsKKwl9CisKKwkvKiBzZWUgdGhlIGNvbW1lbnQgb24gbHJ1X2dlbl9zdHJ1Y3QgKi8K KwlpZiAoY2FuX3N3YXApIHsKKwkJbWluX3NlcVtMUlVfR0VOX0FOT05dID0gbWluKG1pbl9zZXFb TFJVX0dFTl9BTk9OXSwgbWluX3NlcVtMUlVfR0VOX0ZJTEVdKTsKKwkJbWluX3NlcVtMUlVfR0VO X0ZJTEVdID0gbWF4KG1pbl9zZXFbTFJVX0dFTl9BTk9OXSwgbHJ1Z2VuLT5taW5fc2VxW0xSVV9H RU5fRklMRV0pOworCX0KKworCWZvciAodHlwZSA9ICFjYW5fc3dhcDsgdHlwZSA8IEFOT05fQU5E X0ZJTEU7IHR5cGUrKykgeworCQlpZiAobWluX3NlcVt0eXBlXSA9PSBscnVnZW4tPm1pbl9zZXFb dHlwZV0pCisJCQljb250aW51ZTsKKworCQlyZXNldF9jdHJsX3BvcyhscnV2ZWMsIHR5cGUsIHRy dWUpOworCQlXUklURV9PTkNFKGxydWdlbi0+bWluX3NlcVt0eXBlXSwgbWluX3NlcVt0eXBlXSk7 CisJCXN1Y2Nlc3MgPSB0cnVlOworCX0KKworCXJldHVybiBzdWNjZXNzOworfQorCitzdGF0aWMg dm9pZCBpbmNfbWF4X3NlcShzdHJ1Y3QgbHJ1dmVjICpscnV2ZWMsIHVuc2lnbmVkIGxvbmcgbWF4 X3NlcSkKK3sKKwlpbnQgcHJldiwgbmV4dDsKKwlpbnQgdHlwZSwgem9uZTsKKwlzdHJ1Y3QgbHJ1 X2dlbl9zdHJ1Y3QgKmxydWdlbiA9ICZscnV2ZWMtPmxydWdlbjsKKworCXNwaW5fbG9ja19pcnEo JmxydXZlYy0+bHJ1X2xvY2spOworCisJVk1fQlVHX09OKCFzZXFfaXNfdmFsaWQobHJ1dmVjKSk7 CisKKwlpZiAobWF4X3NlcSAhPSBscnVnZW4tPm1heF9zZXEpCisJCWdvdG8gdW5sb2NrOworCisJ aW5jX21pbl9zZXEobHJ1dmVjKTsKKworCS8qIHVwZGF0ZSB0aGUgYWN0aXZlL2luYWN0aXZlIExS VSBzaXplcyBmb3IgY29tcGF0aWJpbGl0eSAqLworCXByZXYgPSBscnVfZ2VuX2Zyb21fc2VxKGxy dWdlbi0+bWF4X3NlcSAtIDEpOworCW5leHQgPSBscnVfZ2VuX2Zyb21fc2VxKGxydWdlbi0+bWF4 X3NlcSArIDEpOworCisJZm9yICh0eXBlID0gMDsgdHlwZSA8IEFOT05fQU5EX0ZJTEU7IHR5cGUr KykgeworCQlmb3IgKHpvbmUgPSAwOyB6b25lIDwgTUFYX05SX1pPTkVTOyB6b25lKyspIHsKKwkJ CWVudW0gbHJ1X2xpc3QgbHJ1ID0gdHlwZSAqIExSVV9JTkFDVElWRV9GSUxFOworCQkJbG9uZyBk ZWx0YSA9IGxydWdlbi0+bnJfcGFnZXNbcHJldl1bdHlwZV1bem9uZV0gLQorCQkJCSAgICAgbHJ1 Z2VuLT5ucl9wYWdlc1tuZXh0XVt0eXBlXVt6b25lXTsKKworCQkJaWYgKCFkZWx0YSkKKwkJCQlj b250aW51ZTsKKworCQkJX191cGRhdGVfbHJ1X3NpemUobHJ1dmVjLCBscnUsIHpvbmUsIGRlbHRh KTsKKwkJCV9fdXBkYXRlX2xydV9zaXplKGxydXZlYywgbHJ1ICsgTFJVX0FDVElWRSwgem9uZSwg LWRlbHRhKTsKKwkJfQorCX0KKworCWZvciAodHlwZSA9IDA7IHR5cGUgPCBBTk9OX0FORF9GSUxF OyB0eXBlKyspCisJCXJlc2V0X2N0cmxfcG9zKGxydXZlYywgdHlwZSwgZmFsc2UpOworCisJLyog bWFrZSBzdXJlIHByZWNlZGluZyBtb2RpZmljYXRpb25zIGFwcGVhciAqLworCXNtcF9zdG9yZV9y ZWxlYXNlKCZscnVnZW4tPm1heF9zZXEsIGxydWdlbi0+bWF4X3NlcSArIDEpOwordW5sb2NrOgor CXNwaW5fdW5sb2NrX2lycSgmbHJ1dmVjLT5scnVfbG9jayk7Cit9CisKK3N0YXRpYyBsb25nIGdl dF9ucl9ldmljdGFibGUoc3RydWN0IGxydXZlYyAqbHJ1dmVjLCB1bnNpZ25lZCBsb25nIG1heF9z ZXEsCisJCQkgICAgIHVuc2lnbmVkIGxvbmcgKm1pbl9zZXEsIGJvb2wgY2FuX3N3YXAsIGJvb2wg Km5lZWRfYWdpbmcpCit7CisJaW50IGdlbiwgdHlwZSwgem9uZTsKKwlsb25nIG9sZCA9IDA7CisJ bG9uZyB5b3VuZyA9IDA7CisJbG9uZyB0b3RhbCA9IDA7CisJc3RydWN0IGxydV9nZW5fc3RydWN0 ICpscnVnZW4gPSAmbHJ1dmVjLT5scnVnZW47CisKKwlmb3IgKHR5cGUgPSAhY2FuX3N3YXA7IHR5 cGUgPCBBTk9OX0FORF9GSUxFOyB0eXBlKyspIHsKKwkJdW5zaWduZWQgbG9uZyBzZXE7CisKKwkJ Zm9yIChzZXEgPSBtaW5fc2VxW3R5cGVdOyBzZXEgPD0gbWF4X3NlcTsgc2VxKyspIHsKKwkJCWxv bmcgc2l6ZSA9IDA7CisKKwkJCWdlbiA9IGxydV9nZW5fZnJvbV9zZXEoc2VxKTsKKworCQkJZm9y ICh6b25lID0gMDsgem9uZSA8IE1BWF9OUl9aT05FUzsgem9uZSsrKQorCQkJCXNpemUgKz0gUkVB RF9PTkNFKGxydWdlbi0+bnJfcGFnZXNbZ2VuXVt0eXBlXVt6b25lXSk7CisKKwkJCXRvdGFsICs9 IHNpemU7CisJCQlpZiAoc2VxID09IG1heF9zZXEpCisJCQkJeW91bmcgKz0gc2l6ZTsKKwkJCWlm IChzZXEgKyBNSU5fTlJfR0VOUyA9PSBtYXhfc2VxKQorCQkJCW9sZCArPSBzaXplOworCQl9CisJ fQorCisJLyogdHJ5IHRvIHNwcmVhZCBwYWdlcyBvdXQgYWNyb3NzIE1JTl9OUl9HRU5TKzEgZ2Vu ZXJhdGlvbnMgKi8KKwlpZiAobWluX3NlcVtMUlVfR0VOX0ZJTEVdICsgTUlOX05SX0dFTlMgPiBt YXhfc2VxKQorCQkqbmVlZF9hZ2luZyA9IHRydWU7CisJZWxzZSBpZiAobWluX3NlcVtMUlVfR0VO X0ZJTEVdICsgTUlOX05SX0dFTlMgPCBtYXhfc2VxKQorCQkqbmVlZF9hZ2luZyA9IGZhbHNlOwor CWVsc2UgaWYgKHlvdW5nICogTUlOX05SX0dFTlMgPiB0b3RhbCkKKwkJKm5lZWRfYWdpbmcgPSB0 cnVlOworCWVsc2UgaWYgKG9sZCAqIChNSU5fTlJfR0VOUyArIDIpIDwgdG90YWwpCisJCSpuZWVk X2FnaW5nID0gdHJ1ZTsKKwllbHNlCisJCSpuZWVkX2FnaW5nID0gZmFsc2U7CisKKwlyZXR1cm4g dG90YWwgPiAwID8gdG90YWwgOiAwOworfQorCitzdGF0aWMgdm9pZCBhZ2VfbHJ1dmVjKHN0cnVj dCBscnV2ZWMgKmxydXZlYywgc3RydWN0IHNjYW5fY29udHJvbCAqc2MpCit7CisJYm9vbCBuZWVk X2FnaW5nOworCWxvbmcgbnJfdG9fc2NhbjsKKwlpbnQgc3dhcHBpbmVzcyA9IGdldF9zd2FwcGlu ZXNzKGxydXZlYywgc2MpOworCXN0cnVjdCBtZW1fY2dyb3VwICptZW1jZyA9IGxydXZlY19tZW1j ZyhscnV2ZWMpOworCURFRklORV9NQVhfU0VRKGxydXZlYyk7CisJREVGSU5FX01JTl9TRVEobHJ1 dmVjKTsKKworCW1lbV9jZ3JvdXBfY2FsY3VsYXRlX3Byb3RlY3Rpb24oTlVMTCwgbWVtY2cpOwor CisJaWYgKG1lbV9jZ3JvdXBfYmVsb3dfbWluKG1lbWNnKSkKKwkJcmV0dXJuOworCisJbnJfdG9f c2NhbiA9IGdldF9ucl9ldmljdGFibGUobHJ1dmVjLCBtYXhfc2VxLCBtaW5fc2VxLCBzd2FwcGlu ZXNzLCAmbmVlZF9hZ2luZyk7CisJaWYgKCFucl90b19zY2FuKQorCQlyZXR1cm47CisKKwlucl90 b19zY2FuID4+PSBzYy0+cHJpb3JpdHk7CisKKwlpZiAoIW1lbV9jZ3JvdXBfb25saW5lKG1lbWNn KSkKKwkJbnJfdG9fc2NhbisrOworCisJaWYgKG5yX3RvX3NjYW4gJiYgbmVlZF9hZ2luZyAmJiAo IW1lbV9jZ3JvdXBfYmVsb3dfbG93KG1lbWNnKSB8fCBzYy0+bWVtY2dfbG93X3JlY2xhaW0pKQor CQlpbmNfbWF4X3NlcShscnV2ZWMsIG1heF9zZXEpOworfQorCitzdGF0aWMgdm9pZCBscnVfZ2Vu X2FnZV9ub2RlKHN0cnVjdCBwZ2xpc3RfZGF0YSAqcGdkYXQsIHN0cnVjdCBzY2FuX2NvbnRyb2wg KnNjKQoreworCXN0cnVjdCBtZW1fY2dyb3VwICptZW1jZzsKKworCVZNX0JVR19PTighY3VycmVu dF9pc19rc3dhcGQoKSk7CisKKwltZW1jZyA9IG1lbV9jZ3JvdXBfaXRlcihOVUxMLCBOVUxMLCBO VUxMKTsKKwlkbyB7CisJCXN0cnVjdCBscnV2ZWMgKmxydXZlYyA9IG1lbV9jZ3JvdXBfbHJ1dmVj KG1lbWNnLCBwZ2RhdCk7CisKKwkJYWdlX2xydXZlYyhscnV2ZWMsIHNjKTsKKworCQljb25kX3Jl c2NoZWQoKTsKKwl9IHdoaWxlICgobWVtY2cgPSBtZW1fY2dyb3VwX2l0ZXIoTlVMTCwgbWVtY2cs IE5VTEwpKSk7Cit9CisKKy8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKKyAqICAgICAgICAgICAgICAg ICAgICAgICAgICB0aGUgZXZpY3Rpb24KKyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovCisKK3N0YXRp YyBib29sIHNvcnRfZm9saW8oc3RydWN0IGxydXZlYyAqbHJ1dmVjLCBzdHJ1Y3QgZm9saW8gKmZv bGlvLCBpbnQgdGllcl9pZHgpCit7CisJYm9vbCBzdWNjZXNzOworCWludCBnZW4gPSBmb2xpb19s cnVfZ2VuKGZvbGlvKTsKKwlpbnQgdHlwZSA9IGZvbGlvX2lzX2ZpbGVfbHJ1KGZvbGlvKTsKKwlp bnQgem9uZSA9IGZvbGlvX3pvbmVudW0oZm9saW8pOworCWludCB0aWVyID0gZm9saW9fbHJ1X3Rp ZXIoZm9saW8pOworCWludCBkZWx0YSA9IGZvbGlvX25yX3BhZ2VzKGZvbGlvKTsKKwlzdHJ1Y3Qg bHJ1X2dlbl9zdHJ1Y3QgKmxydWdlbiA9ICZscnV2ZWMtPmxydWdlbjsKKworCVZNX0JVR19PTl9G T0xJTyhnZW4gPj0gTUFYX05SX0dFTlMsIGZvbGlvKTsKKworCWlmICghZm9saW9fZXZpY3RhYmxl KGZvbGlvKSkgeworCQlzdWNjZXNzID0gbHJ1X2dlbl9kZWxfZm9saW8obHJ1dmVjLCBmb2xpbywg dHJ1ZSk7CisJCVZNX0JVR19PTl9GT0xJTyghc3VjY2VzcywgZm9saW8pOworCQlmb2xpb19zZXRf dW5ldmljdGFibGUoZm9saW8pOworCQlscnV2ZWNfYWRkX2ZvbGlvKGxydXZlYywgZm9saW8pOwor CQlfX2NvdW50X3ZtX2V2ZW50cyhVTkVWSUNUQUJMRV9QR0NVTExFRCwgZGVsdGEpOworCQlyZXR1 cm4gdHJ1ZTsKKwl9CisKKwlpZiAodHlwZSA9PSBMUlVfR0VOX0ZJTEUgJiYgZm9saW9fdGVzdF9h bm9uKGZvbGlvKSAmJiBmb2xpb190ZXN0X2RpcnR5KGZvbGlvKSkgeworCQlzdWNjZXNzID0gbHJ1 X2dlbl9kZWxfZm9saW8obHJ1dmVjLCBmb2xpbywgdHJ1ZSk7CisJCVZNX0JVR19PTl9GT0xJTygh c3VjY2VzcywgZm9saW8pOworCQlmb2xpb19zZXRfc3dhcGJhY2tlZChmb2xpbyk7CisJCWxydXZl Y19hZGRfZm9saW9fdGFpbChscnV2ZWMsIGZvbGlvKTsKKwkJcmV0dXJuIHRydWU7CisJfQorCisJ aWYgKHRpZXIgPiB0aWVyX2lkeCkgeworCQlpbnQgaGlzdCA9IGxydV9oaXN0X2Zyb21fc2VxKGxy dWdlbi0+bWluX3NlcVt0eXBlXSk7CisKKwkJZ2VuID0gZm9saW9faW5jX2dlbihscnV2ZWMsIGZv bGlvLCBmYWxzZSk7CisJCWxpc3RfbW92ZV90YWlsKCZmb2xpby0+bHJ1LCAmbHJ1Z2VuLT5saXN0 c1tnZW5dW3R5cGVdW3pvbmVdKTsKKworCQlXUklURV9PTkNFKGxydWdlbi0+cHJvdGVjdGVkW2hp c3RdW3R5cGVdW3RpZXIgLSAxXSwKKwkJCSAgIGxydWdlbi0+cHJvdGVjdGVkW2hpc3RdW3R5cGVd W3RpZXIgLSAxXSArIGRlbHRhKTsKKwkJX19tb2RfbHJ1dmVjX3N0YXRlKGxydXZlYywgV09SS0lO R1NFVF9BQ1RJVkFURV9CQVNFICsgdHlwZSwgZGVsdGEpOworCQlyZXR1cm4gdHJ1ZTsKKwl9CisK KwlpZiAoZm9saW9fdGVzdF9sb2NrZWQoZm9saW8pIHx8IGZvbGlvX3Rlc3Rfd3JpdGViYWNrKGZv bGlvKSB8fAorCSAgICAodHlwZSA9PSBMUlVfR0VOX0ZJTEUgJiYgZm9saW9fdGVzdF9kaXJ0eShm b2xpbykpKSB7CisJCWdlbiA9IGZvbGlvX2luY19nZW4obHJ1dmVjLCBmb2xpbywgdHJ1ZSk7CisJ CWxpc3RfbW92ZSgmZm9saW8tPmxydSwgJmxydWdlbi0+bGlzdHNbZ2VuXVt0eXBlXVt6b25lXSk7 CisJCXJldHVybiB0cnVlOworCX0KKworCXJldHVybiBmYWxzZTsKK30KKworc3RhdGljIGJvb2wg aXNvbGF0ZV9mb2xpbyhzdHJ1Y3QgbHJ1dmVjICpscnV2ZWMsIHN0cnVjdCBmb2xpbyAqZm9saW8s IHN0cnVjdCBzY2FuX2NvbnRyb2wgKnNjKQoreworCWJvb2wgc3VjY2VzczsKKworCWlmICghc2Mt Pm1heV91bm1hcCAmJiBmb2xpb19tYXBwZWQoZm9saW8pKQorCQlyZXR1cm4gZmFsc2U7CisKKwlp ZiAoIShzYy0+bWF5X3dyaXRlcGFnZSAmJiAoc2MtPmdmcF9tYXNrICYgX19HRlBfSU8pKSAmJgor CSAgICAoZm9saW9fdGVzdF9kaXJ0eShmb2xpbykgfHwKKwkgICAgIChmb2xpb190ZXN0X2Fub24o Zm9saW8pICYmICFmb2xpb190ZXN0X3N3YXBjYWNoZShmb2xpbykpKSkKKwkJcmV0dXJuIGZhbHNl OworCisJaWYgKCFmb2xpb190cnlfZ2V0KGZvbGlvKSkKKwkJcmV0dXJuIGZhbHNlOworCisJaWYg KCFmb2xpb190ZXN0X2NsZWFyX2xydShmb2xpbykpIHsKKwkJZm9saW9fcHV0KGZvbGlvKTsKKwkJ cmV0dXJuIGZhbHNlOworCX0KKworCXN1Y2Nlc3MgPSBscnVfZ2VuX2RlbF9mb2xpbyhscnV2ZWMs IGZvbGlvLCB0cnVlKTsKKwlWTV9CVUdfT05fRk9MSU8oIXN1Y2Nlc3MsIGZvbGlvKTsKKworCXJl dHVybiB0cnVlOworfQorCitzdGF0aWMgaW50IHNjYW5fZm9saW9zKHN0cnVjdCBscnV2ZWMgKmxy dXZlYywgc3RydWN0IHNjYW5fY29udHJvbCAqc2MsCisJCSAgICAgICBpbnQgdHlwZSwgaW50IHRp ZXIsIHN0cnVjdCBsaXN0X2hlYWQgKmxpc3QpCit7CisJaW50IGdlbiwgem9uZTsKKwllbnVtIHZt X2V2ZW50X2l0ZW0gaXRlbTsKKwlpbnQgc29ydGVkID0gMDsKKwlpbnQgc2Nhbm5lZCA9IDA7CisJ aW50IGlzb2xhdGVkID0gMDsKKwlpbnQgcmVtYWluaW5nID0gTUFYX0xSVV9CQVRDSDsKKwlzdHJ1 Y3QgbHJ1X2dlbl9zdHJ1Y3QgKmxydWdlbiA9ICZscnV2ZWMtPmxydWdlbjsKKwlzdHJ1Y3QgbWVt X2Nncm91cCAqbWVtY2cgPSBscnV2ZWNfbWVtY2cobHJ1dmVjKTsKKworCVZNX0JVR19PTighbGlz dF9lbXB0eShsaXN0KSk7CisKKwlpZiAoZ2V0X25yX2dlbnMobHJ1dmVjLCB0eXBlKSA9PSBNSU5f TlJfR0VOUykKKwkJcmV0dXJuIDA7CisKKwlnZW4gPSBscnVfZ2VuX2Zyb21fc2VxKGxydWdlbi0+ bWluX3NlcVt0eXBlXSk7CisKKwlmb3IgKHpvbmUgPSBzYy0+cmVjbGFpbV9pZHg7IHpvbmUgPj0g MDsgem9uZS0tKSB7CisJCUxJU1RfSEVBRChtb3ZlZCk7CisJCWludCBza2lwcGVkID0gMDsKKwkJ c3RydWN0IGxpc3RfaGVhZCAqaGVhZCA9ICZscnVnZW4tPmxpc3RzW2dlbl1bdHlwZV1bem9uZV07 CisKKwkJd2hpbGUgKCFsaXN0X2VtcHR5KGhlYWQpKSB7CisJCQlzdHJ1Y3QgZm9saW8gKmZvbGlv ID0gbHJ1X3RvX2ZvbGlvKGhlYWQpOworCQkJaW50IGRlbHRhID0gZm9saW9fbnJfcGFnZXMoZm9s aW8pOworCisJCQlWTV9CVUdfT05fRk9MSU8oZm9saW9fdGVzdF91bmV2aWN0YWJsZShmb2xpbyks IGZvbGlvKTsKKwkJCVZNX0JVR19PTl9GT0xJTyhmb2xpb190ZXN0X2FjdGl2ZShmb2xpbyksIGZv bGlvKTsKKwkJCVZNX0JVR19PTl9GT0xJTyhmb2xpb19pc19maWxlX2xydShmb2xpbykgIT0gdHlw ZSwgZm9saW8pOworCQkJVk1fQlVHX09OX0ZPTElPKGZvbGlvX3pvbmVudW0oZm9saW8pICE9IHpv bmUsIGZvbGlvKTsKKworCQkJc2Nhbm5lZCArPSBkZWx0YTsKKworCQkJaWYgKHNvcnRfZm9saW8o bHJ1dmVjLCBmb2xpbywgdGllcikpCisJCQkJc29ydGVkICs9IGRlbHRhOworCQkJZWxzZSBpZiAo aXNvbGF0ZV9mb2xpbyhscnV2ZWMsIGZvbGlvLCBzYykpIHsKKwkJCQlsaXN0X2FkZCgmZm9saW8t PmxydSwgbGlzdCk7CisJCQkJaXNvbGF0ZWQgKz0gZGVsdGE7CisJCQl9IGVsc2UgeworCQkJCWxp c3RfbW92ZSgmZm9saW8tPmxydSwgJm1vdmVkKTsKKwkJCQlza2lwcGVkICs9IGRlbHRhOworCQkJ fQorCisJCQlpZiAoIS0tcmVtYWluaW5nIHx8IG1heChpc29sYXRlZCwgc2tpcHBlZCkgPj0gTUlO X0xSVV9CQVRDSCkKKwkJCQlicmVhazsKKwkJfQorCisJCWlmIChza2lwcGVkKSB7CisJCQlsaXN0 X3NwbGljZSgmbW92ZWQsIGhlYWQpOworCQkJX19jb3VudF96aWRfdm1fZXZlbnRzKFBHU0NBTl9T S0lQLCB6b25lLCBza2lwcGVkKTsKKwkJfQorCisJCWlmICghcmVtYWluaW5nIHx8IGlzb2xhdGVk ID49IE1JTl9MUlVfQkFUQ0gpCisJCQlicmVhazsKKwl9CisKKwlpdGVtID0gY3VycmVudF9pc19r c3dhcGQoKSA/IFBHU0NBTl9LU1dBUEQgOiBQR1NDQU5fRElSRUNUOworCWlmICghY2dyb3VwX3Jl Y2xhaW0oc2MpKSB7CisJCV9fY291bnRfdm1fZXZlbnRzKGl0ZW0sIGlzb2xhdGVkKTsKKwkJX19j b3VudF92bV9ldmVudHMoUEdSRUZJTEwsIHNvcnRlZCk7CisJfQorCV9fY291bnRfbWVtY2dfZXZl bnRzKG1lbWNnLCBpdGVtLCBpc29sYXRlZCk7CisJX19jb3VudF9tZW1jZ19ldmVudHMobWVtY2cs IFBHUkVGSUxMLCBzb3J0ZWQpOworCV9fY291bnRfdm1fZXZlbnRzKFBHU0NBTl9BTk9OICsgdHlw ZSwgaXNvbGF0ZWQpOworCisJLyoKKwkgKiBUaGVyZSBtaWdodCBub3QgYmUgZWxpZ2libGUgcGFn ZXMgZHVlIHRvIHJlY2xhaW1faWR4LCBtYXlfdW5tYXAgYW5kCisJICogbWF5X3dyaXRlcGFnZS4g Q2hlY2sgdGhlIHJlbWFpbmluZyB0byBwcmV2ZW50IGxpdmVsb2NrIGlmIHRoZXJlIGlzIG5vCisJ ICogcHJvZ3Jlc3MuCisJICovCisJcmV0dXJuIGlzb2xhdGVkIHx8ICFyZW1haW5pbmcgPyBzY2Fu bmVkIDogMDsKK30KKworc3RhdGljIGludCBnZXRfdGllcl9pZHgoc3RydWN0IGxydXZlYyAqbHJ1 dmVjLCBpbnQgdHlwZSkKK3sKKwlpbnQgdGllcjsKKwlzdHJ1Y3QgY3RybF9wb3Mgc3AsIHB2Owor CisJLyoKKwkgKiBUbyBsZWF2ZSBhIG1hcmdpbiBmb3IgZmx1Y3R1YXRpb25zLCB1c2UgYSBsYXJn ZXIgZ2FpbiBmYWN0b3IgKDE6MikuCisJICogVGhpcyB2YWx1ZSBpcyBjaG9zZW4gYmVjYXVzZSBh bnkgb3RoZXIgdGllciB3b3VsZCBoYXZlIGF0IGxlYXN0IHR3aWNlCisJICogYXMgbWFueSByZWZh dWx0cyBhcyB0aGUgZmlyc3QgdGllci4KKwkgKi8KKwlyZWFkX2N0cmxfcG9zKGxydXZlYywgdHlw ZSwgMCwgMSwgJnNwKTsKKwlmb3IgKHRpZXIgPSAxOyB0aWVyIDwgTUFYX05SX1RJRVJTOyB0aWVy KyspIHsKKwkJcmVhZF9jdHJsX3BvcyhscnV2ZWMsIHR5cGUsIHRpZXIsIDIsICZwdik7CisJCWlm ICghcG9zaXRpdmVfY3RybF9lcnIoJnNwLCAmcHYpKQorCQkJYnJlYWs7CisJfQorCisJcmV0dXJu IHRpZXIgLSAxOworfQorCitzdGF0aWMgaW50IGdldF90eXBlX3RvX3NjYW4oc3RydWN0IGxydXZl YyAqbHJ1dmVjLCBpbnQgc3dhcHBpbmVzcywgaW50ICp0aWVyX2lkeCkKK3sKKwlpbnQgdHlwZSwg dGllcjsKKwlzdHJ1Y3QgY3RybF9wb3Mgc3AsIHB2OworCWludCBnYWluW0FOT05fQU5EX0ZJTEVd ID0geyBzd2FwcGluZXNzLCAyMDAgLSBzd2FwcGluZXNzIH07CisKKwkvKgorCSAqIENvbXBhcmUg dGhlIGZpcnN0IHRpZXIgb2YgYW5vbiB3aXRoIHRoYXQgb2YgZmlsZSB0byBkZXRlcm1pbmUgd2hp Y2gKKwkgKiB0eXBlIHRvIHNjYW4uIEFsc28gbmVlZCB0byBjb21wYXJlIG90aGVyIHRpZXJzIG9m IHRoZSBzZWxlY3RlZCB0eXBlCisJICogd2l0aCB0aGUgZmlyc3QgdGllciBvZiB0aGUgb3RoZXIg dHlwZSB0byBkZXRlcm1pbmUgdGhlIGxhc3QgdGllciAob2YKKwkgKiB0aGUgc2VsZWN0ZWQgdHlw ZSkgdG8gZXZpY3QuCisJICovCisJcmVhZF9jdHJsX3BvcyhscnV2ZWMsIExSVV9HRU5fQU5PTiwg MCwgZ2FpbltMUlVfR0VOX0FOT05dLCAmc3ApOworCXJlYWRfY3RybF9wb3MobHJ1dmVjLCBMUlVf R0VOX0ZJTEUsIDAsIGdhaW5bTFJVX0dFTl9GSUxFXSwgJnB2KTsKKwl0eXBlID0gcG9zaXRpdmVf Y3RybF9lcnIoJnNwLCAmcHYpOworCisJcmVhZF9jdHJsX3BvcyhscnV2ZWMsICF0eXBlLCAwLCBn YWluWyF0eXBlXSwgJnNwKTsKKwlmb3IgKHRpZXIgPSAxOyB0aWVyIDwgTUFYX05SX1RJRVJTOyB0 aWVyKyspIHsKKwkJcmVhZF9jdHJsX3BvcyhscnV2ZWMsIHR5cGUsIHRpZXIsIGdhaW5bdHlwZV0s ICZwdik7CisJCWlmICghcG9zaXRpdmVfY3RybF9lcnIoJnNwLCAmcHYpKQorCQkJYnJlYWs7CisJ fQorCisJKnRpZXJfaWR4ID0gdGllciAtIDE7CisKKwlyZXR1cm4gdHlwZTsKK30KKworc3RhdGlj IGludCBpc29sYXRlX2ZvbGlvcyhzdHJ1Y3QgbHJ1dmVjICpscnV2ZWMsIHN0cnVjdCBzY2FuX2Nv bnRyb2wgKnNjLCBpbnQgc3dhcHBpbmVzcywKKwkJCSAgaW50ICp0eXBlX3NjYW5uZWQsIHN0cnVj dCBsaXN0X2hlYWQgKmxpc3QpCit7CisJaW50IGk7CisJaW50IHR5cGU7CisJaW50IHNjYW5uZWQ7 CisJaW50IHRpZXIgPSAtMTsKKwlERUZJTkVfTUlOX1NFUShscnV2ZWMpOworCisJVk1fQlVHX09O KCFzZXFfaXNfdmFsaWQobHJ1dmVjKSk7CisKKwkvKgorCSAqIFRyeSB0byBtYWtlIHRoZSBvYnZp b3VzIGNob2ljZSBmaXJzdC4gV2hlbiBhbm9uIGFuZCBmaWxlIGFyZSBib3RoCisJICogYXZhaWxh YmxlIGZyb20gdGhlIHNhbWUgZ2VuZXJhdGlvbiwgaW50ZXJwcmV0IHN3YXBwaW5lc3MgMSBhcyBm aWxlCisJICogZmlyc3QgYW5kIDIwMCBhcyBhbm9uIGZpcnN0LgorCSAqLworCWlmICghc3dhcHBp bmVzcykKKwkJdHlwZSA9IExSVV9HRU5fRklMRTsKKwllbHNlIGlmIChtaW5fc2VxW0xSVV9HRU5f QU5PTl0gPCBtaW5fc2VxW0xSVV9HRU5fRklMRV0pCisJCXR5cGUgPSBMUlVfR0VOX0FOT047CisJ ZWxzZSBpZiAoc3dhcHBpbmVzcyA9PSAxKQorCQl0eXBlID0gTFJVX0dFTl9GSUxFOworCWVsc2Ug aWYgKHN3YXBwaW5lc3MgPT0gMjAwKQorCQl0eXBlID0gTFJVX0dFTl9BTk9OOworCWVsc2UKKwkJ dHlwZSA9IGdldF90eXBlX3RvX3NjYW4obHJ1dmVjLCBzd2FwcGluZXNzLCAmdGllcik7CisKKwlm b3IgKGkgPSAhc3dhcHBpbmVzczsgaSA8IEFOT05fQU5EX0ZJTEU7IGkrKykgeworCQlpZiAodGll ciA8IDApCisJCQl0aWVyID0gZ2V0X3RpZXJfaWR4KGxydXZlYywgdHlwZSk7CisKKwkJc2Nhbm5l ZCA9IHNjYW5fZm9saW9zKGxydXZlYywgc2MsIHR5cGUsIHRpZXIsIGxpc3QpOworCQlpZiAoc2Nh bm5lZCkKKwkJCWJyZWFrOworCisJCXR5cGUgPSAhdHlwZTsKKwkJdGllciA9IC0xOworCX0KKwor CSp0eXBlX3NjYW5uZWQgPSB0eXBlOworCisJcmV0dXJuIHNjYW5uZWQ7Cit9CisKK3N0YXRpYyBp bnQgZXZpY3RfZm9saW9zKHN0cnVjdCBscnV2ZWMgKmxydXZlYywgc3RydWN0IHNjYW5fY29udHJv bCAqc2MsIGludCBzd2FwcGluZXNzKQoreworCWludCB0eXBlOworCWludCBzY2FubmVkOworCWlu dCByZWNsYWltZWQ7CisJTElTVF9IRUFEKGxpc3QpOworCXN0cnVjdCBmb2xpbyAqZm9saW87CisJ ZW51bSB2bV9ldmVudF9pdGVtIGl0ZW07CisJc3RydWN0IHJlY2xhaW1fc3RhdCBzdGF0OworCXN0 cnVjdCBtZW1fY2dyb3VwICptZW1jZyA9IGxydXZlY19tZW1jZyhscnV2ZWMpOworCXN0cnVjdCBw Z2xpc3RfZGF0YSAqcGdkYXQgPSBscnV2ZWNfcGdkYXQobHJ1dmVjKTsKKworCXNwaW5fbG9ja19p cnEoJmxydXZlYy0+bHJ1X2xvY2spOworCisJc2Nhbm5lZCA9IGlzb2xhdGVfZm9saW9zKGxydXZl Yywgc2MsIHN3YXBwaW5lc3MsICZ0eXBlLCAmbGlzdCk7CisKKwlpZiAodHJ5X3RvX2luY19taW5f c2VxKGxydXZlYywgc3dhcHBpbmVzcykpCisJCXNjYW5uZWQrKzsKKworCWlmIChnZXRfbnJfZ2Vu cyhscnV2ZWMsIExSVV9HRU5fRklMRSkgPT0gTUlOX05SX0dFTlMpCisJCXNjYW5uZWQgPSAwOwor CisJc3Bpbl91bmxvY2tfaXJxKCZscnV2ZWMtPmxydV9sb2NrKTsKKworCWlmIChsaXN0X2VtcHR5 KCZsaXN0KSkKKwkJcmV0dXJuIHNjYW5uZWQ7CisKKwlyZWNsYWltZWQgPSBzaHJpbmtfcGFnZV9s aXN0KCZsaXN0LCBwZ2RhdCwgc2MsICZzdGF0LCBmYWxzZSk7CisKKwkvKgorCSAqIFRvIGF2b2lk IGxpdmVsb2NrLCBkb24ndCBhZGQgcmVqZWN0ZWQgcGFnZXMgYmFjayB0byB0aGUgc2FtZSBsaXN0 cworCSAqIHRoZXkgd2VyZSBpc29sYXRlZCBmcm9tLiBTZWUgbHJ1X2dlbl9hZGRfZm9saW8oKS4K KwkgKi8KKwlsaXN0X2Zvcl9lYWNoX2VudHJ5KGZvbGlvLCAmbGlzdCwgbHJ1KSB7CisJCWlmIChm b2xpb190ZXN0X3JlY2xhaW0oZm9saW8pICYmCisJCSAgICAoZm9saW9fdGVzdF9kaXJ0eShmb2xp bykgfHwgZm9saW9fdGVzdF93cml0ZWJhY2soZm9saW8pKSkKKwkJCWZvbGlvX2NsZWFyX2FjdGl2 ZShmb2xpbyk7CisJCWVsc2UgaWYgKGZvbGlvX2lzX2ZpbGVfbHJ1KGZvbGlvKSB8fCBmb2xpb190 ZXN0X3N3YXBjYWNoZShmb2xpbykpCisJCQlmb2xpb19zZXRfYWN0aXZlKGZvbGlvKTsKKworCQlm b2xpb19jbGVhcl9yZWZlcmVuY2VkKGZvbGlvKTsKKwkJZm9saW9fY2xlYXJfd29ya2luZ3NldChm b2xpbyk7CisJfQorCisJc3Bpbl9sb2NrX2lycSgmbHJ1dmVjLT5scnVfbG9jayk7CisKKwltb3Zl X3BhZ2VzX3RvX2xydShscnV2ZWMsICZsaXN0KTsKKworCWl0ZW0gPSBjdXJyZW50X2lzX2tzd2Fw ZCgpID8gUEdTVEVBTF9LU1dBUEQgOiBQR1NURUFMX0RJUkVDVDsKKwlpZiAoIWNncm91cF9yZWNs YWltKHNjKSkKKwkJX19jb3VudF92bV9ldmVudHMoaXRlbSwgcmVjbGFpbWVkKTsKKwlfX2NvdW50 X21lbWNnX2V2ZW50cyhtZW1jZywgaXRlbSwgcmVjbGFpbWVkKTsKKwlfX2NvdW50X3ZtX2V2ZW50 cyhQR1NURUFMX0FOT04gKyB0eXBlLCByZWNsYWltZWQpOworCisJc3Bpbl91bmxvY2tfaXJxKCZs cnV2ZWMtPmxydV9sb2NrKTsKKworCW1lbV9jZ3JvdXBfdW5jaGFyZ2VfbGlzdCgmbGlzdCk7CisJ ZnJlZV91bnJlZl9wYWdlX2xpc3QoJmxpc3QpOworCisJc2MtPm5yX3JlY2xhaW1lZCArPSByZWNs YWltZWQ7CisKKwlyZXR1cm4gc2Nhbm5lZDsKK30KKworc3RhdGljIGxvbmcgZ2V0X25yX3RvX3Nj YW4oc3RydWN0IGxydXZlYyAqbHJ1dmVjLCBzdHJ1Y3Qgc2Nhbl9jb250cm9sICpzYywgYm9vbCBj YW5fc3dhcCkKK3sKKwlib29sIG5lZWRfYWdpbmc7CisJbG9uZyBucl90b19zY2FuOworCXN0cnVj dCBtZW1fY2dyb3VwICptZW1jZyA9IGxydXZlY19tZW1jZyhscnV2ZWMpOworCURFRklORV9NQVhf U0VRKGxydXZlYyk7CisJREVGSU5FX01JTl9TRVEobHJ1dmVjKTsKKworCWlmIChtZW1fY2dyb3Vw X2JlbG93X21pbihtZW1jZykgfHwKKwkgICAgKG1lbV9jZ3JvdXBfYmVsb3dfbG93KG1lbWNnKSAm JiAhc2MtPm1lbWNnX2xvd19yZWNsYWltKSkKKwkJcmV0dXJuIDA7CisKKwlucl90b19zY2FuID0g Z2V0X25yX2V2aWN0YWJsZShscnV2ZWMsIG1heF9zZXEsIG1pbl9zZXEsIGNhbl9zd2FwLCAmbmVl ZF9hZ2luZyk7CisJaWYgKCFucl90b19zY2FuKQorCQlyZXR1cm4gMDsKKworCS8qIHJlc2V0IHRo ZSBwcmlvcml0eSBpZiB0aGUgdGFyZ2V0IGhhcyBiZWVuIG1ldCAqLworCW5yX3RvX3NjYW4gPj49 IHNjLT5ucl9yZWNsYWltZWQgPCBzYy0+bnJfdG9fcmVjbGFpbSA/IHNjLT5wcmlvcml0eSA6IERF Rl9QUklPUklUWTsKKworCWlmICghbWVtX2Nncm91cF9vbmxpbmUobWVtY2cpKQorCQlucl90b19z Y2FuKys7CisKKwlpZiAoIW5yX3RvX3NjYW4pCisJCXJldHVybiAwOworCisJaWYgKCFuZWVkX2Fn aW5nKQorCQlyZXR1cm4gbnJfdG9fc2NhbjsKKworCS8qIGxlYXZlIHRoZSB3b3JrIHRvIGxydV9n ZW5fYWdlX25vZGUoKSAqLworCWlmIChjdXJyZW50X2lzX2tzd2FwZCgpKQorCQlyZXR1cm4gMDsK KworCS8qIHRyeSBvdGhlciBtZW1jZ3MgYmVmb3JlIGdvaW5nIHRvIHRoZSBhZ2luZyBwYXRoICov CisJaWYgKCFjZ3JvdXBfcmVjbGFpbShzYykgJiYgIXNjLT5mb3JjZV9kZWFjdGl2YXRlKSB7CisJ CXNjLT5za2lwcGVkX2RlYWN0aXZhdGUgPSB0cnVlOworCQlyZXR1cm4gMDsKKwl9CisKKwlpbmNf bWF4X3NlcShscnV2ZWMsIG1heF9zZXEpOworCisJcmV0dXJuIG5yX3RvX3NjYW47Cit9CisKK3N0 YXRpYyB2b2lkIGxydV9nZW5fc2hyaW5rX2xydXZlYyhzdHJ1Y3QgbHJ1dmVjICpscnV2ZWMsIHN0 cnVjdCBzY2FuX2NvbnRyb2wgKnNjKQoreworCXN0cnVjdCBibGtfcGx1ZyBwbHVnOworCWxvbmcg c2Nhbm5lZCA9IDA7CisKKwlscnVfYWRkX2RyYWluKCk7CisKKwlibGtfc3RhcnRfcGx1ZygmcGx1 Zyk7CisKKwl3aGlsZSAodHJ1ZSkgeworCQlpbnQgZGVsdGE7CisJCWludCBzd2FwcGluZXNzOwor CQlsb25nIG5yX3RvX3NjYW47CisKKwkJaWYgKHNjLT5tYXlfc3dhcCkKKwkJCXN3YXBwaW5lc3Mg PSBnZXRfc3dhcHBpbmVzcyhscnV2ZWMsIHNjKTsKKwkJZWxzZSBpZiAoIWNncm91cF9yZWNsYWlt KHNjKSAmJiBnZXRfc3dhcHBpbmVzcyhscnV2ZWMsIHNjKSkKKwkJCXN3YXBwaW5lc3MgPSAxOwor CQllbHNlCisJCQlzd2FwcGluZXNzID0gMDsKKworCQlucl90b19zY2FuID0gZ2V0X25yX3RvX3Nj YW4obHJ1dmVjLCBzYywgc3dhcHBpbmVzcyk7CisJCWlmICghbnJfdG9fc2NhbikKKwkJCWJyZWFr OworCisJCWRlbHRhID0gZXZpY3RfZm9saW9zKGxydXZlYywgc2MsIHN3YXBwaW5lc3MpOworCQlp ZiAoIWRlbHRhKQorCQkJYnJlYWs7CisKKwkJc2Nhbm5lZCArPSBkZWx0YTsKKwkJaWYgKHNjYW5u ZWQgPj0gbnJfdG9fc2NhbikKKwkJCWJyZWFrOworCisJCWNvbmRfcmVzY2hlZCgpOworCX0KKwor CWJsa19maW5pc2hfcGx1ZygmcGx1Zyk7Cit9CisKIC8qKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICAq ICAgICAgICAgICAgICAgICAgICAgICAgICBpbml0aWFsaXphdGlvbgogICoqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKi8KQEAgLTMxMTMsNiArMzg3NCwxNiBAQCBzdGF0aWMgaW50IF9faW5pdCBpbml0X2xy dV9nZW4odm9pZCkKIH07CiBsYXRlX2luaXRjYWxsKGluaXRfbHJ1X2dlbik7CiAKKyNlbHNlCisK K3N0YXRpYyB2b2lkIGxydV9nZW5fYWdlX25vZGUoc3RydWN0IHBnbGlzdF9kYXRhICpwZ2RhdCwg c3RydWN0IHNjYW5fY29udHJvbCAqc2MpCit7Cit9CisKK3N0YXRpYyB2b2lkIGxydV9nZW5fc2hy aW5rX2xydXZlYyhzdHJ1Y3QgbHJ1dmVjICpscnV2ZWMsIHN0cnVjdCBzY2FuX2NvbnRyb2wgKnNj KQoreworfQorCiAjZW5kaWYgLyogQ09ORklHX0xSVV9HRU4gKi8KIAogc3RhdGljIHZvaWQgc2hy aW5rX2xydXZlYyhzdHJ1Y3QgbHJ1dmVjICpscnV2ZWMsIHN0cnVjdCBzY2FuX2NvbnRyb2wgKnNj KQpAQCAtMzEyNiw2ICszODk3LDExIEBAIHN0YXRpYyB2b2lkIHNocmlua19scnV2ZWMoc3RydWN0 IGxydXZlYyAqbHJ1dmVjLCBzdHJ1Y3Qgc2Nhbl9jb250cm9sICpzYykKIAlzdHJ1Y3QgYmxrX3Bs dWcgcGx1ZzsKIAlib29sIHNjYW5fYWRqdXN0ZWQ7CiAKKwlpZiAobHJ1X2dlbl9lbmFibGVkKCkp IHsKKwkJbHJ1X2dlbl9zaHJpbmtfbHJ1dmVjKGxydXZlYywgc2MpOworCQlyZXR1cm47CisJfQor CiAJZ2V0X3NjYW5fY291bnQobHJ1dmVjLCBzYywgbnIpOwogCiAJLyogUmVjb3JkIHRoZSBvcmln aW5hbCBzY2FuIHRhcmdldCBmb3IgcHJvcG9ydGlvbmFsIGFkanVzdG1lbnRzIGxhdGVyICovCkBA IC0zNjMwLDYgKzQ0MDYsOSBAQCBzdGF0aWMgdm9pZCBzbmFwc2hvdF9yZWZhdWx0cyhzdHJ1Y3Qg bWVtX2Nncm91cCAqdGFyZ2V0X21lbWNnLCBwZ19kYXRhX3QgKnBnZGF0KQogCXN0cnVjdCBscnV2 ZWMgKnRhcmdldF9scnV2ZWM7CiAJdW5zaWduZWQgbG9uZyByZWZhdWx0czsKIAorCWlmIChscnVf Z2VuX2VuYWJsZWQoKSkKKwkJcmV0dXJuOworCiAJdGFyZ2V0X2xydXZlYyA9IG1lbV9jZ3JvdXBf bHJ1dmVjKHRhcmdldF9tZW1jZywgcGdkYXQpOwogCXJlZmF1bHRzID0gbHJ1dmVjX3BhZ2Vfc3Rh dGUodGFyZ2V0X2xydXZlYywgV09SS0lOR1NFVF9BQ1RJVkFURV9BTk9OKTsKIAl0YXJnZXRfbHJ1 dmVjLT5yZWZhdWx0c1swXSA9IHJlZmF1bHRzOwpAQCAtNDAwMCw2ICs0Nzc5LDExIEBAIHN0YXRp YyB2b2lkIGFnZV9hY3RpdmVfYW5vbihzdHJ1Y3QgcGdsaXN0X2RhdGEgKnBnZGF0LAogCXN0cnVj dCBtZW1fY2dyb3VwICptZW1jZzsKIAlzdHJ1Y3QgbHJ1dmVjICpscnV2ZWM7CiAKKwlpZiAobHJ1 X2dlbl9lbmFibGVkKCkpIHsKKwkJbHJ1X2dlbl9hZ2Vfbm9kZShwZ2RhdCwgc2MpOworCQlyZXR1 cm47CisJfQorCiAJaWYgKCFjYW5fYWdlX2Fub25fcGFnZXMocGdkYXQsIHNjKSkKIAkJcmV0dXJu OwogCmRpZmYgLS1naXQgYS9tbS93b3JraW5nc2V0LmMgYi9tbS93b3JraW5nc2V0LmMKaW5kZXgg OGMwM2FmZTFkNjdjLi45M2VlMDBjN2U0ZDEgMTAwNjQ0Ci0tLSBhL21tL3dvcmtpbmdzZXQuYwor KysgYi9tbS93b3JraW5nc2V0LmMKQEAgLTE4Nyw3ICsxODcsNiBAQCBzdGF0aWMgdW5zaWduZWQg aW50IGJ1Y2tldF9vcmRlciBfX3JlYWRfbW9zdGx5Owogc3RhdGljIHZvaWQgKnBhY2tfc2hhZG93 KGludCBtZW1jZ2lkLCBwZ19kYXRhX3QgKnBnZGF0LCB1bnNpZ25lZCBsb25nIGV2aWN0aW9uLAog CQkJIGJvb2wgd29ya2luZ3NldCkKIHsKLQlldmljdGlvbiA+Pj0gYnVja2V0X29yZGVyOwogCWV2 aWN0aW9uICY9IEVWSUNUSU9OX01BU0s7CiAJZXZpY3Rpb24gPSAoZXZpY3Rpb24gPDwgTUVNX0NH Uk9VUF9JRF9TSElGVCkgfCBtZW1jZ2lkOwogCWV2aWN0aW9uID0gKGV2aWN0aW9uIDw8IE5PREVT X1NISUZUKSB8IHBnZGF0LT5ub2RlX2lkOwpAQCAtMjEyLDEwICsyMTEsMTE2IEBAIHN0YXRpYyB2 b2lkIHVucGFja19zaGFkb3codm9pZCAqc2hhZG93LCBpbnQgKm1lbWNnaWRwLCBwZ19kYXRhX3Qg KipwZ2RhdCwKIAogCSptZW1jZ2lkcCA9IG1lbWNnaWQ7CiAJKnBnZGF0ID0gTk9ERV9EQVRBKG5p ZCk7Ci0JKmV2aWN0aW9ucCA9IGVudHJ5IDw8IGJ1Y2tldF9vcmRlcjsKKwkqZXZpY3Rpb25wID0g ZW50cnk7CiAJKndvcmtpbmdzZXRwID0gd29ya2luZ3NldDsKIH0KIAorI2lmZGVmIENPTkZJR19M UlVfR0VOCisKK3N0YXRpYyBpbnQgZm9saW9fbHJ1X3JlZnMoc3RydWN0IGZvbGlvICpmb2xpbykK K3sKKwl1bnNpZ25lZCBsb25nIGZsYWdzID0gUkVBRF9PTkNFKGZvbGlvLT5mbGFncyk7CisKKwlC VUlMRF9CVUdfT04oTFJVX0dFTl9XSURUSCArIExSVV9SRUZTX1dJRFRIID4gQklUU19QRVJfTE9O RyAtIEVWSUNUSU9OX1NISUZUKTsKKworCS8qIHNlZSB0aGUgY29tbWVudCBvbiBNQVhfTlJfVElF UlMgKi8KKwlyZXR1cm4gZmxhZ3MgJiBCSVQoUEdfd29ya2luZ3NldCkgPyAoZmxhZ3MgJiBMUlVf UkVGU19NQVNLKSA+PiBMUlVfUkVGU19QR09GRiA6IDA7Cit9CisKK3N0YXRpYyB2b2lkICpscnVf Z2VuX2V2aWN0aW9uKHN0cnVjdCBmb2xpbyAqZm9saW8pCit7CisJaW50IGhpc3QsIHRpZXI7CisJ dW5zaWduZWQgbG9uZyB0b2tlbjsKKwl1bnNpZ25lZCBsb25nIG1pbl9zZXE7CisJc3RydWN0IGxy dXZlYyAqbHJ1dmVjOworCXN0cnVjdCBscnVfZ2VuX3N0cnVjdCAqbHJ1Z2VuOworCWludCB0eXBl ID0gZm9saW9faXNfZmlsZV9scnUoZm9saW8pOworCWludCByZWZzID0gZm9saW9fbHJ1X3JlZnMo Zm9saW8pOworCWludCBkZWx0YSA9IGZvbGlvX25yX3BhZ2VzKGZvbGlvKTsKKwlib29sIHdvcmtp bmdzZXQgPSBmb2xpb190ZXN0X3dvcmtpbmdzZXQoZm9saW8pOworCXN0cnVjdCBtZW1fY2dyb3Vw ICptZW1jZyA9IGZvbGlvX21lbWNnKGZvbGlvKTsKKwlzdHJ1Y3QgcGdsaXN0X2RhdGEgKnBnZGF0 ID0gZm9saW9fcGdkYXQoZm9saW8pOworCisJbHJ1dmVjID0gbWVtX2Nncm91cF9scnV2ZWMobWVt Y2csIHBnZGF0KTsKKwlscnVnZW4gPSAmbHJ1dmVjLT5scnVnZW47CisJbWluX3NlcSA9IFJFQURf T05DRShscnVnZW4tPm1pbl9zZXFbdHlwZV0pOworCXRva2VuID0gKG1pbl9zZXEgPDwgTFJVX1JF RlNfV0lEVEgpIHwgcmVmczsKKworCWhpc3QgPSBscnVfaGlzdF9mcm9tX3NlcShtaW5fc2VxKTsK Kwl0aWVyID0gbHJ1X3RpZXJfZnJvbV9yZWZzKHJlZnMgKyB3b3JraW5nc2V0KTsKKwlhdG9taWNf bG9uZ19hZGQoZGVsdGEsICZscnVnZW4tPmV2aWN0ZWRbaGlzdF1bdHlwZV1bdGllcl0pOworCisJ cmV0dXJuIHBhY2tfc2hhZG93KG1lbV9jZ3JvdXBfaWQobWVtY2cpLCBwZ2RhdCwgdG9rZW4sIHdv cmtpbmdzZXQpOworfQorCitzdGF0aWMgdm9pZCBscnVfZ2VuX3JlZmF1bHQoc3RydWN0IGZvbGlv ICpmb2xpbywgdm9pZCAqc2hhZG93KQoreworCWludCBoaXN0LCB0aWVyLCByZWZzOworCWludCBt ZW1jZ19pZDsKKwlib29sIHdvcmtpbmdzZXQ7CisJdW5zaWduZWQgbG9uZyB0b2tlbjsKKwl1bnNp Z25lZCBsb25nIG1pbl9zZXE7CisJc3RydWN0IGxydXZlYyAqbHJ1dmVjOworCXN0cnVjdCBscnVf Z2VuX3N0cnVjdCAqbHJ1Z2VuOworCXN0cnVjdCBtZW1fY2dyb3VwICptZW1jZzsKKwlzdHJ1Y3Qg cGdsaXN0X2RhdGEgKnBnZGF0OworCWludCB0eXBlID0gZm9saW9faXNfZmlsZV9scnUoZm9saW8p OworCWludCBkZWx0YSA9IGZvbGlvX25yX3BhZ2VzKGZvbGlvKTsKKworCXVucGFja19zaGFkb3co c2hhZG93LCAmbWVtY2dfaWQsICZwZ2RhdCwgJnRva2VuLCAmd29ya2luZ3NldCk7CisKKwlyZWZz ID0gdG9rZW4gJiAoQklUKExSVV9SRUZTX1dJRFRIKSAtIDEpOworCWlmIChyZWZzICYmICF3b3Jr aW5nc2V0KQorCQlyZXR1cm47CisKKwlpZiAoZm9saW9fcGdkYXQoZm9saW8pICE9IHBnZGF0KQor CQlyZXR1cm47CisKKwlyY3VfcmVhZF9sb2NrKCk7CisJbWVtY2cgPSBmb2xpb19tZW1jZ19yY3Uo Zm9saW8pOworCWlmIChtZW1fY2dyb3VwX2lkKG1lbWNnKSAhPSBtZW1jZ19pZCkKKwkJZ290byB1 bmxvY2s7CisKKwl0b2tlbiA+Pj0gTFJVX1JFRlNfV0lEVEg7CisJbHJ1dmVjID0gbWVtX2Nncm91 cF9scnV2ZWMobWVtY2csIHBnZGF0KTsKKwlscnVnZW4gPSAmbHJ1dmVjLT5scnVnZW47CisJbWlu X3NlcSA9IFJFQURfT05DRShscnVnZW4tPm1pbl9zZXFbdHlwZV0pOworCWlmICh0b2tlbiAhPSAo bWluX3NlcSAmIChFVklDVElPTl9NQVNLID4+IExSVV9SRUZTX1dJRFRIKSkpCisJCWdvdG8gdW5s b2NrOworCisJaGlzdCA9IGxydV9oaXN0X2Zyb21fc2VxKG1pbl9zZXEpOworCXRpZXIgPSBscnVf dGllcl9mcm9tX3JlZnMocmVmcyArIHdvcmtpbmdzZXQpOworCWF0b21pY19sb25nX2FkZChkZWx0 YSwgJmxydWdlbi0+cmVmYXVsdGVkW2hpc3RdW3R5cGVdW3RpZXJdKTsKKwltb2RfbHJ1dmVjX3N0 YXRlKGxydXZlYywgV09SS0lOR1NFVF9SRUZBVUxUX0JBU0UgKyB0eXBlLCBkZWx0YSk7CisKKwkv KgorCSAqIENvdW50IHRoZSBmb2xsb3dpbmcgdHdvIGNhc2VzIGFzIHN0YWxsczoKKwkgKiAxLiBG b3IgcGFnZXMgYWNjZXNzZWQgdGhyb3VnaCBwYWdlIHRhYmxlcywgaG90dGVyIHBhZ2VzIHB1c2hl ZCBvdXQKKwkgKiAgICBob3QgcGFnZXMgd2hpY2ggcmVmYXVsdGVkIGltbWVkaWF0ZWx5LgorCSAq IDIuIEZvciBwYWdlcyBhY2Nlc3NlZCB0aHJvdWdoIGZpbGUgZGVzY3JpcHRvcnMsIG51bWJlcnMg b2YgYWNjZXNzZXMKKwkgKiAgICBtaWdodCBoYXZlIGJlZW4gYmV5b25kIHRoZSBsaW1pdC4KKwkg Ki8KKwlpZiAobHJ1X2dlbl9pbl9mYXVsdCgpIHx8IHJlZnMgKyB3b3JraW5nc2V0ID09IEJJVChM UlVfUkVGU19XSURUSCkpIHsKKwkJZm9saW9fc2V0X3dvcmtpbmdzZXQoZm9saW8pOworCQltb2Rf bHJ1dmVjX3N0YXRlKGxydXZlYywgV09SS0lOR1NFVF9SRVNUT1JFX0JBU0UgKyB0eXBlLCBkZWx0 YSk7CisJfQordW5sb2NrOgorCXJjdV9yZWFkX3VubG9jaygpOworfQorCisjZWxzZQorCitzdGF0 aWMgdm9pZCAqbHJ1X2dlbl9ldmljdGlvbihzdHJ1Y3QgZm9saW8gKmZvbGlvKQoreworCXJldHVy biBOVUxMOworfQorCitzdGF0aWMgdm9pZCBscnVfZ2VuX3JlZmF1bHQoc3RydWN0IGZvbGlvICpm b2xpbywgdm9pZCAqc2hhZG93KQoreworfQorCisjZW5kaWYgLyogQ09ORklHX0xSVV9HRU4gKi8K KwogLyoqCiAgKiB3b3JraW5nc2V0X2FnZV9ub25yZXNpZGVudCAtIGFnZSBub24tcmVzaWRlbnQg ZW50cmllcyBhcyBMUlUgYWdlcwogICogQGxydXZlYzogdGhlIGxydXZlYyB0aGF0IHdhcyBhZ2Vk CkBAIC0yNjQsMTAgKzM2OSwxNCBAQCB2b2lkICp3b3JraW5nc2V0X2V2aWN0aW9uKHN0cnVjdCBw YWdlICpwYWdlLCBzdHJ1Y3QgbWVtX2Nncm91cCAqdGFyZ2V0X21lbWNnKQogCVZNX0JVR19PTl9Q QUdFKHBhZ2VfY291bnQocGFnZSksIHBhZ2UpOwogCVZNX0JVR19PTl9QQUdFKCFQYWdlTG9ja2Vk KHBhZ2UpLCBwYWdlKTsKIAorCWlmIChscnVfZ2VuX2VuYWJsZWQoKSkKKwkJcmV0dXJuIGxydV9n ZW5fZXZpY3Rpb24ocGFnZV9mb2xpbyhwYWdlKSk7CisKIAlscnV2ZWMgPSBtZW1fY2dyb3VwX2xy dXZlYyh0YXJnZXRfbWVtY2csIHBnZGF0KTsKIAkvKiBYWFg6IHRhcmdldF9tZW1jZyBjYW4gYmUg TlVMTCwgZ28gdGhyb3VnaCBscnV2ZWMgKi8KIAltZW1jZ2lkID0gbWVtX2Nncm91cF9pZChscnV2 ZWNfbWVtY2cobHJ1dmVjKSk7CiAJZXZpY3Rpb24gPSBhdG9taWNfbG9uZ19yZWFkKCZscnV2ZWMt Pm5vbnJlc2lkZW50X2FnZSk7CisJZXZpY3Rpb24gPj49IGJ1Y2tldF9vcmRlcjsKIAl3b3JraW5n c2V0X2FnZV9ub25yZXNpZGVudChscnV2ZWMsIHRocF9ucl9wYWdlcyhwYWdlKSk7CiAJcmV0dXJu IHBhY2tfc2hhZG93KG1lbWNnaWQsIHBnZGF0LCBldmljdGlvbiwgUGFnZVdvcmtpbmdzZXQocGFn ZSkpOwogfQpAQCAtMjk3LDcgKzQwNiwxMyBAQCB2b2lkIHdvcmtpbmdzZXRfcmVmYXVsdChzdHJ1 Y3QgZm9saW8gKmZvbGlvLCB2b2lkICpzaGFkb3cpCiAJaW50IG1lbWNnaWQ7CiAJbG9uZyBucjsK IAorCWlmIChscnVfZ2VuX2VuYWJsZWQoKSkgeworCQlscnVfZ2VuX3JlZmF1bHQoZm9saW8sIHNo YWRvdyk7CisJCXJldHVybjsKKwl9CisKIAl1bnBhY2tfc2hhZG93KHNoYWRvdywgJm1lbWNnaWQs ICZwZ2RhdCwgJmV2aWN0aW9uLCAmd29ya2luZ3NldCk7CisJZXZpY3Rpb24gPDw9IGJ1Y2tldF9v cmRlcjsKIAogCXJjdV9yZWFkX2xvY2soKTsKIAkvKgotLSAKMi4zNS4xLjYxNi5nMGJkY2JiNDQ2 NC1nb29nCgoKX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18K bGludXgtYXJtLWtlcm5lbCBtYWlsaW5nIGxpc3QKbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZy YWRlYWQub3JnCmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGlu dXgtYXJtLWtlcm5lbAo=