From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_SANE_1 autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 25360C35671 for ; Sun, 23 Feb 2020 18:49:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id D0F2C20656 for ; Sun, 23 Feb 2020 18:49:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726302AbgBWStT (ORCPT ); Sun, 23 Feb 2020 13:49:19 -0500 Received: from foss.arm.com ([217.140.110.172]:50664 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726208AbgBWStT (ORCPT ); Sun, 23 Feb 2020 13:49:19 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 9A0AA30E; Sun, 23 Feb 2020 10:49:17 -0800 (PST) Received: from localhost (unknown [10.1.198.53]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 377B73F703; Sun, 23 Feb 2020 10:49:17 -0800 (PST) Date: Sun, 23 Feb 2020 18:49:15 +0000 From: Ionela Voinescu To: Valentin Schneider Cc: catalin.marinas@arm.com, will@kernel.org, mark.rutland@arm.com, maz@kernel.org, suzuki.poulose@arm.com, sudeep.holla@arm.com, lukasz.luba@arm.com, rjw@rjwysocki.net, peterz@infradead.org, mingo@redhat.com, vincent.guittot@linaro.org, viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-pm@vger.kernel.org Subject: Re: [PATCH v3 6/7] arm64: use activity monitors for frequency invariance Message-ID: <20200223184915.GA22925@arm.com> References: <20200211184542.29585-1-ionela.voinescu@arm.com> <20200211184542.29585-7-ionela.voinescu@arm.com> <9eeda406-78a8-a910-f6ef-a367bf407a19@arm.com> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <9eeda406-78a8-a910-f6ef-a367bf407a19@arm.com> User-Agent: Mutt/1.9.4 (2018-02-28) Sender: linux-doc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-doc@vger.kernel.org Hi Valentin, Sorry for the delay in my reply and thank you very much for the review! I will push v4 very soon with these changes. On Monday 17 Feb 2020 at 16:59:24 (+0000), Valentin Schneider wrote: > > + * Pre-compute the fixed ratio between the frequency of the constant > > + * counter and the maximum frequency of the CPU. > > + * > > + * const_freq > > + * arch_max_freq_scale = ---------------- * SCHED_CAPACITY_SCALE² > > + * cpuinfo_max_freq > > + * > > + * We use a factor of 2 * SCHED_CAPACITY_SHIFT -> SCHED_CAPACITY_SCALE² > > + * in order to ensure a good resolution for arch_max_freq_scale for > > + * very low arch timer frequencies (up to the KHz range which should be > ^^^^^ > : s/up to/down to/ Done! > > + * unlikely). > > + */ > > + ratio = (u64)arch_timer_get_rate() << (2 * SCHED_CAPACITY_SHIFT); > > + ratio = div64_u64(ratio, max_freq_hz); > > + if (!ratio) { > > + pr_err("System timer frequency too low.\n"); > > Should that be a WARN_ONCE() instead? If the arch timer freq is too low, > we'll end up spamming this message, since we go through this for all CPUs. Done! > > + return -EINVAL; > > + } > > + > > + per_cpu(arch_max_freq_scale, cpu) = (unsigned long)ratio; > > + > > It occurred to me that this isn't strictly speaking a per-CPU information as > it only depends on the max possible frequency. Not really worth bothering > about though, I think. > Yes, it depends on the max possible frequency of all CPUs in a frequency domain. But I wanted to put this factor in a per-cpu variable in order to be able to retrieve it faster in topology_scale_freq_tick, rather than having to consider policies and related CPUs in that function. > > + return 0; > > +} > > + > > +static inline int > > +enable_policy_freq_counters(int cpu, cpumask_var_t valid_cpus) > > +{ > > + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); > > + > > + if (!policy) { > > + pr_debug("CPU%d: No cpufreq policy found.\n", cpu); > > + return false; > > + } > > + > > + if (cpumask_subset(policy->related_cpus, valid_cpus)) { > > + cpumask_or(amu_fie_cpus, policy->related_cpus, > > + amu_fie_cpus); > > + pr_info("CPUs[%*pbl]: counters will be used for FIE.", > > + cpumask_pr_args(amu_fie_cpus)); > > Could we have a single print of all CPUs in one go? AIUI this will generate a > line per cpufreq policy. Maybe just something at the tail of init_amu_fie(): > > if (!cpumask_empty(amu_fie_cpus)) > pr_info(); > Done. I've used this location as well to set the static key that you've suggested below. > > + } > > + > > + cpufreq_cpu_put(policy); > > + > > + return true; > > +} > > + > > +static int __init init_amu_fie(void) > > +{ > > + cpumask_var_t valid_cpus; > > + bool have_policy = false; > > + int cpu; > > + > > + if (!zalloc_cpumask_var(&valid_cpus, GFP_KERNEL) || > > + !zalloc_cpumask_var(&amu_fie_cpus, GFP_KERNEL)) > > + return -ENOMEM; > > + > > + for_each_possible_cpu(cpu) { > > + if (validate_cpu_freq_invariance_counters(cpu)) > > + continue; > > + cpumask_set_cpu(cpu, valid_cpus); > > + have_policy = enable_policy_freq_counters(cpu, valid_cpus) || > > + have_policy; > > What about: > have_policy |= enable_policy_freq_counters(cpu, valid_cpus); > Done as well. > > + } > > + > > + if (!have_policy) { > > + /* > > + * If we are not restricted by cpufreq policies, we only enable > > + * the use of the AMU feature for FIE if all CPUs support AMU. > > + * Otherwise, enable_policy_freq_counters has already enabled > > + * policy cpus. > > + */ > > + if (cpumask_equal(valid_cpus, cpu_possible_mask)) { > > Mmm so I'm thinking what we want here is the cpu_present_mask rather than > the possible one. This is very corner-casy, but I think that if we fail to > boot a secondary, we'll have it possible but not present. > Yes, this is correct. It does depend on the stage it fails at: for example if some feature checks fail, a CPU will not be marked in cpu_present_mask (see cpu_die_early()), while the following will result in possible == present. --- [ 0.056524] EFI services will not be available. [ 0.065690] smp: Bringing up secondary CPUs ... [ 0.098010] psci: failed to boot CPU1 (-22) [ 0.098037] CPU1: failed to boot: -22 [ 0.130290] psci: failed to boot CPU2 (-22) [ 0.130315] CPU2: failed to boot: -22 [ 0.162568] psci: failed to boot CPU3 (-22) [ 0.162594] CPU3: failed to boot: -22 [ 0.194890] Detected PIPT I-cache on CPU4 [ 0.194990] GICv3: CPU4: found redistributor 100 region 0:0x000000002f120000 [ 0.195046] GICv3: CPU4: using allocated LPI pending table @0x00000000fc0d0000 [ 0.195133] CPU4: Booted secondary processor 0x0000000100 [0x410fd0f0] [ 0.227190] psci: failed to boot CPU5 (-22) [ 0.227412] CPU5: failed to boot: -22 [ 0.259431] psci: failed to boot CPU6 (-22) [ 0.259522] CPU6: failed to boot: -22 [ 0.291683] psci: failed to boot CPU7 (-22) [ 0.291709] CPU7: failed to boot: -22 [ 0.291990] smp: Brought up 1 node, 2 CPUs [..] root@buildroot:~# cat present 0-7 root@buildroot:~# cat possible 0-7 This failure happens while the CPU is being brought up (__cpu_up). I'm not sure if this should result in set_cpu_present(cpu, 0) as well. But it's unrelated to this.. In any case, your suggestion is valid and cpu_present_mask is better to be used here. > While at it you could make the loop only target present CPUs, but I think the > one bit that matters is this check right here (!present should fail at > validate_cpu_freq_invariance_counters()). > Will change the loop as well. Thanks! > > + cpumask_or(amu_fie_cpus, amu_fie_cpus, valid_cpus); > > + pr_info("CPUs[%*pbl]: counters will be used for FIE.", > > + cpumask_pr_args(amu_fie_cpus)); > > + } > > + } > > + > > + free_cpumask_var(valid_cpus); > > + > > + return 0; > > +} > > +late_initcall_sync(init_amu_fie); > > + > > +bool topology_cpu_freq_counters(struct cpumask *cpus) > > +{ > > + return cpumask_available(amu_fie_cpus) && > > + cpumask_subset(cpus, amu_fie_cpus); > > +} > > + > > +void topology_scale_freq_tick(void) > > +{ > > + u64 prev_core_cnt, prev_const_cnt; > > + u64 core_cnt, const_cnt, scale; > > + int cpu = smp_processor_id(); > > + > > + if (!cpumask_available(amu_fie_cpus) || > > + !cpumask_test_cpu(cpu, amu_fie_cpus)) > > + return; > > It might be a good idea to have a static key to gate our entry into this > function - that way we can lessen our impact on older platforms (without AMUs) > running a recent kernel with CONFIG_ARM64_AMU_EXTN=y. > > x86 does just that, if you look at their arch_scale_freq_tick() > implementation. FWIW I don't think we should bother with playing with the > key counter to count AMU-enabled CPUs, just enable it at startup if we have > > 1 such CPU and let the cpumask drive the rest. > > In your check here, the static key check could replace the cpumask_available() > check. The static key could also be used for topology_cpu_freq_counters(). > Very good idea! Done as well. Yes, the counter (number of AMU enabled CPUs) would not be of much help for the moment. > > + > > + const_cnt = read_sysreg_s(SYS_AMEVCNTR0_CONST_EL0); > > + core_cnt = read_sysreg_s(SYS_AMEVCNTR0_CORE_EL0); > > + prev_const_cnt = this_cpu_read(arch_const_cycles_prev); > > + prev_core_cnt = this_cpu_read(arch_core_cycles_prev); > > + > > + if (unlikely(core_cnt <= prev_core_cnt || > > + const_cnt <= prev_const_cnt)) > > + goto store_and_exit; > > + > > + /* > > + * /\core arch_max_freq_scale > > + * scale = ------- * -------------------- > > + * /\const SCHED_CAPACITY_SCALE > > + * > > + * We shift by SCHED_CAPACITY_SHIFT (divide by SCHED_CAPACITY_SCALE) > > + * in order to compensate for the SCHED_CAPACITY_SCALE² factor in > > + * arch_max_freq_scale (used to ensure its resolution) while keeping > > + * the scale value in the 0-SCHED_CAPACITY_SCALE capacity range. > > + */ > > A simple "See validate_cpu_freq_invariance_counters() for details on the > scale factor" would suffice wrt the shifting details. > Done! Thank you, Ionela. > > + scale = core_cnt - prev_core_cnt; > > + scale *= this_cpu_read(arch_max_freq_scale); > > + scale = div64_u64(scale >> SCHED_CAPACITY_SHIFT, > > + const_cnt - prev_const_cnt); > > + > > + scale = min_t(unsigned long, scale, SCHED_CAPACITY_SCALE); > > + this_cpu_write(freq_scale, (unsigned long)scale); > > + > > +store_and_exit: > > + this_cpu_write(arch_core_cycles_prev, core_cnt); > > + this_cpu_write(arch_const_cycles_prev, const_cnt); > > +} > > +#endif /* CONFIG_ARM64_AMU_EXTN */ > > diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c > > index 1eb81f113786..1ab2b7503d63 100644 > > --- a/drivers/base/arch_topology.c > > +++ b/drivers/base/arch_topology.c > > @@ -29,6 +29,14 @@ void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq, > > unsigned long scale; > > int i; > > > > + /* > > + * If the use of counters for FIE is enabled, just return as we don't > > + * want to update the scale factor with information from CPUFREQ. > > + * Instead the scale factor will be updated from arch_scale_freq_tick. > > + */ > > + if (arch_cpu_freq_counters(cpus)) > > + return; > > + > > scale = (cur_freq << SCHED_CAPACITY_SHIFT) / max_freq; > > > > for_each_cpu(i, cpus) > > diff --git a/include/linux/topology.h b/include/linux/topology.h > > index eb2fe6edd73c..397aad6ae163 100644 > > --- a/include/linux/topology.h > > +++ b/include/linux/topology.h > > @@ -227,5 +227,12 @@ static inline const struct cpumask *cpu_cpu_mask(int cpu) > > return cpumask_of_node(cpu_to_node(cpu)); > > } > > > > +#ifndef arch_cpu_freq_counters > > +static __always_inline > > +bool arch_cpu_freq_counters(struct cpumask *cpus) > > +{ > > + return false; > > +} > > +#endif > > > > #endif /* _LINUX_TOPOLOGY_H */ > > From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_SANE_1 autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9D98CC35666 for ; Sun, 23 Feb 2020 18:49:51 +0000 (UTC) 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 mail.kernel.org (Postfix) with ESMTPS id 6981D20656 for ; Sun, 23 Feb 2020 18:49:51 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="D+hqK6bx" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6981D20656 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References: Message-ID:Subject:To:From:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=TWXiB/xa60dAEr7bl6QB8RnzZXNL7xAfDbS5LSfACts=; b=D+hqK6bxOd+8/X 6ry9BXA5bpDzW26SsfeyzieKU9mgifQNuK5uDiPojupOKpKRfxdOAJNkWParBj5eZTGvY6AwwCEV8 DVf3USqMWmJuy6c4k6bvG1aXIGZJao5S1i97+e3rUrk1FQy7EMdpOlbxnl3KEzE9uGkDQLfAyPX79 RmfRE2aZw/lZwMst/2kKgw6HurO2lhvAL+NpBB5U6fgQP+R4eEfdsfIkcBpdv3MSKjLUxYQK7hIBe QDNgzvgG9/Tb31iAR6Thdwm2YDz3d5/+IFA4Z1EuPq1W2Vnc1dTtOSJBoSdD13XCNlrRsp4X2UkmL hh+xYxCCHSldZThPLAMw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j5wJk-0005w7-Jn; Sun, 23 Feb 2020 18:49:28 +0000 Received: from foss.arm.com ([217.140.110.172]) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1j5wJf-0005un-L4 for linux-arm-kernel@lists.infradead.org; Sun, 23 Feb 2020 18:49:25 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 9A0AA30E; Sun, 23 Feb 2020 10:49:17 -0800 (PST) Received: from localhost (unknown [10.1.198.53]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 377B73F703; Sun, 23 Feb 2020 10:49:17 -0800 (PST) Date: Sun, 23 Feb 2020 18:49:15 +0000 From: Ionela Voinescu To: Valentin Schneider Subject: Re: [PATCH v3 6/7] arm64: use activity monitors for frequency invariance Message-ID: <20200223184915.GA22925@arm.com> References: <20200211184542.29585-1-ionela.voinescu@arm.com> <20200211184542.29585-7-ionela.voinescu@arm.com> <9eeda406-78a8-a910-f6ef-a367bf407a19@arm.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <9eeda406-78a8-a910-f6ef-a367bf407a19@arm.com> User-Agent: Mutt/1.9.4 (2018-02-28) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200223_104923_782745_D0614D47 X-CRM114-Status: GOOD ( 34.78 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, maz@kernel.org, suzuki.poulose@arm.com, peterz@infradead.org, catalin.marinas@arm.com, linux-pm@vger.kernel.org, linux-doc@vger.kernel.org, rjw@rjwysocki.net, linux-kernel@vger.kernel.org, mingo@redhat.com, viresh.kumar@linaro.org, linux-arm-kernel@lists.infradead.org, sudeep.holla@arm.com, will@kernel.org, lukasz.luba@arm.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org SGkgVmFsZW50aW4sCgpTb3JyeSBmb3IgdGhlIGRlbGF5IGluIG15IHJlcGx5IGFuZCB0aGFuayB5 b3UgdmVyeSBtdWNoIGZvciB0aGUgcmV2aWV3IQoKSSB3aWxsIHB1c2ggdjQgdmVyeSBzb29uIHdp dGggdGhlc2UgY2hhbmdlcy4KCk9uIE1vbmRheSAxNyBGZWIgMjAyMCBhdCAxNjo1OToyNCAoKzAw MDApLCBWYWxlbnRpbiBTY2huZWlkZXIgd3JvdGU6Cj4gPiArCSAqIFByZS1jb21wdXRlIHRoZSBm aXhlZCByYXRpbyBiZXR3ZWVuIHRoZSBmcmVxdWVuY3kgb2YgdGhlIGNvbnN0YW50Cj4gPiArCSAq IGNvdW50ZXIgYW5kIHRoZSBtYXhpbXVtIGZyZXF1ZW5jeSBvZiB0aGUgQ1BVLgo+ID4gKwkgKgo+ ID4gKwkgKgkJCSAgICAgIGNvbnN0X2ZyZXEKPiA+ICsJICogYXJjaF9tYXhfZnJlcV9zY2FsZSA9 ICAgLS0tLS0tLS0tLS0tLS0tLSAqIFNDSEVEX0NBUEFDSVRZX1NDQUxFwrIKPiA+ICsJICoJCQkg ICBjcHVpbmZvX21heF9mcmVxCj4gPiArCSAqCj4gPiArCSAqIFdlIHVzZSBhIGZhY3RvciBvZiAy ICogU0NIRURfQ0FQQUNJVFlfU0hJRlQgLT4gU0NIRURfQ0FQQUNJVFlfU0NBTEXCsgo+ID4gKwkg KiBpbiBvcmRlciB0byBlbnN1cmUgYSBnb29kIHJlc29sdXRpb24gZm9yIGFyY2hfbWF4X2ZyZXFf c2NhbGUgZm9yCj4gPiArCSAqIHZlcnkgbG93IGFyY2ggdGltZXIgZnJlcXVlbmNpZXMgKHVwIHRv IHRoZSBLSHogcmFuZ2Ugd2hpY2ggc2hvdWxkIGJlCj4gICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICBeXl5eXgo+IDxwZWRhbnRpYyBoYXQgb24+OiBzL3VwIHRvL2Rv d24gdG8vCgpEb25lIQoKPiA+ICsJICogdW5saWtlbHkpLgo+ID4gKwkgKi8KPiA+ICsJcmF0aW8g PSAodTY0KWFyY2hfdGltZXJfZ2V0X3JhdGUoKSA8PCAoMiAqIFNDSEVEX0NBUEFDSVRZX1NISUZU KTsKPiA+ICsJcmF0aW8gPSBkaXY2NF91NjQocmF0aW8sIG1heF9mcmVxX2h6KTsKPiA+ICsJaWYg KCFyYXRpbykgewo+ID4gKwkJcHJfZXJyKCJTeXN0ZW0gdGltZXIgZnJlcXVlbmN5IHRvbyBsb3cu XG4iKTsKPiAKPiBTaG91bGQgdGhhdCBiZSBhIFdBUk5fT05DRSgpIGluc3RlYWQ/IElmIHRoZSBh cmNoIHRpbWVyIGZyZXEgaXMgdG9vIGxvdywKPiB3ZSdsbCBlbmQgdXAgc3BhbW1pbmcgdGhpcyBt ZXNzYWdlLCBzaW5jZSB3ZSBnbyB0aHJvdWdoIHRoaXMgZm9yIGFsbCBDUFVzLgoKRG9uZSEKCj4g PiArCQlyZXR1cm4gLUVJTlZBTDsKPiA+ICsJfQo+ID4gKwo+ID4gKwlwZXJfY3B1KGFyY2hfbWF4 X2ZyZXFfc2NhbGUsIGNwdSkgPSAodW5zaWduZWQgbG9uZylyYXRpbzsKPiA+ICsKPiAKPiBJdCBv Y2N1cnJlZCB0byBtZSB0aGF0IHRoaXMgaXNuJ3Qgc3RyaWN0bHkgc3BlYWtpbmcgYSBwZXItQ1BV IGluZm9ybWF0aW9uIGFzCj4gaXQgb25seSBkZXBlbmRzIG9uIHRoZSBtYXggcG9zc2libGUgZnJl cXVlbmN5LiBOb3QgcmVhbGx5IHdvcnRoIGJvdGhlcmluZwo+IGFib3V0IHRob3VnaCwgSSB0aGlu ay4KPiAKClllcywgaXQgZGVwZW5kcyBvbiB0aGUgbWF4IHBvc3NpYmxlIGZyZXF1ZW5jeSBvZiBh bGwgQ1BVcyBpbiBhIGZyZXF1ZW5jeQpkb21haW4uIEJ1dCBJIHdhbnRlZCB0byBwdXQgdGhpcyBm YWN0b3IgaW4gYSBwZXItY3B1IHZhcmlhYmxlIGluIG9yZGVyCnRvIGJlIGFibGUgdG8gcmV0cmll dmUgaXQgZmFzdGVyIGluIHRvcG9sb2d5X3NjYWxlX2ZyZXFfdGljaywgcmF0aGVyCnRoYW4gaGF2 aW5nIHRvIGNvbnNpZGVyIHBvbGljaWVzIGFuZCByZWxhdGVkIENQVXMgaW4gdGhhdCBmdW5jdGlv bi4KCj4gPiArCXJldHVybiAwOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgaW5saW5lIGludAo+ ID4gK2VuYWJsZV9wb2xpY3lfZnJlcV9jb3VudGVycyhpbnQgY3B1LCBjcHVtYXNrX3Zhcl90IHZh bGlkX2NwdXMpCj4gPiArewo+ID4gKwlzdHJ1Y3QgY3B1ZnJlcV9wb2xpY3kgKnBvbGljeSA9IGNw dWZyZXFfY3B1X2dldChjcHUpOwo+ID4gKwo+ID4gKwlpZiAoIXBvbGljeSkgewo+ID4gKwkJcHJf ZGVidWcoIkNQVSVkOiBObyBjcHVmcmVxIHBvbGljeSBmb3VuZC5cbiIsIGNwdSk7Cj4gPiArCQly ZXR1cm4gZmFsc2U7Cj4gPiArCX0KPiA+ICsKPiA+ICsJaWYgKGNwdW1hc2tfc3Vic2V0KHBvbGlj eS0+cmVsYXRlZF9jcHVzLCB2YWxpZF9jcHVzKSkgewo+ID4gKwkJY3B1bWFza19vcihhbXVfZmll X2NwdXMsIHBvbGljeS0+cmVsYXRlZF9jcHVzLAo+ID4gKwkJCSAgIGFtdV9maWVfY3B1cyk7Cj4g PiArCQlwcl9pbmZvKCJDUFVzWyUqcGJsXTogY291bnRlcnMgd2lsbCBiZSB1c2VkIGZvciBGSUUu IiwKPiA+ICsJCQljcHVtYXNrX3ByX2FyZ3MoYW11X2ZpZV9jcHVzKSk7Cj4gCj4gQ291bGQgd2Ug aGF2ZSBhIHNpbmdsZSBwcmludCBvZiBhbGwgQ1BVcyBpbiBvbmUgZ28/IEFJVUkgdGhpcyB3aWxs IGdlbmVyYXRlIGEKPiBsaW5lIHBlciBjcHVmcmVxIHBvbGljeS4gTWF5YmUganVzdCBzb21ldGhp bmcgYXQgdGhlIHRhaWwgb2YgaW5pdF9hbXVfZmllKCk6Cj4gCj4gaWYgKCFjcHVtYXNrX2VtcHR5 KGFtdV9maWVfY3B1cykpCj4gCXByX2luZm8oPGJsYWg+KTsKPiAKCkRvbmUuIEkndmUgdXNlZCB0 aGlzIGxvY2F0aW9uIGFzIHdlbGwgdG8gc2V0IHRoZSBzdGF0aWMga2V5IHRoYXQgeW91J3ZlCnN1 Z2dlc3RlZCBiZWxvdy4KCj4gPiArCX0KPiA+ICsKPiA+ICsJY3B1ZnJlcV9jcHVfcHV0KHBvbGlj eSk7Cj4gPiArCj4gPiArCXJldHVybiB0cnVlOwo+ID4gK30KPiA+ICsKPiA+ICtzdGF0aWMgaW50 IF9faW5pdCBpbml0X2FtdV9maWUodm9pZCkKPiA+ICt7Cj4gPiArCWNwdW1hc2tfdmFyX3QgdmFs aWRfY3B1czsKPiA+ICsJYm9vbCBoYXZlX3BvbGljeSA9IGZhbHNlOwo+ID4gKwlpbnQgY3B1Owo+ ID4gKwo+ID4gKwlpZiAoIXphbGxvY19jcHVtYXNrX3ZhcigmdmFsaWRfY3B1cywgR0ZQX0tFUk5F TCkgfHwKPiA+ICsJICAgICF6YWxsb2NfY3B1bWFza192YXIoJmFtdV9maWVfY3B1cywgR0ZQX0tF Uk5FTCkpCj4gPiArCQlyZXR1cm4gLUVOT01FTTsKPiA+ICsKPiA+ICsJZm9yX2VhY2hfcG9zc2li bGVfY3B1KGNwdSkgewo+ID4gKwkJaWYgKHZhbGlkYXRlX2NwdV9mcmVxX2ludmFyaWFuY2VfY291 bnRlcnMoY3B1KSkKPiA+ICsJCQljb250aW51ZTsKPiA+ICsJCWNwdW1hc2tfc2V0X2NwdShjcHUs IHZhbGlkX2NwdXMpOwo+ID4gKwkJaGF2ZV9wb2xpY3kgPSBlbmFibGVfcG9saWN5X2ZyZXFfY291 bnRlcnMoY3B1LCB2YWxpZF9jcHVzKSB8fAo+ID4gKwkJCSAgICAgIGhhdmVfcG9saWN5Owo+IAo+ IFdoYXQgYWJvdXQ6Cj4gCQloYXZlX3BvbGljeSB8PSBlbmFibGVfcG9saWN5X2ZyZXFfY291bnRl cnMoY3B1LCB2YWxpZF9jcHVzKTsKPiAKCkRvbmUgYXMgd2VsbC4KCj4gPiArCX0KPiA+ICsKPiA+ ICsJaWYgKCFoYXZlX3BvbGljeSkgewo+ID4gKwkJLyoKPiA+ICsJCSAqIElmIHdlIGFyZSBub3Qg cmVzdHJpY3RlZCBieSBjcHVmcmVxIHBvbGljaWVzLCB3ZSBvbmx5IGVuYWJsZQo+ID4gKwkJICog dGhlIHVzZSBvZiB0aGUgQU1VIGZlYXR1cmUgZm9yIEZJRSBpZiBhbGwgQ1BVcyBzdXBwb3J0IEFN VS4KPiA+ICsJCSAqIE90aGVyd2lzZSwgZW5hYmxlX3BvbGljeV9mcmVxX2NvdW50ZXJzIGhhcyBh bHJlYWR5IGVuYWJsZWQKPiA+ICsJCSAqIHBvbGljeSBjcHVzLgo+ID4gKwkJICovCj4gPiArCQlp ZiAoY3B1bWFza19lcXVhbCh2YWxpZF9jcHVzLCBjcHVfcG9zc2libGVfbWFzaykpIHsKPiAKPiBN bW0gc28gSSdtIHRoaW5raW5nIHdoYXQgd2Ugd2FudCBoZXJlIGlzIHRoZSBjcHVfcHJlc2VudF9t YXNrIHJhdGhlciB0aGFuCj4gdGhlIHBvc3NpYmxlIG9uZS4gVGhpcyBpcyB2ZXJ5IGNvcm5lci1j YXN5LCBidXQgSSB0aGluayB0aGF0IGlmIHdlIGZhaWwgdG8KPiBib290IGEgc2Vjb25kYXJ5LCB3 ZSdsbCBoYXZlIGl0IHBvc3NpYmxlIGJ1dCBub3QgcHJlc2VudC4KPgoKWWVzLCB0aGlzIGlzIGNv cnJlY3QuIEl0IGRvZXMgZGVwZW5kIG9uIHRoZSBzdGFnZSBpdCBmYWlscyBhdDogZm9yCmV4YW1w bGUgaWYgc29tZSBmZWF0dXJlIGNoZWNrcyBmYWlsLCBhIENQVSB3aWxsIG5vdCBiZSBtYXJrZWQg aW4KY3B1X3ByZXNlbnRfbWFzayAoc2VlIGNwdV9kaWVfZWFybHkoKSksIHdoaWxlIHRoZSBmb2xs b3dpbmcgd2lsbCByZXN1bHQKaW4gcG9zc2libGUgPT0gcHJlc2VudC4KCi0tLQpbICAgIDAuMDU2 NTI0XSBFRkkgc2VydmljZXMgd2lsbCBub3QgYmUgYXZhaWxhYmxlLgpbICAgIDAuMDY1NjkwXSBz bXA6IEJyaW5naW5nIHVwIHNlY29uZGFyeSBDUFVzIC4uLgpbICAgIDAuMDk4MDEwXSBwc2NpOiBm YWlsZWQgdG8gYm9vdCBDUFUxICgtMjIpClsgICAgMC4wOTgwMzddIENQVTE6IGZhaWxlZCB0byBi b290OiAtMjIKWyAgICAwLjEzMDI5MF0gcHNjaTogZmFpbGVkIHRvIGJvb3QgQ1BVMiAoLTIyKQpb ICAgIDAuMTMwMzE1XSBDUFUyOiBmYWlsZWQgdG8gYm9vdDogLTIyClsgICAgMC4xNjI1NjhdIHBz Y2k6IGZhaWxlZCB0byBib290IENQVTMgKC0yMikKWyAgICAwLjE2MjU5NF0gQ1BVMzogZmFpbGVk IHRvIGJvb3Q6IC0yMgpbICAgIDAuMTk0ODkwXSBEZXRlY3RlZCBQSVBUIEktY2FjaGUgb24gQ1BV NApbICAgIDAuMTk0OTkwXSBHSUN2MzogQ1BVNDogZm91bmQgcmVkaXN0cmlidXRvciAxMDAgcmVn aW9uCjA6MHgwMDAwMDAwMDJmMTIwMDAwClsgICAgMC4xOTUwNDZdIEdJQ3YzOiBDUFU0OiB1c2lu ZyBhbGxvY2F0ZWQgTFBJIHBlbmRpbmcgdGFibGUKQDB4MDAwMDAwMDBmYzBkMDAwMApbICAgIDAu MTk1MTMzXSBDUFU0OiBCb290ZWQgc2Vjb25kYXJ5IHByb2Nlc3NvciAweDAwMDAwMDAxMDAKWzB4 NDEwZmQwZjBdClsgICAgMC4yMjcxOTBdIHBzY2k6IGZhaWxlZCB0byBib290IENQVTUgKC0yMikK WyAgICAwLjIyNzQxMl0gQ1BVNTogZmFpbGVkIHRvIGJvb3Q6IC0yMgpbICAgIDAuMjU5NDMxXSBw c2NpOiBmYWlsZWQgdG8gYm9vdCBDUFU2ICgtMjIpClsgICAgMC4yNTk1MjJdIENQVTY6IGZhaWxl ZCB0byBib290OiAtMjIKWyAgICAwLjI5MTY4M10gcHNjaTogZmFpbGVkIHRvIGJvb3QgQ1BVNyAo LTIyKQpbICAgIDAuMjkxNzA5XSBDUFU3OiBmYWlsZWQgdG8gYm9vdDogLTIyClsgICAgMC4yOTE5 OTBdIHNtcDogQnJvdWdodCB1cCAxIG5vZGUsIDIgQ1BVcyAgClsuLl0Kcm9vdEBidWlsZHJvb3Q6 fiMgY2F0IHByZXNlbnQKMC03CnJvb3RAYnVpbGRyb290On4jIGNhdCBwb3NzaWJsZQowLTcKClRo aXMgZmFpbHVyZSBoYXBwZW5zIHdoaWxlIHRoZSBDUFUgaXMgYmVpbmcgYnJvdWdodCB1cCAoX19j cHVfdXApLgpJJ20gbm90IHN1cmUgaWYgdGhpcyBzaG91bGQgcmVzdWx0IGluIHNldF9jcHVfcHJl c2VudChjcHUsIDApIGFzIHdlbGwuCkJ1dCBpdCdzIHVucmVsYXRlZCB0byB0aGlzLi4KCkluIGFu eSBjYXNlLCB5b3VyIHN1Z2dlc3Rpb24gaXMgdmFsaWQgYW5kIGNwdV9wcmVzZW50X21hc2sgaXMg YmV0dGVyIHRvCmJlIHVzZWQgaGVyZS4KCgo+IFdoaWxlIGF0IGl0IHlvdSBjb3VsZCBtYWtlIHRo ZSBsb29wIG9ubHkgdGFyZ2V0IHByZXNlbnQgQ1BVcywgYnV0IEkgdGhpbmsgdGhlCj4gb25lIGJp dCB0aGF0IG1hdHRlcnMgaXMgdGhpcyBjaGVjayByaWdodCBoZXJlICghcHJlc2VudCBzaG91bGQg ZmFpbCBhdAo+IHZhbGlkYXRlX2NwdV9mcmVxX2ludmFyaWFuY2VfY291bnRlcnMoKSkuCj4gCgpX aWxsIGNoYW5nZSB0aGUgbG9vcCBhcyB3ZWxsLiBUaGFua3MhCgo+ID4gKwkJCWNwdW1hc2tfb3Io YW11X2ZpZV9jcHVzLCBhbXVfZmllX2NwdXMsIHZhbGlkX2NwdXMpOwo+ID4gKwkJCXByX2luZm8o IkNQVXNbJSpwYmxdOiBjb3VudGVycyB3aWxsIGJlIHVzZWQgZm9yIEZJRS4iLAo+ID4gKwkJCQlj cHVtYXNrX3ByX2FyZ3MoYW11X2ZpZV9jcHVzKSk7Cj4gPiArCQl9Cj4gPiArCX0KPiA+ICsKPiA+ ICsJZnJlZV9jcHVtYXNrX3Zhcih2YWxpZF9jcHVzKTsKPiA+ICsKPiA+ICsJcmV0dXJuIDA7Cj4g PiArfQo+ID4gK2xhdGVfaW5pdGNhbGxfc3luYyhpbml0X2FtdV9maWUpOwo+ID4gKwo+ID4gK2Jv b2wgdG9wb2xvZ3lfY3B1X2ZyZXFfY291bnRlcnMoc3RydWN0IGNwdW1hc2sgKmNwdXMpCj4gPiAr ewo+ID4gKwlyZXR1cm4gY3B1bWFza19hdmFpbGFibGUoYW11X2ZpZV9jcHVzKSAmJgo+ID4gKwkg ICAgICAgY3B1bWFza19zdWJzZXQoY3B1cywgYW11X2ZpZV9jcHVzKTsKPiA+ICt9Cj4gPiArCj4g PiArdm9pZCB0b3BvbG9neV9zY2FsZV9mcmVxX3RpY2sodm9pZCkKPiA+ICt7Cj4gPiArCXU2NCBw cmV2X2NvcmVfY250LCBwcmV2X2NvbnN0X2NudDsKPiA+ICsJdTY0IGNvcmVfY250LCBjb25zdF9j bnQsIHNjYWxlOwo+ID4gKwlpbnQgY3B1ID0gc21wX3Byb2Nlc3Nvcl9pZCgpOwo+ID4gKwo+ID4g KwlpZiAoIWNwdW1hc2tfYXZhaWxhYmxlKGFtdV9maWVfY3B1cykgfHwKPiA+ICsJICAgICFjcHVt YXNrX3Rlc3RfY3B1KGNwdSwgYW11X2ZpZV9jcHVzKSkKPiA+ICsJCXJldHVybjsKPiAKPiBJdCBt aWdodCBiZSBhIGdvb2QgaWRlYSB0byBoYXZlIGEgc3RhdGljIGtleSB0byBnYXRlIG91ciBlbnRy eSBpbnRvIHRoaXMKPiBmdW5jdGlvbiAtIHRoYXQgd2F5IHdlIGNhbiBsZXNzZW4gb3VyIGltcGFj dCBvbiBvbGRlciBwbGF0Zm9ybXMgKHdpdGhvdXQgQU1VcykKPiBydW5uaW5nIGEgcmVjZW50IGtl cm5lbCB3aXRoIENPTkZJR19BUk02NF9BTVVfRVhUTj15Lgo+IAo+IHg4NiBkb2VzIGp1c3QgdGhh dCwgaWYgeW91IGxvb2sgYXQgdGhlaXIgYXJjaF9zY2FsZV9mcmVxX3RpY2soKQo+IGltcGxlbWVu dGF0aW9uLiBGV0lXIEkgZG9uJ3QgdGhpbmsgd2Ugc2hvdWxkIGJvdGhlciB3aXRoIHBsYXlpbmcg d2l0aCB0aGUKPiBrZXkgY291bnRlciB0byBjb3VudCBBTVUtZW5hYmxlZCBDUFVzLCBqdXN0IGVu YWJsZSBpdCBhdCBzdGFydHVwIGlmIHdlIGhhdmUKPiA+IDEgc3VjaCBDUFUgYW5kIGxldCB0aGUg Y3B1bWFzayBkcml2ZSB0aGUgcmVzdC4KPiAKPiBJbiB5b3VyIGNoZWNrIGhlcmUsIHRoZSBzdGF0 aWMga2V5IGNoZWNrIGNvdWxkIHJlcGxhY2UgdGhlIGNwdW1hc2tfYXZhaWxhYmxlKCkKPiBjaGVj ay4gVGhlIHN0YXRpYyBrZXkgY291bGQgYWxzbyBiZSB1c2VkIGZvciB0b3BvbG9neV9jcHVfZnJl cV9jb3VudGVycygpLgo+CgpWZXJ5IGdvb2QgaWRlYSEgRG9uZSBhcyB3ZWxsLiBZZXMsIHRoZSBj b3VudGVyIChudW1iZXIgb2YgQU1VIGVuYWJsZWQKQ1BVcykgd291bGQgbm90IGJlIG9mIG11Y2gg aGVscCBmb3IgdGhlIG1vbWVudC4KCj4gPiArCj4gPiArCWNvbnN0X2NudCA9IHJlYWRfc3lzcmVn X3MoU1lTX0FNRVZDTlRSMF9DT05TVF9FTDApOwo+ID4gKwljb3JlX2NudCA9IHJlYWRfc3lzcmVn X3MoU1lTX0FNRVZDTlRSMF9DT1JFX0VMMCk7Cj4gPiArCXByZXZfY29uc3RfY250ID0gdGhpc19j cHVfcmVhZChhcmNoX2NvbnN0X2N5Y2xlc19wcmV2KTsKPiA+ICsJcHJldl9jb3JlX2NudCA9IHRo aXNfY3B1X3JlYWQoYXJjaF9jb3JlX2N5Y2xlc19wcmV2KTsKPiA+ICsKPiA+ICsJaWYgKHVubGlr ZWx5KGNvcmVfY250IDw9IHByZXZfY29yZV9jbnQgfHwKPiA+ICsJCSAgICAgY29uc3RfY250IDw9 IHByZXZfY29uc3RfY250KSkKPiA+ICsJCWdvdG8gc3RvcmVfYW5kX2V4aXQ7Cj4gPiArCj4gPiAr CS8qCj4gPiArCSAqCSAgICAvXGNvcmUgICAgYXJjaF9tYXhfZnJlcV9zY2FsZQo+ID4gKwkgKiBz Y2FsZSA9ICAtLS0tLS0tICogLS0tLS0tLS0tLS0tLS0tLS0tLS0KPiA+ICsJICoJICAgIC9cY29u c3QgICBTQ0hFRF9DQVBBQ0lUWV9TQ0FMRQo+ID4gKwkgKgo+ID4gKwkgKiBXZSBzaGlmdCBieSBT Q0hFRF9DQVBBQ0lUWV9TSElGVCAoZGl2aWRlIGJ5IFNDSEVEX0NBUEFDSVRZX1NDQUxFKQo+ID4g KwkgKiBpbiBvcmRlciB0byBjb21wZW5zYXRlIGZvciB0aGUgU0NIRURfQ0FQQUNJVFlfU0NBTEXC siBmYWN0b3IgaW4KPiA+ICsJICogYXJjaF9tYXhfZnJlcV9zY2FsZSAodXNlZCB0byBlbnN1cmUg aXRzIHJlc29sdXRpb24pIHdoaWxlIGtlZXBpbmcKPiA+ICsJICogdGhlIHNjYWxlIHZhbHVlIGlu IHRoZSAwLVNDSEVEX0NBUEFDSVRZX1NDQUxFIGNhcGFjaXR5IHJhbmdlLgo+ID4gKwkgKi8KPiAK PiBBIHNpbXBsZSAiU2VlIHZhbGlkYXRlX2NwdV9mcmVxX2ludmFyaWFuY2VfY291bnRlcnMoKSBm b3IgZGV0YWlscyBvbiB0aGUKPiBzY2FsZSBmYWN0b3IiIHdvdWxkIHN1ZmZpY2Ugd3J0IHRoZSBz aGlmdGluZyBkZXRhaWxzLgo+CgpEb25lIQoKVGhhbmsgeW91LApJb25lbGEuCgo+ID4gKwlzY2Fs ZSA9IGNvcmVfY250IC0gcHJldl9jb3JlX2NudDsKPiA+ICsJc2NhbGUgKj0gdGhpc19jcHVfcmVh ZChhcmNoX21heF9mcmVxX3NjYWxlKTsKPiA+ICsJc2NhbGUgPSBkaXY2NF91NjQoc2NhbGUgPj4g U0NIRURfQ0FQQUNJVFlfU0hJRlQsCj4gPiArCQkJICBjb25zdF9jbnQgLSBwcmV2X2NvbnN0X2Nu dCk7Cj4gPiArCj4gPiArCXNjYWxlID0gbWluX3QodW5zaWduZWQgbG9uZywgc2NhbGUsIFNDSEVE X0NBUEFDSVRZX1NDQUxFKTsKPiA+ICsJdGhpc19jcHVfd3JpdGUoZnJlcV9zY2FsZSwgKHVuc2ln bmVkIGxvbmcpc2NhbGUpOwo+ID4gKwo+ID4gK3N0b3JlX2FuZF9leGl0Ogo+ID4gKwl0aGlzX2Nw dV93cml0ZShhcmNoX2NvcmVfY3ljbGVzX3ByZXYsIGNvcmVfY250KTsKPiA+ICsJdGhpc19jcHVf d3JpdGUoYXJjaF9jb25zdF9jeWNsZXNfcHJldiwgY29uc3RfY250KTsKPiA+ICt9Cj4gPiArI2Vu ZGlmIC8qIENPTkZJR19BUk02NF9BTVVfRVhUTiAqLwo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMv YmFzZS9hcmNoX3RvcG9sb2d5LmMgYi9kcml2ZXJzL2Jhc2UvYXJjaF90b3BvbG9neS5jCj4gPiBp bmRleCAxZWI4MWYxMTM3ODYuLjFhYjJiNzUwM2Q2MyAxMDA2NDQKPiA+IC0tLSBhL2RyaXZlcnMv YmFzZS9hcmNoX3RvcG9sb2d5LmMKPiA+ICsrKyBiL2RyaXZlcnMvYmFzZS9hcmNoX3RvcG9sb2d5 LmMKPiA+IEBAIC0yOSw2ICsyOSwxNCBAQCB2b2lkIGFyY2hfc2V0X2ZyZXFfc2NhbGUoc3RydWN0 IGNwdW1hc2sgKmNwdXMsIHVuc2lnbmVkIGxvbmcgY3VyX2ZyZXEsCj4gPiAgCXVuc2lnbmVkIGxv bmcgc2NhbGU7Cj4gPiAgCWludCBpOwo+ID4gIAo+ID4gKwkvKgo+ID4gKwkgKiBJZiB0aGUgdXNl IG9mIGNvdW50ZXJzIGZvciBGSUUgaXMgZW5hYmxlZCwganVzdCByZXR1cm4gYXMgd2UgZG9uJ3QK PiA+ICsJICogd2FudCB0byB1cGRhdGUgdGhlIHNjYWxlIGZhY3RvciB3aXRoIGluZm9ybWF0aW9u IGZyb20gQ1BVRlJFUS4KPiA+ICsJICogSW5zdGVhZCB0aGUgc2NhbGUgZmFjdG9yIHdpbGwgYmUg dXBkYXRlZCBmcm9tIGFyY2hfc2NhbGVfZnJlcV90aWNrLgo+ID4gKwkgKi8KPiA+ICsJaWYgKGFy Y2hfY3B1X2ZyZXFfY291bnRlcnMoY3B1cykpCj4gPiArCQlyZXR1cm47Cj4gPiArCj4gPiAgCXNj YWxlID0gKGN1cl9mcmVxIDw8IFNDSEVEX0NBUEFDSVRZX1NISUZUKSAvIG1heF9mcmVxOwo+ID4g IAo+ID4gIAlmb3JfZWFjaF9jcHUoaSwgY3B1cykKPiA+IGRpZmYgLS1naXQgYS9pbmNsdWRlL2xp bnV4L3RvcG9sb2d5LmggYi9pbmNsdWRlL2xpbnV4L3RvcG9sb2d5LmgKPiA+IGluZGV4IGViMmZl NmVkZDczYy4uMzk3YWFkNmFlMTYzIDEwMDY0NAo+ID4gLS0tIGEvaW5jbHVkZS9saW51eC90b3Bv bG9neS5oCj4gPiArKysgYi9pbmNsdWRlL2xpbnV4L3RvcG9sb2d5LmgKPiA+IEBAIC0yMjcsNSAr MjI3LDEyIEBAIHN0YXRpYyBpbmxpbmUgY29uc3Qgc3RydWN0IGNwdW1hc2sgKmNwdV9jcHVfbWFz ayhpbnQgY3B1KQo+ID4gIAlyZXR1cm4gY3B1bWFza19vZl9ub2RlKGNwdV90b19ub2RlKGNwdSkp Owo+ID4gIH0KPiA+ICAKPiA+ICsjaWZuZGVmIGFyY2hfY3B1X2ZyZXFfY291bnRlcnMKPiA+ICtz dGF0aWMgX19hbHdheXNfaW5saW5lCj4gPiArYm9vbCBhcmNoX2NwdV9mcmVxX2NvdW50ZXJzKHN0 cnVjdCBjcHVtYXNrICpjcHVzKQo+ID4gK3sKPiA+ICsJcmV0dXJuIGZhbHNlOwo+ID4gK30KPiA+ ICsjZW5kaWYKPiA+ICAKPiA+ICAjZW5kaWYgLyogX0xJTlVYX1RPUE9MT0dZX0ggKi8KPiA+IAoK X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KbGludXgtYXJt LWtlcm5lbCBtYWlsaW5nIGxpc3QKbGludXgtYXJtLWtlcm5lbEBsaXN0cy5pbmZyYWRlYWQub3Jn Cmh0dHA6Ly9saXN0cy5pbmZyYWRlYWQub3JnL21haWxtYW4vbGlzdGluZm8vbGludXgtYXJtLWtl cm5lbAo=